Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2002:
[Freeciv-Dev] fix for isometric scrolling problem (PR#1222)
Home

[Freeciv-Dev] fix for isometric scrolling problem (PR#1222)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] fix for isometric scrolling problem (PR#1222)
From: jdorje@xxxxxxxxxxxxxxxxxxxxx
Date: Fri, 11 Jan 2002 16:14:07 -0800 (PST)

Attached is a patch that fixes the isometric scrolling problem.

The problem: when using an iso-view client, the scrollbars are still linked to map positions. This means the scrolling will be done diagonally relative to the window. This is clearly Bad.

The solution: when we have is_isometric, link the scrollbars to isometric coordinates.

In this patch, I've separated out the calculation code from gui-gtk into functions in mapview_common. These functions can likely be used by other GUI's to implement the same functionality (though I have not yet looked at this). The calculation code deals in "scrollbar positions", which are closely related to native GUI positions; i.e. they're equivalent to map positions if !is_isometric and become some sort of strange transformed compressed iso positions if is_isometric.

(I also have a simpler patch in which I've just changed the GTK code, without separating the calculations. This can be used instead if necessary.)

jason
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.4
diff -u -r1.4 mapview_common.c
--- client/mapview_common.c     2001/12/21 16:53:10     1.4
+++ client/mapview_common.c     2002/01/11 23:56:28
@@ -307,3 +307,156 @@
   last_pcity = pcity2;
   return pcity2;
 }
+
+/**************************************************************************
+  This function determines how far each scrollbar slider should be
+  scrolled given the window origin.
+
+  The positions returned are essentially "scrollbar positions" which are
+  not directly useful outside of the scrollbar.  However, they're closely
+  related to compressed native GUI coordinates.
+**************************************************************************/
+void get_scrollbar_positions(int *scroll_x, int *scroll_y,
+                               int map_view_topleft_map_x,
+                               int map_view_topleft_map_y)
+{
+  /*
+   * In overhead (flat) view, this is easy: just take the window origin
+   * as the scrollbar index.  In isometric (iso) view, it is substantially
+   * more complicated since we need to convert to (compressed) isometric
+   * coordinates _and_ make sure they're within the valid range.
+   */
+  if (is_isometric) {
+    *scroll_x = (map_view_topleft_map_x +
+                 (map.ysize - 1 - map_view_topleft_map_y)) / 2;
+    *scroll_y = (map_view_topleft_map_x + map_view_topleft_map_y) / 2;
+  } else {
+    /* If not isometric... */
+    *scroll_x = map_view_topleft_map_x;
+    *scroll_y = map_view_topleft_map_y;
+  }
+}
+
+/**************************************************************************
+  This function determines the size of the sliders in the horizontal and
+  vertical scrollbars for the mapview.
+
+  The dimensions returned are in the scale of "scrollbar positions" which
+  are not directly useful outside of the scrollbar.  However, they're
+  closely related to compressed native GUI coordinates.
+**************************************************************************/
+void get_scrollbar_slider_sizes(int *scroll_slider_width,
+                               int *scroll_slider_height,
+                               int map_view_map_width,
+                               int map_view_map_height)
+{
+  if (is_isometric) {
+    *scroll_slider_width = *scroll_slider_height =
+       (map_view_map_width + map_view_map_height) / 2;
+  } else {
+    /* If not isometric... */
+    *scroll_slider_width = map_view_map_width;
+    *scroll_slider_height = map_view_map_height;
+  }
+}
+
+/**************************************************************************
+  This function determines the total sizes of the scrollbars (both
+  horizontal and vertical) for the mapview.
+
+  The dimensions returned are in the scale of "scrollbar positions" which
+  are not directly useful outside of the scrollbar.  However, they're
+  closely related to compressed native GUI coordinates.
+**************************************************************************/
+void get_scrollbar_sizes(int *scroll_xsize, int *scroll_ysize)
+{
+  if (is_isometric) {
+    /*
+     * map.xsize + map.ysize - 1 is the possible range of the index
+     *  value; see update_map_canvas_scrollbars.  Then we add on
+     *  EXTRA_BOTTOM_ROW to be safe.
+     */
+    *scroll_xsize = *scroll_ysize =
+      (map.xsize + map.ysize - 1 + EXTRA_BOTTOM_ROW) / 2;
+  } else {
+    /* If not isometric... */
+    *scroll_xsize = map.xsize;
+    *scroll_ysize = map.ysize + EXTRA_BOTTOM_ROW;
+  }
+}
+
+/**************************************************************************
+  This function centers the mapview given a change in the scrollbar
+  position of one of the scrollbars.
+
+  The scrollbar_slider_pos is in the scale of "scrollbar positions" which
+  are not directly useful outside of the scrollbar.  However, they're
+  closely related to compressed native GUI coordinates.
+
+  The function will call the necessary functions to update the graphics
+  after the change.  This is slightly dangerous since this assumes that
+  when we change map_view_topleft_map_[xy] this will inform those
+  functions of the new position.  This problem 
wouldmap_view_topleft_map_xmap_view_topleft_map_xmap_view_topleft_map_x go away 
if the
+  window origin were stored GUI-independently.
+
+  hscrollbar should be TRUE if the scrollbar is horizontal, FALSE for
+  vertical.
+
+  FIXME: if we adjust the window because of topology concerns, the
+  scrollbars will _not_ be recursively updated.  This is a pretty minor
+  issue, but will probably be a pain to fix.
+**************************************************************************/
+void center_mapview_from_scrollbar(int *map_view_topleft_map_x,
+                                  int *map_view_topleft_map_y,
+                                  int map_view_map_width,
+                                  int map_view_map_height,
+                                  int scroll_slider_pos,
+                                  int hscrollbar)
+{
+  int old_map_view_topleft_map_x = *map_view_topleft_map_x;
+  int old_map_view_topleft_map_y = *map_view_topleft_map_y;
+
+  if(hscrollbar) {
+    if (is_isometric) {
+      int iso_diff_x = scroll_slider_pos -
+                       (*map_view_topleft_map_x +
+                        (map.ysize - 1 - *map_view_topleft_map_y)) / 2;
+      *map_view_topleft_map_x += iso_diff_x;
+      *map_view_topleft_map_y -= iso_diff_x;
+    } else {
+      *map_view_topleft_map_x = scroll_slider_pos;
+    }
+  } else {
+    if (is_isometric) {
+      int iso_diff_y = scroll_slider_pos - (*map_view_topleft_map_x +
+                                           *map_view_topleft_map_y) / 2;
+      *map_view_topleft_map_x += iso_diff_y;
+      *map_view_topleft_map_y += iso_diff_y;
+    } else {
+      *map_view_topleft_map_y = scroll_slider_pos;
+    }
+  }
+
+  /* Note: the second half of this function should be unified with
+     base_center_tile_mapcanvas. */
+
+  /*
+   * Account for topology considerations.  This currently hard-codes
+   * the topology, which is bad.  It also curretnly only uses
+   * map_view_map_height, but under different topologies would also use
+   * map_view_map_width.
+   */
+  *map_view_topleft_map_y = map_adjust_y(*map_view_topleft_map_y);
+  *map_view_topleft_map_y =
+      (*map_view_topleft_map_y > map.ysize + EXTRA_BOTTOM_ROW -
+                                map_view_map_height) ?
+      map.ysize + EXTRA_BOTTOM_ROW - map_view_map_height :
+      *map_view_topleft_map_y;
+
+  /* Finally, we update the graphics. */
+  if (   old_map_view_topleft_map_x != *map_view_topleft_map_x
+      || old_map_view_topleft_map_y != *map_view_topleft_map_y) {
+    update_map_canvas_visible();
+    refresh_overview_viewrect();
+  }
+}
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.3
diff -u -r1.3 mapview_common.h
--- client/mapview_common.h     2001/12/21 16:53:10     1.3
+++ client/mapview_common.h     2002/01/11 23:56:28
@@ -62,4 +62,20 @@
                                
 struct city *find_city_near_tile(int x, int y);
 
+
+void get_scrollbar_positions(int *scroll_x, int *sroll_y,
+                               int map_view_topleft_map_x,
+                               int map_view_topleft_map_y);
+void get_scrollbar_slider_sizes(int *scroll_slider_width,
+                               int *scroll_slider_height,
+                               int map_view_map_width,
+                               int map_view_map_height);
+void get_scrollbar_sizes(int *scroll_xsize, int *scroll_ysize);
+void center_mapview_from_scrollbar(int *map_view_topleft_map_x,
+                                  int *map_view_topleft_map_y,
+                                  int map_view_map_width,
+                                  int map_view_map_height,
+                                  int scroll_slider_pos,
+                                  int hscrollbar);
+
 #endif /* FC__MAPVIEW_COMMON_H */
Index: client/gui-gtk/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapview.c,v
retrieving revision 1.111
diff -u -r1.111 mapview.c
--- client/gui-gtk/mapview.c    2001/12/21 19:14:18     1.111
+++ client/gui-gtk/mapview.c    2002/01/11 23:56:30
@@ -1724,23 +1724,36 @@
 }
 
 /**************************************************************************
-...
+  This function updates the scrollbars by setting how far each one is
+  scrolled.
 **************************************************************************/
 void update_map_canvas_scrollbars(void)
 {
-  gtk_adjustment_set_value(GTK_ADJUSTMENT(map_hadj), map_view_x0);
-  gtk_adjustment_set_value(GTK_ADJUSTMENT(map_vadj), map_view_y0);
+  int scroll_x, scroll_y;
+  get_scrollbar_positions(&scroll_x, &scroll_y, map_view_x0, map_view_y0);
+  gtk_adjustment_set_value(GTK_ADJUSTMENT(map_hadj), scroll_x);
+  gtk_adjustment_set_value(GTK_ADJUSTMENT(map_vadj), scroll_y);
 }
 
 /**************************************************************************
-...
+  This function sets the size of the scrollbars and sliders, for instance
+  on startup or when the window is resized.
 **************************************************************************/
 void update_map_canvas_scrollbars_size(void)
 {
-  map_hadj=gtk_adjustment_new(-1, 0, map.xsize, 1,
-          map_canvas_store_twidth, map_canvas_store_twidth);
-  map_vadj=gtk_adjustment_new(-1, 0, map.ysize+EXTRA_BOTTOM_ROW, 1,
-          map_canvas_store_theight, map_canvas_store_theight);
+  int scroll_slider_width, scroll_slider_height;
+  int scroll_xsize, scroll_ysize;
+
+  get_scrollbar_slider_sizes(&scroll_slider_width,
+                            &scroll_slider_height,
+                            map_canvas_store_twidth,
+                            map_canvas_store_theight);
+  get_scrollbar_sizes(&scroll_xsize, &scroll_ysize);
+
+  map_hadj=gtk_adjustment_new(-1, 0, scroll_xsize, 1,
+                             scroll_slider_width, scroll_slider_width);
+  map_vadj=gtk_adjustment_new(-1, 0, scroll_ysize, 1,
+                             scroll_slider_height, scroll_slider_height);
   gtk_range_set_adjustment(GTK_RANGE(map_horizontal_scrollbar),
        GTK_ADJUSTMENT(map_hadj));
   gtk_range_set_adjustment(GTK_RANGE(map_vertical_scrollbar),
@@ -1753,38 +1766,22 @@
 }
 
 /**************************************************************************
-...
+  This callback function is called by GTK when the scrollbar is moved.
 **************************************************************************/
 void scrollbar_jump_callback(GtkAdjustment *adj, gpointer hscrollbar)
 {
-  int last_map_view_x0;
-  int last_map_view_y0;
-
-  gfloat percent=adj->value;
+  int scrollbar_slider_pos = adj->value;
 
   if(get_client_state()!=CLIENT_GAME_RUNNING_STATE)
      return;
 
-  last_map_view_x0=map_view_x0;
-  last_map_view_y0=map_view_y0;
-
-  if(hscrollbar)
-    map_view_x0=percent;
-  else {
-    map_view_y0=percent;
-    map_view_y0=(map_view_y0<0) ? 0 : map_view_y0;
-    map_view_y0=
-      (map_view_y0>map.ysize+EXTRA_BOTTOM_ROW-map_canvas_store_theight) ? 
-      map.ysize+EXTRA_BOTTOM_ROW-map_canvas_store_theight :
-      map_view_y0;
-  }
-
-  if (last_map_view_x0!=map_view_x0 || last_map_view_y0!=map_view_y0) {
-    update_map_canvas_visible();
-    refresh_overview_viewrect();
-  }
+  /* This call handles all calculations _and_ updates the graphics. */
+  center_mapview_from_scrollbar(&map_view_x0, &map_view_y0,
+                               map_canvas_store_twidth,
+                               map_canvas_store_theight,
+                               scrollbar_slider_pos,
+                               hscrollbar != 0);
 }
-
   
 /**************************************************************************
 draw a line from src_x,src_y -> dest_x,dest_y on both map_canvas and

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