Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2004:
[Freeciv-Dev] (PR#8884) gui_distance_vector and faster scrolling
Home

[Freeciv-Dev] (PR#8884) gui_distance_vector and faster scrolling

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8884) gui_distance_vector and faster scrolling
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 31 May 2004 18:58:32 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8884 >

When scrolling the mapview, only the needed parts are redrawn.  If you 
scroll by (-30,0) then only 30xHEIGHT pixels are redrawn (actually every 
tile and city description that overlaps this area is redrawn in full).

Except, when the GUI coordinates of the origin wrap around, this breaks. 
  You can move -30 pixels in the X direction but end up with a new GUI 
origin that is +3000 pixels in the X direction.  So no overlap is found 
and the redraw is slow.

This can be solved by finding the GUI distance vector (which is needed 
by PR#8210 as well).  After finding this vector it's quite easy to use 
the current code for recentering, thus avoiding a full redraw in all 
possible cases.

Note that gui_distance_vector is quite ugly.  It can be made somewhat 
better by using gui-native positions.  The drawback is that gui-native 
positions are incredibly arcane and hard to visualize.  Although the 
logic of using map positions and offsets is more complicated the math is 
simpler.

For previous discussions see PR#8299.

jason

? ferries
? data/flags
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.121
diff -u -r1.121 mapview_common.c
--- client/mapview_common.c     24 May 2004 21:04:53 -0000      1.121
+++ client/mapview_common.c     1 Jun 2004 01:28:06 -0000
@@ -317,6 +317,49 @@
 }
 
 /****************************************************************************
+  Find the vector with minimum "real" distance between two GUI positions.
+  This corresponds to map_to_distance_vector but works for GUI coordinates.
+****************************************************************************/
+static void gui_distance_vector(int *gui_dx, int *gui_dy,
+                               int gui_x0, int gui_y0,
+                               int gui_x1, int gui_y1)
+{
+  int map_x0, map_y0, map_x1, map_y1;
+  int gui_x0_base, gui_y0_base, gui_x1_base, gui_y1_base;
+  int gui_x0_diff, gui_y0_diff, gui_x1_diff, gui_y1_diff;
+  int map_dx, map_dy;
+
+  /* Make sure positions are canonical.  Yes, this is the only way. */
+  normalize_gui_pos(&gui_x0, &gui_y0);
+  normalize_gui_pos(&gui_x1, &gui_y1);
+
+  /* Now we have to find the offset of each GUI position from its tile
+   * origin.  This is complicated: it means converting to a map position and
+   * then back to the GUI position to find the tile origin, then subtracting
+   * to get the offset. */
+  gui_to_map_pos(&map_x0, &map_y0, gui_x0, gui_y0);
+  gui_to_map_pos(&map_x1, &map_y1, gui_x1, gui_y1);
+
+  map_to_gui_pos(&gui_x0_base, &gui_y0_base, map_x0, map_y0);
+  map_to_gui_pos(&gui_x1_base, &gui_y1_base, map_x1, map_y1);
+
+  gui_x0_diff = gui_x0 - gui_x0_base;
+  gui_y0_diff = gui_y0 - gui_y0_base;
+  gui_x1_diff = gui_x1 - gui_x1_base;
+  gui_y1_diff = gui_y1 - gui_y1_base;
+
+  /* Next we find the map distance vector and convert this into a GUI
+   * vector. */
+  map_distance_vector(&map_dx, &map_dy, map_x0, map_y0, map_x1, map_y1);
+  map_to_gui_pos(gui_dx, gui_dy, map_dx, map_dy);
+
+  /* Finally we add on the difference in offsets to retain pixel
+   * resolution. */
+  *gui_dx += gui_x1_diff - gui_x0_diff;
+  *gui_dy += gui_y1_diff - gui_y0_diff;
+}
+
+/****************************************************************************
   Change the mapview origin, clip it, and update everything.
 ****************************************************************************/
 void set_mapview_origin(int gui_x0, int gui_y0)
@@ -338,15 +381,26 @@
     gui_y0 = CLIP(ymin, gui_y0, ymax - ysize);
   }
 
-  /* Then update everything. */
+  /* Then update everything.  This does some tricky math to avoid having
+   * to do unnecessary redraws in update_map_canvas.  This makes for ugly
+   * code but speeds up the mapview by a large factor. */
   if (mapview_canvas.gui_x0 != gui_x0 || mapview_canvas.gui_y0 != gui_y0) {
-    int map_center_x, map_center_y;
-    int old_gui_x0 = mapview_canvas.gui_x0;
-    int old_gui_y0 = mapview_canvas.gui_y0;
+    int map_center_x, map_center_y, old_gui_x0, old_gui_y0, dx, dy;
     const int width = mapview_canvas.width, height = mapview_canvas.height;
     int common_x0, common_x1, common_y0, common_y1;
     int update_x0, update_x1, update_y0, update_y1;
 
+    /* We need to calculate the vector of movement of the mapview.  So
+     * we find the GUI distance vector and then use this to calculate
+     * the original mapview origin relative to the current position.  Thus
+     * if we move one tile to the left, even if this causes GUI positions
+     * to wrap the distance vector is only one tile. */
+    gui_distance_vector(&dx, &dy,
+                       mapview_canvas.gui_x0, mapview_canvas.gui_y0,
+                       gui_x0, gui_y0);
+    old_gui_x0 = gui_x0 - dx;
+    old_gui_y0 = gui_y0 - dy;
+
     mapview_canvas.gui_x0 = gui_x0;
     mapview_canvas.gui_y0 = gui_y0;
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#8884) gui_distance_vector and faster scrolling, Jason Short <=