Initial Commit

This commit is contained in:
Jeff Farrand
2014-01-12 09:48:16 -06:00
commit 5b1ff23e0f
759 changed files with 319871 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
@interface idAnimatedImage : UIImageView {
}
- (void) SetupAnimation:( NSString * )animationBaseName
:( float )animationDuration
:( int )animationRepeat;
@end

View File

@@ -0,0 +1,67 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "AnimatedImage.h"
@implementation idAnimatedImage
/*
========================
SetupAnimation
========================
*/
- (void) SetupAnimation:( NSString * )animationBaseName
:( float )animationDuration
:( int )animationRepeat {
// Create an Array to store our images in.
const static int MAX_NUM_ANIMFRAMES = 20;
NSMutableArray * imageArray = [ [ NSMutableArray alloc ] initWithCapacity:MAX_NUM_ANIMFRAMES ];
for( int index = 1; index < MAX_NUM_ANIMFRAMES; index++ ) {
NSString * imageName = [ [ NSString alloc ] initWithFormat:@"%@_%d.png", animationBaseName, index ];
// Try and Load the Image.
UIImage * imageCheck = [UIImage imageNamed: imageName ];
// are we good?
if( imageCheck != nil ) {
// add it to the array of Images.
[ imageArray addObject:imageCheck ];
} else {
break;
}
}
// Set the Animation Data.
[ self setAnimationImages: imageArray ];
[ self setAnimationDuration: animationDuration];
[ self setAnimationRepeatCount: animationRepeat ];
}
@end

View File

@@ -0,0 +1,91 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
==============================================================================
Carousel -
This UI Object must be setup by Interface builder.
items must be added by code.
==============================================================================
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "Label.h"
@interface idCarouselItem : NSObject
{
@public
UIImage * image; // Image Of the Item.
NSString * title; // Title of the Item.
int hash; // Optional Item Hash Value.
}
@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) UIImage *image;
@property (nonatomic, assign) int hash;
@end
@interface idCarousel : UIControl {
@public
NSInteger currentItem; // The Current Carousel Item.
NSInteger prevItem; // The Prev Carousel Item.
NSInteger nextItem; // The Next Carousel Item.
@private
IBOutlet UIImageView * mainSelection; // Renderable Main Selection
IBOutlet UIImageView * prevSelection; // Renderable Prev Selection
IBOutlet UIImageView * nextSelection; // Renderable Next Selection
IBOutlet idLabel * selectionLabel; // Title Label.
CGRect mainRect; // Main Selection Layout Rect.
CGRect prevRect; // Prev Selection Layout Rect.
CGRect nextRect; // Next Selection Layout Rect.
NSMutableArray * carouselItems; // All the Available Items to choose from.
int hasDragged; // if the User has Dragged for a revolution.
CGPoint startDragPoint; // the starting point where the user has touched.
}
- (void) Init;
- (void) AddCarouselItem:( NSString* )Image
:( NSString* )Title
:( int )ItemHash;
- (NSInteger) GetSelectedItem_Index;
- (int) GetSelectedItem_Hash;
- (IBAction) MoveForward;
- (IBAction) MoveBackward;
- (void) RotateToOrigin;
- (void) RotateForward;
- (void) RotateBackward;
@end

View File

@@ -0,0 +1,512 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "Carousel.h"
#include <algorithm>
@implementation idCarouselItem
@synthesize image;
@synthesize title;
@synthesize hash;
@end
@implementation idCarousel
// Move full turn at this percentage
const static float CAROUSEL_CHANGE_DRAG = 0.2f;
const static float CAROUSEL_BACKITEMS_ALPHA = 0.5f;
const static float CAROUSEL_FRONTITEM_ALPHA = 1.0f;
enum idCarouselDrag_t {
CAROUSEL_DRAG_MOVE_NONE = 0,
CAROUSEL_DRAG_MOVE_FORWARD,
CAROUSEL_DRAG_MOVE_BACKWARD
};
/*
========================
Lerp
========================
*/
static CGFloat Lerp(CGFloat from, CGFloat to, CGFloat f )
{
return from + ( ( to - from ) * f );
}
/*
========================
LerpPoint
========================
*/
static CGPoint LerpPoint(CGPoint a, CGPoint b, CGFloat t)
{
CGPoint p;
p.x = Lerp(a.x, b.x, t);
p.y = Lerp(a.y, b.y, t);
return p;
}
/*
========================
LerpSize
========================
*/
static CGSize LerpSize(CGSize a, CGSize b, CGFloat t)
{
CGSize s;
s.width = Lerp(a.width, b.width, t);
s.height = Lerp(a.height, b.height, t);
return s;
}
/*
========================
LerpRect
========================
*/
static CGRect LerpRect( CGRect a, CGRect b, CGFloat t ) {
CGRect r;
r.origin = LerpPoint( a.origin, b.origin, t );
r.size = LerpSize( a.size, b.size, t );
return r;
}
/*
========================
awakeFromNib
========================
*/
- (void) awakeFromNib {
mainRect = mainSelection.frame;
prevRect = prevSelection.frame;
nextRect = nextSelection.frame;
// Allocate our Items Array
carouselItems = [[ NSMutableArray alloc ] init ];
}
/*
========================
touchesBegan
========================
*/
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
(void)(event);
hasDragged = 0;
startDragPoint = [[touches anyObject] locationInView:self];
}
/*
========================
touchesMoved
========================
*/
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
(void)(event);
if( prevSelection == nil || nextSelection == nil ) {
// Nothing to transition to... dont swip transition
return;
}
CGPoint movedPoint = [[touches anyObject] locationInView:self];
CGFloat offsetX = movedPoint.x - startDragPoint.x;
// Find out where im at relative to the side of the screen
CGFloat percentage = offsetX / self.frame.size.width;
percentage = (float)fmin( percentage, 1.0f );
percentage = (float)fmax( percentage, -1.0f );
if( percentage > CAROUSEL_CHANGE_DRAG ) {
hasDragged = CAROUSEL_DRAG_MOVE_FORWARD;
} else if( percentage < -CAROUSEL_CHANGE_DRAG ) {
hasDragged = CAROUSEL_DRAG_MOVE_BACKWARD;
}
if( percentage > 0 ) { // Going to the right of the screen..
CGRect newMainRect = LerpRect( mainRect, nextRect , percentage );
CGRect newNextRect = LerpRect( nextRect, prevRect , percentage );
CGRect newPrevRect = LerpRect( prevRect, mainRect , percentage );
mainSelection.frame = newMainRect;
prevSelection.frame = newPrevRect;
nextSelection.frame = newNextRect;
mainSelection.alpha = Lerp( CAROUSEL_FRONTITEM_ALPHA, CAROUSEL_BACKITEMS_ALPHA, percentage );
prevSelection.alpha = Lerp( CAROUSEL_BACKITEMS_ALPHA, CAROUSEL_FRONTITEM_ALPHA, percentage );
} else { // Going the left.
percentage = fabsf( percentage );
CGRect newMainRect = LerpRect( mainRect, prevRect , percentage );
CGRect newNextRect = LerpRect( nextRect, mainRect , percentage );
CGRect newPrevRect = LerpRect( prevRect, nextRect , percentage );
mainSelection.frame = newMainRect;
prevSelection.frame = newPrevRect;
nextSelection.frame = newNextRect;
mainSelection.alpha = Lerp( CAROUSEL_FRONTITEM_ALPHA, CAROUSEL_BACKITEMS_ALPHA, percentage );
nextSelection.alpha = Lerp( CAROUSEL_BACKITEMS_ALPHA, CAROUSEL_FRONTITEM_ALPHA, percentage );
}
}
/*
========================
touchesEnded
========================
*/
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
(void)(event);
(void)(touches);
if( hasDragged == CAROUSEL_DRAG_MOVE_FORWARD ) {
[ self RotateForward ];
} else if( hasDragged == CAROUSEL_DRAG_MOVE_BACKWARD ) {
[ self RotateBackward ];
} else {
[ self RotateToOrigin ];
}
}
/*
========================
Init
========================
*/
- (void) Init {
// Get the items At the new layout.
idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ];
idCarouselItem * nItem = [ carouselItems objectAtIndex: (NSUInteger)nextItem ];
idCarouselItem * pItem = [ carouselItems objectAtIndex: (NSUInteger)prevItem ];
// Set the Main Selection Text.
[ selectionLabel setText: cItem.title ];
// Set the prev selection UIImage
mainSelection.image = cItem.image;
prevSelection.image = nItem.image;
nextSelection.image = pItem.image;
}
/*
========================
AddCarouselItem
========================
*/
- (void) AddCarouselItem:( NSString* )Image
:( NSString* )Title
:( int ) ItemHash {
idCarouselItem * Item = [ idCarouselItem alloc ];
// Initialize the Item with the data passed in.
Item.image = [UIImage imageNamed: Image ];
Item.title = Title;
Item.hash = ItemHash;
// Add the Item to our object array.
[ carouselItems addObject: Item ];
// Set the Cur Item as the one just added.
currentItem = 0;
nextItem = 1;
prevItem = (NSInteger)[ carouselItems count ] - 1;
}
/*
========================
GetSelectedItem_Index
========================
*/
- (NSInteger) GetSelectedItem_Index {
return currentItem;
}
/*
========================
GetSelectedItem_Hash
========================
*/
- (int) GetSelectedItem_Hash {
idCarouselItem * item = [ carouselItems objectAtIndex: (NSUInteger)currentItem ];
return item.hash;
}
/*
========================
MoveForward
Interface Builder Direct Access to moving the Carousel
========================
*/
- (IBAction) MoveForward {
[ self RotateForward ];
}
/*
========================
MoveBackward -
Interface Builder Direct Access to moving the Carousel
========================
*/
- (IBAction) MoveBackward {
[ self RotateBackward ];
}
/*
========================
RotateToOrigin
========================
*/
- (void) RotateToOrigin {
// Animate back to the correct position.
// Move the Current Selection to Next Selection
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// Move them into Place.
mainSelection.frame = mainRect;
prevSelection.frame = prevRect;
nextSelection.frame = nextRect;
mainSelection.alpha = 1.0f;
nextSelection.alpha = CAROUSEL_BACKITEMS_ALPHA;
prevSelection.alpha = CAROUSEL_BACKITEMS_ALPHA;
[UIView commitAnimations];
}
/*
========================
RotateForward
========================
*/
- (void) RotateForward {
if( prevSelection == nil || nextSelection == nil ) {
// Flip book to the next selection.
// increment the item indicies.
currentItem++;
nextItem++;
prevItem++;
// Check the Extents.
if( currentItem >= (NSInteger)[ carouselItems count ] ) {
currentItem = 0;
}
if( nextItem >= (NSInteger)[ carouselItems count ] ) {
nextItem = 0;
}
if( prevItem >= (NSInteger)[ carouselItems count ] ) {
prevItem = 0;
}
idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ];
// Set the Main Selection Text.
[ selectionLabel setText: cItem.title ];
// Set the prev selection UIImage
mainSelection.image = cItem.image;
[self sendActionsForControlEvents:UIControlEventValueChanged];
return;
}
UIImageView * tempMain = mainSelection;
UIImageView * tempPrev = prevSelection;
UIImageView * tempNext = nextSelection;
// Move the Current Selection to Next Selection
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// Move them into Place.
mainSelection.frame = nextRect;
prevSelection.frame = mainRect;
nextSelection.frame = prevRect;
// Darken the prev/next
mainSelection.alpha = CAROUSEL_BACKITEMS_ALPHA;
prevSelection.alpha = CAROUSEL_FRONTITEM_ALPHA;
nextSelection.alpha = CAROUSEL_BACKITEMS_ALPHA;
[UIView commitAnimations];
// Swap out the ImageViews so that they are in the correct order.
nextSelection = tempMain;
mainSelection = tempPrev;
prevSelection = tempNext;
// Make sure they are in back of the main selection.
[ self sendSubviewToBack: nextSelection ];
[ self sendSubviewToBack: prevSelection ];
// increment the item indicies.
currentItem++;
nextItem++;
prevItem++;
// Check the Extents.
if( currentItem >= (NSInteger)[ carouselItems count ] ) {
currentItem = 0;
}
if( nextItem >= (NSInteger)[ carouselItems count ] ) {
nextItem = 0;
}
if( prevItem >= (NSInteger)[ carouselItems count ] ) {
prevItem = 0;
}
// Get the items At the new layout.
idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ];
idCarouselItem * nItem = [ carouselItems objectAtIndex: (NSUInteger)nextItem ];
idCarouselItem * pItem = [ carouselItems objectAtIndex: (NSUInteger)prevItem ];
// Set the Main Selection Text.
[ selectionLabel setText: cItem.title ];
// Set the prev selection UIImage
mainSelection.image = cItem.image;
prevSelection.image = nItem.image;
nextSelection.image = pItem.image;
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
/*
========================
RotateBackward
========================
*/
- (void) RotateBackward {
if( nextSelection == nil || prevSelection == nil ) {
// increment the item indicies.
currentItem--;
nextItem--;
prevItem--;
// Check the Extents.
if( currentItem < 0 ) {
currentItem = (NSInteger)[ carouselItems count ] - 1;
}
if( nextItem < 0 ) {
nextItem = (NSInteger)[ carouselItems count ] - 1;;
}
if( prevItem < 0 ) {
prevItem = (NSInteger)[ carouselItems count ] - 1;;
}
idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ];
// Set the Main Selection Text.
[ selectionLabel setText: cItem.title ];
// Set the prev selection UIImage
mainSelection.image = cItem.image;
[self sendActionsForControlEvents:UIControlEventValueChanged];
return;
}
UIImageView * tempMain = mainSelection;
UIImageView * tempPrev = prevSelection;
UIImageView * tempNext = nextSelection;
// Move the Current Selection to Next Selection
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// Move them into Place.
mainSelection.frame = prevRect;
prevSelection.frame = nextRect;
nextSelection.frame = mainRect;
// Darken the prev/next
mainSelection.alpha = CAROUSEL_BACKITEMS_ALPHA;
prevSelection.alpha = CAROUSEL_BACKITEMS_ALPHA;
nextSelection.alpha = CAROUSEL_FRONTITEM_ALPHA;
[UIView commitAnimations];
// Swap out the ImageViews so that they are in the correct order.
nextSelection = tempPrev;
mainSelection = tempNext;
prevSelection = tempMain;
// Make sure they are in back of the main selection.
[ self sendSubviewToBack: nextSelection ];
[ self sendSubviewToBack: prevSelection ];
// increment the item indicies.
currentItem--;
nextItem--;
prevItem--;
// Check the Extents.
if( currentItem < 0 ) {
currentItem = (NSInteger)[ carouselItems count ] - 1;
}
if( nextItem < 0 ) {
nextItem = (NSInteger)[ carouselItems count ] - 1;;
}
if( prevItem < 0 ) {
prevItem = (NSInteger)[ carouselItems count ] - 1;;
}
// Get the items At the new layout.
idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger) currentItem ];
idCarouselItem * nItem = [ carouselItems objectAtIndex: (NSUInteger)nextItem ];
idCarouselItem * pItem = [ carouselItems objectAtIndex: (NSUInteger)prevItem ];
// Set the Main Selection Text.
[ selectionLabel setText: cItem.title ];
// Set the prev selection UIImage
mainSelection.image = cItem.image;
prevSelection.image = nItem.image;
nextSelection.image = pItem.image;
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
@end

