00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "weathercast.h"
00013 #include "guidimension.h"
00014 #include "graphics/blitter.h"
00015 #include "graphics/drawing.h"
00016 #include "iconrepository.h"
00017 #include "mapdisplay.h"
00018 #include "spfst.h"
00019 #include "paradialog.h"
00020
00021
00022
00023 WeatherPanel::WeatherPanel ( PG_Widget *parent, const PG_Rect &r, const ASCString& panelName_, bool loadTheme): Panel( parent, r, panelName_, loadTheme), counter(0) {
00024
00025 weatherSystem = actmap->weatherSystem;
00026 turnLabel = new PG_Label(this, PG_Rect(Width() - 108, (Height() - GuiDimension::getButtonHeight()) - GetTextHeight() *2, 10, GetTextHeight() * 2), "Turn: +0");
00027 turnLabel->SetSizeByText();
00028
00029 forward = new PG_Button(this, PG_Rect(Width() -60 , Height() - GuiDimension::getButtonHeight(), 55, 35), "forward", 90);
00030 forward->sigClick.connect(SigC::slot( *this, &WeatherPanel::buttonForward));
00031 back = new PG_Button(this, PG_Rect(Width() -(60 + 10) - 60, Height() - GuiDimension::getButtonHeight(), 55, 35), "back", 90);
00032 back->sigClick.connect(SigC::slot( *this, &WeatherPanel::buttonBack));
00033
00034
00035 int windRoseYPos = GuiDimension::getTopOffSet();
00036 windRoseImage = new PG_Image(this, PG_Point(50, windRoseYPos), IconRepository::getIcon("windrose.png").GetSurface(), false, PG_Draw::BkMode(PG_Draw::TILE), "g");
00037
00038 int windBarYPos = windRoseYPos + windRoseImage->Height();
00039 bgw = new BarGraphWidget ( this, PG_Rect(55, windBarYPos + 5, 50, 12), BarGraphWidget::Direction(0) );
00040 windBar = new PG_Image(this, PG_Point(50, windBarYPos ), IconRepository::getIcon("wind_bar.png").GetSurface(), false, PG_Draw::BkMode(PG_Draw::TILE), "g");
00041
00042
00043 WindData wData;
00044 wData.speed = weatherSystem->getCurrentWindSpeed();
00045 wData.direction = weatherSystem->getCurrentWindDirection();
00046 windStack.push_front(wData);
00047 windspeedLabel = new PG_Label(this, PG_Rect(427, windBarYPos + windBar->Height() -16 , 10, GetTextHeight() * 2));
00048 windspeedLabel->SetFontSize(windspeedLabel->GetFontSize() -5);
00049 updateWeatherSpeed(actmap->time.turn());
00050
00051 SpecialDisplayWidget* sdw = new SpecialDisplayWidget(this, PG_Rect(0, 0, 150, 300));
00052 sdw->display.connect( SigC::slot( *this, &WeatherPanel::painter ));
00053
00054
00055
00056 }
00057
00058 WeatherPanel::~WeatherPanel() {}
00059
00060 bool WeatherPanel::buttonForward(PG_Button* button) {
00061 if(counter < weatherSystem->getMaxForecast()) {
00062
00063 ++counter;
00064 showTurn();
00065
00066 updateWeatherSpeed(actmap->time.turn() + counter);
00067
00068 for(int i =0; i < weatherSystem->getActiveWeatherAreasSize(); i++) {
00069 const WeatherArea* wa = weatherSystem->getNthActiveWeatherArea(i);
00070 if(wa->getDuration() - counter > 0) {
00071 WindAccu wAccu;
00072 if(counter == 1) {
00073 wAccu.horizontalValue = static_cast<int>(wa->getHorizontalWindAccu());
00074 wAccu.verticalValue = wa->getVerticalWindAccu();
00075 } else {
00076 wAccu = warea2WindAccu[wa];
00077 }
00078 wAccu = updateWindAccu(wAccu, windSpeed, windStack.front().direction, weatherSystem->getWindspeed2FieldRatio());
00079 warea2WindAccu[wa] = wAccu;
00080 }
00081 }
00082
00083 for(int i =0; i < weatherSystem->getQueuedWeatherAreasSize(); i++) {
00084 pair<GameTime, WeatherArea*> p = weatherSystem->getNthWeatherArea(i);
00085 const WeatherArea* wa = p.second;
00086 WindAccu wAccu;
00087 if(p.first.turn() == actmap->time.turn() + counter) {
00088 wAccu.horizontalValue = 0;
00089 wAccu.verticalValue = 0;
00090 } else {
00091 wAccu.horizontalValue = warea2WindAccu[p.second].horizontalValue;
00092 wAccu.verticalValue = warea2WindAccu[p.second].verticalValue;
00093 }
00094 wAccu = updateWindAccu(wAccu, windSpeed, windStack.front().direction, weatherSystem->getWindspeed2FieldRatio());
00095 warea2WindAccu[p.second] = wAccu;
00096 }
00097 this->Redraw();
00098 Weathercast* wc = static_cast<Weathercast*>(GetParent());
00099 wc->Redraw();
00100 }
00101 return true;
00102 }
00103
00104 bool WeatherPanel::buttonBack( PG_Button* button ) {
00105 if(counter>0) {
00106
00107 --counter;
00108 showTurn();
00109
00110 for(int i =0; i < weatherSystem->getActiveWeatherAreasSize(); i++) {
00111 const WeatherArea* wa = weatherSystem->getNthActiveWeatherArea(i);
00112 if(wa->getDuration() - counter > 0) {
00113 WindAccu wAccu = warea2WindAccu[wa];
00114 wAccu = updateWindAccu(wAccu, windSpeed, static_cast<Direction>((windStack.front().direction +3) % 6), weatherSystem->getWindspeed2FieldRatio());
00115 warea2WindAccu[wa] = wAccu;
00116 }
00117 }
00118
00119 for(int i =0; i < weatherSystem->getQueuedWeatherAreasSize(); i++) {
00120 pair<GameTime, WeatherArea*> p = weatherSystem->getNthWeatherArea(i);
00121 const WeatherArea* wa = p.second;
00122 WindAccu wAccu;
00123 if(p.first.turn() <= actmap->time.turn() + counter) {
00124 WindAccu wAccu = warea2WindAccu[wa];
00125 wAccu = updateWindAccu(wAccu, windSpeed, static_cast<Direction>((windStack.front().direction +3) % 6), weatherSystem->getWindspeed2FieldRatio());
00126 warea2WindAccu[wa] = wAccu;
00127 }
00128 }
00129
00130 if(weatherSystem->getWindDataOfTurn(actmap->time.turn() + counter + 1).speed >=0) {
00131 windStack.pop_front();
00132 windSpeed = windStack.front().speed;
00133 }
00134 Update();
00135 Weathercast* wc = static_cast<Weathercast*>(GetParent());
00136 wc->Redraw();
00137 }
00138 return true;
00139 }
00140
00141 void WeatherPanel::showTurn() {
00142 std::string turn = "Turn: +";
00143 turn.append(strrr(counter));
00144 turnLabel->SetText(turn);
00145 turnLabel->SetSizeByText();
00146 turnLabel->Redraw();
00147
00148 }
00149
00150 void WeatherPanel::updateWeatherSpeed(int turn) {
00151 int newWindSpeed = weatherSystem->getWindDataOfTurn(turn).speed;
00152 WindData wd = weatherSystem->getWindDataOfTurn(turn);
00153 windSpeed = newWindSpeed;
00154 windStack.push_front(wd);
00155 }
00156
00157 void WeatherPanel::painter (const PG_Rect &src, const ASCString& name, const PG_Rect &dst) {
00158 Surface screen = Surface::Wrap( PG_Application::GetScreen() );
00159
00160 {
00161 MegaBlitter<4,colorDepth,ColorTransform_None, ColorMerger_AlphaOverwrite, SourcePixelSelector_DirectZoom> blitter;
00162 static const char* weathernames[] = {"terrain_weather_dry.png",
00163 "terrain_weather_lightrain.png",
00164 "terrain_weather_heavyrain.png",
00165 "terrain_weather_lightsnow.png",
00166 "terrain_weather_heavysnow.png",
00167 "terrain_weather_ice.png"
00168
00169 }
00170 ;
00171 PG_Point defaultWeatherPoint(ClientToScreen(50,100 + GuiDimension::getTopOffSet()));
00172 Surface ws = IconRepository::getIcon(weathernames[actmap->weatherSystem->getDefaultFalloutType()]);
00173 ws.strech(60, 25);
00174 blitter.blit( ws, screen, SPoint(defaultWeatherPoint.x, defaultWeatherPoint.y ));
00175 }
00176
00177 if(windStack.front().speed > 0) {
00178 MegaBlitter<4,colorDepth,ColorTransform_None, ColorMerger_AlphaOverwrite, SourcePixelSelector_DirectRotation> blitter;
00179 blitter.setAngle( directionangle[windStack.front().direction] );
00180 PG_Point p(windRoseImage->x, windRoseImage->y);
00181 blitter.blit ( IconRepository::getIcon("wind-arrow.png"), screen, SPoint(p.x, p.y) );
00182 }
00183
00184
00185 {
00186 bgw->setColor(0x00ff00);
00187 bgw->setFraction(windSpeed/255.0);
00188 bgw->SendToBack();
00189 bgw->Show();
00190 windBar->Show();
00191 std::string wind;
00192 wind.append(strrr(windSpeed));
00193 windspeedLabel->SetText(wind);
00194 windspeedLabel->SetSizeByText();
00195 windspeedLabel->Show();
00196 }
00197 }
00198
00199
00200 int WeatherPanel::getCounter() {
00201 return counter;
00202 }
00203
00204 WindAccu WeatherPanel::getWindAccuData(const WeatherArea* wa) {
00205 return warea2WindAccu[wa];
00206 }
00207
00208 WindAccu WeatherPanel::updateWindAccu(const WindAccu& ac, unsigned int windspeed, Direction windDirection, float ratio) {
00209 WindAccu wAccu = {ac.horizontalValue, ac.verticalValue};
00210 if(windDirection == N) {
00211 wAccu.verticalValue += -1 * static_cast<int>(ratio * windspeed) *2;
00212 } else if(windDirection == NE) {
00213 wAccu.verticalValue += -1 * static_cast<int>(ratio * windspeed) *2;
00214 wAccu.horizontalValue += static_cast<int>(ratio * windspeed);
00215 } else if(windDirection == SE) {
00216 wAccu.verticalValue += static_cast<int>(ratio * windspeed) *2;
00217 wAccu.horizontalValue += static_cast<int>(ratio * windspeed);
00218 } else if(windDirection == S) {
00219 wAccu.verticalValue += static_cast<int>(ratio * windspeed) *2;
00220 } else if(windDirection == SW) {
00221 wAccu.verticalValue += static_cast<int>(ratio * windspeed) *2;
00222 wAccu.horizontalValue += -1 * static_cast<int>(ratio * windspeed);
00223 } else if(windDirection == NW) {
00224 wAccu.verticalValue += -1 * static_cast<int>(ratio * windspeed) *2;
00225 wAccu.horizontalValue += -1 * static_cast<int>(ratio * windspeed);
00226 }
00227 return wAccu;
00228 }
00229
00230 const int Weathercast::xSize = 500;
00231 const int Weathercast::ySize = 400;
00232
00233 const int Weathercast::MAPXSIZE = 200;
00234 const int Weathercast::MAPYSIZE = 200;
00235 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) {
00236
00237 mapDisplayWidget = (MapDisplayPG*)(getPGApplication().GetWidgetById(ASC_PG_App::mapDisplayID));
00238 actmap->overviewMapHolder.clear();
00239 s = actmap->overviewMapHolder.getOverviewMap();
00240 s.strech(MAPXSIZE, MAPYSIZE);
00241
00242 weatherPanel = new WeatherPanel ( this, PG_Rect( 350, 30, 150, 300),"weatherPanel", false );
00243 sdw = new SpecialDisplayWidget(this, PG_Rect(mapXPos, mapYPos, 350, 250));
00244 sdw->display.connect( SigC::slot( *this, &Weathercast::painter ));
00245 sdw->sigMouseMotion.connect( SigC::slot( *this, &Weathercast::mouseMotion ));
00246 sdw->sigMouseButtonDown.connect( SigC::slot( *this, &Weathercast::mouseButtonDown ));
00247 viewChanged.connect ( SigC::slot( *this, &Weathercast::redraw ));
00248
00249
00250 okButton = new PG_Button(this, PG_Rect((xSize - GuiDimension::getButtonWidth()) / 2, ySize - (GuiDimension::getButtonHeight() + GuiDimension::getTopOffSet()), GuiDimension::getButtonWidth(), GuiDimension::getButtonHeight()), "OK", 90);
00251 okButton->sigClick.connect(SigC::slot( *this, &Weathercast::closeWindow ));
00252
00253 sigClose.connect( SigC::slot( *this, &Weathercast::closeWindow ));
00254 }
00255
00256 Weathercast::~Weathercast() {}
00257
00258 bool Weathercast::mouseMotion ( const SDL_MouseMotionEvent *motion) {
00259 if ( sdw->IsMouseInside() )
00260 if ( motion->type == SDL_MOUSEMOTION && (motion->state & 1 ) ) {
00261 PG_Point p = sdw->ScreenToClient( motion->x, motion->y );
00262 return mouseClick( SPoint( p.x, p.y ));
00263 }
00264
00265 return false;
00266 }
00267
00268 bool Weathercast::mouseClick ( SPoint pos ) {
00269 MapCoordinate mc = OverviewMapImage::surface2map( SPoint(float(pos.x) / currentZoomX, float(pos.y) / currentZoomX ));
00270 if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
00271 return false;
00272
00273 mapDisplayWidget->centerOnField( mc );
00274 return true;
00275 }
00276
00277 bool Weathercast::mouseButtonDown ( const SDL_MouseButtonEvent *button) {
00278 if ( sdw->IsMouseInside() )
00279 if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == 1 ) {
00280 PG_Point p = sdw->ScreenToClient( button->x, button->y );
00281 return mouseClick( SPoint( p.x, p.y ));
00282 }
00283
00284 return false;
00285 }
00286
00287
00288 void Weathercast::painter (const PG_Rect &src, const ASCString& name, const PG_Rect &dst) {
00289 Surface screen = Surface::Wrap( PG_Application::GetScreen() );
00290 if ( actmap ) {
00291 actmap->overviewMapHolder.clear();
00292 s = actmap->overviewMapHolder.getOverviewMap( true );
00293
00294 MegaBlitter< gamemapPixelSize, gamemapPixelSize,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectZoom> blitter;
00295 blitter.setSize( s.w(), s.h(), dst.w, dst.h);
00296
00297
00298 currentZoomX = blitter.getZoomX();
00299 currentZoomY = blitter.getZoomY();
00300 PG_Point dstPoint(ClientToScreen(mapXPos, mapYPos));
00301
00302 blitter.blit( s, screen, SPoint(dstPoint.x, dstPoint.y) );
00303 generateWeatherMap(actmap->time.turn() + weatherPanel->getCounter());
00304
00305
00306 SPoint ul = OverviewMapImage::map2surface( mapDisplayWidget->upperLeftCorner());
00307 SPoint lr = OverviewMapImage::map2surface( mapDisplayWidget->lowerRightCorner());
00308
00309
00310 ul.x *= currentZoomX;
00311 ul.y *= currentZoomX;
00312 lr.x *= currentZoomX;
00313 lr.y *= currentZoomX;
00314
00315 if ( ul.x < 0 )
00316 ul.x = 0;
00317 if ( ul.y < 0 )
00318 ul.y = 0;
00319 if ( lr.x >= dst.w )
00320 lr.x = dst.w -1;
00321 if ( lr.y >= dst.h )
00322 lr.y = dst.h -1;
00323
00324 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) );
00325 }
00326
00327 }
00328
00329 void Weathercast::generateWeatherMap(int turn) {
00330 for(int i =0; i < actmap->weatherSystem->getActiveWeatherAreasSize(); i++) {
00331 const WeatherArea* wa = actmap->weatherSystem->getNthActiveWeatherArea(i);
00332 if((wa->getDuration() > (turn - (actmap->time.turn() + 1))) && (wa->getCenterField()->isOnMap(actmap))) {
00333 WindAccu wAccu = weatherPanel->getWindAccuData(wa);
00334 int vMove = static_cast<int>(wAccu.verticalValue);
00335 int hMove = static_cast<int>(wAccu.horizontalValue);
00336 paintWeatherArea(wa, vMove, hMove);
00337 }
00338 }
00339 for(int i =0; i < weatherSystem.getQueuedWeatherAreasSize(); i++) {
00340 pair<GameTime, WeatherArea*> p = weatherSystem.getNthWeatherArea(i);
00341 if(p.first.turn() <= turn) {
00342 WindAccu wAccu = weatherPanel->getWindAccuData(p.second);
00343 int vMove = static_cast<int>(wAccu.verticalValue);
00344 int hMove = static_cast<int>(wAccu.horizontalValue);
00345 paintWeatherArea(p.second, vMove, hMove);
00346 }
00347 }
00348 }
00349
00350 void Weathercast::paintWeatherArea(const WeatherArea* wa, int vMove, int hMove) {
00351
00352 MegaBlitter<gamemapPixelSize, gamemapPixelSize,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectZoom> blitter;
00353 static const char* weathernames[] = {"terrain_weather_dry.png",
00354 "terrain_weather_lightrain.png",
00355 "terrain_weather_heavyrain.png",
00356 "terrain_weather_lightsnow.png",
00357 "terrain_weather_heavysnow.png",
00358 "terrain_weather_ice.png"
00359 };
00360
00361 Surface screen = Surface::Wrap( PG_Application::GetScreen() );
00362 Surface wSurface = IconRepository::getIcon(weathernames[wa->getFalloutType()]);
00363 if((wa->getCenterPos().x + hMove >0) && (wa->getCenterPos().y + vMove >0)) {
00364
00365 SPoint pixCenter = OverviewMapImage::map2surface(MapCoordinate(((wa->getCenterPos().x + hMove)* currentZoomX), (((wa->getCenterPos().y + vMove) * currentZoomY))));
00366 PG_Point transformedPoint = PG_Point(ClientToScreen(pixCenter.x, pixCenter.y));
00367
00368 transformedPoint.x += mapXPos;
00369 transformedPoint.y += mapYPos;
00370
00371
00372
00373
00374
00375 blitter.blit(wSurface, screen, SPoint(transformedPoint.x, transformedPoint.y));
00376
00377
00378
00379
00380
00381 }
00382
00383
00384
00385
00386
00387
00388
00389 }
00390
00391 bool Weathercast::closeWindow() {
00392 quitModalLoop(1);
00393 return true;
00394
00395 }
00396
00397
00398 extern void weathercast() {
00399 Weathercast wc(*(actmap->weatherSystem));
00400 wc.Show();
00401 wc.RunModal();
00402 }
00403
00404