/* * Copyright (C) 2003 Tim Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "sdlwin.h" #include "sdl.h" #include "landvalue.h" #include "map.h" #include "utils.h" #include #include "SDL_rotozoom.h" SDL_Surface *sdlscreen = NULL; SDLFont *myfont = NULL; static int sdlwin_inited = 0; int ownercolors[][3] = { {255, 255, 255}, {60, 175, 80}, {255, 255, 0}, {255, 75, 125}, {125, 100, 255}, {255, 0, 255}, }; static SDL_Surface * resize_image(SDL_Surface *src, int request_width) { double zoom = (double)request_width/src->w; return zoomSurface(src, zoom, zoom, 0); } /* Integer math version of SDL_ScaleBlit(). * Where necessary, a number uses the 16 high bits for the integer * and the 16 low bits for the decimal portion. * * eg: * float a = (float) (b >> 16) + (b & 0xFFFF)/65536.0; */ static inline Uint32 ifloor(Uint32 i) { return i & 0xFFFF0000; } static inline Uint32 iceil(Uint32 i) { return (i & 0xFFFF) ? i : ifloor(i) + (1<<16); } static int set_alpha(int specials, SDL_Surface *image) { int alpha = 255; if ((specials & MAPSPECIAL_HILITE) == MAPSPECIAL_HILITE) { alpha -= 50; } if ((specials & MAPSPECIAL_HILITE_INVALID) == MAPSPECIAL_HILITE_INVALID) { alpha -= 100; } if ((specials & MAPSPECIAL_CURSOR) == MAPSPECIAL_CURSOR) { alpha -= 100; } if ((specials & MAPSPECIAL_SELECTED) == MAPSPECIAL_SELECTED) { alpha -= 60; } if (alpha < 100) alpha = 100; if (alpha < 255) { SDL_SetAlpha(image, SDL_SRCALPHA, alpha); } return alpha; } static void reset_alpha(int alpha, SDL_Surface *image) { if (alpha < 255) { SDL_SetAlpha(image, SDL_SRCALPHA, 255); } } static void ShowImg(SDL_Surface *screen, SDL_Surface *image, int x, int y, int specials) { SDL_Rect dest; int alpha; if (!image) return; /* Blit onto the screen surface. The surfaces should not be locked at this point. */ dest.x = x; dest.y = y; dest.w = image->w; dest.h = image->h; alpha = set_alpha(specials, image); SDL_BlitSurface(image, NULL, screen, &dest); reset_alpha(alpha, image); } void sdlwin_clearscreen(void) { SDL_Rect rect; rect.x = 0; rect.y = 0; rect.w = sdlscreen->w-1; rect.h = sdlscreen->h-1; SDL_FillRect(sdlscreen, &rect, SDL_MapRGB(sdlscreen->format, 0, 0, 0)); } void sdlwin_updatescreen(void) { SDL_Rect dest; dest.x = 0; dest.y = 0; dest.w = sdlscreen->w-1; dest.h = sdlscreen->h-1; SDL_UpdateRects(sdlscreen, 1, &dest); } int sdlwin_init(GtkWidget *widget) { /* Hack to get SDL to use GTK window */ { char SDL_windowhack[32]; sprintf(SDL_windowhack,"SDL_WINDOWID=%ld", GDK_WINDOW_XWINDOW(widget->window)); putenv(SDL_windowhack); } /* Initialize SDL */ if (!sdlwin_inited) { if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr,_("Couldn't initialize SDL: %s\n"),SDL_GetError()); gtk_main_quit(); } } if (sdlscreen) SDL_FreeSurface(sdlscreen); sdlscreen = SDL_SetVideoMode(widget->allocation.width, widget->allocation.height, 0, SDL_RESIZABLE); sdlwin_updatescreen(); if (!myfont) { myfont = load_fixed_font(IMG_DIRECTORY "f_small_green.bmp", 32, 96, 8 ); if (!myfont) { myfont = load_fixed_font( "../img/f_small_green.bmp", 32, 96, 8 ); if (!myfont) { printf(_("Unable to load font!\n")); } } } sdlwin_inited = 1; return 0; } static void draw_grid_lines(display_t *display, square_t *drawsquare, int owner, map_t *map, int mapx, int mapy) { Uint32 gridlinecolor = -1; gridlinecolor = SDL_MapRGB(sdlscreen->format, ownercolors[owner][0], ownercolors[owner][1], ownercolors[owner][2]); /* draw grid lines */ DoLine(sdlscreen, drawsquare->parts.leftx, drawsquare->parts.lefty, drawsquare->parts.topx, drawsquare->parts.topy, gridlinecolor, 255); DoLine(sdlscreen, drawsquare->parts.topx, drawsquare->parts.topy, drawsquare->parts.rightx, drawsquare->parts.righty, gridlinecolor, 255); DoLine(sdlscreen, drawsquare->parts.rightx, drawsquare->parts.righty, drawsquare->parts.botx, drawsquare->parts.boty, gridlinecolor, 255); DoLine(sdlscreen, drawsquare->parts.botx, drawsquare->parts.boty, drawsquare->parts.leftx, drawsquare->parts.lefty, gridlinecolor, 255); /* * If in owner view display another set of lines closer in */ if ((display->view == GAMEVIEW_OWNERS) && (owner > 0)) { if ((mapx == 0) || (map_get_owner(map, mapx-1, mapy) != owner)) { DoLine(sdlscreen, drawsquare->parts.leftx+3, drawsquare->parts.lefty, drawsquare->parts.topx, drawsquare->parts.topy+2, gridlinecolor, 255); DoLine(sdlscreen, drawsquare->parts.leftx+6, drawsquare->parts.lefty, drawsquare->parts.topx, drawsquare->parts.topy+4, gridlinecolor, 255); } if ((mapy == 0) || (map_get_owner(map, mapx, mapy-1) != owner)) { DoLine(sdlscreen, drawsquare->parts.topx, drawsquare->parts.topy+2, drawsquare->parts.rightx-3, drawsquare->parts.righty, gridlinecolor, 255); DoLine(sdlscreen, drawsquare->parts.topx, drawsquare->parts.topy+4, drawsquare->parts.rightx-6, drawsquare->parts.righty, gridlinecolor, 255); } if ((mapx == map_get_sizex(map)-1) || (map_get_owner(map, mapx+1, mapy) != owner)) { DoLine(sdlscreen, drawsquare->parts.rightx-3, drawsquare->parts.righty, drawsquare->parts.botx, drawsquare->parts.boty-2, gridlinecolor, 255); DoLine(sdlscreen, drawsquare->parts.rightx-6, drawsquare->parts.righty, drawsquare->parts.botx, drawsquare->parts.boty-4, gridlinecolor, 255); } if ((mapy == map_get_sizey(map)-1) || (map_get_owner(map, mapx, mapy+1) != owner)) { DoLine(sdlscreen, drawsquare->parts.botx, drawsquare->parts.boty-2, drawsquare->parts.leftx+3, drawsquare->parts.lefty, gridlinecolor, 255); DoLine(sdlscreen, drawsquare->parts.botx, drawsquare->parts.boty-4, drawsquare->parts.leftx+6, drawsquare->parts.lefty, gridlinecolor, 255); } } } static void fillsquare(int r, int g, int b, int a, square_t *drawsquare) { Uint32 color; color = SDL_MapRGBA(sdlscreen->format, r, g, b, a); DoFilledPolygon (sdlscreen, drawsquare->parts.leftx, drawsquare->parts.lefty, drawsquare->parts.topx, drawsquare->parts.topy, drawsquare->parts.rightx, drawsquare->parts.righty, drawsquare->parts.botx, drawsquare->parts.boty, color, a); } static void ShowPattern(SDL_Surface *screen, SDL_Surface *pattern, square_t *drawsquare, int specials) { int alpha; alpha = set_alpha(specials, pattern); DoPattern (sdlscreen, drawsquare->parts.leftx, drawsquare->parts.lefty, drawsquare->parts.topx, drawsquare->parts.topy, drawsquare->parts.rightx, drawsquare->parts.righty, drawsquare->parts.botx, drawsquare->parts.boty, pattern); reset_alpha(alpha, pattern); } #if 0 static void ShowSolid(SDL_Surface *screen, int r, int g, int b, square_t *square, int specials) { int alpha = set_alpha(specials, sdlscreen); fillsquare(r, g, b, alpha, square); reset_alpha(alpha, sdlscreen); } #endif /* 0 */ static void ShowSolid_minus(SDL_Surface *screen, int r, int g, int b, square_t *square, int minus, int specials) { int alpha = set_alpha(specials, sdlscreen); square_t sq2; sq2.parts.topx = square->parts.topx; sq2.parts.rightx = square->parts.rightx - minus; sq2.parts.leftx = square->parts.leftx + minus; sq2.parts.botx = square->parts.botx; sq2.parts.topy = square->parts.topy + minus; sq2.parts.righty = square->parts.righty; sq2.parts.lefty = square->parts.lefty; sq2.parts.boty = square->parts.boty - minus; fillsquare(r, g, b, alpha, &sq2); reset_alpha(alpha, sdlscreen); } static void show_tile(display_t *display, tiles_t *tiles, screen_t *screen, mapobj_t mapobj, int x, int y, int sx, int sy, surrounding_t *surrounding, heightsquare_t *heightsquare, square_t *drawsquare, int dirview, int zoom, int specials) { tile_t *tile; int tilesizex; int tilesizey; int tileheight; screen_tilesizes(screen, &tilesizex, &tilesizey, &tileheight); if (!display->showbuildings) { #if 0 /* xxx */ switch (map_item_gettype(mapobj)) { case MAPTYPE_GOVERNMENT: case MAPTYPE_EMPTY: case MAPTYPE_ENTERTAINMENT: /* don't change */ break; case MAPTYPE_HOUSE: mapobj = MAPOBJ_ZONE_HOUSE; break; case MAPTYPE_COMMERCIAL: mapobj = MAPOBJ_ZONE_COMMERCIAL; break; case MAPTYPE_OFFICE: mapobj = MAPOBJ_ZONE_OFFICE; break; case MAPTYPE_INDUSTRIAL: mapobj = MAPOBJ_ZONE_INDUSTRIAL; break; case MAPTYPE_FARM: mapobj = MAPOBJ_ZONE_FARM; break; } #endif /* 0 */ } if (tiles_get(tiles, mapobj, surrounding, heightsquare, &tile) == 0) { void *image = tile_image(tiles, tile, dirview, zoom); if (image) { if (tile->ispattern) { ShowPattern(sdlscreen, image, drawsquare, specials); } else { ShowImg(sdlscreen, image, x - ((sy-1)*tilesizex/2), y - heightsquare->dir.topleft*tileheight - tile->extray[dirview][zoom] - (sx-1+sy-1)*tilesizey/2, specials); } } else { ShowSolid_minus(sdlscreen, tile->color_r, tile->color_g, tile->color_b, drawsquare, 1, specials); } } else { printf(_("unable to get tile! obj = %d\n"), mapobj); } } static void display_land_value(map_t *map, tiles_t *tiles, int mapx, int mapy, square_t *drawsquare, int zoom, int owner, int activity) { int value; char str[10]; int strheight = 0; int strwidth; if (zoom >= 2) return; switch (activity) { case MAPOBJ_ACTION_BUYLAND: if (!map_empty_land(map, mapx, mapy)) return; /* fallthru */ case MAPOBJ_ACTION_BUYALL: if (owner != NO_OWNER) return; break; case MAPOBJ_ACTION_SELLLAND: if (!map_empty_land(map, mapx, mapy)) return; /* fallthru */ case MAPOBJ_ACTION_SELLALL: if (owner == NO_OWNER) return; break; default: return; } value = government_calculate_onelandvalue(map, tiles, mapx, mapy); snprintf(str, sizeof(str),"$%d",value); strwidth = text_width(myfont, str); strheight = 12; /* xxx */ write_text(myfont, sdlscreen, (drawsquare->parts.leftx + drawsquare->parts.rightx)/2 - strwidth/2, (drawsquare->parts.lefty + drawsquare->parts.righty)/2 - strheight/2, str, OPAQUE); } void sdlwin_draw_spot(display_t *display, map_t *map, player_t *me, screen_t *screen, tiles_t *tiles, int screen_moved, int mapx, int mapy, int x, int y) { square_t drawsquare; mapobj_t mapobj; surrounding_t surrounding; heightsquare_t heightsquare; int specials; int owner = -1; int zoom = screen_getzoom(screen); int screen_dirview = screen_getdirview(screen); int tilesizex; int tilesizey; int tileheight; int sx; int sy; int i; int j; int topx; int topy; int xoffset; screen_tilesizes(screen, &tilesizex, &tilesizey, &tileheight); /* * Get info on this spot */ mapobj = map_get_info(map, mapx, mapy, screen_dirview, &surrounding, &heightsquare, &specials, me, &owner); /* * If tile is bigger than 1x1 do the right thing */ tiles_getsize(tiles, mapobj, &sx, &sy); topx = mapx; topy = mapy; map_find_tiletop(map, &topx, &topy); switch(screen_dirview) { case 0: if ((mapx != topx+sx-1) || (mapy != topy+sy-1)) { return; } break; case 1: if ((mapx != topx+sx-1) || (mapy != topy)) { return; } break; case 2: if ((mapx != topx) || (mapy != topy)) { return; } break; case 3: if ((mapx != topx) || (mapy != topy+sy-1)) { return; } break; } /* * Figure out where we're drawing */ xoffset = (sy - sx)*tilesizex; drawsquare.parts.topx = x + xoffset + tilesizex/2; drawsquare.parts.rightx = x + xoffset + tilesizex*(1+sx)/2; drawsquare.parts.leftx = x + xoffset - tilesizex*(sy-1)/2; drawsquare.parts.botx = x + xoffset + tilesizex*(1+sx-sy)/2; drawsquare.parts.topy = y + 0 - heightsquare.dir.topleft*tileheight; drawsquare.parts.righty = y + tilesizey*sx/2 - heightsquare.dir.topright*tileheight; drawsquare.parts.lefty = y + tilesizey*sy/2 - heightsquare.dir.botleft*tileheight; drawsquare.parts.boty = y + tilesizey*(sx+sy)/2 - heightsquare.dir.botright*tileheight; /* * xxx */ if (screen_moved) { screen_viewarea_set(screen, mapx, mapy, &drawsquare); } /* * If highlighted check if can really place that there */ if (display->activity == MAPOBJ_ACTION_FLATTEN) { if (specials & MAPSPECIAL_HILITE_INVALID) { fillsquare(255, 0, 0, 255, &drawsquare); } else if ((specials) || (mapspot_is_in_list(display->height_change_list, mapx, mapy))) { fillsquare(0, 0, 0, 255, &drawsquare); } } else if (specials) { if (specials & MAPSPECIAL_HILITE_INVALID) { fillsquare(255, 0, 0, 255, &drawsquare); } else { fillsquare(0, 0, 0, 255, &drawsquare); } } if ((display->grid) && (zoom < 3)) { draw_grid_lines(display, &drawsquare, owner, map, mapx, mapy); } switch (display->view) { case GAMEVIEW_OWNERS: ShowSolid_minus(sdlscreen, ownercolors[owner][0], ownercolors[owner][1], ownercolors[owner][2], &drawsquare, 1, specials); break; case GAMEVIEW_MINE: if (owner == player_getnum(me)) { show_tile(display, tiles, screen, mapobj, x, y, sx, sy, &surrounding, &heightsquare, &drawsquare, screen_dirview, zoom, specials); } else { ShowSolid_minus(sdlscreen, 170, 170, 170, &drawsquare, 1, specials); } break; case GAMEVIEW_NORMAL: show_tile(display, tiles, screen, mapobj, x, y, sx, sy, &surrounding, &heightsquare, &drawsquare, screen_dirview, zoom, specials); break; case GAMEVIEW_POLICE_COVER: case GAMEVIEW_HOSPITAL_COVER: case GAMEVIEW_FIRE_COVER: if (map_item_gettype(mapobj) == display->viewtype) { ShowSolid_minus(sdlscreen, 10, 10, 10, &drawsquare, 1, specials); } else if (mapspot_within_range(display->objlist, mapx, mapy, map, tiles)) { ShowSolid_minus(sdlscreen, 150, 150, 150, &drawsquare, 1, specials); } else { show_tile(display, tiles, screen, mapobj, x, y, sx, sy, &surrounding, &heightsquare, &drawsquare, screen_dirview, zoom, specials); } break; } /* * Draw land value if buying land */ display_land_value(map, tiles, mapx, mapy, &drawsquare, zoom, owner, display->activity); } void *sdlwin_loadimage(char *filename, int request_width, int request_height, int *extra_height, void *rock) { SDL_Surface *buf; SDL_Surface *image; buf = IMG_Load(filename); if (!buf) { printf(_("Error loading %s\n"), filename); return NULL; } if (request_width != buf->w) { image = resize_image(buf, request_width); SDL_FreeSurface(buf); } else { image = buf; } *extra_height = image->h - request_height; /* image = SDL_DisplayFormat(image); */ /* Set colorkey for non-opaque tiles */ if (strstr(filename, "png")) { /* SDL_SetColorKey(image, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGBA(image->format, 0, 0, 0, 0)); */ } else { SDL_SetColorKey(image, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGBA(image->format, 255, 255, 255, 255)); } return image; }