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

Attached patch implements a tile "vision" property for the
property editor. This property can be used to view the
contents of the player bitvectors ptile->tile_known and
ptile->tile_seen[v] (for each vision layer v). This is only
really useful for debugging and as a code example of a more
complicated composite object property.


-----------------------------------------------------------------------
苦い暗号は嫌だ!どうしていつも口に入れなきゃ?
diff --git a/client/gui-gtk-2.0/editprop.c b/client/gui-gtk-2.0/editprop.c
index 94d5670..16aa371 100644
--- a/client/gui-gtk-2.0/editprop.c
+++ b/client/gui-gtk-2.0/editprop.c
@@ -93,6 +93,11 @@ union packetdata {
   struct packet_edit_game *game;
 };
 
+/* Helpers for the OPID_TILE_VISION property. */
+struct tile_vision_data {
+  bv_player tile_known, tile_seen[V_COUNT];
+};
+const char *vision_layer_get_name(enum vision_layer);
 
 #define PF_MAX_CLAUSES 16
 #define PF_DISJUNCTION_SEPARATOR "|"
@@ -179,7 +184,8 @@ enum value_types {
   VALTYPE_BUILT_ARRAY,        /* struct built_status[B_LAST] */
   VALTYPE_INVENTIONS_ARRAY,   /* bool[A_LAST] */
   VALTYPE_BV_SPECIAL,
-  VALTYPE_NATION
+  VALTYPE_NATION,
+  VALTYPE_TILE_VISION_DATA    /* struct tile_vision_data */
 };
 
 static const char *valtype_get_name(int valtype);
@@ -203,6 +209,7 @@ union propval_data {
   bv_special v_bv_special;
   struct nation_type *v_nation;
   bool *v_inventions;
+  struct tile_vision_data *v_tile_vision;
 };
 
 struct propval {
@@ -274,6 +281,7 @@ enum object_property_ids {
   OPID_TILE_XY,
   OPID_TILE_RESOURCE,
   OPID_TILE_SPECIALS,
+  OPID_TILE_VISION, /* tile_known and tile_seen */
 
   OPID_UNIT_IMAGE,
   OPID_UNIT_ADDRESS,
@@ -755,6 +763,9 @@ static const char *valtype_get_name(int valtype)
   case VALTYPE_NATION:
     return "nation";
     break;
+  case VALTYPE_TILE_VISION_DATA:
+    return "struct tile_vision_data";
+    break;
   default:
     break;
   }
@@ -945,7 +956,7 @@ static int get_next_unique_tag(void)
 static struct propval *propval_copy(struct propval *pv)
 {
   struct propval *pv_copy;
-  int size;
+  size_t size;
 
   if (!pv) {
     return NULL;
@@ -976,6 +987,17 @@ static struct propval *propval_copy(struct propval *pv)
     memcpy(pv_copy->data.v_pointer, pv->data.v_pointer, size);
     pv_copy->must_free = TRUE;
     break;
+  case VALTYPE_TILE_VISION_DATA:
+    size = sizeof(struct tile_vision_data);
+    pv_copy->data.v_tile_vision = fc_malloc(size);
+    pv_copy->data.v_tile_vision->tile_known
+      = pv->data.v_tile_vision->tile_known;
+    vision_layer_iterate(v) {
+      pv_copy->data.v_tile_vision->tile_seen[v]
+        = pv->data.v_tile_vision->tile_seen[v];
+    } vision_layer_iterate_end;
+    pv_copy->must_free = TRUE;
+    break;
   default:
     pv_copy->data = pv->data;
     break;
@@ -1002,6 +1024,7 @@ static void propval_free(struct propval *pv)
     case VALTYPE_STRING:
     case VALTYPE_BUILT_ARRAY:
     case VALTYPE_INVENTIONS_ARRAY:
+    case VALTYPE_TILE_VISION_DATA:
       free(pv->data.v_pointer);
       break;
     default:
@@ -1072,6 +1095,19 @@ static bool propval_equal(struct propval *pva,
   case VALTYPE_BV_SPECIAL:
     return BV_ARE_EQUAL(pva->data.v_bv_special, pvb->data.v_bv_special);
     break;
+  case VALTYPE_TILE_VISION_DATA:
+    if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_known,
+                      pvb->data.v_tile_vision->tile_known)) {
+      return FALSE;
+    }
+    vision_layer_iterate(v) {
+      if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_seen[v],
+                        pvb->data.v_tile_vision->tile_seen[v])) {
+        return FALSE;
+      }
+    } vision_layer_iterate_end;
+    return TRUE;
+    break;
   default:
     break;
   }
