diff -r b07ee704f35d -r ccf4854df294 project_files/HedgewarsMobile/Classes/MapConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Wed Jun 23 21:39:14 2010 +0200 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Wed Jun 23 21:49:19 2010 +0200 @@ -1,568 +0,0 @@ -// -// 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