]> granicus.if.org Git - nethack/commitdiff
*** empty log message ***
authorjwalz <jwalz>
Sat, 5 Jan 2002 21:06:01 +0000 (21:06 +0000)
committerjwalz <jwalz>
Sat, 5 Jan 2002 21:06:01 +0000 (21:06 +0000)
win/gnome/gnmap.c [new file with mode: 0644]

diff --git a/win/gnome/gnmap.c b/win/gnome/gnmap.c
new file mode 100644 (file)
index 0000000..e7082bf
--- /dev/null
@@ -0,0 +1,612 @@
+/*     SCCS Id: @(#)gnmap.c    3.3     2000/07/16      */
+/* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
+/* Copyright (C) 1998 by Anthony Taylor <tonyt@ptialaska.net> */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#include "gnmap.h"
+#include "gnglyph.h"
+#include "gnsignal.h"
+#include "hack.h"
+
+#ifndef ROWNO
+#define ROWNO 21
+#define COLNO 80
+#endif
+
+/* globals static to this file go here */
+struct {
+  GnomeCanvas       *canvas;
+  GnomeCanvasImage  *map[(ROWNO + 1) * COLNO];
+  GnomeCanvasImage  *overlay[(ROWNO + 1) * COLNO];
+  double            zoom;
+  GtkWidget         *frame;
+} ghack_map;
+  
+static GdkImlibImage *background;
+static GdkImlibImage *petmark;
+static GnomeCanvasGroup *myCanvasGroup;
+
+/* static function declarations -- local to this file go here */
+void ghack_map_cursor_to( GtkWidget *win, int x, int y, gpointer data); 
+void ghack_map_putstr( GtkWidget *win, int attr, const char* text, gpointer data);
+void ghack_map_print_glyph( GtkObject *win, guint x, guint y, GdkImlibImage *im, gpointer data);
+void ghack_map_clear( GtkWidget *win, gpointer data);
+static void ghack_map_display( GtkWidget *win, boolean block, gpointer data);
+static void ghack_map_cliparound( GtkWidget *win, int x, int y, gpointer data);
+static void ghack_map_window_zoom( GtkAdjustment *adj, gpointer data);
+
+
+/* The following XPM is the artwork of Warwick Allison
+ * <warwick@troll.no>.  It has been borrowed from 
+ * the most excellent NetHackQt, until such time as
+ * we can come up with something better.
+ *
+ * More information about NetHackQt can be had from:
+ * http://www.troll.no/~warwick/nethack/
+ */
+
+/* XPM */
+static char *pet_mark_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"8 7 2 1",
+/* colors */
+". c None",
+"  c #FF0000",
+/* pixels */
+"........",
+"..  .  .",
+".       ",
+".       ",
+"..     .",
+"...   ..",
+".... ..."
+};
+
+
+/* NAME: 
+ *     ghack_init_map_window( )
+ *
+ * ARGUMENTS:
+ *     NONE
+ *
+ * RETURNS:
+ *     GtkWidget*
+ *
+ * PURPOSE:
+ *     Create the basic map necessities.  Create a canvas;
+ *     give it a background.  Attach all the right signals
+ *     to all the right places.  Generally prepare the map
+ *     to behave properly.
+*/
+
+GtkWidget*
+ghack_init_map_window ( )
+{
+  GtkWidget        *vbox;
+  GtkWidget        *hbox;
+  GtkWidget        *table;
+  GtkWidget        *frame;
+  GtkWidget        *w;
+  GtkWidget       *hSeparator;
+  GtkAdjustment    *adj;
+  GnomeCanvasImage  *bg;
+  double width, height, x, y;
+  int i;
+
+  width = COLNO * ghack_glyph_width();
+  height = ROWNO * ghack_glyph_height();
+
+  vbox = gtk_vbox_new (FALSE, 4);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
+  gtk_widget_show (vbox);
+  
+  /* Add in a horiz seperator */
+  hSeparator = gtk_hseparator_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), hSeparator, FALSE, FALSE, 2);
+  gtk_widget_show ( hSeparator);
+  
+  hbox = gtk_hbox_new (FALSE, 4);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  gtk_widget_show (hbox);
+
+  /* Create the Zoom spinbutton.
+  */
+  ghack_map.zoom = 1.0;
+  w = gtk_label_new ("Zoom:");
+  gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
+  gtk_widget_show (w);
+  adj = GTK_ADJUSTMENT (gtk_adjustment_new (1.00, 0.5, 3.00, 0.05, 0.50, 0.50));
+  w = gtk_spin_button_new (adj, 0.5, 2);
+  gtk_widget_set_usize (w, 50, 0);
+  gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
+  gtk_widget_show (w);
+
+  /* Canvas and scrollbars
+  */
+  gtk_widget_push_visual (gdk_imlib_get_visual ());
+  gtk_widget_push_colormap (gdk_imlib_get_colormap ());
+  ghack_map.canvas = GNOME_CANVAS (gnome_canvas_new());
+  //gtk_widget_push_visual(gdk_rgb_get_visual());
+  //gtk_widget_push_colormap(gdk_rgb_get_cmap());
+  //ghack_map.canvas = GNOME_CANVAS (gnome_canvas_new_aa());
+
+  gtk_widget_pop_colormap();
+  gtk_widget_pop_visual();
+  gtk_widget_show (GTK_WIDGET(ghack_map.canvas));
+
+  table = gtk_table_new (2, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+  gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
+  gtk_widget_show (table);
+  
+  frame = gtk_frame_new (NULL);
+  ghack_map.frame = frame;
+  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+  gtk_table_attach (GTK_TABLE (table), frame,
+                   0, 1, 0, 1,
+                   GTK_EXPAND | GTK_FILL | GTK_SHRINK,
+                   GTK_EXPAND | GTK_FILL | GTK_SHRINK,
+                   0, 0);
+  gtk_widget_show (frame);
+
+  gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(ghack_map.canvas));
+  gnome_canvas_set_scroll_region (GNOME_CANVAS(ghack_map.canvas), 0, 0, 
+                   width+2*ghack_glyph_width(), height+2*ghack_glyph_height());
+
+  gnome_canvas_set_pixels_per_unit (GNOME_CANVAS(ghack_map.canvas), 1.0);
+
+  w = gtk_hscrollbar_new (GTK_LAYOUT (ghack_map.canvas)->hadjustment);
+  gtk_table_attach (GTK_TABLE (table), w,
+                   0, 1, 1, 2,
+                   GTK_EXPAND | GTK_FILL | GTK_SHRINK,
+                   GTK_FILL,
+                   0, 0);
+  gtk_widget_show (w);
+
+  w = gtk_vscrollbar_new (GTK_LAYOUT (ghack_map.canvas)->vadjustment);
+  gtk_table_attach (GTK_TABLE (table), w,
+                   1, 2, 0, 1, GTK_FILL,
+                   GTK_EXPAND | GTK_FILL | GTK_SHRINK,
+                   0, 0);
+  gtk_widget_show (w); 
+  
+  myCanvasGroup = GNOME_CANVAS_GROUP ( gnome_canvas_item_new ( 
+                   gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas)), 
+                   gnome_canvas_group_get_type (), 
+                   "x", 0.0, 
+                   "y", 0.0, 
+                   NULL) );
+
+  /* Tile the map background with a pretty image */ 
+  background = gdk_imlib_load_image((char *) "mapbg.xpm");
+  if (background == NULL) {
+      g_warning("Bummer! Failed to load the map background image (mapbg.xpm)!");
+  }
+  else {
+    gdk_imlib_render(background, background->rgb_width,
+         background->rgb_height);
+
+    /* Tile the map background */
+    for (y = 0; y < height+background->rgb_height; y+=background->rgb_height)
+    {
+      for (x = 0; x < width+background->rgb_width; x+=background->rgb_width)
+       {
+         bg = GNOME_CANVAS_IMAGE( gnome_canvas_item_new (
+                     myCanvasGroup, gnome_canvas_image_get_type (),
+                     "x",      (double) x,
+                     "y",      (double) y,
+                     "width",  (double) background->rgb_width,
+                     "height", (double) background->rgb_height,
+                     "image",  background,
+                     "anchor", (GtkAnchorType) GTK_ANCHOR_CENTER,
+                     NULL) );
+         gnome_canvas_item_lower_to_bottom (GNOME_CANVAS_ITEM( bg));
+       }
+    }
+  }
+
+  /* ghack_map.map is an array of canvas images.  Each cell of
+   * the array will contain one tile.  Here, we create the
+   * space for the cells and then create the cells for easy
+   * access later.
+  */
+  for (i=0, y = 0; y < height; y+=ghack_glyph_height())
+    {
+      for (x = 0; x < width; x+=ghack_glyph_width())
+       {
+         ghack_map.map[i++] = GNOME_CANVAS_IMAGE( 
+                 gnome_canvas_item_new (
+                     myCanvasGroup,
+                     gnome_canvas_image_get_type (),
+                     "x",      (double) x,
+                     "y",      (double) y,
+                     "width",  (double) ghack_glyph_height(),
+                     "height", (double) ghack_glyph_width(),
+                     "anchor", GTK_ANCHOR_NORTH_WEST,
+                     NULL) );
+       }
+    }
+
+   /* Set up the pet mark image */
+  petmark = gdk_imlib_create_image_from_xpm_data( pet_mark_xpm);
+  if (petmark == NULL) {
+    g_warning("Bummer! Failed to load the pet_mark image!");
+  }
+  else {
+      gdk_imlib_render(petmark, petmark->rgb_width,
+         petmark->rgb_height);
+
+      /* ghack_map.overlay is an array of canvas images used to
+       * overlay tile images...
+       */
+      for (i=0, y = 0; y < height; y+=ghack_glyph_height())
+       {
+         for (x = 0; x < width; x+=ghack_glyph_width())
+           {
+             ghack_map.overlay[i] = GNOME_CANVAS_IMAGE( 
+                     gnome_canvas_item_new (
+                         myCanvasGroup,
+                         gnome_canvas_image_get_type (),
+                         "x",      (double) x,
+                         "y",      (double) y,
+                         "width",  (double) petmark->rgb_width,
+                         "height", (double) petmark->rgb_height,
+                         "image",  petmark,
+                         "anchor", GTK_ANCHOR_NORTH_WEST,
+                         NULL) );
+             gnome_canvas_item_lower_to_bottom (
+                     GNOME_CANVAS_ITEM( ghack_map.overlay[i++]));
+           }
+       }
+  }
+
+  /* Resize the canvas when the spinbutton changes
+  */
+  gtk_signal_connect (GTK_OBJECT (adj),
+                     "value_changed",
+                     (GtkSignalFunc) ghack_map_window_zoom,
+                     ghack_map.canvas);
+
+  /* Game signals
+  */
+  gtk_signal_connect (GTK_OBJECT (vbox),
+                     "ghack_curs",
+                     GTK_SIGNAL_FUNC (ghack_map_cursor_to),
+                     NULL);
+  gtk_signal_connect (GTK_OBJECT (vbox),
+                     "ghack_putstr",
+                     GTK_SIGNAL_FUNC (ghack_map_putstr),
+                     NULL);
+  gtk_signal_connect (GTK_OBJECT (vbox),
+                     "ghack_print_glyph",
+                     GTK_SIGNAL_FUNC (ghack_map_print_glyph),
+                     NULL);
+  gtk_signal_connect (GTK_OBJECT (vbox),
+                     "ghack_clear",
+                     GTK_SIGNAL_FUNC (ghack_map_clear),
+                     NULL);
+  gtk_signal_connect (GTK_OBJECT (vbox),
+                     "ghack_display",
+                     GTK_SIGNAL_FUNC (ghack_map_display),
+                     NULL);
+  gtk_signal_connect (GTK_OBJECT (vbox),
+                     "ghack_cliparound",
+                     GTK_SIGNAL_FUNC (ghack_map_cliparound),
+                     NULL);
+  gtk_signal_connect (GTK_OBJECT (ghack_map.canvas),
+                     "button_press_event",
+                     GTK_SIGNAL_FUNC (ghack_handle_button_press),
+                     NULL);
+  gtk_signal_connect(GTK_OBJECT (ghack_map.canvas), 
+                     "gnome_delay_output",
+                      GTK_SIGNAL_FUNC(ghack_delay), 
+                     NULL);
+  
+  return GTK_WIDGET(vbox);
+}
+
+
+/* NAME: 
+ *     ghack_map_window_zoom
+ *
+ * ARGUMENTS:
+ *     double     zoom -- The zoom factor
+ *
+ * RETURNS:
+ *     Nothing.
+ *
+ * PURPOSE:
+ *     Zoom the map image in and out.  This should allow the user to
+ *     dynamically scale the map.  Ideally, the background should
+ *     *NOT* scale, but this may be impractical.
+*/
+
+static void
+ghack_map_window_zoom( GtkAdjustment *adj, gpointer data)
+{
+  if ( adj->value > 3.0 ) 
+      adj->value = 3.0;
+  if ( adj->value < 0.5 )
+      adj->value = 0.5;
+  ghack_map.zoom = adj->value;
+  gnome_canvas_set_pixels_per_unit (data, adj->value);
+}
+
+
+
+void
+ghack_map_cursor_to( GtkWidget *win, int x, int y, gpointer data)
+{
+  GnomeCanvasGroup *group;
+  static GnomeCanvasRE *cursor = NULL;
+
+  double x1, y1, x2, y2;
+
+  x1 = x * ghack_glyph_width() - 1;
+  y1 = y * ghack_glyph_height() - 1;
+  x2 = x1 + ghack_glyph_width() + 2;
+  y2 = y1 + ghack_glyph_height() + 2;
+
+
+  group = gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas));
+
+  if (!cursor) {
+    cursor = GNOME_CANVAS_RE (gnome_canvas_item_new (group, 
+               gnome_canvas_rect_get_type (), 
+               "outline_color", "antiquewhite2", 
+               "width_units", 1.0, NULL));
+  }
+  gnome_canvas_item_set (GNOME_CANVAS_ITEM (cursor),
+                        "x1", x1,
+                        "y1", y1,
+                        "x2", x2,
+                        "y2", y2,
+                        NULL);
+
+  gnome_canvas_item_raise_to_top( GNOME_CANVAS_ITEM( cursor));
+  gnome_canvas_item_show( GNOME_CANVAS_ITEM(cursor));
+}
+
+
+void
+ghack_map_putstr( GtkWidget *win, int attr, const char* text, gpointer data)
+{
+    g_warning("Fixme!!! ghack_map_putstr is not implemented");
+}
+
+/* NAME: 
+ *     ghack_map_print_glyph( )
+ *
+ * ARGUMENTS:
+ *     XCHAR_P x, y  -- The coordinates where which to print the glyph
+ *     GdkImlibImage*   glyph -- The glyph image to print
+ *
+ * RETURNS:
+ *     Nothing.
+ *
+ * PURPOSE:
+ *     Draw the glyph-tile at the specified coordinates.
+*/
+
+void
+ghack_map_print_glyph( GtkObject *win, 
+                      guint x, 
+                      guint y, 
+                      GdkImlibImage *im,
+                      gpointer data)
+{
+  GnomeCanvasGroup *group;
+  int i = y * COLNO + x;
+  int glyph = glyph_at(x,y);
+  GnomeCanvasImage *canvas_image = GNOME_CANVAS_IMAGE( ghack_map.map[i]);
+
+  group = gnome_canvas_root (GNOME_CANVAS (ghack_map.canvas));
+  
+  gnome_canvas_item_set (GNOME_CANVAS_ITEM ( canvas_image),
+                        "image",  im, NULL);
+  gnome_canvas_item_show( GNOME_CANVAS_ITEM( canvas_image));
+
+  canvas_image = GNOME_CANVAS_IMAGE( ghack_map.overlay[i]);
+
+  if (x==u.ux && y==u.uy)
+      ghack_map_cliparound(NULL, x, y, NULL);
+
+  if (glyph_is_pet(glyph)
+#ifdef TEXTCOLOR
+                 && iflags.hilite_pet
+#endif
+               ) {
+      gnome_canvas_item_raise_to_top( GNOME_CANVAS_ITEM( canvas_image));
+      gnome_canvas_item_show( GNOME_CANVAS_ITEM( canvas_image));
+  }
+  else {
+      gnome_canvas_item_hide( GNOME_CANVAS_ITEM( canvas_image));
+  }
+}
+
+
+/* NAME: 
+ *     ghack_map_clear( )
+ *
+ * ARGUMENTS:
+ *     NONE
+ *
+ * RETURNS:
+ *     Nothing.
+ *
+ * PURPOSE:
+ *     Clear the map by hiding all the map tiles.
+*/
+
+void
+ghack_map_clear( GtkWidget *win, gpointer data)
+{
+  int i;
+
+  for (i = 0; i < ROWNO * COLNO; i++)
+    {
+      if (GNOME_IS_CANVAS_IMAGE(ghack_map.map[i]))
+       {
+         gnome_canvas_item_hide( GNOME_CANVAS_ITEM (ghack_map.map[i]));
+       }
+      if (GNOME_IS_CANVAS_IMAGE(ghack_map.overlay[i]))
+       {
+         gnome_canvas_item_hide( GNOME_CANVAS_ITEM (ghack_map.overlay[i]));
+       }
+    }
+  gnome_canvas_update_now ( GNOME_CANVAS(ghack_map.canvas));
+}
+
+
+void
+ghack_map_display( GtkWidget *win, boolean block, gpointer data)
+{
+  gtk_widget_show_all( GTK_WIDGET(win));
+}
+
+
+void
+ghack_map_cliparound( GtkWidget *win,
+                     int x,
+                     int y,
+                     gpointer data)
+{
+  int  map_width, map_height;
+  int  to_x, to_y;
+  int  cur_x, cur_y;
+  int  width, height, half_width, half_height;
+
+  x *= ghack_glyph_width() * ghack_map.zoom;
+  y *= ghack_glyph_height() * ghack_map.zoom;
+  map_width = COLNO * ghack_glyph_width() * ghack_map.zoom;
+  map_height = ROWNO * ghack_glyph_height() * ghack_map.zoom;
+
+  gdk_window_get_size( GTK_LAYOUT (ghack_map.canvas)->bin_window, 
+         &width, &height);
+  gnome_canvas_get_scroll_offsets( ghack_map.canvas, &cur_x, &cur_y);
+
+  half_width  = width * 0.5;
+  half_height = height * 0.5;
+
+  if ( ((x - cur_x) < (width * 0.25) ) || ( (x - cur_x) > (width * 0.75) ) ) {
+    to_x = ((x-half_width) > 0)? x - half_width : 0;
+    to_x = ((x+half_width) > map_width)? map_width - 2 * half_width : to_x;
+  }                                                                             
+  else {
+    to_x = cur_x;
+  }                                                                             
+
+  if ( ((y - cur_y) < (height * 0.25) ) || ( (y - cur_y) > (height * 0.75) ) ) {
+    to_y = ((y-half_height) > 0)? y - half_height : 0;
+    to_y = ((y+half_height) > map_height)? map_height - 2 * half_height : to_y;
+  }                                                                             
+  else {
+    to_y = cur_y;
+  }                                                                             
+
+  if (to_x != cur_x || to_y != cur_y)
+    gnome_canvas_scroll_to( ghack_map.canvas, to_x, to_y);
+  //gnome_canvas_update_now ( ghack_map.canvas);
+  
+}
+
+
+
+void
+ghack_reinit_map_window ( )
+{
+  GnomeCanvasImage  *bg;
+  double width, height, x, y;
+  int i;
+
+  /* ghack_map_clear(NULL, NULL); */
+
+  width = COLNO * ghack_glyph_width();
+  height = ROWNO * ghack_glyph_height();
+
+  gnome_canvas_set_scroll_region (GNOME_CANVAS(ghack_map.canvas), 0, 0, 
+                   width+2*ghack_glyph_width(), height+2*ghack_glyph_height());
+
+  /* remove everything currently in the canvas map */
+  gtk_object_destroy( GTK_OBJECT (myCanvasGroup));
+
+  /* Put some groups back */
+  myCanvasGroup = GNOME_CANVAS_GROUP ( gnome_canvas_item_new ( 
+                   gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas)), 
+                   gnome_canvas_group_get_type (), 
+                   "x", 0.0, 
+                   "y", 0.0, 
+                   NULL) );
+
+  /* Tile the map background with a pretty image */ 
+  if (background != NULL) {
+    /* Tile the map background */
+    for (y = 0; y < height+background->rgb_height; y+=background->rgb_height)
+    {
+      for (x = 0; x < width+background->rgb_width; x+=background->rgb_width)
+       {
+         bg = GNOME_CANVAS_IMAGE( gnome_canvas_item_new (
+                     myCanvasGroup, gnome_canvas_image_get_type (),
+                     "x",      (double) x,
+                     "y",      (double) y,
+                     "width",  (double) background->rgb_width,
+                     "height", (double) background->rgb_height,
+                     "image",  background,
+                     "anchor", (GtkAnchorType) GTK_ANCHOR_CENTER,
+                     NULL) );
+         gnome_canvas_item_lower_to_bottom (GNOME_CANVAS_ITEM( bg));
+       }
+    }
+  }
+
+  /* ghack_map.map is an array of canvas images.  Each cell of
+   * the array will contain one tile.  Here, we create the
+   * space for the cells and then create the cells for easy
+   * access later.
+  */
+  for (i=0, y = 0; y < height; y+=ghack_glyph_height()) {
+      for (x = 0; x < width; x+=ghack_glyph_width()) {
+         ghack_map.map[i++] = GNOME_CANVAS_IMAGE( 
+                 gnome_canvas_item_new (
+                     myCanvasGroup,
+                     gnome_canvas_image_get_type (),
+                     "x",      (double) x,
+                     "y",      (double) y,
+                     "width",  (double) ghack_glyph_height(),
+                     "height", (double) ghack_glyph_width(),
+                     "anchor", GTK_ANCHOR_NORTH_WEST,
+                     NULL) );
+      }
+  }
+  
+  if (petmark != NULL) {
+      /* ghack_map.overlay is an array of canvas images used to
+       * overlay tile images...
+      */
+      for (i=0, y = 0; y < height; y+=ghack_glyph_height()) {
+         for (x = 0; x < width; x+=ghack_glyph_width()) {
+             ghack_map.overlay[i] = GNOME_CANVAS_IMAGE( 
+                     gnome_canvas_item_new (
+                         myCanvasGroup,
+                         gnome_canvas_image_get_type (),
+                         "x",      (double) x,
+                         "y",      (double) y,
+                         "width",  (double) petmark->rgb_width,
+                         "height", (double) petmark->rgb_height,
+                         "image",  petmark,
+                         "anchor", GTK_ANCHOR_NORTH_WEST,
+                         NULL) );
+             gnome_canvas_item_lower_to_bottom (
+                     GNOME_CANVAS_ITEM( ghack_map.overlay[i++]));
+           }
+       }
+  }
+
+  ghack_map_cliparound(NULL, u.ux, u.uy, NULL);
+  ghack_map_cursor_to(NULL, u.ux, u.uy, NULL);
+  gnome_canvas_update_now ( ghack_map.canvas);
+  doredraw();
+}
+
+