2
* Copyright (C) 2002, 2004 by The Widelands Development Team
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
#include "interactive_player.h"
25
#include "ui_button.h"
26
#include "ui_signal.h"
27
#include "ui_window.h"
28
#include "watchwindow.h"
33
#define REFRESH_TIME 5000
36
==============================================================================
40
==============================================================================
42
//Holds information for a view
43
struct WatchWindowView {
45
Interactive_Player *parent;
46
Object_Ptr tracking; // if non-null, we're tracking a Bob
49
class WatchWindow : public UIWindow {
51
WatchWindow(Interactive_Player *parent, int x, int y, int w, int h, Coords coords, bool single_window=false);
54
UISignal1<Point> warp_mainview;
56
void start_tracking(Point pos);
57
void toggle_tracking();
58
void act_mainview_goto();
60
void add_view(Coords coords);
61
void next_view(bool first=false);
62
void show_view(bool first=false);
63
Point calc_coords(Coords coords);
65
void set_view(int index);
66
void close_cur_view();
67
void toggle_buttons();
71
void stop_tracking_by_drag(int x, int y);
79
std::vector<WatchWindowView> m_views;
80
UIButton* m_view_btns[NUM_VIEWS];
84
static WatchWindow *g_watch_window = NULL;
88
WatchWindow::WatchWindow
90
Initialize a watch window.
93
WatchWindow::WatchWindow(Interactive_Player *parent, int x, int y, int w, int h, Coords coords, bool single_window)
94
: UIWindow(parent, x, y, w, h, "Watch")
98
m_game = parent->get_game();
99
last_visit = m_game->get_gametime();
100
m_single_window = single_window;
103
btn = new UIButton(this, 0, h - 34, 34, 34, 20);
104
btn->set_pic(g_gr->get_picture(PicMod_UI, "pics/menu_watch_follow.png", true));
105
btn->clicked.set(this, &WatchWindow::toggle_tracking);
107
btn = new UIButton(this, 34, h - 34, 34, 34, 21);
108
btn->set_pic(g_gr->get_picture(PicMod_UI, "pics/menu_goto.png", true));
109
btn->clicked.set(this, &WatchWindow::act_mainview_goto);
111
if (m_single_window) {
112
for (int i=0;i<NUM_VIEWS;i++) {
113
btn = new UIButton(this, 74 + (17 * i), 200 - 34, 17, 34, 0, i);
115
btn->clickedid.set(this, &WatchWindow::set_view);
116
m_view_btns[i] = btn;
119
btn = new UIButton(this, w-34, h - 34, 34, 34, 22);
120
btn->set_pic(g_gr->get_picture(PicMod_UI, "pics/menu_abort.png", true));
121
btn->clicked.set(this, &WatchWindow::close_cur_view);
123
m_mapview = new Map_View(this, 0, 0, 200, 166, parent);
124
m_mapview->fieldclicked.set(parent, &Interactive_Player::field_action);
125
m_mapview->warpview.set(this, &WatchWindow::stop_tracking_by_drag);
126
warp_mainview.set(parent, &Interactive_Base::move_view_to_point);
133
//Add a view to a watchwindow, if there is space left
134
void WatchWindow::add_view(Coords coords) {
135
if (m_views.size() >= NUM_VIEWS)
137
WatchWindowView view;
140
view.view_point = calc_coords(coords);
142
m_views.push_back(view);
147
//Calc point on map from coords
148
Point WatchWindow::calc_coords(Coords coords) {
149
// Initial positioning
150
int vx = MULTIPLY_WITH_FIELD_WIDTH(coords.x);
151
int vy = MULTIPLY_WITH_HALF_FIELD_HEIGHT(coords.y);
153
Point p (vx - m_mapview->get_w()/2, vy - m_mapview->get_h()/2);
157
//Switch to next view
158
void WatchWindow::next_view(bool first) {
159
if (!first && m_views.size() == 1)
163
if (first || (static_cast<uint>(m_cur_index) == m_views.size()-1 && m_cur_index != 0))
165
else if (static_cast<uint>(m_cur_index) < m_views.size()-1)
170
//Sets the current view to index and resets timeout
171
void WatchWindow::set_view(int index) {
174
last_visit = m_game->get_gametime();
178
//Saves the coordinates of a view if it was already shown (and possibly moved)
179
void WatchWindow::save_coords() {
180
m_views[m_cur_index].view_point = m_mapview->get_viewpoint();
183
//Closes current view and disables button
184
void WatchWindow::close_cur_view() {
185
if (m_views.size() == 1) {
190
int old_index = m_cur_index;
193
std::vector<WatchWindowView>::iterator view_it = m_views.begin();
195
for (int i=0;i<old_index;i++)
198
m_view_btns[m_cur_index]->set_enabled(false);
199
m_views.erase(view_it);
203
//Enables/Disables buttons for views
204
void WatchWindow::toggle_buttons() {
205
for (uint i=0;i<NUM_VIEWS;i++) {
206
if (i<m_views.size()) {
208
snprintf(buf, sizeof(buf), "%i", i+1);
209
m_view_btns[i]->set_title(buf);
210
m_view_btns[i]->set_enabled(true);
213
m_view_btns[i]->set_title("-");
214
m_view_btns[i]->set_enabled(false);
219
//Draws the current view
220
void WatchWindow::show_view(bool first) {
221
m_mapview->set_viewpoint(m_views[m_cur_index].view_point);
222
//Tracking turned of by default
223
//start_tracking(m_views[m_cur_index].view_point);
226
WatchWindow::~WatchWindow() {
227
g_watch_window = NULL;
232
WatchWindow::start_tracking
234
Find the nearest bob. Other objects cannot move and are therefore not of
237
point is *not* a coordinate, but a map-global position in pixels.
240
void WatchWindow::start_tracking(Point pos)
242
Map* map = m_game->get_map();
243
std::vector<Bob*> bobs;
247
map->normalize_pix(&pos);
248
center = map->calc_coords(pos);
250
// Scan progressively larger circles around the given position for suitable bobs
251
for(radius = 2; radius <= 32; radius <<= 1) {
252
if (map->find_bobs(center, radius, &bobs))
256
// Find the bob closest to us
257
int closest_dist = -1;
260
for(uint i = 0; i < bobs.size(); i++) {
265
map->get_pix(bob->get_position(), &p.x, &p.y);
266
bob->calc_drawpos(m_game, p, &p);
268
dist = map->calc_pix_distance(p, pos);
270
if (!closest || closest_dist > dist) {
275
m_views[m_cur_index].tracking = closest;
281
WatchWindow::toggle_tracking
283
If we're currently tracking, stop tracking.
284
Otherwise, start tracking the nearest bob from our current position.
287
void WatchWindow::toggle_tracking()
290
Map_Object* obj = m_views[m_cur_index].tracking.get(m_game);
293
m_views[m_cur_index].tracking = 0;
295
start_tracking(m_mapview->get_viewpoint() +
296
Point(m_mapview->get_w()/2, m_mapview->get_h()/2));
303
WatchWindow::act_mainview_goto
305
Cause the main mapview to jump to our current position.
308
void WatchWindow::act_mainview_goto()
310
Point p = m_mapview->get_viewpoint() + Point(m_mapview->get_w()/2, m_mapview->get_h()/2);
312
warp_mainview.call(p);
320
Update the mapview if we're tracking something.
323
void WatchWindow::think()
327
Map_Object* obj = m_views[m_cur_index].tracking.get(m_game);
329
if ((m_game->get_gametime() - last_visit) > REFRESH_TIME) {
330
last_visit = m_game->get_gametime();
336
Bob* bob = (Bob*)obj;
339
assert(obj->get_type() == Map_Object::BOB);
341
m_game->get_map()->get_pix(bob->get_position(), &pos.x, &pos.y);
342
bob->calc_drawpos(m_game, pos, &pos);
344
m_mapview->set_viewpoint(pos - Point(m_mapview->get_w()/2, m_mapview->get_h()/2));
351
WatchWindow::stop_tracking_by_drag
353
When the user drags the mapview, we stop tracking.
356
void WatchWindow::stop_tracking_by_drag(int x, int y)
358
//Disable switching while dragging
359
if (m_mapview->is_dragging()) {
360
last_visit = m_game->get_gametime();
361
m_views[m_cur_index].tracking = 0;
373
void show_watch_window(Interactive_Player *parent, Coords coords)
375
Section *s = g_options.pull_section("global");
376
if (s->get_bool("single_watchwin",false)) {
377
if (g_watch_window != NULL)
378
g_watch_window->add_view(coords);
380
g_watch_window = new WatchWindow(parent, 250, 150, 200, 200, coords,true);
383
new WatchWindow(parent, 250, 150, 200, 200, coords,false);