View File

@@ -0,0 +1,134 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
================================================================================================
A game-generic C++ wrapper around the iOS Game Center functionality.
The class checks for Game Center availability in the constructor, and if Game Center is found
to be unsupported, a flag is set that causes all other function calls to early-exit and
do nothing. This way, the game code doesn't have to worry about whether Game Center is supported
for every call it makes, but can still check for support in order to, say, adjust the UI
if necessary.
This class is not meant to be subclassed.
This class uses the pimpl idiom (see http://herbsutter.com/gotw/_100/) to hide many of the
implementation details. I've found this to be a decent way to hide all the Objective-C code
from user code, so that C++-only portions of code can still access iOS functionality.
================================================================================================
*/
#ifndef IDMOBILELIB_GAMECENTER_H
#define IDMOBILELIB_GAMECENTER_H
#include <objc/objc.h>
#include <string>
#include <vector>
#include <tr1/cstdint>
#include "../sys/sys_defines.h"
/*
================================================
Contains function definitions to be overridden by specific games.
================================================
*/
class idGameCenterMatchHandler
{
public:
virtual ~idGameCenterMatchHandler() {}
void createdMatch() { createdMatchImpl(); }
void allPlayersConnected( std::vector<std::string> connectedPlayerIDs ) {
allPlayersConnectedImpl( connectedPlayerIDs );
}
void playerConnected( std::string playerIdentifier ) {
playerConnectedImpl( playerIdentifier );
}
void playerDisconnected( std::string playerIdentifer ) {
playerDisconnectedImpl( playerIdentifer );
}
void receivedData( std::string fromPlayerID, const void * data, int numBytes ) {
receivedDataImpl( fromPlayerID, data, numBytes );
}
private:
virtual void createdMatchImpl() = 0;
virtual void allPlayersConnectedImpl( std::vector<std::string> connectedPlayerIDs ) = 0;
virtual void playerConnectedImpl( std::string playerIdentifer ) = 0;
virtual void playerDisconnectedImpl( std::string playerIdentifer ) = 0;
virtual void receivedDataImpl( std::string fromPlayerID, const void * data, int numBytes ) = 0;
};
namespace idGameCenter {
static const int MAX_PACKET_SIZE_IN_BYTES = 1500;
struct matchParms_t {
unsigned int minimumPlayers;
unsigned int maximumPlayers;
std::tr1::uint32_t automatchGroup;
};
void Initialize();
void Shutdown();
void AuthenticateLocalPlayer( id currentViewController, idGameCenterMatchHandler * handler );
bool IsAvailable();
bool IsLocalPlayerAuthenticated();
void HandleMoveToBackground();
void PresentMatchmaker( id currentViewController, matchParms_t parms, idGameCenterMatchHandler * handler );
void PushMatchmakerToNavigationController( id navigationController,
matchParms_t parms,
idGameCenterMatchHandler * handler );
bool IsInMatch();
void SendPacketToPlayerUnreliable( std::string destinationPlayer,
void * packet,
std::size_t packetSize );
void SendPacketToPlayerReliable( std::string destinationPlayer,
void * packet,
std::size_t packetSize );
void BroadcastPacketReliable( void * packet, int numBytes );
void DisconnectFromMatch();
}
#endif

View File

@@ -0,0 +1,712 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "GameCenter.h"
#include "objectivec_utilities.h"
#include "LocalizationObjectiveC.h"
#include "ios_interface.h"
#include <string>
#import <GameKit/GameKit.h>
#import <UIKit/UIKit.h>
#import <UIKit/UIDevice.h>
#import <Foundation/NSData.h>
namespace {
enum matchmakerViewMode_t {
MATCH_VIEW_MODAL,
MATCH_VIEW_PUSH_TO_NAVIGATION_CONTROLLER
};
}
/*
================================================
The Objective-C delegate required for implementing Game Kit matches.
================================================
*/
@interface MatchDelegate : NSObject< GKMatchmakerViewControllerDelegate, GKMatchDelegate >
@property(nonatomic, assign) UIViewController * gameViewController;
@property(nonatomic, assign) idGameCenterMatchHandler * matchHandler;
@property(nonatomic, retain) GKMatch * currentMatch;
@property(nonatomic, assign) BOOL matchHasStarted;
@property(nonatomic, assign) matchmakerViewMode_t matchmakerMode;
+ (MatchDelegate*)sharedMatchDelegate;
@end
static MatchDelegate * sharedMatchDelegateInstance = nil;
// Unnamed-namespace for internal-linkage definitions.
namespace {
/*
========================
Game Center is only supported on iOS 4.1 and later. If we are running on a device
that doesn't support Game Center, we must disable its functionality.
The implementation of the check was taken straight form the Apple documentation.
========================
*/
bool HasGameCenterSupport() {
BOOL localPlayerClassAvailable = (NSClassFromString(@"GKLocalPlayer")) != nil;
// The device must be running iOS 4.1 or later.
NSString *reqSysVer = @"4.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending);
return (localPlayerClassAvailable && osVersionSupported);
}
}
@implementation MatchDelegate
@synthesize matchHandler;
@synthesize gameViewController;
@synthesize currentMatch;
@synthesize matchHasStarted;
@synthesize matchmakerMode;
/*
========================
Singleton implementation. Since we should only ever have one match going on at a time,
the delegate might as well be a singleton. This is Apple's idiomatic example of a Singleton
in Objective-C.
========================
*/
+ (MatchDelegate*)sharedMatchDelegate
{
if (sharedMatchDelegateInstance == nil) {
sharedMatchDelegateInstance = [[super allocWithZone:NULL] init];
sharedMatchDelegateInstance->matchHandler = NULL;
sharedMatchDelegateInstance->matchHasStarted = NO;
sharedMatchDelegateInstance->currentMatch = nil;
}
return sharedMatchDelegateInstance;
}
+ (id)allocWithZone:(NSZone *)zone
{
(void)zone;
return [[self sharedMatchDelegate] retain];
}
- (id)copyWithZone:(NSZone *)zone
{
(void)zone;
return self;
}
- (id)retain
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax; //denotes an object that cannot be released
}
- (oneway void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}
/*
========================
Called by the system when Game Center receives a packet from another player. I was
somewhat surprised that this method actually runs on the main thread.
========================
*/
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
(void)match;
(void)playerID;
// Sanity-check the size of the data. Discard any packets that won't fit.
if ( static_cast<int>( [data length] ) > idGameCenter::MAX_PACKET_SIZE_IN_BYTES ) {
printf( "Received a packet that was too big. Discarding.\n" );
return;
}
// Sanity-check the size of the data. Discard any packets with zero length.
if ( [data length] == 0 ) {
printf( "Received a packet with zero length. Discarding.\n" );
return;
}
// Give the callback a chance to process the packet.
self.matchHandler->receivedData( NSStringToStdString( playerID ),
[data bytes],
static_cast<int>( [data length] ) );
}
/*
========================
Called by the system when a player's state changes (for example, they connect or disconnect).
========================
*/
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
switch (state)
{
case GKPlayerStateConnected:
matchHandler->playerConnected( NSStringToStdString( playerID ) );
if (!matchHasStarted && match.expectedPlayerCount == 0)
{
matchHasStarted = YES;
std::vector<std::string> players;
for( NSString* currentID in match.playerIDs ) {
players.push_back( NSStringToStdString( currentID ) );
}
matchHandler->allPlayersConnected( players );
}
break;
case GKPlayerStateDisconnected:
matchHandler->playerDisconnected( NSStringToStdString( playerID ) );
break;
}
}
/*
========================
Called by the system if the connection with a player fails.
========================
*/
- (void)match:(GKMatch *)match connectionWithPlayerFailed:(NSString *)playerID withError:(NSError *)error {
(void)match;
(void)playerID;
DisplayNSErrorMessage( @"GameKit Error", error );
}
/*
========================
Called by the system if the matchmaking interface fails.
========================
*/
- (void)match:(GKMatch *)match didFailWithError:(NSError *)error {
(void)match;
DisplayNSErrorMessage( @"GameKit Error", error );
}
// GKMatchmakerViewController
/*
========================
Called by the system if the user dismisses the matchmaking interface.
========================
*/
- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController
{
switch ( matchmakerMode ) {
case MATCH_VIEW_MODAL: {
[gameViewController dismissModalViewControllerAnimated:YES];
break;
}
case MATCH_VIEW_PUSH_TO_NAVIGATION_CONTROLLER: {
[viewController.navigationController popViewControllerAnimated:YES];
break;
}
}
}
/*
========================
Called by the system if there is an error in the matchmaking process.
========================
*/
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error
{
(void)viewController;
DisplayNSErrorMessage( idLocalization_GetNSString( @"Matchmaking error" ), error );
switch ( matchmakerMode ) {
case MATCH_VIEW_MODAL: {
[gameViewController dismissModalViewControllerAnimated:YES];
break;
}
case MATCH_VIEW_PUSH_TO_NAVIGATION_CONTROLLER: {
[viewController.navigationController popViewControllerAnimated:YES];
break;
}
}
}
/*
========================
Called by the system if it finds a match.
========================
*/
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)match
{
(void)viewController;
(void)match;
switch ( matchmakerMode ) {
case MATCH_VIEW_MODAL: {
[gameViewController dismissModalViewControllerAnimated:YES];
break;
}
case MATCH_VIEW_PUSH_TO_NAVIGATION_CONTROLLER: {
[viewController.navigationController popViewControllerAnimated:NO];
break;
}
}
NSLog(@"Found a Game Center match!!!");
self.currentMatch = match;
match.delegate = self;
matchHandler->createdMatch();
if (!matchHasStarted && match.expectedPlayerCount == 0)
{
matchHasStarted = NO;
std::vector<std::string> players;
for( NSString* currentID in match.playerIDs ) {
players.push_back( NSStringToStdString( currentID ) );
}
matchHandler->allPlayersConnected( players );
}
}
@end
/*
================================================
The private implementation of idGameCenter, defined here in order to insulate user code from
Objective-C land.
================================================
*/
namespace {
// Cache the result of HasGameCenterSupport. Even if HasGameCenterSupport returns true,
// it's possible that a Game Kit method may cause a GKErrorNotSupported. If it does, this
// variable will be set to false in HandleError.
bool isAvailable;
// Cache the player identifier. This is the unique key used to distiguish players in
// Game Kit. All data associated with a player should be tied to this ID, such as
// achievement and savegame progress. Note that this ID can change if a user task-switches
// to the Game Center app and logs in with a different account.
// The string will be empty if no local player is authenticated.
// The string is UTF8 encoded.
std::string playerIdentifier;
// Store the match handler object. This is how we deal with "callbacks" from the Game Center
// API.
idGameCenterMatchHandler * matchHandler;
void HandleError( NSError * error );
void ConfigureDelegate( matchmakerViewMode_t mode,
id currentViewController,
idGameCenterMatchHandler * handler );
void SendPacketToPlayerHelper( std::string destinationPlayer,
void *packet,
std::size_t numBytes,
GKMatchSendDataMode mode );
/*
========================
Handles errors reported by the Game Kit APIs. If it gets GKErrorNotSupported, this function
sets isAvailable to false.
========================
*/
void HandleError( NSError * error ) {
if ( error == nil ) {
return;
}
switch ( [error code] ) {
case GKErrorGameUnrecognized: {
NSLog( @"GameKit error: Game unrecognized." );
break;
}
case GKErrorNotSupported: {
NSLog( @"GameKit error: Not supported. Disabling GameKit features." );
isAvailable = false;
break;
}
default: {
break;
}
}
}
/*
========================
Sets up neede properties of the match delegate. Call this before showing the matchmaking view
controller. This implementation supports two ways of showing the built-in matchmaker, either
modally or as a new view controller on a navigation controller's stack. If using a
navigation controller, the currentViewController parameter can be left nil.
========================
*/
void ConfigureDelegate( matchmakerViewMode_t mode,
id currentViewController,
idGameCenterMatchHandler * handler ) {
[MatchDelegate sharedMatchDelegate].matchmakerMode = mode;
[MatchDelegate sharedMatchDelegate].matchHandler = handler;
[MatchDelegate sharedMatchDelegate].gameViewController = currentViewController;
[MatchDelegate sharedMatchDelegate].matchHasStarted = NO;
}
/*
========================
Sends a packet to a player ID with the data mode specified in the parameter.
========================
*/
void SendPacketToPlayerHelper( std::string destinationPlayer,
void *packet,
std::size_t numBytes,
GKMatchSendDataMode mode ) {
if ( idGameCenter::IsAvailable() == false || idGameCenter::IsLocalPlayerAuthenticated() == false ) {
return;
}
if ( idGameCenter::IsInMatch() == false ) {
return;
}
GKMatch * theMatch = [MatchDelegate sharedMatchDelegate].currentMatch;
NSError * theError = nil;
NSData *nsPacket = [ NSData dataWithBytes:packet length:static_cast<NSUInteger>( numBytes ) ];
NSArray *playerArray = [ NSArray arrayWithObject:StdStringToNSString( destinationPlayer ) ];
[theMatch sendData:nsPacket toPlayers:playerArray withDataMode:mode error:&theError];
if ( theError != nil )
{
DisplayNSErrorMessage( @"GameKit Error", theError );
}
}
}
namespace idGameCenter {
/*
========================
impl constructor. Sets the inital value of isAvailable based on the OS checks in
HasGameCenterSupport. Note that isAvailable might be set to false later if a GameKit API
returns a GKErrorNotSupported.
========================
*/
void Initialize() {
isAvailable = HasGameCenterSupport();
matchHandler = NULL;
}
/*
========================
Returns true if the runtime device supports Game Center. If it doesn't, we may need to
disable UI elements, etc.
========================
*/
bool IsAvailable() {
return isAvailable;
}
/*
========================
Returns true if there is a local player authenticated.
========================
*/
bool IsLocalPlayerAuthenticated() {
return !playerIdentifier.empty();
}
/*
========================
Attempts to authenticate the local player. Apple recommends that this be done as soon as
possible after the game starts up and is able to display a UI (probably in
applicationDidFinishLaunching).
========================
*/
void AuthenticateLocalPlayer( id currentViewController, idGameCenterMatchHandler * handler ) {
// Early exit if Game Center is not supported.
if ( IsAvailable() == false ) {
return;
}
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[localPlayer authenticateWithCompletionHandler:^(NSError * error) {
if ( localPlayer.isAuthenticated )
{
// Perform additional tasks for the authenticated player.
GKLocalPlayer * lp = [GKLocalPlayer localPlayer];
// Cache the player identifier string.
std::string newPlayerIdentifier = NSStringToStdString( [lp playerID] );
// If the player changed while the app was in the background, the playerIDs will
// be different. If they are, we have to switch any game state to reflect the
// new player.
if ( newPlayerIdentifier != playerIdentifier ) {
// TODO: Switch game state to reflect the newly logged in player.
}
playerIdentifier = newPlayerIdentifier;
// Set up the invitation handler. This code handles the cases where a friend
// is invited to the game from the matchmaking UI or the Game Center application.
[GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
// Disconnect from any previous game.
idGameCenter::DisconnectFromMatch();
ConfigureDelegate( MATCH_VIEW_MODAL, currentViewController, handler );
if (acceptedInvite)
{
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
mmvc.matchmakerDelegate = [MatchDelegate sharedMatchDelegate];
[currentViewController presentModalViewController:mmvc animated:YES];
}
else if (playersToInvite)
{
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 2;
request.maxPlayers = 4;
request.playersToInvite = playersToInvite;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = [MatchDelegate sharedMatchDelegate];
[currentViewController presentModalViewController:mmvc animated:YES];
}
};
} else {
// No new local player is logged in. If no player was logged in before, we shouldn't
// have to do anything here.
// But if a player was previously logged in, we need to update the game state, for
// example, clear achievement progress or load different saved games.
if ( !playerIdentifier.empty() ) {
// TODO: Clean up state related to the old playerIdentifier.
}
// Empty the string to indicate no one is logged in.
playerIdentifier.clear();
}
HandleError( error );
}];
}
/*
========================
This function must be called when the app is moving to the background (such as from
applicationWillResignActive). It will de-authenticate the local player, because the user
might sign out while our app is in the background.
According to the Apple documentation, we need to de-authenticate the local player when the app
moves to the background. The implication of this is that for lockstep games like DOOM, we
can't continue to update the game while our app is in the background. In order to not cause
problems for other players, we just disconnect from a match (if any) right here.
TODO: When we support achievements and/or leaderboards, serialize out any data that hasn't
been successfully sent to Game Center yet. We'll need to do this because the OS might kill
our app while it's in the background.
========================
*/
void HandleMoveToBackground() {
if ( IsInMatch() ) {
ShowSystemAlert( "Connection lost", "Lost connection to server" );
}
DisconnectFromMatch();
playerIdentifier.empty();
}
/*
========================
Presents Game Center's built-in matchmaking view controller as a model view controller on top
of currentViewController.
MAKE SURE the handler object survives the duration of the app!
========================
*/
void PresentMatchmaker( id currentViewController, matchParms_t parms, idGameCenterMatchHandler * handler ) {
// Early exit if Game Center is not active.
if ( IsAvailable() == false || IsLocalPlayerAuthenticated() == false ) {
return;
}
ConfigureDelegate( MATCH_VIEW_MODAL, currentViewController, handler );
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = parms.minimumPlayers;
request.maxPlayers = parms.maximumPlayers;
request.playerGroup = parms.automatchGroup;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = [MatchDelegate sharedMatchDelegate];
[(UIViewController*)currentViewController presentModalViewController:mmvc animated:YES];
}
/*
========================
Presents Game Center's built-in matchmaking view controller as a new controller on top
of the navigationController's stack.
MAKE SURE the handler object survives the duration of the app!
========================
*/
void PushMatchmakerToNavigationController( id navigationController,
matchParms_t parms,
idGameCenterMatchHandler * handler ) {
// Early exit if Game Center is not active.
if ( IsAvailable() == false || IsLocalPlayerAuthenticated() == false ) {
return;
}
ConfigureDelegate( MATCH_VIEW_PUSH_TO_NAVIGATION_CONTROLLER, nil, handler );
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = parms.minimumPlayers;
request.maxPlayers = parms.maximumPlayers;
request.playerGroup = parms.automatchGroup;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = [MatchDelegate sharedMatchDelegate];
[navigationController pushViewController:mmvc animated:YES];
}
/*
========================
Returns true if the player is currently connected to a Game Center match, false if not.
========================
*/
bool IsInMatch() {
return [MatchDelegate sharedMatchDelegate].currentMatch != nil;
}
/*
========================
Sends an unreliable packet to a single player.
========================
*/
void SendPacketToPlayerUnreliable( std::string destinationPlayer,
void *packet,
std::size_t numBytes ) {
SendPacketToPlayerHelper( destinationPlayer, packet, numBytes, GKMatchSendDataUnreliable );
}
/*
========================
Sends a reliable packet to a single player.
========================
*/
void SendPacketToPlayerReliable( std::string destinationPlayer,
void *packet,
std::size_t numBytes ) {
SendPacketToPlayerHelper( destinationPlayer, packet, numBytes, GKMatchSendDataReliable );
}
/*
========================
Sends a packet to all other players in the current match. Just returns if Game Center is not
available or if the local player is not in a match.
========================
*/
void BroadcastPacketReliable( void * packet, int numBytes ) {
if ( IsAvailable() == false || IsLocalPlayerAuthenticated() == false ) {
return;
}
if ( IsInMatch() == false ) {
return;
}
GKMatch * theMatch = [MatchDelegate sharedMatchDelegate].currentMatch;
NSError * theError = nil;
NSData *nsPacket = [NSData dataWithBytes:packet length:static_cast<NSUInteger>(numBytes)];
[theMatch sendDataToAllPlayers:nsPacket withDataMode:GKMatchSendDataReliable error:&theError];
if ( theError != nil )
{
DisplayNSErrorMessage( @"GameKit Error", theError );
}
}
/*
========================
If this player is currently connected to a match. this will disconnect them.
========================
*/
void DisconnectFromMatch() {
if ( IsInMatch() ) {
[[MatchDelegate sharedMatchDelegate].currentMatch disconnect];
// currentMatch is a retained property, so this will release it.
[MatchDelegate sharedMatchDelegate].currentMatch = nil;
}
}
}

