project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m
changeset 3910 dd47efbdec46
child 4082 bfe14b38dad1
equal deleted inserted replaced
3908:1429c303858d 3910:dd47efbdec46
       
     1 /*
       
     2  * Hedgewars-iOS, a Hedgewars port for iOS devices
       
     3  * Copyright (c) 2009-2010 Vittorio Giovara <vittorio.giovara@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
       
    17  *
       
    18  * File created on 26/09/2010.
       
    19  */
       
    20 
       
    21 
       
    22 #import "MapPreviewButtonView.h"
       
    23 #import "MapConfigViewController.h"
       
    24 #import "UIImageExtra.h"
       
    25 #import <pthread.h>
       
    26 
       
    27 #define INDICATOR_TAG 7654
       
    28 
       
    29 @implementation MapPreviewButtonView
       
    30 @synthesize delegate;
       
    31 
       
    32 -(id) initWithFrame:(CGRect)frame {
       
    33     if ((self = [super initWithFrame:frame])) {
       
    34         delegate = nil;
       
    35         [self setBackgroundImageRounded:[UIImage whiteImage:frame.size] forState:UIControlStateNormal];
       
    36     }
       
    37     return self;
       
    38 }
       
    39 
       
    40 -(id) initWithCoder:(NSCoder *)aDecoder {
       
    41     if ((self = [super initWithCoder:aDecoder])) {
       
    42         delegate = nil;
       
    43         [self setBackgroundImageRounded:[UIImage whiteImage:self.frame.size] forState:UIControlStateNormal];
       
    44     }
       
    45     return self;
       
    46 }
       
    47 
       
    48 -(void) dealloc {
       
    49     self.delegate = nil;
       
    50     [super dealloc];
       
    51 }
       
    52 
       
    53 #pragma mark -
       
    54 #pragma mark image wrappers
       
    55 -(void) setBackgroundImageRounded:(UIImage *)image forState:(UIControlState)state {
       
    56     [self setBackgroundImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];    
       
    57 }
       
    58 
       
    59 -(void) setImageRounded:(UIImage *)image forState:(UIControlState)state {
       
    60     [self setImage:[image makeRoundCornersOfSize:CGSizeMake(12, 12)] forState:UIControlStateNormal];    
       
    61 }
       
    62 
       
    63 -(void) setImageRoundedForNormalState:(UIImage *)image {
       
    64     [self setImageRounded:image forState:UIControlStateNormal];
       
    65 }
       
    66 
       
    67 #pragma mark -
       
    68 #pragma mark preview 
       
    69 -(int) sendToEngine:(NSString *)string {
       
    70     unsigned char length = [string length];
       
    71 
       
    72     SDLNet_TCP_Send(csd, &length, 1);
       
    73     return SDLNet_TCP_Send(csd, [string UTF8String], length);
       
    74 }
       
    75 
       
    76 -(const uint8_t *)engineProtocol {
       
    77     IPaddress ip;
       
    78     BOOL serverQuit = NO;
       
    79     static uint8_t map[128*32];
       
    80     int port = randomPort();
       
    81 
       
    82     if (SDLNet_Init() < 0) {
       
    83         DLog(@"SDLNet_Init: %s", SDLNet_GetError());
       
    84         serverQuit = YES;
       
    85     }
       
    86 
       
    87     // Resolving the host using NULL make network interface to listen
       
    88     if (SDLNet_ResolveHost(&ip, NULL, port) < 0) {
       
    89         DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
       
    90         serverQuit = YES;
       
    91     }
       
    92 
       
    93     // Open a connection with the IP provided (listen on the host's port)
       
    94     if (!(sd = SDLNet_TCP_Open(&ip))) {
       
    95         DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
       
    96         serverQuit = YES;
       
    97     }
       
    98 
       
    99     // launch the preview here so that we're sure the tcp channel is open
       
   100     pthread_t thread_id;
       
   101     pthread_create(&thread_id, NULL, (void *)GenLandPreview, (void *)port);
       
   102     pthread_detach(thread_id);
       
   103 
       
   104     DLog(@"Waiting for a client on port %d", port);
       
   105     while (!serverQuit) {
       
   106         /* This check the sd if there is a pending connection.
       
   107          * If there is one, accept that, and open a new socket for communicating */
       
   108         csd = SDLNet_TCP_Accept(sd);
       
   109         if (NULL != csd) {
       
   110             DLog(@"Client found");
       
   111 
       
   112             NSDictionary *dictForEngine = [self getDataForEngine];
       
   113             [self sendToEngine:[dictForEngine objectForKey:@"seedCommand"]];
       
   114             [self sendToEngine:[dictForEngine objectForKey:@"templateFilterCommand"]];
       
   115             [self sendToEngine:[dictForEngine objectForKey:@"mapGenCommand"]];
       
   116             [self sendToEngine:[dictForEngine objectForKey:@"mazeSizeCommand"]];
       
   117             [self sendToEngine:@"!"];
       
   118 
       
   119             memset(map, 0, 128*32);
       
   120             SDLNet_TCP_Recv(csd, map, 128*32);
       
   121             SDLNet_TCP_Recv(csd, &maxHogs, sizeof(uint8_t));
       
   122 
       
   123             SDLNet_TCP_Close(csd);
       
   124             serverQuit = YES;
       
   125         }
       
   126     }
       
   127 
       
   128     SDLNet_TCP_Close(sd);
       
   129     SDLNet_Quit();
       
   130     return map;
       
   131 }
       
   132 
       
   133 -(void) drawingThread {
       
   134     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
   135     const uint8_t *map = [self engineProtocol];
       
   136     uint8_t mapExp[128*32*8];
       
   137 
       
   138     // draw the buffer (1 pixel per component, 0= transparent 1= color)
       
   139     int k = 0;
       
   140     for (int i = 0; i < 32*128; i++) {
       
   141         unsigned char byte = map[i];
       
   142         for (int j = 0; j < 8; j++) {
       
   143             // select the color based on the leftmost bit
       
   144             if ((byte & 0x80) != 0)
       
   145                 mapExp[k] = 100;
       
   146             else
       
   147                 mapExp[k] = 255;
       
   148             // shift to next bit
       
   149             byte <<= 1;
       
   150             k++;
       
   151         }
       
   152     }
       
   153     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
       
   154     CGContextRef bitmapImage = CGBitmapContextCreate(mapExp, 256, 128, 8, 256, colorspace, kCGImageAlphaNone);
       
   155     CGColorSpaceRelease(colorspace);
       
   156 
       
   157     CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage);
       
   158     CGContextRelease(bitmapImage);
       
   159     UIImage *previewImage = [[UIImage alloc] initWithCGImage:previewCGImage];
       
   160     CGImageRelease(previewCGImage);
       
   161     previewCGImage = nil;
       
   162 
       
   163     // all these are performed on the main thread to prevent a leak
       
   164     [self performSelectorOnMainThread:@selector(setImageRoundedForNormalState:)
       
   165                            withObject:previewImage
       
   166                         waitUntilDone:NO];
       
   167     [previewImage release];
       
   168     [self performSelectorOnMainThread:@selector(setLabelText:)
       
   169                            withObject:[NSString stringWithFormat:@"%d", maxHogs]
       
   170                         waitUntilDone:NO];
       
   171     [self performSelectorOnMainThread:@selector(turnOnWidgets)
       
   172                            withObject:nil
       
   173                         waitUntilDone:NO];
       
   174     [self performSelectorOnMainThread:@selector(removeIndicator)
       
   175                            withObject:nil
       
   176                         waitUntilDone:NO];
       
   177     
       
   178     [pool release];
       
   179 
       
   180     /*
       
   181     // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html
       
   182     UIGraphicsBeginImageContext(CGSizeMake(256,128));
       
   183     CGContextRef context = UIGraphicsGetCurrentContext();
       
   184     UIGraphicsPushContext(context);
       
   185     CGContextSetRGBFillColor(context, 0.5, 0.5, 0.7, 1.0);
       
   186     CGContextFillRect(context,CGRectMake(xc,yc,1,1));
       
   187     UIGraphicsPopContext();
       
   188     UIImage *previewImage = UIGraphicsGetImageFromCurrentImageContext();
       
   189     UIGraphicsEndImageContext();
       
   190     */
       
   191 }
       
   192 
       
   193 -(void) updatePreviewWithSeed:(NSString *)seed {
       
   194     // remove the current preview and title
       
   195     [self setImage:nil forState:UIControlStateNormal];
       
   196     [self setTitle:nil forState:UIControlStateNormal];
       
   197     
       
   198     // don't display preview on slower device, too slow and memory hog
       
   199     NSString *modelId = modelType();
       
   200     if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) {
       
   201         //self.delegate.busy = NO;
       
   202         [self setTitle:NSLocalizedString(@"Preview not available",@"") forState:UIControlStateNormal];
       
   203     } else {        
       
   204         // add a very nice spinning wheel
       
   205         UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]
       
   206                                               initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
       
   207         indicator.center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
       
   208         indicator.tag = INDICATOR_TAG;
       
   209         [indicator startAnimating];
       
   210         [self addSubview:indicator];
       
   211         [indicator release];
       
   212         
       
   213         // let's draw in a separate thread so the gui can work; at the end it restore other widgets
       
   214         [NSThread detachNewThreadSelector:@selector(drawingThread) toTarget:self withObject:nil];
       
   215     }
       
   216 }
       
   217 
       
   218 -(void) updatePreviewWithFile:(NSString *)filePath {
       
   219     UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
       
   220     [self setImageRounded:image forState:UIControlStateNormal];
       
   221     [image release];
       
   222 }
       
   223 
       
   224 -(void) removeIndicator {
       
   225     UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[self viewWithTag:INDICATOR_TAG];
       
   226     if (indicator) {
       
   227         [indicator stopAnimating];
       
   228         [indicator removeFromSuperview];
       
   229     }
       
   230 }
       
   231 
       
   232 #pragma mark -
       
   233 #pragma mark delegate
       
   234 -(void) turnOnWidgets {
       
   235     [self.delegate turnOnWidgets];
       
   236 }
       
   237 
       
   238 -(void) setLabelText:(NSString *)string {
       
   239     [self.delegate setLabelText:string];
       
   240 }
       
   241 
       
   242 -(NSDictionary *)getDataForEngine {
       
   243     return [self.delegate getDataForEngine];
       
   244 }
       
   245 
       
   246 @end