Atrinik Client  4.0
minimap.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <region_map.h>
34 
38 enum {
39  MINIMAP_TEXTURE_BG,
40  MINIMAP_TEXTURE_MASK,
41  MINIMAP_TEXTURE_BORDER,
42  MINIMAP_TEXTURE_BORDER_ROTATED,
43  MINIMAP_TEXTURE_NUM
44 };
45 
49 typedef enum {
50  MINIMAP_TYPE_PREFER_REGION_MAP,
51  MINIMAP_TYPE_REGION_MAP,
52  MINIMAP_TYPE_DYNAMIC,
53 
54  MINIMAP_TYPE_NUM
56 
60 #define MINIMAP_CIRCLE_PADDING(widget) (10. * ((double) (widget)->w / \
61  TEXTURE_CLIENT(minimap_texture_names[MINIMAP_TEXTURE_BG])->w))
62 
66 typedef struct minimap_widget {
70  SDL_Surface *surface;
71 
75  SDL_Surface *textures[MINIMAP_TEXTURE_NUM];
76 
82 
86 static const char *const minimap_texture_names[MINIMAP_TEXTURE_NUM] = {
87  "minimap_bg", "minimap_mask", "minimap_border", "minimap_border_rotated"
88 };
89 
93 static const char *const minimap_display_modes[MINIMAP_TYPE_NUM] = {
94  "Prefer region maps", "Only region maps", "Only dynamic maps"
95 };
96 
98 static void widget_draw(widgetdata *widget)
99 {
100  minimap_widget_t *minimap;
101  SDL_Rect box;
102  size_t i;
103 
104  minimap = widget->subwidget;
105 
106  /* No surface or the widget dimensions changed, (re-)create the surface
107  * and the zoomed minimap textures. */
108  if (widget->surface == NULL || widget->surface->w != widget->w ||
109  widget->surface->h != widget->h) {
110  SDL_Surface *texture;
111 
112  if (widget->surface != NULL) {
113  SDL_FreeSurface(widget->surface);
114  }
115 
116  widget->surface = SDL_CreateRGBSurface(get_video_flags(), widget->w,
117  widget->h, video_get_bpp(), 0, 0, 0, 0);
118  minimap_redraw_flag = 1;
119 
120  for (i = 0; i < MINIMAP_TEXTURE_NUM; i++) {
121  if (minimap->textures[i] != NULL) {
122  SDL_FreeSurface(minimap->textures[i]);
123  }
124 
125  texture = TEXTURE_CLIENT(minimap_texture_names[i]);
126  minimap->textures[i] = zoomSurface(texture,
127  (double) widget->w / texture->w + 0.001,
128  (double) widget->h / texture->h + 0.001,
130  }
131  }
132 
133  if (minimap_redraw_flag) {
134  minimap_redraw_flag = 0;
135  SDL_FillRect(widget->surface, NULL, 0);
136  SDL_BlitSurface(minimap->textures[MINIMAP_TEXTURE_BG], NULL,
137  widget->surface, NULL);
138 
139  /* Determine which version of the minimap to show based on the user's
140  * preferences. */
141  if (minimap->type == MINIMAP_TYPE_REGION_MAP || (minimap->type ==
142  MINIMAP_TYPE_PREFER_REGION_MAP && MapData.region_has_map)) {
143  /* Free dynamic map surface. */
144  if (minimap->surface != NULL) {
145  SDL_FreeSurface(minimap->surface);
146  minimap->surface = NULL;
147  }
148 
150  int cx, cy, sx, sy;
151  double rad;
152  SDL_Rect rect;
153  SDL_Surface *surface;
154 
155  cx = (widget->w - MINIMAP_CIRCLE_PADDING(widget) * 2) / 2;
156  cy = (widget->h - MINIMAP_CIRCLE_PADDING(widget) * 2) / 2;
157  rad = 45.0 * (M_PI / 180.0);
158  sx = cx * cos(rad);
159  sy = cy * sin(rad);
160 
161  rect.x = cx - sx + MINIMAP_CIRCLE_PADDING(widget);
162  rect.y = cy - sy + MINIMAP_CIRCLE_PADDING(widget);
163  rect.w = widget->surface->w - MINIMAP_CIRCLE_PADDING(widget) *
164  2 - (cx - sx) * 2;
165  rect.h = widget->surface->h - MINIMAP_CIRCLE_PADDING(widget) *
166  2 - (cy - sy) * 2;
167 
168  MapData.region_map->pos.x += rect.x;
169  MapData.region_map->pos.y += rect.y;
170  MapData.region_map->pos.w = rect.w;
171  MapData.region_map->pos.h = rect.h;
173  region_map_pan(MapData.region_map);
174  MapData.region_map->pos.x -= rect.x;
175  MapData.region_map->pos.y -= rect.y;
176  MapData.region_map->pos.w = widget->surface->w;
177  MapData.region_map->pos.h = widget->surface->h;
178 
180 
181  SDL_BlitSurface(surface, &MapData.region_map->pos,
182  widget->surface, NULL);
183  region_map_render_fow(MapData.region_map,
184  widget->surface, 0, 0);
186  widget->surface, 0, 0);
187  } else {
188  SDL_Rect tmp;
189 
190  tmp.w = widget->w;
191  tmp.h = widget->h;
192  text_show(widget->surface, FONT_SANS10, "Downloading...", 0, 0,
194  TEXT_OUTLINE, &tmp);
195  }
196 
197  SDL_BlitSurface(minimap->textures[MINIMAP_TEXTURE_MASK], NULL,
198  widget->surface, NULL);
199  SDL_BlitSurface(minimap->textures[MINIMAP_TEXTURE_BORDER_ROTATED],
200  NULL, widget->surface, NULL);
201  } else {
202  SDL_Surface *zoomed;
203  SDL_Rect zoomedbox;
204 
205  if (minimap->surface == NULL) {
206  minimap->surface = SDL_CreateRGBSurface(get_video_flags(),
207  850 * (MAP_FOW_SIZE / 2), 600 * (MAP_FOW_SIZE / 2),
208  video_get_bpp(), 0, 0, 0, 0);
209  }
210 
211  double zoomx = (double) widget->w / minimap->surface->w *
212  (minimap->surface->w / (MAP_FOW_SIZE + 1.0));
213  double zoomy = (double) widget->h / minimap->surface->h *
214  (minimap->surface->h / (MAP_FOW_SIZE + 1.0));
215 
216  SDL_FillRect(minimap->surface, NULL, 0);
217  map_draw_map(minimap->surface);
218 
219  zoomx = (MapData.region_map->zoom) / 100.0 * (zoomx / 100.0);
220  zoomy = (MapData.region_map->zoom) / 100.0 * (zoomy / 100.0);
221  zoomed = zoomSurface(minimap->surface, zoomx, zoomy,
223  zoomedbox.x = zoomed->w / 2 - widget->surface->w / 2;
224  zoomedbox.y = zoomed->h / 2 - widget->surface->h / 2;
225  zoomedbox.w = widget->surface->w;
226  zoomedbox.h = widget->surface->h;
227  SDL_BlitSurface(zoomed, &zoomedbox, widget->surface, NULL);
228  SDL_FreeSurface(zoomed);
229 
230  SDL_BlitSurface(minimap->textures[MINIMAP_TEXTURE_MASK], NULL,
231  widget->surface, NULL);
232  SDL_BlitSurface(minimap->textures[MINIMAP_TEXTURE_BORDER], NULL,
233  widget->surface, NULL);
234  }
235 
236  SDL_SetColorKey(widget->surface, SDL_SRCCOLORKEY,
237  getpixel(widget->surface, 0, 0));
238  }
239 
240  box.x = widget->x;
241  box.y = widget->y;
242  SDL_BlitSurface(widget->surface, NULL, ScreenSurface, &box);
243 }
244 
246 static int widget_event(widgetdata *widget, SDL_Event *event)
247 {
248  if (event->type == SDL_MOUSEBUTTONDOWN) {
249  if (event->button.button == SDL_BUTTON_WHEELUP) {
250  /* Zoom in. */
251  if (MapData.region_map->zoom < 100) {
252  MapData.region_map->zoom += 5;
253  minimap_redraw_flag = 1;
254  return 1;
255  }
256  } else if (event->button.button == SDL_BUTTON_WHEELDOWN) {
257  /* Zoom out. */
258  if (MapData.region_map->zoom > 10) {
259  MapData.region_map->zoom -= 5;
260  minimap_redraw_flag = 1;
261  return 1;
262  }
263  }
264  }
265 
266  return 0;
267 }
268 
270 static void widget_deinit(widgetdata *widget)
271 {
272  minimap_widget_t *minimap;
273  size_t i;
274 
275  minimap = widget->subwidget;
276  SDL_FreeSurface(minimap->surface);
277 
278  for (i = 0; i < MINIMAP_TEXTURE_NUM; i++) {
279  SDL_FreeSurface(minimap->textures[i]);
280  }
281 }
282 
284 static int widget_load(widgetdata *widget, const char *keyword, const char *parameter)
285 {
286  minimap_widget_t *minimap;
287 
288  minimap = widget->subwidget;
289 
290  if (strcmp(keyword, "type") == 0) {
291  minimap->type = atoi(parameter);
292  return 1;
293  }
294 
295  return 0;
296 }
297 
299 static void widget_save(widgetdata *widget, FILE *fp, const char *padding)
300 {
301  minimap_widget_t *minimap;
302 
303  minimap = widget->subwidget;
304 
305  fprintf(fp, "%stype = %d\n", padding, minimap->type);
306 }
307 
308 static void menu_minimap_display_change(widgetdata *widget,
309  widgetdata *menuitem, SDL_Event *event)
310 {
311  minimap_widget_t *minimap;
312  widgetdata *tmp2;
313  _widget_label *label;
314  size_t i;
315 
316  minimap = widget->subwidget;
317 
318  for (tmp2 = menuitem->inv; tmp2; tmp2 = tmp2->next) {
319  if (tmp2->type == LABEL_ID) {
320  label = LABEL(tmp2);
321 
322  for (i = 0; i < MINIMAP_TYPE_NUM; i++) {
323  if (strcmp(minimap_display_modes[i], label->text) == 0) {
324  minimap->type = i;
325  break;
326  }
327  }
328 
329  minimap_redraw_flag = 1;
330 
331  break;
332  }
333  }
334 }
335 
336 static void menu_minimap_display(widgetdata *widget, widgetdata *menuitem,
337  SDL_Event *event)
338 {
339  minimap_widget_t *minimap;
340  widgetdata *submenu;
341  size_t i;
342 
343  minimap = widget->subwidget;
344  submenu = MENU(menuitem->env)->submenu;
345 
346  for (i = 0; i < MINIMAP_TYPE_NUM; i++) {
348  &menu_minimap_display_change, MENU_RADIO, minimap->type == i);
349  }
350 }
351 
353 static int widget_menu_handle(widgetdata *widget, SDL_Event *event)
354 {
355  widgetdata *menu;
356 
357  menu = create_menu(event->motion.x, event->motion.y, widget);
358 
359  widget_menu_standard_items(widget, menu);
360  add_menuitem(menu, "Display >", &menu_minimap_display, MENU_SUBMENU, 0);
361 
362  menu_finalize(menu);
363 
364  return 1;
365 }
366 
368 static void
369 widget_padding (widgetdata *widget, int *x, int *y)
370 {
371  *x = *y = MINIMAP_CIRCLE_PADDING(widget);
372 }
373 
374 void widget_minimap_init(widgetdata *widget)
375 {
376  minimap_widget_t *minimap;
377 
378  minimap = ecalloc(1, sizeof(*minimap));
379  minimap->type = MINIMAP_TYPE_PREFER_REGION_MAP;
380  MapData.region_map->zoom = 50;
381 
382  widget->draw_func = widget_draw;
383  widget->event_func = widget_event;
384  widget->deinit_func = widget_deinit;
385  widget->load_func = widget_load;
386  widget->save_func = widget_save;
387  widget->menu_handle_func = widget_menu_handle;
388  widget->padding_func = widget_padding;
389  widget->subwidget = minimap;
390 }
static SDL_Surface * zoomed
Definition: map.c:55
int type
Definition: widget.h:118
#define MINIMAP_CIRCLE_PADDING(widget)
Definition: minimap.c:60
struct widgetdata * env
Definition: widget.h:98
struct minimap_widget minimap_widget_t
void * subwidget
Definition: widget.h:107
minimap_type_t
Definition: minimap.c:49
void region_map_resize(region_map_t *region_map, int adjust)
Definition: region_map.c:362
static void widget_draw(widgetdata *widget)
Definition: minimap.c:98
SDL_Surface * surface
Definition: widget.h:110
struct region_map * region_map
Definition: map.h:169
uint32_t get_video_flags(void)
Definition: video.c:365
static const char *const minimap_texture_names[MINIMAP_TEXTURE_NUM]
Definition: minimap.c:86
void text_show(SDL_Surface *surface, font_struct *font, const char *text, int x, int y, const char *color_notation, uint64_t flags, SDL_Rect *box)
Definition: text.c:1983
Uint32 getpixel(SDL_Surface *surface, int x, int y)
Definition: sprite.c:910
#define COLOR_HGOLD
Definition: text.h:319
static int widget_menu_handle(widgetdata *widget, SDL_Event *event)
Definition: minimap.c:353
void menu_finalize(widgetdata *widget)
Definition: widget.c:2524
struct widgetdata * next
Definition: widget.h:86
SDL_Surface * ScreenSurface
Definition: main.c:47
SDL_Surface * textures[MINIMAP_TEXTURE_NUM]
Definition: minimap.c:75
struct widgetdata * inv
Definition: widget.h:92
#define TEXT_ALIGN_CENTER
Definition: text.h:230
_mapdata MapData
Definition: map.c:64
static int widget_event(widgetdata *widget, SDL_Event *event)
Definition: minimap.c:246
static void widget_deinit(widgetdata *widget)
Definition: minimap.c:270
static void widget_padding(widgetdata *widget, int *x, int *y)
Definition: minimap.c:369
int video_get_bpp(void)
Definition: video.c:334
bool region_map_ready(region_map_t *region_map)
Definition: region_map.c:200
static void widget_save(widgetdata *widget, FILE *fp, const char *padding)
Definition: minimap.c:299
SDL_Rect pos
Definition: region_map.h:224
SDL_Surface * region_map_surface(region_map_t *region_map)
Definition: region_map.c:319
int64_t setting_get_int(int cat, int setting)
Definition: settings.c:414
int x
Definition: widget.h:48
static const char *const minimap_display_modes[MINIMAP_TYPE_NUM]
Definition: minimap.c:93
#define TEXT_OUTLINE
Definition: text.h:255
bool region_has_map
Definition: map.h:128
widgetdata * create_menu(int x, int y, widgetdata *owner)
Definition: widget.c:2428
int w
Definition: widget.h:54
int h
Definition: widget.h:57
#define MAP_FOW_SIZE
Definition: config.h:65
void region_map_render_marker(region_map_t *region_map, SDL_Surface *surface, int x, int y)
Definition: region_map.c:417
SDL_Surface * surface
Definition: minimap.c:70
#define TEXT_VALIGN_CENTER
Definition: text.h:246
void map_draw_map(SDL_Surface *surface)
Definition: map.c:1520
void add_menuitem(widgetdata *menu, const char *text, void(*menu_func_ptr)(widgetdata *, widgetdata *, SDL_Event *event), int menu_type, int val)
Definition: widget.c:2451
static int widget_load(widgetdata *widget, const char *keyword, const char *parameter)
Definition: minimap.c:284
minimap_type_t type
Definition: minimap.c:80
int y
Definition: widget.h:51
char * text
Definition: widget.h:210