diff -r 1429c303858d -r dd47efbdec46 project_files/HedgewarsMobile/Classes/MapConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Sun Sep 26 16:28:04 2010 -0400 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Sun Sep 26 23:48:03 2010 +0200 @@ -23,10 +23,7 @@ #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, staticMapCommand, @@ -37,130 +34,6 @@ 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) { - DLog(@"SDLNet_Init: %s", SDLNet_GetError()); - serverQuit = YES; - } - - // Resolving the host using NULL make network interface to listen - if (SDLNet_ResolveHost(&ip, NULL, port) < 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(), 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); - CGContextRelease(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) mapButtonPressed { playSound(@"clickSound"); [self updatePreview]; @@ -176,77 +49,26 @@ 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) { - // remove the current preview and title - [self.previewButton setImage:nil forState:UIControlStateNormal]; - [self.previewButton setTitle:nil forState:UIControlStateNormal]; - - // don't display preview on slower device, too slow and memory hog - NSString *modelId = modelType(); - if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) { - busy = NO; - [self.previewButton setTitle:NSLocalizedString(@"Preview not available",@"") forState:UIControlStateNormal]; - } else { - // prevent other events and add an activity while the preview is beign generated - [self turnOffWidgets]; - - // 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]; - } - + // prevent other events and add an activity while the preview is beign generated + [self turnOffWidgets]; + [self.previewButton updatePreviewWithSeed:seed]; theIndex = [NSIndexPath indexPathForRow:(random()%[self.themeArray count]) inSection:0]; } else { theIndex = [NSIndexPath indexPathForRow:(random()%[self.mapArray count]) inSection:0]; + // the preview for static maps is loaded in didSelectRowAtIndexPath } - [self.tableView reloadData]; + [seed release]; + + // perform as if user clicked on an entry [self tableView:self.tableView didSelectRowAtIndexPath:theIndex]; [self.tableView scrollToRowAtIndexPath:theIndex atScrollPosition:UITableViewScrollPositionNone animated:YES]; } -// instead of drawing a random map we load an image; this function is called by didSelectRowAtIndexPath only --(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"]; - [contents release]; - - // set the theme and map here - self.themeCommand = [NSString stringWithFormat:@"etheme %@", [split objectAtIndex:0]]; - self.staticMapCommand = [NSString stringWithFormat:@"emap %@", [self.mapArray objectAtIndex:index]]; - - // 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]; - NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs]; - self.maxLabel.text = max; - [max release]; -} - -(void) turnOffWidgets { busy = YES; self.previewButton.alpha = 0.5f; @@ -262,35 +84,21 @@ 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.maxHogs = [str intValue]; 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]; +-(NSDictionary *)getDataForEngine { + NSDictionary *dictForEngine = [NSDictionary dictionaryWithObjectsAndKeys: + self.seedCommand,@"seedCommand", + self.templateFilterCommand,@"templateFilterCommand", + self.mapGenCommand,@"mapGenCommand", + self.mazeSizeCommand,@"mazeSizeCommand", + nil]; + return dictForEngine; } #pragma mark - @@ -340,6 +148,28 @@ return cell; } +// this set details for a static map (called by didSelectRowAtIndexPath) +-(void) setDetailsForStaticMap:(NSInteger) index { + // 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"]; + [contents release]; + + // set the theme and map here + self.themeCommand = [NSString stringWithFormat:@"etheme %@", [split objectAtIndex:0]]; + self.staticMapCommand = [NSString stringWithFormat:@"emap %@", [self.mapArray objectAtIndex:index]]; + + // 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]; + NSString *max = [[NSString alloc] initWithFormat:@"%d",maxHogs]; + self.maxLabel.text = max; + [max release]; +} #pragma mark - #pragma mark Table view delegate @@ -348,12 +178,14 @@ int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; if (newRow != oldRow) { + [self.tableView reloadData]; if (self.segmentedControl.selectedSegmentIndex != 1) { - NSString *theme = [self.themeArray objectAtIndex:newRow]; - self.themeCommand = [NSString stringWithFormat:@"etheme %@", theme]; + // just change the theme, don't update preview + self.themeCommand = [NSString stringWithFormat:@"etheme %@", [self.themeArray objectAtIndex:newRow]]; } else { - // theme and map are set in the function below - [self updatePreviewWithMap:newRow]; + NSString *fileImage = [NSString stringWithFormat:@"%@/%@/preview.png",MAPS_DIRECTORY(),[self.mapArray objectAtIndex:newRow]]; + [self.previewButton updatePreviewWithFile:fileImage]; + [self setDetailsForStaticMap:newRow]; } UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; @@ -456,7 +288,6 @@ } // 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, *staticmap; @@ -477,7 +308,6 @@ staticmap = @"map Bamboo"; self.slider.enabled = NO; self.sizeLabel.text = NSLocalizedString(@"No filter",@""); - [self restoreBackgroundImage]; break; case 2: // Maze @@ -539,11 +369,6 @@ [array release]; self.mapArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL]; - busy = NO; - - // draw a white background - [self restoreBackgroundImage]; - // initialize some "default" values self.sizeLabel.text = NSLocalizedString(@"All",@""); self.slider.value = 0.05f; @@ -564,7 +389,8 @@ oldValue = 5; oldPage = 0; - + busy = NO; + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [self.tableView setBackgroundView:nil]; self.view.backgroundColor = [UIColor clearColor]; @@ -575,8 +401,8 @@ } -(void) viewDidAppear:(BOOL) animated { + [self updatePreview]; [super viewDidAppear:animated]; - [self updatePreview]; } #pragma mark - @@ -589,7 +415,6 @@ #pragma mark - -(void) didReceiveMemoryWarning { [super didReceiveMemoryWarning]; - //[previewButton setImage:nil forState:UIControlStateNormal]; MSG_MEMCLEAN(); } @@ -643,5 +468,4 @@ [super dealloc]; } - @end