Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2006:
[Freeciv-Dev] (PR#15935) cursors for editing mode
Home

[Freeciv-Dev] (PR#15935) cursors for editing mode

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#15935) cursors for editing mode
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 16 Mar 2006 12:37:04 -0800
Reply-to: bugs@xxxxxxxxxxx

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

This patch adds two cursors for editing mode, with the infrastructure to 
add more.

A couple of new editor functions are added to test the result of 
clicking on a tile.  The result is one of CURSOR_EDITOR_PAINT, 
CURSOR_EDITOR_ADD, or CURSOR_EDITOR_INVALID.  Another new function (now 
used in two placces) tests whether an editor click is possible at all. 
I fixed a bug that prevented painting terrain or adding units beneath an 
existing city (now instead, you can't open cities while in edit mode).

There are still some problems.  You can't open a city or select a unit 
while in edit mode...at all.  And the INVALID cursor isn't set properly 
for unit-adding or city-adding because there are no checks for validity 
in editor.c.

The graphics leave a bit to be desired.  Presumably the artists will 
eventually improve them.

-jason

Index: data/misc/cursors.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: data/misc/cursors.spec
===================================================================
--- data/misc/cursors.spec      (revision 11776)
+++ data/misc/cursors.spec      (working copy)
@@ -8,6 +8,9 @@
 
 artists = "
     Andreas Røsdal <andrearo@xxxxxxxxxxxx>
+
+    edit_paint cursor take from GIMP
+    
 "
 
 [file]
@@ -64,4 +67,16 @@
        3, 6, "cursor.attack3", 16, 16
        4, 6, "cursor.attack4", 16, 16
        5, 6, "cursor.attack5", 16, 16
+       0, 7, "cursor.edit_paint0", 16, 16
+       1, 7, "cursor.edit_paint1", 16, 16
+       2, 7, "cursor.edit_paint2", 16, 16
+       3, 7, "cursor.edit_paint3", 16, 16
+       4, 7, "cursor.edit_paint4", 16, 16
+       5, 7, "cursor.edit_paint5", 16, 16
+       0, 8, "cursor.edit_add0", 16, 16
+       1, 8, "cursor.edit_add1", 16, 16
+       2, 8, "cursor.edit_add2", 16, 16
+       3, 8, "cursor.edit_add3", 16, 16
+       4, 8, "cursor.edit_add4", 16, 16
+       5, 8, "cursor.edit_add5", 16, 16
 }
Index: common/tile.c
===================================================================
--- common/tile.c       (revision 11776)
+++ common/tile.c       (working copy)
@@ -91,6 +91,14 @@
 }
 
 /****************************************************************************
+  Returns TRUE iff the given tile has any specials.
+****************************************************************************/
+bool tile_has_any_specials(const struct tile *ptile)
+{
+  return contains_any_specials(ptile->special);
+}
+
+/****************************************************************************
   Add the given special or specials to the tile.
 
   Note that this does not erase any existing specials already on the tile
Index: common/tile.h
===================================================================
--- common/tile.h       (revision 11776)
+++ common/tile.h       (working copy)
@@ -60,6 +60,7 @@
 bv_special tile_get_special(const struct tile *ptile);
 bool tile_has_special(const struct tile *ptile,
                      enum tile_special_type to_test_for);
+bool tile_has_any_specials(const struct tile *ptile);
 void tile_set_special(struct tile *ptile, enum tile_special_type spe);
 const struct resource *tile_get_resource(const struct tile *ptile);
 void tile_set_resource(struct tile *ptile, const struct resource *presource);
Index: common/terrain.c
===================================================================
--- common/terrain.c    (revision 11776)
+++ common/terrain.c    (working copy)
@@ -372,6 +372,14 @@
 }
 
 /****************************************************************************
+ Returns TRUE iff any specials are set on the tile.
+****************************************************************************/
+bool contains_any_specials(bv_special set)
+{
+  return BV_ISSET_ANY(set);
+}
+
+/****************************************************************************
   Returns TRUE iff any tile adjacent to (map_x,map_y) has the given special.
 ****************************************************************************/
 bool is_special_near_tile(const struct tile *ptile, enum tile_special_type spe)
Index: common/terrain.h
===================================================================
--- common/terrain.h    (revision 11776)
+++ common/terrain.h    (working copy)
@@ -214,6 +214,7 @@
 void clear_all_specials(bv_special *set);
 bool contains_special(bv_special all,
                      enum tile_special_type to_test_for);
+bool contains_any_specials(bv_special all);
 
 /* Functions to operate on a terrain special. */
 bool is_special_near_tile(const struct tile *ptile,
Index: client/control.c
===================================================================
--- client/control.c    (revision 11776)
+++ client/control.c    (working copy)
@@ -35,6 +35,7 @@
 #include "clinet.h"
 #include "combat.h"
 #include "dialogs_g.h"
+#include "editor.h"
 #include "goto.h"
 #include "gui_main_g.h"
 #include "mapctrl_g.h"
@@ -889,6 +890,7 @@
       /* hover_tile is the tile which is currently under the mouse cursor. */
       ptile = hover_tile;
     } else {
+      update_mouse_cursor(mouse_cursor_type);
       return;
     }
   }