View File

@@ -0,0 +1,95 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
================================================================================================
Interface to the device's In-App Purchase system.
This interface was designed to be dropped into any game that needs support for in-app purchases,
that is, there is nothing game-specific about this interface or its implementation.
It is essentially a singleton implemented in the idInAppPurchase namespace. The singleton must
be initialized at application launch (via Initialize()) and shut down at application exit (via
Shutdown()).
There are functions to request information about products for sale within the app, check whether
a particular product has been purchased, and get the localized price for a product, suitable
for displaying in the user interface.
Generally an app should call RequestInformation() at startup (but after Initialize()) and pass
in all the product identifiers that the app offers for sale. The request will run in the
background so that the interface will remain responsive. Once the requests have been returned,
the application can get the price information and actually initiate purchases of products.
================================================================================================
*/
#ifndef INAPPSTORE_H
#define INAPPSTORE_H
#include <vector>
#include <string>
#include <tr1/functional>
namespace idInAppStore {
void Initialize( const std::vector<std::string> & productIdentifiers );
void Shutdown();
bool IsEnabled();
void ShowDisabledAlert( std::string title,
std::string description,
std::string okButton );
bool HasPurchased( const char * const productIdentifier );
bool CanPurchase( const char * const productIdentifier );
bool IsWaitingForInformation( const char * const productIdentifier );
bool IsWaitingForPurchase( const char * const productIdentifier );
std::string GetLocalizedPrice( const char * const productIdentifier );
void StartPurchase( const char * const productIdentifier );
/*
========================
The application can register callbacks to be notified of events that occur relating to
the in-app store. The first parameter to the callback function is the product identifier
string for the product that was affected, the second is the status of that product.
========================
*/
enum productStatus_t {
PRODUCT_STATUS_TRANSACTION_FAILED,
PRODUCT_STATUS_RECEIVED_INFORMATION,
PRODUCT_STATUS_PURCHASED
};
typedef std::tr1::function< void ( const char * const, productStatus_t ) > callback_t;
void SetCallback( callback_t callback );
void ClearCallback();
}
#endif

