edselfnt.cpp

Go to the documentation of this file.
00001 
00005 /*
00006     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00007     Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU General Public License for more details.
00018 
00019     You should have received a copy of the GNU General Public License
00020     along with this program; see the file COPYING. If not, write to the 
00021     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00022     Boston, MA  02111-1307  USA
00023 */
00024 
00025 
00026 #include "vehicletype.h"
00027 #include "buildingtype.h"
00028 
00029 #include "edmisc.h"
00030 #include "edselfnt.h"
00031 #include "mapdisplay.h"
00032 #include "itemrepository.h"
00033 #include "edglobal.h"
00034 
00035 #include "graphics/blitter.h"
00036 #include "paradialog.h"
00037 
00038 #include "dialogs/vehicletypeselector.h"
00039 #include "unitset.h"
00040 #include "spfst-legacy.h"
00041 
00042 SigC::Signal0<void> filtersChangedSignal;
00043 
00044 
00045 
00046 
00047 
00048 bool buildingComp( const BuildingType* v1, const BuildingType* v2 )
00049 {
00050    int id1 = getUnitSetID(v1);
00051    int id2 = getUnitSetID(v2);
00052    return (id1 <  id2) ||
00053           (id1 == id2 && v1->name < v2->name);
00054 }
00055 
00056 bool objectComp( const ObjectType* v1, const ObjectType* v2 )
00057 {
00058    return v1->name < v2->name;
00059 }
00060 
00061 bool terrainComp( const TerrainType* v1, const TerrainType* v2 )
00062 {
00063    if (  v1->weather[0] && v2->weather[0] )
00064       return v1->weather[0]->art.to_ulong()  < v2->weather[0]->art.to_ulong();
00065    else
00066       return v1->name < v2->name;
00067 }
00068 
00069 bool mineComp( const MineType* v1, const MineType* v2 )
00070 {
00071    return v1->id < v2->id;
00072 }
00073 
00074 
00075 void sortItems( vector<VehicleType*>& vec )
00076 {
00077    sort( vec.begin(), vec.end(), vehicleComp );
00078 }
00079 
00080 void sortItems( vector<BuildingType*>& vec )
00081 {
00082    sort( vec.begin(), vec.end(), buildingComp );
00083 }
00084 
00085 void sortItems( vector<ObjectType*>& vec )
00086 {
00087    sort( vec.begin(), vec.end(), objectComp );
00088 }
00089 
00090 void sortItems( vector<TerrainType*>& vec )
00091 {
00092    sort( vec.begin(), vec.end(), terrainComp );
00093 }
00094 
00095 void sortItems( vector<MineType*>& vec )
00096 {
00097    sort( vec.begin(), vec.end(), mineComp );
00098 }
00099 
00100 
00101 void MapComponent::displayClip( PG_Widget* parent, SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst ) const
00102 {
00103    if ( !getClippingSurface().valid() )
00104       getClippingSurface() = Surface::createSurface( displayWidth() + 10, displayHeight() + fontHeight + 10, 32, 0 );
00105       
00106    getClippingSurface().Fill(0);   
00107    display( getClippingSurface(), SPoint( 0, 0 ) );
00108    
00109    static PG_ThemeWidget* fontProvidingWidget = NULL;
00110    if ( !fontProvidingWidget  )
00111       fontProvidingWidget = new PG_ThemeWidget( NULL, PG_Rect::null , false, "MapedItemSelector" );
00112       
00113    /*
00114    SDL_Rect      blitRect;
00115    blitRect.x = 0;
00116    blitRect.y = displayHeight() + 2;
00117    blitRect.w = displayWidth();
00118    blitRect.h = displayHeight() - blitRect.y;
00119 
00120    PG_FontEngine::RenderText( getClippingSurface().getBaseSurface(), blitRect, blitRect.x, blitRect.y+fontProvidingWidget ->GetFontAscender(), getItemType()->getName(), fontProvidingWidget ->GetFont() );
00121    */
00122 
00123    PG_Draw::BlitSurface( getClippingSurface().getBaseSurface(), src, surface, dst);
00124 
00125    int x = dst.x;
00126    int y = dst.y + displayHeight() + fontProvidingWidget ->GetFontAscender() - src.y;
00127    
00128    PG_FontEngine::RenderText( surface, dst, x, y, getItemType()->getName(), fontProvidingWidget ->GetFont() );
00129 }
00130 
00131 
00132 
00133 
00134 int VehicleItem::place( GameMap* gamemap, const MapCoordinate& mc, const VehicleType* v, int owner )
00135 {
00136    MapField* fld = gamemap->getField(mc);
00137    if ( !fld )
00138       return -1;
00139 
00140    const VehicleType* veh = v;
00141    
00142    if ( !veh )
00143       return -2;
00144      
00145    if ( owner  >= 8 )
00146       return -3;
00147 
00148    bool accessible = veh->terrainaccess.accessible ( fld->bdt );
00149    if ( veh->height >= chtieffliegend )
00150          accessible = true;
00151 
00152    if ( fld->building  || ( !accessible && !gamemap->getgameparameter( cgp_movefrominvalidfields)) ) 
00153       return -3;
00154    
00155    
00156    if ( fld->vehicle ) {
00157       if ( fld->vehicle->typ != veh ) {
00158          delete fld->vehicle;
00159          fld->vehicle = NULL;
00160       } else {
00161          fld->vehicle->convert( owner  );
00162          return 1;
00163       }
00164    }
00165    fld->vehicle = new Vehicle ( v, gamemap, owner  );
00166    fld->vehicle->setnewposition ( mc );
00167    fld->vehicle->fillMagically();
00168    
00169    for ( int i = 0; i < 9; ++i ) {
00170       if ( fld->vehicle->typ->height & (1 << i )) {
00171          fld->vehicle->height = 1 << i;
00172          if ( terrainaccessible( fld, fld->vehicle ) == 2 ) //  || gamemap->getgameparameter( cgp_movefrominvalidfields)
00173             break;
00174       }
00175       if ( i == 8 ) { // no height found
00176          delete fld->vehicle;
00177          fld->vehicle = NULL;
00178          return -3;
00179       }   
00180    }
00181    fld->vehicle->resetMovement();
00182    return 1;
00183    
00184 }
00185 
00186 int VehicleItem::place( const MapCoordinate& mc ) const
00187 {
00188    return place( actmap, mc, item, selection.getPlayer() );
00189 }
00190 
00191 Surface BuildingItem::clippingSurface;
00192 Surface BuildingItem::fullSizeImage;
00193 int BuildingItem::place( const MapCoordinate& mc ) const
00194 {
00195    if ( selection.getPlayer()  > 8 )
00196       return -3;
00197    
00198    int f = 0;
00199    for ( int x = 0; x < 4; x++ )
00200       for ( int y = 0; y < 6; y++ )
00201          if ( bld->fieldExists ( BuildingType::LocalCoordinate(x, y) )) {
00202             MapCoordinate mc = bld->getFieldCoordinate ( actmap->getCursor() , BuildingType::LocalCoordinate (x, y) );
00203             if ( !actmap->getField (mc) )
00204                return -1;
00205 
00206             if ( bld->terrainaccess.accessible ( actmap->getField (mc)->bdt ) <= 0 )
00207                f++;
00208          }
00209    if ( f ) {
00210       if (choice_dlg("Invalid terrain for building !","~i~gnore","~c~ancel") == 2)
00211          return -1 ;
00212    }      
00213 
00214    putbuilding( actmap, actmap->getCursor(), selection.getPlayer()  * 8, bld, bld->construction_steps );
00215    return 0;
00216 }
00217 
00218 void BuildingItem::display( Surface& s, const SPoint& pos ) const 
00219 { 
00220    if ( !fullSizeImage.valid() )
00221       fullSizeImage = Surface::createSurface( displayWidth()*2 + 10, displayHeight()*2 + 30, 32, 0 );
00222    fullSizeImage.FillTransparent();
00223    if ( actmap )
00224       bld->paint ( fullSizeImage, SPoint(0,0), actmap->getPlayer( selection.getPlayer()).getPlayerColor() ); 
00225    else
00226       bld->paint ( fullSizeImage, SPoint(0,0) ); 
00227    
00228    MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectZoom,TargetPixelSelector_Valid> blitter;
00229    blitter.setZoom( 0.5 );
00230    blitter.blit( fullSizeImage, s, pos );
00231 }
00232 
00233 
00234 
00235 // template<> Surface BasicItem<ObjectType>::clippingSurface;
00236 int ObjectItem::place( const MapCoordinate& mc ) const
00237 {
00238    if ( !actmap->getField(mc)->addobject( item ) )
00239       if ( SDL_GetKeyState(NULL)[SDLK_LCTRL] || SDL_GetKeyState(NULL)[SDLK_RCTRL] || choice_dlg("object cannot be built here\n(bypass this dialog by pressing <ctrl>)","~c~ancel","~i~gnore") == 2)
00240          actmap->getField(mc)->addobject( item, -1, true );
00241 
00242    return 0;
00243 }
00244 
00245 
00246 bool ObjectItem::remove ( const MapCoordinate& mc ) const
00247 {
00248    if ( item && actmap->getField(mc)->checkForObject(item) ) {
00249       actmap->getField(mc)->removeObject ( item );
00250       return true;
00251    }
00252    return false;
00253 
00254 }
00255 
00256 
00257 template<typename T> Surface BasicItem<T>::clippingSurface;
00258 int TerrainItem::place( const MapCoordinate& mc ) const
00259 {
00260    MapField* fld = actmap->getField(mc);
00261    fld->typ = item->weather[0]; 
00262    fld->setWeather( selection.getWeather() );
00263    fld->setparams();
00264    for ( int d = 0; d < 6; ++d ) {
00265       MapCoordinate pos = getNeighbouringFieldCoordinate( mc, d );
00266       MapField* fld = actmap->getField( pos );
00267       if ( fld ) 
00268          for ( MapField::ObjectContainer::iterator i = fld->objects.begin(); i != fld->objects.end(); ++i )
00269             calculateobject( pos, false, i->typ, actmap );
00270    }
00271    return 0;
00272 }
00273 
00274 
00275 int MineItem::place( const MapCoordinate& mc ) const
00276 {
00277    actmap->getField(mc)->putmine( selection.getPlayer(), MineTypes(item->id), MineBasePunch[item->id-1] );
00278    return 0;
00279 }
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 class CargoItemFactory: public MapItemTypeWidgetFactory<MapItemTypeWidget< VehicleType > > {
00302       typedef MapItemTypeWidgetFactory<MapItemTypeWidget< VehicleType > > Parent;
00303       typedef MapItemTypeWidget< VehicleType > WidgetType;
00304        ContainerBase* container;
00305    protected:
00306       bool isFiltered( const ItemType& item ) {
00307          if ( Parent::isFiltered( item ))
00308             return true;
00309       
00310          if ( !container->baseType->vehicleFit( &item ))
00311             return true;
00312               
00313          bool result = true;
00314          Vehicle* unit = new Vehicle ( &item, actmap, container->getOwner() );
00315          if ( container->vehicleFit ( unit ))
00316             result = false;
00317          delete unit;
00318          return result;
00319       };
00320 
00321    public:
00322       CargoItemFactory(  ContainerBase* container_ )  : Parent(vehicleTypeRepository), container( container_ ) {};
00323       
00324       void itemSelected( const SelectionWidget* widget, bool mouse )
00325       {
00326          if ( !widget )
00327             return;
00328             
00329          const WidgetType* mapItemWidget = dynamic_cast<const WidgetType*>(widget);
00330          assert( mapItemWidget );
00331          if ( mapItemWidget->getItem() ) {
00332             Vehicle* unit = new Vehicle ( mapItemWidget->getItem(), actmap, container->getOwner() );
00333             unit->fillMagically();
00334             unit->setnewposition ( container->getPosition() );
00335             unit->tank.material = 0;
00336             unit->tank.fuel = 0;
00337             if ( container->vehicleFit ( unit )) {
00338                unit->tank.material = unit->getStorageCapacity().material;
00339                unit->tank.fuel = unit->getStorageCapacity().fuel;
00340       
00341                if ( !container->vehicleFit ( unit )) {
00342                   unit->tank.material = 0;
00343                   unit->tank.fuel = 0;
00344                   displaymessage("Warning:\nThe unit you just set could not be loaded with full material and fuel\nPlease set these values manually",1);
00345                }
00346                container->addToCargo( unit );
00347       
00348             } else {
00349                delete unit;
00350                displaymessage("The unit could not be loaded !",1);
00351             }
00352          }
00353       }
00354      
00355 };
00356 
00357 
00358 void addCargo( ContainerBase* container )
00359 {
00360    ItemSelectorWindow isw( NULL, PG_Rect( 100, 100, 280, 600), "cargo", new CargoItemFactory( container ) );
00361    isw.Show();
00362    isw.RunModal();
00363 }
00364 
00365 
00366 
00367 
00368 
00369 class ProductionItemFactory: public MapItemTypeWidgetFactory<MapItemTypeWidget< VehicleType > > {
00370       typedef MapItemTypeWidgetFactory<MapItemTypeWidget< VehicleType > > Parent;
00371       typedef MapItemTypeWidget< VehicleType > WidgetType;
00372       ContainerBase* container;
00373       const VehicleType* selectedItem;
00374    protected:
00375       bool isFiltered( const ItemType& item ) {
00376          if ( Parent::isFiltered( item ))
00377             return true;
00378       
00379          if ( !container->baseType->vehicleFit( &item ))
00380             return true;
00381          
00382          if ( !(container->baseType->vehicleCategoriesProduceable & (1 << item.movemalustyp)))
00383             return true;
00384 
00385          return false;
00386       };
00387 
00388    public:
00389       ProductionItemFactory(  ContainerBase* container_ )  : Parent(vehicleTypeRepository), container( container_ ), selectedItem(NULL) {};
00390       
00391 
00392       void itemMarked  ( const SelectionWidget* widget )
00393       {
00394          if ( !widget )
00395             return;
00396             
00397          const WidgetType* mapItemWidget = dynamic_cast<const WidgetType*>(widget);
00398          assert( mapItemWidget );
00399          const VehicleType* type = mapItemWidget->getItem();
00400          if ( type ) {
00401             selectedItem = type;
00402          }
00403       };
00404       
00405       void itemSelected( const SelectionWidget* widget, bool mouse )
00406       {
00407          itemMarked( widget );
00408       }
00409       
00410       const VehicleType* getSelectedVehicleType()
00411       {
00412          return selectedItem;
00413       }
00414      
00415 };
00416 
00417 
00418 class AvailableProductionItemFactory: public SelectionItemFactory, public SigC::Object  {
00419    private:
00420       const ContainerBase* container;
00421       const VehicleType* selectedItem;
00422    protected:
00423       ContainerBase::Production::const_iterator it;
00424       ContainerBase::Production& production;
00425    public:
00426       AvailableProductionItemFactory(  ContainerBase* container_, ContainerBase::Production& prod )  : container( container_ ), selectedItem(NULL), production( prod )
00427       {
00428          restart();
00429       };
00430       
00431       void restart()
00432       {
00433          // sort( items.begin(), items.end(), VehicleComp );
00434          it = production.begin();
00435       }
00436       
00437       SelectionWidget* spawnNextItem( PG_Widget* parent, const PG_Point& pos )
00438       {
00439          if ( it != production.end() ) {
00440             const VehicleType* v = *(it++);
00441             return new VehicleTypeBaseWidget( parent, pos, parent->Width() - 15, v, actmap->getCurrentPlayer() );
00442          } else
00443             return NULL;
00444       };
00445       
00446       void itemMarked  ( const SelectionWidget* widget )
00447       {
00448          if ( !widget )
00449             return;
00450             
00451          const VehicleTypeBaseWidget* mapItemWidget = dynamic_cast<const VehicleTypeBaseWidget*>(widget);
00452          assert( mapItemWidget );
00453          const VehicleType* type = mapItemWidget->getVehicletype();
00454          if ( type ) {
00455             selectedItem = type;
00456          }
00457       }
00458       
00459       
00460       void itemSelected( const SelectionWidget* widget, bool mouse )
00461       {
00462          itemMarked( widget );
00463       }
00464 
00465       const VehicleType* getSelectedVehicleType()
00466       {
00467          return selectedItem;
00468       }
00469             
00470 };
00471 
00472 
00473 
00474 class ProductionEditorWindow : public ASC_PG_Dialog {
00475    private:
00476       ProductionItemFactory* allTypesFactory;
00477       ItemSelectorWidget* allTypes;
00478       
00479       AvailableProductionItemFactory* productionFactory;
00480       ItemSelectorWidget* productionWidget;
00481       
00482 
00483       ContainerBase* container;
00484 
00485       ContainerBase::Production production;
00486       
00487 
00488       bool ok()
00489       {
00490          container->setProductionLines( production );
00491          QuitModal();
00492          return true;
00493       }
00494 
00495       bool addOne()
00496       {
00497          const VehicleType* v = allTypesFactory->getSelectedVehicleType();
00498          if ( !v )
00499             return false;
00500          
00501          if ( find( production.begin(), production.end(), v ) == production.end() ) {
00502             production.push_back( v );
00503             productionWidget->reLoad( true );
00504             return true;
00505          }
00506          return false;
00507       }
00508       
00509       bool removeOne()
00510       {
00511          const VehicleType* v = productionFactory->getSelectedVehicleType();
00512          if ( !v )
00513             return false;
00514 
00515          ContainerBase::Production::iterator i = find( production.begin(), production.end(), v );
00516          if ( i != production.end() ) {
00517             production.erase( i );
00518             productionWidget->reLoad( true );
00519             return true;
00520          }
00521          return false;
00522       }
00523 
00524       
00525    public:
00526       ProductionEditorWindow ( ContainerBase* container ) : ASC_PG_Dialog ( NULL, PG_Rect( 20,20, 700, 550 ), "Unit Production" )
00527       {
00528          this->container = container;
00529          production = container->getProduction();
00530          
00531          const int centerSpace = 80;
00532          const int border  = 10;
00533          
00534          allTypesFactory = new ProductionItemFactory( container );
00535          allTypes = new ItemSelectorWidget( this, PG_Rect( border, 50, (my_width- centerSpace) / 2 - 2 * border, my_height - 100 ), allTypesFactory );
00536 
00537          productionFactory = new AvailableProductionItemFactory( container, production );
00538          productionWidget = new ItemSelectorWidget( this, PG_Rect( (my_width + centerSpace) / 2 + border, 50, (my_width- centerSpace) / 2 - 2 * border, my_height - 100 ), productionFactory);
00539 
00540 
00541          
00542          PG_Button* addB = new PG_Button( this, PG_Rect( (my_width - centerSpace) / 2, 100, centerSpace, 30 ), "->" );
00543          addB->sigClick.connect( SigC::slot( *this, &ProductionEditorWindow::addOne ));
00544          
00545          PG_Button* removeB = new PG_Button( this, PG_Rect( (my_width - centerSpace) / 2, 140, centerSpace, 30 ), "<-" );
00546          removeB->sigClick.connect( SigC::slot( *this, &ProductionEditorWindow::removeOne ));
00547 
00548          
00549          PG_Button* ok = new PG_Button( this, PG_Rect( my_width - 100, my_height - 40, 90, 30 ), "OK" );
00550          ok->sigClick.connect( SigC::slot( *this, &ProductionEditorWindow::ok ));
00551       };
00552 
00553 };
00554       
00555 
00556 void editProduction( ContainerBase* container )
00557 {
00558    ProductionEditorWindow pew ( container );
00559    pew.Show();
00560    pew.RunModal();
00561 }
00562 

Generated on Mon May 21 01:26:32 2012 for Advanced Strategic Command by  doxygen 1.5.1