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

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

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8210) WISHLIST: a sliding mapview
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 22 May 2004 22:47:42 -0700
Reply-to: rt@xxxxxxxxxxx

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

Here is version 3.  It is substantially faster - possibly even usably fast.

It is still rather crude, but I believe the potential is very high.

jason

? convert.sh
? diff
? flags
? data/flags
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.120
diff -u -r1.120 mapview_common.c
--- client/mapview_common.c     22 May 2004 18:12:21 -0000      1.120
+++ client/mapview_common.c     23 May 2004 05:46:45 -0000
@@ -317,11 +317,123 @@
 }
 
 /****************************************************************************
+  Find the vector with minimum "real" distance between two GUI positions.
+
+  See also map_distance_vector().
+****************************************************************************/
+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);
+
+  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;
+
+  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);
+
+  *gui_dx += gui_x1_diff - gui_x0_diff;
+  *gui_dy += gui_y1_diff - gui_y1_diff;
+}
+
+static void base_set_mapview_origin(int gui_x0, int 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;
+  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;
+
+  normalize_gui_pos(&gui_x0, &gui_y0);
+  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)
 {
   int xmin, xmax, ymin, ymax, xsize, ysize;
+  int start_x = mapview_canvas.gui_x0, start_y = mapview_canvas.gui_y0;
+  int diff_x, diff_y;
+  int timing_msec = 500;
 
   /* Normalize (wrap) the mapview origin. */
   normalize_gui_pos(&gui_x0, &gui_y0);
@@ -338,78 +450,31 @@
     gui_y0 = CLIP(ymin, gui_y0, ymax - ysize);
   }
 
+  if (mapview_canvas.gui_x0 == gui_x0 && mapview_canvas.gui_y0 == gui_y0) {
+    return;
+  }
+
   /* Then update everything. */
-  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;
-    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;
-
-    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 (timing_msec > 0) {
+    double timing_sec = (double)timing_msec / 1000.0, mytime;
+    static struct timer *anim_timer;
 
-      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();
-    }
+    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);
 
-    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();
+    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();
 }
 
 /****************************************************************************

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#8210) WISHLIST: a sliding mapview, Jason Short <=