1 /* aNetHack 0.0.1 gnmap.c $ANH-Date: 1432512806 2015/05/25 00:13:26 $ $ANH-Branch: master $:$ANH-Revision: 1.10 $ */
2 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
3 /* Copyright (C) 1998 by Anthony Taylor <tonyt@ptialaska.net> */
4 /* aNetHack 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 aNetHackQt, until such time as
43 * we can come up with something better.
45 * More information about aNetHackQt can be had from:
46 * http://www.troll.no/~warwick/anethack/
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
);