Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] (PR#2708) patch: backing rectangle for city descriptions i
Home

[Freeciv-Dev] (PR#2708) patch: backing rectangle for city descriptions i

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#2708) patch: backing rectangle for city descriptions in gtk2 client
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 31 Mar 2005 17:57:08 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=2708 >

Here's an updated patch.

TODO: make the full-style bars a tileset option.

-jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.225
diff -u -r1.225 mapview_common.c
--- client/mapview_common.c     31 Mar 2005 17:28:02 -0000      1.225
+++ client/mapview_common.c     1 Apr 2005 01:56:27 -0000
@@ -1158,6 +1158,10 @@
                       canvas_x, canvas_y, width, height);
 
   mapview_layer_iterate(layer) {
+    if (layer == LAYER_CITYBAR) {
+      show_city_descriptions(canvas_x, canvas_y, width, height);
+      continue;
+    }
     gui_rect_iterate(gui_x0, gui_y0, width,
                     height + (tileset_is_isometric(tileset)
                               ? (tileset_tile_height(tileset) / 2) : 0),
@@ -1197,8 +1201,6 @@
     } adjc_dir_iterate_end;
   } gui_rect_iterate_end;
 
-  show_city_descriptions(canvas_x, canvas_y, width, height);
-
   if (!full) {
     /* Swap store and tmp_store back. */
     tmp = mapview.store;
@@ -1251,62 +1253,167 @@
   city's tile).
 ****************************************************************************/
 static void show_city_desc(struct canvas *pcanvas,
-                          int canvas_x, int canvas_y,
+                          const int canvas_x0, const int canvas_y0,
                           struct city *pcity, int *width, int *height)
 {
-  static char name[512], growth[32], prod[512];
-  enum color_std growth_color;
+  const struct citybar_sprites *citybar = get_citybar_sprites(tileset);
+  const bool line1 = draw_city_names;
+  const bool line2 = ((draw_city_productions || draw_city_growth)
+                     && pcity->owner == game.player_idx);
+  static char name[512], growth[32], prod[512], size[32];
+  enum color_std growth_color, owner_color;
   struct {
     int x, y, w, h;
   } name_rect = {0, 0, 0, 0}, growth_rect = {0, 0, 0, 0},
-    prod_rect = {0, 0, 0, 0};
-  int extra_width = 0, total_width, total_height;
+    prod_rect = {0, 0, 0, 0}, size_rect = {0, 0, 0, 0},
+    flag_rect = {0, 0, 0, 0}, occupy_rect = {0, 0, 0, 0},
+    food_rect = {0, 0, 0, 0}, shield_rect = {0, 0, 0, 0};
+  int width1 = 0, width2 = 0, height1 = 0, height2 = 0;
+  struct sprite *bg = citybar->background;
+  struct sprite *flag = get_city_nation_flag_sprite(pcity);
+  struct sprite *occupy = NULL;
+  int bg_w, bg_h, x, y;
+  const int canvas_x = canvas_x0 + tileset_tile_width(tileset) / 2;
+  const int canvas_y = canvas_y0 + tileset_citybar_offset_y(tileset);
+  const int border = 6;
+  const enum client_font FONT_CITY_SIZE = FONT_CITY_NAME; /* TODO: new font */
 
+  get_sprite_dimensions(bg, &bg_w, &bg_h);
   *width = *height = 0;
 
-  canvas_x += tileset_tile_width(tileset) / 2;
-  canvas_y += tileset_citybar_offset_y(tileset);
+  if (!line1 && !line2) {
+    return;
+  }
 
-  if (draw_city_names) {
-    get_city_mapview_name_and_growth(pcity, name, sizeof(name),
-                                    growth, sizeof(growth), &growth_color);
+  /* First: calculate rect dimensions (but not positioning). */
+  get_city_mapview_name_and_growth(pcity, name, sizeof(name),
+                                  growth, sizeof(growth), &growth_color);
+  if (line1) {
+    my_snprintf(size, sizeof(size), "%d", pcity->size);
 
+    get_text_size(&size_rect.w, &size_rect.h, FONT_CITY_SIZE, size);
     get_text_size(&name_rect.w, &name_rect.h, FONT_CITY_NAME, name);
 
-    if (growth[0] != '\0') {
-      get_text_size(&growth_rect.w, &growth_rect.h, FONT_CITY_PROD, growth);
-      /* HACK: put a character's worth of space between the two strings. */
-      get_text_size(&extra_width, NULL, FONT_CITY_NAME, "M");
-    }
-    total_width = name_rect.w + extra_width + growth_rect.w;
-    total_height = MAX(name_rect.h, growth_rect.h);
-    canvas_put_text(pcanvas,
-                   canvas_x - total_width / 2, canvas_y,
-                   FONT_CITY_NAME, COLOR_STD_WHITE, name);
-    if (growth[0] != '\0') {
-      canvas_put_text(pcanvas,
-                     canvas_x - total_width / 2 + name_rect.w + extra_width,
-                     canvas_y + total_height - growth_rect.h,
-                     FONT_CITY_PROD, growth_color, growth);
+    if (can_player_see_units_in_city(game.player_ptr, pcity)) {
+      int count = unit_list_size(pcity->tile->units);
+
+      count = CLIP(0, count, citybar->occupancy.size - 1);
+      occupy = citybar->occupancy.p[count];
+    } else {
+      if (pcity->client.occupied) {
+       occupy = citybar->occupied;
+      } else {
+       occupy = citybar->occupancy.p[0];
+      }
     }
-    canvas_y += total_height + 3;
 
-    *width = MAX(*width, total_width);
-    *height += total_height + 3;
+    get_sprite_dimensions(flag, &flag_rect.w, &flag_rect.h);
+    get_sprite_dimensions(occupy, &occupy_rect.w, &occupy_rect.h);
+
+    width1 = (flag_rect.w + occupy_rect.w + name_rect.w
+             + 2 * border + size_rect.w);
+    height1 = MAX(flag_rect.h,
+                 MAX(occupy_rect.h,
+                     MAX(name_rect.h + border,
+                         size_rect.h + border)));
   }
-  if (draw_city_productions && pcity->owner == game.player_idx) {
+  if (line2) {
     get_city_mapview_production(pcity, prod, sizeof(prod));
     get_text_size(&prod_rect.w, &prod_rect.h, FONT_CITY_PROD, prod);
 
-    total_width = prod_rect.w;
-    total_height = prod_rect.h;
+    get_sprite_dimensions(citybar->shields, &shield_rect.w, &shield_rect.h);
 
-    canvas_put_text(pcanvas, canvas_x - total_width / 2, canvas_y,
-                   FONT_CITY_PROD, COLOR_STD_WHITE, prod);
+    get_text_size(&growth_rect.w, &growth_rect.h, FONT_CITY_PROD, growth);
+    get_sprite_dimensions(citybar->food, &food_rect.w, &food_rect.h);
+
+    width2 = (prod_rect.w + growth_rect.w + shield_rect.w + food_rect.w
+             + 2 * border);
+    height2 = MAX(shield_rect.h,
+                 MAX(prod_rect.h + border,
+                     MAX(growth_rect.h + border,
+                         food_rect.h)));
+  }
+
+  *width = MAX(width1, width2);
+  *height = height1 + height2;
+
+  /* Next fill in X and Y locations. */
+  if (line1) {
+    flag_rect.x = canvas_x - *width / 2;
+    flag_rect.y = canvas_y + (height1 - flag_rect.h) / 2;
+
+    occupy_rect.x = flag_rect.x + flag_rect.w;
+    occupy_rect.y = canvas_y + (height1 - occupy_rect.h) / 2;
 
-    canvas_y += total_height;
-    *width = MAX(*width, total_width);
-    *height += total_height;
+    name_rect.x = canvas_x + (flag_rect.w + occupy_rect.w
+                             - name_rect.w - size_rect.w - border) / 2;
+    name_rect.y = canvas_y + (height1 - name_rect.h) / 2;
+
+    size_rect.x = canvas_x + (*width + 1) / 2 - size_rect.w - border / 2;
+    size_rect.y = canvas_y + (height1 - size_rect.h) / 2;
+  }
+  if (line2) {
+    shield_rect.x = canvas_x - *width / 2;
+    shield_rect.y = canvas_y + height1 + (height2 - shield_rect.h) / 2;
+
+    prod_rect.x = shield_rect.x + shield_rect.w + border / 2;
+    prod_rect.y = canvas_y + height1 + (height2 - prod_rect.h) / 2;
+
+    growth_rect.x = canvas_x + (*width + 1) / 2 - growth_rect.w - border / 2;
+    growth_rect.y = canvas_y + height1 + (height2 - growth_rect.h) / 2;
+
+    food_rect.x = growth_rect.x - border / 2 - food_rect.w;
+    food_rect.y = canvas_y + height1 + (height2 - food_rect.h) / 2;
+  }
+
+  /* Now draw. */
+  for (x = 0; x < *width; x += bg_w) {
+    for (y = 0; y < *height; y += bg_h) {
+      canvas_put_sprite(pcanvas, canvas_x - *width / 2 + x, canvas_y + y,
+                       bg, 0, 0, *width - x, *height - y);
+    }
+  }
+  owner_color = player_color(city_owner(pcity));
+  if (line1) {
+    canvas_put_sprite_full(pcanvas, flag_rect.x, flag_rect.y, flag);
+    canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                   flag_rect.x + flag_rect.w - 1, canvas_y,
+                   0, height1);
+    canvas_put_sprite_full(pcanvas, occupy_rect.x, occupy_rect.y, occupy);
+    canvas_put_text(pcanvas, name_rect.x, name_rect.y,
+                   FONT_CITY_NAME, COLOR_STD_WHITE, name);
+
+    canvas_put_rectangle(pcanvas, owner_color,
+                        size_rect.x - border / 2, canvas_y,
+                        size_rect.w + border, height1);
+    canvas_put_text(pcanvas, size_rect.x, size_rect.y,
+                   FONT_CITY_NAME, COLOR_STD_WHITE, size);
+  }
+  if (line2) {
+    canvas_put_sprite_full(pcanvas, shield_rect.x, shield_rect.y,
+                          citybar->shields);
+    canvas_put_text(pcanvas, prod_rect.x, prod_rect.y,
+                   FONT_CITY_PROD, COLOR_STD_WHITE, prod);
+    canvas_put_sprite_full(pcanvas, food_rect.x, food_rect.y, citybar->food);
+    canvas_put_text(pcanvas, growth_rect.x, growth_rect.y,
+                     FONT_CITY_PROD, growth_color, growth);
+  }
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2, canvas_y,
+                 *width, 0);
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2, canvas_y,
+                 0, *height);
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2, canvas_y + *height - 1,
+                 *width, 0);
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2 + *width, canvas_y,
+                 0, *height);
+  if (line1 && line2) {
+    canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                   canvas_x - *width / 2, canvas_y + height1 - 1,
+                   *width, 0);
   }
 }
 
