From: jwalz Date: Sat, 5 Jan 2002 21:06:01 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: MOVE2GIT~3611 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74975f098333c073dde6e50ba2cce8edf4cc2619;p=nethack *** empty log message *** --- diff --git a/win/gnome/gnmap.c b/win/gnome/gnmap.c new file mode 100644 index 000000000..e7082bfc8 --- /dev/null +++ b/win/gnome/gnmap.c @@ -0,0 +1,612 @@ +/* SCCS Id: @(#)gnmap.c 3.3 2000/07/16 */ +/* Copyright (C) 1998 by Erik Andersen */ +/* Copyright (C) 1998 by Anthony Taylor */ +/* 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 + * . 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(); +} + +