# HG changeset patch # User koda # Date 1277323436 -7200 # Node ID 02875b1145b7f289e779d2a070c29b4041db7cc6 # Parent ccf4854df2940d686f0ecb2fe379add210466ba4 i <3 mercurial diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/CGPointUtils.c --- a/project_files/HedgewarsMobile/Classes/CGPointUtils.c Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/CGPointUtils.c Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,34 @@ +/* + * CGPointUtils.c + * PinchMe + * + * Created by Jeff LaMarche on 8/2/08. + * Copyright 2008 __MyCompanyName__. All rights reserved. + * + */ + +#include "CGPointUtils.h" +#include + + +CGFloat distanceBetweenPoints (CGPoint first, CGPoint second) { + CGFloat deltaX = second.x - first.x; + CGFloat deltaY = second.y - first.y; + return sqrt(deltaX*deltaX + deltaY*deltaY ); +} + +CGFloat angleBetweenPoints(CGPoint first, CGPoint second) { + CGFloat height = second.y - first.y; + CGFloat width = first.x - second.x; + CGFloat rads = atan(height/width); + return radiansToDegrees(rads); +} + +CGFloat angleBetweenLines(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint line2End) { + CGFloat a = line1End.x - line1Start.x; + CGFloat b = line1End.y - line1Start.y; + CGFloat c = line2End.x - line2Start.x; + CGFloat d = line2End.y - line2Start.y; + CGFloat rads = acos(((a*c) + (b*d)) / ((sqrt(a*a + b*b)) * (sqrt(c*c + d*d)))); + return radiansToDegrees(rads); +} diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/CGPointUtils.h --- a/project_files/HedgewarsMobile/Classes/CGPointUtils.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/CGPointUtils.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,17 @@ +/* + * CGPointUtils.h + * PinchMe + * + * Created by Jeff LaMarche on 8/2/08. + * Copyright 2008 __MyCompanyName__. All rights reserved. + * + */ + +#import + +#define degreesToRadian(x) (M_PI * x / 180.0) +#define radiansToDegrees(x) (180.0 * x / M_PI) + +CGFloat distanceBetweenPoints (CGPoint first, CGPoint second); +CGFloat angleBetweenPoints(CGPoint first, CGPoint second); +CGFloat angleBetweenLines(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint lin2End); diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/CommodityFunctions.h --- a/project_files/HedgewarsMobile/Classes/CommodityFunctions.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/CommodityFunctions.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,49 @@ +// +// CommodityFunctions.h +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +#define MAX_HOGS 8 + + +#define SETTINGS_FILE() [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) \ + objectAtIndex:0] stringByAppendingString:@"/settings.plist"] +#define GAMECONFIG_FILE() [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) \ + objectAtIndex:0] stringByAppendingString:@"/gameconfig.plist"] +#define DEBUG_FILE() [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) \ + objectAtIndex:0] stringByAppendingString:@"/debug.txt"] + +#define TEAMS_DIRECTORY() [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) \ + objectAtIndex:0] stringByAppendingString:@"/Teams/"] +#define WEAPONS_DIRECTORY() [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) \ + objectAtIndex:0] stringByAppendingString:@"/Weapons/"] +#define SCHEMES_DIRECTORY() [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) \ + objectAtIndex:0] stringByAppendingString:@"/Schemes/"] + +#define GRAPHICS_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/"] +#define HATS_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Hats/"] +#define GRAVES_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Graves/"] +#define BOTLEVELS_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Hedgehog/botlevels"] +#define BTN_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Btn"] +#define FLAGS_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Graphics/Flags/"] +#define FORTS_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Forts/"] +#define THEMES_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Themes/"] +#define MAPS_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Maps/"] +#define VOICES_DIRECTORY() [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Sounds/voices/"] + +#define MSG_MEMCLEAN() DLog(@"has cleaned up some memory"); print_free_memory() +#define MSG_DIDUNLOAD() DLog(@"did unload"); + +void createTeamNamed (NSString *nameWithoutExt); +void createWeaponNamed (NSString *nameWithoutExt); +void createSchemeNamed (NSString *nameWithoutExt); +BOOL rotationManager (UIInterfaceOrientation interfaceOrientation); +NSInteger randomPort (); +void popError (const char *title, const char *message); +void print_free_memory (); + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/CommodityFunctions.m --- a/project_files/HedgewarsMobile/Classes/CommodityFunctions.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/CommodityFunctions.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,158 @@ +// +// CommodityFunctions.m +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "CommodityFunctions.h" +#import +#import + +void createTeamNamed (NSString *nameWithoutExt) { + NSString *teamsDirectory = TEAMS_DIRECTORY(); + + if (![[NSFileManager defaultManager] fileExistsAtPath: teamsDirectory]) { + [[NSFileManager defaultManager] createDirectoryAtPath:teamsDirectory + withIntermediateDirectories:NO + attributes:nil + error:NULL]; + } + + NSMutableArray *hedgehogs = [[NSMutableArray alloc] initWithCapacity: MAX_HOGS]; + + for (int i = 0; i < MAX_HOGS; i++) { + NSString *hogName = [[NSString alloc] initWithFormat:@"hedgehog %d",i]; + NSDictionary *hog = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt:0],@"level", + hogName,@"hogname", @"NoHat",@"hat", nil]; + [hogName release]; + [hedgehogs addObject:hog]; + [hog release]; + } + + NSDictionary *theTeam = [[NSDictionary alloc] initWithObjectsAndKeys:@"0",@"hash", nameWithoutExt,@"teamname", + @"Statue",@"grave", @"Plane",@"fort", @"Default",@"voicepack", + @"hedgewars",@"flag", hedgehogs,@"hedgehogs", nil]; + [hedgehogs release]; + + NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist", teamsDirectory, nameWithoutExt]; + + [theTeam writeToFile:teamFile atomically:YES]; + [teamFile release]; + [theTeam release]; +} + +void createWeaponNamed (NSString *nameWithoutExt) { + NSString *weaponsDirectory = WEAPONS_DIRECTORY(); + + if (![[NSFileManager defaultManager] fileExistsAtPath: weaponsDirectory]) { + [[NSFileManager defaultManager] createDirectoryAtPath:weaponsDirectory + withIntermediateDirectories:NO + attributes:nil + error:NULL]; + } + + NSDictionary *theWeapon = [[NSDictionary alloc] initWithObjectsAndKeys: + @"9391929422199121032235111001201000000211190911",@"ammostore_initialqt", + @"0405040541600655546554464776576666666155501000",@"ammostore_probability", + @"0000000000000205500000040007004000000000200000",@"ammostore_delay", + @"1311110312111111123114111111111111111211101111",@"ammostore_crate", nil]; + + NSString *weaponFile = [[NSString alloc] initWithFormat:@"%@/%@.plist", weaponsDirectory, nameWithoutExt]; + + [theWeapon writeToFile:weaponFile atomically:YES]; + [weaponFile release]; + [theWeapon release]; +} + +void createSchemeNamed (NSString *nameWithoutExt) { + NSString *schemesDirectory = SCHEMES_DIRECTORY(); + + if (![[NSFileManager defaultManager] fileExistsAtPath: schemesDirectory]) { + [[NSFileManager defaultManager] createDirectoryAtPath:schemesDirectory + withIntermediateDirectories:NO + attributes:nil + error:NULL]; + } + + NSArray *theScheme = [[NSArray alloc] initWithObjects: + [NSNumber numberWithBool:NO], //fortmode + [NSNumber numberWithBool:NO], //divideteam + [NSNumber numberWithBool:NO], //solidland + [NSNumber numberWithBool:NO], //addborder + [NSNumber numberWithBool:NO], //lowgravity + [NSNumber numberWithBool:NO], //lasersight + [NSNumber numberWithBool:NO], //invulnerable + [NSNumber numberWithBool:NO], //addmines + [NSNumber numberWithBool:NO], //vampirism + [NSNumber numberWithBool:NO], //karma + [NSNumber numberWithBool:NO], //artillery + [NSNumber numberWithBool:YES], //randomorder + [NSNumber numberWithBool:NO], //king + [NSNumber numberWithBool:NO], //placehedgehogs + [NSNumber numberWithBool:NO], //clansharesammo + [NSNumber numberWithBool:NO], //disablegirders + [NSNumber numberWithBool:NO], //disablelandobjects + [NSNumber numberWithInt:100], //damagemodifier + [NSNumber numberWithInt:45], //turntime + [NSNumber numberWithInt:100], //initialhealth + [NSNumber numberWithInt:15], //suddendeathtimeout + [NSNumber numberWithInt:5], //cratedrops + [NSNumber numberWithInt:3], //minestime + [NSNumber numberWithInt:4], //mines + [NSNumber numberWithInt:0], //dudmines + [NSNumber numberWithInt:2], //explosives + nil]; + + NSString *schemeFile = [[NSString alloc] initWithFormat:@"%@/%@.plist", schemesDirectory, nameWithoutExt]; + + [theScheme writeToFile:schemeFile atomically:YES]; + [schemeFile release]; + [theScheme release]; +} + +BOOL rotationManager (UIInterfaceOrientation interfaceOrientation) { + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + return YES; + else + return (interfaceOrientation == UIInterfaceOrientationLandscapeRight) || + (interfaceOrientation == UIInterfaceOrientationLandscapeLeft); +} + +NSInteger randomPort () { + srandom(time(NULL)); + return (random() % 64511) + 1024; +} + +void popError (const char *title, const char *message) { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithUTF8String:title] + message:[NSString stringWithUTF8String:message] + delegate:nil + cancelButtonTitle:@"Ok" + otherButtonTitles:nil]; + [alert show]; + [alert release]; +} + +// by http://landonf.bikemonkey.org/code/iphone/Determining_Available_Memory.20081203.html +void print_free_memory () { + mach_port_t host_port; + mach_msg_type_number_t host_size; + vm_size_t pagesize; + + host_port = mach_host_self(); + host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); + host_page_size(host_port, &pagesize); + + vm_statistics_data_t vm_stat; + + if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) + DLog(@"Failed to fetch vm statistics"); + + /* Stats in bytes */ + natural_t mem_used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pagesize; + natural_t mem_free = vm_stat.free_count * pagesize; + natural_t mem_total = mem_used + mem_free; + DLog(@"used: %u free: %u total: %u", mem_used, mem_free, mem_total); +} diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/DetailViewController.h --- a/project_files/HedgewarsMobile/Classes/DetailViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/DetailViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,32 @@ +// +// DetailViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 27/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class GeneralSettingsViewController; +@class TeamSettingsViewController; +@class WeaponSettingsViewController; +@class SchemeSettingsViewController; + +@interface DetailViewController : UITableViewController { + NSArray *controllerNames; + + GeneralSettingsViewController *generalSettingsViewController; + TeamSettingsViewController *teamSettingsViewController; + WeaponSettingsViewController *weaponSettingsViewController; + SchemeSettingsViewController *schemeSettingsViewController; + UIPopoverController *popoverController; +} + +// used in iphone version +-(IBAction) dismissSplitView; + +@property (nonatomic, retain) NSArray *controllerNames; +@property (nonatomic,retain) UIPopoverController *popoverController; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/DetailViewController.m --- a/project_files/HedgewarsMobile/Classes/DetailViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/DetailViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,206 @@ + // +// DetailViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 27/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "DetailViewController.h" +#import "SDL_uikitappdelegate.h" +#import "GeneralSettingsViewController.h" +#import "TeamSettingsViewController.h" +#import "WeaponSettingsViewController.h" +#import "SchemeSettingsViewController.h" +#import "CommodityFunctions.h" + +@implementation DetailViewController +@synthesize controllerNames,popoverController; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{ + self.view.frame = CGRectMake(0, 0, 1024, 1024); +} + +-(void) viewDidLoad { + self.title = NSLocalizedString(@"Settings",@""); + + // allocate controllers and store them into the array + NSArray *array= [[NSArray alloc] initWithObjects:NSLocalizedString(@"General",@""), + NSLocalizedString(@"Teams",@""), + NSLocalizedString(@"Weapons",@""), + NSLocalizedString(@"Schemes",@""), + nil]; + self.controllerNames = array; + [array release]; + + // on ipad make the general setting the first view, on iphone add the "Done" button on top left + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(112, 112, 480, 320)]; + label.text = @"Press the buttons on the left"; + label.font = [UIFont systemFontOfSize:20]; + label.textAlignment = UITextAlignmentCenter; + [self.view addSubview:label]; + [label release]; + + //[self.navigationController pushViewController:nextController animated:NO]; + } else { + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissSplitView)]; + } + + [super viewDidLoad]; +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + // don't display + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + return 0; + else + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [controllerNames count]; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CellIdentifier] autorelease]; + } + + NSInteger row = [indexPath row]; + + cell.textLabel.text = [controllerNames objectAtIndex:row]; + cell.imageView.image = [UIImage imageNamed:@"Icon.png"]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + + return cell; +} + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSInteger row = [indexPath row]; + UIViewController *nextController = nil; + + switch (row) { + case 0: + if (nil == generalSettingsViewController) + generalSettingsViewController = [[GeneralSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = generalSettingsViewController; + break; + case 1: + if (nil == teamSettingsViewController) + teamSettingsViewController = [[TeamSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = teamSettingsViewController; + break; + case 2: + if (nil == weaponSettingsViewController) + weaponSettingsViewController = [[WeaponSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = weaponSettingsViewController; + break; + case 3: + if (nil == schemeSettingsViewController) + schemeSettingsViewController = [[SchemeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = schemeSettingsViewController; + break; + } + + nextController.title = [controllerNames objectAtIndex:row]; + [self.navigationController pushViewController:nextController animated:YES]; +} + +-(IBAction) dismissSplitView { + [[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" object:nil]; +} + +#pragma mark - +#pragma mark splitview support +-(void) splitViewController:(UISplitViewController *)svc popoverController:(UIPopoverController *)pc willPresentViewController:(UIViewController *)aViewController { + if (popoverController != nil) { + [popoverController dismissPopoverAnimated:YES]; + } +} + +// Called when the master view controller is about to be hidden +-(void) splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController + withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc { + + /* barButtonItem.title = @"Master View"; + UIToolbar *toolbar = self.parentViewController.navigationController.toolbar; + NSMutableArray *items = [[toolbar items] mutableCopy]; + [items insertObject:barButtonItem atIndex:0]; + [toolbar setItems:items animated:YES]; + + [items release]; + + self.popoverController = pc;*/ + barButtonItem.title = aViewController.title; + self.navigationItem.rightBarButtonItem = barButtonItem; +} + +// Called when the master view controller is about to appear +-(void) splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController + invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem { + /*UIToolbar *toolbar = self.parentViewController.navigationController.toolbar; + + NSMutableArray *items = [[toolbar items] mutableCopy]; + [items removeObjectAtIndex:0]; + + [toolbar setItems:items animated:YES]; + + [items release]; + + self.popoverController = nil;*/ + self.navigationItem.rightBarButtonItem = nil; + +} + +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Release any cached data, images, etc that aren't in use. + if (generalSettingsViewController.view.superview == nil) + generalSettingsViewController = nil; + if (teamSettingsViewController.view.superview == nil) + teamSettingsViewController = nil; + if (weaponSettingsViewController.view.superview == nil) + weaponSettingsViewController = nil; + if (schemeSettingsViewController.view.superview == nil) + schemeSettingsViewController = nil; + MSG_MEMCLEAN(); +} + +-(void) viewDidUnload { + self.controllerNames = nil; + generalSettingsViewController = nil; + teamSettingsViewController = nil; + weaponSettingsViewController = nil; + schemeSettingsViewController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [controllerNames release]; + [generalSettingsViewController release]; + [teamSettingsViewController release]; + [weaponSettingsViewController release]; + [schemeSettingsViewController release]; + [super dealloc]; +} +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/FlagsViewController.h --- a/project_files/HedgewarsMobile/Classes/FlagsViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/FlagsViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,23 @@ +// +// FlagsViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface FlagsViewController : UITableViewController { + NSDictionary *teamDictionary; + + NSArray *flagArray; + NSIndexPath *lastIndexPath; +} + +@property (nonatomic,retain) NSDictionary * teamDictionary; +@property (nonatomic,retain) NSArray *flagArray; +@property (nonatomic,retain) NSIndexPath *lastIndexPath; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/FlagsViewController.m --- a/project_files/HedgewarsMobile/Classes/FlagsViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/FlagsViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,126 @@ +// +// FlagsViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "FlagsViewController.h" +#import "CommodityFunctions.h" + +@implementation FlagsViewController +@synthesize teamDictionary, flagArray, lastIndexPath; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + self.flagArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:FLAGS_DIRECTORY() error:NULL]; +} + +-(void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.tableView reloadData]; + [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [flagArray count]; +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + NSString *flag = [flagArray objectAtIndex:[indexPath row]]; + + NSString *flagFile = [[NSString alloc] initWithFormat:@"%@/%@", FLAGS_DIRECTORY(), flag]; + UIImage *flagSprite = [[UIImage alloc] initWithContentsOfFile:flagFile]; + [flagFile release]; + cell.imageView.image = flagSprite; + [flagSprite release]; + + cell.textLabel.text = [flag stringByDeletingPathExtension]; + if ([cell.textLabel.text isEqualToString:[self.teamDictionary objectForKey:@"flag"]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath = indexPath; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + // if the two selected rows differ update data on the hog dictionary and reload table content + [self.teamDictionary setValue:[[flagArray objectAtIndex:newRow] stringByDeletingPathExtension] forKey:@"flag"]; + + // tell our boss to write this new stuff on disk + [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; + + UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; + newCell.accessoryType = UITableViewCellAccessoryCheckmark; + UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:lastIndexPath]; + oldCell.accessoryType = UITableViewCellAccessoryNone; + self.lastIndexPath = indexPath; + [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; + [self.navigationController popViewControllerAnimated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +-(void) viewDidUnload { + self.teamDictionary = nil; + self.lastIndexPath = nil; + self.flagArray = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [teamDictionary release]; + [lastIndexPath release]; + [flagArray release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/FortsViewController.h --- a/project_files/HedgewarsMobile/Classes/FortsViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/FortsViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,23 @@ +// +// FortsViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface FortsViewController : UITableViewController { + NSDictionary *teamDictionary; + + NSArray *fortArray; + NSIndexPath *lastIndexPath; +} + +@property (nonatomic,retain) NSDictionary * teamDictionary; +@property (nonatomic,retain) NSArray *fortArray; +//@property (nonatomic,retain) NSArray *fortSprites; +@property (nonatomic,retain) NSIndexPath *lastIndexPath; +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/FortsViewController.m --- a/project_files/HedgewarsMobile/Classes/FortsViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/FortsViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,161 @@ +// +// FortsViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "FortsViewController.h" +#import "CommodityFunctions.h" +#import "UIImageExtra.h" + +@implementation FortsViewController +@synthesize teamDictionary, fortArray, lastIndexPath; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:FORTS_DIRECTORY() error:NULL]; + NSMutableArray *filteredContents = [[NSMutableArray alloc] initWithCapacity:([directoryContents count] / 2)]; + // we need to remove the double entries and the L.png suffix + for (int i = 0; i < [directoryContents count]; i++) { + if (i % 2) { + NSString *currentName = [directoryContents objectAtIndex:i]; + NSString *correctName = [currentName substringToIndex:([currentName length] - 5)]; + [filteredContents addObject:correctName]; + } + } + self.fortArray = filteredContents; + [filteredContents release]; + + /* + // this creates a scaled down version of the image + NSMutableArray *spriteArray = [[NSMutableArray alloc] initWithCapacity:[fortArray count]]; + for (NSString *fortName in fortArray) { + NSString *fortFile = [[NSString alloc] initWithFormat:@"%@/%@L.png", fortsDirectory, fortName]; + UIImage *fortSprite = [[UIImage alloc] initWithContentsOfFile:fortFile]; + [fortFile release]; + [spriteArray addObject:[fortSprite scaleToSize:CGSizeMake(196,196)]]; + [fortSprite release]; + } + self.fortSprites = spriteArray; + [spriteArray release]; + */ + + // statically set row height instead of using delegate method for performance reasons + self.tableView.rowHeight = 200; +} + + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.tableView reloadData]; + [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.fortArray count]; +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle + reuseIdentifier:CellIdentifier] autorelease]; + } + + NSString *fortName = [fortArray objectAtIndex:[indexPath row]]; + cell.textLabel.text = fortName; + + // this creates a scaled down version of the image + // TODO: create preview files, scaling is way too slow! + NSString *fortFile = [[NSString alloc] initWithFormat:@"%@/%@L.png", FORTS_DIRECTORY(), fortName]; + UIImage *fortSprite = [[UIImage alloc] initWithContentsOfFile:fortFile]; + [fortFile release]; + cell.imageView.image = [fortSprite scaleToSize:CGSizeMake(196,196)]; + [fortSprite release]; + + cell.detailTextLabel.text = @"Insert funny description here"; + if ([cell.textLabel.text isEqualToString:[self.teamDictionary objectForKey:@"fort"]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath = indexPath; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + // if the two selected rows differ update data on the hog dictionary and reload table content + [self.teamDictionary setValue:[fortArray objectAtIndex:newRow] forKey:@"fort"]; + + // tell our boss to write this new stuff on disk + [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; + + UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; + newCell.accessoryType = UITableViewCellAccessoryCheckmark; + UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:lastIndexPath]; + oldCell.accessoryType = UITableViewCellAccessoryNone; + self.lastIndexPath = indexPath; + [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; + [self.navigationController popViewControllerAnimated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +-(void) viewDidUnload { + self.teamDictionary = nil; + self.lastIndexPath = nil; + self.fortArray = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + + +- (void)dealloc { + [teamDictionary release]; + [lastIndexPath release]; + [fortArray release]; +// [fortSprites release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GameConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,26 @@ +// +// GameConfigViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 18/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class TeamConfigViewController; +@class MapConfigViewController; +@class SchemeWeaponConfigViewController; + +@interface GameConfigViewController : UIViewController { + UIViewController *activeController; + MapConfigViewController *mapConfigViewController; + TeamConfigViewController *teamConfigViewController; + SchemeWeaponConfigViewController *schemeWeaponConfigViewController; +} + +-(IBAction) buttonPressed:(id) sender; +-(IBAction) segmentPressed:(id) sender; +-(void) startGame:(UIButton *)button; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GameConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,212 @@ + // +// GameConfigViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 18/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "GameConfigViewController.h" +#import "SDL_uikitappdelegate.h" +#import "CommodityFunctions.h" +#import "MapConfigViewController.h" +#import "TeamConfigViewController.h" +#import "SchemeWeaponConfigViewController.h" + +@implementation GameConfigViewController + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +-(IBAction) buttonPressed:(id) sender { + // works even if it's not actually a button + UIButton *theButton = (UIButton *)sender; + switch (theButton.tag) { + case 0: + [[self parentViewController] dismissModalViewControllerAnimated:YES]; + break; + case 1: + theButton.enabled = NO; + [self performSelector:@selector(startGame:) + withObject:theButton + afterDelay:0.25]; + break; + default: + break; + } +} + +-(IBAction) segmentPressed:(id) sender { + UISegmentedControl *theSegment = (UISegmentedControl *)sender; + + switch (theSegment.selectedSegmentIndex) { + case 0: + // this init here is just aestetic as this controller was already set up in viewDidLoad + if (mapConfigViewController == nil) { + mapConfigViewController = [[MapConfigViewController alloc] initWithNibName:@"MapConfigViewController-iPhone" bundle:nil]; + } + activeController = mapConfigViewController; + break; + case 1: + if (teamConfigViewController == nil) { + teamConfigViewController = [[TeamConfigViewController alloc] initWithStyle:UITableViewStyleGrouped]; + // this message is compulsory otherwise the table won't be loaded at all + } + activeController = teamConfigViewController; + break; + case 2: + if (schemeWeaponConfigViewController == nil) { + schemeWeaponConfigViewController = [[SchemeWeaponConfigViewController alloc] initWithStyle:UITableViewStyleGrouped]; + } + activeController = schemeWeaponConfigViewController; + break; + } + + // this message is compulsory otherwise the table won't be loaded at all + [activeController viewWillAppear:NO]; + [self.view addSubview:activeController.view]; +} + +-(void) startGame:(UIButton *)button { + button.enabled = YES; + + // don't start playing if the preview is in progress + if ([mapConfigViewController busy]) { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Wait for the Preview",@"") + message:NSLocalizedString(@"Before playing the preview needs to be generated",@"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Ok, got it",@"") + otherButtonTitles:nil]; + [alert show]; + [alert release]; + return; + } + + // play only if there is more than one team + if ([teamConfigViewController.listOfSelectedTeams count] < 2) { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Too few teams playing",@"") + message:NSLocalizedString(@"You need to select at least two teams to play a game",@"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Ok, got it",@"") + otherButtonTitles:nil]; + [alert show]; + [alert release]; + return; + } + + // play if there's room for enough hogs in the selected map + int hogs = 0; + for (NSDictionary *teamData in teamConfigViewController.listOfSelectedTeams) + hogs += [[teamData objectForKey:@"number"] intValue]; + + if (hogs > mapConfigViewController.maxHogs) { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Too many hogs",@"") + message:NSLocalizedString(@"The map you selected is too small for that many hogs",@"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"Ok, got it",@"") + otherButtonTitles:nil]; + [alert show]; + [alert release]; + return; + } + + // create the configuration file that is going to be sent to engine + NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:mapConfigViewController.seedCommand,@"seed_command", + mapConfigViewController.templateFilterCommand,@"templatefilter_command", + mapConfigViewController.mapGenCommand,@"mapgen_command", + mapConfigViewController.mazeSizeCommand,@"mazesize_command", + mapConfigViewController.themeCommand,@"theme_command", + teamConfigViewController.listOfSelectedTeams,@"teams_list", + schemeWeaponConfigViewController.selectedScheme,@"scheme", + schemeWeaponConfigViewController.selectedWeapon,@"weapon", + nil]; + [dict writeToFile:GAMECONFIG_FILE() atomically:YES]; + [dict release]; + + // finally launch game and remove this controller + [[self parentViewController] dismissModalViewControllerAnimated:YES]; + [[SDLUIKitDelegate sharedAppDelegate] startSDLgame]; +} + +-(void) viewDidLoad { + CGRect screen = [[UIScreen mainScreen] bounds]; + self.view.frame = CGRectMake(0, 0, screen.size.height, screen.size.width); + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + if (mapConfigViewController == nil) + mapConfigViewController = [[MapConfigViewController alloc] initWithNibName:@"MapConfigViewController-iPad" bundle:nil]; + if (teamConfigViewController == nil) + teamConfigViewController = [[TeamConfigViewController alloc] initWithStyle:UITableViewStylePlain]; + teamConfigViewController.view.frame = CGRectMake(0, 224, 300, 500); + teamConfigViewController.view.backgroundColor = [UIColor clearColor]; + [mapConfigViewController.view addSubview:teamConfigViewController.view]; + if (schemeWeaponConfigViewController == nil) + schemeWeaponConfigViewController = [[SchemeWeaponConfigViewController alloc] initWithStyle:UITableViewStyleGrouped]; + schemeWeaponConfigViewController.view.frame = CGRectMake(362, 224, 300, 500); + schemeWeaponConfigViewController.view.backgroundColor = [UIColor clearColor]; + [mapConfigViewController.view addSubview:schemeWeaponConfigViewController.view]; + for (UIView *oneView in self.view.subviews) { + if ([oneView isMemberOfClass:[UIToolbar class]]) { + [[oneView viewWithTag:12345] setHidden:YES]; + break; + } + } + } else + mapConfigViewController = [[MapConfigViewController alloc] initWithNibName:@"MapConfigViewController-iPhone" bundle:nil]; + activeController = mapConfigViewController; + + [self.view addSubview:mapConfigViewController.view]; + + [super viewDidLoad]; +} + +-(void) viewWillAppear:(BOOL)animated { + [mapConfigViewController viewWillAppear:animated]; + [teamConfigViewController viewWillAppear:animated]; + [schemeWeaponConfigViewController viewWillAppear:animated]; + // ADD other controllers here + + [super viewWillAppear:animated]; +} + +-(void) viewDidAppear:(BOOL)animated { + [mapConfigViewController viewDidAppear:animated]; + [teamConfigViewController viewDidAppear:animated]; + [schemeWeaponConfigViewController viewDidAppear:animated]; + [super viewDidAppear:animated]; +} + +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Release any cached data, images, etc that aren't in use. + if (mapConfigViewController.view.superview == nil) + mapConfigViewController = nil; + if (teamConfigViewController.view.superview == nil) + teamConfigViewController = nil; + if (schemeWeaponConfigViewController.view.superview == nil) + schemeWeaponConfigViewController = nil; + activeController = nil; + MSG_MEMCLEAN(); +} + +-(void) viewDidUnload { + activeController = nil; + mapConfigViewController = nil; + teamConfigViewController = nil; + schemeWeaponConfigViewController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [activeController release]; + [mapConfigViewController release]; + [teamConfigViewController release]; + [schemeWeaponConfigViewController release]; + [super dealloc]; +} + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GameSetup.h --- a/project_files/HedgewarsMobile/Classes/GameSetup.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GameSetup.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,32 @@ +// +// gameSetup.h +// hwengine +// +// Created by Vittorio on 10/01/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "SDL_net.h" + +@interface GameSetup : NSObject { + NSDictionary *systemSettings; + NSDictionary *gameConfig; + + NSInteger ipcPort; + TCPsocket sd, csd; // Socket descriptor, Client socket descriptor +} + +@property (nonatomic, retain) NSDictionary *systemSettings; +@property (nonatomic, retain) NSDictionary *gameConfig; + +-(void) engineProtocol; +-(void) startThread:(NSString *)selector; +-(int) sendToEngine:(NSString *)string; +-(void) provideTeamData:(NSString *)teamName forHogs:(NSInteger) numberOfPlayingHogs withHealth:(NSInteger) initialHealth ofColor:(NSNumber *)teamColor; +-(void) provideAmmoData:(NSString *)ammostoreName forPlayingTeams:(NSInteger) numberOfTeams; +-(NSInteger) provideScheme:(NSString *)schemeName; + +-(const char **)getSettings; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GameSetup.m --- a/project_files/HedgewarsMobile/Classes/GameSetup.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GameSetup.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,445 @@ +// +// gameSetup.m +// hwengine +// +// Created by Vittorio on 10/01/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#include +#include + +#import "GameSetup.h" +#import "SDL_uikitappdelegate.h" +#import "SDL_net.h" +#import "PascalImports.h" +#import "CommodityFunctions.h" + +#define BUFFER_SIZE 256 +#define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]); + +@implementation GameSetup + +@synthesize systemSettings, gameConfig; + +-(id) init { + if (self = [super init]) { + ipcPort = randomPort(); + + // should check they exist and throw and exection if not + NSDictionary *dictSett = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE()]; + self.systemSettings = dictSett; + [dictSett release]; + + NSDictionary *dictGame = [[NSDictionary alloc] initWithContentsOfFile:GAMECONFIG_FILE()]; + self.gameConfig = dictGame; + [dictGame release]; + } + return self; +} + +-(NSString *)description { + return [NSString stringWithFormat:@"ipcport: %d\nsockets: %d,%d\n teams: %@\n systemSettings: %@",ipcPort,sd,csd,gameConfig,systemSettings]; +} + +-(void) dealloc { + [gameConfig release]; + [systemSettings release]; + [super dealloc]; +} + +#pragma mark - +#pragma mark Provider functions +// unpacks team data from the selected team.plist to a sequence of engine commands +-(void) provideTeamData:(NSString *)teamName forHogs:(NSInteger) numberOfPlayingHogs withHealth:(NSInteger) initialHealth ofColor:(NSNumber *)teamColor { + /* + addteam <32charsMD5hash> + addhh + is 0 for human, 1-5 for bots (5 is the most stupid) + */ + + NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@", TEAMS_DIRECTORY(), teamName]; + NSDictionary *teamData = [[NSDictionary alloc] initWithContentsOfFile:teamFile]; + [teamFile release]; + + NSString *teamHashColorAndName = [[NSString alloc] initWithFormat:@"eaddteam %@ %@ %@", + [teamData objectForKey:@"hash"], [teamColor stringValue], [teamData objectForKey:@"teamname"]]; + [self sendToEngine: teamHashColorAndName]; + [teamHashColorAndName release]; + + NSString *grave = [[NSString alloc] initWithFormat:@"egrave %@", [teamData objectForKey:@"grave"]]; + [self sendToEngine: grave]; + [grave release]; + + NSString *fort = [[NSString alloc] initWithFormat:@"efort %@", [teamData objectForKey:@"fort"]]; + [self sendToEngine: fort]; + [fort release]; + + NSString *voicepack = [[NSString alloc] initWithFormat:@"evoicepack %@", [teamData objectForKey:@"voicepack"]]; + [self sendToEngine: voicepack]; + [voicepack release]; + + NSString *flag = [[NSString alloc] initWithFormat:@"eflag %@", [teamData objectForKey:@"flag"]]; + [self sendToEngine: flag]; + [flag release]; + + NSArray *hogs = [teamData objectForKey:@"hedgehogs"]; + for (int i = 0; i < numberOfPlayingHogs; i++) { + NSDictionary *hog = [hogs objectAtIndex:i]; + + NSString *hogLevelHealthAndName = [[NSString alloc] initWithFormat:@"eaddhh %@ %d %@", + [hog objectForKey:@"level"], initialHealth, [hog objectForKey:@"hogname"]]; + [self sendToEngine: hogLevelHealthAndName]; + [hogLevelHealthAndName release]; + + NSString *hogHat = [[NSString alloc] initWithFormat:@"ehat %@", [hog objectForKey:@"hat"]]; + [self sendToEngine: hogHat]; + [hogHat release]; + } + + [teamData release]; +} + +// unpacks ammostore data from the selected ammo.plist to a sequence of engine commands +-(void) provideAmmoData:(NSString *)ammostoreName forPlayingTeams:(NSInteger) numberOfTeams { + NSString *weaponPath = [[NSString alloc] initWithFormat:@"%@/%@",WEAPONS_DIRECTORY(),ammostoreName]; + NSDictionary *ammoData = [[NSDictionary alloc] initWithContentsOfFile:weaponPath]; + [weaponPath release]; + + NSString *ammloadt = [[NSString alloc] initWithFormat:@"eammloadt %@", [ammoData objectForKey:@"ammostore_initialqt"]]; + [self sendToEngine: ammloadt]; + [ammloadt release]; + + NSString *ammprob = [[NSString alloc] initWithFormat:@"eammprob %@", [ammoData objectForKey:@"ammostore_probability"]]; + [self sendToEngine: ammprob]; + [ammprob release]; + + NSString *ammdelay = [[NSString alloc] initWithFormat:@"eammdelay %@", [ammoData objectForKey:@"ammostore_delay"]]; + [self sendToEngine: ammdelay]; + [ammdelay release]; + + NSString *ammreinf = [[NSString alloc] initWithFormat:@"eammreinf %@", [ammoData objectForKey:@"ammostore_crate"]]; + [self sendToEngine: ammreinf]; + [ammreinf release]; + + // sent twice so it applies to both teams + NSString *ammstore = [[NSString alloc] initWithString:@"eammstore"]; + for (int i = 0; i < numberOfTeams; i++) + [self sendToEngine: ammstore]; + [ammstore release]; + + [ammoData release]; +} + +// unpacks scheme data from the selected scheme.plist to a sequence of engine commands +-(NSInteger) provideScheme:(NSString *)schemeName { + NSString *schemePath = [[NSString alloc] initWithFormat:@"%@/%@",SCHEMES_DIRECTORY(),schemeName]; + NSArray *scheme = [[NSArray alloc] initWithContentsOfFile:schemePath]; + [schemePath release]; + int result = 0; + int i = 0; + + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x01; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x10; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x04; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x08; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x20; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x40; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x80; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x100; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x200; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x400; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x800; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x2000; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x4000; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x8000; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x10000; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x20000; + if ([[scheme objectAtIndex:i++] boolValue]) + result |= 0x80000; + + NSString *flags = [[NSString alloc] initWithFormat:@"e$gmflags %d",result]; + [self sendToEngine:flags]; + [flags release]; + + NSString *dmgMod = [[NSString alloc] initWithFormat:@"e$damagepct %d",[[scheme objectAtIndex:i++] intValue]]; + [self sendToEngine:dmgMod]; + [dmgMod release]; + + NSString *turnTime = [[NSString alloc] initWithFormat:@"e$turntime %d",[[scheme objectAtIndex:i++] intValue] * 1000]; + [self sendToEngine:turnTime]; + [turnTime release]; + + result = [[scheme objectAtIndex:i++] intValue]; // initial health + + NSString *sdTime = [[NSString alloc] initWithFormat:@"e$sd_turns %d",[[scheme objectAtIndex:i++] intValue]]; + [self sendToEngine:sdTime]; + [sdTime release]; + + NSString *crateDrops = [[NSString alloc] initWithFormat:@"e$casefreq %d",[[scheme objectAtIndex:i++] intValue]]; + [self sendToEngine:crateDrops]; + [crateDrops release]; + + NSString *minesTime = [[NSString alloc] initWithFormat:@"e$minestime %d",[[scheme objectAtIndex:i++] intValue] * 1000]; + [self sendToEngine:minesTime]; + [minesTime release]; + + NSString *minesNumber = [[NSString alloc] initWithFormat:@"e$landadds %d",[[scheme objectAtIndex:i++] intValue]]; + [self sendToEngine:minesNumber]; + [minesNumber release]; + + NSString *dudMines = [[NSString alloc] initWithFormat:@"e$minedudpct %d",[[scheme objectAtIndex:i++] intValue]]; + [self sendToEngine:dudMines]; + [dudMines release]; + + NSString *explosives = [[NSString alloc] initWithFormat:@"e$explosives %d",[[scheme objectAtIndex:i++] intValue]]; + [self sendToEngine:explosives]; + [explosives release]; + + [scheme release]; + return result; +} + +#pragma mark - +#pragma mark Thread/Network relevant code +// select one of GameSetup method and execute it in a seprate thread +-(void) startThread: (NSString *) selector { + SEL usage = NSSelectorFromString(selector); + [NSThread detachNewThreadSelector:usage toTarget:self withObject:nil]; +} + +// wrapper that computes the length of the message and then sends the command string +-(int) sendToEngine: (NSString *)string { + uint8_t length = [string length]; + + SDLNet_TCP_Send(csd, &length , 1); + return SDLNet_TCP_Send(csd, [string UTF8String], length); +} + +// method that handles net setup with engine and keeps connection alive +-(void) engineProtocol { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + IPaddress ip; + int eProto; + BOOL clientQuit, serverQuit; + char buffer[BUFFER_SIZE], string[BUFFER_SIZE]; + uint8_t msgSize; + uint16_t gameTicks; + + serverQuit = NO; + + if (SDLNet_Init() < 0) { + DLog(@"SDLNet_Init: %s", SDLNet_GetError()); + serverQuit = YES; + } + + // Resolving the host using NULL make network interface to listen + if (SDLNet_ResolveHost(&ip, NULL, ipcPort) < 0) { + DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError()); + serverQuit = YES; + } + + // Open a connection with the IP provided (listen on the host's port) + if (!(sd = SDLNet_TCP_Open(&ip))) { + DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), ipcPort); + serverQuit = YES; + } + + DLog(@"Waiting for a client on port %d", ipcPort); + while (!serverQuit) { + // This check the sd if there is a pending connection. + // If there is one, accept that, and open a new socket for communicating + csd = SDLNet_TCP_Accept(sd); + if (NULL != csd) { + // Now we can communicate with the client using csd socket + // sd will remain opened waiting other connections + DLog(@"client found"); + + //first byte of the command alwayas contain the size of the command + SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)); + + SDLNet_TCP_Recv(csd, buffer, msgSize); + gameTicks = SDLNet_Read16 (&buffer[msgSize - 2]); + //DLog(@"engineProtocol - %d: received [%s]", gameTicks, buffer); + + if ('C' == buffer[0]) { + DLog(@"sending game config"); + + // local game + [self sendToEngine:@"TL"]; + + // seed info + [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]]; + + // dimension of the map + [self sendToEngine:[self.gameConfig objectForKey:@"templatefilter_command"]]; + [self sendToEngine:[self.gameConfig objectForKey:@"mapgen_command"]]; + [self sendToEngine:[self.gameConfig objectForKey:@"mazesize_command"]]; + + // theme info + [self sendToEngine:[self.gameConfig objectForKey:@"theme_command"]]; + + // scheme (returns initial health) + NSInteger health = [self provideScheme:[self.gameConfig objectForKey:@"scheme"]]; + + NSArray *teamsConfig = [self.gameConfig objectForKey:@"teams_list"]; + for (NSDictionary *teamData in teamsConfig) { + [self provideTeamData:[teamData objectForKey:@"team"] + forHogs:[[teamData objectForKey:@"number"] intValue] + withHealth:health + ofColor:[teamData objectForKey:@"color"]]; + } + + [self provideAmmoData:@"Default.plist" forPlayingTeams:[teamsConfig count]]; + + clientQuit = NO; + } else { + DLog(@"wrong message or client closed connection"); + clientQuit = YES; + } + + while (!clientQuit){ + msgSize = 0; + memset(buffer, 0, BUFFER_SIZE); + memset(string, 0, BUFFER_SIZE); + if (SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)) <= 0) + clientQuit = YES; + if (SDLNet_TCP_Recv(csd, buffer, msgSize) <=0) + clientQuit = YES; + + gameTicks = SDLNet_Read16(&buffer[msgSize - 2]); + //DLog(@"engineProtocolThread - %d: received [%s]", gameTicks, buffer); + + switch (buffer[0]) { + case '?': + DLog(@"Ping? Pong!"); + [self sendToEngine:@"!"]; + break; + case 'E': + DLog(@"ERROR - last console line: [%s]", buffer); + clientQuit = YES; + break; + case 'e': + sscanf(buffer, "%*s %d", &eProto); + short int netProto = 0; + char *versionStr; + + HW_versionInfo(&netProto, &versionStr); + if (netProto == eProto) { + DLog(@"Setting protocol version %d (%s)", eProto, versionStr); + } else { + DLog(@"ERROR - wrong protocol number: [%s] - expecting %d", buffer, eProto); + clientQuit = YES; + } + + break; + case 'i': + switch (buffer[1]) { + case 'r': + NSLog(@"Winning team: %s", &buffer[2]); + break; + case 'k': + NSLog(@"Best Hedgehog: %s", &buffer[2]); + break; + } + break; + default: + // empty packet or just statistics + break; + // missing case for exiting right away + } + } + DLog(@"Engine exited, closing server"); + // wait a little to let the client close cleanly + [NSThread sleepForTimeInterval:2]; + // Close the client socket + SDLNet_TCP_Close(csd); + serverQuit = YES; + } + } + + SDLNet_TCP_Close(sd); + SDLNet_Quit(); + + [[NSFileManager defaultManager] removeItemAtPath:GAMECONFIG_FILE() error:NULL]; + + [pool release]; + //Invoking this method should be avoided as it does not give your thread a chance to clean up any resources it allocated during its execution. + //[NSThread exit]; +} + +#pragma mark - +#pragma mark Setting methods +// returns an array of c-strings that are read by engine at startup +-(const char **)getSettings { + NSString *ipcString = [[NSString alloc] initWithFormat:@"%d", ipcPort]; + NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt", [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]]; + CGRect screenBounds = [[UIScreen mainScreen] bounds]; + NSString *wSize = [[NSString alloc] initWithFormat:@"%d", (int) screenBounds.size.width]; + NSString *hSize = [[NSString alloc] initWithFormat:@"%d", (int) screenBounds.size.height]; + const char **gameArgs = (const char**) malloc(sizeof(char *) * 9); + + /* + size_t size; + // Set 'oldp' parameter to NULL to get the size of the data returned so we can allocate appropriate amount of space + sysctlbyname("hw.machine", NULL, &size, NULL, 0); + char *name = malloc(size); + // Get the platform name + sysctlbyname("hw.machine", name, &size, NULL, 0); + NSString *machine = [[NSString alloc] initWithUTF8String:name]; + free(name); + + const char **gameArgs = (const char**) malloc(sizeof(char*) * 9); + + // if the machine is less than iphone 3gs or less than ipod touch 3g use reduced graphics (land array) + if ([machine hasPrefix:@"iPhone1"] || ([machine hasPrefix:@"iPod"] && ([machine hasSuffix:@"1,1"] || [machine hasSuffix:@"2,1"]))) + gameArgs[8] = "1"; + else + gameArgs[8] = "0"; + [machine release]; + */ + + // prevents using an empty nickname + NSString *username; + NSString *originalUsername = [self.systemSettings objectForKey:@"username"]; + if ([originalUsername length] == 0) + username = [[NSString alloc] initWithFormat:@"MobileUser-%@",ipcString]; + else + username = [[NSString alloc] initWithString:originalUsername]; + + gameArgs[0] = [username UTF8String]; //UserNick + gameArgs[1] = [ipcString UTF8String]; //ipcPort + gameArgs[2] = [[[self.systemSettings objectForKey:@"sound"] stringValue] UTF8String]; //isSoundEnabled + gameArgs[3] = [[[self.systemSettings objectForKey:@"music"] stringValue] UTF8String]; //isMusicEnabled + gameArgs[4] = [localeString UTF8String]; //cLocaleFName + gameArgs[5] = [[[self.systemSettings objectForKey:@"alternate"] stringValue] UTF8String]; //cAltDamage + gameArgs[6] = [wSize UTF8String]; //cScreenHeight + gameArgs[7] = [hSize UTF8String]; //cScreenWidth + gameArgs[8] = NULL; //recordFileName + + [wSize release]; + [hSize release]; + [localeString release]; + [ipcString release]; + [username release]; + return gameArgs; +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,31 @@ +// +// SettingsViewController.h +// hwengine +// +// Created by Vittorio on 08/01/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface GeneralSettingsViewController : UITableViewController { + NSMutableDictionary *settingsDictionary; + UITextField *textFieldBeingEdited; + UISwitch *musicSwitch; + UISwitch *soundSwitch; + UISwitch *altDamageSwitch; + BOOL isWriteNeeded; +} + +@property (nonatomic, retain) NSMutableDictionary *settingsDictionary; +@property (nonatomic, retain) UITextField *textFieldBeingEdited;; +@property (nonatomic, retain) UISwitch *musicSwitch; +@property (nonatomic, retain) UISwitch *soundSwitch; +@property (nonatomic, retain) UISwitch *altDamageSwitch; + +#define kNetworkFields 0 +#define kAudioFields 1 +#define kOtherFields 2 + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,398 @@ +// +// SettingsViewController.m +// hwengine +// +// Created by Vittorio on 08/01/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "GeneralSettingsViewController.h" +#import "CommodityFunctions.h" + +@implementation GeneralSettingsViewController +@synthesize settingsDictionary, textFieldBeingEdited, musicSwitch, soundSwitch, altDamageSwitch; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark textfield methods +// return to previous table +-(void) cancel:(id) sender { + if (textFieldBeingEdited != nil) + [self.textFieldBeingEdited resignFirstResponder]; +} + +// set the new value +-(BOOL) save:(id) sender { + if (textFieldBeingEdited != nil) { + if (textFieldBeingEdited.tag == 0) { + [self.settingsDictionary setObject:textFieldBeingEdited.text forKey:@"username"]; + } else { + [self.settingsDictionary setObject:textFieldBeingEdited.text forKey:@"password"]; + } + + isWriteNeeded = YES; + [self.textFieldBeingEdited resignFirstResponder]; + return YES; + } + return NO; +} + +// the textfield is being modified, update the navigation controller +-(void) textFieldDidBeginEditing:(UITextField *)aTextField{ + self.textFieldBeingEdited = aTextField; + UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel",@"from the settings table") + style:UIBarButtonItemStylePlain + target:self + action:@selector(cancel:)]; + self.navigationItem.leftBarButtonItem = cancelButton; + [cancelButton release]; + + UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Save",@"from the settings table") + style:UIBarButtonItemStyleDone + target:self + action:@selector(save:)]; + self.navigationItem.rightBarButtonItem = saveButton; + [saveButton release]; +} + +// the textfield has been modified, check for empty strings and restore original navigation bar +-(void) textFieldDidEndEditing:(UITextField *)aTextField{ + self.textFieldBeingEdited = nil; + self.navigationItem.rightBarButtonItem = self.navigationItem.backBarButtonItem; + self.navigationItem.leftBarButtonItem = nil; +} + +// limit the size of the field to 64 characters like in original frontend +-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + int limit = 64; + return !([textField.text length] > limit && [string length] > range.length); +} + + +#pragma mark - +#pragma mark View Lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + self.musicSwitch = [[UISwitch alloc] init]; + self.soundSwitch = [[UISwitch alloc] init]; + self.altDamageSwitch = [[UISwitch alloc] init]; + [self.soundSwitch addTarget:self action:@selector(alsoTurnOffMusic:) forControlEvents:UIControlEventValueChanged]; + [self.musicSwitch addTarget:self action:@selector(dontTurnOnMusic:) forControlEvents:UIControlEventValueChanged]; + [self.altDamageSwitch addTarget:self action:@selector(justUpdateDictionary:) forControlEvents:UIControlEventValueChanged]; + + NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:SETTINGS_FILE()]; + self.settingsDictionary = dictionary; + [dictionary release]; +} + +-(void) viewWillAppear:(BOOL)animated { + [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; + isWriteNeeded = NO; + + musicSwitch.on = [[settingsDictionary objectForKey:@"music"] boolValue]; + soundSwitch.on = [[settingsDictionary objectForKey:@"sound"] boolValue]; + altDamageSwitch.on = [[settingsDictionary objectForKey:@"alternate"] boolValue]; + + [super viewWillAppear:animated]; +} + +-(void) viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + if (isWriteNeeded) { + NSLog(@"writing preferences to file"); + [self.settingsDictionary writeToFile:SETTINGS_FILE() atomically:YES]; + isWriteNeeded = NO; + } +} + +#pragma mark - +// if the sound system is off, turn off also the background music +-(void) alsoTurnOffMusic:(id) sender { + [self.settingsDictionary setObject:[NSNumber numberWithBool:soundSwitch.on] forKey:@"sound"]; + if (YES == self.musicSwitch.on) { + [musicSwitch setOn:NO animated:YES]; + [self.settingsDictionary setObject:[NSNumber numberWithBool:musicSwitch.on] forKey:@"music"]; + } + isWriteNeeded = YES; +} + +// if the sound system is off, don't enable background music +-(void) dontTurnOnMusic:(id) sender { + if (NO == self.soundSwitch.on) { + [musicSwitch setOn:NO animated:YES]; + } else { + [self.settingsDictionary setObject:[NSNumber numberWithBool:musicSwitch.on] forKey:@"music"]; + isWriteNeeded = YES; + } +} + +-(void) justUpdateDictionary:(id) sender { + UISwitch *theSwitch = (UISwitch *)sender; + [self.settingsDictionary setObject:[NSNumber numberWithBool:theSwitch.on] forKey:@"alternate"]; + isWriteNeeded = YES; +} + +/* +#pragma mark - +#pragma mark UIActionSheet Methods +-(IBAction) deleteData: (id)sender { + UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"Are you reeeeeally sure?", @"") + delegate:self + cancelButtonTitle:NSLocalizedString(@"Well, maybe not...", @"") + destructiveButtonTitle:NSLocalizedString(@"As sure as I can be!", @"") + otherButtonTitles:nil]; + [actionSheet showInView:self.view]; + [actionSheet release]; +} + +-(void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger) buttonIndex { + if ([actionSheet cancelButtonIndex] != buttonIndex) { + // get the documents dirctory + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + + // get the content of the directory + NSFileManager *fm = [NSFileManager defaultManager]; + NSArray *dirContent = [fm directoryContentsAtPath:documentsDirectory]; + NSError *error; + + // delete data + for (NSString *fileName in dirContent) { + [fm removeItemAtPath:[documentsDirectory stringByAppendingPathComponent:fileName] error:&error]; + } + + // force resetting + UIAlertView *anAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Hit Home Button to Exit", @"") + message:NSLocalizedString(@"\nEverything is gone!\nNow you need to restart the game...", @"") + delegate:self + cancelButtonTitle:nil + otherButtonTitles:nil]; + [anAlert show]; + [anAlert release]; + } +} +*/ + +#pragma mark - +#pragma mark TableView Methods +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 3; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + switch (section) { + case kNetworkFields: + return 2; + break; + case kAudioFields: + return 2; + break; + case kOtherFields: + return 1; + break; + default: + break; + } + return 0; +} + +-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *cellIdentifier = @"systemSettingsCell"; + NSInteger row = [indexPath row]; + NSInteger section = [indexPath section]; + + UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:cellIdentifier]; + if (nil == cell) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease]; + if (section == kNetworkFields) { + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(-15, 10, 100, 25)]; + label.textAlignment = UITextAlignmentRight; + label.backgroundColor = [UIColor clearColor]; + label.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2]; + if (row == 0) + label.text = NSLocalizedString(@"Nickname","from the settings table"); + else + label.text = NSLocalizedString(@"Password","from the settings table"); + [cell.contentView addSubview:label]; + [label release]; + + UITextField *aTextField = [[UITextField alloc] initWithFrame: + CGRectMake(110, 12, (cell.frame.size.width + cell.frame.size.width/3) - 90, 25)]; + aTextField.clearsOnBeginEditing = NO; + aTextField.returnKeyType = UIReturnKeyDone; + aTextField.adjustsFontSizeToFitWidth = YES; + aTextField.delegate = self; + aTextField.tag = row; + aTextField.clearButtonMode = UITextFieldViewModeWhileEditing; + [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit]; + [cell.contentView addSubview:aTextField]; + [aTextField release]; + } + } + + cell.accessoryType = UITableViewCellAccessoryNone; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.imageView.image = nil; + + UITextField *aTextField; + switch (section) { + case kNetworkFields: + for (UIView *oneView in cell.contentView.subviews) + if ([oneView isMemberOfClass:[UITextField class]]) + aTextField = (UITextField *)oneView; + + switch (row) { + case 0: + aTextField.placeholder = NSLocalizedString(@"Insert your username (if you have one)",@""); + aTextField.text = [self.settingsDictionary objectForKey:@"username"]; + break; + case 1: + aTextField.placeholder = NSLocalizedString(@"Insert your password",@""); + aTextField.text = [self.settingsDictionary objectForKey:@"password"]; + aTextField.secureTextEntry = YES; + break; + default: + break; + } + break; + + case kAudioFields: + switch (row) { + case 0: + cell.textLabel.text = NSLocalizedString(@"Sound", @""); + cell.accessoryView = soundSwitch; + break; + case 1: + cell.textLabel.text = NSLocalizedString(@"Music", @""); + cell.accessoryView = musicSwitch; + break; + default: + break; + } + break; + + case kOtherFields: + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.textLabel.text = NSLocalizedString(@"Alternate Damage", @""); + cell.accessoryView = altDamageSwitch; + break; + default: + break; + } + return cell; +} + +-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + NSString *sectionTitle = nil; + switch (section) { + case kNetworkFields: + sectionTitle = NSLocalizedString(@"Network Configuration", @""); + break; + case kAudioFields: + sectionTitle = NSLocalizedString(@"Audio Preferences", @""); + break; + case kOtherFields: + sectionTitle = NSLocalizedString(@"Other Settings", @""); + break; + default: + NSLog(@"Nope"); + break; + } + return sectionTitle; +} + +/* +-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + UIView *containerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)] autorelease]; + UILabel *headerLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 20, 300, 40)] autorelease]; + headerLabel.textColor = [UIColor lightGrayColor]; + headerLabel.shadowColor = [UIColor blackColor]; + headerLabel.shadowOffset = CGSizeMake(0, 1); + headerLabel.font = [UIFont boldSystemFontOfSize:20]; + headerLabel.backgroundColor = [UIColor clearColor]; + + switch (section) { + case kNetworkFields: + headerLabel.text = NSLocalizedString(@"Network Configuration", @""); + break; + case kAudioFields: + headerLabel.text = NSLocalizedString(@"Audio Preferences", @""); + break; + case kOtherFields: + headerLabel.text = NSLocalizedString(@"Other Settings", @""); + break; + default: + NSLog(@"Warning: unset case value in titleForHeaderInSection!"); + headerLabel.text = @"!"; + break; + } + + [containerView addSubview:headerLabel]; + return containerView; +} + +-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (kAudioFields == [indexPath section] && 2 == [indexPath row]) + return volumeCell.frame.size.height; + else + return table.rowHeight; +} + +-(CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return 57.0; +} +*/ + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell; + if (kNetworkFields == [indexPath section]) { + cell = [aTableView cellForRowAtIndexPath:indexPath]; + for (UIView *oneView in cell.contentView.subviews) { + if ([oneView isMemberOfClass:[UITextField class]]) { + textFieldBeingEdited = (UITextField *)oneView; + [textFieldBeingEdited becomeFirstResponder]; + } + } + [aTableView deselectRowAtIndexPath:indexPath animated:NO]; + } +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +-(void) viewDidUnload { + self.settingsDictionary = nil; + self.textFieldBeingEdited = nil; + self.musicSwitch = nil; + self.soundSwitch = nil; + self.altDamageSwitch = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [settingsDictionary release]; + [textFieldBeingEdited release]; + [musicSwitch release]; + [soundSwitch release]; + [altDamageSwitch release]; + [super dealloc]; +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GravesViewController.h --- a/project_files/HedgewarsMobile/Classes/GravesViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GravesViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,23 @@ +// +// GravesViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface GravesViewController : UITableViewController { + NSMutableDictionary *teamDictionary; + + NSArray *graveArray; + NSIndexPath *lastIndexPath; +} + +@property (nonatomic,retain) NSMutableDictionary *teamDictionary; +@property (nonatomic,retain) NSArray *graveArray; +@property (nonatomic,retain) NSIndexPath *lastIndexPath; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/GravesViewController.m --- a/project_files/HedgewarsMobile/Classes/GravesViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/GravesViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,127 @@ +// +// GravesViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "GravesViewController.h" +#import "CommodityFunctions.h" +#import "UIImageExtra.h" + +@implementation GravesViewController +@synthesize teamDictionary, graveArray, lastIndexPath; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + // load all the grave names and store them into graveArray + self.graveArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:GRAVES_DIRECTORY() error:NULL]; +} + +-(void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.tableView reloadData]; + // this moves the tableview to the top + [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.graveArray count]; +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + + NSString *grave = [self.graveArray objectAtIndex:[indexPath row]]; + cell.textLabel.text = [grave stringByDeletingPathExtension]; + + if ([grave isEqualToString:[self.teamDictionary objectForKey:@"grave"]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath = indexPath; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + + NSString *graveFilePath = [[NSString alloc] initWithFormat:@"%@/%@",GRAVES_DIRECTORY(),grave]; + // because we also have multi frame graves, let's take the first one only + UIImage *graveSprite = [[UIImage alloc] initWithContentsOfFile:graveFilePath andCutAt:CGRectMake(0, 0, 32, 32)]; + [graveFilePath release]; + cell.imageView.image = graveSprite; + [graveSprite release]; + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + [teamDictionary setObject:[[graveArray objectAtIndex:newRow] stringByDeletingPathExtension] forKey:@"grave"]; + + // tell our boss to write this new stuff on disk + [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; + + UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; + newCell.accessoryType = UITableViewCellAccessoryCheckmark; + UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:lastIndexPath]; + oldCell.accessoryType = UITableViewCellAccessoryNone; + self.lastIndexPath = indexPath; + [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; + [self.navigationController popViewControllerAnimated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +- (void)viewDidUnload { + self.lastIndexPath = nil; + self.teamDictionary = nil; + self.graveArray = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +- (void)dealloc { + [graveArray release]; + [teamDictionary release]; + [lastIndexPath release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/HogButtonView.h --- a/project_files/HedgewarsMobile/Classes/HogButtonView.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/HogButtonView.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,25 @@ +// +// HogButtonView.h +// HedgewarsMobile +// +// Created by Vittorio on 20/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface HogButtonView : UIButton { + NSInteger numberOfHogs; + UIImage *singleHog; + NSMutableDictionary *ownerDictionary; +} + +@property (nonatomic,retain) UIImage *singleHog; +@property (nonatomic) NSInteger numberOfHogs; +@property (nonatomic,retain) NSMutableDictionary *ownerDictionary; + +-(void) drawManyHogs:(NSInteger) hogs; +-(void) addOne; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/HogButtonView.m --- a/project_files/HedgewarsMobile/Classes/HogButtonView.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/HogButtonView.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,67 @@ +// +// HogButtonView.m +// HedgewarsMobile +// +// Created by Vittorio on 20/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "HogButtonView.h" +#import "CommodityFunctions.h" +#import "UIImageExtra.h" + +@implementation HogButtonView +@synthesize singleHog, numberOfHogs, ownerDictionary; + +-(id) initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + self.backgroundColor = [UIColor clearColor]; + + NSString *normalHogFile = [[NSString alloc] initWithFormat:@"%@/Hedgehog.png",GRAPHICS_DIRECTORY()]; + UIImage *normalHogSprite = [[UIImage alloc] initWithContentsOfFile:normalHogFile andCutAt:CGRectMake(96, 0, 32, 32)]; + [normalHogFile release]; + + self.singleHog = normalHogSprite; + [normalHogSprite release]; + [self addTarget:self action:@selector(addOne) forControlEvents:UIControlEventTouchUpInside]; + } + return self; +} + +-(void) addOne { + self.highlighted = NO; + NSInteger number = self.numberOfHogs; + number++; + [self drawManyHogs:number]; +} + +-(void) drawManyHogs:(NSInteger) hogs { + if (numberOfHogs != hogs) { + if (hogs <= MAX_HOGS && hogs >= 1) + numberOfHogs = hogs; + else { + if (hogs > MAX_HOGS) + numberOfHogs = 1; + else + numberOfHogs = MAX_HOGS; + } + [ownerDictionary setObject:[NSNumber numberWithInt:numberOfHogs] forKey:@"number"]; + + UIImage *teamHogs = [[[UIImage alloc] init] autorelease]; + for (int i = 0; i < numberOfHogs; i++) { + teamHogs = [singleHog mergeWith:teamHogs + atPoint:CGPointMake(8, 0) + atSize:CGSizeMake(88, 32)]; + } + [self setImage:teamHogs forState:UIControlStateNormal]; + } +} + +-(void) dealloc { + [ownerDictionary release]; + [singleHog release]; + [super dealloc]; +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/HogHatViewController.h --- a/project_files/HedgewarsMobile/Classes/HogHatViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/HogHatViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,27 @@ +// +// HogHatViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface HogHatViewController : UITableViewController { + NSDictionary *teamDictionary; + NSInteger selectedHog; + + NSArray *hatArray; + UIImage *normalHogSprite; + NSIndexPath *lastIndexPath; +} + +@property (nonatomic,retain) NSDictionary *teamDictionary; +@property (nonatomic) NSInteger selectedHog; +@property (nonatomic,retain) NSArray *hatArray; +@property (nonatomic,retain) UIImage *normalHogSprite; +@property (nonatomic,retain) NSIndexPath *lastIndexPath; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/HogHatViewController.m --- a/project_files/HedgewarsMobile/Classes/HogHatViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/HogHatViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,149 @@ +// +// HogHatViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "HogHatViewController.h" +#import "CommodityFunctions.h" +#import "UIImageExtra.h" + +@implementation HogHatViewController +@synthesize teamDictionary, hatArray, normalHogSprite, lastIndexPath, selectedHog; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +- (void)viewDidLoad { + [super viewDidLoad]; + + // load all the hat file names and store them into hatArray + NSString *hatsDirectory = HATS_DIRECTORY(); + NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:hatsDirectory error:NULL]; + self.hatArray = array; + + // load the base hog image, drawing will occure in cellForRow... + NSString *normalHogFile = [[NSString alloc] initWithFormat:@"%@/Hedgehog.png",GRAPHICS_DIRECTORY()]; + UIImage *hogSprite = [[UIImage alloc] initWithContentsOfFile:normalHogFile andCutAt:CGRectMake(96, 0, 32, 32)]; + [normalHogFile release]; + self.normalHogSprite = hogSprite; + [hogSprite release]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + self.title = [[[teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:selectedHog] objectForKey:@"hogname"]; + + // this updates the hog name and its hat + [self.tableView reloadData]; + // this moves the tableview to the top + [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.hatArray count]; +} + +// Customize the appearance of table view cells. +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + + NSDictionary *hog = [[self.teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:selectedHog]; + NSString *hat = [hatArray objectAtIndex:[indexPath row]]; + cell.textLabel.text = [hat stringByDeletingPathExtension]; + + NSString *hatFile = [[NSString alloc] initWithFormat:@"%@/%@", HATS_DIRECTORY(), hat]; + UIImage *hatSprite = [[UIImage alloc] initWithContentsOfFile: hatFile andCutAt:CGRectMake(0, 0, 32, 32)]; + [hatFile release]; + cell.imageView.image = [self.normalHogSprite mergeWith:hatSprite atPoint:CGPointMake(0, -5)]; + [hatSprite release]; + + if ([hat isEqualToString:[hog objectForKey:@"hat"]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath = indexPath; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + // if the two selected rows differ update data on the hog dictionary and reload table content + // TODO: maybe this section could be cleaned up + NSDictionary *oldHog = [[teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:selectedHog]; + + NSMutableDictionary *newHog = [[NSMutableDictionary alloc] initWithDictionary: oldHog]; + [newHog setObject:[[hatArray objectAtIndex:newRow] stringByDeletingPathExtension] forKey:@"hat"]; + [[teamDictionary objectForKey:@"hedgehogs"] replaceObjectAtIndex:selectedHog withObject:newHog]; + [newHog release]; + + // tell our boss to write this new stuff on disk + [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; + + UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; + newCell.accessoryType = UITableViewCellAccessoryCheckmark; + UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:lastIndexPath]; + oldCell.accessoryType = UITableViewCellAccessoryNone; + self.lastIndexPath = indexPath; + [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; + [self.navigationController popViewControllerAnimated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +- (void)viewDidUnload { + self.lastIndexPath = nil; + self.normalHogSprite = nil; + self.teamDictionary = nil; + self.hatArray = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +- (void)dealloc { + [hatArray release]; + [teamDictionary release]; + [normalHogSprite release]; + [lastIndexPath release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/LevelViewController.h --- a/project_files/HedgewarsMobile/Classes/LevelViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/LevelViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,25 @@ +// +// LevelViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface LevelViewController : UITableViewController { + NSDictionary *teamDictionary; + + NSArray *levelArray; + NSArray *levelSprites; + NSIndexPath *lastIndexPath; +} + +@property (nonatomic,retain) NSDictionary *teamDictionary; +@property (nonatomic,retain) NSArray *levelArray; +@property (nonatomic,retain) NSArray *levelSprites; +@property (nonatomic,retain) NSIndexPath *lastIndexPath; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/LevelViewController.m --- a/project_files/HedgewarsMobile/Classes/LevelViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/LevelViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,177 @@ +// +// LevelViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "LevelViewController.h" +#import "CommodityFunctions.h" + + +@implementation LevelViewController +@synthesize teamDictionary, levelArray, levelSprites, lastIndexPath; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +- (void)viewDidLoad { + [super viewDidLoad]; + + NSArray *array = [[NSArray alloc] initWithObjects: + NSLocalizedString(@"Human",@""), + NSLocalizedString(@"Brutal",@""), + NSLocalizedString(@"Aggressive",@""), + NSLocalizedString(@"Bully",@""), + NSLocalizedString(@"Average",@""), + NSLocalizedString(@"Weaky",@""), + nil]; + self.levelArray = array; + [array release]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.tableView reloadData]; + // this moves the tableview to the top + [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; +} + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.levelArray count]; +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + NSInteger row = [indexPath row]; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + cell.textLabel.text = [levelArray objectAtIndex:row]; + NSDictionary *hog = [[self.teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:0]; + if ([[hog objectForKey:@"level"] intValue] == row) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath = indexPath; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + + NSString *botlevelPath = [[NSString alloc] initWithFormat:@"%@/%d.png",BOTLEVELS_DIRECTORY(),row]; + UIImage *levelImage = [[UIImage alloc] initWithContentsOfFile:botlevelPath]; + [botlevelPath release]; + cell.imageView.image = levelImage; + [levelImage release]; + + return cell; +} + + +/* +// Override to support conditional editing of the table view. +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the specified item to be editable. + return YES; +} +*/ + + +/* +// Override to support editing the table view. +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + + if (editingStyle == UITableViewCellEditingStyleDelete) { + // Delete the row from the data source + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; + } + else if (editingStyle == UITableViewCellEditingStyleInsert) { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } +} +*/ + + +/* +// Override to support rearranging the table view. +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { +} +*/ + + +/* +// Override to support conditional rearranging of the table view. +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the item to be re-orderable. + return YES; +} +*/ + + +#pragma mark - +#pragma mark Table view delegate +- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + NSMutableArray *hogs = [teamDictionary objectForKey:@"hedgehogs"]; + + for (NSMutableDictionary *hog in hogs) { + [hog setObject:[NSNumber numberWithInt:newRow] forKey:@"level"]; + } + + // tell our boss to write this new stuff on disk + [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; + [self.tableView reloadData]; + + self.lastIndexPath = indexPath; + [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + [self.navigationController popViewControllerAnimated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +-(void) viewDidUnload { + self.lastIndexPath = nil; + self.teamDictionary = nil; + self.levelArray = nil; + self.levelSprites = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [levelArray release]; + [levelSprites release]; + [teamDictionary release]; + [lastIndexPath release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/MainMenuViewController.h --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,23 @@ +// +// MainMenuViewController.h +// hwengine +// +// Created by Vittorio on 08/01/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class SplitViewRootController; +@class GameConfigViewController; + +@interface MainMenuViewController : UIViewController { + UILabel *versionLabel; + SplitViewRootController *settingsViewController; + GameConfigViewController *gameConfigViewController; +} + +@property (nonatomic,retain) IBOutlet UILabel *versionLabel; + +-(IBAction) switchViews:(id)sender; +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/MainMenuViewController.m --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,171 @@ +// +// MainMenuViewController.m +// hwengine +// +// Created by Vittorio on 08/01/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "MainMenuViewController.h" +#import "SDL_uikitappdelegate.h" +#import "PascalImports.h" +#import "GameConfigViewController.h" +#import "SplitViewRootController.h" +#import "CommodityFunctions.h" + +@implementation MainMenuViewController +@synthesize versionLabel; + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + if (settingsViewController.view.superview == nil) + settingsViewController = nil; + if (gameConfigViewController.view.superview == nil) + gameConfigViewController = nil; + MSG_MEMCLEAN(); +} + +-(void) viewDidLoad { + char *ver; + HW_versionInfo(NULL, &ver); + NSString *versionNumber = [[NSString alloc] initWithCString:ver]; + self.versionLabel.text = versionNumber; + [versionNumber release]; + + // listen to request to remove the modalviewcontroller + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(dismissModalViewController) + name: @"dismissModalView" + object:nil]; + + // initialize some files the first time we load the game + if (!([[NSFileManager defaultManager] fileExistsAtPath:SETTINGS_FILE()])) + [NSThread detachNewThreadSelector:@selector(checkFirstRun) toTarget:self withObject:nil]; + + [super viewDidLoad]; +} + +// this is called to verify whether it's the first time the app is launched +// if it is it blocks user interaction with an alertView until files are created +-(void) checkFirstRun { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSLog(@"First time run, creating settings files at %@", SETTINGS_FILE()); + + // show a popup with an indicator to make the user wait + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Please wait",@"") + message:nil + delegate:nil + cancelButtonTitle:nil + otherButtonTitles:nil]; + [alert show]; + + UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] + initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + indicator.center = CGPointMake(alert.bounds.size.width / 2, alert.bounds.size.height - 50); + [indicator startAnimating]; + [alert addSubview:indicator]; + [indicator release]; + + // create default files (teams/weapons/scheme) + createTeamNamed(@"Pirates"); + createTeamNamed(@"Ninjas"); + createWeaponNamed(@"Default"); + createSchemeNamed(@"Default"); + + // create settings.plist + NSMutableDictionary *saveDict = [[NSMutableDictionary alloc] init]; + + [saveDict setObject:@"" forKey:@"username"]; + [saveDict setObject:@"" forKey:@"password"]; + [saveDict setObject:[NSNumber numberWithBool:YES] forKey:@"music"]; + [saveDict setObject:[NSNumber numberWithBool:YES] forKey:@"sound"]; + [saveDict setObject:[NSNumber numberWithBool:NO] forKey:@"alternate"]; + + [saveDict writeToFile:SETTINGS_FILE() atomically:YES]; + [saveDict release]; + + // ok let the user take control + [alert dismissWithClickedButtonIndex:0 animated:YES]; + [alert release]; + + [pool release]; + [NSThread exit]; +} + +#pragma mark - +-(IBAction) switchViews:(id) sender { + UIButton *button = (UIButton *)sender; + UIAlertView *alert; + NSString *debugStr; + + switch (button.tag) { + case 0: + gameConfigViewController = [[GameConfigViewController alloc] initWithNibName:@"GameConfigViewController" bundle:nil]; + + // bug in UIModalTransitionStylePartialCurl, displays the controller awkwardly if it is not allocated every time + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + gameConfigViewController.modalTransitionStyle = UIModalTransitionStylePartialCurl; + [self presentModalViewController:gameConfigViewController animated:YES]; + break; + case 2: + if (nil == settingsViewController) { + settingsViewController = [[SplitViewRootController alloc] initWithNibName:nil bundle:nil]; + settingsViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; + } + + [self presentModalViewController:settingsViewController animated:YES]; + break; + case 3: + debugStr = [[NSString alloc] initWithContentsOfFile:DEBUG_FILE()]; + UITextView *scroll = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width)]; + scroll.text = debugStr; + [debugStr release]; + scroll.editable = NO; + + UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; + [btn addTarget:scroll action:@selector(removeFromSuperview) forControlEvents:UIControlEventTouchUpInside]; + btn.backgroundColor = [UIColor blackColor]; + btn.frame = CGRectMake(self.view.frame.size.height-70, 0, 70, 70); + [scroll addSubview:btn]; + [self.view addSubview:scroll]; + [scroll release]; + break; + default: + alert = [[UIAlertView alloc] initWithTitle:@"Not Yet Implemented" + message:@"Sorry, this feature is not yet implemented" + delegate:nil + cancelButtonTitle:@"Well, don't worry" + otherButtonTitles:nil]; + [alert show]; + [alert release]; + break; + } +} + +// allows child controllers to return to the main controller +-(void) dismissModalViewController { + [self dismissModalViewControllerAnimated:YES]; +} + + +-(void) viewDidUnload { + self.versionLabel = nil; + gameConfigViewController = nil; + settingsViewController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [versionLabel release]; + [settingsViewController release]; + [gameConfigViewController release]; + [super dealloc]; +} + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/MapConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,70 @@ +// +// MapConfigViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 22/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +#import "SDL_net.h" + +@interface MapConfigViewController : UIViewController { + TCPsocket sd, csd; + NSInteger oldValue; //slider + NSInteger oldPage; //segmented control + BOOL busy; + + // objects read (mostly) by parent view + NSInteger maxHogs; + NSString *seedCommand; + NSString *templateFilterCommand; + NSString *mapGenCommand; + NSString *mazeSizeCommand; + NSString *themeCommand; + + // various widgets in the view + UIButton *previewButton; + UITableView *tableView; + UILabel *maxLabel; + UILabel *sizeLabel; + UISegmentedControl *segmentedControl; + UISlider *slider; + + // internal objects + NSIndexPath *lastIndexPath; + NSArray *themeArray; + NSArray *mapArray; +} + +@property (nonatomic) NSInteger maxHogs; +@property (nonatomic) BOOL busy; +@property (nonatomic,retain) NSString *seedCommand; +@property (nonatomic,retain) NSString *templateFilterCommand; +@property (nonatomic,retain) NSString *mapGenCommand; +@property (nonatomic,retain) NSString *mazeSizeCommand; +@property (nonatomic,retain) NSString *themeCommand; + +@property (nonatomic,retain) IBOutlet UIButton *previewButton; +@property (nonatomic,retain) IBOutlet UITableView *tableView; +@property (nonatomic,retain) IBOutlet UILabel *maxLabel; +@property (nonatomic,retain) IBOutlet UILabel *sizeLabel; +@property (nonatomic,retain) IBOutlet UISegmentedControl *segmentedControl; +@property (nonatomic,retain) IBOutlet UISlider *slider; + +@property (nonatomic,retain) NSIndexPath *lastIndexPath; +@property (nonatomic,retain) NSArray *themeArray; +@property (nonatomic,retain) NSArray *mapArray; + +-(IBAction) updatePreview; +-(IBAction) sliderChanged:(id) sender; +-(IBAction) sliderEndedChanging:(id) sender; +-(IBAction) segmentedControlChanged:(id) sender; +-(void) turnOnWidgets; +-(void) turnOffWidgets; +-(void) setLabelText:(NSString *)str; +-(void) setButtonImage:(UIImage *)img; + +-(const uint8_t *)engineProtocol:(NSInteger) port; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/MapConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,568 @@ +// +// MapConfigViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 22/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "MapConfigViewController.h" +#import "PascalImports.h" +#import "CommodityFunctions.h" +#import "UIImageExtra.h" +#import "SDL_net.h" +#import + +#define INDICATOR_TAG 7654 + +@implementation MapConfigViewController +@synthesize previewButton, maxHogs, seedCommand, templateFilterCommand, mapGenCommand, mazeSizeCommand, themeCommand, + tableView, maxLabel, sizeLabel, segmentedControl, slider, lastIndexPath, themeArray, mapArray, busy; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +#pragma mark - +#pragma mark Preview Handling +-(int) sendToEngine: (NSString *)string { + unsigned char length = [string length]; + + SDLNet_TCP_Send(csd, &length , 1); + return SDLNet_TCP_Send(csd, [string UTF8String], length); +} + +-(const uint8_t *)engineProtocol:(NSInteger) port { + IPaddress ip; + BOOL serverQuit = NO; + static uint8_t map[128*32]; + + if (SDLNet_Init() < 0) { + NSLog(@"SDLNet_Init: %s", SDLNet_GetError()); + serverQuit = YES; + } + + // Resolving the host using NULL make network interface to listen + if (SDLNet_ResolveHost(&ip, NULL, port) < 0) { + NSLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError()); + serverQuit = YES; + } + + // Open a connection with the IP provided (listen on the host's port) + if (!(sd = SDLNet_TCP_Open(&ip))) { + NSLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port); + serverQuit = YES; + } + + // launch the preview here so that we're sure the tcp channel is open + pthread_t thread_id; + pthread_create(&thread_id, NULL, (void *)GenLandPreview, (void *)port); + pthread_detach(thread_id); + + DLog(@"Waiting for a client on port %d", port); + while (!serverQuit) { + /* This check the sd if there is a pending connection. + * If there is one, accept that, and open a new socket for communicating */ + csd = SDLNet_TCP_Accept(sd); + if (NULL != csd) { + DLog(@"Client found"); + + [self sendToEngine:self.seedCommand]; + [self sendToEngine:self.templateFilterCommand]; + [self sendToEngine:self.mapGenCommand]; + [self sendToEngine:self.mazeSizeCommand]; + [self sendToEngine:@"!"]; + + memset(map, 0, 128*32); + SDLNet_TCP_Recv(csd, map, 128*32); + SDLNet_TCP_Recv(csd, &maxHogs, sizeof(uint8_t)); + + SDLNet_TCP_Close(csd); + serverQuit = YES; + } + } + + SDLNet_TCP_Close(sd); + SDLNet_Quit(); + return map; +} + +-(void) drawingThread { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // select the port for IPC and launch the preview generation through engineProtocol: + int port = randomPort(); + const uint8_t *map = [self engineProtocol:port]; + uint8_t mapExp[128*32*8]; + + // draw the buffer (1 pixel per component, 0= transparent 1= color) + int k = 0; + for (int i = 0; i < 32*128; i++) { + unsigned char byte = map[i]; + for (int j = 0; j < 8; j++) { + // select the color based on the leftmost bit + if ((byte & 0x80) != 0) + mapExp[k] = 100; + else + mapExp[k] = 255; + // shift to next bit + byte <<= 1; + k++; + } + } + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray(); + CGContextRef bitmapImage = CGBitmapContextCreate(mapExp, 256, 128, 8, 256, colorspace, kCGImageAlphaNone); + CGColorSpaceRelease(colorspace); + + CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage); + UIImage *previewImage = [[UIImage alloc] initWithCGImage:previewCGImage]; + CGImageRelease(previewCGImage); + previewCGImage = nil; + + // set the preview image (autoreleased) in the button and the maxhog label on the main thread to prevent a leak + [self performSelectorOnMainThread:@selector(setButtonImage:) withObject:[previewImage makeRoundCornersOfSize:CGSizeMake(12, 12)] waitUntilDone:NO]; + [previewImage release]; + [self performSelectorOnMainThread:@selector(setLabelText:) withObject:[NSString stringWithFormat:@"%d", maxHogs] waitUntilDone:NO]; + + // restore functionality of button and remove the spinning wheel on the main thread to prevent a leak + [self performSelectorOnMainThread:@selector(turnOnWidgets) withObject:nil waitUntilDone:NO]; + + [pool release]; + //Invoking this method should be avoided as it does not give your thread a chance to clean up any resources it allocated during its execution. + //[NSThread exit]; + + /* + // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html + UIGraphicsBeginImageContext(CGSizeMake(256,128)); + CGContextRef context = UIGraphicsGetCurrentContext(); + UIGraphicsPushContext(context); + + CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0); + CGContextFillRect(context,CGRectMake(xc,yc,1,1)); + + UIGraphicsPopContext(); + UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + */ +} + +-(IBAction) updatePreview { + // don't generate a new preview while it's already generating one + if (busy) + return; + + // generate a seed + CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); + NSString *seed = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid); + CFRelease(uuid); + NSString *seedCmd = [[NSString alloc] initWithFormat:@"eseed {%@}", seed]; + [seed release]; + self.seedCommand = seedCmd; + [seedCmd release]; + + NSIndexPath *theIndex; + if (segmentedControl.selectedSegmentIndex != 1) { + // prevent other events and add an activity while the preview is beign generated + [self turnOffWidgets]; + + // remove the current preview + [self.previewButton setImage:nil forState:UIControlStateNormal]; + + // add a very nice spinning wheel + UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] + initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + indicator.center = CGPointMake(previewButton.bounds.size.width / 2, previewButton.bounds.size.height / 2); + indicator.tag = INDICATOR_TAG; + [indicator startAnimating]; + [self.previewButton addSubview:indicator]; + [indicator release]; + + // let's draw in a separate thread so the gui can work; at the end it restore other widgets + [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil]; + + theIndex = [NSIndexPath indexPathForRow:(random()%[self.themeArray count]) inSection:0]; + } else { + theIndex = [NSIndexPath indexPathForRow:(random()%[self.mapArray count]) inSection:0]; + } + [self.tableView reloadData]; + [self tableView:self.tableView didSelectRowAtIndexPath:theIndex]; + [self.tableView scrollToRowAtIndexPath:theIndex atScrollPosition:UITableViewScrollPositionNone animated:YES]; +} + +-(void) updatePreviewWithMap:(NSInteger) index { + // change the preview button + NSString *fileImage = [[NSString alloc] initWithFormat:@"%@/%@/preview.png", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]]; + UIImage *image = [[UIImage alloc] initWithContentsOfFile:fileImage]; + [fileImage release]; + [self.previewButton setImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal]; + [image release]; + + // update label + maxHogs = 18; + NSString *fileCfg = [[NSString alloc] initWithFormat:@"%@/%@/map.cfg", MAPS_DIRECTORY(),[self.mapArray objectAtIndex:index]]; + NSString *contents = [[NSString alloc] initWithContentsOfFile:fileCfg encoding:NSUTF8StringEncoding error:NULL]; + [fileCfg release]; + NSArray *split = [contents componentsSeparatedByString:@"\n"]; + + // if the number is not set we keep 18 standard; + // sometimes it's not set but there are trailing characters, we get around them with the second equation + if ([split count] > 1 && [[split objectAtIndex:1] intValue] > 0) + maxHogs = [[split objectAtIndex:1] intValue]; + [contents release]; + NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs]; + self.maxLabel.text = max; + [max release]; +} + +-(void) turnOffWidgets { + busy = YES; + self.previewButton.alpha = 0.5f; + self.previewButton.enabled = NO; + self.maxLabel.text = @"..."; + self.segmentedControl.enabled = NO; + self.slider.enabled = NO; +} + +-(void) turnOnWidgets { + self.previewButton.alpha = 1.0f; + self.previewButton.enabled = YES; + self.segmentedControl.enabled = YES; + self.slider.enabled = YES; + busy = NO; + + UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[self.previewButton viewWithTag:INDICATOR_TAG]; + if (indicator) { + [indicator stopAnimating]; + [indicator removeFromSuperview]; + } +} + +-(void) setLabelText:(NSString *)str { + self.maxLabel.text = str; +} + +-(void) setButtonImage:(UIImage *)img { + [self.previewButton setBackgroundImage:img forState:UIControlStateNormal]; +} + +-(void) restoreBackgroundImage { + // white rounded rectangle as background image for previewButton + UIGraphicsBeginImageContext(CGSizeMake(256,128)); + CGContextRef context = UIGraphicsGetCurrentContext(); + UIGraphicsPushContext(context); + + CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0); + CGContextFillRect(context,CGRectMake(0,0,256,128)); + + UIGraphicsPopContext(); + UIImage *bkgImg = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + [self.previewButton setBackgroundImage:[bkgImg makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal]; +} + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger) section { + if (self.segmentedControl.selectedSegmentIndex != 1) + return [themeArray count]; + else + return [mapArray count]; +} + +-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + NSInteger row = [indexPath row]; + + UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + + if (self.segmentedControl.selectedSegmentIndex != 1) { + // the % prevents a strange bug that occurs sporadically + NSString *themeName = [self.themeArray objectAtIndex:row % [self.themeArray count]]; + cell.textLabel.text = themeName; + UIImage *image = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@/icon.png",THEMES_DIRECTORY(),themeName]]; + cell.imageView.image = image; + [image release]; + } else { + cell.textLabel.text = [self.mapArray objectAtIndex:row]; + cell.imageView.image = nil; + } + + if (row == [self.lastIndexPath row]) + cell.accessoryType = UITableViewCellAccessoryCheckmark; + else + cell.accessoryType = UITableViewCellAccessoryNone; + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + if (self.segmentedControl.selectedSegmentIndex != 1) { + NSString *theme = [self.themeArray objectAtIndex:newRow]; + self.themeCommand = [NSString stringWithFormat:@"etheme %@", theme]; + } else + [self updatePreviewWithMap:newRow]; + + UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; + newCell.accessoryType = UITableViewCellAccessoryCheckmark; + UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:self.lastIndexPath]; + oldCell.accessoryType = UITableViewCellAccessoryNone; + + self.lastIndexPath = indexPath; + [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +#pragma mark - +#pragma mark slider & segmentedControl +// this updates the label and the command keys when the slider is moved, depending of the selection in segmentedControl +// no methods are called by this routine and you can pass nil to it +-(IBAction) sliderChanged:(id) sender { + NSString *labelText; + NSString *templateCommand; + NSString *mazeCommand; + + switch ((int)(self.slider.value*100)) { + case 0: + if (self.segmentedControl.selectedSegmentIndex == 0) { + labelText = NSLocalizedString(@"Wacky",@""); + } else { + labelText = NSLocalizedString(@"Large Floating Islands",@""); + } + templateCommand = @"e$template_filter 5"; + mazeCommand = @"e$maze_size 5"; + break; + case 1: + if (self.segmentedControl.selectedSegmentIndex == 0) { + labelText = NSLocalizedString(@"Cavern",@""); + } else { + labelText = NSLocalizedString(@"Medium Floating Islands",@""); + } + templateCommand = @"e$template_filter 4"; + mazeCommand = @"e$maze_size 4"; + break; + case 2: + if (self.segmentedControl.selectedSegmentIndex == 0) { + labelText = NSLocalizedString(@"Small",@""); + } else { + labelText = NSLocalizedString(@"Small Floating Islands",@""); + } + templateCommand = @"e$template_filter 1"; + mazeCommand = @"e$maze_size 3"; + break; + case 3: + if (self.segmentedControl.selectedSegmentIndex == 0) { + labelText = NSLocalizedString(@"Medium",@""); + } else { + labelText = NSLocalizedString(@"Large Tunnels",@""); + } + templateCommand = @"e$template_filter 2"; + mazeCommand = @"e$maze_size 2"; + break; + case 4: + if (self.segmentedControl.selectedSegmentIndex == 0) { + labelText = NSLocalizedString(@"Large",@""); + } else { + labelText = NSLocalizedString(@"Medium Tunnels",@""); + } + templateCommand = @"e$template_filter 3"; + mazeCommand = @"e$maze_size 1"; + break; + case 5: + if (self.segmentedControl.selectedSegmentIndex == 0) { + labelText = NSLocalizedString(@"All",@""); + } else { + labelText = NSLocalizedString(@"Small Tunnels",@""); + } + templateCommand = @"e$template_filter 0"; + mazeCommand = @"e$maze_size 0"; + break; + default: + labelText = nil; + templateCommand = nil; + mazeCommand = nil; + break; + } + + self.sizeLabel.text = labelText; + self.templateFilterCommand = templateCommand; + self.mazeSizeCommand = mazeCommand; +} + +// update preview (if not busy and if its value really changed) as soon as the user lifts its finger up +-(IBAction) sliderEndedChanging:(id) sender { + int num = (int) (self.slider.value * 100); + if (oldValue != num) { + [self updatePreview]; + oldValue = num; + } +} + +// perform actions based on the activated section, then call updatePreview to visually update the selection +// updatePreview will call didSelectRowAtIndexPath which will call the right update routine) +// and if necessary update the table with a slide animation +-(IBAction) segmentedControlChanged:(id) sender { + NSString *mapgen; + NSInteger newPage = self.segmentedControl.selectedSegmentIndex; + + switch (newPage) { + case 0: // Random + mapgen = @"e$mapgen 0"; + [self sliderChanged:nil]; + self.slider.enabled = YES; + break; + + case 1: // Map + mapgen = @"e$mapgen 0"; + self.slider.enabled = NO; + self.sizeLabel.text = @"."; + [self restoreBackgroundImage]; + break; + + case 2: // Maze + mapgen = @"e$mapgen 1"; + [self sliderChanged:nil]; + self.slider.enabled = YES; + break; + + default: + mapgen = nil; + break; + } + self.mapGenCommand = mapgen; + [self updatePreview]; + + // nice animation for updating the table when appropriate (on iphone) + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) + if (((oldPage == 0 || oldPage == 2) && newPage == 1) || + (oldPage == 1 && (newPage == 0 || newPage == 2))) { + [UIView beginAnimations:@"moving out table" context:NULL]; + self.tableView.frame = CGRectMake(480, 0, 185, 276); + [UIView commitAnimations]; + [self performSelector:@selector(moveTable) withObject:nil afterDelay:0.2]; + } + oldPage = newPage; +} + +// update data when table is not visible and then show it +-(void) moveTable { + [self.tableView reloadData]; + + [UIView beginAnimations:@"moving in table" context:NULL]; + self.tableView.frame = CGRectMake(295, 0, 185, 276); + [UIView commitAnimations]; +} + +#pragma mark - +#pragma mark view management +-(void) viewDidLoad { + [super viewDidLoad]; + + srandom(time(NULL)); + + CGSize screenSize = [[UIScreen mainScreen] bounds].size; + self.view.frame = CGRectMake(0, 0, screenSize.height, screenSize.width - 44); + + // themes.cfg contains all the user-selectable themes + NSString *string = [[NSString alloc] initWithContentsOfFile:[THEMES_DIRECTORY() stringByAppendingString:@"/themes.cfg"] + encoding:NSUTF8StringEncoding + error:NULL]; + NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[string componentsSeparatedByString:@"\n"]]; + [string release]; + // remove a trailing "" element + [array removeLastObject]; + self.themeArray = array; + [array release]; + self.mapArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL]; + + self.tableView.rowHeight = 42; + busy = NO; + + // draw a white background + [self restoreBackgroundImage]; + + // initialize some "default" values + self.sizeLabel.text = NSLocalizedString(@"All",@""); + self.slider.value = 0.05f; + self.segmentedControl.selectedSegmentIndex = 0; + + self.templateFilterCommand = @"e$template_filter 0"; + self.mazeSizeCommand = @"e$maze_size 0"; + self.mapGenCommand = @"e$mapgen 0"; + self.lastIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; + + oldValue = 5; + oldPage = 0; +} + +-(void) viewDidAppear:(BOOL) animated { + [super viewDidAppear:animated]; + [self updatePreview]; +} + +#pragma mark - +#pragma mark memory +-(void) didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +-(void) viewDidUnload { + self.previewButton = nil; + self.seedCommand = nil; + self.templateFilterCommand = nil; + self.mapGenCommand = nil; + self.mazeSizeCommand = nil; + self.themeCommand = nil; + + self.previewButton = nil; + self.tableView = nil; + self.maxLabel = nil; + self.sizeLabel = nil; + self.segmentedControl = nil; + self.slider = nil; + + self.lastIndexPath = nil; + self.themeArray = nil; + self.mapArray = nil; + + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [seedCommand release]; + [templateFilterCommand release]; + [mapGenCommand release]; + [mazeSizeCommand release]; + [themeCommand release]; + + [previewButton release]; + [tableView release]; + [maxLabel release]; + [sizeLabel release]; + [segmentedControl release]; + [slider release]; + + [lastIndexPath release]; + [themeArray release]; + [mapArray release]; + + [super dealloc]; +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/MasterViewController.h --- a/project_files/HedgewarsMobile/Classes/MasterViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/MasterViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,34 @@ +// +// MasterViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 27/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@class DetailViewController; +@class GeneralSettingsViewController; +@class TeamSettingsViewController; +@class WeaponSettingsViewController; +@class SchemeSettingsViewController; + +@interface MasterViewController : UITableViewController { + DetailViewController *detailViewController; + NSArray *controllerNames; + NSIndexPath *lastIndexPath; + GeneralSettingsViewController *generalSettingsViewController; + TeamSettingsViewController *teamSettingsViewController; + WeaponSettingsViewController *weaponSettingsViewController; + SchemeSettingsViewController *schemeSettingsViewController; +} + +@property (nonatomic, retain) DetailViewController *detailViewController; +@property (nonatomic, retain) NSArray *controllerNames; +@property (nonatomic, retain) NSIndexPath *lastIndexPath; + +-(IBAction) dismissSplitView; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/MasterViewController.m --- a/project_files/HedgewarsMobile/Classes/MasterViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/MasterViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,155 @@ +// +// MasterViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 27/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "MasterViewController.h" +#import "DetailViewController.h" +#import "GeneralSettingsViewController.h" +#import "TeamSettingsViewController.h" +#import "WeaponSettingsViewController.h" +#import "SchemeSettingsViewController.h" +#import "CommodityFunctions.h" + +@implementation MasterViewController +@synthesize detailViewController, controllerNames, lastIndexPath; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + // the list of selectable controllers + controllerNames = [[NSArray alloc] initWithObjects:NSLocalizedString(@"General",@""), + NSLocalizedString(@"Teams",@""), + NSLocalizedString(@"Weapons",@""), + NSLocalizedString(@"Schemes",@""), + nil]; + // the "Done" button on top left + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissSplitView)]; +} + +#pragma mark - +#pragma mark Table view data source + +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [controllerNames count]; +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + cell.textLabel.text = [controllerNames objectAtIndex:[indexPath row]]; + } + + return cell; +} + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + UIViewController *nextController = nil; + + if (newRow != oldRow) { + [self.tableView deselectRowAtIndexPath:lastIndexPath animated:YES]; + [detailViewController.navigationController popToRootViewControllerAnimated:NO]; + + switch (newRow) { + case 0: + if (nil == generalSettingsViewController) + generalSettingsViewController = [[GeneralSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = generalSettingsViewController; + break; + case 1: + if (nil == teamSettingsViewController) + teamSettingsViewController = [[TeamSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = teamSettingsViewController; + break; + case 2: + if (nil == weaponSettingsViewController) + weaponSettingsViewController = [[WeaponSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = weaponSettingsViewController; + break; + case 3: + if (nil == schemeSettingsViewController) + schemeSettingsViewController = [[SchemeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + nextController = schemeSettingsViewController; + break; + } + + nextController.navigationItem.hidesBackButton = YES; + nextController.title = [controllerNames objectAtIndex:newRow]; + [detailViewController.navigationController pushViewController:nextController animated:NO]; + self.lastIndexPath = indexPath; + [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. + if (generalSettingsViewController.view.superview == nil) + generalSettingsViewController = nil; + if (teamSettingsViewController.view.superview == nil) + teamSettingsViewController = nil; + if (weaponSettingsViewController.view.superview == nil) + weaponSettingsViewController = nil; + if (schemeSettingsViewController.view.superview == nil) + schemeSettingsViewController = nil; + MSG_MEMCLEAN(); +} + +-(void) viewDidUnload { + self.detailViewController = nil; + self.controllerNames = nil; + self.lastIndexPath = nil; + generalSettingsViewController = nil; + teamSettingsViewController = nil; + weaponSettingsViewController = nil; + schemeSettingsViewController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [controllerNames release]; + [detailViewController release]; + [lastIndexPath release]; + [generalSettingsViewController release]; + [teamSettingsViewController release]; + [weaponSettingsViewController release]; + [schemeSettingsViewController release]; + [super dealloc]; +} + +-(IBAction) dismissSplitView { + [[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" object:nil]; +} + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/OverlayViewController.h --- a/project_files/HedgewarsMobile/Classes/OverlayViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/OverlayViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,52 @@ +// +// overlayViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 16/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class PopoverMenuViewController; + +@interface OverlayViewController : UIViewController { + NSTimer *dimTimer; + + // used only on the ipad + UIPopoverController *popoverController; + + PopoverMenuViewController *popupMenu; + BOOL isPopoverVisible; + + UITextField *writeChatTextField; + + CGFloat initialDistanceForPinching; + CGPoint gestureStartPoint; + UIActivityIndicatorView *spinningWheel; +} + +@property (nonatomic,retain) id popoverController; +@property (nonatomic,retain) PopoverMenuViewController *popupMenu; +@property (nonatomic,retain) UITextField *writeChatTextField; +@property (nonatomic,retain) IBOutlet UIActivityIndicatorView *spinningWheel; + +UIActivityIndicatorView *singleton; +BOOL canDim; + +-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; +-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; +-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; +-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; + +-(IBAction) buttonReleased:(id) sender; +-(IBAction) buttonPressed:(id) sender; + +-(void) showPopover; +-(void) dismissPopover; +-(void) dimOverlay; +-(void) activateOverlay; +-(void) chatAppear; +-(void) chatDisappear; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/OverlayViewController.m --- a/project_files/HedgewarsMobile/Classes/OverlayViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/OverlayViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,445 @@ +// +// overlayViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 16/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "OverlayViewController.h" +#import "SDL_uikitappdelegate.h" +#import "PascalImports.h" +#import "CGPointUtils.h" +#import "SDL_mouse.h" +#import "SDL_config_iphoneos.h" +#import "PopoverMenuViewController.h" +#import "CommodityFunctions.h" + +#define HIDING_TIME_DEFAULT [NSDate dateWithTimeIntervalSinceNow:2.7] +#define HIDING_TIME_NEVER [NSDate dateWithTimeIntervalSinceNow:10000] + + +@implementation OverlayViewController +@synthesize popoverController, popupMenu, writeChatTextField, spinningWheel; + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Release any cached data, images, etc that aren't in use. + if (popupMenu.view.superview == nil) + popupMenu = nil; +} + +-(void) didRotate:(NSNotification *)notification { + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + CGRect rect = [[UIScreen mainScreen] bounds]; + CGRect usefulRect = CGRectMake(0, 0, rect.size.width, rect.size.height); + UIView *sdlView = [[[UIApplication sharedApplication] keyWindow] viewWithTag:12345]; + + [UIView beginAnimations:@"rotation" context:NULL]; + [UIView setAnimationDuration:0.8f]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; + switch (orientation) { + case UIDeviceOrientationLandscapeLeft: + sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(0)); + self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); + [self chatDisappear]; + HW_setLandscape(YES); + break; + case UIDeviceOrientationLandscapeRight: + sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(180)); + self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(-90)); + [self chatDisappear]; + HW_setLandscape(YES); + break; + case UIDeviceOrientationPortrait: + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(270)); + self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(0)); + [self chatAppear]; + HW_setLandscape(NO); + } + break; + case UIDeviceOrientationPortraitUpsideDown: + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + sdlView.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); + self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(180)); + [self chatAppear]; + HW_setLandscape(NO); + } + break; + default: + break; + } + self.view.frame = usefulRect; + //sdlView.frame = usefulRect; + [UIView commitAnimations]; +} + +-(void) chatAppear { + if (writeChatTextField == nil) { + writeChatTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 100, 768, [UIFont systemFontSize]+8)]; + writeChatTextField.textColor = [UIColor whiteColor]; + writeChatTextField.backgroundColor = [UIColor blueColor]; + writeChatTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; + writeChatTextField.autocorrectionType = UITextAutocorrectionTypeNo; + writeChatTextField.enablesReturnKeyAutomatically = NO; + writeChatTextField.keyboardAppearance = UIKeyboardAppearanceDefault; + writeChatTextField.keyboardType = UIKeyboardTypeDefault; + writeChatTextField.returnKeyType = UIReturnKeyDefault; + writeChatTextField.secureTextEntry = NO; + [self.view addSubview:writeChatTextField]; + } + writeChatTextField.alpha = 1; + [self activateOverlay]; + [dimTimer setFireDate:HIDING_TIME_NEVER]; +} + +-(void) chatDisappear { + writeChatTextField.alpha = 0; + [writeChatTextField resignFirstResponder]; + [dimTimer setFireDate:HIDING_TIME_DEFAULT]; +} + +#pragma mark - +#pragma mark View Management +-(void) viewDidLoad { + isPopoverVisible = NO; + singleton = self.spinningWheel; + canDim = NO; + self.view.alpha = 0; + self.view.center = CGPointMake(self.view.frame.size.height/2.0, self.view.frame.size.width/2.0); + + + dimTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:6] + interval:1000 + target:self + selector:@selector(dimOverlay) + userInfo:nil + repeats:YES]; + + // add timer too runloop, otherwise it doesn't work + [[NSRunLoop currentRunLoop] addTimer:dimTimer forMode:NSDefaultRunLoopMode]; + + // listen for dismissal of the popover (see below) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(dismissPopover) + name:@"dismissPopover" + object:nil]; + + [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didRotate:) + name:@"UIDeviceOrientationDidChangeNotification" + object:nil]; + + //self.view.transform = CGAffineTransformRotate(self.view.transform, (M_PI/2.0)); + [UIView beginAnimations:@"showing overlay" context:NULL]; + [UIView setAnimationDuration:1]; + self.view.alpha = 1; + [UIView commitAnimations]; +} + +-(void) viewDidUnload { + self.writeChatTextField = nil; + self.popoverController = nil; + self.popupMenu = nil; + self.spinningWheel = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [dimTimer invalidate]; + [writeChatTextField release]; + [popupMenu release]; + [popoverController release]; + // dimTimer is autoreleased + [spinningWheel release]; + [super dealloc]; +} + +#pragma mark - +#pragma mark Overlay actions and members +// dim the overlay when there's no more input for a certain amount of time +-(IBAction) buttonReleased:(id) sender { + HW_allKeysUp(); + [dimTimer setFireDate:HIDING_TIME_DEFAULT]; +} + +// nice transition for dimming, should be called only by the timer himself +-(void) dimOverlay { + if (canDim) { + [UIView beginAnimations:@"overlay dim" context:NULL]; + [UIView setAnimationDuration:0.6]; + self.view.alpha = 0.2; + [UIView commitAnimations]; + } +} + +// set the overlay visible and put off the timer for enough time +-(void) activateOverlay { + self.view.alpha = 1; + [dimTimer setFireDate:HIDING_TIME_NEVER]; +} + +// issue certain action based on the tag of the button +-(IBAction) buttonPressed:(id) sender { + [self activateOverlay]; + if (isPopoverVisible) { + [self dismissPopover]; + } + UIButton *theButton = (UIButton *)sender; + + switch (theButton.tag) { + case 0: + HW_walkLeft(); + break; + case 1: + HW_walkRight(); + break; + case 2: + HW_aimUp(); + break; + case 3: + HW_aimDown(); + break; + case 4: + HW_shoot(); + break; + case 5: + HW_jump(); + break; + case 6: + HW_backjump(); + break; + case 7: + HW_tab(); + break; + case 10: + [self showPopover]; + break; + default: + NSLog(@"Nope"); + break; + } +} + +// present a further check before closing game +-(void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger) buttonIndex { + if ([actionSheet cancelButtonIndex] != buttonIndex) + HW_terminate(NO); + else + HW_pause(); +} + +// show up a popover containing a popupMenuViewController; we hook it with setPopoverContentSize +// on iphone instead just use the tableViewController directly (and implement manually all animations) +-(IBAction) showPopover{ + isPopoverVisible = YES; + CGRect anchorForPopover; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + if (popupMenu == nil) + popupMenu = [[PopoverMenuViewController alloc] initWithStyle:UITableViewStylePlain]; + if (popoverController == nil) { + popoverController = [[UIPopoverController alloc] initWithContentViewController:popupMenu]; + [popoverController setPopoverContentSize:CGSizeMake(220, 170) animated:YES]; + [popoverController setPassthroughViews:[NSArray arrayWithObject:self.view]]; + } + + if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])) + anchorForPopover = CGRectMake(960, 0, 220, 32); + else + anchorForPopover = CGRectMake(736, 0, 220, 32); + + [popoverController presentPopoverFromRect:anchorForPopover + inView:self.view + permittedArrowDirections:UIPopoverArrowDirectionUp + animated:YES]; + } else { + if (popupMenu == nil) { + popupMenu = [[PopoverMenuViewController alloc] initWithStyle:UITableViewStyleGrouped]; + popupMenu.view.backgroundColor = [UIColor clearColor]; + popupMenu.view.frame = CGRectMake(480, 0, 200, 170); + } + [self.view addSubview:popupMenu.view]; + + [UIView beginAnimations:@"showing popover" context:NULL]; + [UIView setAnimationDuration:0.35]; + popupMenu.view.frame = CGRectMake(280, 0, 200, 170); + [UIView commitAnimations]; + } + popupMenu.tableView.scrollEnabled = NO; +} + +// on ipad just dismiss it, on iphone transtion to the right +-(void) dismissPopover { + if (YES == isPopoverVisible) { + isPopoverVisible = NO; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + [popoverController dismissPopoverAnimated:YES]; + } else { + [UIView beginAnimations:@"hiding popover" context:NULL]; + [UIView setAnimationDuration:0.35]; + popupMenu.view.frame = CGRectMake(480, 0, 200, 170); + [UIView commitAnimations]; + + [popupMenu.view performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0.35]; + } + [self buttonReleased:nil]; + } +} + +-(void) textFieldDoneEditing:(id) sender{ + [sender resignFirstResponder]; +} + +// this function is called by pascal FinishProgress and removes the spinning wheel when loading is done +void spinningWheelDone (void) { + [UIView beginAnimations:@"hiding spinning wheel" context:NULL]; + [UIView setAnimationDuration:0.7]; + singleton.alpha = 0; + [UIView commitAnimations]; + [singleton performSelector:@selector(stopAnimating) withObject:nil afterDelay:0.7]; + canDim = YES; +} + +#pragma mark - +#pragma mark Custom touch event handling +-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + NSArray *twoTouches; + UITouch *touch = [touches anyObject]; + + if (isPopoverVisible) { + [self dismissPopover]; + } + if (writeChatTextField) { + [self.writeChatTextField resignFirstResponder]; + [dimTimer setFireDate:HIDING_TIME_DEFAULT]; + } + + gestureStartPoint = [touch locationInView:self.view]; + + switch ([touches count]) { + /*case 1: + initialDistanceForPinching = 0; + switch ([touch tapCount]) { + case 1: + NSLog(@"X:%d Y:%d", (int)gestureStartPoint.x, (int)gestureStartPoint.y ); + //SDL_WarpMouseInWindow([SDLUIKitDelegate sharedAppDelegate].window, + // (int)gestureStartPoint.y, width - (int)gestureStartPoint.x); + //HW_click(); + break; + case 2: + HW_ammoMenu(); + break; + default: + break; + } + break;*/ + case 2: + if (2 == [touch tapCount]) { + HW_zoomReset(); + } + + // pinching + gestureStartPoint = CGPointMake(0, 0); + twoTouches = [touches allObjects]; + UITouch *first = [twoTouches objectAtIndex:0]; + UITouch *second = [twoTouches objectAtIndex:1]; + initialDistanceForPinching = distanceBetweenPoints([first locationInView:self.view], [second locationInView:self.view]); + break; + default: + break; + } + +} + +-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + gestureStartPoint = CGPointMake(0, 0); + initialDistanceForPinching = 0; + //HW_allKeysUp(); +} + +-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + // this can happen if the user puts more than 5 touches on the screen at once, or perhaps in other circumstances + [self touchesEnded:touches withEvent:event]; +} + +-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + CGFloat minimumGestureLength; + int logCoeff; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + minimumGestureLength = 5.0f; + logCoeff = 19; + } else { + minimumGestureLength = 3.0f; + logCoeff = 3; + } + + NSArray *twoTouches; + CGPoint currentPosition; + UITouch *touch = [touches anyObject]; + + switch ([touches count]) { + /*case 1: + currentPosition = [touch locationInView:self.view]; + // panning + CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x); + CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y); + + // the two ifs are not mutually exclusive + if (deltaX >= minimumGestureLength) { + DLog(@"deltaX: %f deltaY: %f", deltaX, deltaY); + if (currentPosition.x > gestureStartPoint.x) { + HW_cursorLeft(logCoeff*log(deltaX)); + } else { + HW_cursorRight(logCoeff*log(deltaX)); + } + + } + if (deltaY >= minimumGestureLength) { + DLog(@"deltaX: %f deltaY: %f", deltaX, deltaY); + if (currentPosition.y < gestureStartPoint.y) { + HW_cursorDown(logCoeff*log(deltaY)); + } else { + HW_cursorUp(logCoeff*log(deltaY)); + } + } + + break;*/ + case 2: + twoTouches = [touches allObjects]; + UITouch *first = [twoTouches objectAtIndex:0]; + UITouch *second = [twoTouches objectAtIndex:1]; + CGFloat currentDistanceOfPinching = distanceBetweenPoints([first locationInView:self.view], [second locationInView:self.view]); + const int pinchDelta = 40; + + if (0 != initialDistanceForPinching) { + if (currentDistanceOfPinching - initialDistanceForPinching > pinchDelta) { + HW_zoomIn(); + initialDistanceForPinching = currentDistanceOfPinching; + } + else if (initialDistanceForPinching - currentDistanceOfPinching > pinchDelta) { + HW_zoomOut(); + initialDistanceForPinching = currentDistanceOfPinching; + } + } else + initialDistanceForPinching = currentDistanceOfPinching; + + break; + default: + break; + } +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/PascalImports.h --- a/project_files/HedgewarsMobile/Classes/PascalImports.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/PascalImports.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,59 @@ +/* + * PascalImports.h +// fpciphonedel +// +// Created by Vittorio on 07/01/10. +// Copyright __MyCompanyName__ 2010. All rights reserved. + * + */ + +#ifndef PASCALIMPORTS +#define PASCALIMPORTS + +#ifdef __cplusplus +extern "C" { +#endif + + /* add C declarations below for all exported Pascal functions/procedure + * that you want to use + */ + + void Game(const char *args[]); + void GenLandPreview(void); + + + void HW_versionInfo(short int*, char**); + + void HW_click(void); + void HW_zoomIn(void); + void HW_zoomOut(void); + void HW_zoomReset(void); + void HW_ammoMenu(void); + + void HW_allKeysUp(void); + + void HW_walkLeft(void); + void HW_walkRight(void); + void HW_aimUp(void); + void HW_aimDown(void); + void HW_shoot(void); + void HW_jump(void); + void HW_backjump(void); + + void HW_chat(void); + void HW_tab(void); + void HW_pause(void); + + void HW_cursorUp(int); + void HW_cursorDown(int); + void HW_cursorLeft(int); + void HW_cursorRight(int); + + void HW_terminate(BOOL); + + void HW_setLandscape(BOOL); +#ifdef __cplusplus +} +#endif + +#endif diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/PopoverMenuViewController.h --- a/project_files/HedgewarsMobile/Classes/PopoverMenuViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/PopoverMenuViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,18 @@ +// +// popupMenuViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 25/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface PopoverMenuViewController : UITableViewController { + NSArray *menuList; + BOOL isPaused; +} +@property (nonatomic,retain) NSArray *menuList; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/PopoverMenuViewController.m --- a/project_files/HedgewarsMobile/Classes/PopoverMenuViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/PopoverMenuViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,141 @@ + // +// popupMenuViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 25/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SDL_uikitappdelegate.h" +#import "PopoverMenuViewController.h" +#import "PascalImports.h" +#import "CommodityFunctions.h" +#import "SDL_sysvideo.h" + +@implementation PopoverMenuViewController +@synthesize menuList; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; +} + +-(void) viewDidLoad { + isPaused = NO; + + NSArray *array = [[NSArray alloc] initWithObjects: + NSLocalizedString(@"Pause Game", @""), + NSLocalizedString(@"Chat", @""), + NSLocalizedString(@"End Game", @""), + nil]; + self.menuList = array; + [array release]; + + [super viewDidLoad]; +} + +-(void) viewDidUnload { + self.menuList = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [menuList release]; + [super dealloc]; +} + +#pragma mark - +#pragma mark tableView methods +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 3; +} + +-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *cellIdentifier = @"CellIdentifier"; + + UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:cellIdentifier]; + if (nil == cell) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:cellIdentifier] autorelease]; + } + cell.textLabel.text = [menuList objectAtIndex:[indexPath row]]; + + return cell; +} + +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + UIActionSheet *actionSheet; + + switch ([indexPath row]) { + case 0: + HW_pause(); + isPaused = !isPaused; + break; + case 1: + HW_chat(); + /* + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_VideoDisplay *display = &_this->displays[0]; + SDL_Window *window = display->windows; + SDL_iPhoneKeyboardShow(window); + */ + break; + case 2: + // expand the view (and table) so that the actionsheet can be selected on the iPhone + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { + [self.tableView deselectRowAtIndexPath:indexPath animated:NO]; + [UIView beginAnimations:@"table width more" context:NULL]; + [UIView setAnimationDuration:0.2]; + self.view.frame = CGRectMake(0, 0, 480, 320); + [UIView commitAnimations]; + } + actionSheet = [[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"Are you reeeeeally sure?", @"") + delegate:self + cancelButtonTitle:NSLocalizedString(@"Well, maybe not...", @"") + destructiveButtonTitle:NSLocalizedString(@"Of course!", @"") + otherButtonTitles:nil]; + [actionSheet showInView:self.view]; + [actionSheet release]; + + if (!isPaused) + HW_pause(); + break; + default: + NSLog(@"Warning: unset case value in section!"); + break; + } + + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +#pragma mark - +#pragma mark actionSheet methods +-(void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger) buttonIndex { + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){ + [UIView beginAnimations:@"table width less" context:NULL]; + [UIView setAnimationDuration:0.2]; + self.view.frame = CGRectMake(280, 0, 200, 170); + [UIView commitAnimations]; + } + + if ([actionSheet cancelButtonIndex] != buttonIndex) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"dismissPopover" object:nil]; + HW_terminate(NO); + } + else + if (!isPaused) + HW_pause(); +} + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.h --- a/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,44 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#import +#import "SDL_uikitopenglview.h" + +@class MainMenuViewController; +@class OverlayViewController; + +@interface SDLUIKitDelegate:NSObject { + SDL_Window *window; + UIWindow *uiwindow; + MainMenuViewController *mainViewController; + BOOL isInGame; +} + +@property (readwrite, assign) SDL_Window *window; +@property (readwrite, retain) UIWindow *uiwindow; + ++(SDLUIKitDelegate *)sharedAppDelegate; +-(void) startSDLgame; +-(void) displayOverlayLater; + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m --- a/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,194 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga, mods for Hedgewars by Vittorio Giovara + slouken@libsdl.org, vittorio.giovara@gmail.com +*/ + +#import "SDL_uikitappdelegate.h" +#import "SDL_uikitopenglview.h" +#import "SDL_uikitwindow.h" +#import "SDL_events_c.h" +#import "../SDL_sysvideo.h" +#import "jumphack.h" +#import "SDL_video.h" +#import "GameSetup.h" +#import "PascalImports.h" +#import "MainMenuViewController.h" +#import "OverlayViewController.h" +#import "CommodityFunctions.h" + +#ifdef main +#undef main +#endif + +#define VALGRIND "/opt/valgrind/bin/valgrind" + +int main (int argc, char *argv[]) { +#ifdef VALGRIND_REXEC + // Using the valgrind build config, rexec ourself in valgrind + // from http://landonf.bikemonkey.org/code/iphone/iPhone_Simulator_Valgrind.20081224.html + if (argc < 2 || (argc >= 2 && strcmp(argv[1], "-valgrind") != 0)) + execl(VALGRIND, VALGRIND, "--leak-check=full", argv[0], "-valgrind", NULL); +#endif + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, @"SDLUIKitDelegate"); + [pool release]; + return retVal; +} + +@implementation SDLUIKitDelegate +@synthesize uiwindow, window; + +// convenience method ++(SDLUIKitDelegate *)sharedAppDelegate { + // the delegate is set in UIApplicationMain(), which is guaranteed to be called before this method + return (SDLUIKitDelegate *)[[UIApplication sharedApplication] delegate]; +} + +-(id) init { + if (self = [super init]){ + mainViewController = nil; + isInGame = NO; + self.uiwindow = nil; + self.window = NULL; + } + return self; +} + +-(void) dealloc { + SDL_DestroyWindow(self.window); + [uiwindow release]; + [mainViewController release]; + [super dealloc]; +} + +// main routine for calling the actual game engine +-(IBAction) startSDLgame { + [UIView beginAnimations:@"removing main controller" context:NULL]; + [UIView setAnimationDuration:1]; + mainViewController.view.alpha = 0; + [UIView commitAnimations]; + + // pull out useful configuration info from various files + GameSetup *setup = [[GameSetup alloc] init]; + [setup startThread:@"engineProtocol"]; + const char **gameArgs = [setup getSettings]; + [setup release]; + + // since the sdlwindow is not yet created, we add the overlayController with a delay + [self performSelector:@selector(displayOverlayLater) withObject:nil afterDelay:0.5]; + + // this is the pascal fuction that starts the game (wrapped around isInGame) + isInGame = YES; + Game(gameArgs); + isInGame = NO; + + free(gameArgs); + + [UIView beginAnimations:@"inserting main controller" context:NULL]; + [UIView setAnimationDuration:1]; + mainViewController.view.alpha = 1; + [UIView commitAnimations]; +} + +-(void) displayOverlayLater { + // overlay with controls, become visible after 4 seconds, with a transparency effect + OverlayViewController *overlayController = [[OverlayViewController alloc] initWithNibName:@"OverlayViewController" bundle:nil]; + + [[[UIApplication sharedApplication] keyWindow] addSubview:overlayController.view]; + [overlayController release]; +} + +// override the direct execution of SDL_main to allow us to implement the frontend (or even using a nib) +-(void) applicationDidFinishLaunching:(UIApplication *)application { + [application setStatusBarHidden:YES]; + [application setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; + + uiwindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + uiwindow.backgroundColor = [UIColor blackColor]; + // needed to keep the app running after a game (gets released in sdl_uikitwindow) + [uiwindow retain]; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + mainViewController = [[MainMenuViewController alloc] initWithNibName:@"MainMenuViewController-iPad" bundle:nil]; + else + mainViewController = [[MainMenuViewController alloc] initWithNibName:@"MainMenuViewController-iPhone" bundle:nil]; + + [uiwindow addSubview:mainViewController.view]; + [uiwindow makeKeyAndVisible]; + + // Set working directory to resource path + [[NSFileManager defaultManager] changeCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]]; +} + +-(void) applicationWillTerminate:(UIApplication *)application { + SDL_SendQuit(); + if (isInGame) { + HW_terminate(YES); + // hack to prevent automatic termination. See SDL_uikitevents.m for details + longjmp(*(jump_env()), 1); + } +} + +-(void) applicationWillResignActive:(UIApplication *)application { + //NSLog(@"%@", NSStringFromSelector(_cmd)); + if (isInGame) { + HW_pause(); + + /* + // Send every window on every screen a MINIMIZED event. + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (!_this) + return; + + int i; + for (i = 0; i < _this->num_displays; i++) { + const SDL_VideoDisplay *display = &_this->displays[i]; + SDL_Window *window; + for (window = display->windows; window != nil; window = window->next) + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MINIMIZED, 0, 0); + } + */ + } +} + +-(void) applicationDidBecomeActive:(UIApplication *)application { + //NSLog(@"%@", NSStringFromSelector(_cmd)); + if (isInGame) { + HW_pause(); + + /* + // Send every window on every screen a RESTORED event. + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (!_this) + return; + + int i; + for (i = 0; i < _this->num_displays; i++) { + const SDL_VideoDisplay *display = &_this->displays[i]; + SDL_Window *window; + for (window = display->windows; window != nil; window = window->next) + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0); + } + */ + } +} + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,19 @@ +// +// SchemeSettingsViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 19/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +@class SingleSchemeViewController; + +@interface SchemeSettingsViewController : UITableViewController { + NSMutableArray *listOfSchemes; + SingleSchemeViewController *childController; +} + +@property (nonatomic, retain) NSMutableArray *listOfSchemes; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,169 @@ +// +// SchemeSettingsViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 19/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SchemeSettingsViewController.h" +#import "CommodityFunctions.h" +#import "SingleSchemeViewController.h" + +@implementation SchemeSettingsViewController +@synthesize listOfSchemes; + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Edit",@"from the scheme panel") + style:UIBarButtonItemStyleBordered + target:self + action:@selector(toggleEdit:)]; + self.navigationItem.rightBarButtonItem = editButton; + [editButton release]; + +} + +-(void) viewWillAppear:(BOOL) animated { + [super viewWillAppear:animated]; + + NSArray *contentsOfDir = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:SCHEMES_DIRECTORY() error:NULL]; + NSMutableArray *array = [[NSMutableArray alloc] initWithArray:contentsOfDir copyItems:YES]; + self.listOfSchemes = array; + [array release]; + + [self.tableView reloadData]; +} + +// modifies the navigation bar to add the "Add" and "Done" buttons +-(void) toggleEdit:(id) sender { + BOOL isEditing = self.tableView.editing; + [self.tableView setEditing:!isEditing animated:YES]; + + if (isEditing) { + [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Edit",@"from the scheme panel")]; + [self.navigationItem.rightBarButtonItem setStyle: UIBarButtonItemStyleBordered]; + self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem; + } else { + [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Done",@"from the scheme panel")]; + [self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone]; + UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Add",@"from the scheme panel") + style:UIBarButtonItemStyleBordered + target:self + action:@selector(addScheme:)]; + self.navigationItem.leftBarButtonItem = addButton; + [addButton release]; + } +} + +-(void) addScheme:(id) sender { + NSString *fileName = [[NSString alloc] initWithFormat:@"Scheme %u.plist", [self.listOfSchemes count]]; + + createSchemeNamed([fileName stringByDeletingPathExtension]); + + [self.listOfSchemes addObject:fileName]; + [fileName release]; + + // order the array alphabetically, so schemes will keep their position + [self.listOfSchemes sortUsingSelector:@selector(compare:)]; + + [self.tableView reloadData]; +} + +#pragma mark - +#pragma mark Table view data source +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.listOfSchemes count]; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + NSUInteger row = [indexPath row]; + NSString *rowString = [[self.listOfSchemes objectAtIndex:row] stringByDeletingPathExtension]; + cell.textLabel.text = rowString; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + + return cell; +} + +// delete the row and the file +-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + NSUInteger row = [indexPath row]; + + NSString *schemeFile = [[NSString alloc] initWithFormat:@"%@/%@",SCHEMES_DIRECTORY(),[self.listOfSchemes objectAtIndex:row]]; + [[NSFileManager defaultManager] removeItemAtPath:schemeFile error:NULL]; + [schemeFile release]; + + [self.listOfSchemes removeObjectAtIndex:row]; + [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; +} + +-(BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; + if (![cell.textLabel.text isEqualToString:@"Default"]) + return YES; + else + return NO; +} + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + if (childController == nil) { + childController = [[SingleSchemeViewController alloc] initWithStyle:UITableViewStyleGrouped]; + } + + NSInteger row = [indexPath row]; + NSString *selectedSchemeFile = [self.listOfSchemes objectAtIndex:row]; + + // this must be set so childController can load the correct plist + childController.title = [selectedSchemeFile stringByDeletingPathExtension]; + [childController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; + + [self.navigationController pushViewController:childController animated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + if (childController.view.superview == nil ) + childController = nil; +} + +-(void) viewDidUnload { + self.listOfSchemes = nil; + childController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + + +-(void) dealloc { + [self.listOfSchemes release]; + [childController release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,30 @@ +// +// SchemeWeaponConfigViewController.h +// Hedgewars +// +// Created by Vittorio on 13/06/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface SchemeWeaponConfigViewController : UITableViewController { + NSArray *listOfSchemes; + NSArray *listOfWeapons; + + NSIndexPath *lastIndexPath_sc; + NSIndexPath *lastIndexPath_we; + + NSString *selectedScheme; + NSString *selectedWeapon; +} + +@property (nonatomic, retain) NSArray *listOfSchemes; +@property (nonatomic, retain) NSArray *listOfWeapons; +@property (nonatomic,retain) NSIndexPath *lastIndexPath_sc; +@property (nonatomic,retain) NSIndexPath *lastIndexPath_we; +@property (nonatomic,retain) NSString *selectedScheme; +@property (nonatomic,retain) NSString *selectedWeapon; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,160 @@ +// +// SchemeWeaponConfigViewController.m +// Hedgewars +// +// Created by Vittorio on 13/06/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SchemeWeaponConfigViewController.h" +#import "CommodityFunctions.h" + +@implementation SchemeWeaponConfigViewController +@synthesize listOfSchemes, listOfWeapons, lastIndexPath_sc, lastIndexPath_we, selectedScheme, selectedWeapon; + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + CGSize screenSize = [[UIScreen mainScreen] bounds].size; + self.view.frame = CGRectMake(0, 0, screenSize.height, screenSize.width - 44); +} + +-(void) viewWillAppear:(BOOL) animated { + [super viewWillAppear:animated]; + + NSArray *contentsOfDir = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:SCHEMES_DIRECTORY() error:NULL]; + self.listOfSchemes = contentsOfDir; + + contentsOfDir = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:WEAPONS_DIRECTORY() error:NULL]; + self.listOfWeapons = contentsOfDir; + + self.selectedScheme = @"Default.plist"; + self.selectedWeapon = @"Default.plist"; + + [self.tableView reloadData]; +} + + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 2; +} + + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + if (section == 0) + return [self.listOfSchemes count]; + else + return [self.listOfWeapons count]; +} + + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + NSInteger row = [indexPath row]; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + cell.accessoryType = UITableViewCellAccessoryNone; + if ([indexPath section] == 0) { + cell.textLabel.text = [[self.listOfSchemes objectAtIndex:row] stringByDeletingPathExtension]; + if ([[self.listOfSchemes objectAtIndex:row] isEqualToString:self.selectedScheme]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath_sc = indexPath; + } + } else { + cell.textLabel.text = [[self.listOfWeapons objectAtIndex:row] stringByDeletingPathExtension]; + if ([[self.listOfWeapons objectAtIndex:row] isEqualToString:self.selectedWeapon]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath_we = indexPath; + } + } + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSIndexPath *lastIndexPath; + if ([indexPath section] == 0) + lastIndexPath = self.lastIndexPath_sc; + else + lastIndexPath = self.lastIndexPath_we; + + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + //TODO: this code works only for a single section table + UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; + newCell.accessoryType = UITableViewCellAccessoryCheckmark; + UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:lastIndexPath]; + oldCell.accessoryType = UITableViewCellAccessoryNone; + + if ([indexPath section] == 0) { + self.lastIndexPath_sc = indexPath; + self.selectedScheme = [self.listOfSchemes objectAtIndex:newRow]; + } else { + self.lastIndexPath_we = indexPath; + self.selectedWeapon = [self.listOfWeapons objectAtIndex:newRow]; + } + + [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger) section { + if (section == 0) { + return NSLocalizedString(@"Schemes",@""); + } else { + return NSLocalizedString(@"Weapons",@"");; + } +} + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +-(void) viewDidUnload { + self.listOfSchemes = nil; + self.listOfWeapons = nil; + self.lastIndexPath_sc = nil; + self.lastIndexPath_we = nil; + self.selectedScheme = nil; + self.selectedWeapon = nil; + MSG_DIDUNLOAD(); +} + + +-(void) dealloc { + [listOfSchemes release]; + [listOfWeapons release]; + [lastIndexPath_sc release]; + [lastIndexPath_we release]; + [selectedScheme release]; + [selectedWeapon release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SingleSchemeViewController.h --- a/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,25 @@ +// +// SingleSchemeViewController.h +// Hedgewars +// +// Created by Vittorio on 23/05/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface SingleSchemeViewController : UITableViewController { + UITextField *textFieldBeingEdited; + NSMutableArray *schemeArray; + + NSArray *basicSettingList; + NSArray *gameModifierArray; +} + +@property (nonatomic, retain) UITextField *textFieldBeingEdited; +@property (nonatomic, retain) NSMutableArray *schemeArray; +@property (nonatomic, retain) NSArray *basicSettingList; +@property (nonatomic, retain) NSArray *gameModifierArray; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,321 @@ +// +// SingleSchemeViewController.m +// Hedgewars +// +// Created by Vittorio on 23/05/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SingleSchemeViewController.h" +#import +#import "CommodityFunctions.h" +#import "UIImageExtra.h" + +@implementation SingleSchemeViewController +@synthesize textFieldBeingEdited, schemeArray, basicSettingList, gameModifierArray; + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + NSArray *mods = [[NSArray alloc] initWithObjects: + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Fort Mode",@""),@"title", + NSLocalizedString(@"Defend your fort and destroy the opponents (two team colours max)",@""),@"description", + @"Forts",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Divide Team",@""),@"title", + NSLocalizedString(@"Teams will start on opposite sides of the terrain (two team colours max)",@""),@"description", + @"TeamsDivide",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Solid Land",@""),@"title", + NSLocalizedString(@"Land can not be destroyed",@""),@"description", + @"Solid",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Add Border",@""),@"title", + NSLocalizedString(@"Add an indestructable border around the terrain",@""),@"description", + @"Border",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Low Gravity",@""),@"title", + NSLocalizedString(@"Lower gravity",@""),@"description", + @"LowGravity",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Laser Sight",@""),@"title", + NSLocalizedString(@"Assisted aiming with laser sight",@""),@"description", + @"LaserSight",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Invulnerable",@""),@"title", + NSLocalizedString(@"All hogs have a personal forcefield",@""),@"description", + @"Invulnerable",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Add Mines",@""),@"title", + NSLocalizedString(@"Enable random mines",@""),@"description", + @"Mines",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Vampirism Mode",@""),@"title", + NSLocalizedString(@"Gain 80% of the damage you do back in health",@""),@"description", + @"Vampiric",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Karma Mode",@""),@"title", + NSLocalizedString(@"Share your opponents pain, share their damage",@""),@"description", + @"Karma",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Artillery Mode",@""),@"title", + NSLocalizedString(@"Your hogs are unable to move, test your aim",@""),@"description", + @"Artillery",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Random Order",@""),@"title", + NSLocalizedString(@"Order of play is random instead of in room order",@""),@"description", + @"RandomOrder",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"King Mode",@""),@"title", + NSLocalizedString(@"Play with a King. If he dies, your side loses",@""),@"description", + @"King",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys: NSLocalizedString(@"Place Hedgehogs",@""),@"title", + NSLocalizedString(@"Take turns placing your hedgehogs pre-game",@""),@"description", + @"PlaceHog",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Clan Shares Ammo",@""),@"title", + NSLocalizedString(@"Ammo is shared between all clan teams",@""),@"description", + @"SharedAmmo",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Disable Girders",@""),@"title", + NSLocalizedString(@"Disable girders when generating random maps",@""),@"description", + @"DisableGirders",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Disable Land Objects",@""),@"title", + NSLocalizedString(@"Disable land objects when generating maps",@""),@"description", + @"DisableLandObjects",@"image",nil], + nil]; + self.gameModifierArray = mods; + [mods release]; + + NSArray *basicSettings = [[NSArray alloc] initWithObjects: + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Damage Modifier",@""),@"title",@"Damage",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Turn Time",@""),@"title",@"Time",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Initial Health",@""),@"title",@"Health",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Sudden Death Timeout",@""),@"title",@"SuddenDeath",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Crate Drops",@""),@"title",@"Box",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Mines Time",@""),@"title",@"Time",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Mines Number",@""),@"title",@"Mine",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Dud Mines Probability",@""),@"title",@"Dud",@"image",nil], + [NSDictionary dictionaryWithObjectsAndKeys:NSLocalizedString(@"Explosives",@""),@"title",@"Damage",@"image",nil], + nil]; + self.basicSettingList = basicSettings; + [basicSettings release]; +} + +// load from file +-(void) viewWillAppear:(BOOL) animated { + [super viewWillAppear:animated]; + + NSString *schemeFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",SCHEMES_DIRECTORY(),self.title]; + NSMutableArray *scheme = [[NSMutableArray alloc] initWithContentsOfFile:schemeFile]; + self.schemeArray = scheme; + [scheme release]; + [schemeFile release]; + + [self.tableView reloadData]; +} + +// save to file +-(void) viewWillDisappear:(BOOL) animated { + [super viewWillDisappear:animated]; + + NSString *schemeFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",SCHEMES_DIRECTORY(),self.title]; + [self.schemeArray writeToFile:schemeFile atomically:YES]; + [schemeFile release]; +} + +#pragma mark - +#pragma mark textfield methods +-(void) cancel:(id) sender { + if (textFieldBeingEdited != nil) + [self.textFieldBeingEdited resignFirstResponder]; +} + +// set the new value +-(BOOL) save:(id) sender { + if (textFieldBeingEdited != nil) { + [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@.plist",SCHEMES_DIRECTORY(),self.title] error:NULL]; + self.title = self.textFieldBeingEdited.text; + [self.schemeArray writeToFile:[NSString stringWithFormat:@"%@/%@.plist",SCHEMES_DIRECTORY(),self.title] atomically:YES]; + [self.textFieldBeingEdited resignFirstResponder]; + return YES; + } + return NO; +} + +// the textfield is being modified, update the navigation controller +-(void) textFieldDidBeginEditing:(UITextField *)aTextField{ + self.textFieldBeingEdited = aTextField; + + UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel",@"from schemes table") + style:UIBarButtonItemStylePlain + target:self + action:@selector(cancel:)]; + self.navigationItem.leftBarButtonItem = cancelButton; + [cancelButton release]; + + UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Save",@"from schemes table") + style:UIBarButtonItemStyleDone + target:self + action:@selector(save:)]; + self.navigationItem.rightBarButtonItem = saveButton; + [saveButton release]; +} + +// the textfield has been modified, check for empty strings and restore original navigation bar +-(void) textFieldDidEndEditing:(UITextField *)aTextField{ + if ([textFieldBeingEdited.text length] == 0) + textFieldBeingEdited.text = [NSString stringWithFormat:@"New Scheme"]; + + self.textFieldBeingEdited = nil; + self.navigationItem.rightBarButtonItem = self.navigationItem.backBarButtonItem; + self.navigationItem.leftBarButtonItem = nil; +} + +// limit the size of the field to 64 characters like in original frontend +-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + int limit = 64; + return !([textField.text length] > limit && [string length] > range.length); +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 3; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + switch (section) { + case 0: + return 1; + break; + case 1: + return [self.basicSettingList count]; + break; + case 2: + return [self.gameModifierArray count]; + default: + break; + } + return 0; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier0 = @"Cell0"; + static NSString *CellIdentifier1 = @"Cell1"; + static NSString *CellIdentifier2 = @"Cell2"; + + UITableViewCell *cell = nil; + NSInteger row = [indexPath row]; + + switch ([indexPath section]) { + case 0: + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier0]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CellIdentifier0] autorelease]; + // create a uitextfield for each row, expand it to take the maximum size + UITextField *aTextField = [[UITextField alloc] + initWithFrame:CGRectMake(5, 12, (cell.frame.size.width + cell.frame.size.width/3) - 42, 25)]; + aTextField.clearsOnBeginEditing = NO; + aTextField.returnKeyType = UIReturnKeyDone; + aTextField.adjustsFontSizeToFitWidth = YES; + aTextField.delegate = self; + aTextField.tag = [indexPath row]; + aTextField.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2]; + aTextField.clearButtonMode = UITextFieldViewModeWhileEditing; + [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit]; + [cell.contentView addSubview:aTextField]; + [aTextField release]; + } + + for (UIView *oneView in cell.contentView.subviews) { + if ([oneView isMemberOfClass:[UITextField class]]) { + // we find the uitextfied and we'll use its tag to understand which one is being edited + UITextField *textFieldFound = (UITextField *)oneView; + textFieldFound.text = self.title; + } + } + cell.detailTextLabel.text = nil; + cell.imageView.image = nil; + break; + case 1: + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CellIdentifier1] autorelease]; + } + + UIImage *img = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/icon%@.png",BTN_DIRECTORY(),[[self.basicSettingList objectAtIndex:row] objectForKey:@"image"]]]; + cell.imageView.image = [img scaleToSize:CGSizeMake(40, 40)]; + [img release]; + cell.textLabel.text = [[self.basicSettingList objectAtIndex:row] objectForKey:@"title"]; + cell.detailTextLabel.text = nil; + break; + case 2: + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle + reuseIdentifier:CellIdentifier2] autorelease]; + UISwitch *onOff = [[UISwitch alloc] init]; + onOff.tag = row; + [onOff addTarget:self action:@selector(toggleSwitch:) forControlEvents:UIControlEventValueChanged]; + cell.accessoryView = onOff; + [onOff release]; + } + + UIImage *image = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/btn%@.png",BTN_DIRECTORY(),[[self.gameModifierArray objectAtIndex:row] objectForKey:@"image"]]]; + cell.imageView.image = image; + [image release]; + [cell.imageView.layer setCornerRadius:7.0f]; + [cell.imageView.layer setMasksToBounds:YES]; + cell.textLabel.text = [[self.gameModifierArray objectAtIndex:row] objectForKey:@"title"]; + cell.detailTextLabel.text = [[self.gameModifierArray objectAtIndex:row] objectForKey:@"description"]; + [(UISwitch *)cell.accessoryView setOn:[[self.schemeArray objectAtIndex:row] boolValue] animated:NO]; + } + + return cell; +} + +-(void) toggleSwitch:(id) sender { + UISwitch *theSwitch = (UISwitch *)sender; + [self.schemeArray replaceObjectAtIndex:theSwitch.tag withObject:[NSNumber numberWithBool:theSwitch.on]]; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + + if ([indexPath section] == 0) { + UITableViewCell *cell = [aTableView cellForRowAtIndexPath:indexPath]; + for (UIView *oneView in cell.contentView.subviews) { + if ([oneView isMemberOfClass:[UITextField class]]) { + textFieldBeingEdited = (UITextField *)oneView; + [textFieldBeingEdited becomeFirstResponder]; + } + } + } + [aTableView deselectRowAtIndexPath:indexPath animated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +-(void) viewDidUnload { + self.textFieldBeingEdited = nil; + self.schemeArray = nil; + self.basicSettingList = nil; + self.gameModifierArray = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [textFieldBeingEdited release]; + [schemeArray release]; + [basicSettingList release]; + [gameModifierArray release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SingleTeamViewController.h --- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,44 @@ +// +// SingleTeamViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class HogHatViewController; +@class GravesViewController; +@class VoicesViewController; +@class FortsViewController; +@class FlagsViewController; +@class LevelViewController; +@interface SingleTeamViewController : UITableViewController { + NSMutableDictionary *teamDictionary; + + UITextField *textFieldBeingEdited; + NSString *teamName; + UIImage *normalHogSprite; + + NSArray *secondaryItems; + BOOL isWriteNeeded; + + HogHatViewController *hogHatViewController; + GravesViewController *gravesViewController; + VoicesViewController *voicesViewController; + FortsViewController *fortsViewController; + FlagsViewController *flagsViewController; + LevelViewController *levelViewController; +} + +@property (nonatomic,retain) NSMutableDictionary *teamDictionary; +@property (nonatomic,retain) UITextField *textFieldBeingEdited; +@property (nonatomic,retain) NSString *teamName; +@property (nonatomic,retain) UIImage *normalHogSprite; +@property (nonatomic,retain) NSArray *secondaryItems; + +-(void) writeFile; +-(void) setWriteNeeded; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SingleTeamViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,453 @@ +// +// SingleTeamViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SingleTeamViewController.h" +#import "HogHatViewController.h" +#import "GravesViewController.h" +#import "VoicesViewController.h" +#import "FortsViewController.h" +#import "FlagsViewController.h" +#import "LevelViewController.h" +#import "CommodityFunctions.h" +#import "UIImageExtra.h" + +#define TEAMNAME_TAG 1234 + +@implementation SingleTeamViewController +@synthesize teamDictionary, normalHogSprite, secondaryItems, textFieldBeingEdited, teamName; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark textfield methods +-(void) cancel:(id) sender { + if (textFieldBeingEdited != nil) + [self.textFieldBeingEdited resignFirstResponder]; +} + +// set the new value +-(BOOL) save:(id) sender { + NSInteger index = textFieldBeingEdited.tag; + + if (textFieldBeingEdited != nil) { + if (TEAMNAME_TAG == index) { + [self.teamDictionary setObject:textFieldBeingEdited.text forKey:@"teamname"]; + } else { + //replace the old value with the new one + NSMutableDictionary *hog = [[teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:index]; + [hog setObject:textFieldBeingEdited.text forKey:@"hogname"]; + } + + isWriteNeeded = YES; + [self.textFieldBeingEdited resignFirstResponder]; + return YES; + } + return NO; +} + +// the textfield is being modified, update the navigation controller +-(void) textFieldDidBeginEditing:(UITextField *)aTextField{ + self.textFieldBeingEdited = aTextField; + + UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel",@"from the hog name table") + style:UIBarButtonItemStylePlain + target:self + action:@selector(cancel:)]; + self.navigationItem.leftBarButtonItem = cancelButton; + [cancelButton release]; + + UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Save",@"from the hog name table") + style:UIBarButtonItemStyleDone + target:self + action:@selector(save:)]; + self.navigationItem.rightBarButtonItem = saveButton; + [saveButton release]; +} + +// the textfield has been modified, check for empty strings and restore original navigation bar +-(void) textFieldDidEndEditing:(UITextField *)aTextField{ + if ([textFieldBeingEdited.text length] == 0) + textFieldBeingEdited.text = [NSString stringWithFormat:@"hedgehog %d",textFieldBeingEdited.tag]; + + self.textFieldBeingEdited = nil; + self.navigationItem.rightBarButtonItem = self.navigationItem.backBarButtonItem; + self.navigationItem.leftBarButtonItem = nil; +} + +// limit the size of the field to 64 characters like in original frontend +-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + int limit = 64; + return !([textField.text length] > limit && [string length] > range.length); +} + + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + // labels for the entries + NSArray *array = [[NSArray alloc] initWithObjects: + NSLocalizedString(@"Grave",@""), + NSLocalizedString(@"Voice",@""), + NSLocalizedString(@"Fort",@""), + NSLocalizedString(@"Flag",@""), + NSLocalizedString(@"Level",@""),nil]; + self.secondaryItems = array; + [array release]; + + // load the base hog image, drawing will occure in cellForRow... + NSString *normalHogFile = [[NSString alloc] initWithFormat:@"%@/Hedgehog.png",GRAPHICS_DIRECTORY()]; + UIImage *hogSprite = [[UIImage alloc] initWithContentsOfFile:normalHogFile andCutAt:CGRectMake(96, 0, 32, 32)]; + [normalHogFile release]; + self.normalHogSprite = hogSprite; + [hogSprite release]; + + // listen if any childController modifies the plist and write it if needed + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setWriteNeeded) name:@"setWriteNeedTeams" object:nil]; + isWriteNeeded = NO; +} + +-(void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // load data about the team and write if there has been a change + if (isWriteNeeded) + [self writeFile]; + + NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),self.title]; + NSMutableDictionary *teamDict = [[NSMutableDictionary alloc] initWithContentsOfFile:teamFile]; + self.teamDictionary = teamDict; + [teamDict release]; + [teamFile release]; + + self.teamName = self.title; + + [self.tableView reloadData]; +} + +// write on file if there has been a change +-(void) viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + // end the editing of the current field + if (textFieldBeingEdited != nil) { + [self save:nil]; + } + + if (isWriteNeeded) + [self writeFile]; +} + +#pragma mark - +// needed by other classes to warn about a user change +-(void) setWriteNeeded { + isWriteNeeded = YES; +} + +-(void) writeFile { + NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),self.title]; + + NSString *newTeamName = [self.teamDictionary objectForKey:@"teamname"]; + if (![newTeamName isEqualToString:self.teamName]) { + //delete old + [[NSFileManager defaultManager] removeItemAtPath:teamFile error:NULL]; + [teamFile release]; + self.title = newTeamName; + self.teamName = newTeamName; + teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),newTeamName]; + } + + [self.teamDictionary writeToFile:teamFile atomically:YES]; + NSLog(@"writing: %@",teamDictionary); + isWriteNeeded = NO; + [teamFile release]; +} + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 3; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + NSInteger rows = 0; + switch (section) { + case 0: // team name + rows = 1; + break; + case 1: // team members + rows = MAX_HOGS; + break; + case 2: // team details + rows = [self.secondaryItems count]; + break; + default: + break; + } + return rows; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier0 = @"Cell0"; + static NSString *CellIdentifier1 = @"Cell1"; + static NSString *CellIdentifier2 = @"Cell2"; + + NSArray *hogArray; + UITableViewCell *cell = nil; + NSInteger row = [indexPath row]; + UIImage *accessoryImage; + + switch ([indexPath section]) { + case 0: + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier0]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CellIdentifier0] autorelease]; + // create a uitextfield for each row, expand it to take the maximum size + UITextField *aTextField = [[UITextField alloc] + initWithFrame:CGRectMake(5, 12, (cell.frame.size.width + cell.frame.size.width/3) - 42, 25)]; + aTextField.clearsOnBeginEditing = NO; + aTextField.returnKeyType = UIReturnKeyDone; + aTextField.adjustsFontSizeToFitWidth = YES; + aTextField.delegate = self; + aTextField.tag = [indexPath row]; + aTextField.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2]; + aTextField.clearButtonMode = UITextFieldViewModeWhileEditing; + [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit]; + [cell.contentView addSubview:aTextField]; + [aTextField release]; + } + + cell.imageView.image = nil; + cell.accessoryType = UITableViewCellAccessoryNone; + for (UIView *oneView in cell.contentView.subviews) { + if ([oneView isMemberOfClass:[UITextField class]]) { + // we find the uitextfied and we'll use its tag to understand which one is being edited + UITextField *textFieldFound = (UITextField *)oneView; + textFieldFound.text = [self.teamDictionary objectForKey:@"teamname"]; + textFieldFound.tag = TEAMNAME_TAG; + } + } + break; + case 1: + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CellIdentifier1] autorelease]; + + // create a uitextfield for each row, expand it to take the maximum size + UITextField *aTextField = [[UITextField alloc] + initWithFrame:CGRectMake(42, 12, (cell.frame.size.width + cell.frame.size.width/3) - 42, 25)]; + aTextField.clearsOnBeginEditing = NO; + aTextField.returnKeyType = UIReturnKeyDone; + aTextField.adjustsFontSizeToFitWidth = YES; + aTextField.delegate = self; + aTextField.tag = [indexPath row]; + aTextField.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2]; + aTextField.clearButtonMode = UITextFieldViewModeWhileEditing; + [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit]; + [cell.contentView addSubview:aTextField]; + [aTextField release]; + } + + hogArray = [self.teamDictionary objectForKey:@"hedgehogs"]; + + NSString *hatFile = [[NSString alloc] initWithFormat:@"%@/%@.png", HATS_DIRECTORY(), [[hogArray objectAtIndex:row] objectForKey:@"hat"]]; + UIImage *hatSprite = [[UIImage alloc] initWithContentsOfFile: hatFile andCutAt:CGRectMake(0, 0, 32, 32)]; + [hatFile release]; + cell.imageView.image = [self.normalHogSprite mergeWith:hatSprite atPoint:CGPointMake(0, -5)]; + [hatSprite release]; + + for (UIView *oneView in cell.contentView.subviews) { + if ([oneView isMemberOfClass:[UITextField class]]) { + // we find the uitextfied and we'll use its tag to understand which one is being edited + UITextField *textFieldFound = (UITextField *)oneView; + textFieldFound.text = [[hogArray objectAtIndex:row] objectForKey:@"hogname"]; + } + } + + cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; + break; + case 2: + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CellIdentifier2] autorelease]; + } + + cell.textLabel.text = [self.secondaryItems objectAtIndex:row]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + switch (row) { + case 0: // grave + accessoryImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.png", + GRAVES_DIRECTORY(),[teamDictionary objectForKey:@"grave"]] + andCutAt:CGRectMake(0,0,32,32)]; + cell.imageView.image = accessoryImage; + [accessoryImage release]; + break; + case 2: // fort + accessoryImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@L.png", + FORTS_DIRECTORY(),[teamDictionary objectForKey:@"fort"]]]; + cell.imageView.image = [accessoryImage scaleToSize:CGSizeMake(42, 42)]; + [accessoryImage release]; + break; + + case 3: // flags + accessoryImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.png", + FLAGS_DIRECTORY(),[teamDictionary objectForKey:@"flag"]]]; + cell.imageView.image = accessoryImage; + [accessoryImage release]; + break; + case 4: // level + accessoryImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%d.png", + BOTLEVELS_DIRECTORY(),[[[[teamDictionary objectForKey:@"hedgehogs"] + objectAtIndex:0] objectForKey:@"level"] + intValue]]]; + cell.imageView.image = accessoryImage; + [accessoryImage release]; + break; + default: + cell.imageView.image = nil; + break; + } + break; + } + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSInteger row = [indexPath row]; + NSInteger section = [indexPath section]; + UITableViewController *nextController = nil; + UITableViewCell *cell; + + if (2 == section) { + switch (row) { + case 0: // grave + if (nil == gravesViewController) + gravesViewController = [[GravesViewController alloc] initWithStyle:UITableViewStyleGrouped]; + + nextController = gravesViewController; + break; + case 1: // voice + if (nil == voicesViewController) + voicesViewController = [[VoicesViewController alloc] initWithStyle:UITableViewStyleGrouped]; + + nextController = voicesViewController; + break; + case 2: // fort + if (nil == fortsViewController) + fortsViewController = [[FortsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + + nextController = fortsViewController; + break; + case 3: // flag + if (nil == flagsViewController) + flagsViewController = [[FlagsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + + nextController = flagsViewController; + break; + case 4: // level + if (nil == levelViewController) + levelViewController = [[LevelViewController alloc] initWithStyle:UITableViewStyleGrouped]; + + nextController = levelViewController; + break; + } + + nextController.title = [secondaryItems objectAtIndex:row]; + [nextController setTeamDictionary:teamDictionary]; + [self.navigationController pushViewController:nextController animated:YES]; + } else { + cell = [aTableView cellForRowAtIndexPath:indexPath]; + for (UIView *oneView in cell.contentView.subviews) { + if ([oneView isMemberOfClass:[UITextField class]]) { + textFieldBeingEdited = (UITextField *)oneView; + [textFieldBeingEdited becomeFirstResponder]; + } + } + [aTableView deselectRowAtIndexPath:indexPath animated:NO]; + } + +} + +// action to perform when you want to change a hog hat +-(void) tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { + if (nil == hogHatViewController) { + hogHatViewController = [[HogHatViewController alloc] initWithStyle:UITableViewStyleGrouped]; + } + + // cache the dictionary file of the team, so that other controllers can modify it + hogHatViewController.teamDictionary = self.teamDictionary; + hogHatViewController.selectedHog = [indexPath row]; + + [self.navigationController pushViewController:hogHatViewController animated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. + if (hogHatViewController.view.superview == nil) + hogHatViewController = nil; + if (gravesViewController.view.superview == nil) + gravesViewController = nil; + if (voicesViewController.view.superview == nil) + voicesViewController = nil; + if (fortsViewController.view.superview == nil) + fortsViewController = nil; + if (flagsViewController.view.superview == nil) + flagsViewController = nil; + if (levelViewController.view.superview == nil) + levelViewController = nil; +} + +-(void) viewDidUnload { + self.teamDictionary = nil; + self.textFieldBeingEdited = nil; + self.teamName = nil; + self.normalHogSprite = nil; + self.secondaryItems = nil; + hogHatViewController = nil; + flagsViewController = nil; + fortsViewController = nil; + gravesViewController = nil; + levelViewController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [teamDictionary release]; + [textFieldBeingEdited release]; + [teamName release]; + [normalHogSprite release]; + [secondaryItems release]; + [hogHatViewController release]; + [fortsViewController release]; + [gravesViewController release]; + [flagsViewController release]; + [levelViewController release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SingleWeaponViewController.h --- a/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,16 @@ +// +// SingleWeaponViewController.h +// Hedgewars +// +// Created by Vittorio on 19/06/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface SingleWeaponViewController : UITableViewController { + +} + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,180 @@ +// +// SingleWeaponViewController.m +// Hedgewars +// +// Created by Vittorio on 19/06/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SingleWeaponViewController.h" + + +@implementation SingleWeaponViewController + + +#pragma mark - +#pragma mark Initialization + +/* +- (id)initWithStyle:(UITableViewStyle)style { + // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. + if ((self = [super initWithStyle:style])) { + } + return self; +} +*/ + + +#pragma mark - +#pragma mark View lifecycle + +/* +- (void)viewDidLoad { + [super viewDidLoad]; + + // Uncomment the following line to preserve selection between presentations. + self.clearsSelectionOnViewWillAppear = NO; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem; +} +*/ + +/* +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; +} +*/ +/* +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; +} +*/ +/* +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; +} +*/ +/* +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; +} +*/ +/* +// Override to allow orientations other than the default portrait orientation. +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + // Return YES for supported orientations + return (interfaceOrientation == UIInterfaceOrientationPortrait); +} +*/ + + +#pragma mark - +#pragma mark Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + // Return the number of sections. + return 0; +} + + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + // Return the number of rows in the section. + return 0; +} + + +// Customize the appearance of table view cells. +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + // Configure the cell... + + return cell; +} + + +/* +// Override to support conditional editing of the table view. +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the specified item to be editable. + return YES; +} +*/ + + +/* +// Override to support editing the table view. +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + + if (editingStyle == UITableViewCellEditingStyleDelete) { + // Delete the row from the data source + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; + } + else if (editingStyle == UITableViewCellEditingStyleInsert) { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } +} +*/ + + +/* +// Override to support rearranging the table view. +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { +} +*/ + + +/* +// Override to support conditional rearranging of the table view. +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the item to be re-orderable. + return YES; +} +*/ + + +#pragma mark - +#pragma mark Table view delegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + // Navigation logic may go here. Create and push another view controller. + /* + <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil]; + // ... + // Pass the selected object to the new view controller. + [self.navigationController pushViewController:detailViewController animated:YES]; + [detailViewController release]; + */ +} + + +#pragma mark - +#pragma mark Memory management + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +- (void)viewDidUnload { + // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand. + // For example: self.myOutlet = nil; +} + + +- (void)dealloc { + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SplitViewRootController.h --- a/project_files/HedgewarsMobile/Classes/SplitViewRootController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SplitViewRootController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,16 @@ +// +// SplitViewRootController.h +// HedgewarsMobile +// +// Created by Vittorio on 27/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + +@class DetailViewController; +@interface SplitViewRootController: UIViewController { + DetailViewController *detailViewController; +} + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SplitViewRootController.m --- a/project_files/HedgewarsMobile/Classes/SplitViewRootController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SplitViewRootController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,103 @@ + // +// SplitViewRootController.m +// HedgewarsMobile +// +// Created by Vittorio on 27/03/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SplitViewRootController.h" +#import "MasterViewController.h" +#import "DetailViewController.h" +#import "CommodityFunctions.h" + +@implementation SplitViewRootController + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Release any cached data, images, etc that aren't in use. + if (detailViewController.view.superview == nil) + detailViewController = nil; + MSG_MEMCLEAN(); +} + +// load the view programmatically; we need a splitViewController that handles a MasterViewController +// (which is just a UITableViewController) and a DetailViewController where we present options +-(void) viewDidLoad { + detailViewController = [[DetailViewController alloc] initWithStyle:UITableViewStyleGrouped]; + UINavigationController *detailedNavController = [[UINavigationController alloc] initWithRootViewController:detailViewController]; + [detailViewController release]; + + CGRect rect = [[UIScreen mainScreen] bounds]; + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + self.view.frame = CGRectMake(0, 0, rect.size.height, rect.size.width); + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + UISplitViewController *splitViewRootController = [[UISplitViewController alloc] init]; + //splitViewRootController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + splitViewRootController.view.frame = CGRectMake(0, 0, rect.size.height, rect.size.width); + + MasterViewController *masterViewController = [[MasterViewController alloc] initWithStyle:UITableViewStylePlain]; + UINavigationController *mainNavController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; + [masterViewController release]; + + splitViewRootController.delegate = detailViewController; + masterViewController.detailViewController = detailViewController; + splitViewRootController.viewControllers = [NSArray arrayWithObjects: mainNavController, detailedNavController, nil]; + [mainNavController release]; + [detailedNavController release]; + + // add view to main controller + [self.view addSubview:splitViewRootController.view]; + } else { + [self.view addSubview:detailedNavController.view]; + } + + [super viewDidLoad]; +} + +-(void) viewDidUnload { + detailViewController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [detailViewController release]; + [super dealloc]; +} +-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{ + [detailViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; +} + +#pragma mark - +#pragma mark additional methods as we're using a UINavigationController programmatically +// see http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/ +-(void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [detailViewController.navigationController viewWillAppear:animated]; +} + +-(void) viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [detailViewController.navigationController viewWillDisappear:animated]; +} + +-(void) viewDidAppear:(BOOL)animated { + [super viewDidLoad]; + [detailViewController.navigationController viewDidAppear:animated]; +} + +-(void) viewDidDisappear:(BOOL)animated { + [super viewDidUnload]; + [detailViewController.navigationController viewDidDisappear:animated]; +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SquareButtonView.h --- a/project_files/HedgewarsMobile/Classes/SquareButtonView.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SquareButtonView.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,26 @@ +// +// HogButtonView.h +// HedgewarsMobile +// +// Created by Vittorio on 20/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface SquareButtonView : UIButton { + NSInteger colorIndex; + NSUInteger selectedColor; + NSArray *colorArray; + NSMutableDictionary *ownerDictionary; +} + +@property (nonatomic,retain) NSArray *colorArray; +@property (nonatomic) NSUInteger selectedColor; +@property (nonatomic,retain) NSMutableDictionary *ownerDictionary; + +-(void) nextColor; +-(void) selectColor:(NSUInteger) color; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/SquareButtonView.m --- a/project_files/HedgewarsMobile/Classes/SquareButtonView.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/SquareButtonView.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,81 @@ +// +// HogButtonView.m +// HedgewarsMobile +// +// Created by Vittorio on 20/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "SquareButtonView.h" +#import +#import "CommodityFunctions.h" +#import "UIImageExtra.h" + +@implementation SquareButtonView +@synthesize colorArray, selectedColor, ownerDictionary; + +-(id) initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + colorIndex = -1; + selectedColor = 0; + + // list of allowed colors + NSArray *colors = [[NSArray alloc] initWithObjects: [NSNumber numberWithUnsignedInt:4421353], // bluette + [NSNumber numberWithUnsignedInt:4100897], // greeeen + [NSNumber numberWithUnsignedInt:10632635], // violett + [NSNumber numberWithUnsignedInt:16749353], // oranngy + [NSNumber numberWithUnsignedInt:14483456], // reddish + [NSNumber numberWithUnsignedInt:7566195], // graaaay + nil]; + self.colorArray = colors; + [colors release]; + + // set the color to the first available one + [self nextColor]; + + // this makes the button round and nice with a border + [self.layer setCornerRadius:7.0f]; + [self.layer setMasksToBounds:YES]; + [self.layer setBorderWidth:2]; + + // this changes the color at button press + [self addTarget:self action:@selector(nextColor) forControlEvents:UIControlEventTouchUpInside]; + } + return self; +} + +-(void) nextColor { + colorIndex++; + + if (colorIndex >= [colorArray count]) + colorIndex = 0; + + NSUInteger color = [[self.colorArray objectAtIndex:colorIndex] unsignedIntValue]; + self.backgroundColor = [UIColor colorWithRed:((color & 0x00FF0000) >> 16)/255.0f + green:((color & 0x0000FF00) >> 8)/255.0f + blue: (color & 0x000000FF)/255.0f + alpha:1.0f]; + + [ownerDictionary setObject:[NSNumber numberWithInt:color] forKey:@"color"]; +} + +-(void) selectColor:(NSUInteger) color { + if (color != selectedColor) { + selectedColor = color; + colorIndex = [colorArray indexOfObject:[NSNumber numberWithUnsignedInt:color]]; + + self.backgroundColor = [UIColor colorWithRed:((color & 0x00FF0000) >> 16)/255.0f + green:((color & 0x0000FF00) >> 8)/255.0f + blue: (color & 0x000000FF)/255.0f + alpha:1.0f]; + } +} + +-(void) dealloc { + [ownerDictionary release]; + [colorArray release]; + [super dealloc]; +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/TeamConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/TeamConfigViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/TeamConfigViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,20 @@ +// +// TeamConfigViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 20/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface TeamConfigViewController : UITableViewController { + NSMutableArray *listOfTeams; + NSMutableArray *listOfSelectedTeams; +} + +@property (nonatomic, retain) NSMutableArray *listOfTeams; +@property (nonatomic, retain) NSMutableArray *listOfSelectedTeams; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/TeamConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,174 @@ +// +// TeamConfigViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 20/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "TeamConfigViewController.h" +#import "CommodityFunctions.h" +#import "HogButtonView.h" +#import "SquareButtonView.h" + +@implementation TeamConfigViewController +@synthesize listOfTeams, listOfSelectedTeams; + +#define NUMBERBUTTON_TAG 123456 +#define SQUAREBUTTON_TAG 654321 +#define LABEL_TAG 456123 + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + CGSize screenSize = [[UIScreen mainScreen] bounds].size; + self.view.frame = CGRectMake(0, 0, screenSize.height, screenSize.width - 44); +} + +-(void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // integer representation of various color (defined in SquareButtonView) + NSUInteger colors[6] = { 4421353, 4100897, 10632635, 16749353, 14483456, 7566195 }; + NSArray *contentsOfDir = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:TEAMS_DIRECTORY() error:NULL]; + NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[contentsOfDir count]]; + for (int i = 0; i < [contentsOfDir count]; i++) { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + [contentsOfDir objectAtIndex:i],@"team", + [NSNumber numberWithInt:4],@"number", + [NSNumber numberWithInt:colors[i%6]],@"color",nil]; + [array addObject:dict]; + [dict release]; + } + self.listOfTeams = array; + [array release]; + + NSMutableArray *emptyArray = [[NSMutableArray alloc] initWithObjects:nil]; + self.listOfSelectedTeams = emptyArray; + [emptyArray release]; + + [self.tableView reloadData]; +} + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 2; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + if (section == 0) + return [listOfSelectedTeams count] ; + else + return [listOfTeams count]; +} + +-(NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section { + if (section == 0) + return NSLocalizedString(@"Playing Teams",@""); + else + return NSLocalizedString(@"Available Teams",@""); +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier0 = @"Cell0"; + static NSString *CellIdentifier1 = @"Cell1"; + NSInteger section = [indexPath section]; + UITableViewCell *cell; + + if (section == 0) { + cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier0]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier0] autorelease]; + + UIButton *numberButton = [[HogButtonView alloc] initWithFrame:CGRectMake(12, 5, 88, 32)]; + numberButton.tag = NUMBERBUTTON_TAG; + [cell addSubview:numberButton]; + [numberButton release]; + + SquareButtonView *squareButton = [[SquareButtonView alloc] initWithFrame:CGRectMake(12+88+7, 5, 36, 36)]; + squareButton.tag = SQUAREBUTTON_TAG; + [cell addSubview:squareButton]; + [squareButton release]; + + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(12+88+7+36+7, 10, 250, 25)]; + label.textAlignment = UITextAlignmentLeft; + label.backgroundColor = [UIColor clearColor]; + label.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2]; + label.tag = LABEL_TAG; + [cell.contentView addSubview:label]; + [label release]; + } + + NSMutableDictionary *selectedRow = [listOfSelectedTeams objectAtIndex:[indexPath row]]; + + UILabel *cellLabel = (UILabel *)[cell viewWithTag:LABEL_TAG]; + cellLabel.text = [[selectedRow objectForKey:@"team"] stringByDeletingPathExtension]; + + HogButtonView *numberButton = (HogButtonView *)[cell viewWithTag:NUMBERBUTTON_TAG]; + [numberButton drawManyHogs:[[selectedRow objectForKey:@"number"] intValue]]; + numberButton.ownerDictionary = selectedRow; + + SquareButtonView *squareButton = (SquareButtonView *)[cell viewWithTag:SQUAREBUTTON_TAG]; + [squareButton selectColor:[[selectedRow objectForKey:@"color"] intValue]]; + squareButton.ownerDictionary = selectedRow; + } else { + cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier1]; + if (cell == nil) + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease]; + + cell.textLabel.text = [[[listOfTeams objectAtIndex:[indexPath row]] objectForKey:@"team"] stringByDeletingPathExtension]; + } + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSInteger row = [indexPath row]; + NSInteger section = [indexPath section]; + + if (section == 0) { + [self.listOfTeams addObject:[self.listOfSelectedTeams objectAtIndex:row]]; + [self.listOfSelectedTeams removeObjectAtIndex:row]; + } else { + [self.listOfSelectedTeams addObject:[self.listOfTeams objectAtIndex:row]]; + [self.listOfTeams removeObjectAtIndex:row]; + } + [aTableView reloadData]; +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +-(void) viewDidUnload { + self.listOfTeams = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + + +-(void) dealloc { + [self.listOfTeams release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,19 @@ +// +// TeamSettingsViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +@class SingleTeamViewController; + +@interface TeamSettingsViewController : UITableViewController { + NSMutableArray *listOfTeams; + SingleTeamViewController *childController; +} + +@property (nonatomic, retain) NSMutableArray *listOfTeams; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,167 @@ +// +// TeamSettingsViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "TeamSettingsViewController.h" +#import "SingleTeamViewController.h" +#import "CommodityFunctions.h" + +@implementation TeamSettingsViewController +@synthesize listOfTeams; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +// add an edit button +-(void) viewDidLoad { + [super viewDidLoad]; + + UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Edit",@"from the team panel") + style:UIBarButtonItemStyleBordered + target:self + action:@selector(toggleEdit:)]; + self.navigationItem.rightBarButtonItem = editButton; + [editButton release]; +} + +// load the list of teams in the teams directory +-(void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + NSArray *contentsOfDir = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:TEAMS_DIRECTORY() error:NULL]; + NSMutableArray *array = [[NSMutableArray alloc] initWithArray:contentsOfDir copyItems:YES]; + self.listOfTeams = array; + [array release]; + + [self.tableView reloadData]; +} + +// modifies the navigation bar to add the "Add" and "Done" buttons +-(void) toggleEdit:(id) sender { + BOOL isEditing = self.tableView.editing; + [self.tableView setEditing:!isEditing animated:YES]; + + if (isEditing) { + [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Edit",@"from the team panel")]; + [self.navigationItem.rightBarButtonItem setStyle: UIBarButtonItemStyleBordered]; + self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem; + } else { + [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Done",@"from the team panel")]; + [self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone]; + UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Add",@"from the team panel") + style:UIBarButtonItemStyleBordered + target:self + action:@selector(addTeam:)]; + self.navigationItem.leftBarButtonItem = addButton; + [addButton release]; + } +} + +// add a team file with default values and updates the table +-(void) addTeam:(id) sender { + NSString *fileName = [[NSString alloc] initWithFormat:@"Default Team %u.plist", [self.listOfTeams count]]; + + createTeamNamed([fileName stringByDeletingPathExtension]); + + [self.listOfTeams addObject:fileName]; + [fileName release]; + + // order the array alphabetically, so teams will keep their position + [self.listOfTeams sortUsingSelector:@selector(compare:)]; + + [self.tableView reloadData]; +} + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.listOfTeams count]; +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + NSUInteger row = [indexPath row]; + NSString *rowString = [[self.listOfTeams objectAtIndex:row] stringByDeletingPathExtension]; + cell.textLabel.text = rowString; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + + return cell; +} + +// delete the row and the file +-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + NSUInteger row = [indexPath row]; + + NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@",TEAMS_DIRECTORY(),[self.listOfTeams objectAtIndex:row]]; + [[NSFileManager defaultManager] removeItemAtPath:teamFile error:NULL]; + [teamFile release]; + + [self.listOfTeams removeObjectAtIndex:row]; + [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + if (childController == nil) { + childController = [[SingleTeamViewController alloc] initWithStyle:UITableViewStyleGrouped]; + } + + NSInteger row = [indexPath row]; + NSString *selectedTeamFile = [listOfTeams objectAtIndex:row]; + + // this must be set so childController can load the correct plist + childController.title = [selectedTeamFile stringByDeletingPathExtension]; + [childController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; + + [self.navigationController pushViewController:childController animated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. + if (childController.view.superview == nil ) + childController = nil; +} + +-(void) viewDidUnload { + self.listOfTeams = nil; + childController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [self.listOfTeams release]; + [childController release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/UIImageExtra.h --- a/project_files/HedgewarsMobile/Classes/UIImageExtra.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/UIImageExtra.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,22 @@ +// +// UIImageExtra.h +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface UIImage (extra) + +-(UIImage *)scaleToSize:(CGSize) size; +-(UIImage *)mergeWith:(UIImage *)secondImage atPoint:(CGPoint) secondImagePoint; +-(UIImage *)mergeWith:(UIImage *)secondImage atPoint:(CGPoint) secondImagePoint atSize:(CGSize) resultingSize; +-(id) initWithContentsOfFile:(NSString *)path andCutAt:(CGRect) rect; +-(UIImage *)convertToGrayScale; +-(UIImage *)maskImageWith:(UIImage *)maskImage; +-(UIImage *)makeRoundCornersOfSize:(CGSize) sizewh; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/UIImageExtra.m --- a/project_files/HedgewarsMobile/Classes/UIImageExtra.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/UIImageExtra.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,184 @@ +// +// UIImageExtra.m +// HedgewarsMobile +// +// Created by Vittorio on 08/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "UIImageExtra.h" + + +@implementation UIImage (extra) + +-(UIImage *)scaleToSize:(CGSize) size { + // Create a bitmap graphics context + // This will also set it as the current context + UIGraphicsBeginImageContext(size); + + // Draw the scaled image in the current context + [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; + + // Create a new image from current context + UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); + + // Pop the current context from the stack + UIGraphicsEndImageContext(); + + // Return our new scaled image (autoreleased) + return scaledImage; +} + +-(UIImage *)mergeWith:(UIImage *)secondImage atPoint:(CGPoint) secondImagePoint { + // create a contex of size of the background image + return [self mergeWith:secondImage atPoint:secondImagePoint atSize:self.size]; +} + +-(UIImage *)mergeWith:(UIImage *)secondImage atPoint:(CGPoint) secondImagePoint atSize:(CGSize) resultingSize { + UIGraphicsBeginImageContext(resultingSize); + + // drav the background image + [self drawAtPoint:CGPointMake(0,0)]; + + // draw the image on top of the first image + [secondImage drawAtPoint:secondImagePoint]; + + // create an image from the current contex (not thread safe) + UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext(); + + // free drawing contex + UIGraphicsEndImageContext(); + + // return the resulting autoreleased image + return resultImage; +} + +-(id) initWithContentsOfFile:(NSString *)path andCutAt:(CGRect) rect { + // load image from path + UIImage *image = [[UIImage alloc] initWithContentsOfFile: path]; + + if (nil != image) { + // get its CGImage representation with a give size + CGImageRef cgImgage = CGImageCreateWithImageInRect([image CGImage], rect); + + // clean memory + [image release]; + + // create a UIImage from the CGImage (memory must be allocated already) + UIImage *sprite = [self initWithCGImage:cgImgage]; + + // clean memory + CGImageRelease(cgImgage); + + // return resulting image + return sprite; + } else { + DLog(@"error - image == nil"); + return nil; + } +} + +-(UIImage *)convertToGrayScale { + // Create image rectangle with current image width/height + CGRect imageRect = CGRectMake(0, 0, self.size.width, self.size.height); + + // Grayscale color space + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); + + // Create bitmap content with current image size and grayscale colorspace + CGContextRef context = CGBitmapContextCreate(nil, self.size.width, self.size.height, 8, 0, colorSpace, kCGImageAlphaNone); + + // Draw image into current context, with specified rectangle + // using previously defined context (with grayscale colorspace) + CGContextDrawImage(context, imageRect, [self CGImage]); + + // Create bitmap image info from pixel data in current context + CGImageRef imageRef = CGBitmapContextCreateImage(context); + + // Create a new UIImage object + UIImage *newImage = [UIImage imageWithCGImage:imageRef]; + + // Release colorspace, context and bitmap information + CGColorSpaceRelease(colorSpace); + CGContextRelease(context); + CFRelease(imageRef); + + // Return the new grayscale image + return newImage; +} + +// by http://iphonedevelopertips.com/cocoa/how-to-mask-an-image.html turned into a category by koda +-(UIImage*) maskImageWith:(UIImage *)maskImage { + CGImageRef maskRef = maskImage.CGImage; + + CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef), + CGImageGetHeight(maskRef), + CGImageGetBitsPerComponent(maskRef), + CGImageGetBitsPerPixel(maskRef), + CGImageGetBytesPerRow(maskRef), + CGImageGetDataProvider(maskRef), NULL, false); + + CGImageRef masked = CGImageCreateWithMask([self CGImage], mask); + + CGImageRelease(mask); + + UIImage* retImage = [UIImage imageWithCGImage:masked]; + + CGImageRelease(masked); + + return retImage; +} + +// by http://blog.sallarp.com/iphone-uiimage-round-corners/ turned into a category by koda +void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight) +{ + float fw, fh; + if (ovalWidth == 0 || ovalHeight == 0) { + CGContextAddRect(context, rect); + return; + } + CGContextSaveGState(context); + CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect)); + CGContextScaleCTM (context, ovalWidth, ovalHeight); + fw = CGRectGetWidth (rect) / ovalWidth; + fh = CGRectGetHeight (rect) / ovalHeight; + CGContextMoveToPoint(context, fw, fh/2); + CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); + CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); + CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); + CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); + CGContextClosePath(context); + CGContextRestoreGState(context); +} + +-(UIImage *)makeRoundCornersOfSize:(CGSize) sizewh { + UIImage * newImage = nil; + + NSInteger cornerWidth = sizewh.width; + NSInteger cornerHeight = sizewh.height; + int w = self.size.width; + int h = self.size.height; + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst); + + CGContextBeginPath(context); + CGRect rect = CGRectMake(0, 0, w, h); + addRoundedRectToPath(context, rect, cornerWidth, cornerHeight); + CGContextClosePath(context); + CGContextClip(context); + + CGContextDrawImage(context, CGRectMake(0, 0, w, h), self.CGImage); + + CGImageRef imageMasked = CGBitmapContextCreateImage(context); + CGContextRelease(context); + CGColorSpaceRelease(colorSpace); + + newImage = [UIImage imageWithCGImage:imageMasked]; + CGImageRelease(imageMasked); + + return newImage; +} + + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/VoicesViewController.h --- a/project_files/HedgewarsMobile/Classes/VoicesViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/VoicesViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,25 @@ +// +// VoicesViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface VoicesViewController : UITableViewController { + NSMutableDictionary *teamDictionary; + + NSArray *voiceArray; + NSIndexPath *lastIndexPath; + + int voiceBeingPlayed; +} + +@property (nonatomic,retain) NSMutableDictionary *teamDictionary; +@property (nonatomic,retain) NSArray *voiceArray; +@property (nonatomic,retain) NSIndexPath *lastIndexPath; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/VoicesViewController.m --- a/project_files/HedgewarsMobile/Classes/VoicesViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/VoicesViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,150 @@ +// +// VoicesViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 02/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "VoicesViewController.h" +#import "CommodityFunctions.h" +#import "openalbridge.h" + + +@implementation VoicesViewController +@synthesize teamDictionary, voiceArray, lastIndexPath; + + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + + +#pragma mark - +#pragma mark View lifecycle +- (void)viewDidLoad { + [super viewDidLoad]; + srandom(time(NULL)); + + openal_init(); + voiceBeingPlayed = -1; + + // load all the voices names and store them into voiceArray + // it's here and not in viewWillAppear because user cannot add/remove them + NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:VOICES_DIRECTORY() error:NULL]; + self.voiceArray = array; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // this moves the tableview to the top + [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; +} + +-(void) viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + if(voiceBeingPlayed >= 0) { + openal_stopsound(voiceBeingPlayed); + voiceBeingPlayed = -1; + } +} + + +#pragma mark - +#pragma mark Table view data source +-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.voiceArray count]; +} + +// Customize the appearance of table view cells. +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + NSString *voice = [[voiceArray objectAtIndex:[indexPath row]] stringByDeletingPathExtension]; + cell.textLabel.text = voice; + + if ([voice isEqualToString:[teamDictionary objectForKey:@"voicepack"]]) { + cell.accessoryType = UITableViewCellAccessoryCheckmark; + self.lastIndexPath = indexPath; + } else { + cell.accessoryType = UITableViewCellAccessoryNone; + } + + return cell; +} + + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + int newRow = [indexPath row]; + int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + + if (newRow != oldRow) { + [teamDictionary setObject:[voiceArray objectAtIndex:newRow] forKey:@"voicepack"]; + + // tell our boss to write this new stuff on disk + [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; + [self.tableView reloadData]; + + self.lastIndexPath = indexPath; + [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + } + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + + if (voiceBeingPlayed >= 0) { + openal_stopsound(voiceBeingPlayed); + voiceBeingPlayed = -1; + } + + // the keyword static prevents re-initialization of the variable + NSString *voiceDir = [[NSString alloc] initWithFormat:@"%@/%@/",VOICES_DIRECTORY(),[voiceArray objectAtIndex:newRow]]; + NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:voiceDir error:NULL]; + + int index = random() % [array count]; + + voiceBeingPlayed = openal_loadfile([[voiceDir stringByAppendingString:[array objectAtIndex:index]] UTF8String]); + [voiceDir release]; + openal_playsound(voiceBeingPlayed); +} + + +#pragma mark - +#pragma mark Memory management +-(void) didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + // Relinquish ownership any cached data, images, etc that aren't in use. +} + +-(void) viewDidUnload { + openal_close(); + voiceBeingPlayed = -1; + self.lastIndexPath = nil; + self.teamDictionary = nil; + self.voiceArray = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + +-(void) dealloc { + [voiceArray release]; + [teamDictionary release]; + [lastIndexPath release]; + [super dealloc]; +} + + +@end + diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,19 @@ +// +// WeaponSettingsViewController.h +// HedgewarsMobile +// +// Created by Vittorio on 19/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import +@class SingleWeaponViewController; + +@interface WeaponSettingsViewController : UITableViewController { + NSMutableArray *listOfWeapons; + SingleWeaponViewController *childController; +} + +@property (nonatomic, retain) NSMutableArray *listOfWeapons; + +@end diff -r ccf4854df294 -r 02875b1145b7 project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m Wed Jun 23 21:49:19 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m Wed Jun 23 22:03:56 2010 +0200 @@ -0,0 +1,168 @@ +// +// WeaponSettingsViewController.m +// HedgewarsMobile +// +// Created by Vittorio on 19/04/10. +// Copyright 2010 __MyCompanyName__. All rights reserved. +// + +#import "WeaponSettingsViewController.h" +#import "CommodityFunctions.h" +#import "SingleWeaponViewController.h" + +@implementation WeaponSettingsViewController +@synthesize listOfWeapons; + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +#pragma mark - +#pragma mark View lifecycle +-(void) viewDidLoad { + [super viewDidLoad]; + + UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Edit",@"from the weapon panel") + style:UIBarButtonItemStyleBordered + target:self + action:@selector(toggleEdit:)]; + self.navigationItem.rightBarButtonItem = editButton; + [editButton release]; + +} + +-(void) viewWillAppear:(BOOL) animated { + [super viewWillAppear:animated]; + + NSArray *contentsOfDir = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:WEAPONS_DIRECTORY() error:NULL]; + NSMutableArray *array = [[NSMutableArray alloc] initWithArray:contentsOfDir copyItems:YES]; + self.listOfWeapons = array; + [array release]; + + [self.tableView reloadData]; +} + +// modifies the navigation bar to add the "Add" and "Done" buttons +-(void) toggleEdit:(id) sender { + BOOL isEditing = self.tableView.editing; + [self.tableView setEditing:!isEditing animated:YES]; + + if (isEditing) { + [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Edit",@"from the scheme panel")]; + [self.navigationItem.rightBarButtonItem setStyle: UIBarButtonItemStyleBordered]; + self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem; + } else { + [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Done",@"from the scheme panel")]; + [self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone]; + UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Add",@"from the scheme panel") + style:UIBarButtonItemStyleBordered + target:self + action:@selector(addWeapon:)]; + self.navigationItem.leftBarButtonItem = addButton; + [addButton release]; + } +} + +-(void) addWeapon:(id) sender { + NSString *fileName = [[NSString alloc] initWithFormat:@"Weapon %u.plist", [self.listOfWeapons count]]; + + createWeaponNamed([fileName stringByDeletingPathExtension]); + + [self.listOfWeapons addObject:fileName]; + [fileName release]; + + // order the array alphabetically, so schemes will keep their position + [self.listOfWeapons sortUsingSelector:@selector(compare:)]; + + [self.tableView reloadData]; +} + +#pragma mark - +#pragma mark Table view data source +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.listOfWeapons count]; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + NSUInteger row = [indexPath row]; + NSString *rowString = [[self.listOfWeapons objectAtIndex:row] stringByDeletingPathExtension]; + cell.textLabel.text = rowString; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + + return cell; +} + +// delete the row and the file +-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + NSUInteger row = [indexPath row]; + + NSString *schemeFile = [[NSString alloc] initWithFormat:@"%@/%@",WEAPONS_DIRECTORY(),[self.listOfWeapons objectAtIndex:row]]; + [[NSFileManager defaultManager] removeItemAtPath:schemeFile error:NULL]; + [schemeFile release]; + + [self.listOfWeapons removeObjectAtIndex:row]; + [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; +} + +-(BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; + if (![cell.textLabel.text isEqualToString:@"Default"]) + return YES; + else + return NO; +} + +#pragma mark - +#pragma mark Table view delegate +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + if (childController == nil) { + childController = [[SingleWeaponViewController alloc] initWithStyle:UITableViewStyleGrouped]; + } + + NSInteger row = [indexPath row]; + NSString *selectedWeaponFile = [self.listOfWeapons objectAtIndex:row]; + + // this must be set so childController can load the correct plist + childController.title = [selectedWeaponFile stringByDeletingPathExtension]; + [childController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; + + [self.navigationController pushViewController:childController animated:YES]; +} + + +#pragma mark - +#pragma mark Memory management +-(void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + if (childController.view.superview == nil ) + childController = nil; +} + +-(void) viewDidUnload { + self.listOfWeapons = nil; + childController = nil; + [super viewDidUnload]; + MSG_DIDUNLOAD(); +} + + +-(void) dealloc { + [self.listOfWeapons release]; + [childController release]; + [super dealloc]; +} + + +@end +