[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]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=2708 >
And, here is yet another patch.
This one makes the "full citybar" a tileset option. It's disabled for
all the default tilesets.
Although there are some small issues left I think it should be
committed. This version shouldn't include the new files in
citybar.tar.gz (though they can easily be added later).
-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.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 17 Apr 2005 08:51:24 -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;
@@ -1239,18 +1241,180 @@
}
/****************************************************************************
- Draw a description for the given city. This description may include the
- name, turns-to-grow, production, and city turns-to-build (depending on
- client options).
+ Draw a "full" citybar for the city. This is a subcase of show_city_desc
+ (see that function for more info) for tilesets that have a full citybar.
+****************************************************************************/
+static void show_full_citybar(struct canvas *pcanvas,
+ const int canvas_x0, const int canvas_y0,
+ struct city *pcity, int *width, int *height)
+{
+ 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}, 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_flag_sprite(tileset, 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 */
- (canvas_x, canvas_y) gives the location on the given canvas at which to
- draw the description. This is the location of the city itself so the
- text must be drawn underneath it. pcity gives the city to be drawn,
- while (*width, *height) should be set by show_ctiy_desc to contain the
- width and height of the text block (centered directly underneath the
- city's tile).
+ get_sprite_dimensions(bg, &bg_w, &bg_h);
+ *width = *height = 0;
+
+ if (!line1 && !line2) {
+ return;
+ }
+
+ /* 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 (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];
+ }
+ }
+
+ 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 (line2) {
+ get_city_mapview_production(pcity, prod, sizeof(prod));
+ get_text_size(&prod_rect.w, &prod_rect.h, FONT_CITY_PROD, prod);
+
+ get_sprite_dimensions(citybar->shields, &shield_rect.w, &shield_rect.h);
+
+ 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;
+
+ 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);
+ }
+}
+
+/****************************************************************************
+ Draw a "small" citybar for the city. This is a subcase of show_city_desc
+ (see that function for more info) for tilesets that do not have a full
+ citybar.
****************************************************************************/
-static void show_city_desc(struct canvas *pcanvas,
+static void show_small_citybar(struct canvas *pcanvas,
int canvas_x, int canvas_y,
struct city *pcity, int *width, int *height)
{
@@ -1269,7 +1433,7 @@
if (draw_city_names) {
get_city_mapview_name_and_growth(pcity, name, sizeof(name),
- growth, sizeof(growth), &growth_color);
+ growth, sizeof(growth), &growth_color);
get_text_size(&name_rect.w, &name_rect.h, FONT_CITY_NAME, name);
@@ -1281,13 +1445,13 @@
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);
+ 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);
+ canvas_x - total_width / 2 + name_rect.w + extra_width,
+ canvas_y + total_height - growth_rect.h,
+ FONT_CITY_PROD, growth_color, growth);
}
canvas_y += total_height + 3;
@@ -1302,7 +1466,7 @@
total_height = prod_rect.h;
canvas_put_text(pcanvas, canvas_x - total_width / 2, canvas_y,
- FONT_CITY_PROD, COLOR_STD_WHITE, prod);
+ FONT_CITY_PROD, COLOR_STD_WHITE, prod);
canvas_y += total_height;
*width = MAX(*width, total_width);
@@ -1310,6 +1474,29 @@
}
}
+/****************************************************************************
+ Draw a description for the given city. This description may include the
+ name, turns-to-grow, production, and city turns-to-build (depending on
+ client options).
+
+ (canvas_x, canvas_y) gives the location on the given canvas at which to
+ draw the description. This is the location of the city itself so the
+ text must be drawn underneath it. pcity gives the city to be drawn,
+ while (*width, *height) should be set by show_ctiy_desc to contain the
+ width and height of the text block (centered directly underneath the
+ city's tile).
+****************************************************************************/
+static void show_city_desc(struct canvas *pcanvas,
+ int canvas_x, int canvas_y,
+ struct city *pcity, int *width, int *height)
+{
+ if (tileset_is_full_citybar(tileset)) {
+ show_full_citybar(pcanvas, canvas_x, canvas_y, pcity, width, height);
+ } else {
+ show_small_citybar(pcanvas, canvas_x, canvas_y, pcity, width, height);
+ }
+}
+
/**************************************************************************
Show descriptions for all cities visible on the map canvas.
**************************************************************************/
@@ -1919,7 +2106,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 +2115,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.293
diff -u -r1.293 tilespec.c
--- client/tilespec.c 15 Apr 2005 05:40:49 -0000 1.293
+++ client/tilespec.c 17 Apr 2005 08:51:25 -0000
@@ -209,6 +209,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],
@@ -352,6 +353,7 @@
int flag_offset_x, flag_offset_y;
int unit_offset_x, unit_offset_y;
+ bool is_full_citybar;
int citybar_offset_y;
#define NUM_CORNER_DIRS 4
@@ -512,6 +514,16 @@
}
/****************************************************************************
+ Return TRUE iff a "full" citybar is to be used. The full citybar draws
+ the flag and size and occupied sprites as part of the citybar instead of
+ behind the city.
+****************************************************************************/
+bool tileset_is_full_citybar(const struct tileset *t)
+{
+ return t->is_full_citybar;
+}
+
+/****************************************************************************
Return the offset from the origin of the city tile at which to place the
citybar text.
****************************************************************************/
@@ -1304,6 +1316,8 @@
t->unit_offset_y = secfile_lookup_int_default(file, 0,
"tilespec.unit_offset_y");
+ t->is_full_citybar
+ = secfile_lookup_bool_default(file, FALSE, "tilespec.is_full_citybar");
t->citybar_offset_y
= secfile_lookup_int_default(file, t->normal_tile_height,
"tilespec.citybar_offset_y");
@@ -1965,6 +1979,28 @@
}
}
+ if (t->is_full_citybar) {
+ 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++) {
@@ -2571,8 +2607,8 @@
/**********************************************************************
Return the flag graphic to be used by the city.
***********************************************************************/
-static struct sprite *get_city_nation_flag_sprite(const struct tileset *t,
- const struct city *pcity)
+struct sprite *get_city_flag_sprite(const struct tileset *t,
+ const struct city *pcity)
{
return get_nation_flag_sprite(t, city_owner(pcity)->nation);
}
@@ -3833,13 +3869,13 @@
case LAYER_CITY1:
/* City. Some city sprites are drawn later. */
if (pcity && draw_cities) {
- if (!solid_color_behind_units) {
- ADD_SPRITE(get_city_nation_flag_sprite(t, pcity), TRUE,
+ if (!t->is_full_citybar && !solid_color_behind_units) {
+ ADD_SPRITE(get_city_flag_sprite(t, pcity), TRUE,
FULL_TILE_X_OFFSET + t->flag_offset_x,
FULL_TILE_Y_OFFSET + t->flag_offset_y);
}
ADD_SPRITE_FULL(get_city_sprite(t, pcity));
- if (pcity->client.occupied) {
+ if (!t->is_full_citybar && pcity->client.occupied) {
ADD_SPRITE_FULL(get_city_occupied_sprite(t, pcity));
}
if (!t->is_isometric && city_got_citywalls(pcity)) {
@@ -3873,7 +3909,7 @@
case LAYER_CITY2:
/* City size. Drawing this under fog makes it hard to read. */
- if (pcity && draw_cities) {
+ if (pcity && draw_cities && !t->is_full_citybar) {
if (pcity->size >= 10) {
ADD_SPRITE(t->sprites.city.size_tens[pcity->size / 10],
FALSE, FULL_TILE_X_OFFSET, FULL_TILE_Y_OFFSET);
@@ -3926,6 +3962,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;
@@ -4215,6 +4255,9 @@
sprite_vector_free(&t->sprites.explode.unit);
sprite_vector_free(&t->sprites.nation_flag);
+ if (t->is_full_citybar) {
+ sprite_vector_free(&t->sprites.citybar.occupancy);
+ }
}
/**************************************************************************
@@ -4381,6 +4424,18 @@
}
/**************************************************************************
+ Return all the sprites used for citybar drawing.
+**************************************************************************/
+const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
+{
+ if (t->is_full_citybar) {
+ return &t->sprites.citybar;
+ } else {
+ return NULL;
+ }
+}
+
+/**************************************************************************
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.148
diff -u -r1.148 tilespec.h
--- client/tilespec.h 15 Apr 2005 05:08:09 -0000 1.148
+++ client/tilespec.h 17 Apr 2005 08:51:25 -0000
@@ -79,6 +79,7 @@
LAYER_SPECIAL3,
LAYER_GRID2,
LAYER_OVERLAYS,
+ LAYER_CITYBAR,
LAYER_FOCUS_UNIT,
LAYER_GOTO,
LAYER_COUNT
@@ -173,12 +174,23 @@
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,
struct citizen_type type,
int citizen_index,
const struct city *pcity);
+struct sprite *get_city_flag_sprite(const struct tileset *t,
+ const struct city *pcity);
struct sprite *get_nation_flag_sprite(const struct tileset *t,
Nation_Type_id nation);
struct sprite *get_tech_sprite(const struct tileset *t, Tech_Type_id tech);
@@ -197,6 +209,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,
@@ -219,6 +232,7 @@
int tileset_full_tile_height(const struct tileset *t);
int tileset_small_sprite_width(const struct tileset *t);
int tileset_small_sprite_height(const struct tileset *t);
+bool tileset_is_full_citybar(const struct tileset *t);
int tileset_citybar_offset_y(const struct tileset *t);
const char *tileset_main_intro_filename(const struct tileset *t);
const char *tileset_mini_intro_filename(const struct tileset *t);
Index: data/isophex.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isophex.tilespec,v
retrieving revision 1.13
diff -u -r1.13 isophex.tilespec
--- data/isophex.tilespec 15 Apr 2005 05:40:49 -0000 1.13
+++ data/isophex.tilespec 17 Apr 2005 08:51:25 -0000
@@ -34,6 +34,7 @@
unit_offset_y = 13
; offset the citybar text by this amount (from the city tile origin)
+is_full_citybar = 0
citybar_offset_y = 20
; Hex data.
Index: data/isotrident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident.tilespec,v
retrieving revision 1.36
diff -u -r1.36 isotrident.tilespec
--- data/isotrident.tilespec 15 Apr 2005 05:40:49 -0000 1.36
+++ data/isotrident.tilespec 17 Apr 2005 08:51:25 -0000
@@ -36,6 +36,7 @@
unit_offset_y = 13
; offset the citybar text by this amount (from the city tile origin)
+is_full_citybar = 0
citybar_offset_y = 20
; Font size (points) to use to draw city names and productions:
Index: data/trident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident.tilespec,v
retrieving revision 1.36
diff -u -r1.36 trident.tilespec
--- data/trident.tilespec 15 Apr 2005 05:40:49 -0000 1.36
+++ data/trident.tilespec 17 Apr 2005 08:51:25 -0000
@@ -32,6 +32,7 @@
flag_offset_y = 0
; offset the citybar text by this amount (from the city tile origin)
+is_full_citybar = 0
citybar_offset_y = 27
; Font size (points) to use to draw city names and productions:
Index: data/trident_shields.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident_shields.tilespec,v
retrieving revision 1.27
diff -u -r1.27 trident_shields.tilespec
--- data/trident_shields.tilespec 15 Apr 2005 05:40:49 -0000 1.27
+++ data/trident_shields.tilespec 17 Apr 2005 08:51:25 -0000
@@ -23,6 +23,7 @@
flag_offset_y = 2
; offset the citybar text by this amount (from the city tile origin)
+is_full_citybar = 0
citybar_offset_y = 27
; Do not blend hills and mountains together.
|
|