View File

@@ -0,0 +1,683 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
================================================================================================
Implentation of the In-App Purchase system for iOS devices.
This implementation conforms to the interface in InAppStore.h. It uses the NSUserDefaults object
provided by the system to keep track of the state of the products that the application offers.
================================================================================================
*/
#include "InAppStore.h"
#import <StoreKit/StoreKit.h>
#import <UIKit/UIKit.h>
#include <map>
#include <utility>
#include <vector>
#include <algorithm>
// For ease of development, leave this defined to skip in-app purchase prompts.
//#define TEST_ALL_PRODUCTS_PURCHASED
@interface MyStoreObserver : NSObject<SKProductsRequestDelegate, SKPaymentTransactionObserver> {
}
// SKProductsRequestDelegate methods
- (void)productsRequest: (SKProductsRequest *)request didReceiveResponse: (SKProductsResponse *)response;
// SKPaymentTransactionObserver methods
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions;
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error;
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue;
// MyStoreObserver methods
- (void)completeTransaction:(SKPaymentTransaction *)transaction;
- (void)failedTransaction:(SKPaymentTransaction *)transaction;
- (void)restoreTransaction:(SKPaymentTransaction *)transaction;
- (void)finalizeTransaction:(SKPaymentTransaction *)transaction;
@end
// Unnamed-namespace for stuff that's "private" to this file (internal linkage).
namespace {
// The single instance of the store observer. This is created in Initialize and released
// in Shutdown.
MyStoreObserver * observer;
// The callback to invoke when an interesting event occurs.
idInAppStore::callback_t callbackObject;
/*
================================================
Each product identifier has an associated state to keep track of the progress of
in-app purchases. These states are stored in the NSUserDefaults for the corresponding
product identifier. These states are not in an enum because the the NSUserDefaults store
NSIntegers, and we can't define the type of an enum in C++03.
================================================
*/
typedef NSInteger productState_t;
// This is the state of a product if it not found in the user's defaults.
const productState_t PRODUCT_NOT_FOUND = 0;
// Information from this product has been requested, but has not been received yet.
const productState_t PRODUCT_WAIT_FOR_INFORMATION = 1;
// Information for this product is available, but a purchase has not been initiated.
const productState_t PRODUCT_HAS_INFORMATION = 2;
// A purchase was initiated, and the application is waiting for the App Store to
// process the purchase.
const productState_t PRODUCT_WAIT_FOR_PURCHASE = 3;
// The app store has fully processed the purchase and the product is available for the
// user/
const productState_t PRODUCT_PURCHASED = 4;
void RequestInformation( const std::vector<std::string> & productIdentifiers );
/*
================================================
Store product information in a C++ friendly way.
================================================
*/
struct productInformation_t {
std::string identifier;
std::string localizedPrice;
productInformation_t( const std::string & identifier_, const std::string & localizedPrice_ )
: identifier( identifier_ )
, localizedPrice( localizedPrice_ )
{
}
};
// Cache the product information that has been received from the App Store.
typedef std::map<std::string, productInformation_t> productMap_t;
productMap_t productCache;
/*
========================
GetProductState
Queries the NSUserDefaults for the state of the product corresponding to the
productIdentifier.
========================
*/
productState_t GetProductState( const char * const productIdentifier ) {
#if defined( TEST_ALL_PRODUCTS_PURCHASED )
return PRODUCT_PURCHASED;
#endif
// Convert the C string to an NSString for use with NSUserDefaults.
NSString *productKey = [NSString stringWithCString:productIdentifier
encoding:NSUTF8StringEncoding];
// Purchase records are stored in the standardUserDefaults, with a key equal to the
// product identifier.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger productState = [defaults integerForKey:productKey];
return productState;
}
/*
========================
SetProductState
Sets the NSUserDefaults value corresponding to product identifier to the given state.
========================
*/
void SetProductState( NSString * productIdentifier, productState_t state ) {
// Purchase records are stored in the standardUserDefaults, with a key equal to the
// product identifier.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:state forKey:productIdentifier];
}
/*
========================
SetProductState
Sets the NSUserDefaults value corresponding to product identifier to the given state.
========================
*/
void SetProductState( const char * const productIdentifier, productState_t state ) {
// Convert the C string to an NSString for use with NSUserDefaults.
NSString *productKey = [NSString stringWithCString:productIdentifier
encoding:NSUTF8StringEncoding];
SetProductState( productKey, state );
}
/*
========================
RequestInformation
Queries the App Store for information about the all the identifiers in the vector.
When the App Store responds, calls the callback. The product identifiers are UTF8 encoded.
If in-app purchases are disabled, this function does nothing. The application may want to
show an alert in this case. The application can call IsEnabled() to check for this.
========================
*/
void RequestInformation( const std::vector<std::string> & productIdentifiers ) {
// Early exit if the system hasn't been initialized.
if ( observer == nil ) {
printf( "In-App Purchase system not initialized. Can't purchase anything!\n" );
return;
}
// Early exit if in-app purchases are disabled.
if ( [SKPaymentQueue canMakePayments] == FALSE ) {
printf( "In-App Purchases are disabled for this device. Can't purchase anything!\n" );
return;
}
// This will be the set of product identifiers to request from the App Store.
NSMutableSet * identifiersToRequest = [NSMutableSet setWithCapacity: productIdentifiers.size()];
#ifndef NDEBUG
// For debugging purposes, set this flag to 'true' and all in-app purchase products
// will be reset to the unpurchased state.
bool resetPurchases = false;
if ( resetPurchases ) {
for( std::vector<std::string>::const_iterator i = productIdentifiers.begin(); i != productIdentifiers.end(); ++i ) {
SetProductState( i->c_str(), PRODUCT_NOT_FOUND );
}
}
#endif
// Check the NSUserDefaults for each identifier requested, to get the state of
// the product.
for( std::vector<std::string>::const_iterator i = productIdentifiers.begin(); i != productIdentifiers.end(); ++i ) {
// If the user has not purchased this product, we need to request information about
// it from the App Store.
productState_t productState = GetProductState( i->c_str() );
if ( productState != PRODUCT_PURCHASED ) {
SetProductState( i->c_str(), PRODUCT_WAIT_FOR_INFORMATION );
NSString * nsIdentifier = [NSString stringWithCString:i->c_str()
encoding:NSUTF8StringEncoding];
[identifiersToRequest addObject:nsIdentifier];
}
}
// Now we know which identifiers to request from the store, start the request object.
if ( [identifiersToRequest count] > 0 ) {
SKProductsRequest *request= [[SKProductsRequest alloc]
initWithProductIdentifiers:identifiersToRequest ];
request.delegate = observer;
[request start];
}
}
}
namespace idInAppStore {
/*
========================
Initialize
Creates the StoreKit observer object and registers it with the payment queue. The
application must provide all the product IDs it has available for sale to this function,
so that it can request information from the app store.
========================
*/
void Initialize( const std::vector<std::string> & productIdentifiers ) {
if ( !observer ) {
observer = [[MyStoreObserver alloc] init];
// Add the observer here in case purchase requests were interrupted last time.
[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
}
RequestInformation( productIdentifiers );
}
/*
========================
Shutdown
Frees the StoreKit observer object.
========================
*/
void Shutdown() {
[observer release];
observer = nil;
}
/*
========================
IsEnabled
Returns true if in-app purchases are enabled, false if they are not.
========================
*/
bool IsEnabled() {
return ( [SKPaymentQueue canMakePayments] )? true: false;
}
/*
========================
StartPurchase
Begins the purchase process with the App Store. The product id must have been
previously requested through RequestInformation. This will launch the OS-controlled
confirmation prompt after a moment, and it might take a while to actually complete the
purchase.
========================
*/
void StartPurchase( const char * const productIdentifier ) {
if ( ![SKPaymentQueue canMakePayments] ) {
return;
}
if ( !CanPurchase( productIdentifier ) ) {
return;
}
SetProductState( productIdentifier, PRODUCT_WAIT_FOR_PURCHASE );
NSString * nsProductIdentifier = [NSString stringWithCString:productIdentifier
encoding:NSUTF8StringEncoding];
SKPayment * payment = [SKPayment paymentWithProductIdentifier:nsProductIdentifier];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
/*
========================
ShowDisabledAlert
If and only if in-app purchases are disabled, shows an alert notifying the user of this fact
and reminds him or her that he or she can enable in-app purchases in settings.
If in-app purchasees are enabled, this function does nothing.
The string parameters must be encoded in UTF8.
========================
*/
void ShowDisabledAlert( std::string title,
std::string description,
std::string okButton ) {
if ( ![SKPaymentQueue canMakePayments] ) {
// User has disabled In-App purchases in settings. Kindly remind him that he can
// enable purchases again.
if ( title.empty() ) {
title = "In-App Purchases are disabled";
}
if ( description.empty() ) {
description = "You can enable In-App purchases in your device's settings.";
}
if ( okButton.empty() ) {
title = "OK";
}
NSString * nsTitle = [NSString stringWithCString:title.c_str() encoding:NSUTF8StringEncoding];
NSString * nsDescription = [NSString stringWithCString:description.c_str() encoding:NSUTF8StringEncoding];
NSString * nsOkButton = [NSString stringWithCString:okButton.c_str() encoding:NSUTF8StringEncoding];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nsTitle
message:nsDescription
delegate:nil
cancelButtonTitle:nsOkButton
otherButtonTitles:nil];
// Make sure the alert shows up on the main thread.
[alert show];
[alert release];
}
}
/*
========================
HasPurchased
Queries the standard NSUserDefaults object for the state of the product with the given
identifier. If the state is PRODUCT_PURCHASED, the user has purchased the product.
If the state is anything else, the user has not purchased the product.
========================
*/
bool HasPurchased( const char * const productIdentifier ) {
const productState_t state = GetProductState( productIdentifier );
const bool stateIsPurchased = (state == PRODUCT_PURCHASED);
return ( stateIsPurchased );
}
/*
========================
CanPurchase
Returns true if it is safe for the application to start a purchase, false if the application
should not start a purchase at this time.
========================
*/
bool CanPurchase( const char * const productIdentifier ) {
const productState_t state = GetProductState( productIdentifier );
const bool stateHasInformaion = ( state == PRODUCT_HAS_INFORMATION );
return ( stateHasInformaion );
}
/*
========================
IsWaitingForInformation
Queries the standard NSUserDefaults object for the state of the product with the given
identifier. If the application is still waiting for the App Store to return information,
this function returns true. If the application has information, this function returns false.
========================
*/
bool IsWaitingForInformation( const char * const productIdentifier ) {
return ( GetProductState( productIdentifier ) == PRODUCT_WAIT_FOR_INFORMATION );
}
/*
========================
IsWaitingForPurchase
Queries the standard NSUserDefaults object for the state of the product with the given
identifier. If the application is still waiting for the App Store to purchase the item,
this function returns true. If the application is not waiting on the app store, returns false.
========================
*/
bool IsWaitingForPurchase( const char * const productIdentifier ) {
return ( GetProductState( productIdentifier ) == PRODUCT_WAIT_FOR_PURCHASE );
}
/*
========================
GetLocalizedPrice
Returns a UTF-8 encoded string that represents the price of the product. This string is
suitable for display to the user. If the string isn't available yet, for example, if the
App Store hasn't responded to an information request, the return value will be an empty
string.
========================
*/
std::string GetLocalizedPrice( const char * const productIdentifier ) {
productMap_t::iterator found = productCache.find( productIdentifier );
if ( found != productCache.end() ) {
return found->second.localizedPrice;
}
return std::string();
}
/*
========================
SetCallback
Stores a callback function to be invoked when something happens relating to a product.
========================
*/
void SetCallback( callback_t callback ) {
callbackObject = callback;
}
/*
========================
ClearCallback
Removes the callback function previously registered through SetCallback.
========================
*/
void ClearCallback() {
callbackObject = callback_t();
}
}
@implementation MyStoreObserver
- (void) showInvalidProductIdAlert
{
NSString * nsTitle = @"In-app purchase error";
NSString * nsDescription = @"Invalid product ID requested. In-app purchase will not work!";
NSString * nsOkButton = @"OK";
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nsTitle
message:nsDescription
delegate:nil
cancelButtonTitle:nsOkButton
otherButtonTitles:nil];
[alert show];
[alert release];
}
/*
========================
productsRequest:didReceiveResponse
Called by the OS when the application gets product information about an In-App Purchase.
========================
*/
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProduct = response.products;
NSArray *invalidProducts = response.invalidProductIdentifiers;
for ( SKProduct * product in myProduct )
{
NSLog( @"Valid product: %@", product.productIdentifier);
}
for ( NSString * productId in invalidProducts )
{
NSLog( @"Invalid product: %@", productId);
[self performSelectorOnMainThread:@selector(showInvalidProductIdAlert) withObject:nil waitUntilDone:NO];
return;
}
// We should handle the case of an empty array, this seems to occur if we send a request
// with a nonexistant product ID, but there may be other cases.
// TODO: Need a timeout to be even more robust.
if ( [myProduct count] == 0 ) {
//if ( clientCallback ) {
// clientCallback( IAP_FAILURE );
//}
return;
}
// We can use the same number formatter for all the products.
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
// Get the response and cache it.
for ( SKProduct * product in response.products )
{
// Convert the price to user-interface worthy representation.
[numberFormatter setLocale:product.priceLocale];
NSString *formattedString = [numberFormatter stringFromNumber:product.price];
const std::string priceString = [formattedString cStringUsingEncoding:NSUTF8StringEncoding];
// Convert the NSString identifier to a C++ string.
const std::string identifierString = [product.productIdentifier cStringUsingEncoding:NSUTF8StringEncoding];
productInformation_t productInformation( identifierString, priceString );
// Add the C++ product information to the cache.
productCache.insert( std::make_pair( identifierString, productInformation ) );
// Store the fact that we have information in the defaults.
SetProductState( identifierString.c_str(), PRODUCT_HAS_INFORMATION );
if ( callbackObject ) {
callbackObject( identifierString.c_str(), idInAppStore::PRODUCT_STATUS_RECEIVED_INFORMATION );
}
}
[numberFormatter release];
[request autorelease];
}
/*
========================
paymentQueue:updatedTransactions
Called by the system when purchase requests are updated.
========================
*/
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
(void)queue;
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions
{
(void)queue; (void)transactions;
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
(void)queue; (void)error;
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
(void)queue;}
/*
========================
completeTransaction
Called by updatedTransactions when a request is completed.
========================
*/
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
[self finalizeTransaction:transaction];
}
/*
========================
failedTransaction
Called by updatedTransactions when a request fails.
========================
*/
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
if (transaction.error.code != SKErrorPaymentCancelled)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"In-App Purchase error"
message:[transaction.error localizedDescription]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
const char * const cProductIdentifier = [transaction.payment.productIdentifier cStringUsingEncoding:NSUTF8StringEncoding];
// Since we can get failed transactions after the user has already purchased a product,
// don't do anthing if the user has already purchased the product.
if ( GetProductState( cProductIdentifier ) != PRODUCT_PURCHASED ) {
SetProductState( transaction.payment.productIdentifier, PRODUCT_HAS_INFORMATION );
if ( callbackObject ) {
callbackObject( cProductIdentifier, idInAppStore::PRODUCT_STATUS_TRANSACTION_FAILED );
}
}
}
/*
========================
restoreTransaction
Called by updatedTransactions when a request is restored. This can behave identically to
completeTransaction.
========================
*/
- (void)restoreTransaction:(SKPaymentTransaction *)transaction
{
[self finalizeTransaction:transaction.originalTransaction];
}
/*
========================
finalizeTransaction
This method actually delivers the purchased item to the user. Currently, this means setting
the state in NSUserDefaults to PRODUCT_PURCHASED.
========================
*/
- (void)finalizeTransaction:(SKPaymentTransaction *)transaction
{
SetProductState( transaction.payment.productIdentifier, PRODUCT_PURCHASED );
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
const char * const cProductIdentifier = [transaction.payment.productIdentifier cStringUsingEncoding:NSUTF8StringEncoding];
if ( callbackObject ) {
callbackObject( cProductIdentifier, idInAppStore::PRODUCT_STATUS_PURCHASED );
}
}
@end

