alliancesetup.cpp

Go to the documentation of this file.
00001 /*
00002      This file is part of Advanced Strategic Command; http://www.asc-hq.de
00003      Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00004  
00005      This program is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published by
00007      the Free Software Foundation; either version 2 of the License, or
00008      (at your option) any later version.
00009  
00010      This program is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013      GNU General Public License for more details.
00014  
00015      You should have received a copy of the GNU General Public License
00016      along with this program; see the file COPYING. If not, write to the 
00017      Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00018      Boston, MA  02111-1307  USA
00019 */
00020 
00021 
00022 #include <sstream>
00023 #include <pgimage.h>
00024 #include <pglistboxbaseitem.h>
00025 #include <pgtooltiphelp.h>
00026 
00027 #include "../iconrepository.h"
00028 #include "../gamemap.h"
00029 #include "../paradialog.h"
00030 #include "playersetup.h"
00031 #include "alliancesetup.h"
00032 #include "../actions/diplomacycommand.h"
00033 #include "../dialog.h"
00034 
00035 const int diplomaticStateIconSize = 20;
00036 const int diplomaticStateIconSpace = 2;
00037 
00038 
00039 template<typename SelectionType>
00040 int getItemNum() { return 0; };
00041 
00042 template<typename SelectionType>
00043 const char* getStateName(int s) { return NULL; };
00044 
00045 
00046 template<>
00047 int getItemNum<DiplomaticStates>() { return diplomaticStateNum; };
00048 
00049 template<>
00050 const char* getStateName<DiplomaticStates>(int s) { return diplomaticStateNames[s]; };
00051 
00052 
00053 template<>
00054 int getItemNum<AllianceSetupWidget::DiplomaticTransitions>() { return diplomaticStateNum+1; };
00055 
00056 template<>
00057 const char* getStateName<AllianceSetupWidget::DiplomaticTransitions>(int s) 
00058 { 
00059    if ( s == 0 ) 
00060       return "Sneak Attack"; 
00061    else 
00062       return diplomaticStateNames[s-1]; 
00063 };
00064 
00065 
00066 ASCString getDiplomaticStateImage( DiplomaticStates s )
00067 {
00068    ASCString filename = "diplo-" + ASCString::toString(s) + ".png";
00069    return filename;
00070 };
00071 
00072 ASCString getDiplomaticStateImage( AllianceSetupWidget::DiplomaticTransitions s )
00073 {
00074    if ( s == AllianceSetupWidget::SNEAK_ATTACK ) {
00075       ASCString filename = "diplo-sneak.png";
00076       return filename;
00077    } else 
00078       return getDiplomaticStateImage( DiplomaticStates( s-1 ));
00079 };
00080 
00081 
00082 template <typename SelectionType>
00083 class ListBoxImageItem : public PG_ListBoxBaseItem {
00084       SelectionType state;
00085    public:
00086       ListBoxImageItem( PG_ListBox *parent, PG_Point pos, SelectionType s )  : PG_ListBoxBaseItem( parent, diplomaticStateIconSize + 2*diplomaticStateIconSpace ), state(s)
00087       {
00088          new PG_Image( this, PG_Point(diplomaticStateIconSpace,diplomaticStateIconSpace), IconRepository::getIcon( getDiplomaticStateImage(s)).getBaseSurface() , false );
00089          new PG_Label( this, PG_Rect(diplomaticStateIconSize + 5, diplomaticStateIconSpace, 200,diplomaticStateIconSize), getStateName<SelectionType>(s));
00090       }
00091       
00092       SigC::Signal1<void,SelectionType> sigSet;
00093       
00094       bool eventMouseButtonUp(const SDL_MouseButtonEvent* button) 
00095       {
00096             if(button->button != 1) {
00097                      return false;
00098             }
00099             
00100             PG_ListBox* listbox = dynamic_cast<PG_ListBox*>(GetParent());
00101       
00102             if(listbox == NULL || !listbox->IsVisible()) {
00103                      return true;
00104             }
00105       
00106             listbox->SelectItem(this);
00107             listbox->QuitModal();
00108             sigSet(state);
00109       
00110             return true;
00111       }
00112 };
00113 
00114 
00115 
00116 
00117 
00118 template <typename SelectionType>
00119 class DiplomaticModeChooser : public PG_Widget {
00120       SelectionType& mode;
00121       bool writePossible;
00122       
00123    protected:
00124 
00125       void selectMode()
00126       {
00127          PG_ListBox listBox( NULL, PG_Rect( x, y + Height(), 250, getItemNum<SelectionType>() * ( diplomaticStateIconSpace * 2 + diplomaticStateIconSize ) + 4 ));
00128          for ( int i = 0; i < getItemNum<SelectionType>(); ++i) {
00129             ListBoxImageItem<SelectionType>* item = new ListBoxImageItem<SelectionType>( NULL, PG_Point(0,0), SelectionType(i));
00130             item->sigSet.connect( SigC::slot( *this, &DiplomaticModeChooser::SetState));
00131             listBox.AddChild( item );
00132          }
00133          listBox.Show();
00134          listBox.RunModal();
00135       }     
00136             
00137    public:
00138       DiplomaticModeChooser ( PG_Widget *parent, const PG_Rect& pos, SelectionType& dm, bool writeable ) : PG_Widget( parent, pos, true ), mode(dm), writePossible( writeable )
00139       {
00140       };
00141 
00142       SigC::Signal1<void,SelectionType> sigStateChange;
00143             
00144       void eventDraw (SDL_Surface *surface, const PG_Rect &rect)
00145       {
00146          Surface s = Surface::Wrap( surface );
00147          s.Blit(  IconRepository::getIcon( getDiplomaticStateImage(mode) ) );
00148       }
00149       
00150       void SetState( SelectionType state )
00151       {
00152          mode = state;
00153          Redraw();
00154          Update(true);
00155          sigStateChange(state);
00156       }
00157       
00158       bool eventMouseButtonUp(const SDL_MouseButtonEvent* button) 
00159       {
00160          if (button->button != 1) {
00161             return false;
00162          }
00163 
00164          if ( writePossible )   
00165             selectMode();
00166          return true;
00167       }
00168 };      
00169  
00170 
00171 AllianceSetupWidget::AllianceSetupWidget( GameMap* gamemap, ApplyStrategy* applyStrategy, bool allEditable, PG_Widget *parent, const PG_Rect &r, const std::string &style ) 
00172    : PG_ScrollWidget( parent, r, style ) , actmap ( gamemap ), strategy( applyStrategy )
00173 
00174 {
00175    this->allEditable = allEditable;
00176    int playerNum = 0;
00177    
00178    for ( int i = 0; i < actmap->getPlayerCount(); ++i ) {
00179       vector<DiplomaticTransitions> t;
00180       vector< DiplomaticStates > s;
00181       
00182       const DiplomaticStateVector& diplo = actmap->player[i].diplomacy;
00183       
00184       for ( int j = 0; j < actmap->getPlayerCount(); ++j )  {
00185          DiplomaticStateVector::QueuedStateChanges::const_iterator change = diplo.queuedStateChanges.find(j);
00186          if ( change != diplo.queuedStateChanges.end() )
00187             t.push_back( DiplomaticTransitions( change->second + 1 ));
00188          else
00189             t.push_back( DiplomaticTransitions( diplo.getState(j) + 1 ));
00190          s.push_back( diplo.getState(j));
00191       }   
00192        
00193       stateChanges.push_back ( t );        
00194       states.push_back ( s );
00195       
00196       if ( actmap->player[i].exist() ) 
00197          ++playerNum;
00198    }      
00199 
00200          
00201    const int colWidth = 40;
00202    const int lineHeight = 30;
00203    const int barSpace = 5;
00204    const int spacing = 10;
00205    const int nameLength = 200;
00206    const int barOverhang = 20;
00207    const int sqaureWidth = lineHeight;
00208    const int lineLength = sqaureWidth + nameLength + playerNum * (colWidth + spacing) + barOverhang;
00209    const int colHeight  =  barOverhang + playerNum * (lineHeight + spacing) - spacing +  barOverhang;
00210 
00211    #define calcx(counter) (sqaureWidth + nameLength + spacing + counter * (colWidth + spacing) )
00212    #define calcy(counter) (barOverhang + counter * (lineHeight + spacing))
00213 
00214    int counter = 0; 
00215    for ( int i = 0; i < actmap->getPlayerCount(); ++i ) 
00216       if ( actmap->player[i].exist() ) {
00217          int x = calcx(counter);
00218          
00219          ColoredBar* verticalBar = new ColoredBar( actmap->player[i].getColor(), this, PG_Rect( x, 0, colWidth, colHeight ));
00220          verticalBar->SetTransparency( 128 );
00221          
00222          ++counter;
00223       }
00224    
00225                         
00226    counter = 0; 
00227    for ( int i = 0; i < actmap->getPlayerCount(); ++i ) // rows
00228       if ( actmap->player[i].exist() ) {
00229       
00230          PlayerWidgets pw;
00231          pw.pos  = i;
00232          
00233          int y = calcy(counter);
00234          
00235          ColoredBar* horizontalBar = new ColoredBar( actmap->player[i].getColor(), this, PG_Rect( 0, y, lineLength, lineHeight ));
00236          horizontalBar->SetTransparency( 128 );
00237          
00238          pw.name = new PG_LineEdit( horizontalBar, PG_Rect( sqaureWidth, barSpace, nameLength, lineHeight-2*barSpace ));
00239          pw.name->SetText( actmap->player[i].getName());
00240          pw.name->SetEditable( false );
00241 
00242          new PG_ToolTipHelp( pw.name, "Position: " + ASCString::toString(i) );
00243 
00244          PG_ThemeWidget* col = new PG_ThemeWidget( horizontalBar, PG_Rect( barSpace, barSpace, sqaureWidth - 2*barSpace, lineHeight - 2*barSpace ));
00245          col->SetSimpleBackground(true);
00246          col->SetBackgroundColor ( actmap->player[i].getColor());
00247          col->SetBorderSize(0);
00248          
00249          int cnt2 = 0;
00250          for ( int j = 0; j < actmap->getPlayerCount(); ++j ) // columns
00251             if ( actmap->player[j].exist() )  {
00252                if ( i != j ) {
00253                   int x = calcx(cnt2) - barSpace;
00254                   PG_Rect rect ( x + (colWidth - diplomaticStateIconSize)/2 ,  (lineHeight - diplomaticStateIconSize)/2,diplomaticStateIconSize,diplomaticStateIconSize); 
00255                   if ( allEditable ) {
00256                      DiplomaticModeChooser<DiplomaticStates>* dmc = new DiplomaticModeChooser<DiplomaticStates>( horizontalBar, rect, getState(i,j), true );
00257                      dmc->sigStateChange.connect( SigC::bind( SigC::slot( *this, &AllianceSetupWidget::setState ), j, i));
00258                      diplomaticWidgets[ linearize( i,j) ] = dmc;
00259                   } else {
00260                      DiplomaticTransitions& s = stateChanges[i][j];
00261                      DiplomaticModeChooser<DiplomaticTransitions>* dmc = new DiplomaticModeChooser<DiplomaticTransitions>( horizontalBar, rect, s, i == gamemap->actplayer );
00262                      // dmc->sigStateChange.connect( SigC::bind( SigC::slot( *this, &AllianceSetupWidget::setState ), j, i));
00263                      diplomaticWidgets[ linearize( i,j) ] = dmc;
00264                   }   
00265                      
00266                }
00267                ++cnt2;
00268             }   
00269                         
00270          playerWidgets.push_back( pw );
00271                         
00272          ++counter;
00273       } 
00274       
00275    SetTransparency(255);
00276 };
00277 
00278 
00279 void AllianceSetupWidget::setState( DiplomaticStates s, int actingPlayer, int secondPlayer )
00280 {
00281    getState( actingPlayer, secondPlayer) = s;
00282    
00283    DiplomaticWidgets::iterator i = diplomaticWidgets.find( linearize( actingPlayer, secondPlayer) );
00284    if ( i != diplomaticWidgets.end() )
00285       i->second->Redraw(true);
00286 }
00287 
00288 DiplomaticStates& AllianceSetupWidget::getState( int actingPlayer, int secondPlayer )
00289 {
00290    return states.at(actingPlayer).at(secondPlayer);
00291 }
00292 
00293 int AllianceSetupWidget::linearize( int actingPlayer, int secondPlayer  )
00294 {
00295    return actingPlayer * actmap->getPlayerCount() + secondPlayer;
00296 }
00297 
00298 
00299 void AllianceSetupWidget::Apply() 
00300 {
00301    for ( int acting = 0; acting < actmap->getPlayerCount(); ++acting )
00302       for ( int second = 0; second < actmap->getPlayerCount(); ++second ) {
00303       
00304          if ( allEditable ) {
00305             if ( getState( acting, second ) != actmap->player[acting].diplomacy.getState( second ))
00306                actmap->player[acting].diplomacy.setState( second, getState( acting, second ));         
00307          } else {
00308             if ( acting == actmap->actplayer ) {
00309                if ( stateChanges[acting][second] == SNEAK_ATTACK ) {
00310                   strategy->sneakAttack( actmap, acting, second );
00311                } else {
00312                   DiplomaticStates s = DiplomaticStates( stateChanges[acting][second] - 1);
00313                   DiplomaticStates t;
00314                   DiplomaticStateVector::QueuedStateChanges::iterator q = actmap->player[acting].diplomacy.queuedStateChanges.find( second );
00315                   if ( q == actmap->player[acting].diplomacy.queuedStateChanges.end() )
00316                      t = getState( acting, second );
00317                   else
00318                      t = q->second;   
00319                      
00320                   if ( t != s ) {
00321                      strategy->setState( actmap, acting, second, s );
00322                   }                     
00323                }   
00324             }
00325          }
00326       }
00327 };
00328 
00329 
00330 AllianceSetupWidget::~AllianceSetupWidget()
00331 {
00332 }   
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 class AllianceSetupWindow : public ASC_PG_Dialog {
00344       AllianceSetupWidget* asw;
00345       bool changed;
00346    public:
00347       AllianceSetupWindow( GameMap* actmap, AllianceSetupWidget::ApplyStrategy* strategy, bool allEditable, PG_Widget *parent, const PG_Rect &r ) : ASC_PG_Dialog( parent, r, "Diplomacy" ), changed(false)
00348       {
00349          asw = new AllianceSetupWidget( actmap, strategy, allEditable, this, PG_Rect( 5, 30, r.Width() - 10, r.Height() - 60 ));
00350          PG_Button* ok = new PG_Button( this, PG_Rect( Width() - 200, Height() - 30, 90, 20 ), "OK" );
00351          ok->sigClick.connect( SigC::slot( *this, &AllianceSetupWindow::Apply ));
00352          PG_Button* cancel = new PG_Button( this, PG_Rect( Width() - 100, Height() - 30, 90, 20 ), "Cancel" );
00353          cancel->sigClick.connect( SigC::slot( *this, &AllianceSetupWindow::QuitModal ));
00354       }
00355 
00356       bool Apply()
00357       {
00358          asw->Apply();
00359          QuitModal();
00360          changed = true;
00361          return true;
00362       }
00363 
00364       bool isSomethingChanged() { return changed; };
00365       
00366 };
00367 
00368 bool  setupalliances( GameMap* actmap, AllianceSetupWidget::ApplyStrategy* strategy, bool supervisor  )
00369 {
00370    AllianceSetupWindow asw ( actmap, strategy, supervisor, NULL, PG_Rect( 100, 100, 700, 500 ));
00371    asw.Show();
00372    asw.RunModal();
00373    return asw.isSomethingChanged();
00374 }
00375 
00376 void DirectAllianceSetupStrategy::sneakAttack ( GameMap* map, int actingPlayer, int towardsPlayer )
00377 {
00378    map->getPlayer( actingPlayer ).diplomacy.setState( towardsPlayer, WAR );
00379 }
00380 
00381 
00382 void DirectAllianceSetupStrategy::setState ( GameMap* map, int actingPlayer, int towardsPlayer, DiplomaticStates newState )
00383 {
00384    map->getPlayer( actingPlayer ).diplomacy.setState( towardsPlayer, newState );
00385 }

Generated on Mon May 14 01:31:39 2012 for Advanced Strategic Command by  doxygen 1.5.1