@@ -1259,6 +1295,7 @@ static struct propval *objbind_get_value_from_object(struct objbind *ob,
   int objtype, propid;
   struct tile *ptile;
   struct propval *pv;
+  size_t size;
 
   if (!op || !ob) {
     return NULL;
@@ -1329,6 +1366,15 @@ static struct propval *objbind_get_value_from_object(struct objbind *ob,
     case OPID_TILE_SPECIALS:
       pv->data.v_bv_special = tile_specials(ptile);
       break;
+    case OPID_TILE_VISION:
+      size = sizeof(struct tile_vision_data);
+      pv->data.v_tile_vision = fc_malloc(size);
+      pv->data.v_tile_vision->tile_known = ptile->tile_known;
+      vision_layer_iterate(v) {
+        pv->data.v_tile_vision->tile_seen[v] = ptile->tile_seen[v];
+      } vision_layer_iterate_end;
+      pv->must_free = TRUE;
+      break;
     default:
       freelog(LOG_ERROR, "Unhandled request for value of property %d "
               "(%s) from object of type \"%s\" in "
@@ -2407,6 +2453,7 @@ static void objprop_setup_widget(struct objprop *op)
     break;
 
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_VISION:
   case OPID_CITY_BUILDINGS:
   case OPID_PLAYER_NATION:
   case OPID_PLAYER_INVENTIONS:
@@ -2593,6 +2640,7 @@ static void objprop_refresh_widget(struct objprop *op,
     break;
 
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_VISION:
   case OPID_CITY_BUILDINGS:
   case OPID_PLAYER_NATION:
   case OPID_PLAYER_INVENTIONS:
@@ -2770,10 +2818,11 @@ static struct extviewer *extviewer_new(struct objprop *op)
 {
   struct extviewer *ev;
   GtkWidget *hbox, *vbox, *label, *button, *scrollwin, *image;
-  GtkWidget *view = NULL;
+  GtkWidget *view = NULL, *spacer;
   GtkTreeSelection *sel;
   GtkListStore *store = NULL;
-  int propid;
+  GType *gtypes;
+  int propid, num_cols;
 
   if (!op) {
     return NULL;
@@ -2818,13 +2867,27 @@ static struct extviewer *extviewer_new(struct objprop *op)
     ev->panel_image = image;
     break;
 
+  case OPID_TILE_VISION:
+    hbox = gtk_hbox_new(FALSE, 4);
+    ev->panel_widget = hbox;
+    spacer = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
+    gtk_box_pack_start(GTK_BOX(hbox), spacer, TRUE, TRUE, 0);
+    break;
+
   default:
+    freelog(LOG_ERROR, "Unhandled request to create panel widget "
+            "for property %d (%s) in extviewer_new().",
+            propid, objprop_get_name(op));
     hbox = gtk_hbox_new(FALSE, 4);
     ev->panel_widget = hbox;
     break;
   }
 
-  button = gtk_button_new_with_label(_("Edit"));
+  if (objprop_is_readonly(op)) {
+    button = gtk_button_new_with_label(_("View"));
+  } else {
+    button = gtk_button_new_with_label(_("Edit"));
+  }
   g_signal_connect(button, "clicked",
                    G_CALLBACK(extviewer_panel_button_clicked), ev);
   gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
@@ -2834,28 +2897,32 @@ static struct extviewer *extviewer_new(struct objprop *op)
   /* Create the data store. */
 
   switch (propid) {
-
   case OPID_TILE_SPECIALS:
   case OPID_PLAYER_INVENTIONS:
-    store = gtk_list_store_new(3, G_TYPE_BOOLEAN,
-                               G_TYPE_INT,
+    store = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_INT,
                                G_TYPE_STRING);
     break;
-
+  case OPID_TILE_VISION:
+    num_cols = 3 + 1 + V_COUNT;
+    gtypes = fc_malloc(num_cols * sizeof(GType));
+    gtypes[0] = G_TYPE_INT;       /* player number */
+    gtypes[1] = GDK_TYPE_PIXBUF;  /* player flag */
+    gtypes[2] = G_TYPE_STRING;    /* player name */
+    gtypes[3] = G_TYPE_BOOLEAN;   /* tile_known */
+    vision_layer_iterate(v) {
+      gtypes[4 + v] = G_TYPE_BOOLEAN; /* tile_seen[v] */
+    } vision_layer_iterate_end;
+    store = gtk_list_store_newv(num_cols, gtypes);
+    free(gtypes);
+    break;
   case OPID_CITY_BUILDINGS:
-    store = gtk_list_store_new(4, G_TYPE_BOOLEAN,
-                               G_TYPE_INT,
-                               G_TYPE_STRING,
-                               G_TYPE_STRING);
+    store = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_INT,
+                               G_TYPE_STRING, G_TYPE_STRING);
     break;
-
   case OPID_PLAYER_NATION:
-    store = gtk_list_store_new(4, G_TYPE_BOOLEAN,
-                               G_TYPE_INT,
-                               GDK_TYPE_PIXBUF,
-                               G_TYPE_STRING);
+    store = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_INT,
+                               GDK_TYPE_PIXBUF, G_TYPE_STRING);
     break;
-
   default:
     freelog(LOG_ERROR, "Unhandled request to create data store "
             "for property %d (%s) in extviewer_new().",
@@ -2906,6 +2973,21 @@ static struct extviewer *extviewer_new(struct objprop *op)
                FALSE, FALSE, NULL, NULL);
     break;
 
+  case OPID_TILE_VISION:
+    add_column(view, 0, _("ID"), G_TYPE_INT,
+               FALSE, FALSE, NULL, NULL);
+    add_column(view, 1, _("Nation"), GDK_TYPE_PIXBUF,
+               FALSE, FALSE, NULL, NULL);
+    add_column(view, 2, _("Name"), G_TYPE_STRING,
+               FALSE, FALSE, NULL, NULL);
+    add_column(view, 3, _("Known"), G_TYPE_BOOLEAN,
+               FALSE, FALSE, NULL, NULL);
+    vision_layer_iterate(v) {
+      add_column(view, 4 + v, vision_layer_get_name(v),
+                 G_TYPE_BOOLEAN, FALSE, FALSE, NULL, NULL);
+    } vision_layer_iterate_end;
+    break;
+
   case OPID_CITY_BUILDINGS:
     /* TRANS: As in "this building is present". */
     add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
@@ -3020,6 +3102,9 @@ static void extviewer_refresh_widgets(struct extviewer *ev,
   store = ev->store;
 
 
+  /* NB: Remember to have -1 as the last argument to
+   * gtk_list_store_set() and to use the correct column
+   * number when inserting data. :) */
   switch (propid) {
 
   case OPID_TILE_SPECIALS:
@@ -3035,6 +3120,33 @@ static void extviewer_refresh_widgets(struct extviewer *ev,
     gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
     break;
 
+  case OPID_TILE_VISION:
+    gtk_list_store_clear(store);
+    player_slots_iterate(pslot) {
+      id = player_number(pslot);
+      if (player_slot_is_used(pslot)) {
+        name = player_name(pslot);
+        pixbuf = get_flag(pslot->nation);
+      } else {
+        name = "";
+        pixbuf = NULL;
+      }
+      gtk_list_store_append(store, &iter);
+      gtk_list_store_set(store, &iter, 0, id, 2, name, -1);
+      if (pixbuf) {
+        gtk_list_store_set(store, &iter, 1, pixbuf, -1);
+        g_object_unref(pixbuf);
+        pixbuf = NULL;
+      }
+      present = BV_ISSET(pv->data.v_tile_vision->tile_known, id);
+      gtk_list_store_set(store, &iter, 3, present, -1);
+      vision_layer_iterate(v) {
+        present = BV_ISSET(pv->data.v_tile_vision->tile_seen[v], id);
+        gtk_list_store_set(store, &iter, 4 + v, present, -1);
+      } vision_layer_iterate_end;
+    } player_slots_iterate_end;
+    break;
+
   case OPID_CITY_BUILDINGS:
     gtk_list_store_clear(store);
     improvement_iterate(pimprove) {
@@ -3120,10 +3232,13 @@ static void extviewer_clear_widgets(struct extviewer *ev)
 
   switch (propid) {
   case OPID_TILE_SPECIALS:
+  case OPID_TILE_VISION:
   case OPID_CITY_BUILDINGS:
   case OPID_PLAYER_INVENTIONS:
     gtk_list_store_clear(ev->store);
-    gtk_label_set_text(GTK_LABEL(ev->panel_label), NULL);
+    if (ev->panel_label != NULL) {
+      gtk_label_set_text(GTK_LABEL(ev->panel_label), NULL);
+    }
     break;
   case OPID_PLAYER_NATION:
     gtk_list_store_clear(ev->store);
@@ -3285,8 +3400,6 @@ static void property_page_setup_objprops(struct property_page *pp)
   case OBJTYPE_TILE:
     ADDPROP(OPID_TILE_IMAGE, _("Image"),
             OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_PIXBUF);
-    ADDPROP(OPID_TILE_ADDRESS, _("Address"),
-            OPF_HAS_WIDGET, VALTYPE_STRING);
     ADDPROP(OPID_TILE_TERRAIN, _("Terrain"),
             OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
     ADDPROP(OPID_TILE_RESOURCE, _("Resource"),
@@ -3311,6 +3424,10 @@ static void property_page_setup_objprops(struct property_page *pp)
             OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
     ADDPROP(OPID_TILE_SPECIALS, _("Specials"), OPF_IN_LISTVIEW
             | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BV_SPECIAL);
+    ADDPROP(OPID_TILE_ADDRESS, _("Address"),
+            OPF_HAS_WIDGET, VALTYPE_STRING);
+    ADDPROP(OPID_TILE_VISION, _("Vision"),
+            OPF_HAS_WIDGET, VALTYPE_TILE_VISION_DATA);
     break;
 
   case OBJTYPE_UNIT:
@@ -5323,3 +5440,26 @@ static void property_filter_free(struct property_filter *pf)
   pf->count = 0;
   free(pf);
 }
+
+/****************************************************************************
+  Returns a translated string name for the given "vision layer".
+****************************************************************************/
+const char *vision_layer_get_name(enum vision_layer vl)
+{
+  switch (vl) {
+  case V_MAIN:
+    /* TRANS: Vision layer name. Feel free to leave untranslated. */
+    return _("Seen (Main)");
+    break;
+  case V_INVIS:
+    /* TRANS: Vision layer name. Feel free to leave untranslated. */
+    return _("Seen (Invis)");
+    break;
+  default:
+    freelog(LOG_ERROR, "Unrecognized vision layer %d in "
+            "vision_layer_get_name().", vl);
+    break;
+  }
+
+  return _("Unknown");
+}
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to