--- 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 <pthread.h>
-
-#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