1 /* NetHack 3.6 gnmap.c $NHDT-Date: 1432512806 2015/05/25 00:13:26 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
2 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
3 /* Copyright (C) 1998 by Anthony Taylor <tonyt@ptialaska.net> */
4 /* NetHack may be freely redistributed. See license for details. */
16 /* globals static to this file go here */
19 GnomeCanvasImage *map[(ROWNO + 1) * COLNO];
20 GnomeCanvasImage *overlay[(ROWNO + 1) * COLNO];
25 static GdkImlibImage *background;
26 static GdkImlibImage *petmark;
27 static GnomeCanvasGroup *myCanvasGroup;
29 /* static function declarations -- local to this file go here */
30 void ghack_map_cursor_to(GtkWidget *win, int x, int y, gpointer data);
31 void ghack_map_putstr(GtkWidget *win, int attr, const char *text,
33 void ghack_map_print_glyph(GtkObject *win, guint x, guint y,
34 GdkImlibImage *im, gpointer data);
35 void ghack_map_clear(GtkWidget *win, gpointer data);
36 static void ghack_map_display(GtkWidget *win, boolean block, gpointer data);
37 static void ghack_map_cliparound(GtkWidget *win, int x, int y, gpointer data);
38 static void ghack_map_window_zoom(GtkAdjustment *adj, gpointer data);
40 /* The following XPM is the artwork of Warwick Allison
41 * <warwick@troll.no>. It has been borrowed from
42 * the most excellent NetHackQt, until such time as
43 * we can come up with something better.
45 * More information about NetHackQt can be had from:
46 * http://www.troll.no/~warwick/nethack/
50 static char *pet_mark_xpm[] = {
51 /* width height ncolors chars_per_pixel */
54 ". c None", " c #FF0000",
56 "........", ".. . .", ". ", ". ",
57 ".. .", "... ..", ".... ..."
61 * ghack_init_map_window( )
70 * Create the basic map necessities. Create a canvas;
71 * give it a background. Attach all the right signals
72 * to all the right places. Generally prepare the map
77 ghack_init_map_window()
84 GtkWidget *hSeparator;
87 double width, height, x, y;
90 width = COLNO * ghack_glyph_width();
91 height = ROWNO * ghack_glyph_height();
93 vbox = gtk_vbox_new(FALSE, 4);
94 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
95 gtk_widget_show(vbox);
97 /* Add in a horiz seperator */
98 hSeparator = gtk_hseparator_new();
99 gtk_box_pack_start(GTK_BOX(vbox), hSeparator, FALSE, FALSE, 2);
100 gtk_widget_show(hSeparator);
102 hbox = gtk_hbox_new(FALSE, 4);
103 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
104 gtk_widget_show(hbox);
106 /* Create the Zoom spinbutton.
108 ghack_map.zoom = 1.0;
109 w = gtk_label_new("Zoom:");
110 gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
113 GTK_ADJUSTMENT(gtk_adjustment_new(1.00, 0.5, 3.00, 0.05, 0.50, 0.50));
114 w = gtk_spin_button_new(adj, 0.5, 2);
115 gtk_widget_set_usize(w, 50, 0);
116 gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
119 /* Canvas and scrollbars
121 gtk_widget_push_visual(gdk_imlib_get_visual());
122 gtk_widget_push_colormap(gdk_imlib_get_colormap());
123 ghack_map.canvas = GNOME_CANVAS(gnome_canvas_new());
124 // gtk_widget_push_visual(gdk_rgb_get_visual());
125 // gtk_widget_push_colormap(gdk_rgb_get_cmap());
126 // ghack_map.canvas = GNOME_CANVAS (gnome_canvas_new_aa());
128 gtk_widget_pop_colormap();
129 gtk_widget_pop_visual();
130 gtk_widget_show(GTK_WIDGET(ghack_map.canvas));
132 table = gtk_table_new(2, 2, FALSE);
133 gtk_table_set_row_spacings(GTK_TABLE(table), 4);
134 gtk_table_set_col_spacings(GTK_TABLE(table), 4);
135 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
136 gtk_widget_show(table);
138 frame = gtk_frame_new(NULL);
139 ghack_map.frame = frame;
140 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
141 gtk_table_attach(GTK_TABLE(table), frame, 0, 1, 0, 1,
142 GTK_EXPAND | GTK_FILL | GTK_SHRINK,
143 GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
144 gtk_widget_show(frame);
146 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(ghack_map.canvas));
147 gnome_canvas_set_scroll_region(GNOME_CANVAS(ghack_map.canvas), 0, 0,
148 width + 2 * ghack_glyph_width(),
149 height + 2 * ghack_glyph_height());
151 gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(ghack_map.canvas), 1.0);
153 w = gtk_hscrollbar_new(GTK_LAYOUT(ghack_map.canvas)->hadjustment);
154 gtk_table_attach(GTK_TABLE(table), w, 0, 1, 1, 2,
155 GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0);
158 w = gtk_vscrollbar_new(GTK_LAYOUT(ghack_map.canvas)->vadjustment);
159 gtk_table_attach(GTK_TABLE(table), w, 1, 2, 0, 1, GTK_FILL,
160 GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
163 myCanvasGroup = GNOME_CANVAS_GROUP(gnome_canvas_item_new(
164 gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas)),
165 gnome_canvas_group_get_type(), "x", 0.0, "y", 0.0, NULL));
167 /* Tile the map background with a pretty image */
168 background = gdk_imlib_load_image((char *) "mapbg.xpm");
169 if (background == NULL) {
171 "Bummer! Failed to load the map background image (mapbg.xpm)!");
173 gdk_imlib_render(background, background->rgb_width,
174 background->rgb_height);
176 /* Tile the map background */
177 for (y = 0; y < height + background->rgb_height;
178 y += background->rgb_height) {
179 for (x = 0; x < width + background->rgb_width;
180 x += background->rgb_width) {
181 bg = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
182 myCanvasGroup, gnome_canvas_image_get_type(), "x",
183 (double) x, "y", (double) y, "width",
184 (double) background->rgb_width, "height",
185 (double) background->rgb_height, "image", background,
186 "anchor", (GtkAnchorType) GTK_ANCHOR_CENTER, NULL));
187 gnome_canvas_item_lower_to_bottom(GNOME_CANVAS_ITEM(bg));
192 /* ghack_map.map is an array of canvas images. Each cell of
193 * the array will contain one tile. Here, we create the
194 * space for the cells and then create the cells for easy
197 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
198 for (x = 0; x < width; x += ghack_glyph_width()) {
199 ghack_map.map[i++] = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
200 myCanvasGroup, gnome_canvas_image_get_type(), "x", (double) x,
201 "y", (double) y, "width", (double) ghack_glyph_width(),
202 "height", (double) ghack_glyph_height(), "anchor",
203 GTK_ANCHOR_NORTH_WEST, NULL));
207 /* Set up the pet mark image */
208 petmark = gdk_imlib_create_image_from_xpm_data(pet_mark_xpm);
209 if (petmark == NULL) {
210 g_warning("Bummer! Failed to load the pet_mark image!");
212 gdk_imlib_render(petmark, petmark->rgb_width, petmark->rgb_height);
214 /* ghack_map.overlay is an array of canvas images used to
215 * overlay tile images...
217 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
218 for (x = 0; x < width; x += ghack_glyph_width()) {
219 ghack_map.overlay[i] =
220 GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
221 myCanvasGroup, gnome_canvas_image_get_type(), "x",
222 (double) x, "y", (double) y, "width",
223 (double) petmark->rgb_width, "height",
224 (double) petmark->rgb_height, "image", petmark,
225 "anchor", GTK_ANCHOR_NORTH_WEST, NULL));
226 gnome_canvas_item_lower_to_bottom(
227 GNOME_CANVAS_ITEM(ghack_map.overlay[i++]));
232 /* Resize the canvas when the spinbutton changes
234 gtk_signal_connect(GTK_OBJECT(adj), "value_changed",
235 (GtkSignalFunc) ghack_map_window_zoom,
240 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_curs",
241 GTK_SIGNAL_FUNC(ghack_map_cursor_to), NULL);
242 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_putstr",
243 GTK_SIGNAL_FUNC(ghack_map_putstr), NULL);
244 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_print_glyph",
245 GTK_SIGNAL_FUNC(ghack_map_print_glyph), NULL);
246 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_clear",
247 GTK_SIGNAL_FUNC(ghack_map_clear), NULL);
248 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_display",
249 GTK_SIGNAL_FUNC(ghack_map_display), NULL);
250 gtk_signal_connect(GTK_OBJECT(vbox), "ghack_cliparound",
251 GTK_SIGNAL_FUNC(ghack_map_cliparound), NULL);
252 gtk_signal_connect(GTK_OBJECT(ghack_map.canvas), "button_press_event",
253 GTK_SIGNAL_FUNC(ghack_handle_button_press), NULL);
254 gtk_signal_connect(GTK_OBJECT(ghack_map.canvas), "gnome_delay_output",
255 GTK_SIGNAL_FUNC(ghack_delay), NULL);
257 return GTK_WIDGET(vbox);
261 * ghack_map_window_zoom
264 * double zoom -- The zoom factor
270 * Zoom the map image in and out. This should allow the user to
271 * dynamically scale the map. Ideally, the background should
272 * *NOT* scale, but this may be impractical.
276 ghack_map_window_zoom(GtkAdjustment *adj, gpointer data)
278 if (adj->value > 3.0)
280 if (adj->value < 0.5)
282 ghack_map.zoom = adj->value;
283 gnome_canvas_set_pixels_per_unit(data, adj->value);
287 ghack_map_cursor_to(GtkWidget *win, int x, int y, gpointer data)
289 GnomeCanvasGroup *group;
290 static GnomeCanvasRE *cursor = NULL;
292 double x1, y1, x2, y2;
296 x1 = x * ghack_glyph_width() - 1;
297 y1 = y * ghack_glyph_height() - 1;
298 x2 = x1 + ghack_glyph_width() + 2;
299 y2 = y1 + ghack_glyph_height() + 2;
300 hp = u.mtimedone ? (u.mhmax ? (float) u.mh / u.mhmax : 1)
301 : (u.uhpmax ? (float) u.uhp / u.uhpmax : 1);
304 g = (hp >= 0.75) ? 255 : (hp >= 0.25 ? 255 * 2 * (hp - 0.25) : 0);
305 b = (hp >= 0.75) ? 255 * 4 * (hp - 0.75)
306 : (hp >= 0.25 ? 0 : 255 * 4 * (0.25 - hp));
308 group = gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas));
311 cursor = GNOME_CANVAS_RE(gnome_canvas_item_new(
312 group, gnome_canvas_rect_get_type(), "width_units", 1.0, NULL));
314 gnome_canvas_item_set(GNOME_CANVAS_ITEM(cursor), "outline_color_rgba",
315 GNOME_CANVAS_COLOR(r, g, b), "x1", x1, "y1", y1,
316 "x2", x2, "y2", y2, NULL);
318 gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(cursor));
319 gnome_canvas_item_show(GNOME_CANVAS_ITEM(cursor));
323 ghack_map_putstr(GtkWidget *win, int attr, const char *text, gpointer data)
325 g_warning("Fixme!!! ghack_map_putstr is not implemented");
329 * ghack_map_print_glyph( )
332 * XCHAR_P x, y -- The coordinates where which to print the glyph
333 * GdkImlibImage* glyph -- The glyph image to print
339 * Draw the glyph-tile at the specified coordinates.
343 ghack_map_print_glyph(GtkObject *win, guint x, guint y, GdkImlibImage *im,
346 GnomeCanvasGroup *group;
347 int i = y * COLNO + x;
348 int glyph = glyph_at(x, y);
349 GnomeCanvasImage *canvas_image = GNOME_CANVAS_IMAGE(ghack_map.map[i]);
351 group = gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas));
353 gnome_canvas_item_set(GNOME_CANVAS_ITEM(canvas_image), "image", im, NULL);
354 gnome_canvas_item_show(GNOME_CANVAS_ITEM(canvas_image));
356 canvas_image = GNOME_CANVAS_IMAGE(ghack_map.overlay[i]);
358 if (x == u.ux && y == u.uy)
359 ghack_map_cliparound(NULL, x, y, NULL);
361 if (glyph_is_pet(glyph)
366 gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(canvas_image));
367 gnome_canvas_item_show(GNOME_CANVAS_ITEM(canvas_image));
369 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(canvas_image));
383 * Clear the map by hiding all the map tiles.
387 ghack_map_clear(GtkWidget *win, gpointer data)
391 for (i = 0; i < ROWNO * COLNO; i++) {
392 if (GNOME_IS_CANVAS_IMAGE(ghack_map.map[i])) {
393 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ghack_map.map[i]));
395 if (GNOME_IS_CANVAS_IMAGE(ghack_map.overlay[i])) {
396 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ghack_map.overlay[i]));
399 gnome_canvas_update_now(GNOME_CANVAS(ghack_map.canvas));
403 ghack_map_display(GtkWidget *win, boolean block, gpointer data)
405 gtk_widget_show_all(GTK_WIDGET(win));
409 ghack_map_cliparound(GtkWidget *win, int x, int y, gpointer data)
411 int map_width, map_height;
414 int width, height, half_width, half_height;
416 x *= ghack_glyph_width() * ghack_map.zoom;
417 y *= ghack_glyph_height() * ghack_map.zoom;
418 map_width = COLNO * ghack_glyph_width() * ghack_map.zoom;
419 map_height = ROWNO * ghack_glyph_height() * ghack_map.zoom;
421 gdk_window_get_size(GTK_LAYOUT(ghack_map.canvas)->bin_window, &width,
423 gnome_canvas_get_scroll_offsets(ghack_map.canvas, &cur_x, &cur_y);
425 half_width = width * 0.5;
426 half_height = height * 0.5;
428 if (((x - cur_x) < (width * 0.25)) || ((x - cur_x) > (width * 0.75))) {
429 to_x = ((x - half_width) > 0) ? x - half_width : 0;
430 to_x = ((x + half_width) > map_width) ? map_width - 2 * half_width
436 if (((y - cur_y) < (height * 0.25)) || ((y - cur_y) > (height * 0.75))) {
437 to_y = ((y - half_height) > 0) ? y - half_height : 0;
438 to_y = ((y + half_height) > map_height) ? map_height - 2 * half_height
444 if (to_x != cur_x || to_y != cur_y)
445 gnome_canvas_scroll_to(ghack_map.canvas, to_x, to_y);
446 // gnome_canvas_update_now ( ghack_map.canvas);
450 ghack_reinit_map_window()
452 GnomeCanvasImage *bg;
453 double width, height, x, y;
456 /* ghack_map_clear(NULL, NULL); */
458 width = COLNO * ghack_glyph_width();
459 height = ROWNO * ghack_glyph_height();
461 gnome_canvas_set_scroll_region(GNOME_CANVAS(ghack_map.canvas), 0, 0,
462 width + 2 * ghack_glyph_width(),
463 height + 2 * ghack_glyph_height());
465 /* remove everything currently in the canvas map */
466 gtk_object_destroy(GTK_OBJECT(myCanvasGroup));
468 /* Put some groups back */
469 myCanvasGroup = GNOME_CANVAS_GROUP(gnome_canvas_item_new(
470 gnome_canvas_root(GNOME_CANVAS(ghack_map.canvas)),
471 gnome_canvas_group_get_type(), "x", 0.0, "y", 0.0, NULL));
473 /* Tile the map background with a pretty image */
474 if (background != NULL) {
475 /* Tile the map background */
476 for (y = 0; y < height + background->rgb_height;
477 y += background->rgb_height) {
478 for (x = 0; x < width + background->rgb_width;
479 x += background->rgb_width) {
480 bg = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
481 myCanvasGroup, gnome_canvas_image_get_type(), "x",
482 (double) x, "y", (double) y, "width",
483 (double) background->rgb_width, "height",
484 (double) background->rgb_height, "image", background,
485 "anchor", (GtkAnchorType) GTK_ANCHOR_CENTER, NULL));
486 gnome_canvas_item_lower_to_bottom(GNOME_CANVAS_ITEM(bg));
491 /* ghack_map.map is an array of canvas images. Each cell of
492 * the array will contain one tile. Here, we create the
493 * space for the cells and then create the cells for easy
496 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
497 for (x = 0; x < width; x += ghack_glyph_width()) {
498 ghack_map.map[i++] = GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
499 myCanvasGroup, gnome_canvas_image_get_type(), "x", (double) x,
500 "y", (double) y, "width", (double) ghack_glyph_width(),
501 "height", (double) ghack_glyph_height(), "anchor",
502 GTK_ANCHOR_NORTH_WEST, NULL));
506 if (petmark != NULL) {
507 /* ghack_map.overlay is an array of canvas images used to
508 * overlay tile images...
510 for (i = 0, y = 0; y < height; y += ghack_glyph_height()) {
511 for (x = 0; x < width; x += ghack_glyph_width()) {
512 ghack_map.overlay[i] =
513 GNOME_CANVAS_IMAGE(gnome_canvas_item_new(
514 myCanvasGroup, gnome_canvas_image_get_type(), "x",
515 (double) x, "y", (double) y, "width",
516 (double) petmark->rgb_width, "height",
517 (double) petmark->rgb_height, "image", petmark,
518 "anchor", GTK_ANCHOR_NORTH_WEST, NULL));
519 gnome_canvas_item_lower_to_bottom(
520 GNOME_CANVAS_ITEM(ghack_map.overlay[i++]));
525 ghack_map_cliparound(NULL, u.ux, u.uy, NULL);
526 ghack_map_cursor_to(NULL, u.ux, u.uy, NULL);
527 gnome_canvas_update_now(ghack_map.canvas);