Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

weathercast.cpp

Go to the documentation of this file.
00001 //
00002 // C++ Implementation: weathercast
00003 //
00004 // Description:
00005 //
00006 //
00007 // Author: Kevin Hirschmann <hirsch@dhcppc0>, (C) 2005
00008 //
00009 // Copyright: See COPYING file that comes with this distribution
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     //    turnLabelWidth = turnLabel->Width();//????
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     // Weathercast* wc = static_cast<Weathercast*>(GetParent());
00055     // wc->Redraw();
00056 }
00057 
00058 WeatherPanel::~WeatherPanel() {}
00059 
00060 bool WeatherPanel::buttonForward(PG_Button* button) {
00061     if(counter < weatherSystem->getMaxForecast()) {
00062         //update turn information
00063         ++counter;
00064         showTurn();
00065         //update wind data
00066         updateWeatherSpeed(actmap->time.turn() + counter);
00067         //update display data of active weatherareas (active at least since actmap->time)
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           //update display data for queued weatherareas
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         //update turn information
00107         --counter;
00108         showTurn();
00109         //update display data of active weatherareas (active at least since actmap->time)
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              //update display data for queued weatherareas
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         //update wind data
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     //generateWeatherMap(actmap->time.turn() + counter);
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     //WindArrow update
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     //WindBar and WindLabel update
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 //      cout << "counter: " << weatherPanel->getCounter() <<endl;
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 //    cout << "painting area" << endl;
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 //        cout << "currentZoom: " << currentZoomX << endl;
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         //transformedPoint.x += static_cast<float>(transformedPoint.x);
00368         transformedPoint.x += mapXPos;
00369         transformedPoint.y += mapYPos;
00370        /* if(pixCenter.x + wSurface.w() > s.w()) {        
00371             blitter.setRectangle( SPoint(0,0), s.w() - (pixCenter.x), wSurface.h());
00372         } else {        
00373             blitter.setRectangle( SPoint(0,0), wSurface.w(), wSurface.h());
00374         }*/                    
00375         blitter.blit(wSurface, screen, SPoint(transformedPoint.x, transformedPoint.y));//SPoint(transformedPoint.x, transformedPoint.y));
00376 //      cout << "pixCenter.x " << pixCenter.x << endl;
00377 //      cout << "pixCenter.y " << pixCenter.y << endl;
00378         //cout << "trans.x " << transformedPoint.x << endl;
00379         //cout << "trans.y " << transformedPoint.y << endl;
00380         
00381     }
00382 
00383     /*for(int i = (wa->getCenterPos().x - wa->getWidth()/2); i < wa->getCenterPos().x + wa->getWidth(); i++){
00384       for(int j = (wa->getCenterPos().y - wa->getHeight()/2); j < wa->getCenterPos().y + wa->getHeight()/2; j++){   
00385         SPoint pixCenter = OverviewMapImage::map2surface(MapCoordinate(i,j));
00386         OverviewMapImage::fill(s, pixCenter, LRAINOR);
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 

Generated on Tue Jun 24 01:27:55 2008 for Advanced Strategic Command by  doxygen 1.4.2