Advanced Strategic Command
weathercast.cpp
Go to the documentation of this file.
1 //
2 // C++ Implementation: weathercast
3 //
4 // Description:
5 //
6 //
7 // Author: Kevin Hirschmann <hirsch@dhcppc0>, (C) 2005
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12 #include "weathercast.h"
13 #include "guidimension.h"
14 #include "graphics/blitter.h"
15 #include "graphics/drawing.h"
16 #include "iconrepository.h"
17 #include "mapdisplay.h"
18 #include "spfst.h"
19 #include "paradialog.h"
20 
21 
22 
23 WeatherPanel::WeatherPanel ( PG_Widget *parent, const PG_Rect &r, const ASCString& panelName_, bool loadTheme): Panel( parent, r, panelName_, loadTheme), counter(0) {
24 
25  weatherSystem = actmap->weatherSystem;
26  turnLabel = new PG_Label(this, PG_Rect(Width() - 108, (Height() - GuiDimension::getButtonHeight()) - GetTextHeight() *2, 10, GetTextHeight() * 2), "Turn: +0");
27  turnLabel->SetSizeByText();
28  // turnLabelWidth = turnLabel->Width();//????
29  forward = new PG_Button(this, PG_Rect(Width() -60 , Height() - GuiDimension::getButtonHeight(), 55, 35), "forward", 90);
30  forward->sigClick.connect( sigc::hide(sigc::mem_fun( *this, &WeatherPanel::buttonForward)));
31  back = new PG_Button(this, PG_Rect(Width() -(60 + 10) - 60, Height() - GuiDimension::getButtonHeight(), 55, 35), "back", 90);
32  back->sigClick.connect( sigc::hide(sigc::mem_fun( *this, &WeatherPanel::buttonBack)));
33 
34 
35  int windRoseYPos = GuiDimension::getTopOffSet();
36  windRoseImage = new PG_Image(this, PG_Point(50, windRoseYPos), IconRepository::getIcon("windrose.png").GetSurface(), false, PG_Draw::BkMode(PG_Draw::TILE), "g");
37 
38  int windBarYPos = windRoseYPos + windRoseImage->Height();
39  bgw = new BarGraphWidget ( this, PG_Rect(55, windBarYPos + 5, 50, 12), BarGraphWidget::Direction(0) );
40  windBar = new PG_Image(this, PG_Point(50, windBarYPos ), IconRepository::getIcon("wind_bar.png").GetSurface(), false, PG_Draw::BkMode(PG_Draw::TILE), "g");
41 
42 
43  WindData wData;
44  wData.speed = weatherSystem->getCurrentWindSpeed();
45  wData.direction = weatherSystem->getCurrentWindDirection();
46  windStack.push_front(wData);
47  windspeedLabel = new PG_Label(this, PG_Rect(427, windBarYPos + windBar->Height() -16 , 10, GetTextHeight() * 2));
48  windspeedLabel->SetFontSize(windspeedLabel->GetFontSize() -5);
49  updateWeatherSpeed(actmap->time.turn());
50 
51  SpecialDisplayWidget* sdw = new SpecialDisplayWidget(this, PG_Rect(0, 0, 150, 300));
52  sdw->display.connect( sigc::mem_fun( *this, &WeatherPanel::painter ));
53 
54  // Weathercast* wc = static_cast<Weathercast*>(GetParent());
55  // wc->Redraw();
56 }
57 
59 
60 bool WeatherPanel::buttonForward(PG_Button* button) {
61  if(counter < weatherSystem->getMaxForecast()) {
62  //update turn information
63  ++counter;
64  showTurn();
65  //update wind data
66  updateWeatherSpeed(actmap->time.turn() + counter);
67  //update display data of active weatherareas (active at least since actmap->time)
68  for(int i =0; i < weatherSystem->getActiveWeatherAreasSize(); i++) {
69  const WeatherArea* wa = weatherSystem->getNthActiveWeatherArea(i);
70  if(wa->getDuration() - counter > 0) {
71  WindAccu wAccu;
72  if(counter == 1) {
73  wAccu.horizontalValue = static_cast<int>(wa->getHorizontalWindAccu());
74  wAccu.verticalValue = wa->getVerticalWindAccu();
75  } else {
76  wAccu = warea2WindAccu[wa];
77  }
78  wAccu = updateWindAccu(wAccu, windSpeed, windStack.front().direction, weatherSystem->getWindspeed2FieldRatio());
79  warea2WindAccu[wa] = wAccu;
80  }
81  }
82  //update display data for queued weatherareas
83  for(int i =0; i < weatherSystem->getQueuedWeatherAreasSize(); i++) {
84  pair<GameTime, WeatherArea*> p = weatherSystem->getNthWeatherArea(i);
85  const WeatherArea* wa = p.second;
86  WindAccu wAccu;
87  if(p.first.turn() == actmap->time.turn() + counter) {
88  wAccu.horizontalValue = 0;
89  wAccu.verticalValue = 0;
90  } else {
91  wAccu.horizontalValue = warea2WindAccu[p.second].horizontalValue;
92  wAccu.verticalValue = warea2WindAccu[p.second].verticalValue;
93  }
94  wAccu = updateWindAccu(wAccu, windSpeed, windStack.front().direction, weatherSystem->getWindspeed2FieldRatio());
95  warea2WindAccu[p.second] = wAccu;
96  }
97  this->Redraw();
98  Weathercast* wc = static_cast<Weathercast*>(GetParent());
99  wc->Redraw();
100  }
101  return true;
102 }
103 
104 bool WeatherPanel::buttonBack( PG_Button* button ) {
105  if(counter>0) {
106  //update turn information
107  --counter;
108  showTurn();
109  //update display data of active weatherareas (active at least since actmap->time)
110  for(int i =0; i < weatherSystem->getActiveWeatherAreasSize(); i++) {
111  const WeatherArea* wa = weatherSystem->getNthActiveWeatherArea(i);
112  if(wa->getDuration() - counter > 0) {
113  WindAccu wAccu = warea2WindAccu[wa];
114  wAccu = updateWindAccu(wAccu, windSpeed, static_cast<Direction>((windStack.front().direction +3) % 6), weatherSystem->getWindspeed2FieldRatio());
115  warea2WindAccu[wa] = wAccu;
116  }
117  }
118  //update display data for queued weatherareas
119  for(int i =0; i < weatherSystem->getQueuedWeatherAreasSize(); i++) {
120  pair<GameTime, WeatherArea*> p = weatherSystem->getNthWeatherArea(i);
121  const WeatherArea* wa = p.second;
122  WindAccu wAccu;
123  if(p.first.turn() <= actmap->time.turn() + counter) {
124  WindAccu wAccu = warea2WindAccu[wa];
125  wAccu = updateWindAccu(wAccu, windSpeed, static_cast<Direction>((windStack.front().direction +3) % 6), weatherSystem->getWindspeed2FieldRatio());
126  warea2WindAccu[wa] = wAccu;
127  }
128  }
129  //update wind data
130  if(weatherSystem->getWindDataOfTurn(actmap->time.turn() + counter + 1).speed >=0) {
131  windStack.pop_front();
132  windSpeed = windStack.front().speed;
133  }
134  Update();
135  Weathercast* wc = static_cast<Weathercast*>(GetParent());
136  wc->Redraw();
137  }
138  return true;
139 }
140 
141 void WeatherPanel::showTurn() {
142  std::string turn = "Turn: +";
143  turn.append(strrr(counter));
144  turnLabel->SetText(turn);
145  turnLabel->SetSizeByText();
146  turnLabel->Redraw();
147 
148 }
149 
150 void WeatherPanel::updateWeatherSpeed(int turn) {
151  int newWindSpeed = weatherSystem->getWindDataOfTurn(turn).speed;
152  WindData wd = weatherSystem->getWindDataOfTurn(turn);
153  windSpeed = newWindSpeed;
154  windStack.push_front(wd);
155 }
156 
157 void WeatherPanel::painter (const PG_Rect &src, const ASCString& name, const PG_Rect &dst) {
158  Surface screen = Surface::Wrap( PG_Application::GetScreen() );
159  //generateWeatherMap(actmap->time.turn() + counter);
160  {
162  static const char* weathernames[] = {"terrain_weather_dry.png",
163  "terrain_weather_lightrain.png",
164  "terrain_weather_heavyrain.png",
165  "terrain_weather_lightsnow.png",
166  "terrain_weather_heavysnow.png",
167  "terrain_weather_ice.png"
168 
169  }
170  ;
171  PG_Point defaultWeatherPoint(ClientToScreen(50,100 + GuiDimension::getTopOffSet()));
172  Surface ws = IconRepository::getIcon(weathernames[actmap->weatherSystem->getDefaultFalloutType()]);
173  ws.strech(60, 25);
174  blitter.blit( ws, screen, SPoint(defaultWeatherPoint.x, defaultWeatherPoint.y ));
175  }
176  //WindArrow update
177  if(windStack.front().speed > 0) {
179  blitter.setAngle( directionangle[windStack.front().direction] );
180  PG_Point p(windRoseImage->x, windRoseImage->y);
181  blitter.blit ( IconRepository::getIcon("wind-arrow.png"), screen, SPoint(p.x, p.y) );
182  }
183 
184  //WindBar and WindLabel update
185  {
186  bgw->setColor(0x00ff00);
187  bgw->setFraction(windSpeed/255.0);
188  bgw->SendToBack();
189  bgw->Show();
190  windBar->Show();
191  std::string wind;
192  wind.append(strrr(windSpeed));
193  windspeedLabel->SetText(wind);
194  windspeedLabel->SetSizeByText();
195  windspeedLabel->Show();
196  }
197 }
198 
199 
201  return counter;
202 }
203 
205  return warea2WindAccu[wa];
206 }
207 
208 WindAccu WeatherPanel::updateWindAccu(const WindAccu& ac, unsigned int windspeed, Direction windDirection, float ratio) {
209  WindAccu wAccu = {ac.horizontalValue, ac.verticalValue};
210  if(windDirection == N) {
211  wAccu.verticalValue += -1 * static_cast<int>(ratio * windspeed) *2;
212  } else if(windDirection == NE) {
213  wAccu.verticalValue += -1 * static_cast<int>(ratio * windspeed) *2;
214  wAccu.horizontalValue += static_cast<int>(ratio * windspeed);
215  } else if(windDirection == SE) {
216  wAccu.verticalValue += static_cast<int>(ratio * windspeed) *2;
217  wAccu.horizontalValue += static_cast<int>(ratio * windspeed);
218  } else if(windDirection == S) {
219  wAccu.verticalValue += static_cast<int>(ratio * windspeed) *2;
220  } else if(windDirection == SW) {
221  wAccu.verticalValue += static_cast<int>(ratio * windspeed) *2;
222  wAccu.horizontalValue += -1 * static_cast<int>(ratio * windspeed);
223  } else if(windDirection == NW) {
224  wAccu.verticalValue += -1 * static_cast<int>(ratio * windspeed) *2;
225  wAccu.horizontalValue += -1 * static_cast<int>(ratio * windspeed);
226  }
227  return wAccu;
228 }
229 
230 const int Weathercast::xSize = 500;
231 const int Weathercast::ySize = 400;
232 
233 const int Weathercast::MAPXSIZE = 200;
234 const int Weathercast::MAPYSIZE = 200;
235 Weathercast::Weathercast(const WeatherSystem& ws): ASC_PG_Dialog(NULL, PG_Rect( 100, 100, xSize, ySize ), "Weathercast", MODAL ), weatherSystem(ws), currentZoomX(1.0), currentZoomY(1.0), mapYPos(30), mapXPos(30) {
236 
237  mapDisplayWidget = (MapDisplayPG*)(getPGApplication().GetWidgetById(ASC_PG_App::mapDisplayID));
240  s.strech(MAPXSIZE, MAPYSIZE);
241 
242  weatherPanel = new WeatherPanel ( this, PG_Rect( 350, 30, 150, 300),"weatherPanel", false );
243  sdw = new SpecialDisplayWidget(this, PG_Rect(mapXPos, mapYPos, 350, 250));
244  sdw->display.connect( sigc::mem_fun( *this, &Weathercast::painter ));
245  sdw->sigMouseMotion.connect( sigc::mem_fun( *this, &Weathercast::mouseMotion ));
246  sdw->sigMouseButtonDown.connect( sigc::mem_fun( *this, &Weathercast::mouseButtonDown ));
247  viewChanged.connect ( sigc::mem_fun( *this, &Weathercast::redraw ));
248 
249 
250  okButton = new PG_Button(this, PG_Rect((xSize - GuiDimension::getButtonWidth()) / 2, ySize - (GuiDimension::getButtonHeight() + GuiDimension::getTopOffSet()), GuiDimension::getButtonWidth(), GuiDimension::getButtonHeight()), "OK", 90);
251  okButton->sigClick.connect( sigc::hide(sigc::mem_fun( *this, &Weathercast::closeWindow )));
252 
253  sigClose.connect( sigc::mem_fun( *this, &Weathercast::closeWindow ));
254 }
255 
257 
258 bool Weathercast::mouseMotion ( const SDL_MouseMotionEvent *motion) {
259  if ( sdw->IsMouseInside() )
260  if ( motion->type == SDL_MOUSEMOTION && (motion->state & 1 ) ) {
261  PG_Point p = sdw->ScreenToClient( motion->x, motion->y );
262  return mouseClick( SPoint( p.x, p.y ));
263  }
264 
265  return false;
266 }
267 
269  MapCoordinate mc = OverviewMapImage::surface2map( SPoint(float(pos.x) / currentZoomX, float(pos.y) / currentZoomX ));
270  if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
271  return false;
272 
273  mapDisplayWidget->centerOnField( mc );
274  return true;
275 }
276 
277 bool Weathercast::mouseButtonDown ( const SDL_MouseButtonEvent *button) {
278  if ( sdw->IsMouseInside() )
279  if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == 1 ) {
280  PG_Point p = sdw->ScreenToClient( button->x, button->y );
281  return mouseClick( SPoint( p.x, p.y ));
282  }
283 
284  return false;
285 }
286 
287 
288 void Weathercast::painter (const PG_Rect &src, const ASCString& name, const PG_Rect &dst) {
289  Surface screen = Surface::Wrap( PG_Application::GetScreen() );
290  if ( actmap ) {
293 
295  blitter.setSize( s.w(), s.h(), dst.w, dst.h);
296 
297 
298  currentZoomX = blitter.getZoomX();
299  currentZoomY = blitter.getZoomY();
300  PG_Point dstPoint(ClientToScreen(mapXPos, mapYPos));
301 
302  blitter.blit( s, screen, SPoint(dstPoint.x, dstPoint.y) );
303  generateWeatherMap(actmap->time.turn() + weatherPanel->getCounter());
304 // cout << "counter: " << weatherPanel->getCounter() <<endl;
305 
306  SPoint ul = OverviewMapImage::map2surface( mapDisplayWidget->upperLeftCorner());
307  SPoint lr = OverviewMapImage::map2surface( mapDisplayWidget->lowerRightCorner());
308 
309 
310  ul.x *= currentZoomX;
311  ul.y *= currentZoomX;
312  lr.x *= currentZoomX;
313  lr.y *= currentZoomX;
314 
315  if ( ul.x < 0 )
316  ul.x = 0;
317  if ( ul.y < 0 )
318  ul.y = 0;
319  if ( lr.x >= dst.w )
320  lr.x = dst.w -1;
321  if ( lr.y >= dst.h )
322  lr.y = dst.h -1;
323 
324  rectangle<4>(screen, SPoint(dstPoint.x + ul.x, dstPoint.y + ul.y), lr.x - ul.x, lr.y- ul.y, ColorMerger_Set<4>(0xff), ColorMerger_Set<4>(0xff) );
325  }
326 
327 }
328 
329 void Weathercast::generateWeatherMap(int turn) {
330  for(int i =0; i < actmap->weatherSystem->getActiveWeatherAreasSize(); i++) {
331  const WeatherArea* wa = actmap->weatherSystem->getNthActiveWeatherArea(i);
332  if((wa->getDuration() > (turn - (actmap->time.turn() + 1))) && (wa->getCenterField()->isOnMap(actmap))) {
333  WindAccu wAccu = weatherPanel->getWindAccuData(wa);
334  int vMove = static_cast<int>(wAccu.verticalValue);
335  int hMove = static_cast<int>(wAccu.horizontalValue);
336  paintWeatherArea(wa, vMove, hMove);
337  }
338  }
339  for(int i =0; i < weatherSystem.getQueuedWeatherAreasSize(); i++) {
340  pair<GameTime, WeatherArea*> p = weatherSystem.getNthWeatherArea(i);
341  if(p.first.turn() <= turn) {
342  WindAccu wAccu = weatherPanel->getWindAccuData(p.second);
343  int vMove = static_cast<int>(wAccu.verticalValue);
344  int hMove = static_cast<int>(wAccu.horizontalValue);
345  paintWeatherArea(p.second, vMove, hMove);
346  }
347  }
348 }
349 
350 void Weathercast::paintWeatherArea(const WeatherArea* wa, int vMove, int hMove) {
351 // cout << "painting area" << endl;
353  static const char* weathernames[] = {"terrain_weather_dry.png",
354  "terrain_weather_lightrain.png",
355  "terrain_weather_heavyrain.png",
356  "terrain_weather_lightsnow.png",
357  "terrain_weather_heavysnow.png",
358  "terrain_weather_ice.png"
359  };
360 
361  Surface screen = Surface::Wrap( PG_Application::GetScreen() );
362  Surface wSurface = IconRepository::getIcon(weathernames[wa->getFalloutType()]);
363  if((wa->getCenterPos().x + hMove >0) && (wa->getCenterPos().y + vMove >0)) {
364 // cout << "currentZoom: " << currentZoomX << endl;
365  SPoint pixCenter = OverviewMapImage::map2surface(MapCoordinate(((wa->getCenterPos().x + hMove)* currentZoomX), (((wa->getCenterPos().y + vMove) * currentZoomY))));
366  PG_Point transformedPoint = PG_Point(ClientToScreen(pixCenter.x, pixCenter.y));
367  //transformedPoint.x += static_cast<float>(transformedPoint.x);
368  transformedPoint.x += mapXPos;
369  transformedPoint.y += mapYPos;
370  /* if(pixCenter.x + wSurface.w() > s.w()) {
371  blitter.setRectangle( SPoint(0,0), s.w() - (pixCenter.x), wSurface.h());
372  } else {
373  blitter.setRectangle( SPoint(0,0), wSurface.w(), wSurface.h());
374  }*/
375  blitter.blit(wSurface, screen, SPoint(transformedPoint.x, transformedPoint.y));//SPoint(transformedPoint.x, transformedPoint.y));
376 // cout << "pixCenter.x " << pixCenter.x << endl;
377 // cout << "pixCenter.y " << pixCenter.y << endl;
378  //cout << "trans.x " << transformedPoint.x << endl;
379  //cout << "trans.y " << transformedPoint.y << endl;
380 
381  }
382 
383  /*for(int i = (wa->getCenterPos().x - wa->getWidth()/2); i < wa->getCenterPos().x + wa->getWidth(); i++){
384  for(int j = (wa->getCenterPos().y - wa->getHeight()/2); j < wa->getCenterPos().y + wa->getHeight()/2; j++){
385  SPoint pixCenter = OverviewMapImage::map2surface(MapCoordinate(i,j));
386  OverviewMapImage::fill(s, pixCenter, LRAINOR);
387  }
388  }*/
389 }
390 
391 bool Weathercast::closeWindow() {
392  quitModalLoop(1);
393  return true;
394 
395 }
396 
397 
398 extern void weathercast() {
399  Weathercast wc(*(actmap->weatherSystem));
400  wc.Show();
401  wc.RunModal();
402 }
403 
404 
void painter(const PG_Rect &src, const ASCString &name, const PG_Rect &dst)
int xsize
the size of the map
Definition: gamemap.h:201
float getWindspeed2FieldRatio() const
Definition: weatherarea.h:377
void clear(bool allImages=false)
Definition: gamemap.cpp:201
DisplayHook display
Definition: paradialog.h:182
map accessing and usage routines used by ASC and the mapeditor
int getDuration() const
virtual ~Weathercast()
bool valid() const
Definition: typen.h:221
void blit(const Surface &src, Surface &dst, SPoint dstPos)
Definition: blitter.h:349
Definition: weatherarea.h:86
MapCoordinate lowerRightCorner()
Definition: mapdisplay.cpp:952
const WeatherArea * getNthActiveWeatherArea(int n) const
WindAccu getWindAccuData(const WeatherArea *wa)
int turn() const
Definition: typen.h:181
virtual ~WeatherPanel()
Definition: weathercast.cpp:58
static SPoint map2surface(const MapCoordinate &pos)
Definition: weatherarea.h:87
const Surface & getOverviewMap(bool complete=true)
returns the overview surface for the map.
Definition: gamemap.cpp:180
bool mouseButtonDown(const SDL_MouseButtonEvent *button)
float getHorizontalWindAccu() const
bool mouseMotion(const SDL_MouseMotionEvent *motion)
void strech(int width, int height)
Definition: surface.cpp:457
MapCoordinate getCenterPos() const
Definition: weatherarea.h:183
static int getButtonWidth()
const int getActiveWeatherAreasSize() const
WeatherPanel(PG_Widget *parent, const PG_Rect &r, const ASCString &panelName_, bool loadTheme=true)
Definition: weathercast.cpp:23
Direction direction
Definition: weatherarea.h:105
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
int verticalValue
Definition: weathercast.h:31
WindData getWindDataOfTurn(int turn) const
Definition: weatherarea.h:90
void setColor(int c)
int horizontalValue
Definition: weathercast.h:30
float getVerticalWindAccu() const
ASC_PG_App & getPGApplication()
Definition: paradialog.cpp:294
char * strrr(int a)
converts a to a string.
Definition: misc.cpp:66
bool quitModalLoop(int value)
Definition: paradialog.cpp:545
int getCurrentWindSpeed() const
Definition: weatherarea.h:329
const int directionangle[sidenum]
Definition: typen.cpp:81
Coordinate on the twodimensional map.
Definition: typen.h:202
Adapter class for using Paragui Dialogs in ASC. This class transfers the event control from ASC to Pa...
Definition: paradialog.h:127
Dialog classes based on the Paragui library.
unsigned int speed
Definition: weatherarea.h:104
Definition: weatherarea.h:88
const int getQueuedWeatherAreasSize() const
static int getButtonHeight()
MapCoordinate upperLeftCorner()
Definition: mapdisplay.cpp:947
Direction getCurrentWindDirection() const
Definition: weatherarea.h:333
SDLmm::SPoint SPoint
Definition: surface.h:27
int ysize
Definition: gamemap.h:201
sigc::signal< void > viewChanged
the view of the player onto the map changed, for example because he scrolled the map ...
Definition: spfst.cpp:51
void weathercast()
OverviewMapHolder overviewMapHolder
Definition: gamemap.h:532
FalloutType getFalloutType() const
Weathercast(const WeatherSystem &ws)
void setFraction(float f)
static Surface & getIcon(const ASCString &name)
static MapCoordinate surface2map(const SPoint &pos)
const WeatherField * getCenterField() const
Definition: weatherarea.h:187
bool isOnMap(const GameMap *map) const
Direction
Definition: weatherarea.h:84
Definition: weatherarea.h:85
GameMap * actmap
Definition: spfst.cpp:64
static const int mapDisplayID
Definition: paradialog.h:87
static Surface Wrap(SDL_Surface *surface)
Definition: surface.h:76
void paintWeatherArea(const WeatherArea *wa, int vMove, int hMove)
static int getTopOffSet()
pair< GameTime, WeatherArea * > getNthWeatherArea(int n) const
SDL_Surface * screen
Definition: graphics.cpp:31
Definition: weatherarea.h:89
bool centerOnField(const MapCoordinate &mc)
Definition: mapdisplay.cpp:958
bool mouseClick(SPoint pos)
GameTime time
the time in the game, mesured in a turns and moves
Definition: gamemap.h:235