Complete.Org: Mailing Lists: Archives: freeciv-dev: October 2003:
[Freeciv-Dev] Re: (PR#6439) get_mapview_scroll_window for iso-maps
Home

[Freeciv-Dev] Re: (PR#6439) get_mapview_scroll_window for iso-maps

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] Re: (PR#6439) get_mapview_scroll_window for iso-maps
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 10 Oct 2003 11:27:42 -0700
Reply-to: rt@xxxxxxxxxxxxxx

Here's an update to the patch.  It removes EXTRA_BOTTOM_ROW, which is 
now unused.

jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.66
diff -u -r1.66 mapview_common.c
--- client/mapview_common.c     2003/10/06 11:46:27     1.66
+++ client/mapview_common.c     2003/10/10 18:26:18
@@ -31,11 +31,6 @@
 
 #include "mapview_common.h"
 
-/* We need to be able to scroll a little bit down past the end of the map,
- * since the bottom row of tiles may not fit completely on the mapview.
- * In iso-view we have to scroll even further past. */
-#define EXTRA_BOTTOM_ROW (is_isometric ? 6 : 1)
-
 struct canvas mapview_canvas;
 
 /* Overview oordinates of the upper left corner of the map overview. */
@@ -349,17 +344,134 @@
 }
 
 /****************************************************************************
-  Return the range of values that the mapview origin can take, in scroll
-  positions.  Useful for scrollbars or when manually clipping the window.
+  Return the scroll dimensions of the clipping window for the mapview window..
+
+  Imagine the entire map in scroll coordinates.  It is a rectangle.  Now
+  imagine the mapview "window" sliding around through this rectangle.  How
+  far can it slide?  In most cases it has to be able to slide past the
+  ends of the map rectangle so that it's capable of reaching the whole
+  area.
+
+  This function gives constraints on how far the window is allowed to
+  slide.  xmin and ymin are the minimum values for the window origin.
+  xsize and ysize give the scroll dimensions of the mapview window.
+  xmax and ymax give the maximum values that the bottom/left ends of the
+  window may reach.  The constraints, therefore, are that:
+
+    get_mapview_scroll_pos(&scroll_x, &scroll_y);
+    xmin <= scroll_x < xmax - xsize
+    ymin <= scroll_y < ymax - ysize
+
+  This function should be used anywhere and everywhere that scrolling is
+  constrained.
+
+  Note that scroll coordinates, not map coordinates, are used.  Currently
+  these correspond to native coordinates.
 ****************************************************************************/
 void get_mapview_scroll_window(int *xmin, int *ymin, int *xmax, int *ymax,
                               int *xsize, int *ysize)
 {
-  *xmin = *ymin = 0;
+  /* There are a number of factors that must be taken into account in
+   * calculating these values:
+   *
+   * 1. Basic constraints: X should generally range from 0 to map.xsize;
+   * Y from 0 to map.ysize.
+   *
+   * 2. Non-aligned borders: if the borders don't line up (an iso-view client
+   * with a standard map, for instance) the minimum and maximum must be
+   * extended if the map doesn't wrap in that direction.  They are extended
+   * by an amount proportional to the size of the screen.
+   *
+   * 3. Compression: on an iso-map native coordinates are compressed 2x in
+   * the X direction.
+   *
+   * 4. Translation: the min and max values give a range for the origin.
+   * Since the base constraint is on the minimal value contained in the
+   * mapview, we have to translate the minimum and maximum to account for
+   * this.
+   *
+   * 5. Wrapping: if the map wraps in a given direction, no border adjustment
+   * or translation is needed.  Instead we have to make sure the range is
+   * large enough to get the full wrap.
+   */
+  *xmin = 0;
+  *ymin = 0;
   *xmax = map.xsize;
-  *ymax = map.ysize + EXTRA_BOTTOM_ROW;
-  *xsize = mapview_canvas.tile_width;
-  *ysize = mapview_canvas.tile_height;
+  *ymax = map.ysize;
+
+  if (topo_has_flag(TF_ISO) != is_isometric) {
+    /* The mapview window is aligned differently than the map.  In this
+     * case we need to give looser constraints because (if the map doesn't
+     * wrap) the edges will not line up well. */
+
+    /* These are the dimensions of the bounding box. */
+    *xsize = *ysize =
+      mapview_canvas.tile_width + mapview_canvas.tile_height;
+
+    if (is_isometric) {
+      /* Step 2: Calculate extra border distance. */
+      *xmin = *ymin = -(MAX(mapview_canvas.tile_width,
+                           mapview_canvas.tile_height) + 1) / 2;
+      *xmax -= *xmin;
+      *ymax -= *ymin;
+
+      /* Step 4: Translate the Y coordinate.  The mapview origin is at the
+       * top-left corner of the window, which is offset at +tile_width from
+       * the minimum Y value (at the top-right corner). */
+      *ymin += mapview_canvas.tile_width;
+      *ymax += mapview_canvas.tile_width;
+    } else {
+      /* Compression. */
+      *xsize = (*xsize + 1) / 2;
+
+      /* Step 2: calculate border adjustment. */
+      *ymin = -(MAX(mapview_canvas.tile_width,
+                   mapview_canvas.tile_height) + 1) / 2;
+      *xmin = (*ymin + 1) / 2; /* again compressed */
+      *xmax -= *xmin;
+      *ymax -= *ymin;
+
+      /* Step 4: translate the X coordinate.  The mapview origin is at the
+       * top-left corner of the window, which is offset at +tile_height/2
+       * from the minimum X value (at the bottom-left corner). */
+      *xmin += mapview_canvas.tile_height / 2;
+      *xmax += (mapview_canvas.tile_height + 1) / 2;
+    }
+  } else {
+    *xsize = mapview_canvas.tile_width;
+    *ysize = mapview_canvas.tile_height;
+
+    if (is_isometric) {
+      /* Compression: Each vertical half-tile corresponds to one native
+       * unit (a full horizontal tile corresponds to a native unit). */
+      *ysize = (mapview_canvas.height - 1) / (NORMAL_TILE_HEIGHT / 2) + 1;
+
+      /* Isometric fixes: the above calculations are in half-tiles; since we
+       * need to see full tiles we have to extend the range a bit.  This also
+       * corrects for the off-by-one error caused by the X compression of
+       * native coordinates. */
+      (*xmin)--;
+      (*xmax)++;
+      (*ymax) += 2;
+    } else {
+      (*ymax)++;
+    }
+  }
+
+  /* Now override the above to satisfy wrapping constraints.  We allow the
+   * scrolling to cover the full range of the map, plus one unit in each
+   * direction (to allow scrolling with the scroll bars, for instance). */
+  if (topo_has_flag(TF_WRAPX)) {
+    *xmin = -1;
+    *xmax = map.xsize + *xsize;
+  }
+  if (topo_has_flag(TF_WRAPY)) {
+    *ymin = -1;
+    *ymax = map.ysize + *ysize;
+  }
+
+  freelog(LOG_DEBUG, "x: %d<-%d->%d; y: %d<-%d->%d",
+         *xmin, *xsize, *xmax, *ymin, *ymax, *ysize);
 }
 
 /****************************************************************************

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