You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							803 lines
						
					
					
						
							30 KiB
						
					
					
				
			
		
		
	
	
							803 lines
						
					
					
						
							30 KiB
						
					
					
				// 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 <OpenGLES/ES3/gl.h> | 
						|
#import <OpenGLES/ES3/glext.h> | 
						|
 | 
						|
#include <sys/time.h> | 
						|
#include <sys/types.h> | 
						|
#include <sys/socket.h> | 
						|
#include <netdb.h> | 
						|
 | 
						|
#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; | 
						|
}
 | 
						|
 |