Crossfire Client, Branch
R11627
|
00001 const char * const rcsid_gtk2_map_c = 00002 "$Id: map.c 11117 2009-01-05 07:11:04Z mwedel $"; 00003 /* 00004 Crossfire client, a client program for the crossfire program. 00005 00006 Copyright (C) 2005 Mark Wedel & Crossfire Development Team 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00021 00022 The author can be reached via e-mail to crossfire@metalforge.org 00023 */ 00024 00031 #include <config.h> 00032 #include <stdlib.h> 00033 #include <sys/stat.h> 00034 #ifndef WIN32 00035 #include <unistd.h> 00036 #endif 00037 #include <png.h> 00038 00039 /* Pick up the gtk headers we need */ 00040 #include <gtk/gtk.h> 00041 #include <glade/glade.h> 00042 #ifndef WIN32 00043 #include <gdk/gdkx.h> 00044 #else 00045 #include <time.h> 00046 #include <gdk/gdkwin32.h> 00047 #endif 00048 #include <gdk/gdkkeysyms.h> 00049 00050 #include "client-types.h" 00051 #include "image.h" 00052 #include "main.h" 00053 #include "client.h" 00054 #include "mapdata.h" 00055 #include "gtk2proto.h" 00056 00057 static uint8 map_updated = 0; 00058 00059 /* 00060 * Added for fog of war. Current size of the map structure in memory. 00061 * We assume a rectangular map so this is the length of one side. 00062 * command.c needs to know about this so not static 00063 * FIX ME: Don't assume rectangle 00064 */ 00065 00066 PlayerPosition pl_pos; 00067 00068 GtkWidget *map_drawing_area, *map_notebook; 00069 GdkGC *mapgc; 00070 int map_image_size=DEFAULT_IMAGE_SIZE; 00071 int map_image_half_size=DEFAULT_IMAGE_SIZE/2; 00072 static GdkBitmap *dark1, *dark2, *dark3; 00073 static GdkPixmap *dark; 00074 00075 /* 00076 * This should really be one of the CONFIG values, or perhaps a checkbox 00077 * someplace that displays frame rate. 00078 */ 00079 int time_map_redraw=0; 00080 00081 #if WIN32 00082 00088 int gettimeofday(struct timeval* tp, void* tzp) { 00089 DWORD t; 00090 t = timeGetTime(); 00091 tp->tv_sec = t / 1000; 00092 tp->tv_usec = t % 1000; 00093 /* 0 indicates that the call succeeded. */ 00094 return 0; 00095 } 00096 #endif 00097 00103 void map_init(GtkWidget *window_root) 00104 { 00105 GladeXML* xml_tree; 00106 00107 xml_tree = glade_get_widget_tree(GTK_WIDGET(window_root)); 00108 00109 map_drawing_area = glade_xml_get_widget(xml_tree, "drawingarea_map"); 00110 map_notebook = glade_xml_get_widget(xml_tree, "map_notebook"); 00111 00112 g_signal_connect ((gpointer) map_drawing_area, "expose_event", 00113 G_CALLBACK (on_drawingarea_map_expose_event), NULL); 00114 g_signal_connect ((gpointer) map_drawing_area, "button_press_event", 00115 G_CALLBACK (on_drawingarea_map_button_press_event), NULL); 00116 g_signal_connect ((gpointer) map_drawing_area, "configure_event", 00117 G_CALLBACK (on_drawingarea_map_configure_event), NULL); 00118 00119 #if 0 00120 gtk_widget_set_size_request (map_drawing_area, 00121 use_config[CONFIG_MAPWIDTH] * map_image_size, 00122 use_config[CONFIG_MAPHEIGHT] * map_image_size); 00123 #endif 00124 mapgc = gdk_gc_new(map_drawing_area->window); 00125 gtk_widget_show(map_drawing_area); 00126 gtk_widget_add_events (map_drawing_area, GDK_BUTTON_PRESS_MASK); 00127 00128 if (use_config[CONFIG_DISPLAYMODE] == CFG_DM_PIXMAP) { 00129 int x,y,count; 00130 GdkGC *darkgc; 00131 /* 00132 * This is used when drawing with GdkPixmaps. Create another surface, 00133 * as well as some light/dark images 00134 */ 00135 dark = gdk_pixmap_new(map_drawing_area->window, map_image_size, map_image_size, -1); 00136 gdk_draw_rectangle(dark, map_drawing_area->style->black_gc, TRUE, 0, 0, map_image_size, map_image_size); 00137 dark1 = gdk_pixmap_new(map_drawing_area->window, map_image_size, map_image_size, 1); 00138 dark2 = gdk_pixmap_new(map_drawing_area->window, map_image_size, map_image_size, 1); 00139 dark3 = gdk_pixmap_new(map_drawing_area->window, map_image_size, map_image_size, 1); 00140 /* 00141 * We need our own GC here because we are working with single bit depth 00142 * images 00143 */ 00144 darkgc = gdk_gc_new(dark1); 00145 gdk_gc_set_foreground(darkgc, &root_color[NDI_WHITE]); 00146 /* Clear any garbage values we get when we create the bitmaps */ 00147 gdk_draw_rectangle(dark1, darkgc, TRUE, 0, 0, map_image_size, map_image_size); 00148 gdk_draw_rectangle(dark2, darkgc, TRUE, 0, 0, map_image_size, map_image_size); 00149 gdk_draw_rectangle(dark3, darkgc, TRUE, 0, 0, map_image_size, map_image_size); 00150 gdk_gc_set_foreground(darkgc, &root_color[NDI_BLACK]); 00151 count=0; 00152 for (x=0; x<map_image_size; x++) { 00153 for (y=0; y<map_image_size; y++) { 00154 /* 00155 * We just fill in points every X pixels - dark1 is the 00156 * darkest, dark3 is the lightest. dark1 has 50% of the pixels 00157 * filled in, dark2 has 33%, dark3 has 25% The formula's here 00158 * are not perfect - dark2 will not match perfectly with an 00159 * adjacent dark2 image. dark3 results in diagonal stripes. 00160 * OTOH, these will change depending on the image size. 00161 */ 00162 if ((x+y) % 2) { 00163 gdk_draw_point(dark1, darkgc, x, y); 00164 } 00165 if ((x+y) %3) { 00166 gdk_draw_point(dark2, darkgc, x, y); 00167 } 00168 if ((x+y) % 4) { 00169 gdk_draw_point(dark3, darkgc, x, y); 00170 } 00171 /* 00172 * dark1 gets filled on 0x01, 0x11, 0x10, only leaving 0x00 00173 * empty 00174 */ 00175 } 00176 /* 00177 * if the row size is even, we put an extra value in count - in 00178 * this way, the pixels will be even on one line, odd on the next, 00179 * etc instead of vertical lines - at least for dark1 and dark3 00180 */ 00181 } 00182 gdk_gc_unref(darkgc); 00183 } 00184 #ifdef HAVE_SDL 00185 else if (use_config[CONFIG_DISPLAYMODE] == CFG_DM_SDL) { 00186 init_SDL(map_drawing_area,0); 00187 } 00188 #endif 00189 #ifdef HAVE_OPENGL 00190 else if (use_config[CONFIG_DISPLAYMODE] == CFG_DM_OPENGL) { 00191 init_opengl(map_drawing_area); 00192 } 00193 #endif 00194 } 00195 00201 void reset_map(void) 00202 { 00203 } 00204 00218 static void draw_pixmap(int srcx, int srcy, int dstx, int dsty, int clipx, int clipy, 00219 void *mask, void *image, int sizex, int sizey) 00220 { 00221 gdk_gc_set_clip_mask(mapgc, mask); 00222 gdk_gc_set_clip_origin(mapgc, clipx, clipy); 00223 gdk_draw_pixmap(map_drawing_area->window, mapgc, image, srcx, srcy, dstx, dsty, sizex, sizey); 00224 } 00225 00231 int display_mapscroll(int dx, int dy) 00232 { 00233 #ifdef HAVE_SDL 00234 if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) 00235 return sdl_mapscroll(dx,dy); 00236 else 00237 #endif 00238 return 0; 00239 } 00240 00251 void drawsmooth (int mx,int my,int layer,int picx,int picy){ 00252 static int dx[8]={0,1,1,1,0,-1,-1,-1}; 00253 static int dy[8]={-1,-1,0,1,1,1,0,-1}; 00254 static int bweights[8]={2,0,4,0,8,0,1,0}; 00255 static int cweights[8]={0,2,0,4,0,8,0,1}; 00256 static int bc_exclude[8]={ 00257 1+2,/*north exclude northwest (bit0) and northeast(bit1)*/ 00258 0, 00259 2+4,/*east exclude northeast and southeast*/ 00260 0, 00261 4+8,/*and so on*/ 00262 0, 00263 8+1, 00264 0 00265 }; 00266 int partdone[8]={0,0,0,0,0,0,0,0}; 00267 int slevels[8]; 00268 int sfaces[8]; 00269 int i,lowest,weight,weightC; 00270 int emx,emy; 00271 int smoothface; 00272 int hasFace = 0; 00273 for (i=0;i<=layer;i++) 00274 hasFace |= the_map.cells[mx][my].heads[i].face; 00275 if (!hasFace 00276 || !CAN_SMOOTH(the_map.cells[mx][my], layer)) { 00277 return; 00278 } 00279 for (i=0;i<8;i++){ 00280 emx=mx+dx[i]; 00281 emy=my+dy[i]; 00282 if ( (emx<0) || (emy<0) || (the_map.x<=emx) || (the_map.y<=emy)){ 00283 slevels[i]=0; 00284 sfaces[i]=0; /*black picture*/ 00285 } 00286 else if (the_map.cells[emx][emy].smooth[layer]<=the_map.cells[mx][my].smooth[layer]){ 00287 slevels[i]=0; 00288 sfaces[i]=0; /*black picture*/ 00289 }else{ 00290 slevels[i]=the_map.cells[emx][emy].smooth[layer]; 00291 sfaces[i]=pixmaps[the_map.cells[emx][emy].heads[layer].face]->smooth_face; 00292 } 00293 } 00294 /* 00295 * Now we have a list of smoothlevel higher than current square. There are 00296 * at most 8 different levels. so... check 8 times for the lowest one (we 00297 * draw from bottom to top!). 00298 */ 00299 lowest=-1; 00300 while (1){ 00301 lowest = -1; 00302 for (i=0;i<8;i++){ 00303 if ( (slevels[i]>0) && (!partdone[i]) && 00304 ((lowest<0) || (slevels[i]<slevels[lowest])) 00305 ) 00306 lowest=i; 00307 } 00308 if (lowest<0) 00309 break; /*no more smooth to do on this square*/ 00310 /*printf ("hey, must smooth something...%d\n",sfaces[lowest]);*/ 00311 /* Here we know 'what' to smooth 00312 * 00313 * Calculate the weight for border and weight for corners. Then 00314 * 'markdone' the corresponding squares 00315 * 00316 * First, the border, which may exclude some corners 00317 */ 00318 weight=0; 00319 weightC=15; /*works in backward. remove where there is nothing*/ 00320 /*for (i=0;i<8;i++) 00321 cornermask[i]=1;*/ 00322 for (i=0;i<8;i++){ /*check all nearby squares*/ 00323 if ( (slevels[i]==slevels[lowest]) && 00324 (sfaces[i]==sfaces[lowest])){ 00325 partdone[i]=1; 00326 weight=weight+bweights[i]; 00327 weightC&=~bc_exclude[i]; 00328 }else{ 00329 /*must rmove the weight of a corner if not in smoothing*/ 00330 weightC&=~cweights[i]; 00331 } 00332 } 00333 /*We can't do this before since we need the partdone to be adjusted*/ 00334 if (sfaces[lowest]<=0) 00335 continue; /*Can't smooth black*/ 00336 smoothface=sfaces[lowest]; 00337 if (smoothface<=0){ 00338 continue; /*picture for smoothing not yet available*/ 00339 } 00340 /* 00341 * now, it's quite easy. We must draw using a 32x32 part of the picture 00342 * smoothface. This part is located using the 2 weights calculated: 00343 * (32*weight,0) and (32*weightC,32) 00344 */ 00345 if ( (!pixmaps[smoothface]->map_image) || 00346 (pixmaps[smoothface] == pixmaps[0])) 00347 continue; /*don't have the picture associated*/ 00348 if (weight>0){ 00349 draw_pixmap( 00350 weight*map_image_size, 0, 00351 picx, picy, 00352 picx-weight*map_image_size, picy, 00353 pixmaps[smoothface]->map_mask, pixmaps[smoothface]->map_image, map_image_size, map_image_size); 00354 } 00355 if (weightC>0){ 00356 draw_pixmap( 00357 weightC*map_image_size, map_image_size, 00358 picx, picy, 00359 picx-weightC*map_image_size, picy-map_image_size, 00360 pixmaps[smoothface]->map_mask, pixmaps[smoothface]->map_image, map_image_size, map_image_size); 00361 } 00362 } /* while there's some smooth to do */ 00363 } 00364 00372 static void display_mapcell(int ax, int ay, int mx, int my) 00373 { 00374 int layer; 00375 00376 /* First, we need to black out this space. */ 00377 gdk_draw_rectangle(map_drawing_area->window, map_drawing_area->style->black_gc, TRUE, ax*map_image_size, ay*map_image_size, map_image_size, map_image_size); 00378 /* 00379 * Now draw the different layers. Only draw if using fog of war or the 00380 * space isn't clear. 00381 */ 00382 if (use_config[CONFIG_FOGWAR] || !the_map.cells[mx][my].cleared) { 00383 for (layer=0; layer<MAXLAYERS; layer++) { 00384 int sx, sy; 00385 00386 /* draw single-tile faces first */ 00387 int face = mapdata_face(ax, ay, layer); 00388 if (face > 0 && pixmaps[face]->map_image != NULL) { 00389 int src_x = pixmaps[face]->map_width - map_image_size;; 00390 int src_y = pixmaps[face]->map_height - map_image_size; 00391 int off_x=0, off_y=0; 00392 00393 /* Normalize the source coordinates - clearly it can't be 00394 * be less than zero. If it is less than zero, this denotes 00395 * a 'small' image. By definition, the bottom right is the 00396 * origin of the image (an image 16 pixels high is drawn on the 00397 * bottom half of the space, not top), which is why 00398 * the offsets are negative of the base values. 00399 */ 00400 if (src_x<0) { 00401 off_x=-src_x; 00402 src_x=0; 00403 } 00404 if (src_y<0) { 00405 off_y = -src_y; 00406 src_y=0; 00407 } 00408 draw_pixmap( 00409 src_x, src_y, 00410 ax*map_image_size + off_x, ay*map_image_size + off_y, 00411 ax*map_image_size+map_image_size-pixmaps[face]->map_width, 00412 ay*map_image_size+map_image_size-pixmaps[face]->map_height, 00413 pixmaps[face]->map_mask, pixmaps[face]->map_image, 00414 pixmaps[face]->map_width>map_image_size?map_image_size:pixmaps[face]->map_width, 00415 pixmaps[face]->map_height>map_image_size?map_image_size:pixmaps[face]->map_height); 00416 00417 } 00418 /* 00419 * Sometimes, it may happens we need to draw the smooth while there 00420 * is nothing to draw at that layer (but there was something at 00421 * lower layers). This is handled here. The else part is to take 00422 * into account cases where the smooth as already been handled 2 00423 * code lines before 00424 */ 00425 if ( use_config[CONFIG_SMOOTH]) 00426 drawsmooth (mx, my, layer, ax*map_image_size, ay*map_image_size); 00427 00428 /* draw big faces last (should overlap other objects) */ 00429 face = mapdata_bigface(ax, ay, layer, &sx, &sy); 00430 00431 if (face > 0 && pixmaps[face]->map_image != NULL) { 00432 /* 00433 * This is pretty messy, because images are not required to be 00434 * an integral multiplier of the image size. There are really 00435 * 4 main variables: 00436 * source[xy]: Where within the pixmap to start grabbing pixels. 00437 * off[xy]: Offset from space edge on the visible map to start 00438 * drawing pixels. 00439 * off[xy] also determines how many pixels to draw 00440 * (map_image_size - off[xy]) 00441 * clip[xy]: Position of the clipmask. The position of the 00442 * clipmask is always at the upper left of the image as we 00443 * drawn it on the map, so for any given big image, it will 00444 * have the same values for all the pieces. However we 00445 * need to re-construct that location based on current 00446 * location. 00447 * 00448 * For a 32x72 image, it would be drawn like follows: 00449 * sourcey offy 00450 * top space: 0 24 00451 * middle space: 8 0 00452 * bottom space: 40 0 00453 */ 00454 int dx, dy, sourcex, sourcey, offx, offy, clipx, clipy; 00455 00456 dx = pixmaps[face]->map_width % map_image_size; 00457 offx = dx?(map_image_size -dx):0; 00458 clipx = (ax - sx)*map_image_size + offx; 00459 00460 if (sx) { 00461 sourcex = sx * map_image_size - offx ; 00462 offx=0; 00463 } else { 00464 sourcex=0; 00465 } 00466 00467 dy = pixmaps[face]->map_height % map_image_size; 00468 offy = dy?(map_image_size -dy):0; 00469 clipy = (ay - sy)*map_image_size + offy; 00470 00471 if (sy) { 00472 sourcey = sy * map_image_size - offy; 00473 offy=0; 00474 } else { 00475 sourcey=0; 00476 } 00477 00478 draw_pixmap( 00479 sourcex, sourcey, 00480 ax*map_image_size+offx, ay*map_image_size + offy, 00481 clipx, clipy, 00482 pixmaps[face]->map_mask, pixmaps[face]->map_image, 00483 map_image_size - offx, map_image_size - offy); 00484 } 00485 } /* else for processing the layers */ 00486 } 00487 /* 00488 * If this is a fog cell, do darkening of the space. otherwise, process 00489 * light/darkness - only do those if not a fog cell. 00490 */ 00491 if (use_config[CONFIG_FOGWAR] && the_map.cells[mx][my].cleared) { 00492 draw_pixmap(0, 0, ax*map_image_size, ay*map_image_size, ax*map_image_size, ay*map_image_size, dark1, dark, map_image_size, map_image_size); 00493 } 00494 else if (the_map.cells[mx][my].darkness > 192) { /* Full dark */ 00495 gdk_draw_rectangle (map_drawing_area->window, map_drawing_area->style->black_gc, 00496 TRUE,map_image_size*ax, map_image_size*ay, 00497 map_image_size, map_image_size); 00498 } else if (the_map.cells[mx][my].darkness> 128) { 00499 draw_pixmap(0, 0, ax*map_image_size, ay*map_image_size, ax*map_image_size, ay*map_image_size, dark1, dark, map_image_size, map_image_size); 00500 } else if (the_map.cells[mx][my].darkness> 64) { 00501 draw_pixmap(0, 0, ax*map_image_size, ay*map_image_size, ax*map_image_size, ay*map_image_size, dark2, dark, map_image_size, map_image_size); 00502 } else if (the_map.cells[mx][my].darkness> 1) { 00503 draw_pixmap(0, 0, ax*map_image_size, ay*map_image_size, ax*map_image_size, ay*map_image_size, dark3, dark, map_image_size, map_image_size); 00504 } 00505 } 00506 00511 void gtk_draw_map(int redraw) { 00512 int mx, my; 00513 int x, y; 00514 struct timeval tv1, tv2,tv3; 00515 long elapsed1, elapsed2; 00516 00517 if(!redraw && !map_updated) 00518 return; 00519 00520 if (time_map_redraw) 00521 gettimeofday(&tv1, NULL); 00522 00523 for(x = 0; x < use_config[CONFIG_MAPWIDTH]; x++) { 00524 for(y = 0; y < use_config[CONFIG_MAPHEIGHT]; y++) { 00525 /* 00526 * mx,my represent the spaces on the 'virtual' map (ie, the_map 00527 * structure). x and y (from the for loop) represent the visible 00528 * screen. 00529 */ 00530 mx = pl_pos.x+x; 00531 my = pl_pos.y+y; 00532 00533 if (redraw 00534 || the_map.cells[mx][my].need_update 00535 || the_map.cells[mx][my].need_resmooth) { 00536 display_mapcell(x, y, mx, my); 00537 the_map.cells[mx][my].need_update = 0; 00538 the_map.cells[mx][my].need_resmooth = 0; 00539 } 00540 } /* For y spaces */ 00541 } /* for x spaces */ 00542 00543 if (time_map_redraw) 00544 gettimeofday(&tv2, NULL); 00545 00546 if (time_map_redraw) { 00547 gettimeofday(&tv3, NULL); 00548 elapsed1 = (tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec); 00549 elapsed2 = (tv3.tv_sec - tv2.tv_sec)*1000000 + (tv3.tv_usec - tv2.tv_usec); 00550 /* 00551 * I care about performance for 'long' updates, so put the check in to 00552 * make these a little more noticable 00553 */ 00554 if ((elapsed1 + elapsed2)>10000) 00555 LOG(LOG_INFO,"gtk::sdl_gen_map","gen took %7ld, flip took %7ld, total = %7ld", 00556 elapsed1, elapsed2, elapsed1 + elapsed2); 00557 } 00558 } 00559 00564 void display_map_newmap(void) 00565 { 00566 reset_map(); 00567 } 00568 00575 void resize_map_window(int x, int y) 00576 { 00577 /* We do an implicit clear, since after a resize, there may be some 00578 * left over pixels at the edge which will not get drawn on by map spaces. 00579 */ 00580 gdk_window_clear(map_drawing_area->window); 00581 draw_map(TRUE); 00582 } 00583 00584 00585 gboolean 00586 on_drawingarea_map_configure_event (GtkWidget *widget, 00587 GdkEventConfigure *event, 00588 gpointer user_data) 00589 { 00590 sint16 w = event->width / map_image_size, h=event->height / map_image_size; 00591 00592 if (w > MAP_MAX_SIZE) w = MAP_MAX_SIZE; 00593 if (h > MAP_MAX_SIZE) h = MAP_MAX_SIZE; 00594 00595 /* Only need to do something if the size actually changes in terms 00596 * of displayable mapspaces. 00597 */ 00598 if (w!= use_config[CONFIG_MAPWIDTH] || h!=use_config[CONFIG_MAPHEIGHT]) { 00599 /* We need to set the use_config values, even though we are not really using them, 00600 * because the setup processing basically expects the values returned from the 00601 * server to use these values. 00602 * Likewise, we need to call mapdata_set_size because we may try 00603 * to do map draws before we get the setup command from the server, and if it 00604 * is using the old values, that doesn't work quite right. 00605 */ 00606 use_config[CONFIG_MAPWIDTH] = w; 00607 use_config[CONFIG_MAPHEIGHT] = h; 00608 mapdata_set_size(use_config[CONFIG_MAPWIDTH], use_config[CONFIG_MAPHEIGHT]); 00609 cs_print_string(csocket.fd, 00610 "setup mapsize %dx%d", use_config[CONFIG_MAPWIDTH], use_config[CONFIG_MAPHEIGHT]); 00611 } 00612 return FALSE; 00613 } 00614 00615 00620 void draw_splash(void) 00621 { 00622 static GdkPixmap *splash; 00623 static int have_init=0; 00624 GdkBitmap *aboutgdkmask; 00625 int x,y, w, h; 00626 00627 #include "../../pixmaps/crossfiretitle.xpm" 00628 00629 if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_PIXMAP) { 00630 if (!have_init) { 00631 splash = gdk_pixmap_create_from_xpm_d(map_drawing_area->window, 00632 &aboutgdkmask, NULL, 00633 (gchar **)crossfiretitle_xpm); 00634 have_init=1; 00635 } 00636 gdk_window_clear(map_drawing_area->window); 00637 gdk_drawable_get_size(splash, &w, &h); 00638 x = (map_drawing_area->allocation.width- w)/2; 00639 y = (map_drawing_area->allocation.height - h)/2; 00640 /* 00641 * Clear the clip mask - it can be left in an inconsistent state from 00642 * last map redraw. 00643 */ 00644 gdk_gc_set_clip_mask(mapgc, NULL); 00645 gdk_draw_pixmap(map_drawing_area->window, mapgc, splash, 0, 0, 00646 x, y, w, h); 00647 } 00648 } 00649 00654 void draw_map(int redraw) 00655 { 00656 #ifdef HAVE_SDL 00657 if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) sdl_gen_map(redraw); 00658 else 00659 #endif 00660 #ifdef HAVE_OPENGL 00661 if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_OPENGL) opengl_gen_map(redraw); 00662 else 00663 #endif 00664 if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_PIXMAP) { 00665 if (cpl.input_state == Metaserver_Select) draw_splash(); 00666 else gtk_draw_map(redraw); 00667 } 00668 } 00669 00677 gboolean 00678 on_drawingarea_map_expose_event (GtkWidget *widget, 00679 GdkEventExpose *event, 00680 gpointer user_data) 00681 { 00682 draw_map(TRUE); 00683 return FALSE; 00684 } 00685 00693 gboolean 00694 on_drawingarea_map_button_press_event (GtkWidget *widget, 00695 GdkEventButton *event, 00696 gpointer user_data) 00697 { 00698 int dx, dy, i, x, y, xmidl, xmidh, ymidl, ymidh; 00699 00700 x=(int)event->x; 00701 y=(int)event->y; 00702 dx=(x-2)/map_image_size-(use_config[CONFIG_MAPWIDTH]/2); 00703 dy=(y-2)/map_image_size-(use_config[CONFIG_MAPHEIGHT]/2); 00704 xmidl=(use_config[CONFIG_MAPWIDTH]/2) * map_image_size; 00705 xmidh=(use_config[CONFIG_MAPWIDTH]/2 + 1) * map_image_size; 00706 ymidl=(use_config[CONFIG_MAPHEIGHT]/2) * map_image_size; 00707 ymidh=(use_config[CONFIG_MAPHEIGHT]/2 + 1) * map_image_size; 00708 00709 switch (event->button) { 00710 case 1: 00711 look_at(dx,dy); 00712 break; 00713 00714 case 2: 00715 case 3: 00716 if (x<xmidl) 00717 i = 0; 00718 else if (x>xmidh) 00719 i = 6; 00720 else i =3; 00721 00722 if (y>ymidh) 00723 i += 2; 00724 else if (y>ymidl) 00725 i++; 00726 00727 if (event->button==2) { 00728 switch (i) { 00729 case 0: fire_dir (8);break; 00730 case 1: fire_dir (7);break; 00731 case 2: fire_dir (6);break; 00732 case 3: fire_dir (1);break; 00733 case 5: fire_dir (5);break; 00734 case 6: fire_dir (2);break; 00735 case 7: fire_dir (3);break; 00736 case 8: fire_dir (4);break; 00737 } 00738 /* Only want to fire once */ 00739 clear_fire(); 00740 } 00741 else switch (i) { 00742 case 0: move_player (8);break; 00743 case 1: move_player (7);break; 00744 case 2: move_player (6);break; 00745 case 3: move_player (1);break; 00746 case 5: move_player (5);break; 00747 case 6: move_player (2);break; 00748 case 7: move_player (3);break; 00749 case 8: move_player (4);break; 00750 } 00751 } 00752 return FALSE; 00753 } 00754 00761 void display_map_startupdate(void) 00762 { 00763 } 00764 00772 void display_map_doneupdate(int redraw, int notice) 00773 { 00774 map_updated |= redraw || !notice; 00775 }