30
common/idmobilelib/ios/Label.h Executable file
View File

@@ -0,0 +1,30 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
@interface idLabel : UILabel {
}
- (void) SetupLabel: ( NSString * )fontName ;
@end

55
common/idmobilelib/ios/Label.mm Executable file
View File

@@ -0,0 +1,55 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "Label.h"
#include "Localization.h"
@implementation idLabel
/*
========================
awakeFromNib
========================
*/
- (void)awakeFromNib {
[ self SetupLabel:@"idGinza Narrow" ];
}
/*
========================
SetupLabel
========================
*/
- (void) SetupLabel: ( NSString * )fontName {
// Set the Font
CGFloat points = self.font.pointSize;
self.font = [UIFont fontWithName:fontName size:points];
// Localize the text.
NSString * unLocText = self.text;
const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] );
self.text = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ];
}
@end

View File

@@ -0,0 +1,40 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "Label.h"
@interface idLabelButton : UIButton {
UIColor * labelColor;
UIColor * label2Color;
}
@property (nonatomic, retain) IBOutlet idLabel *label;
@property (nonatomic, retain) IBOutlet idLabel *label2;
- (void) Hide;
- (void) Show;
- (void) Enable;
- (void) Disable;
@end

View File

@@ -0,0 +1,202 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "LabelButton.h"
#import "Label.h"
#import "Slider.h"
#import "Switch.h"
#import "Carousel.h"
#import "Localization.h"
@implementation idLabelButton
@synthesize label;
@synthesize label2;
/*
========================
idLabelButton::awakeFromNib
========================
*/
- (void)awakeFromNib {
// Do not optimize my class out
[idLabel class ];
[idSlider class];
[idSwitch class];
[idCarousel class];
CGFloat points = self.titleLabel.font.pointSize;
self.titleLabel.font = [UIFont fontWithName:@"idGinza Narrow" size:points];
// Localize the text.
NSString * unLocText = self.titleLabel.text;
if( unLocText ) {
const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] );
NSString * localizedString = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ];
[self setTitle: localizedString forState:UIControlStateNormal];
[self setTitle: localizedString forState:UIControlStateHighlighted];
}
if( self.label2 )
label2Color = self.label2.textColor;
if( self.label ) {
labelColor = self.label.textColor;
}
}
/*
========================
idLabelButton::setHighlighted
========================
*/
- (void)setHighlighted:(BOOL)highlight {
if( highlight ) {
if( self.label )
self.label.textColor = self.label.highlightedTextColor;
if( self.label2 )
self.label2.textColor = self.label2.highlightedTextColor;
} else if( self.enabled ) {
if( self.label )
self.label.textColor = labelColor;
if( self.label2 )
self.label2.textColor = label2Color;
}
[super setHighlighted:highlight];
// Localize the text.
NSString * unLocText = self.titleLabel.text;
if( unLocText ) {
const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] );
self.titleLabel.text = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ];
}
}
/*
========================
idLabelButton::setEnabled
========================
*/
- (void)setEnabled:(BOOL)enabled {
if( !enabled ) {
if( self.label )
self.label.textColor = self.label.highlightedTextColor;
if( self.label2 )
self.label2.textColor = self.label2.highlightedTextColor;
} else {
if( self.label )
self.label.textColor = labelColor;
if( self.label2 )
self.label2.textColor = label2Color;
}
[super setEnabled:enabled];
// Localize the text.
NSString * unLocText = self.titleLabel.text;
if( unLocText ) {
const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] );
self.titleLabel.text = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ];
}
}
/*
========================
idLabelButton::Enable
========================
*/
- (void) Enable {
self.enabled = YES;
if( self.label )
label.enabled = YES;
if( self.label2 )
label2.enabled = YES;
}
/*
========================
idLabelButton::Disable
========================
*/
- (void) Disable {
self.enabled = NO;
if( self.label )
label.enabled = NO;
if( self.label2 )
label2.enabled = NO;
}
/*
========================
idLabelButton::Hide
========================
*/
- (void) Hide {
[UIView beginAnimations:@"Hide" context:nil];
[UIView setAnimationDuration:1.0f];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(Disable)];
self.alpha = 0.0f;
if( self.label )
label.alpha = 0.0f;
if( self.label2 )
label2.alpha = 0.0f;
[UIView commitAnimations];
}
/*
========================
idLabelButton::Show
========================
*/
- (void) Show {
[UIView beginAnimations:@"Show" context:nil];
[UIView setAnimationDuration:1.0f];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(Enable)];
self.alpha = 1.0f;
if( self.label )
label.alpha = 1.0f;
if( self.label2 )
label2.alpha = 1.0f;
[UIView commitAnimations];
}
- (void) dealloc {
label = nil;
label2 = nil;
[super dealloc];
}
@end

View File

