The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
How to make SDL 2.0, iOS work together. (Game Center too)
Sam Lantinga


Joined: 10 Sep 2009
Posts: 1765
Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom. Smile

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ wrote:
Quote:
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == Cool {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

How to make SDL 2.0, iOS work together. (Game Center too)
gabomdq


Joined: 28 Jul 2011
Posts: 495
Location: Argentina
That is awesome, I think that pseudo code you posted should go in the iOS readme.
El 22/06/2012 20:23, "Sam Lantinga" escribió:
Quote:
Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom. Smile

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ wrote:
Quote:
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == Cool {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org





_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: How to make SDL 2.0, iOS work together. (Game Center too
stevo5800


Joined: 30 Jun 2012
Posts: 49
Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks


Sam Lantinga wrote:
Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom. Smile

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ wrote:
Quote:
The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == Cool {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

How to make SDL 2.0, iOS work together. (Game Center too)
Sam Lantinga


Joined: 10 Sep 2009
Posts: 1765
No idea... anyone?

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:
Quote:
Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

How to make SDL 2.0, iOS work together. (Game Center too)
Ye Xing
Guest

- (void) authenticateLocalUser
{
    [self becomeFirstResponder];
    
    if([GKLocalPlayer localPlayer].authenticated == NO)
    {
        [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error)
        {
            if(error == nil)
            {
                SDL_Delay(1000);
2012/7/5 Sam Lantinga
Quote:
No idea... anyone?

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:


Quote:
Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org












_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org




_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org





--

Best Regards
Re: How to make SDL 2.0, iOS work together. (Game Center too
stevo5800


Joined: 30 Jun 2012
Posts: 49
So I tried the above and had no success. After looking at the keyboard code I realized its creating a new window. So I decide to do window count and it happens that game center is doing the same thing as soon as the banner came up it showed another window opening. So I decided to trap any window that opens up .

this code is assuming there will be no other windows popping up but you could always add a count for other windows that is open and just do the math
not sure if it was the best solution but it works and now I understand how its working

//check if theres more then one window
if([[UIApplication sharedApplication].windows count] > 1)
{
if(one_time)
{
//getting the current window
UIWindow *main_window = [[UIApplication sharedApplication] keyWindow];
//get the new window
UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];
//add the second window view to the main window
[main_window addSubview:window.superview];

//set window level
window.windowLevel = 1;

//run this once every time it opens a new window
one_time = false;
}
}
else
{
//reset the flag when window closes
one_time = true;
}

Ye Xing wrote:
- (void) authenticateLocalUser
{
    [self becomeFirstResponder];
    
    if([GKLocalPlayer localPlayer].authenticated == NO)
    {
        [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error)
        {
            if(error == nil)
            {
                SDL_Delay(1000);
2012/7/5 Sam Lantinga
Quote:
No idea... anyone?

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:


Quote:
Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org












_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org




_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org





--

Best Regards
How to make SDL 2.0, iOS work together. (Game Center too)
Sam Lantinga


Joined: 10 Sep 2009
Posts: 1765
David Ludwig discovered the issue with the game center being hidden, and I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab


Can you let me know if this works?  I should be able to test iOS stuff again in a week or so.

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:
Quote:
Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: How to make SDL 2.0, iOS work together. (Game Center too
stevo5800


Joined: 30 Jun 2012
Posts: 49
I got a black screen but the banner shows up

Sam Lantinga wrote:
David Ludwig discovered the issue with the game center being hidden, and I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab


Can you let me know if this works?  I should be able to test iOS stuff again in a week or so.

On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 wrote:
Quote:
Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.

I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       
        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

How to make SDL 2.0, iOS work together. (Game Center too)
Sam Lantinga


Joined: 10 Sep 2009
Posts: 1765
If you revert that patch, do you get a normal (non-black) screen and no banner?

On Sun, Jul 22, 2012 at 3:39 PM, stevo5800 wrote:
Quote:
I got a black screen but the banner shows up




Sam Lantinga wrote:

David Ludwig discovered the issue with the game center being hidden, and I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab


Can you let me know if this works?  I should be able to test iOS stuff again in a week or so.


On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <> wrote:



Quote:

Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.


I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       


        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list



http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: How to make SDL 2.0, iOS work together. (Game Center too
stevo5800


Joined: 30 Jun 2012
Posts: 49
Yea I used it on an existing project switch back to my old SDL folder no black screen but banner behind

Sam Lantinga wrote:
If you revert that patch, do you get a normal (non-black) screen and no banner?

On Sun, Jul 22, 2012 at 3:39 PM, stevo5800 wrote:
Quote:
I got a black screen but the banner shows up




Sam Lantinga wrote:

David Ludwig discovered the issue with the game center being hidden, and I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab


Can you let me know if this works?  I should be able to test iOS stuff again in a week or so.


On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <> wrote:



Quote:

Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.


I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       


        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list



http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

How to make SDL 2.0, iOS work together. (Game Center too)
DLudwig


Joined: 09 Feb 2012
Posts: 179
Hi all,

I did a similar fix to a much older version of SDL 1.3 for iOS, had a blank screen on launch, and eventually found a fix.  At the time, I was working on a port of a commercial, Windows-based app to iOS.  Early in the project, the app would launch ok, but there'd be a blank screen.  Once the app did its first draw cycle, it'd go away.  The fix ended up being to make SDL display, on app launch, a "splash screen" view controller.   SDL would use the app's launch image (Default.png) for content, along with a UIActivityIndicator-based spinning wheel to show the user that things were happening.  When SDL was asked to update the screen for the first time, the splash screen would be hidden.


I hope this helps,
-- David L.

On Mon, Jul 23, 2012 at 5:14 AM, stevo5800 wrote:
Quote:
Yea I used it on an existing project switch back to my old SDL folder no black screen but banner behind




Sam Lantinga wrote:

If you revert that patch, do you get a normal (non-black) screen and no banner?

On Sun, Jul 22, 2012 at 3:39 PM, stevo5800 <> wrote:



Quote:

I got a black screen but the banner shows up




Sam Lantinga wrote:

David Ludwig discovered the issue with the game center being hidden, and I put in an untested fix:http://hg.libsdl.org/SDL/rev/8f224d0762ab


Can you let me know if this works?  I should be able to test iOS stuff again in a week or so.


On Wed, Jul 4, 2012 at 5:09 AM, stevo5800 <> wrote:



Quote:

Sam that function works like a charm, I was able to use that function to run my main loop then use the initialize stuff from BJ. I successfully launched game centre in my app but now the issue is how to get the welcome back message to pop up, or even any notification banner from game kit. If I don't render then I see the banner if not it draws over it. I got the idea of checking for views but it seems to only show the SDL view. I base my self of the SDL template included in the SDK. So I was wondering if there was a way to to display this banner?

Thanks





Sam Lantinga wrote:

Thanks BJ, this was incredibly helpful adding Game Center support to Maelstrom.


I added a function to SDL to make this easier to hook up:
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);


This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.


e.g.


extern "C"
void ShowFrame(void*)
{
    ... do frame logic and rendering
}


int main(int argc, char *argv[])
{
   ... initialize game ...


#if __IPHONEOS__
        // Initialize the Game Center for scoring and matchmaking
        InitGameCenter();


        // Set up the game to run in the window animation callback on iOS
        // so that Game Center and so forth works correctly.
        SDL_iPhoneSetAnimationCallback(screen->GetWindow(), 1, ShowFrame, 0);
#else
        while ( gRunning ) {
                ShowFrame(0);
                DelayFrame();
        }
        CleanUp();
#endif
        return 0;

}

On Thu, May 3, 2012 at 12:27 AM, BJ <> wrote:



Quote:

The problem is that SDL uses a pull messaging system, but iOS requires a pull system. Here is how to get the two working together correctly.
(I am using this on a project that is on PC and iOS)

This only change that I made to SDL was as follows



Code:


void
UIKit_PumpEvents(_THIS)
{
    return;
    /*
        When the user presses the 'home' button on the iPod
        the application exits -- immediatly.

        Unlike in Mac OS X, it appears there is no way to cancel the termination.

        This doesn't give the SDL user's application time to respond to an SDL_Quit event.
        So what we do is that in the UIApplicationDelegate class (SDLUIApplicationDelegate),
        when the delegate receives the ApplicationWillTerminate message, we execute
        a longjmp statement to get back here, preventing an immediate exit.
     */
    if (setjmp(*jump_env()) == 0) {
        /* if we're setting the jump, rather than jumping back */
        SInt32 result;
        do {
            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE);
        } while (result == kCFRunLoopRunHandledSource);
    }
}





This stops SDL processing all the events ( I added a return at the top of the function ). This fixes SDL crashing some times when other views are laid over the top. The problem of needing the long jump is avoided as this message will be processed when iOS sends the message and not during the next update.

The next thing that needs to be done is to intercept the events as they occur, fortunately this is an easy thing to do. Create a callback function and inform SDL, like so. Always return 0, this will stop SDL from storing the event.



Code:


 int SystemEventCallback(SDL_Event* event)
 {
     MyEventHandler::instance().OnEvent(event);
    return 0;
}

// Add this line to the initialisation code.
SDL_SetEventFilter(EventCallback, NULL);





The event handler looks something like this. (Remember that the events are processed as they occur, so save results when needed)



Code:


void EventHandler::OnEvent(SDL_Event *aEvent)
{
   switch (aEvent->type)
       {
    case SDL_WINDOWEVENT:
        {
            switch (aEvent->window.event)
            {
                case SDL_WINDOWEVENT_FOCUS_LOST:
                    OnLostFocus();
                    break;
                case SDL_WINDOWEVENT_FOCUS_GAINED:
                    OnGainedFocus();
                    break;
            }
            break;
          }
       }
}





Not sure these events work I applied the patch http://forums.libsdl.org/viewtopic.php?t=7733&sid=c9ade150b99a01c8f080cdd465f21b11 to this code so I use the SDL_SYSEVENT_WILL_SUSPEND and SDL_SYSEVENT_WILL_SUSPEND events.

So now we are half done, the other problem is that SDL runs in a tight loop. It is time to change this to an event driven approach. First SDL_uikitopenglview needs to be modified. Create a new objective c class and implement as follows. (Header first)



Code:


#import
#import "./sdl/src/video/uikit/SDL_uikitopenglview.h"

@interface SDL_uikitopenglview (MYOpenGLView)

- (void)startAnimation;
- (void)stopAnimation;

- (void)doLoop:(id)sender;
@end








Code:


#import "MYOpenGLView.h"
#import
#import
#include "SDL.h"
// a file that will let me use c++ for SDL
#include "SystemCalls.h"

id displayLink;
NSInteger animationFrameInterval = 1;

@implementation SDL_uikitopenglview (MYOpenGLView)

// make an exact copy of the SDL function
- (id)initWithFrame:(CGRect)frame
      retainBacking:(BOOL)retained
              rBits:(int)rBits
              gBits:(int)gBits
              bBits:(int)bBits
              aBits:(int)aBits
          depthBits:(int)depthBits
        stencilBits:(int)stencilBits
       majorVersion:(int)majorVersion
{
    depthBufferFormat = 0;
   
    if ((self = [super initWithFrame:frame])) {
        const BOOL useStencilBuffer = (stencilBits != 0);
        const BOOL useDepthBuffer = (depthBits != 0);
        NSString *colorFormat = nil;
       


        if (rBits == 8 && gBits == 8 && bBits == {
            /* if user specifically requests rbg888 or some color format higher than 16bpp */
            colorFormat = kEAGLColorFormatRGBA8;
        } else {
            /* default case (faster) */
            colorFormat = kEAGLColorFormatRGB565;
        }
       
        /* Get the layer */
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
       
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil];
       
        if (majorVersion > 1) {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
        } else {
            context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
        }
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            SDL_SetError("OpenGL ES %d not supported", majorVersion);
            return nil;
        }
       
        // !!! FIXME: use the screen this is on!
        /* Use the main screen scale (for retina display support) */
        if ([self respondsToSelector:@selector(contentScaleFactor)])
            self.contentScaleFactor = [UIScreen mainScreen].scale;
       
        /* create the buffers */
        glGenFramebuffersOES(1, &viewFramebuffer);
        glGenRenderbuffersOES(1, &viewRenderbuffer);
       
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
       
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
       
        if ((useDepthBuffer) || (useStencilBuffer)) {
            if (useStencilBuffer) {
                /* Apparently you need to pack stencil and depth into one buffer. */
                depthBufferFormat = GL_DEPTH24_STENCIL8_OES;
            } else if (useDepthBuffer) {
                /* iOS only has 24-bit depth buffers, even with GL_DEPTH_COMPONENT16_OES */
                depthBufferFormat = GL_DEPTH_COMPONENT24_OES;
            }
           
            glGenRenderbuffersOES(1, &depthRenderbuffer);
            glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
            glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depthBufferFormat, backingWidth, backingHeight);
            if (useDepthBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
            if (useStencilBuffer) {
                glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_STENCIL_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
            }
        }
       
        if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
            return NO;
        }
        /* end create buffers */
       
        self.autoresizingMask = 0;  // don't allow autoresize, since we need to do some magic in -(void)updateFrame.
       
        [self startAnimation];
    }
    return self;
}

- (void)startAnimation
{
    // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
    // if the system version runtime check for CADisplayLink exists in -initWithCoder:.
   
    displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doLoop:)];
    [displayLink setFrameInterval:animationFrameInterval];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopAnimation
{
    [displayLink invalidate];
    displayLink = nil;
}

- (void)doLoop:(id)sender
{
    runApplicationFrame();
}
@end





The initWithFrame function is a copy of the function in SDL with one exception [self startAnimation];. This is the important part as it sets up the way that we do a loop by callback. The start animation function basically sets up the doLoop function to run every x number of frames. Set this animationFrameInterval variable to 1 to run every frame, 2 for every 2nd frame etc. For more details (and other ways to do this) http://www.ananseproductions.com/game-loops-on-ios/.

Call the stopAnimation function when the application is suspended; and call the startAnimation function when the application resumes.

Lastly setup the function to run the application runApplicationFrame();.



Code:


void runApplicationFrame()
{
   // iOS uses a push event system instead of a pull event system
#ifdef WIN32
    SDL_Event Event;
    while (SDL_PollEvent(&Event))
    {
       OnEvent(&Event);
    }
#else
    /* Check for joystick state change */
    SDL_JoystickUpdate();
#endif // WIN32

   // do update stuff here

   // do render stuff here
   SDL_RenderClear(mRenderer);
   SDL_RenderCopy(mRenderer, mPrimaryTexture, NULL, &destRect);
   SDL_RenderPresent(mRenderer);
}





I am assuming that SDL has already been setup, this can all happen as usual. The important one is the SDL_JoystickUpdate (if you are using it) as it was called in the PollEvent function.

Game center and all other iOS windows will now work correctly.

Enjoy


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list



http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org










_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org