@@ -898,7 +900,9 @@
 
   switch (hover_state) {
   case HOVER_NONE:
-    if (punit && game.player_ptr == punit->owner) {
+    if (can_do_editor_click(ptile)) {
+      mouse_cursor_type = editor_test_click(ptile);
+    } else if (punit && game.player_ptr == punit->owner) {
       /* Set mouse cursor to select a unit.  */
       mouse_cursor_type = CURSOR_SELECT;
     } else if (pcity
Index: client/tilespec.c
===================================================================
--- client/tilespec.c   (revision 11776)
+++ client/tilespec.c   (working copy)
@@ -2019,9 +2019,10 @@
     for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
       const char *names[CURSOR_LAST] =
                {"goto", "patrol", "paradrop", "nuke", "select", 
-               "invalid", "attack"};
+               "invalid", "attack", "edit_paint", "edit_add"};
       struct small_sprite *ss;
 
+      assert(ARRAY_SIZE(names) == CURSOR_LAST);
       my_snprintf(buffer, sizeof(buffer), "cursor.%s%d", names[i], f);
       SET_SPRITE(cursor[i].frame[f], buffer);
       ss = hash_lookup_data(t->sprite_hash, buffer);
Index: client/mapctrl_common.c
===================================================================
--- client/mapctrl_common.c     (revision 11776)
+++ client/mapctrl_common.c     (working copy)
@@ -531,7 +531,7 @@
 {
   struct tile *ptile = canvas_pos_to_tile(canvas_x, canvas_y);
 
-  if (!ptile->city && can_conn_edit(&aconnection)) {
+  if (can_do_editor_click(ptile)) {
     editor_do_click(ptile);
   } else if (can_client_change_view() && ptile) {
     /* FIXME: Some actions here will need to check can_client_issue_orders.
Index: client/tilespec.h
===================================================================
--- client/tilespec.h   (revision 11776)
+++ client/tilespec.h   (working copy)
@@ -160,6 +160,8 @@
   CURSOR_SELECT,
   CURSOR_INVALID,
   CURSOR_ATTACK,
+  CURSOR_EDIT_PAINT,
+  CURSOR_EDIT_ADD,
   CURSOR_LAST,
   CURSOR_DEFAULT,
 };
Index: client/editor.c
===================================================================
--- client/editor.c     (revision 11776)
+++ client/editor.c     (working copy)
@@ -30,6 +30,7 @@
 #include "clinet.h"
 #include "control.h"
 #include "editor.h"
+#include "tilespec.h"
 
 /* where the selected terrain and specials for editing are stored */
 static enum editor_tool_type selected_tool = ETOOL_PAINT;
@@ -117,48 +118,60 @@
  problem: could be multiple units on a particular tile
  TODO: edit existing units
 ****************************************************************************/
-static void do_unit(struct tile *ptile)
+static enum cursor_type editor_unit(struct tile *ptile, bool testing)
 {
-  struct packet_edit_unit packet;
+  /* FIXME: Do checks to see if the placement is allowed, so that the
+   * cursor can be set properly. */
+  if (!testing) {
+    struct packet_edit_unit packet;
 
-  packet.create_new = TRUE; /* ? */
-  packet.delete = FALSE;
+    packet.create_new = TRUE; /* ? */
+    packet.delete = FALSE;
 
-  packet.id = selected_unit->id;
-  packet.owner = selected_unit->owner->player_no;
+    packet.id = selected_unit->id;
+    packet.owner = selected_unit->owner->player_no;
 
-  packet.x = ptile->x;
-  packet.y = ptile->y;
+    packet.x = ptile->x;
+    packet.y = ptile->y;
 
-  packet.homecity = selected_unit->homecity;
+    packet.homecity = selected_unit->homecity;
 
-  packet.veteran = selected_unit->veteran;
-  packet.paradropped = selected_unit->paradropped;
+    packet.veteran = selected_unit->veteran;
+    packet.paradropped = selected_unit->paradropped;
 
-  packet.type = selected_unit->type->index;
-  packet.transported_by = selected_unit->transported_by;
+    packet.type = selected_unit->type->index;
+    packet.transported_by = selected_unit->transported_by;
 
-  packet.movesleft = selected_unit->moves_left;
-  packet.hp = selected_unit->hp;
-  packet.fuel = selected_unit->fuel;
+    packet.movesleft = selected_unit->moves_left;
+    packet.hp = selected_unit->hp;
+    packet.fuel = selected_unit->fuel;
 
-  packet.activity_count = selected_unit->activity_count;
+    packet.activity_count = selected_unit->activity_count;
 
-  send_packet_edit_unit(&aconnection, &packet);
+    send_packet_edit_unit(&aconnection, &packet);
+  }
+
+  return CURSOR_EDIT_ADD;
 }
 
 /****************************************************************************
  basically package_city in citytools.c
 ****************************************************************************/
-static void do_city(struct tile *ptile)
+static enum cursor_type editor_city(struct tile *ptile, bool testing)
 {
-  struct packet_edit_create_city packet = {
-    .owner = selected_city->owner->player_no,
-    .x = ptile->x,
-    .y = ptile->y
-  };
+  /* FIXME: Do checks to see if the placement is allowed, so that the
+   * cursor can be set properly. */
+  if (!testing) {
+    struct packet_edit_create_city packet = {
+      .owner = selected_city->owner->player_no,
+      .x = ptile->x,
+      .y = ptile->y
+    };
 
-  send_packet_edit_create_city(&aconnection, &packet);
+    send_packet_edit_create_city(&aconnection, &packet);
+  }
+
+  return CURSOR_EDIT_ADD;
 }
 
 #if 0
@@ -179,61 +192,105 @@
   For instance, if the paint operation is paint-terrain, then we just change
   the current tile's terrain to the selected terrain.
 ****************************************************************************/
-static void do_paint(struct tile *ptile)
+static enum cursor_type editor_paint(struct tile *ptile, bool testing)
 {
   struct tile tile = *ptile;
 
   switch (selected_paint_type) {
   case EPAINT_TERRAIN:
-    if (selected_terrain) {
+    if (selected_terrain && tile.terrain != selected_terrain) {
       tile.terrain = selected_terrain;
+    } else {
+      return CURSOR_INVALID;
     }
     break;
   case EPAINT_SPECIAL:
     /* add new special to existing specials on the tile */
-    if (selected_special == S_LAST) {
+    if (selected_special == S_LAST && tile_has_any_specials(&tile)) {
       tile_clear_all_specials(&tile);
+    } else if (selected_special != S_LAST
+              && !tile_has_special(&tile, selected_special)) {
+      tile_add_special(&tile, selected_special);
     } else {
-      tile_add_special(&tile, selected_special);
+      return CURSOR_INVALID;
     }
     break;
   case EPAINT_LAST:
-    return;
-  } 
+  default:
+    return CURSOR_INVALID;
+  }
 
-  /* send the result to the server for changing */
-  /* FIXME: No way to change resources. */
-  dsend_packet_edit_tile(&aconnection, ptile->x, ptile->y,
-                        tile.terrain->index,
-                        tile.resource ? tile.resource->index : -1,
-                        tile.special);
+  if (!testing) {
+    /* send the result to the server for changing */
+    /* FIXME: No way to change resources. */
+    dsend_packet_edit_tile(&aconnection, ptile->x, ptile->y,
+                          tile.terrain->index,
+                          tile.resource ? tile.resource->index : -1,
+                          tile.special);
+  }
+
+  return CURSOR_EDIT_PAINT;
 }
 
 /****************************************************************************
   if the client is in edit_mode, then this function captures clicks on the
   map canvas.
+
+  If the testing parameter is given then no actions are taken, but the
+  return value indicates what would happen if a click was made.
 ****************************************************************************/
-void editor_do_click(struct tile *ptile)
+static enum cursor_type editor_click(struct tile *ptile, bool testing)
 {
   /* Editing tiles that we can't see (or are fogged) will only lead to
    * problems. */
   if (client_tile_get_known(ptile) != TILE_KNOWN) {
-    return;
+    return CURSOR_INVALID;
   }
 
   switch (selected_tool) {
   case ETOOL_PAINT:
-    do_paint(ptile);
-    break;
+    return editor_paint(ptile, testing);
   case ETOOL_UNIT:
-    do_unit(ptile);
-    break;
+    return editor_unit(ptile, testing);
   case ETOOL_CITY:
-    do_city(ptile);
-    break;
+    return editor_city(ptile, testing);
   case ETOOL_PLAYER:
   case ETOOL_DELETE:
   case ETOOL_LAST:
     break;
   }
+  return CURSOR_INVALID;
 }
+
+/****************************************************************************
+  Return TRUE if an editor click on this tile is allowed - if not then a
+  normal click should be done instead.
+****************************************************************************/
+bool can_do_editor_click(struct tile *ptile)
+{
+  /* Previously, editor clicks were not allowed on city tiles; instead
+   * a click here would cause a regular click and the citydlg would open.
+   * This made it impossible to add a unit or paint a terrain underneath
+   * a city. */
+  return can_conn_edit(&aconnection);
+}
+
+/****************************************************************************
+  if the client is in edit_mode, then this function captures clicks on the
+  map canvas.
+****************************************************************************/
+void editor_do_click(struct tile *ptile)
+{
+  (void) editor_click(ptile, FALSE);
+}
+
+/****************************************************************************
+  if the client is in edit_mode, then this function returns the cursor_type
+  indicating what action would be taken on a click.  This can be used by
+  the code to set the cursor so the user can anticipate what clicking will
+  do.
+****************************************************************************/
+enum cursor_type editor_test_click(struct tile *ptile)
+{
+  return editor_click(ptile, TRUE);
+}
Index: client/editor.h
===================================================================
--- client/editor.h     (revision 11776)
+++ client/editor.h     (working copy)
@@ -44,6 +44,8 @@
 struct unit *editor_get_selected_unit(void);
 struct city *editor_get_selected_city(void);
 
+bool can_do_editor_click(struct tile *ptile);
 void editor_do_click(struct tile *ptile);
+enum cursor_type editor_test_click(struct tile *ptile);
 
 #endif /* FC__TOOLS_H */

PNG image


[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#15935) cursors for editing mode, Jason Short <=