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

mapdisplay.cpp

Go to the documentation of this file.
00001 
00006 /***************************************************************************
00007                           mapdisplay.cpp  -  description
00008                              -------------------
00009     begin                : Wed Jan 24 2001
00010     copyright            : (C) 2001 by Martin Bickel
00011     email                : bickel@asc-hq.org
00012  ***************************************************************************/
00013 
00014 /***************************************************************************
00015  *                                                                         *
00016  *   This program is free software; you can redistribute it and/or modify  *
00017  *   it under the terms of the GNU General Public License as published by  *
00018  *   the Free Software Foundation; either version 2 of the License, or     *
00019  *   (at your option) any later version.                                   *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 // #define debugmapdisplay
00024 
00025 
00026 #include <cmath>
00027 #include <limits>
00028 
00029 #include "pgeventsupplier.h"
00030 
00031 #include "global.h"
00032 #include "typen.h"
00033 #include "mapdisplay.h"
00034 #include "vehicletype.h"
00035 #include "buildingtype.h"
00036 #include "spfst.h"
00037 #include "dialog.h"
00038 #include "loaders.h"
00039 #include "gameoptions.h"
00040 #include "loadbi3.h"
00041 #include "mapalgorithms.h"
00042 #include "graphicset.h"
00043 #include "graphics/blitter.h"
00044 #include "graphics/drawing.h"
00045 #include "loadpcx.h"
00046 #include "iconrepository.h"
00047 #include "mainscreenwidget.h"
00048 #include "sdl/sound.h"
00049 
00050 #ifndef karteneditor
00051  #include "dialogs/attackpanel.h"
00052 #endif
00053 
00054 
00055 #ifdef debugmapdisplay
00056 #include <iostream>
00057 #endif
00058 
00059 
00060 MapRenderer::Icons MapRenderer::icons;
00061 
00062 bool tempsvisible = true;
00063 
00064 
00065 SigC::Signal0<void> lockMapdisplay;
00066 SigC::Signal0<void> unlockMapdisplay;
00067 
00068 
00069 class ContainerInfoLayer : public MapLayer {
00070       Surface& marker;
00071       bool hasCargo( const ContainerBase* c ) {
00072          for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00073             if ( *i )
00074                return true;
00075          return false;
00076       };
00077       
00078       bool hasOwnCargo( const ContainerBase* c, int viewingPlayer ) {
00079          for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00080             if ( *i ) {
00081                if ( (*i)->getOwner() == viewingPlayer )
00082                   return true;
00083                else
00084                   if ( hasOwnCargo( *i, viewingPlayer ))
00085                      return true;
00086             }
00087          return false;
00088       };
00089     public: 
00090       ContainerInfoLayer() : marker( IconRepository::getIcon("fieldcontainermarker.png") ) {};
00091          
00092       bool onLayer( int layer ) { return layer == 17; };
00093       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00094 };
00095 
00096 void ContainerInfoLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00097 {
00098    if ( fieldInfo.visibility >= visible_ago) {
00099       if ( fieldInfo.fld->vehicle || (fieldInfo.fld->building && fieldInfo.fld->bdt.test(cbbuildingentry) )) {
00100          ContainerBase* c = fieldInfo.fld->getContainer();
00101          if ( hasCargo(c) ) {
00102             if ( c->getOwner() == fieldInfo.playerView  ) 
00103                fieldInfo.surface.Blit( marker, pos );
00104             else
00105                if ( hasOwnCargo(c, fieldInfo.playerView  ))
00106                   fieldInfo.surface.Blit( marker, pos );
00107          }
00108       }
00109    }
00110 }
00111 
00112 
00113  
00114 class ResourceGraphLayer : public MapLayer {
00115       void paintBar( const MapRenderer::FieldRenderInfo& fieldInfo, const SPoint& pos, int row, int amount, int color ) {
00116          /*
00117          int length = amount / 10;
00118          int maxlength = 255/10;
00119          if ( amount ) 
00120             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10, pos.y + 2 + row*12), length, 5, ColorMerger_ColoredOverwrite<4>( color ));
00121          if ( length < maxlength )
00122             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10 + length, pos.y + 2 + row*12), maxlength-length, 5, ColorMerger_ColoredOverwrite<4>( 0x888888 ));
00123          */
00124 
00125          int length = amount * 28 / 255;
00126          int maxlength = 28;
00127          if ( amount ) 
00128             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10, pos.y + 12 + row*15), length, 8, ColorMerger_ColoredOverwrite<4>( color ));
00129          if ( length < maxlength )
00130             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10 + length, pos.y + 12 + row*15), maxlength-length, 8, ColorMerger_ColoredOverwrite<4>( 0 ));
00131            
00132       };
00133     public: 
00134       bool onLayer( int layer ) { return layer == 17; };
00135       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00136 };
00137 
00138 void ResourceGraphLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00139 {
00140 #ifndef karteneditor
00141    if ( fieldInfo.visibility >= visible_ago) {
00142       bool visible = false;
00143 
00144       if ( fieldInfo.playerView == -1 )
00145          visible = true;
00146 
00147       if ( fieldInfo.playerView >= 0 )
00148          if ( fieldInfo.fld->resourceview && (fieldInfo.fld->resourceview->visible & ( 1 << fieldInfo.playerView) ) )
00149             visible = true;
00150 
00151       if ( visible ) {
00152          if ( fieldInfo.playerView>=0 && fieldInfo.gamemap->getPlayer(fieldInfo.playerView).stat == Player::supervisor ) {
00153             paintBar( fieldInfo, pos, 0, fieldInfo.fld->material, Resources::materialColor );
00154             paintBar( fieldInfo, pos, 1, fieldInfo.fld->fuel,     Resources::fuelColor );
00155          } else {
00156             paintBar( fieldInfo, pos, 0, fieldInfo.fld->resourceview->materialvisible[max(fieldInfo.playerView,0)], Resources::materialColor );
00157             paintBar( fieldInfo, pos, 1, fieldInfo.fld->resourceview->fuelvisible[max(fieldInfo.playerView,0)], Resources::fuelColor );
00158          }
00159       }
00160    }
00161 #else
00162    paintBar( fieldInfo, pos, 0, fieldInfo.fld->material, Resources::materialColor );
00163    paintBar( fieldInfo, pos, 1, fieldInfo.fld->fuel, Resources::fuelColor );
00164 #endif
00165 }
00166 
00167 
00168 
00169 
00170 class PipeLayer : public MapLayer {
00171       ObjectType* buried_pipeline;
00172       ObjectType* pipeline;
00173       bool isPipe( const ContainerBase* c ) {
00174          for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00175             if ( *i )
00176                return true;
00177          return false;
00178       };
00179 
00180       bool isObjectPipeline( const ObjectType* obj )
00181       {
00182          if ( !obj )
00183             return false;
00184          return (obj->displayMethod <= 1 ) && obj->fieldModification[0].terrain_or.test( cbpipeline );
00185       }
00186 
00187     public: 
00188       PipeLayer() : buried_pipeline( NULL ), pipeline ( NULL )
00189       {
00190          pipeline = objectTypeRepository.getObject_byID( 3 );
00191          if ( !isObjectPipeline( pipeline )) 
00192             pipeline = NULL;
00193 
00194          for ( int i = 0; i < objectTypeRepository.getNum(); ++i ) {
00195             ObjectType* obj = objectTypeRepository.getObject_byPos( i );
00196             if (obj->displayMethod == 1 && obj->fieldModification[0].terrain_or.test( cbpipeline )) {
00197                buried_pipeline = obj;
00198             }
00199             if (obj->displayMethod == 0 && obj->fieldModification[0].terrain_or.test( cbpipeline ) && !pipeline) {
00200                pipeline = obj;
00201             }
00202          }
00203       }
00204     
00205       bool onLayer( int layer ) { return layer == 17; };
00206       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00207 };
00208 
00209 void PipeLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00210 {
00211    if ( !pipeline )
00212       return;
00213       
00214    if ( fieldInfo.visibility > visible_ago) {
00215       if ( fieldInfo.fld->building ) {
00216          pipeline->display( fieldInfo.surface, pos, 63, 0 );
00217       } else {
00218          if ( fieldInfo.fld->bdt.test( cbpipeline )) {
00219             Object* o = fieldInfo.fld->checkforobject( buried_pipeline );
00220             if ( o )
00221                pipeline->display( fieldInfo.surface, pos, o->dir, 0 );
00222             else {
00223                bool objfound = false;
00224                for ( tfield::ObjectContainer::iterator i = fieldInfo.fld->objects.begin(); i != fieldInfo.fld->objects.end(); ++i )
00225                   if ( i->typ->fieldModification[0].terrain_or.test( cbpipeline ) ) {
00226                      pipeline->display( fieldInfo.surface, pos, i->dir, 0 );
00227                      objfound = true;
00228                      break;
00229                   }   
00230 
00231                if ( !objfound )
00232                   pipeline->display( fieldInfo.surface, pos, 63, 0 );
00233                      
00234             }
00235          }
00236       }   
00237    }
00238 }
00239 
00240 
00241 class WeaponRange : public SearchFields
00242 {
00243    public:
00244       int run ( const Vehicle* veh );
00245       void testfield ( const MapCoordinate& mc )
00246       {
00247          gamemap->getField( mc )->tempw = 1;
00248       };
00249       WeaponRange ( GameMap* _gamemap ) : SearchFields ( _gamemap )
00250       {}
00251       ;
00252 };
00253 
00254 int  WeaponRange :: run ( const Vehicle* veh )
00255 {
00256    int found = 0;
00257    if ( fieldvisiblenow ( getfield ( veh->xpos, veh->ypos )))
00258       for ( int i = 0; i < veh->typ->weapons.count; i++ ) {
00259          if ( veh->typ->weapons.weapon[i].shootable() ) {
00260             initsearch ( veh->getPosition(), veh->typ->weapons.weapon[i].maxdistance/minmalq, (veh->typ->weapons.weapon[i].mindistance+maxmalq-1)/maxmalq );
00261             startsearch();
00262             found++;
00263          }
00264       }
00265    return found;
00266 }
00267 
00268 
00269  
00270 
00271 
00272 MapRenderer::ViewPort::ViewPort( int x1, int y1, int x2, int y2 ) 
00273 { 
00274    this->x1 = x1; 
00275    this->y1 = y1; 
00276    this->x2 = x2; 
00277    this->y2 = y2; 
00278 };
00279 
00280 MapRenderer::ViewPort::ViewPort()
00281 {
00282 };
00283 
00284 MapRenderer :: MapRenderer()  
00285 { 
00286    readData(); 
00287 };
00288 
00289 
00290 void MapRenderer::readData()
00291 {
00292    if ( !icons.mapBackground.valid() ) {
00293       icons.mapBackground = IconRepository::getIcon("mapbkgr.raw");
00294       icons.notVisible    = IconRepository::getIcon("hexinvis.raw");
00295       icons.markField     = IconRepository::getIcon("markedfield.pcx");
00296       icons.markField.detectColorKey();
00297       icons.markFieldDark = IconRepository::getIcon("markedfielddark.png");
00298    }
00299 }
00300 
00301 
00302 /*
00303   layer:
00304     0: terrain
00305     1: below everything objects
00306     2: deep submerged units and building
00307     3: deep submerged objects
00308     4: submerged units and buildings
00309     5: submerged objects
00310     6: floating  units and buildings
00311     7: floating  objects
00312     8: ground    units and buildings
00313     9: ground    objects
00314    10: low flying units and buildings
00315    11: low flying objects
00316    12: flying units and buildings
00317    13: flying objects
00318    14: high flying units and buildings
00319    15: high flying objects
00320    16: orbiting units
00321    17: orbiting objects
00322    18  view obstructions
00323 */
00324 
00325 int MapRenderer::bitmappedHeight2pass( int height )
00326 {
00327    return log2(height) * 2 + 2;
00328 }
00329 
00330 
00331 void MapRenderer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00332 {
00333 
00334    int binaryUnitHeight = 0;
00335    if ( layer > 1 ) 
00336       if ( !(layer & 1 ))
00337          binaryUnitHeight = 1 << (( layer-2)/2);
00338    
00339    tfield* fld = fieldInfo.fld;
00340 
00341    if ( layer == 0 && fieldInfo.visibility >= visible_ago )
00342       fld->typ->paint ( fieldInfo.surface, pos );
00343 
00344 
00345    if ( fieldInfo.visibility > visible_ago ) {
00346 
00347       /* display buildings */
00348       if ( fld->building  &&  (fld->building->typ->buildingheight & binaryUnitHeight) && fld->building->visible )
00349          if ((fieldInfo.visibility == visible_all) || (fld->building->typ->buildingheight >= chschwimmend) || ( fld->building->getOwner() == fieldInfo.playerView ))
00350             fld->building->paintSingleField( fieldInfo.surface, pos, fld->building->getLocalCoordinate( fieldInfo.pos ));
00351 
00352 
00353       /* display units */
00354       if ( fld->vehicle  &&  (fld->vehicle->height == binaryUnitHeight))
00355          if ( ( fld->vehicle->getOwner() == fieldInfo.playerView ) || (fieldInfo.visibility == visible_all) || ((fld->vehicle->height >= chschwimmend) && (fld->vehicle->height <= chhochfliegend)))
00356             fld->vehicle->paint( fieldInfo.surface, pos );
00357 
00358    }
00359 
00360    // display objects
00361    if ( layer & 1 )
00362       for ( tfield::ObjectContainer::iterator o = fld->objects.begin(); o != fld->objects.end(); o++ ) {
00363          int h = o->typ->imageHeight;
00364          if ( fieldInfo.visibility > visible_ago || (o->typ->visibleago && fieldInfo.visibility >= visible_ago ))
00365             if (  h >= ((layer-1)/2)*30 && h < (layer-1)/2*30+30 )
00366                o->display ( fieldInfo.surface, pos, fld->getweather() );
00367       }
00368 
00369 
00370 
00371 
00372    if ( fieldInfo.visibility > visible_ago ) {
00373       /* display mines */
00374       
00375       if ( fieldInfo.visibility == visible_all )
00376          if ( !fld->mines.empty() && layer == 7 ) 
00377             fld->mines.begin()->paint( fieldInfo.surface, pos );
00378      
00379 
00380 
00381       /* display marked fields */
00382 
00383       if ( layer == 18 ) {
00384          if ( fld->a.temp && tempsvisible )
00385             fieldInfo.surface.Blit( icons.markField, pos );
00386          else
00387             if ( fld->a.temp2 && tempsvisible )
00388                fieldInfo.surface.Blit( icons.markFieldDark, pos );
00389       }
00390 
00391 
00392    } else {
00393       if (fieldInfo.visibility == visible_ago ) {
00394          if ( fld->building  &&  (fld->building->typ->buildingheight & binaryUnitHeight) && fld->building->visible )
00395             if ((fieldInfo.visibility == visible_all) || (fld->building->typ->buildingheight >= chschwimmend) || ( fld->building->getOwner() == fieldInfo.playerView ))
00396                fld->building->paintSingleField( fieldInfo.surface, pos, fld->building->getLocalCoordinate( fieldInfo.pos ));
00397 
00398       }
00399    }
00400 
00401 
00402    // display view obstructions
00403    if ( layer == 18 ) {
00404       if ( fieldInfo.visibility == visible_ago) {
00405          MegaBlitter<1,colorDepth,ColorTransform_None,ColorMerger_AlphaShadow> blitter;
00406          // PG_Point pnt = ClientToScreen( 0,0 );
00407          blitter.blit( icons.notVisible, fieldInfo.surface, pos);
00408          /*
00409                          // putspriteimage( r + unitrightshift , yp + unitdownshift , view.va8);
00410                          putshadow( r, yp, icons.view.nv8, &xlattables.a.dark2 );
00411                          if ( fld->a.temp && tempsvisible )
00412                             putspriteimage(  r, yp, cursor.markfield);
00413                          else
00414                             if ( fld->a.temp2 && tempsvisible )
00415                                putspriteimage(  r, yp, xlatpict ( &xlattables.a.dark2 , cursor.markfield));
00416           
00417          */
00418       } else
00419          if ( fieldInfo.visibility == visible_not) {
00420             fieldInfo.surface.Blit( icons.notVisible, pos );
00421             /*
00422                             if ( ( fld->a.temp || fld->a.temp2 ) && tempsvisible )
00423                                   putspriteimage(  r, yp, cursor.markfield);
00424             */
00425 
00426          }
00427 
00428    }
00429    
00430    for ( LayerRenderer::iterator i = layerRenderer.begin(); i != layerRenderer.end(); ++i )
00431       if ( (*i)->isActive() && (*i)->onLayer(layer))
00432          (*i)->paintSingleField( fieldInfo , layer, pos );
00433 
00434 }
00435 
00436 
00437 void MapRenderer::paintBackground( Surface& surf, const ViewPort& viewPort )
00438 {
00439    for (int y= viewPort.y1; y < viewPort.y2; ++y )
00440       for ( int x=viewPort.x1; x < viewPort.x2; ++x ) 
00441          paintBackgroundField( surf, getFieldPos(x,y) );
00442 }
00443 
00444 void MapRenderer::paintBackgroundField( Surface& surf, SPoint pos )
00445 {
00446    surf.Blit( icons.mapBackground, pos );
00447 }
00448 
00449 
00450 
00451 void MapRenderer::paintTerrain( Surface& surf, GameMap* actmap, int playerView, const ViewPort& viewPort, const MapCoordinate& offset )
00452 {
00453    FieldRenderInfo fieldRenderInfo( surf, actmap );
00454    fieldRenderInfo.playerView = playerView;
00455 
00456    GraphicSetManager::Instance().setActive ( actmap->graphicset );
00457 
00458    for (int pass = 0; pass <= 18 ;pass++ ) {
00459       for (int y= viewPort.y1; y < viewPort.y2; ++y )
00460          for ( int x=viewPort.x1; x < viewPort.x2; ++x ) {
00461             fieldRenderInfo.pos = MapCoordinate( offset.x + x, offset.y + y ); 
00462             fieldRenderInfo.fld = actmap->getField ( fieldRenderInfo.pos );
00463             SPoint pos = getFieldPos(x,y);
00464             if ( fieldRenderInfo.fld ) {
00465                fieldRenderInfo.visibility = fieldVisibility ( fieldRenderInfo.fld, playerView );
00466                paintSingleField( fieldRenderInfo, pass, pos );
00467             } else
00468                if ( pass == 0 )
00469                   paintBackgroundField( surf, pos );
00470 
00471          }
00472       additionalItemDisplayHook( surf, pass );
00473    }
00474    
00475 }
00476 
00477 
00478 
00479 void benchMapDisplay()
00480 {/*
00481    int t = ticker;
00482    for ( int i = 0; i < 20; ++i )
00483       repaintMap();
00484 
00485    int t2 = ticker;
00486    
00487    for ( int i = 0; i< 20; ++i)
00488       theGlobalMapDisplay->Redraw();
00489    
00490    int t3 = ticker;
00491 
00492    ASCString s;
00493    s.format("update map: %d \nupdate widget: %d \n%f fps", t2-t,t3-t2, 20.0 / float(t3-t) * 100 );
00494    displaymessage(s, 1 );
00495    */
00496 }
00497 
00498 
00499 MapDisplayPG* MapDisplayPG::theMapDisplay = NULL;
00500 MapDisplayPG* theGlobalMapDisplay = NULL;
00501 
00502 MapDisplayPG::MapDisplayPG ( MainScreenWidget *parent, const PG_Rect r )
00503       : PG_Widget ( parent, r, false ) ,
00504       zoom(-1),
00505       surface(NULL),
00506       lastDisplayedMap(NULL),
00507       offset(0,0),
00508       dirty(Map),
00509       additionalUnit(NULL),
00510       disableKeyboardCursorMovement(false),
00511       signalPrio(0),
00512       cursor(this),
00513       lock(0)
00514 {
00515    SetDirtyUpdate(true);
00516    dataLoaderTicker();
00517    
00518    readData();
00519    
00520    dataLoaderTicker();
00521    
00522    setNewZoom( CGameOptions::Instance()->mapzoom );
00523 
00524    repaintMap.connect( SigC::slot( *this, &MapDisplayPG::updateWidget ));
00525 
00526    PG_Application::GetApp()->sigKeyDown.connect( SigC::slot( *this, &MapDisplayPG::keyboardHandler ));
00527 
00528    SetName( "THEMapDisplay");
00529 
00530    dataLoaderTicker();
00531    SDL_Surface* ws = GetWidgetSurface ();
00532    if ( ws ) {
00533       Surface s = Surface::Wrap( ws );
00534       s.assignDefaultPalette();
00535    }
00536    
00537    MapRenderer::additionalItemDisplayHook.connect( SigC::slot( *this, &MapDisplayPG::displayAddons ));
00538    
00539    upperLeftSourceBlitCorner = SPoint( getFieldPosX(0,0), getFieldPosY(0,0));
00540 
00541    theMapDisplay = this;
00542    theGlobalMapDisplay = this;
00543    dataLoaderTicker();
00544    
00545    addMapLayer( new ResourceGraphLayer(), "resources" );
00546    addMapLayer( new ContainerInfoLayer(), "container" );
00547    addMapLayer( new PipeLayer()         , "pipes" );
00548    
00549    parent->lockOptionsChanged.connect( SigC::slot( *this, &MapDisplayPG::lockOptionsChanged ));
00550    GameMap::sigMapDeletion.connect( SigC::slot( *this, &MapDisplayPG::sigMapDeleted ));
00551 }
00552 
00553 
00554 
00555 void MapDisplayPG::lockOptionsChanged( int options )
00556 {
00557    if ( options & MainScreenWidget::LockOptions::MapControl )  
00558       EnableReceiver(false);
00559    else  
00560       EnableReceiver(true);
00561 }
00562 
00563 void MapDisplayPG::sigMapDeleted( GameMap& deletedMap )
00564 {
00565    if ( &deletedMap == lastDisplayedMap ) { 
00566       paintBackground();
00567       Update();
00568    }
00569 }
00570 
00571 
00572 MapDisplayPG::~MapDisplayPG ()
00573 {
00574    if ( surface ) {
00575       delete surface;
00576       surface = NULL;
00577    }
00578 }
00579 
00580 
00581 MapDisplayPG::Icons MapDisplayPG::icons;
00582 
00583 
00584 void MapDisplayPG::readData()
00585 {
00586    if ( !icons.cursor.valid() ) {
00587       icons.cursor = IconRepository::getIcon( "curshex.raw" );
00588       icons.fieldShape = IconRepository::getIcon("hexinvis.raw");
00589    }
00590 }
00591 
00592 
00593 void MapDisplayPG::setNewZoom( int zoom )
00594 {
00595    if ( zoom > 100 )
00596       zoom = 100;
00597    if ( zoom < 20 )
00598       zoom = 20;
00599 
00600    if ( zoom == this->zoom )
00601       return;
00602    
00603    this->zoom = zoom;
00604 
00605    field.numx = int( ceil(float(Width()) * 100  / zoom / fielddistx) );
00606    field.numy = int( ceil(float(Height()) * 100 / zoom / fielddisty) );
00607 
00608    field.viewPort.x1 = -1;
00609    field.viewPort.y1 = -1;
00610    field.viewPort.x2 = field.numx + 1;
00611    field.viewPort.y2 = field.numy + 1;
00612 
00613    if ( field.numy & 1 )
00614       field.numy += 1;
00615 
00616    delete surface;
00617    surface = new Surface( Surface::createSurface ( field.numx * fielddistx + 2 * surfaceBorder, (field.numy - 1) * fielddisty + fieldysize +  2 * surfaceBorder, colorDepth*8 ));
00618 
00619    dirty = Map;
00620    if ( zoom != CGameOptions::Instance()->mapzoom ) {
00621       CGameOptions::Instance()->mapzoom = zoom;
00622       CGameOptions::Instance()->setChanged();
00623    }
00624    newZoom( zoom );
00625 }
00626 
00627 
00628 void MapDisplayPG::fillSurface( int playerView )
00629 {
00630    checkViewPosition( offset );
00631    if ( !lock ) {
00632       paintTerrain( *surface, actmap, playerView, field.viewPort, offset );
00633       lastDisplayedMap = actmap;
00634    }
00635    else
00636       paintBackground();
00637    dirty = Curs;
00638 }
00639 
00640 void MapDisplayPG::paintBackground( )
00641 {
00642    MapRenderer::paintBackground( *surface, field.viewPort );
00643    lastDisplayedMap = NULL;
00644 }
00645 
00646 
00647 
00648 void MapDisplayPG::checkViewPosition( MapCoordinate& offset )
00649 {
00650    if ( offset.x + field.numx >= actmap->xsize +1 )
00651       offset.x = max(0,actmap->xsize - field.numx +1 );
00652 
00653    if ( offset.y + field.numy >= actmap->ysize +4)
00654       offset.y = max(0,actmap->ysize - field.numy +4);
00655 
00656    if ( offset.y & 1 )
00657       offset.y -= 1;
00658 
00659    if ( offset.x < 0 )
00660       offset.x = 0;
00661 
00662    if ( offset.y < 0 )
00663       offset.y = 0;
00664 }
00665 
00666 
00667 
00668 
00669 template<int pixelSize>
00670 class PixSel : public SourcePixelSelector_CacheZoom<pixelSize, SourcePixelSelector_DirectRectangle<pixelSize> >
00671 {}
00672 ;
00673 
00674 
00675 void MapDisplayPG::updateMap(bool force )
00676 {
00677    if ( !actmap )
00678       return;
00679       
00680    if ( dirty > Curs || force ) 
00681       fillSurface( actmap->getPlayerView() );
00682 }
00683 
00684 void MapDisplayPG::updateWidget()
00685 {
00686    updateMap(true);
00687    Update(true);
00688 }
00689 
00690 
00691 
00692 void MapDisplayPG::blitInternalSurface( SDL_Surface* dest, const SPoint& pnt, const PG_Rect& dstClip )
00693 {
00694    if ( zoom != 100 ) {
00695       float fzoom = float(zoom) / 100.0;
00696       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,PixSel,TargetPixelSelector_Rect> blitter;
00697       blitter.setZoom( fzoom );
00698       blitter.initSource( *surface );
00699 
00700       // SourcePixelSelector
00701       blitter.setSrcRectangle( upperLeftSourceBlitCorner, int(float(Width()) / fzoom), int(float(Height()) / fzoom));
00702 
00703       PG_Rect clip= dstClip.IntersectRect( dest->clip_rect );
00704       blitter.setTargetRect( clip );
00705       
00706       Surface s = Surface::Wrap( dest );
00707       blitter.blit( *surface, s, SPoint(pnt.x, pnt.y ));
00708    } else {
00709       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectRectangle,TargetPixelSelector_Rect> blitter;
00710       blitter.initSource( *surface );
00711       
00712       // SourcePixelSelector
00713       blitter.setSrcRectangle( upperLeftSourceBlitCorner, Width(), Height() );
00714       
00715       PG_Rect clip= dstClip.IntersectRect( dest->clip_rect );
00716       blitter.setTargetRect( clip );
00717       
00718       Surface s = Surface::Wrap( dest );
00719       blitter.blit( *surface, s, SPoint(pnt.x, pnt.y ));
00720    }   
00721    
00722 }
00723 
00724 
00725 void MapDisplayPG::displayCursor()
00726 {
00727    displayCursor( *this );
00728 }
00729 
00730 void MapDisplayPG::displayCursor( const PG_Rect& dst )
00731 {
00732    if ( !actmap )
00733       return;
00734 
00735    if ( dst.w <= 0 || dst.h <= 0 )
00736       return;
00737       
00738    int x = cursor.pos().x - offset.x;
00739    int y = cursor.pos().y  - offset.y;
00740    if( x >= field.viewPort.x1 && x < field.viewPort.x2 && y >= field.viewPort.y1 && y < field.viewPort.y2 && x >= 0 && y >= 0 && x < actmap->xsize && y < actmap->ysize ) {
00741       // surface->Blit( icons.cursor, getFieldPos(x,y));
00742       MegaBlitter<1,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectZoom,TargetPixelSelector_Rect> blitter;
00743       blitter.setZoom( float(zoom) / 100.0 );
00744 
00745       PG_Rect clip= dst.IntersectRect( PG_Application::GetScreen()->clip_rect );
00746 
00747       if ( clip.w && clip.h ) {
00748          blitter.setTargetRect ( clip );
00749    
00750          Surface s = Surface::Wrap( PG_Application::GetScreen() );
00751          SPoint pos = widget2screen ( internal2widget( mapViewPos2internalPos( MapCoordinate(x,y))));
00752          blitter.blit( icons.cursor, s, pos );
00753       }
00754    }
00755 }
00756 
00757 
00758 void MapDisplayPG::UpdateRect( const PG_Rect& rect )
00759 {
00760    SPoint p = widget2screen (  SPoint( rect.x, rect.y));
00761    PG_Rect sc ( p.x, p.y, rect.w, rect.h );
00762    sc = sc.IntersectRect( *this );
00763    eventBlit( GetWidgetSurface (), rect, sc );
00764    if ( sc.w && sc.h )
00765       PG_Application::UpdateRect(PG_Application::GetScreen(), sc.x, sc.y, sc.w, sc.h );
00766 }
00767 
00768 
00769 void MapDisplayPG::eventBlit(SDL_Surface* srf, const PG_Rect& src, const PG_Rect& dst)
00770 {
00771    if ( !GetWidgetSurface ()) {
00772       if ( dirty > Nothing )
00773          updateMap();
00774 
00775       PG_Point pnt = ClientToScreen( 0,0 );
00776       blitInternalSurface( PG_Application::GetScreen(), SPoint(pnt.x,pnt.y), dst );
00777    } else {
00778       PG_Widget::eventBlit(srf,src,dst);
00779    }
00780 
00781    if ( !cursor.invisible )
00782       displayCursor( dst );
00783 
00784 
00785 }
00786 
00787 
00788 SPoint MapDisplayPG::mapGlobalPos2internalPos ( const MapCoordinate& pos )
00789 {
00790    return getFieldPos( pos.x - offset.x, pos.y - offset.y );
00791 }
00792 
00793 SPoint MapDisplayPG::mapViewPos2internalPos ( const MapCoordinate& pos )
00794 {
00795    return getFieldPos( pos.x, pos.y );
00796 }
00797 
00798 
00799 SPoint MapDisplayPG::internal2widget( const SPoint& pos )
00800 {
00801    return SPoint( int(ceil(float(pos.x - surfaceBorder) * zoom / 100.0)), int(ceil(float(pos.y - surfaceBorder) * zoom / 100.0)));
00802 }
00803 
00804 SPoint MapDisplayPG::widget2screen( const SPoint& pos )
00805 {
00806    PG_Point p = ClientToScreen ( pos.x, pos.y );
00807    return SPoint ( p.x, p.y );
00808 }
00809 
00810 
00811 MapCoordinate MapDisplayPG::screenPos2mapPos( const SPoint& pos )
00812 {
00813    PG_Point pnt = ScreenToClient( pos.x, pos.y );
00814    if ( pnt.x >= 0 && pnt.y >= 0 && pnt.x < Width() && pnt.y < Height() )
00815       return widgetPos2mapPos ( SPoint( pnt.x, pnt.y ));
00816    else
00817       return MapCoordinate();
00818 }
00819 
00820 MapCoordinate MapDisplayPG::widgetPos2mapPos( const SPoint& pos )
00821 {
00822    int x = int( float(pos.x) * 100 / zoom ) + surfaceBorder;
00823    int y = int( float(pos.y) * 100 / zoom ) + surfaceBorder;
00824 
00825    for (int yy= field.viewPort.y1; yy < field.viewPort.y2; ++yy )
00826       for ( int xx=field.viewPort.x1; xx < field.viewPort.x2; ++xx ) {
00827          int x1 = getFieldPosX(xx,yy);
00828          int y1 = getFieldPosY(xx,yy);
00829          if ( x >= x1 && x < x1+ fieldsizex && y >= y1 && y < y1+fieldsizey )
00830             if ( icons.fieldShape.GetPixel(x-x1,y-y1) != 255 )
00831                return MapCoordinate(xx+offset.x,yy+offset.y);
00832       }
00833 
00834    return MapCoordinate();
00835 }
00836 
00837 MapCoordinate MapDisplayPG::upperLeftCorner()
00838 {
00839    return offset;       
00840 }
00841 
00842 MapCoordinate MapDisplayPG::lowerRightCorner()
00843 {
00844    return MapCoordinate( offset.x + field.numx , offset.y + field.numy );
00845 }
00846 
00847 
00848 bool MapDisplayPG::centerOnField( const MapCoordinate& mc )
00849 {
00850    if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
00851       return false;
00852       
00853    MapCoordinate newpos ( mc.x - field.numx / 2,  mc.y - field.numy / 2 );
00854 
00855    checkViewPosition( newpos );
00856 
00857    if ( newpos != offset  ) {
00858       offset = newpos;
00859       dirty = Map;
00860       Redraw();
00861       viewChanged();
00862    }
00863    return true;
00864 
00865 }
00866 
00867 void MapDisplayPG::redrawMapAtCursor ( const MapCoordinate& oldpos )
00868 {
00869    if ( oldpos.valid() ) {
00870       SPoint p = internal2widget( mapGlobalPos2internalPos( oldpos ));
00871       UpdateRect( PG_Rect( p.x, p.y, fieldsizex, fieldsizey ) );
00872    }
00873          
00874    SPoint p = internal2widget( mapGlobalPos2internalPos( cursor.pos() ));
00875    UpdateRect( PG_Rect( p.x, p.y, fieldsizex, fieldsizey ) );
00876 }
00877 
00878 
00879 int MapDisplayPG::setSignalPriority( int priority )
00880 {
00881    int old = signalPrio;
00882    signalPrio = priority;
00883    return old;
00884 }
00885 
00886 void filterQueuedZoomEvents()
00887 {
00888    SDL_Event event;
00889    while ( PG_Application::GetEventSupplier()->PeepEvent(&event) && (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) && (event.button.button == CGameOptions::Instance()->mouse.zoomoutbutton || event.button.button == CGameOptions::Instance()->mouse.zoominbutton ))
00890       PG_Application::GetEventSupplier()->PollEvent ( &event );
00891 }
00892 
00893 bool MapDisplayPG::eventMouseButtonDown (const SDL_MouseButtonEvent *button)
00894 {
00895    MapCoordinate mc = screenPos2mapPos( SPoint(button->x, button->y));
00896 
00897    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.zoomoutbutton ) {
00898       changeZoom( 10 );
00899    
00900       MapCoordinate newpos = screenPos2mapPos( SPoint(button->x, button->y));
00901       MapCoordinate newOffset ( offset.x - ( newpos.x - mc.x ), offset.y - ( newpos.y - mc.y ));
00902       checkViewPosition( newOffset );
00903       offset = newOffset;
00904 
00905       viewChanged();
00906       repaintMap();
00907       filterQueuedZoomEvents();
00908       return true;
00909    }
00910 
00911    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.zoominbutton ) {
00912       changeZoom( -10 );
00913 
00914       MapCoordinate newpos = screenPos2mapPos( SPoint(button->x, button->y));
00915       MapCoordinate newOffset ( offset.x - ( newpos.x - mc.x ), offset.y - ( newpos.y - mc.y ));
00916       checkViewPosition( newOffset );
00917       offset = newOffset;
00918 
00919       viewChanged();
00920       repaintMap();
00921       filterQueuedZoomEvents();
00922       return true;
00923    }
00924 
00925 
00926    if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
00927       return false;
00928 
00929    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.fieldmarkbutton ) {
00930       MapCoordinate oldpos = cursor.pos();
00931       bool changed = cursor.pos() != mc;
00932       cursor.pos() = mc;
00933       cursor.invisible = 0;
00934       dirty = Curs;
00935 
00936       updateFieldInfo();
00937 
00938       if ( changed )
00939          redrawMapAtCursor( oldpos );
00940 
00941       mouseButtonOnField( mc, SPoint(button->x, button->y), changed, button->button, signalPrio );
00942       return true;
00943       
00944    }
00945 
00946    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.centerbutton ) {
00947       return centerOnField( mc );
00948    }
00949 
00950    mouseButtonOnField( mc, SPoint(button->x, button->y), false, button->button, signalPrio );
00951    
00952    return false;
00953 }
00954 
00955 bool MapDisplayPG::eventMouseMotion (const SDL_MouseMotionEvent *button)
00956 {
00957    MapCoordinate mc = screenPos2mapPos( SPoint(button->x, button->y));
00958    if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
00959       return false;
00960       
00961    if ( button->type == SDL_MOUSEMOTION && (button->state == SDL_BUTTON( CGameOptions::Instance()->mouse.fieldmarkbutton) )) {
00962       bool changed = cursor.pos() != mc;
00963       if ( changed ) {
00964          MapCoordinate oldpos = cursor.pos();
00965          cursor.pos() = mc;
00966          cursor.invisible = 0;
00967          dirty = Curs;
00968 
00969          redrawMapAtCursor( oldpos );
00970          cursorMoved();
00971 
00972          mouseDraggedToField( mc, SPoint(button->x, button->y), changed, signalPrio );
00973    
00974          return true;
00975      }
00976    }
00977    return false;
00978 }
00979 
00980 
00981 bool MapDisplayPG::eventMouseButtonUp (const SDL_MouseButtonEvent *button)
00982 {
00983    return false;
00984 }
00985 
00986 
00987 bool MapDisplayPG::fieldCompletelyInViewX( const MapCoordinate& pos )
00988 {
00989    SPoint internal = mapGlobalPos2internalPos( pos);
00990    SPoint s = widget2screen( internal2widget( internal ));
00991    SPoint s2 = widget2screen( internal2widget( internal + SPoint(fieldsizex,fieldsizey) ));
00992    return s.x >= my_xpos && s2.x < my_xpos + my_width;
00993 }
00994 
00995 bool MapDisplayPG::fieldCompletelyInViewY( const MapCoordinate& pos )
00996 {
00997    SPoint internal = mapGlobalPos2internalPos( pos);
00998    SPoint s = widget2screen( internal2widget( internal ));
00999    SPoint s2 = widget2screen( internal2widget( internal + SPoint(fieldsizex,fieldsizey) ));
01000    return s.y >= my_ypos && s2.y < my_ypos + my_height;
01001 }
01002 
01003 bool MapDisplayPG::fieldCompletelyInView( const MapCoordinate& pos )
01004 {
01005    // for performance-reasons we don't call the above two methods
01006    SPoint internal = mapGlobalPos2internalPos( pos);
01007    SPoint s = widget2screen( internal2widget( internal ));
01008    SPoint s2 = widget2screen( internal2widget( internal + SPoint(fieldsizex,fieldsizey) ));
01009    return (s.y >= my_ypos && s2.y < my_ypos + my_height) && (s.x >= my_xpos && s2.x < my_xpos + my_width);
01010 
01011 }
01012 
01013 
01014 bool MapDisplayPG::fieldInView(const MapCoordinate& mc )
01015 {
01016    if ( mc.x < offset.x || mc.y < offset.y || mc.x >= offset.x + field.numx || mc.y >= offset.y +  field.numy || !fieldCompletelyInView(mc) )
01017       return false;
01018    else
01019       return true;
01020 }
01021 
01022 
01023 
01024 Surface MapDisplayPG::createMovementBufferSurface()
01025 {
01026    Surface s = Surface::createSurface( 2*surfaceBorder + effectiveMovementSurfaceWidth, 2*surfaceBorder + effectiveMovementSurfaceHeight, 8*colorDepth, 0x00ffffff ) ;
01027    s.SetColorKey( SDL_SRCCOLORKEY, 0xffffff);
01028    return s;
01029 }
01030 
01031 
01032 void MapDisplayPG::initMovementStructure()
01033 {
01034    if ( !movementMask[0].mask.valid() ) 
01035       for ( int dir = 0; dir < sidenum; ++dir ) {
01036          movementMask[dir].mask = createMovementBufferSurface();
01037          MapCoordinate start;
01038          if ( dir >= 2 && dir <= 4 )
01039             start = MapCoordinate( 1, 2 );
01040          else
01041             start = MapCoordinate( 1, 4 );
01042 
01043          MapCoordinate dest = getNeighbouringFieldCoordinate( start, dir );
01044 
01045          for ( int i = 0; i < sidenum; ++i)
01046             movementMask[dir].mask.Blit( icons.fieldShape, getFieldPos2( getNeighbouringFieldCoordinate( start, i )));
01047          for ( int i = 0; i < sidenum; ++i)
01048             movementMask[dir].mask.Blit( icons.fieldShape, getFieldPos2( getNeighbouringFieldCoordinate( dest, i )));
01049 
01050          SPoint pix = getFieldPos2( start );
01051          movementMask[dir].startFieldPos = pix;
01052 
01053          pix.x += fieldsizex/2;
01054          pix.y += fieldsizey/2;
01055          movementMask[dir].mask.SetColorKey( SDL_SRCCOLORKEY, movementMask[dir].mask.GetPixel( pix ) & ~movementMask[dir].mask.GetPixelFormat().Amask());
01056       }
01057 }
01058 
01059 
01060 template<int pixelsize>
01061 class SourcePixelSelector_DirectSubRectangle
01062 {
01063    typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01064    int x,y,x1,y1;
01065    int w,h;
01066    PG_Rect innerRect;
01067    int outerwidth;
01068 
01069    const PixelType* pointer;
01070    const PixelType* startPointer;
01071    int pitch;
01072    int linelength;
01073    const Surface* surface;
01074    protected:
01075       SourcePixelSelector_DirectSubRectangle() : x(0),y(0),x1(0),y1(0),w(0),h(0),outerwidth(0),pointer(NULL), surface(NULL)
01076       {}
01077       ;
01078 
01079       int getWidth()
01080       {
01081          return min(w, surface->w() -x1 );
01082       };
01083       int getHeight()
01084       {
01085          return min(h, surface->h()-y1 );
01086       };
01087 
01088 
01089       void init ( const Surface& srv )
01090       {
01091          surface = &srv;
01092          startPointer = pointer = (const PixelType*)(srv.pixels());
01093          linelength = srv.pitch()/sizeof(PixelType);
01094          pitch = linelength - w -1  ;
01095          y = y1;
01096          x = x1;
01097          pointer += x1 + y1 * linelength;
01098          outerwidth = getWidth();
01099       };
01100 
01101       PixelType getPixel(int x, int y)
01102       {
01103          x += x1;
01104          y += y1;
01105          if ( x >= 0 && y >= 0 && x < surface->w() && y < surface->h() )
01106             return surface->GetPixel(SPoint(x,y));
01107          else
01108             return surface->GetPixelFormat().colorkey();
01109       };
01110 
01111 
01112       PixelType nextPixel()
01113       {
01114          ++x;
01115          return *(pointer++);
01116       };
01117 
01118 
01119       void skipWholeLine()
01120       {
01121          pointer += linelength;
01122          ++y;
01123       };
01124 
01125       void skipPixels( int pixNum )
01126       {
01127          pointer += pixNum;
01128          x += pixNum;
01129       };
01130 
01131       int getSourcePixelSkip()
01132       {
01133          if ( y < innerRect.y )
01134             return outerwidth - (x - x1);
01135          else
01136             if ( y >= innerRect.y + innerRect.h )
01137                return outerwidth - (x - x1);
01138             else
01139                if ( x < innerRect.x )
01140                   return innerRect.x - x;
01141                else
01142                   if ( x >= innerRect.x + innerRect.w )
01143                      return outerwidth - (x - x1);
01144                   else
01145                      return 0;
01146        
01147       };
01148       
01149       void nextLine()
01150       {
01151          pointer = startPointer + x1 + (y++) * linelength;
01152          x = x1;
01153       };
01154 
01155    public:
01156       void setSrcRectangle( SPoint pos, int width, int height )
01157       {
01158          x1 = pos.x;
01159          y1 = pos.y;
01160          w = width;
01161          h = height;
01162       };
01163       void setInnerSrcRectangle( const PG_Rect& rect )
01164       {
01165          innerRect = rect;
01166       };
01167 
01168 };
01169 
01170 template<int pixelSize>
01171 class MovePixSel : public SourcePixelSelector_CacheZoom<pixelSize, SourcePixelSelector_DirectSubRectangle<pixelSize> >
01172 {}
01173 ;
01174 
01175 
01176 void MapDisplayPG::displayMovementStep( Movement& movement, int percentage  )
01177 {
01178 #ifdef debugmapdisplay
01179    surface->Fill( 0xff00ff00);
01180 #endif
01181 
01182    FieldRenderInfo fieldRenderInfo( *surface, movement.veh->getMap() );
01183    fieldRenderInfo.playerView = movement.playerView;
01184    for (int pass = 0; pass <= 18 ;pass++ ) {
01185       for ( int i = 0; i < movement.actualFieldNum; ++i ) {
01186          SPoint pos = movement.touchedFields[i].surfPos;
01187          fieldRenderInfo.pos = movement.touchedFields[i].mapPos;
01188          fieldRenderInfo.fld = movement.actmap->getField ( fieldRenderInfo.pos );
01189          if ( fieldRenderInfo.fld ) {
01190             fieldRenderInfo.visibility = fieldVisibility ( fieldRenderInfo.fld, fieldRenderInfo.playerView );
01191 
01192             paintSingleField( fieldRenderInfo, pass, pos );
01193          }
01194       }
01195       
01196       if ( pass >= 2 && pass < 18 )
01197          if ( !(pass & 1 ))
01198             if ( movement.veh->height & (1 << (( pass-2)/2))) {
01199                SPoint pos;
01200                pos.x = movement.from.x + (movement.to.x - movement.from.x) * percentage/100;
01201                pos.y = movement.from.y + (movement.to.y - movement.from.y) * percentage/100;
01202                int shadow = 0;
01203                if ( movement.fromShadow >= 0 && movement.toShadow >= 0 )
01204                   shadow = movement.fromShadow + (movement.toShadow - movement.fromShadow) * percentage/100;
01205                movement.veh->paint( *surface, pos, false, shadow );
01206             }
01207    }
01208 
01209 #ifdef debugmapdisplay
01210    MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_Plain,TargetPixelSelector_Valid> alphaBlitter;
01211    alphaBlitter.blit( *movement.mask, *surface, movement.maskPosition);
01212 #endif
01213    
01214    PG_Rect targetArea  ( widget2screen( SPoint( 0, 0 )).x, widget2screen( SPoint( 0, 0 )).y, Width(), Height() );
01215    Surface s = Surface::Wrap( PG_Application::GetScreen() );
01216    
01217 #ifdef debugmapdisplay
01218    s.Fill( 0xff00ff );
01219 #endif
01220 
01221    if ( zoom != 100 ) {
01222       float fzoom = float(zoom) / 100.0;
01223       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,MovePixSel,TargetPixelSelector_Rect> blitter;
01224       blitter.setZoom( fzoom );
01225       blitter.initSource( *surface );
01226       
01227       blitter.setSrcRectangle( SPoint( getFieldPosX(0,0), getFieldPosY(0,0)), int(float(Width()) / fzoom), int(float(Height()) / fzoom));
01228       blitter.setInnerSrcRectangle( movement.blitViewPortInternal  );
01229       
01230       blitter.setTargetRect( targetArea );
01231       blitter.blit( *surface, s, movement.targetBlitPos );
01232    } else {
01233       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectSubRectangle,TargetPixelSelector_Rect> blitter;
01234       blitter.initSource( *surface );
01235       
01236       blitter.setSrcRectangle( SPoint( getFieldPosX(0,0), getFieldPosY(0,0)), Width(), Height() );
01237       blitter.setInnerSrcRectangle( movement.blitViewPortInternal  );
01238       
01239       blitter.setTargetRect( targetArea  );
01240       blitter.blit( *surface, s, movement.targetBlitPos );
01241    }
01242 
01243 #ifdef debugmapdisplay
01244    rectangle<4>( s, SPoint(targetArea.x, targetArea.y), targetArea.w, targetArea.h, ColorMerger_ColoredOverwrite<4>( 0x00ffff ), ColorMerger_ColoredOverwrite<4>( 0x00ffff ) );
01245    rectangle<4>( s, SPoint(movement.blitViewPortScreen.x, movement.blitViewPortScreen.y), movement.blitViewPortScreen.w, movement.blitViewPortScreen.h, ColorMerger_ColoredOverwrite<4>( 0x0000ff ), ColorMerger_ColoredOverwrite<4>( 0x0000ff ) );
01246    PG_Application::UpdateRect(PG_Application::GetScreen(), 0, 0, PG_Application::GetScreen()->w, PG_Application::GetScreen()->h );
01247 #else   
01248    PG_Application::UpdateRect(PG_Application::GetScreen(), movement.blitViewPortScreen.x, movement.blitViewPortScreen.y, movement.blitViewPortScreen.w, movement.blitViewPortScreen.h );
01249 #endif
01250 }
01251 
01252 
01253 
01254 
01255 
01256 bool ccompare( const MapCoordinate& a, const MapCoordinate& b )
01257 {
01258    return a.y < b.y || (a.y == b.y && a.x < b.x);
01259 }   
01260 
01261 
01262 void MapDisplayPG::displayUnitMovement( GameMap* actmap, Vehicle* veh, const MapCoordinate3D& from, const MapCoordinate3D& to )
01263 {
01264    static int col = 0xff;
01265    
01266 #ifdef debugmapdisplay
01267    col += 30;
01268    if ( col > 255 )
01269       col -= 255;
01270 #endif
01271 
01272    surface->Fill( col << 8 );
01273    
01274    if ( !fieldInView( from ) && !fieldInView( to ))
01275       return;
01276 
01277    if ( from.x == to.x && from.y == to.y && from.getBitmappedHeight() <= chschwimmend && to.getBitmappedHeight() <=