initial commit, lordsawar source, slightly modified
[lordsawar] / src / smallmap.cpp
1 // Copyright (C) 2001, 2002, 2003 Michael Bartl
2 // Copyright (C) 2002, 2003, 2004, 2005, 2006 Ulf Lorenz
3 // Copyright (C) 2004, 2005, 2006 Andrea Paternesi
4 // Copyright (C) 2004 Thomas Plonka
5 // Copyright (C) 2006, 2007, 2008, 2009 Ben Asselstine
6 // Copyright (C) 2007 Ole Laursen
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 3 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 Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 
21 //  02110-1301, USA.
22
23 #include <config.h>
24
25 #include <algorithm>
26 #include <assert.h>
27
28 #include "vector.h"
29
30 #include "GameScenarioOptions.h"
31 #include "smallmap.h"
32 #include "timing.h"
33 #include "GameMap.h"
34 #include "Configuration.h"
35
36 SmallMap::SmallMap()
37 {
38     input_locked = false;
39     view.pos = Vector<int>(0, 0);
40     view.dim = Vector<int>(3, 3);
41     sleep_interval = TIMER_SMALLMAP_REFRESH;
42 }
43
44 void SmallMap::set_view(Rectangle new_view)
45 {
46     if (view != new_view)
47     {
48         view = new_view;
49         draw(Playerlist::getViewingplayer());
50     }
51 }
52
53 void SmallMap::draw_selection()
54 {
55     // draw the selection rectangle that shows the viewed part of the map
56     Vector<int> pos = mapToSurface(view.pos);
57
58     int w = int(view.w * pixels_per_tile);
59     int h = int(view.h * pixels_per_tile);
60
61     int width;
62     int height;
63     surface->get_size(width, height);
64     // this is a bit unfortunate.  we require this catch-all
65     // so that our selector box isn't too big for the smallmap
66     if (pos.x + w >= width)
67       pos.x = width - w - 1;
68     if (pos.y + h >= height)
69       pos.y = height - h - 1;
70
71     assert(pos.x >= 0 && pos.x + w < width &&
72            pos.y >= 0 && pos.y + h < height);
73     
74     Gdk::Color box_color = Gdk::Color();
75     box_color.set_rgb_p(100,100,100);
76     draw_rect(pos.x, pos.y, w, h, box_color);
77     draw_rect(pos.x-1, pos.y-1, w+2,  h+2, box_color);
78 }
79
80 void SmallMap::center_view_on_tile(Vector<int> pos, bool slide)
81 {
82   pos = clip(Vector<int>(0,0), pos - view.dim / 2, 
83              GameMap::get_dim() - view.dim);
84
85   if (slide)
86     slide_view(Rectangle(pos.x, pos.y, view.w, view.h));
87   else
88     set_view(Rectangle(pos.x, pos.y, view.w, view.h));
89           
90   view_changed.emit(view);
91 }
92
93 void SmallMap::center_view_on_pixel(Vector<int> pos, bool slide)
94 {
95   pos.x = int(round(pos.x / pixels_per_tile));
96   pos.y = int(round(pos.y / pixels_per_tile));
97
98   pos -= view.dim / calculateResizeFactor();
99
100   pos = clip(Vector<int>(0, 0), pos, GameMap::get_dim() - view.dim);
101
102   if (slide)
103     slide_view(Rectangle(pos.x, pos.y, view.w, view.h));
104   else
105     set_view(Rectangle(pos.x, pos.y, view.w, view.h));
106
107   view_changed.emit(view);
108 }
109
110 void SmallMap::after_draw()
111 {
112   int width = 0, height = 0;
113   surface->get_size(width, height);
114   if (blank_screen == true)
115     {
116       map_changed.emit(surface, Gdk::Rectangle(0, 0, width, height));
117       return;
118     }
119   Player *p = Playerlist::getViewingplayer();
120   OverviewMap::after_draw();
121   if (p->getType() == Player::HUMAN ||
122       GameScenarioOptions::s_hidden_map == false)
123     {
124       draw_cities(false);
125       draw_selection();
126     }
127   //for the editor...
128   if (GameScenarioOptions::s_round == 0)
129     {
130       draw_cities(false);
131       draw_selection();
132     }
133     map_changed.emit(surface, Gdk::Rectangle(0, 0, width, height));
134 }
135
136 void SmallMap::mouse_button_event(MouseButtonEvent e)
137 {
138   if (input_locked)
139     return;
140
141   if ((e.button == MouseButtonEvent::LEFT_BUTTON ||
142        e.button == MouseButtonEvent::RIGHT_BUTTON)
143       && e.state == MouseButtonEvent::PRESSED)
144     center_view_on_pixel(e.pos, true);
145 }
146
147 void SmallMap::mouse_motion_event(MouseMotionEvent e)
148 {
149   if (input_locked)
150     return;
151
152   if (e.pressed[MouseMotionEvent::LEFT_BUTTON] ||
153       e.pressed[MouseMotionEvent::RIGHT_BUTTON])
154     center_view_on_pixel(e.pos, false);
155 }
156
157 int slide (int x, int y)
158 {
159   int skip = 2;
160   if (x < y)
161     {
162       if (x + skip < y)
163         x += skip;
164       else
165         x++;
166     }
167   else if (x > y)
168     {
169       if (x - skip > y)
170         x -= skip;
171       else
172         x--;
173     }
174   return x;
175 }
176
177 void SmallMap::slide_view(Rectangle new_view)
178 {
179   if (view != new_view)
180     {
181       while (1)
182         {
183           Rectangle tmp_view(view);
184           tmp_view.x = slide(tmp_view.x, new_view.x);
185           tmp_view.y = slide(tmp_view.y, new_view.y);
186
187           view = tmp_view;
188           draw(Playerlist::getViewingplayer());
189           view_slid.emit(view);
190           Glib::usleep(sleep_interval);
191
192           if (tmp_view.x == new_view.x && tmp_view.y == new_view.y)
193             break;
194         }
195     }
196 }
197
198 void SmallMap::move_map_in_dir(Vector<int> dir)
199 {
200   Rectangle new_view = view;
201   new_view.pos += dir;
202   if (new_view.pos.x + new_view.w >= GameMap::getWidth() ||
203       new_view.pos.y + new_view.h >= GameMap::getHeight() ||
204       new_view.pos.x < 0 || new_view.pos.y < 0)
205     new_view.pos -= dir;
206
207   set_view(new_view);
208   view_changed.emit(view);
209 }