Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2004:
[Freeciv-Dev] (PR#8210) Wish List: a sliding mapview
Home

[Freeciv-Dev] (PR#8210) Wish List: a sliding mapview

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: arnstein.lindgard@xxxxxxx
Subject: [Freeciv-Dev] (PR#8210) Wish List: a sliding mapview
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 22 Sep 2004 20:27:51 -0700
Reply-to: rt@xxxxxxxxxxx

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

Here is another update of the patch.

I added a client option to control the sliding speed.  It defaults to 0,
giving the same behavior we have now.  Changing it to 50 or 500 gives
some interesting results.

I think this may be worth including before the release.  It's been
requested in RT by some anonymous user, and since it defaults to off
there should be no impact for normal users.

jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.148
diff -u -r1.148 mapview_common.c
--- client/mapview_common.c     20 Sep 2004 16:27:12 -0000      1.148
+++ client/mapview_common.c     23 Sep 2004 02:54:33 -0000
@@ -383,6 +383,96 @@
 }
 
 /****************************************************************************
+  Move the GUI origin to the given normalized, clipped origin.  This may
+  be called many times when sliding the mapview.
+****************************************************************************/
+static void base_set_mapview_origin(int gui_x0, int 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;
+
+  /* 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. */
+
+  /* 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. */
+  normalize_gui_pos(&gui_x0, &gui_y0);
+  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;
+
+  /* Find the overlapping area of the new and old mapview.  This is
+   * done in GUI coordinates.  Note that if the GUI coordinates wrap
+   * no overlap will be found. */
+  common_x0 = MAX(old_gui_x0, gui_x0);
+  common_x1 = MIN(old_gui_x0, gui_x0) + width;
+  common_y0 = MAX(old_gui_y0, gui_y0);
+  common_y1 = MIN(old_gui_y0, gui_y0) + height;
+
+  if (common_x1 > common_x0 && common_y1 > common_y0) {
+    /* Do a partial redraw only.  This means the area of overlap (a
+     * rectangle) is copied.  Then the remaining areas (two rectangles)
+     * are updated through update_map_canvas. */
+    struct canvas *target = mapview_canvas.tmp_store;
+
+    if (old_gui_x0 < gui_x0) {
+      update_x0 = MAX(old_gui_x0 + width, gui_x0);
+      update_x1 = gui_x0 + width;
+    } else {
+      update_x0 = gui_x0;
+      update_x1 = MIN(old_gui_x0, gui_x0 + width);
+    }
+    if (old_gui_y0 < gui_y0) {
+      update_y0 = MAX(old_gui_y0 + height, gui_y0);
+      update_y1 = gui_y0 + height;
+    } else {
+      update_y0 = gui_y0;
+      update_y1 = MIN(old_gui_y0, gui_y0 + height);
+    }
+
+    dirty_all();
+    canvas_copy(target, mapview_canvas.store,
+               common_x0 - old_gui_x0,
+               common_y0 - old_gui_y0,
+               common_x0 - gui_x0, common_y0 - gui_y0,
+               common_x1 - common_x0, common_y1 - common_y0);
+    mapview_canvas.tmp_store = mapview_canvas.store;
+    mapview_canvas.store = target;
+
+    if (update_y1 > update_y0) {
+      update_map_canvas(0, update_y0 - gui_y0,
+                       width, update_y1 - update_y0);
+    }
+    if (update_x1 > update_x0) {
+      update_map_canvas(update_x0 - gui_x0, common_y0 - gui_y0,
+                       update_x1 - update_x0, common_y1 - common_y0);
+    }
+  } else {
+    update_map_canvas_visible();
+  }
+
+  get_center_tile_mapcanvas(&map_center_x, &map_center_y);
+  center_tile_overviewcanvas(map_center_x, map_center_y);
+  if (hover_state == HOVER_GOTO || hover_state == HOVER_PATROL) {
+    create_line_at_mouse_pos();
+  }
+  if (rectangle_active) {
+    update_rect_at_mouse_pos();
+  }
+}
+
+/****************************************************************************
   Change the mapview origin, clip it, and update everything.
 ****************************************************************************/
 void set_mapview_origin(int gui_x0, int gui_y0)
@@ -404,90 +494,32 @@
     gui_y0 = CLIP(ymin, gui_y0, ymax - ysize);
   }
 
-  /* 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, old_gui_x0, old_gui_y0, dx, dy;
-    const int width = mapview_canvas.store_width;
-    const int height = mapview_canvas.store_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;
-
-    /* Find the overlapping area of the new and old mapview.  This is
-     * done in GUI coordinates.  Note that if the GUI coordinates wrap
-     * no overlap will be found. */
-    common_x0 = MAX(old_gui_x0, gui_x0);
-    common_x1 = MIN(old_gui_x0, gui_x0) + width;
-    common_y0 = MAX(old_gui_y0, gui_y0);
-    common_y1 = MIN(old_gui_y0, gui_y0) + height;
-
-    if (common_x1 > common_x0 && common_y1 > common_y0) {
-      /* Do a partial redraw only.  This means the area of overlap (a
-       * rectangle) is copied.  Then the remaining areas (two rectangles)
-       * are updated through update_map_canvas. */
-      struct canvas *target = mapview_canvas.tmp_store;
-
-      if (old_gui_x0 < gui_x0) {
-       update_x0 = MAX(old_gui_x0 + width, gui_x0);
-       update_x1 = gui_x0 + width;
-      } else {
-       update_x0 = gui_x0;
-       update_x1 = MIN(old_gui_x0, gui_x0 + width);
-      }
-      if (old_gui_y0 < gui_y0) {
-       update_y0 = MAX(old_gui_y0 + height, gui_y0);
-       update_y1 = gui_y0 + height;
-      } else {
-       update_y0 = gui_y0;
-       update_y1 = MIN(old_gui_y0, gui_y0 + height);
-      }
+  if (mapview_canvas.gui_x0 == gui_x0 && mapview_canvas.gui_y0 == gui_y0) {
+    return;
+  }
 
-      dirty_all();
-      canvas_copy(target, mapview_canvas.store,
-                 common_x0 - old_gui_x0,
-                 common_y0 - old_gui_y0,
-                 common_x0 - gui_x0, common_y0 - gui_y0,
-                 common_x1 - common_x0, common_y1 - common_y0);
-      mapview_canvas.tmp_store = mapview_canvas.store;
-      mapview_canvas.store = target;
-
-      if (update_y1 > update_y0) {
-       update_map_canvas(0, update_y0 - gui_y0,
-                         width, update_y1 - update_y0);
-      }
-      if (update_x1 > update_x0) {
-       update_map_canvas(update_x0 - gui_x0, common_y0 - gui_y0,
-                         update_x1 - update_x0, common_y1 - common_y0);
-      }
-    } else {
-      update_map_canvas_visible();
-    }
+  if (smooth_center_slide_msec > 0) {
+    int start_x = mapview_canvas.gui_x0, start_y = mapview_canvas.gui_y0;
+    int diff_x, diff_y;
+    double timing_sec = (double)smooth_center_slide_msec / 1000.0, mytime;
+    static struct timer *anim_timer;
 
-    get_center_tile_mapcanvas(&map_center_x, &map_center_y);
-    center_tile_overviewcanvas(map_center_x, map_center_y);
-    update_map_canvas_scrollbars();
-    if (hover_state == HOVER_GOTO || hover_state == HOVER_PATROL) {
-      create_line_at_mouse_pos();
-    }
-  }
-  if (rectangle_active) {
-    update_rect_at_mouse_pos();
+    gui_distance_vector(&diff_x, &diff_y, start_x, start_y, gui_x0, gui_y0);
+    anim_timer = renew_timer_start(anim_timer, TIMER_USER, TIMER_ACTIVE);
+
+    do {
+      mytime = MIN(read_timer_seconds(anim_timer), timing_sec);
+
+      base_set_mapview_origin(start_x + diff_x * (mytime / timing_sec),
+                             start_y + diff_y * (mytime / timing_sec));
+      flush_dirty();
+      gui_flush();
+    } while (mytime < timing_sec);
+  } else {
+    base_set_mapview_origin(gui_x0, gui_y0);
   }
+
+  update_map_canvas_scrollbars();
 }
 
 /****************************************************************************
Index: client/options.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/options.c,v
retrieving revision 1.103
diff -u -r1.103 options.c
--- client/options.c    26 Aug 2004 07:59:01 -0000      1.103
+++ client/options.c    23 Sep 2004 02:54:34 -0000
@@ -55,6 +55,7 @@
 bool solid_color_behind_units = FALSE;
 bool sound_bell_at_new_turn = FALSE;
 int  smooth_move_unit_msec = 30;
+int smooth_center_slide_msec = 0;
 bool do_combat_animation = TRUE;
 bool ai_popup_windows = FALSE;
 bool ai_manual_turn_done = FALSE;
@@ -94,6 +95,8 @@
   GEN_BOOL_OPTION(sound_bell_at_new_turn,   N_("Sound bell at new turn")),
   GEN_INT_OPTION(smooth_move_unit_msec,
                 N_("Unit movement animation time (milliseconds)")),
+  GEN_INT_OPTION(smooth_center_slide_msec,
+                N_("Mapview recentering time (milliseconds)")),
   GEN_BOOL_OPTION(do_combat_animation,      N_("Show combat animation")),
   GEN_BOOL_OPTION(ai_popup_windows,         N_("Popup dialogs in AI Mode")),
   GEN_BOOL_OPTION(ai_manual_turn_done,      N_("Manual Turn Done in AI Mode")),
Index: client/options.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/options.h,v
retrieving revision 1.38
diff -u -r1.38 options.h
--- client/options.h    3 Aug 2004 00:09:44 -0000       1.38
+++ client/options.h    23 Sep 2004 02:54:34 -0000
@@ -29,6 +29,7 @@
 extern bool solid_color_behind_units;
 extern bool sound_bell_at_new_turn;
 extern int smooth_move_unit_msec;
+extern int smooth_center_slide_msec;
 extern bool do_combat_animation;
 extern bool ai_popup_windows;
 extern bool ai_manual_turn_done;

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