[Freeciv-Dev] fix for isometric scrolling problem (PR#1222)
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
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
- [Freeciv-Dev] fix for isometric scrolling problem (PR#1222),
jdorje <=
|
|