@@ -0,0 +1,83 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
================================================================================================
A game-generic C++ wrapper around the iOS Localizable Strings functionality.
Basics of Localaization on Apple platforms:
Each Localization language has a bundle associated with it ( *.lproj ).
We gather the bundle for the current ( or needed ) language.
[[NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ];
You MUST add a Localizable.strings file ( named exactly that ) to the project.
Apple provides a system for getting strings from the localizable.strings file.
NSString* nsString = [ bundle localizedStringForKey:key value:nil table:nil ];
The Localizable.strings file must be formatted like:
"KEY" = "VALUE";
and end with a semi-coln.
Apple Developer Reference:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html
We wrapper this up into 4 easy functions.
"Localization_Initialize" Must be called to create/set the current language bundle for the system.
"Localization_SetLanguage" Can be called at dynamically to set the language.
"Localization_GetString" Gets a string value from a key'd pair
SUPPORTED LANGUAGES:
ENGLISH,
FRENCH,
ITALIAN,
GERMAN,
SPANISH
================================================================================================
*/
#ifndef IDMOBILELIB_LOCALIZATION_H
#define IDMOBILELIB_LOCALIZATION_H
#ifdef __cplusplus
extern "C" {
#endif
enum ID_LANGUAGE {
LANGUAGE_ENGLISH = 0,
LANGUAGE_FRENCH,
LANGUAGE_ITALIAN,
LANGUAGE_GERMAN,
LANGUAGE_SPANISH
};
void idLocalization_Initialize();
void idLocalization_SetLanguage( enum ID_LANGUAGE language );
enum ID_LANGUAGE idLocalization_GetLanguage();
const char * idLocalization_GetString( const char * key );
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,134 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Localization.h"
#include "LocalizationObjectiveC.h"
#import <Foundation/Foundation.h>
static NSBundle* mCurrentBundle = NULL;
static ID_LANGUAGE mCurrentLanguage;
static const char* mCurrentLanguageStr;
/*
========================
idLocalization::SetLanguage
Sets the language of the system with an enumeration passed in.
========================
*/
void idLocalization_SetLanguage( ID_LANGUAGE language ) {
NSString* langPath = nil;
switch( language ) {
case LANGUAGE_ENGLISH:
langPath = [[NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ];
break;
case LANGUAGE_FRENCH:
langPath = [[NSBundle mainBundle ] pathForResource:@"fr" ofType:@"lproj" ];
break;
case LANGUAGE_ITALIAN:
langPath = [[NSBundle mainBundle ] pathForResource:@"it" ofType:@"lproj" ];
break;
case LANGUAGE_GERMAN:
langPath = [[NSBundle mainBundle ] pathForResource:@"de" ofType:@"lproj" ];
break;
case LANGUAGE_SPANISH:
langPath = [[NSBundle mainBundle ] pathForResource:@"es" ofType:@"lproj" ];
break;
default:
langPath = [[NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ];
break;
}
mCurrentBundle = [[NSBundle bundleWithPath:langPath] retain ];
}
/*
========================
idLocalization::GetLanguage
Gets the current system's language
========================
*/
ID_LANGUAGE idLocalization_GetLanguage() {
return mCurrentLanguage;
}
/*
========================
idLocalization::Initialize
Gathers the local device's language, and sets that as the systems language.
========================
*/
void idLocalization_Initialize() {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defaults objectForKey:@"AppleLanguages"];
NSString* current = [[languages objectAtIndex:0] retain ];
mCurrentLanguageStr = [current UTF8String];
if([current isEqualToString:@"en"]){
mCurrentLanguage = LANGUAGE_ENGLISH;
} else if([current isEqualToString:@"fr"]){
mCurrentLanguage = LANGUAGE_FRENCH;
} else if([current isEqualToString:@"it"]){
mCurrentLanguage = LANGUAGE_ENGLISH;
} else if([current isEqualToString:@"sp"] || [current isEqualToString:@"es"]){
mCurrentLanguage = LANGUAGE_SPANISH;
} else if([current isEqualToString:@"ge"] || [current isEqualToString:@"de"]){
mCurrentLanguage = LANGUAGE_GERMAN;
} else {
mCurrentLanguage = LANGUAGE_ENGLISH;
}
idLocalization_SetLanguage( mCurrentLanguage );
}
/*
========================
idLocalization::GetString
Gets a String value from the pair key passed in from Localizable.strings file.
========================
*/
const char * idLocalization_GetString( const char * key ) {
NSString* nsKey = [NSString stringWithUTF8String:key];
NSString* nsString = [mCurrentBundle localizedStringForKey:nsKey value:nil table:nil];
const char* cString = nil;
if( nsString != nil ) {
cString = [nsString cStringUsingEncoding:NSWindowsCP1252StringEncoding];
} else {
cString = key;
}
return cString;
}
/*
========================
idLocalization::GetString
Gets a String value from the pair key passed in from Localizable.strings file.
========================
*/
NSString * idLocalization_GetNSString( NSString * key ) {
return [mCurrentBundle localizedStringForKey:key value:nil table:nil];
}

View File

@@ -0,0 +1,39 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef idmobilelib_LocalizationObjectiveC_h
#define idmobilelib_LocalizationObjectiveC_h
@class NSString;
#ifdef __cplusplus
extern "C" {
#endif
// If we already have an NSString localization key, we can use this function and avoid the
// overhead of the const char * <-> NSString * conversions.
NSString * idLocalization_GetNSString( NSString * key );
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,70 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef IDMOBILELIB_RENDER_CONTEXT_H
#define IDMOBILELIB_RENDER_CONTEXT_H
#if defined(__OBJC__) && defined(__cplusplus)
#import <QuartzCore/QuartzCore.h>
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/EAGLDrawable.h>
class idRenderContext {
public:
idRenderContext();
virtual ~idRenderContext();
void Initialize( EAGLRenderingAPI apiVersion, EAGLSharegroup * sharegroup );
void InitFrameBuffer( CAEAGLLayer * layer );
void Begin();
void End();
void SetActiveContext();
void SwapBuffers();
void SetContextWidth( int width );
void SetContextHeight( int height );
int GetContextWidth() const { return mWidth; }
int GetContextHeight() const { return mHeight; }
EAGLSharegroup * GetShareGroup() { return [mEAGLContext sharegroup]; }
protected:
GLuint mViewRenderbuffer;
GLuint mViewFramebuffer;
GLuint mDepthRenderbuffer;
EAGLContext *mEAGLContext;
int mWidth;
int mHeight;
};
#endif
#endif // _RENDER_CONTEXT_H

View File

@@ -0,0 +1,174 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "RenderContext.h"
/*
=========================================
idRenderContext::idRenderContext
=========================================
*/
idRenderContext::idRenderContext() :
mViewRenderbuffer( 0 ),
mViewFramebuffer( 0 ),
mDepthRenderbuffer( 0 ),
mEAGLContext( NULL ) {
mWidth = 0;
mHeight = 0;
}
/*
=========================================
idRenderContext::Initialize
=========================================
*/
void idRenderContext::Initialize( EAGLRenderingAPI apiVersion, EAGLSharegroup * sharegroup ) {
// Allocate and initialize the Rendering context for this view.
if( sharegroup == NULL ) {
mEAGLContext = [[EAGLContext alloc] initWithAPI:apiVersion];
} else {
mEAGLContext = [[EAGLContext alloc] initWithAPI:apiVersion sharegroup: sharegroup];
}
assert( mEAGLContext );
assert( [mEAGLContext API] == apiVersion );
SetActiveContext();
}
/*
=========================================
idRenderContext::~idRenderContext
=========================================
*/
idRenderContext::~idRenderContext() {
glDeleteFramebuffersOES( 1, &mViewFramebuffer );
mViewFramebuffer = 0;
glDeleteRenderbuffersOES( 1, &mViewRenderbuffer );
mViewRenderbuffer = 0;
glDeleteRenderbuffersOES( 1, &mDepthRenderbuffer );
mDepthRenderbuffer = 0;
[ mEAGLContext release ];
}
/*
=========================================
idRenderContext::SetActiveContext
=========================================
*/
void idRenderContext::SetActiveContext() {
if ( ![EAGLContext setCurrentContext:mEAGLContext]) {
assert( 0 );
return;
}
}
/*
=========================================
idRenderContext::SwapBuffers
=========================================
*/
void idRenderContext::SwapBuffers() {
glBindRenderbufferOES(GL_RENDERBUFFER_OES, mViewRenderbuffer);
// present the renderbuffer for display
[mEAGLContext presentRenderbuffer:GL_RENDERBUFFER_OES];
}
/*
=========================================
idRenderContext::RenderBufferStorage
=========================================
*/
void idRenderContext::InitFrameBuffer( CAEAGLLayer * layer ) {
glDeleteFramebuffersOES( 1, &mViewFramebuffer );
mViewFramebuffer = 0;
glDeleteRenderbuffersOES( 1, &mViewRenderbuffer );
mViewRenderbuffer = 0;
glDeleteRenderbuffersOES( 1, &mDepthRenderbuffer );
mDepthRenderbuffer = 0;
glGenFramebuffersOES(1, &mViewFramebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, mViewFramebuffer);
glGenRenderbuffersOES(1, &mViewRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, mViewRenderbuffer);
[mEAGLContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
// the backing sizes should be the same as the screen
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &mWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &mHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, mViewRenderbuffer);
glGenRenderbuffersOES(1, &mDepthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, mDepthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, mWidth, mHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, mDepthRenderbuffer);
// the framebuffer will stay constant
glBindRenderbufferOES(GL_RENDERBUFFER_OES, mViewRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, mViewFramebuffer);
if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) != GL_FRAMEBUFFER_COMPLETE_OES ) {
assert( 0 );
}
}
/*
=========================================
idRenderContext::Begin
=========================================
*/
void idRenderContext::Begin() {
SetActiveContext();
// Clear the Buffer to begin for a new Frame.
//GL_Clear( true, true, false );
// Set the Viewport for our Context.
// GL_Viewport( 0, 0, mWidth, mHeight );
}
/*
=========================================
idRenderContext::End
=========================================
*/
void idRenderContext::End() {
SwapBuffers();
}

33
common/idmobilelib/ios/Slider.h Executable file
View File

@@ -0,0 +1,33 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface idSlider : UISlider {
}
- (void) CustomizeSlider:( UIImage* )minimumImage
:( UIImage* )maximumImage
:( UIImage* )thumbImage;
@end

View File

@@ -0,0 +1,52 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "Slider.h"
@implementation idSlider
/*
========================
CustomizeSlider
========================
*/
- (void) CustomizeSlider:( UIImage* )minimumImage
:( UIImage* )maximumImage
:( UIImage* )thumbImage {
minimumImage = nil;
maximumImage = nil;
//[ self setMinimumTrackImage:minimumImage forState:UIControlStateNormal ];
//[ self setMaximumTrackImage:maximumImage forState:UIControlStateNormal ];
[ self setThumbImage:thumbImage forState:UIControlStateNormal ];
[ self setThumbImage:thumbImage forState:UIControlStateHighlighted ];
}
@end

31
common/idmobilelib/ios/Switch.h Executable file
View File

@@ -0,0 +1,31 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface idSwitch : UIButton {
BOOL on;
}
@property(nonatomic,getter=isOn) BOOL on;
@end

View File

@@ -0,0 +1,79 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "Switch.h"
@implementation idSwitch
@synthesize on;
/*
========================
setOn
========================
*/
- (void)setOn:(BOOL)turnOn
{
on = turnOn;
if (on)
{
[ self setHighlighted: YES ];
}
else
{
[ self setHighlighted: NO ];
}
}
/*
========================
touchesBegan
========================
*/
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
[super touchesBegan:touches withEvent:event];
[self setOn: !on ];
}
/*
========================
touchesEnded
========================
*/
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
[super touchesEnded:touches withEvent:event];
if (on)
{
[ self setHighlighted: YES ];
}
else
{
[ self setHighlighted: NO ];
}
}
@end