@@ -1919,7 +2026,7 @@
 
 /**************************************************************************
   Fill the two buffers which information about the city which is shown
-  below it. It takes draw_city_names and draw_city_growth into account.
+  below it. It does not take draw_city_names/draw_city_growth into account.
 **************************************************************************/
 void get_city_mapview_name_and_growth(struct city *pcity,
                                      char *name_buffer,
@@ -1928,16 +2035,9 @@
                                      size_t growth_buffer_len,
                                      enum color_std *growth_color)
 {
-  if (!draw_city_names) {
-    name_buffer[0] = '\0';
-    growth_buffer[0] = '\0';
-    *growth_color = COLOR_STD_WHITE;
-    return;
-  }
-
   my_snprintf(name_buffer, name_buffer_len, pcity->name);
 
-  if (draw_city_growth && pcity->owner == game.player_idx) {
+  if (pcity->owner == game.player_idx) {
     int turns = city_turns_to_grow(pcity);
 
     if (turns == 0) {
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.284
diff -u -r1.284 tilespec.c
--- client/tilespec.c   31 Mar 2005 17:28:02 -0000      1.284
+++ client/tilespec.c   1 Apr 2005 01:56:28 -0000
@@ -204,6 +204,7 @@
     struct sprite_vector worked_tile_overlay;
     struct sprite_vector unworked_tile_overlay;
   } city;
+  struct citybar_sprites citybar;
   struct {
     struct sprite
       *turns[NUM_TILES_DIGITS],
@@ -1912,6 +1913,26 @@
     }
   }
 
+  SET_SPRITE(citybar.shields, "citybar.shields");
+  SET_SPRITE(citybar.food, "citybar.food");
+  SET_SPRITE(citybar.occupied, "citybar.occupied");
+  SET_SPRITE(citybar.background, "citybar.background");
+  sprite_vector_init(&t->sprites.citybar.occupancy);
+  for (i = 0; ; i++) {
+    struct sprite *sprite;
+
+    my_snprintf(buffer, sizeof(buffer), "citybar.occupancy_%d", i);
+    sprite = load_sprite(t, buffer);
+    if (!sprite) {
+      break;
+    }
+    sprite_vector_append(&t->sprites.citybar.occupancy, &sprite);
+  }
+  if (t->sprites.citybar.occupancy.size < 2) {
+    freelog(LOG_FATAL, "Missing necessary citybar.occupancy_N sprites.");
+    exit(EXIT_FAILURE);
+  }
+
   SET_SPRITE(city.disorder, "city.disorder");
 
   for(i=0; i<NUM_TILES_DIGITS; i++) {
@@ -2511,7 +2532,7 @@
 /**********************************************************************
   Return the flag graphic to be used by the city.
 ***********************************************************************/
-static struct sprite *get_city_nation_flag_sprite(const struct city *pcity)
+struct sprite *get_city_nation_flag_sprite(const struct city *pcity)
 {
   return get_nation_by_plr(city_owner(pcity))->flag_sprite;
 }
@@ -2561,6 +2582,7 @@
   return t->sprites.city.tile[style][city_styles[style].tiles_num];
 }
 
+#if 0
 /**************************************************************************
 Return the sprite needed to draw the occupied tile
 **************************************************************************/
@@ -2571,6 +2593,7 @@
 
   return t->sprites.city.tile[style][city_styles[style].tiles_num + 1];
 }
+#endif
 
 #define FULL_TILE_X_OFFSET ((t->normal_tile_width - t->full_tile_width) / 2)
 #define FULL_TILE_Y_OFFSET (t->normal_tile_height - t->full_tile_height)
@@ -3771,15 +3794,19 @@
   case LAYER_CITY1:
     /* City.  Some city sprites are drawn later. */
     if (pcity && draw_cities) {
+#if 0
       if (!solid_color_behind_units) {
        ADD_SPRITE(get_city_nation_flag_sprite(pcity), TRUE,
                   FULL_TILE_X_OFFSET + t->flag_offset_x,
                   FULL_TILE_Y_OFFSET + t->flag_offset_y);
       }
+#endif
       ADD_SPRITE_FULL(get_city_sprite(t, pcity));
+#if 0
       if (pcity->client.occupied) {
        ADD_SPRITE_FULL(get_city_occupied_sprite(t, pcity));
       }
+#endif
       if (!t->is_isometric && city_got_citywalls(pcity)) {
        /* In iso-view the city wall is a part of the city sprite. */
        ADD_SPRITE_SIMPLE(get_city_wall_sprite(t, pcity));
@@ -3810,6 +3837,7 @@
     break;
 
   case LAYER_CITY2:
+#if 0
     /* City size.  Drawing this under fog makes it hard to read. */
     if (pcity && draw_cities) {
       if (pcity->size >= 10) {
@@ -3819,6 +3847,7 @@
       ADD_SPRITE(t->sprites.city.size[pcity->size % 10],
                 FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
     }
+#endif
     break;
 
   case LAYER_UNIT:
@@ -3864,6 +3893,10 @@
     }
     break;
 
+  case LAYER_CITYBAR:
+    /* Nothing.  This is just a placeholder. */
+    break;
+
   case LAYER_GOTO:
     sprs += fill_goto_sprite_array(t, sprs, ptile, pedge, pcorner);
     break;
@@ -4152,6 +4185,7 @@
   } specfile_list_iterate_end;
 
   sprite_vector_free(&t->sprites.explode.unit);
+  sprite_vector_free(&t->sprites.citybar.occupancy);
 }
 
 /**************************************************************************
@@ -4277,6 +4311,14 @@
 }
 
 /**************************************************************************
+  Return all the sprites used for citybar drawing.
+**************************************************************************/
+const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
+{
+  return &t->sprites.citybar;
+}
+
+/**************************************************************************
   Returns a sprite for the given cursor.  The "hot" coordinates (the
   active coordinates of the mouse relative to the sprite) are placed int
   (*hot_x, *hot_y).
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.143
diff -u -r1.143 tilespec.h
--- client/tilespec.h   31 Mar 2005 17:28:02 -0000      1.143
+++ client/tilespec.h   1 Apr 2005 01:56:28 -0000
@@ -79,6 +79,7 @@
   LAYER_SPECIAL3,
   LAYER_GRID2,
   LAYER_OVERLAYS,
+  LAYER_CITYBAR,
   LAYER_FOCUS_UNIT,
   LAYER_GOTO,
   LAYER_COUNT
@@ -172,6 +173,15 @@
   SPACESHIP_COUNT
 };
 
+struct citybar_sprites {
+  struct sprite
+    *shields,
+    *food,
+    *occupied,
+    *background;
+  struct sprite_vector occupancy;
+};
+
 struct sprite *get_spaceship_sprite(const struct tileset *t,
                                    enum spaceship_part part);
 struct sprite *get_citizen_sprite(const struct tileset *t,
@@ -180,6 +190,7 @@
                                  const struct city *pcity);
 struct sprite *get_nation_flag_sprite(const struct tileset *t,
                                      const struct nation_type *nation);
+struct sprite *get_city_nation_flag_sprite(const struct city *pcity);
 struct sprite *get_tech_sprite(const struct tileset *t, Tech_Type_id tech);
 struct sprite *get_sample_city_sprite(const struct tileset *t,
                                      int city_style);
@@ -192,6 +203,7 @@
 struct sprite *get_cursor_sprite(const struct tileset *t,
                                 enum cursor_type cursor,
                                 int *hot_x, int *hot_y);
+const struct citybar_sprites *get_citybar_sprites(const struct tileset *t);
 struct sprite *get_icon_sprite(const struct tileset *t, enum icon_type icon);
 struct sprite *get_attention_crosshair_sprite(const struct tileset *t);
 struct sprite *get_indicator_sprite(const struct tileset *t,
Index: data/isophex.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isophex.tilespec,v
retrieving revision 1.12
diff -u -r1.12 isophex.tilespec
--- data/isophex.tilespec       18 Mar 2005 00:38:55 -0000      1.12
+++ data/isophex.tilespec       1 Apr 2005 01:56:28 -0000
@@ -36,6 +36,9 @@
 ; offset the citybar text by this amount (from the city tile origin)
 citybar_offset_y = 20
 
+; offset the citybar text by this amount (from the city tile origin)
+citybar_offset_y = 20
+
 ; Hex data.
 is_hex = 1
 is_isometric = 0
@@ -62,6 +65,7 @@
 files = 
   "misc/colors.spec",
   "misc/overlays.spec",
+  "misc/citybar.spec",
   "isophex/terrain1.spec",
   "isophex/terrain2.spec",
   "isophex/darkness.spec",
Index: data/isotrident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident.tilespec,v
retrieving revision 1.35
diff -u -r1.35 isotrident.tilespec
--- data/isotrident.tilespec    18 Mar 2005 00:38:55 -0000      1.35
+++ data/isotrident.tilespec    1 Apr 2005 01:56:28 -0000
@@ -38,6 +38,9 @@
 ; offset the citybar text by this amount (from the city tile origin)
 citybar_offset_y = 20
 
+; offset the citybar text by this amount (from the city tile origin)
+citybar_offset_y = 20
+
 ; Font size (points) to use to draw city names and productions:
 city_names_font_size = 10
 city_productions_font_size = 10
@@ -54,6 +57,7 @@
 files = 
   "misc/colors.spec",
   "misc/overlays.spec",
+  "misc/citybar.spec",
   "isotrident/terrain1.spec",
   "isotrident/terrain2.spec",
   "isotrident/tiles.spec",
Index: data/trident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident.tilespec,v
retrieving revision 1.35
diff -u -r1.35 trident.tilespec
--- data/trident.tilespec       18 Mar 2005 00:38:55 -0000      1.35
+++ data/trident.tilespec       1 Apr 2005 01:56:29 -0000
@@ -34,6 +34,9 @@
 ; offset the citybar text by this amount (from the city tile origin)
 citybar_offset_y = 27
 
+; offset the citybar text by this amount (from the city tile origin)
+citybar_offset_y = 27
+
 ; Font size (points) to use to draw city names and productions:
 city_names_font_size = 10
 city_productions_font_size = 10
@@ -50,6 +53,7 @@
 files = 
   "misc/colors.spec",
   "misc/overlays.spec",
+  "misc/citybar.spec",
   "trident/tiles.spec",
   "misc/small.spec",
   "trident/units.spec",
Index: data/trident_shields.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident_shields.tilespec,v
retrieving revision 1.26
diff -u -r1.26 trident_shields.tilespec
--- data/trident_shields.tilespec       18 Mar 2005 00:38:55 -0000      1.26
+++ data/trident_shields.tilespec       1 Apr 2005 01:56:29 -0000
@@ -25,6 +25,9 @@
 ; offset the citybar text by this amount (from the city tile origin)
 citybar_offset_y = 27
 
+; offset the citybar text by this amount (from the city tile origin)
+citybar_offset_y = 27
+
 ; Do not blend hills and mountains together.
 is_mountainous = 0
 
@@ -53,6 +56,7 @@
 files = 
   "misc/colors.spec",
   "misc/overlays.spec",
+  "misc/citybar.spec",
   "trident/tiles.spec",
   "misc/small.spec",
   "trident/units.spec",

[Prev in Thread] Current Thread [Next in Thread]