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

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

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#2708) patch: backing rectangle for city descriptions in gtk2 client
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 13 Mar 2005 19:34:27 -0800
Reply-to: bugs@xxxxxxxxxxx

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

Screenshot at 
http://bugs.freeciv.org/Ticket/Attachment/92441/58872/citybar-ss.jpeg. 
(The jpeg messes up the colors a bit, but a PNG was too big and RT 
rejected it.)

This patch implements freim's proposed citybar format.  Apply the patch 
and untar the tarball in the top-level directory.

There are two problems with it:

1.  It's big, and you can't see stuff behind it.  The most important 
thing here is the focus unit.  I think this should be easily solved by 
putting the citybar in a layer underneath the focus-unit layer (and 
probably also underneath the fog).

2.  It's big.  Too big to really work with a smaller tileset (isotrident 
is okay because adjacent tiles are offset, but trident isn't so good). 
This could be improved by making the graphics and/or text smaller 
(tileset authors have complete control of this).  However I think this 
is going to be a problem.  Maybe we can make it more configurable so 
that each individual element can be turned on or off (right now if part 
of a line is present the whole line is present).

-jason


? data/misc/citybar.png
? data/misc/citybar.spec
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.213
diff -u -r1.213 mapview_common.c
--- client/mapview_common.c     13 Mar 2005 17:53:44 -0000      1.213
+++ client/mapview_common.c     14 Mar 2005 03:22:09 -0000
@@ -1233,62 +1233,166 @@
   city's tile).
 ****************************************************************************/
 static void show_city_desc(struct canvas *pcanvas,
-                          int canvas_x, int canvas_y,
+                          const int canvas_xx, const int canvas_yy,
                           struct city *pcity, int *width, int *height)
 {
-  static char name[512], growth[32], prod[512];
-  enum color_std growth_color;
+  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_xx + NORMAL_TILE_WIDTH / 2;
+  const int canvas_y = canvas_yy + NORMAL_TILE_HEIGHT;
+  const int border = 6;
 
+  get_sprite_dimensions(bg, &bg_w, &bg_h);
   *width = *height = 0;
 
-  canvas_x += NORMAL_TILE_WIDTH / 2;
-  canvas_y += NORMAL_TILE_HEIGHT;
+  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);
 
-    canvas_y += total_height;
-    *width = MAX(*width, total_width);
-    *height += total_height;
+    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;
+
+    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_SIZE, 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);
   }
 }
 
@@ -1324,7 +1428,7 @@
    */
   gui_rect_iterate(mapview.gui_x0 + canvas_x - dx / 2,
                   mapview.gui_y0 + canvas_y - dy,
-                  width + dx, height + dy - NORMAL_TILE_HEIGHT,
+                  width + dx, height + dy,
                   ptile, pedge, pcorner, gui_x, gui_y) {
     const int canvas_x = gui_x - mapview.gui_x0;
     const int canvas_y = gui_y - mapview.gui_y0;
@@ -1900,7 +2004,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,
@@ -1909,16 +2013,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/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.106
diff -u -r1.106 mapview_common.h
--- client/mapview_common.h     11 Mar 2005 17:11:26 -0000      1.106
+++ client/mapview_common.h     14 Mar 2005 03:22:10 -0000
@@ -56,6 +56,7 @@
 extern struct overview overview;
 
 enum client_font {
+  FONT_CITY_SIZE,
   FONT_CITY_NAME,
   FONT_CITY_PROD,
   FONT_COUNT
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.266
diff -u -r1.266 tilespec.c
--- client/tilespec.c   13 Mar 2005 17:53:44 -0000      1.266
+++ client/tilespec.c   14 Mar 2005 03:22:14 -0000
@@ -1577,6 +1577,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(&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(&sprites.citybar.occupancy, &sprite);
+  }
+  if (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++) {
@@ -2172,7 +2192,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;
 }
@@ -2220,6 +2240,7 @@
   return sprites.city.tile[style][city_styles[style].tiles_num];
 }
 
+#if 0
 /**************************************************************************
 Return the sprite needed to draw the occupied tile
 **************************************************************************/
@@ -2229,6 +2250,7 @@
 
   return sprites.city.tile[style][city_styles[style].tiles_num+1];
 }