49
common/idmobilelib/ios/View.h Executable file
View File

@@ -0,0 +1,49 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef IDMOBILELIB_VIEW_H
#define IDMOBILELIB_VIEW_H
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/EAGLDrawable.h>
#include "RenderContext.h"
/*
================================================
idView
Standard Objective C OpenGL UIView Class
================================================
*/
@interface idView : UIView {
@public
idRenderContext mRenderContext;
}
extern idView * gMainView;
- (void) Initialize;
- (void) EndFrame;
@end
#endif

165
common/idmobilelib/ios/View.mm Executable file
View File

@@ -0,0 +1,165 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "View.h"
/*
================================================
idView
Standard Objective C UIView Class
================================================
*/
idView * gMainView; // global openGL View.
@implementation idView
/*
==================================
idView::layerClass
==================================
*/
+ (Class) layerClass
{
return [CAEAGLLayer class];
}
/*
==================================
idView::initWithCoder
==================================
*/
- (id) initWithCoder:(NSCoder *)aCoder{
if ( ( self = [super initWithCoder:aCoder] ) ) {
[self Initialize];
}
return self;
}
/*
==================================
idView::initWithFrame
==================================
*/
- (id) initWithFrame:(CGRect)rect{
if ( ( self = [super initWithFrame:rect] ) ) {
[self Initialize];
}
return self;
}
/*
==================================
idView::handleTouches
==================================
*/
- (void) handleTouches:(UIEvent*)event {
(void)event;
}
/*
==================================
idView::touchesBegan
==================================
*/
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
(void)touches;
[self handleTouches:event];
}
/*
==================================
idView::touchesMoved
==================================
*/
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
(void)touches;
[self handleTouches:event];
}
/*
==================================
idView::touchesEnded
==================================
*/
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
(void)touches;
[self handleTouches:event];
}
/*
==================================
idView::touchesCancelled
==================================
*/
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
(void)touches;
[self handleTouches:event];
}
/*
==================================
idView::Initialize
==================================
*/
- (void) Initialize {
self.multipleTouchEnabled = YES;
gMainView = self;
// Double the resolution on iPhone 4.
[self setContentScaleFactor:[UIScreen mainScreen].scale];
// Get the layer for this view
CAEAGLLayer *glLayer = (CAEAGLLayer *)self.layer;
glLayer.opaque = TRUE;
glLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGB565,
kEAGLDrawablePropertyColorFormat, nil];
// Create Our Render Context.
mRenderContext.Initialize( kEAGLRenderingAPIOpenGLES1, NULL );
// Create our Frame Buffers.
mRenderContext.InitFrameBuffer( glLayer );
}
/*
==================================
idView::EndFrame
==================================
*/
- (void) EndFrame {
mRenderContext.SwapBuffers();
}
@end

View File

@@ -0,0 +1,432 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
3D7D557F14D21FEC00A0F1FF /* ios_interface.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D7D557E14D21FEC00A0F1FF /* ios_interface.h */; };
3D7D558214D2201E00A0F1FF /* ios_interface.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D7D558114D2201E00A0F1FF /* ios_interface.mm */; };
3D80884B14928766002D6CC3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D80884A14928766002D6CC3 /* Foundation.framework */; };
3D80885E149287EB002D6CC3 /* GameCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D80885D149287EB002D6CC3 /* GameCenter.h */; };
3D80886D14928AED002D6CC3 /* GameCenter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D80886C14928AED002D6CC3 /* GameCenter.mm */; };
3D80886F14928C16002D6CC3 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D80886E14928C16002D6CC3 /* GameKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
3D8088721492B362002D6CC3 /* sys_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D8088711492B362002D6CC3 /* sys_defines.h */; };
3D8088741492CA59002D6CC3 /* objectivec_utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D8088731492CA59002D6CC3 /* objectivec_utilities.h */; };
3D8088761492CBCB002D6CC3 /* objectivec_utilities.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D8088751492CBCB002D6CC3 /* objectivec_utilities.mm */; };
3DCB047B1498279D00E986AF /* LocalizationObjectiveC.h in Headers */ = {isa = PBXBuildFile; fileRef = 3DCB04781498279D00E986AF /* LocalizationObjectiveC.h */; };
C8011C8D14C0EB7A007AC5C5 /* InAppStore.h in Headers */ = {isa = PBXBuildFile; fileRef = C8011C8B14C0EB7A007AC5C5 /* InAppStore.h */; };
C8011C8E14C0EB7A007AC5C5 /* InAppStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8011C8C14C0EB7A007AC5C5 /* InAppStore.mm */; };
C8011C9414C0EC70007AC5C5 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8011C9314C0EC70007AC5C5 /* StoreKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
C8012E5F14B61D4900B0E213 /* AnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = C8012E5314B61D4900B0E213 /* AnimatedImage.h */; };
C8012E6014B61D4900B0E213 /* AnimatedImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8012E5414B61D4900B0E213 /* AnimatedImage.mm */; };
C8012E6114B61D4900B0E213 /* Carousel.h in Headers */ = {isa = PBXBuildFile; fileRef = C8012E5514B61D4900B0E213 /* Carousel.h */; };
C8012E6214B61D4900B0E213 /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8012E5614B61D4900B0E213 /* Carousel.mm */; };
C8012E6314B61D4900B0E213 /* Label.h in Headers */ = {isa = PBXBuildFile; fileRef = C8012E5714B61D4900B0E213 /* Label.h */; };
C8012E6414B61D4900B0E213 /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8012E5814B61D4900B0E213 /* Label.mm */; };
C8012E6514B61D4900B0E213 /* LabelButton.h in Headers */ = {isa = PBXBuildFile; fileRef = C8012E5914B61D4900B0E213 /* LabelButton.h */; };
C8012E6614B61D4900B0E213 /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8012E5A14B61D4900B0E213 /* LabelButton.mm */; };
C8012E6714B61D4900B0E213 /* Slider.h in Headers */ = {isa = PBXBuildFile; fileRef = C8012E5B14B61D4900B0E213 /* Slider.h */; };
C8012E6814B61D4900B0E213 /* Slider.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8012E5C14B61D4900B0E213 /* Slider.mm */; };
C8012E6914B61D4900B0E213 /* Switch.h in Headers */ = {isa = PBXBuildFile; fileRef = C8012E5D14B61D4900B0E213 /* Switch.h */; };
C8012E6A14B61D4900B0E213 /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8012E5E14B61D4900B0E213 /* Switch.mm */; };
C8A6294514969EEE002EF3F5 /* Localization.h in Headers */ = {isa = PBXBuildFile; fileRef = C8A6294414969EEE002EF3F5 /* Localization.h */; };
C8A6294814969F07002EF3F5 /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8A6294714969F07002EF3F5 /* Localization.mm */; };
C8A629611497F318002EF3F5 /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8A629601497F318002EF3F5 /* View.mm */; };
C8A629631497F329002EF3F5 /* View.h in Headers */ = {isa = PBXBuildFile; fileRef = C8A629621497F329002EF3F5 /* View.h */; };
C8A629651497F509002EF3F5 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8A629641497F508002EF3F5 /* OpenGLES.framework */; };
C8A629671497F510002EF3F5 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C8A629661497F510002EF3F5 /* QuartzCore.framework */; };
C8A6296914980C5B002EF3F5 /* RenderContext.h in Headers */ = {isa = PBXBuildFile; fileRef = C8A6296814980C5B002EF3F5 /* RenderContext.h */; };
C8A6296B14980C6E002EF3F5 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = C8A6296A14980C6E002EF3F5 /* RenderContext.mm */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
3D7D557E14D21FEC00A0F1FF /* ios_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios_interface.h; sourceTree = "<group>"; };
3D7D558114D2201E00A0F1FF /* ios_interface.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ios_interface.mm; sourceTree = "<group>"; };
3D80884714928766002D6CC3 /* libidmobilelib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libidmobilelib.a; sourceTree = BUILT_PRODUCTS_DIR; };
3D80884A14928766002D6CC3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
3D80885D149287EB002D6CC3 /* GameCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameCenter.h; sourceTree = "<group>"; };
3D80886C14928AED002D6CC3 /* GameCenter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GameCenter.mm; sourceTree = "<group>"; };
3D80886E14928C16002D6CC3 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
3D8088711492B362002D6CC3 /* sys_defines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sys_defines.h; path = ../sys/sys_defines.h; sourceTree = "<group>"; };
3D8088731492CA59002D6CC3 /* objectivec_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = objectivec_utilities.h; sourceTree = "<group>"; };
3D8088751492CBCB002D6CC3 /* objectivec_utilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = objectivec_utilities.mm; sourceTree = "<group>"; };
3DCB04781498279D00E986AF /* LocalizationObjectiveC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalizationObjectiveC.h; sourceTree = "<group>"; };
C8011C8B14C0EB7A007AC5C5 /* InAppStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppStore.h; sourceTree = "<group>"; };
C8011C8C14C0EB7A007AC5C5 /* InAppStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InAppStore.mm; sourceTree = "<group>"; };
C8011C9314C0EC70007AC5C5 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
C8012E5314B61D4900B0E213 /* AnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimatedImage.h; sourceTree = "<group>"; };
C8012E5414B61D4900B0E213 /* AnimatedImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AnimatedImage.mm; sourceTree = "<group>"; };
C8012E5514B61D4900B0E213 /* Carousel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Carousel.h; sourceTree = "<group>"; };
C8012E5614B61D4900B0E213 /* Carousel.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Carousel.mm; sourceTree = "<group>"; };
C8012E5714B61D4900B0E213 /* Label.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Label.h; sourceTree = "<group>"; };
C8012E5814B61D4900B0E213 /* Label.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Label.mm; sourceTree = "<group>"; };
C8012E5914B61D4900B0E213 /* LabelButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelButton.h; sourceTree = "<group>"; };
C8012E5A14B61D4900B0E213 /* LabelButton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LabelButton.mm; sourceTree = "<group>"; };
C8012E5B14B61D4900B0E213 /* Slider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Slider.h; sourceTree = "<group>"; };
C8012E5C14B61D4900B0E213 /* Slider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Slider.mm; sourceTree = "<group>"; };
C8012E5D14B61D4900B0E213 /* Switch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Switch.h; sourceTree = "<group>"; };
C8012E5E14B61D4900B0E213 /* Switch.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Switch.mm; sourceTree = "<group>"; };
C8A6294414969EEE002EF3F5 /* Localization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Localization.h; sourceTree = "<group>"; };
C8A6294714969F07002EF3F5 /* Localization.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Localization.mm; sourceTree = "<group>"; };
C8A629601497F318002EF3F5 /* View.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = View.mm; sourceTree = "<group>"; };
C8A629621497F329002EF3F5 /* View.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = View.h; sourceTree = "<group>"; };
C8A629641497F508002EF3F5 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
C8A629661497F510002EF3F5 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
C8A6296814980C5B002EF3F5 /* RenderContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderContext.h; sourceTree = "<group>"; };
C8A6296A14980C6E002EF3F5 /* RenderContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RenderContext.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
3D80884414928766002D6CC3 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C8011C9414C0EC70007AC5C5 /* StoreKit.framework in Frameworks */,
C8A629671497F510002EF3F5 /* QuartzCore.framework in Frameworks */,
C8A629651497F509002EF3F5 /* OpenGLES.framework in Frameworks */,
3D80886F14928C16002D6CC3 /* GameKit.framework in Frameworks */,
3D80884B14928766002D6CC3 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3D80883C14928766002D6CC3 = {
isa = PBXGroup;
children = (
3D80885714928798002D6CC3 /* idmobilelib */,
3D80884914928766002D6CC3 /* Frameworks */,
3D80884814928766002D6CC3 /* Products */,
);
sourceTree = "<group>";
};
3D80884814928766002D6CC3 /* Products */ = {
isa = PBXGroup;
children = (
3D80884714928766002D6CC3 /* libidmobilelib.a */,
);
name = Products;
sourceTree = "<group>";
};
3D80884914928766002D6CC3 /* Frameworks */ = {
isa = PBXGroup;
children = (
C8011C9314C0EC70007AC5C5 /* StoreKit.framework */,
C8A629661497F510002EF3F5 /* QuartzCore.framework */,
C8A629641497F508002EF3F5 /* OpenGLES.framework */,
3D80884A14928766002D6CC3 /* Foundation.framework */,
3D80886E14928C16002D6CC3 /* GameKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
3D80885714928798002D6CC3 /* idmobilelib */ = {
isa = PBXGroup;
children = (
3D808858149287A1002D6CC3 /* ios */,
3D8088701492B34E002D6CC3 /* sys */,
);
name = idmobilelib;
sourceTree = "<group>";
};
3D808858149287A1002D6CC3 /* ios */ = {
isa = PBXGroup;
children = (
C8A6295E1497F2A6002EF3F5 /* Interface Builder */,
3D80885D149287EB002D6CC3 /* GameCenter.h */,
3D80886C14928AED002D6CC3 /* GameCenter.mm */,
3D8088731492CA59002D6CC3 /* objectivec_utilities.h */,
3D8088751492CBCB002D6CC3 /* objectivec_utilities.mm */,
C8A6294414969EEE002EF3F5 /* Localization.h */,
C8A6294714969F07002EF3F5 /* Localization.mm */,
3DCB04781498279D00E986AF /* LocalizationObjectiveC.h */,
C8A6296814980C5B002EF3F5 /* RenderContext.h */,
C8A6296A14980C6E002EF3F5 /* RenderContext.mm */,
C8011C8B14C0EB7A007AC5C5 /* InAppStore.h */,
C8011C8C14C0EB7A007AC5C5 /* InAppStore.mm */,
3D7D557E14D21FEC00A0F1FF /* ios_interface.h */,
3D7D558114D2201E00A0F1FF /* ios_interface.mm */,
);
name = ios;
sourceTree = "<group>";
};
3D8088701492B34E002D6CC3 /* sys */ = {
isa = PBXGroup;
children = (
3D8088711492B362002D6CC3 /* sys_defines.h */,
);
name = sys;
sourceTree = "<group>";
};
C8A6295E1497F2A6002EF3F5 /* Interface Builder */ = {
isa = PBXGroup;
children = (
C8012E5314B61D4900B0E213 /* AnimatedImage.h */,
C8012E5414B61D4900B0E213 /* AnimatedImage.mm */,
C8012E5514B61D4900B0E213 /* Carousel.h */,
C8012E5614B61D4900B0E213 /* Carousel.mm */,
C8012E5714B61D4900B0E213 /* Label.h */,
C8012E5814B61D4900B0E213 /* Label.mm */,
C8012E5914B61D4900B0E213 /* LabelButton.h */,
C8012E5A14B61D4900B0E213 /* LabelButton.mm */,
C8012E5B14B61D4900B0E213 /* Slider.h */,
C8012E5C14B61D4900B0E213 /* Slider.mm */,
C8012E5D14B61D4900B0E213 /* Switch.h */,
C8012E5E14B61D4900B0E213 /* Switch.mm */,
C8A629621497F329002EF3F5 /* View.h */,
C8A629601497F318002EF3F5 /* View.mm */,
);
name = "Interface Builder";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
3D80884514928766002D6CC3 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3D80885E149287EB002D6CC3 /* GameCenter.h in Headers */,
3D8088721492B362002D6CC3 /* sys_defines.h in Headers */,
3D8088741492CA59002D6CC3 /* objectivec_utilities.h in Headers */,
C8A6294514969EEE002EF3F5 /* Localization.h in Headers */,
C8A629631497F329002EF3F5 /* View.h in Headers */,
C8A6296914980C5B002EF3F5 /* RenderContext.h in Headers */,
3DCB047B1498279D00E986AF /* LocalizationObjectiveC.h in Headers */,
C8012E5F14B61D4900B0E213 /* AnimatedImage.h in Headers */,
C8012E6114B61D4900B0E213 /* Carousel.h in Headers */,
C8012E6314B61D4900B0E213 /* Label.h in Headers */,
C8012E6514B61D4900B0E213 /* LabelButton.h in Headers */,
C8012E6714B61D4900B0E213 /* Slider.h in Headers */,
C8012E6914B61D4900B0E213 /* Switch.h in Headers */,
C8011C8D14C0EB7A007AC5C5 /* InAppStore.h in Headers */,
3D7D557F14D21FEC00A0F1FF /* ios_interface.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
3D80884614928766002D6CC3 /* idmobilelib */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3D80885414928766002D6CC3 /* Build configuration list for PBXNativeTarget "idmobilelib" */;
buildPhases = (
3D80884314928766002D6CC3 /* Sources */,
3D80884414928766002D6CC3 /* Frameworks */,
3D80884514928766002D6CC3 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = idmobilelib;
productName = idmobilelib;
productReference = 3D80884714928766002D6CC3 /* libidmobilelib.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
3D80883E14928766002D6CC3 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
};
buildConfigurationList = 3D80884114928766002D6CC3 /* Build configuration list for PBXProject "idmobilelib" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 3D80883C14928766002D6CC3;
productRefGroup = 3D80884814928766002D6CC3 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
3D80884614928766002D6CC3 /* idmobilelib */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
3D80884314928766002D6CC3 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3D80886D14928AED002D6CC3 /* GameCenter.mm in Sources */,
3D8088761492CBCB002D6CC3 /* objectivec_utilities.mm in Sources */,
C8A6294814969F07002EF3F5 /* Localization.mm in Sources */,
C8A629611497F318002EF3F5 /* View.mm in Sources */,
C8A6296B14980C6E002EF3F5 /* RenderContext.mm in Sources */,
C8012E6014B61D4900B0E213 /* AnimatedImage.mm in Sources */,
C8012E6214B61D4900B0E213 /* Carousel.mm in Sources */,
C8012E6414B61D4900B0E213 /* Label.mm in Sources */,
C8012E6614B61D4900B0E213 /* LabelButton.mm in Sources */,
C8012E6814B61D4900B0E213 /* Slider.mm in Sources */,
C8012E6A14B61D4900B0E213 /* Switch.mm in Sources */,
C8011C8E14C0EB7A007AC5C5 /* InAppStore.mm in Sources */,
3D7D558214D2201E00A0F1FF /* ios_interface.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
3D80885214928766002D6CC3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_OBJCPP_ARC_ABI = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_THUMB_SUPPORT = NO;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = "";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
GCC_WARN_PEDANTIC = YES;
GCC_WARN_PROTOTYPE_CONVERSION = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 3.2;
ONLY_ACTIVE_ARCH = NO;
SDKROOT = iphoneos;
USER_HEADER_SEARCH_PATHS = ../;
WARNING_CFLAGS = (
"-Wall",
"-Wextra",
"-pedantic-errors",
);
};
name = Debug;
};
3D80885314928766002D6CC3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_OBJCPP_ARC_ABI = YES;
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
GCC_THUMB_SUPPORT = NO;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = "";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
GCC_WARN_PEDANTIC = YES;
GCC_WARN_PROTOTYPE_CONVERSION = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 3.2;
SDKROOT = iphoneos;
USER_HEADER_SEARCH_PATHS = ../;
VALIDATE_PRODUCT = YES;
WARNING_CFLAGS = (
"-Wall",
"-Wextra",
"-pedantic-errors",
);
};
name = Release;
};
3D80885514928766002D6CC3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DSTROOT = /tmp/idmobilelib.dst;
GCC_VERSION = "";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USE_HEADERMAP = NO;
};
name = Debug;
};
3D80885614928766002D6CC3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DSTROOT = /tmp/idmobilelib.dst;
GCC_VERSION = "";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USE_HEADERMAP = NO;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3D80884114928766002D6CC3 /* Build configuration list for PBXProject "idmobilelib" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3D80885214928766002D6CC3 /* Debug */,
3D80885314928766002D6CC3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3D80885414928766002D6CC3 /* Build configuration list for PBXNativeTarget "idmobilelib" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3D80885514928766002D6CC3 /* Debug */,
3D80885614928766002D6CC3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 3D80883E14928766002D6CC3 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:idmobilelib.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3D80884614928766002D6CC3"
BuildableName = "libidmobilelib.a"
BlueprintName = "idmobilelib"
ReferencedContainer = "container:idmobilelib.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>3D80884614928766002D6CC3</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>idmobilelib.xcscheme_^#shared#^_</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>3</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>3D80884614928766002D6CC3</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,28 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef idmobilelib_ios_interface_h
#define idmobilelib_ios_interface_h
#include <string>
void ShowSystemAlert( const std::string & title, const std::string & message ) ;
#endif

View File

@@ -0,0 +1,42 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "ios_interface.h"
#import "objectivec_utilities.h"
#import "LocalizationObjectiveC.h"
#import <UIKit/UIAlertView.h>
/*
=======================
Shows the blue system alert box with localized text.
=======================
*/
void ShowSystemAlert( const std::string & title, const std::string & message ) {
NSString * nsTitle = idLocalization_GetNSString( StdStringToNSString( title ) );
NSString * nsMessage = idLocalization_GetNSString( StdStringToNSString( message ) );
NSString * nsCancelButton = idLocalization_GetNSString( @"#OK" );
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:nsTitle message:nsMessage delegate:nil cancelButtonTitle:nsCancelButton otherButtonTitles:nil];
[alert show];
[alert release];
}

View File

@@ -0,0 +1,47 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
================================================================================================
This header collects miscellaneous utilities that automate certain tasks in
Objective-C programming.
================================================================================================
*/
#ifndef IDMOBILELIB_IOS_OBJECTIVEC_UTILITIES_H
#define IDMOBILELIB_IOS_OBJECTIVEC_UTILITIES_H
#include <string>
@class NSString;
@class NSError;
std::string NSStringToStdString( NSString * toConvert );
NSString * StdStringToNSString( const std::string & toConvert );
void DisplayNSErrorMessage( NSString* title, NSError * error );
#endif

View File

@@ -0,0 +1,67 @@
/*
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "objectivec_utilities.h"
#include "LocalizationObjectiveC.h"
#import <Foundation/NSString.h>
#import <UIKit/UIAlertView.h>
#import <Foundation/NSError.h>
/*
========================
Copies an NSString object to a C++ string encoded in UTF8.
========================
*/
std::string NSStringToStdString( NSString * toConvert ) {
const char * cString = [toConvert cStringUsingEncoding:NSUTF8StringEncoding];
return std::string( cString );
}
/*
========================
Copies a C++ string encoded in UTF8 to an NSString object.
========================
*/
NSString * StdStringToNSString( const std::string & toConvert ) {
return [NSString stringWithCString:toConvert.c_str() encoding:NSUTF8StringEncoding];
}
/*
========================
Disaplys a system alert with information about the given error.
========================
*/
void DisplayNSErrorMessage( NSString * title, NSError * error ) {
NSString *messageString = [error localizedDescription];
NSString *reasonString = [error localizedFailureReason];
if ( reasonString != nil ) {
messageString = [NSString stringWithFormat:@"%@. %@", messageString, reasonString];
} else {
messageString = [NSString stringWithFormat:@"%@", messageString];
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:idLocalization_GetNSString( title )
message:messageString delegate:nil
cancelButtonTitle:idLocalization_GetNSString(@"OK") otherButtonTitles:nil];
[alertView show];
[alertView release];
}