+#endif
 
 #define FULL_TILE_X_OFFSET ((NORMAL_TILE_WIDTH - UNIT_TILE_WIDTH) / 2)
 #define FULL_TILE_Y_OFFSET (NORMAL_TILE_HEIGHT - UNIT_TILE_HEIGHT)
@@ -3427,15 +3449,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(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(pcity));
@@ -3466,6 +3492,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) {
@@ -3475,6 +3502,7 @@
       ADD_SPRITE(sprites.city.size[pcity->size % 10],
                 FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
     }
+#endif
     break;
 
   case LAYER_UNIT:
@@ -3833,6 +3861,7 @@
   } specfile_list_iterate_end;
 
   sprite_vector_free(&sprites.explode.unit);
+  sprite_vector_free(&sprites.citybar.occupancy);
 }
 
 /**************************************************************************
@@ -3915,6 +3944,14 @@
 }
 
 /**************************************************************************
+  Return all the sprites used for citybar drawing.
+**************************************************************************/
+struct citybar_sprites *get_citybar_sprites(struct tileset *t)
+{
+  return &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.127
diff -u -r1.127 tilespec.h
--- client/tilespec.h   11 Mar 2005 17:11:26 -0000      1.127
+++ client/tilespec.h   14 Mar 2005 03:22:14 -0000
@@ -206,6 +206,15 @@
   INDICATOR_COUNT
 };
 
+struct citybar_sprites {
+  struct Sprite
+    *shields,
+    *food,
+    *occupied,
+    *background;
+  struct sprite_vector occupancy;
+};
+
 struct named_sprites {
   struct Sprite
     *indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS],
@@ -305,6 +314,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],
@@ -363,6 +373,8 @@
 struct Sprite *get_tax_sprite(Output_type_id otype);
 struct Sprite *get_treaty_thumb_sprite(bool on_off);
 struct sprite_vector *get_unit_explode_animation(void);
+struct Sprite *get_city_nation_flag_sprite(const struct city *pcity);
+struct citybar_sprites *get_citybar_sprites(struct tileset *t);
 struct Sprite *get_cursor_sprite(enum cursor_type cursor,
                                 int *hot_x, int *hot_y);
 struct Sprite *get_attention_crosshair_sprite(void);
Index: client/gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.165
diff -u -r1.165 mapview.c
--- client/gui-gtk-2.0/mapview.c        11 Mar 2005 22:40:53 -0000      1.165
+++ client/gui-gtk-2.0/mapview.c        14 Mar 2005 03:22:14 -0000
@@ -463,6 +463,7 @@
 
 static PangoLayout *layout;
 static PangoFontDescription **fonts[FONT_COUNT] = {&main_font,
+                                                  &main_font,
                                                   &city_productions_font};
 
 /****************************************************************************
Index: data/isophex.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isophex.tilespec,v
retrieving revision 1.10
diff -u -r1.10 isophex.tilespec
--- data/isophex.tilespec       3 Mar 2005 03:47:32 -0000       1.10
+++ data/isophex.tilespec       14 Mar 2005 03:22:14 -0000
@@ -59,6 +59,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.33
diff -u -r1.33 isotrident.tilespec
--- data/isotrident.tilespec    3 Mar 2005 03:47:32 -0000       1.33
+++ data/isotrident.tilespec    14 Mar 2005 03:22:14 -0000
@@ -51,6 +51,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.33
diff -u -r1.33 trident.tilespec
--- data/trident.tilespec       3 Mar 2005 03:47:32 -0000       1.33
+++ data/trident.tilespec       14 Mar 2005 03:22:14 -0000
@@ -47,6 +47,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.24
diff -u -r1.24 trident_shields.tilespec
--- data/trident_shields.tilespec       3 Mar 2005 03:47:32 -0000       1.24
+++ data/trident_shields.tilespec       14 Mar 2005 03:22:14 -0000
@@ -50,6 +50,7 @@
 files = 
   "misc/colors.spec",
   "misc/overlays.spec",
+  "misc/citybar.spec",
   "trident/tiles.spec",
   "misc/small.spec",
   "trident/units.spec",

Attachment: citybar.tar.gz
Description: Unix tar archive


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