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 #include <sstream>
00029 
00030 #include "pgeventsupplier.h"
00031 
00032 #include "global.h"
00033 #include "typen.h"
00034 #include "mapdisplay.h"
00035 #include "vehicletype.h"
00036 #include "buildingtype.h"
00037 #include "spfst.h"
00038 #include "dialog.h"
00039 #include "loaders.h"
00040 #include "gameoptions.h"
00041 #include "loadbi3.h"
00042 #include "mapalgorithms.h"
00043 #include "graphicset.h"
00044 #include "graphics/blitter.h"
00045 #include "graphics/drawing.h"
00046 #include "loadpcx.h"
00047 #include "iconrepository.h"
00048 #include "mainscreenwidget.h"
00049 #include "sdl/sound.h"
00050 #include "spfst-legacy.h"
00051 
00052 #ifndef karteneditor
00053  #include "dialogs/attackpanel.h"
00054 #endif
00055 
00056 
00057 #ifdef debugmapdisplay
00058 #include <iostream>
00059 #endif
00060 
00061 
00062 MapRenderer::Icons MapRenderer::icons;
00063 
00064 bool tempsvisible = true;
00065 
00066 
00067 SigC::Signal0<void> lockMapdisplay;
00068 SigC::Signal0<void> unlockMapdisplay;
00069 
00070 
00071 class ContainerInfoLayer : public MapLayer {
00072       Surface& marker;
00073       bool hasCargo( const ContainerBase* c ) {
00074          for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00075             if ( *i )
00076                return true;
00077          return false;
00078       };
00079       
00080       bool hasOwnCargo( const ContainerBase* c, int viewingPlayer ) {
00081          for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00082             if ( *i ) {
00083                if ( (*i)->getOwner() == viewingPlayer )
00084                   return true;
00085                else
00086                   if ( hasOwnCargo( *i, viewingPlayer ))
00087                      return true;
00088             }
00089          return false;
00090       };
00091     public: 
00092       ContainerInfoLayer() : marker( IconRepository::getIcon("fieldcontainermarker.png") ) {};
00093          
00094       bool onLayer( int layer ) { return layer == 17; };
00095       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00096 };
00097 
00098 void ContainerInfoLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00099 {
00100    if ( fieldInfo.visibility >= visible_ago) {
00101       if ( fieldInfo.fld->vehicle || (fieldInfo.fld->building && fieldInfo.fld->bdt.test(cbbuildingentry) )) {
00102          ContainerBase* c = fieldInfo.fld->getContainer();
00103          if ( hasCargo(c) ) {
00104             if ( c->getOwner() == fieldInfo.playerView  ) 
00105                fieldInfo.surface.Blit( marker, pos );
00106             else
00107                if ( hasOwnCargo(c, fieldInfo.playerView  ))
00108                   fieldInfo.surface.Blit( marker, pos );
00109          }
00110       }
00111    }
00112 }
00113 
00114  
00115 class ResourceGraphLayer : public MapLayer {
00116       void paintBar( const MapRenderer::FieldRenderInfo& fieldInfo, const SPoint& pos, int row, int amount, int color ) {
00117          /*
00118          int length = amount / 10;
00119          int maxlength = 255/10;
00120          if ( amount ) 
00121             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10, pos.y + 2 + row*12), length, 5, ColorMerger_ColoredOverwrite<4>( color ));
00122          if ( length < maxlength )
00123             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10 + length, pos.y + 2 + row*12), maxlength-length, 5, ColorMerger_ColoredOverwrite<4>( 0x888888 ));
00124          */
00125 
00126          int length = amount * 28 / 255;
00127          int maxlength = 28;
00128          if ( amount ) 
00129             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10, pos.y + 12 + row*15), length, 8, ColorMerger_ColoredOverwrite<4>( color ));
00130          if ( length < maxlength )
00131             paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 10 + length, pos.y + 12 + row*15), maxlength-length, 8, ColorMerger_ColoredOverwrite<4>( 0 ));
00132            
00133       };
00134     public: 
00135       bool onLayer( int layer ) { return layer == 17; };
00136       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00137 };
00138 
00139 void ResourceGraphLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00140 {
00141 #ifndef karteneditor
00142    if ( fieldInfo.visibility >= visible_ago) {
00143       bool visible = false;
00144 
00145       if ( fieldInfo.playerView == -1 )
00146          visible = true;
00147 
00148       if ( fieldInfo.playerView >= 0 )
00149          if ( fieldInfo.fld->resourceview && (fieldInfo.fld->resourceview->visible & ( 1 << fieldInfo.playerView) ) )
00150             visible = true;
00151 
00152       if ( visible ) {
00153          if ( fieldInfo.playerView>=0 && fieldInfo.gamemap->getPlayer(fieldInfo.playerView).stat == Player::supervisor ) {
00154             paintBar( fieldInfo, pos, 0, fieldInfo.fld->material, Resources::materialColor );
00155             paintBar( fieldInfo, pos, 1, fieldInfo.fld->fuel,     Resources::fuelColor );
00156          } else {
00157             paintBar( fieldInfo, pos, 0, fieldInfo.fld->resourceview->materialvisible[max(fieldInfo.playerView,0)], Resources::materialColor );
00158             paintBar( fieldInfo, pos, 1, fieldInfo.fld->resourceview->fuelvisible[max(fieldInfo.playerView,0)], Resources::fuelColor );
00159          }
00160       }
00161    }
00162 #else
00163    paintBar( fieldInfo, pos, 0, fieldInfo.fld->material, Resources::materialColor );
00164    paintBar( fieldInfo, pos, 1, fieldInfo.fld->fuel, Resources::fuelColor );
00165 #endif
00166 }
00167 
00168 
00169 
00170 
00171 class PipeLayer : public MapLayer {
00172       ObjectType* buried_pipeline;
00173       ObjectType* pipeline;
00174       bool isPipe( const ContainerBase* c ) {
00175          for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00176             if ( *i )
00177                return true;
00178          return false;
00179       };
00180 
00181       bool isObjectPipeline( const ObjectType* obj )
00182       {
00183          if ( !obj )
00184             return false;
00185          return (obj->displayMethod <= 1 ) && obj->fieldModification[0].terrain_or.test( cbpipeline );
00186       }
00187 
00188     public: 
00189       PipeLayer() : buried_pipeline( NULL ), pipeline ( NULL )
00190       {
00191          pipeline = objectTypeRepository.getObject_byID( 3 );
00192          if ( !isObjectPipeline( pipeline )) 
00193             pipeline = NULL;
00194 
00195          for ( int i = 0; i < objectTypeRepository.getNum(); ++i ) {
00196             ObjectType* obj = objectTypeRepository.getObject_byPos( i );
00197             if (obj->displayMethod == 1 && obj->fieldModification[0].terrain_or.test( cbpipeline )) {
00198                buried_pipeline = obj;
00199             }
00200             if (obj->displayMethod == 0 && obj->fieldModification[0].terrain_or.test( cbpipeline ) && !pipeline) {
00201                pipeline = obj;
00202             }
00203          }
00204       }
00205     
00206       bool onLayer( int layer ) { return layer == 17; };
00207       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00208 };
00209 
00210 void PipeLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00211 {
00212    if ( !pipeline )
00213       return;
00214       
00215    if ( fieldInfo.visibility > visible_ago) {
00216       if ( fieldInfo.fld->building ) {
00217          pipeline->display( fieldInfo.surface, pos, 63, 0 );
00218       } else {
00219          if ( fieldInfo.fld->bdt.test( cbpipeline )) {
00220             Object* o = fieldInfo.fld->checkForObject( buried_pipeline );
00221             if ( o )
00222                pipeline->display( fieldInfo.surface, pos, o->dir, 0 );
00223             else {
00224                bool objfound = false;
00225                for ( MapField::ObjectContainer::iterator i = fieldInfo.fld->objects.begin(); i != fieldInfo.fld->objects.end(); ++i )
00226                   if ( i->typ->fieldModification[0].terrain_or.test( cbpipeline ) ) {
00227                      pipeline->display( fieldInfo.surface, pos, i->dir, 0 );
00228                      objfound = true;
00229                      break;
00230                   }   
00231 
00232                if ( !objfound )
00233                   pipeline->display( fieldInfo.surface, pos, 63, 0 );
00234                      
00235             }
00236          }
00237       }   
00238    }
00239 }
00240 
00241 
00242 
00243 class ReactionFireLayer : public MapLayer {
00244       Surface& image;
00245 
00246    public: 
00247       ReactionFireLayer() : image ( IconRepository::getIcon("rf-icon.png")) {} ;
00248       bool onLayer( int layer ) { return layer == 17; };
00249       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00250 };
00251 
00252 void ReactionFireLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00253 {
00254    if ( fieldInfo.visibility > visible_ago) {
00255       if ( fieldInfo.fld->vehicle && fieldInfo.fld->vehicle->reactionfire.getStatus() != Vehicle::ReactionFire::off && fieldInfo.fld->vehicle->getOwner() == fieldInfo.playerView ) {
00256          MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaMerge> blitter;
00257          blitter.blit( image, fieldInfo.surface, pos);
00258       }   
00259    }
00260 }
00261 
00262 //The Class UnitInfoLayer paint informations about the health and the fuel on the top of the unit
00263 class UnitInfoLayer : public MapLayer {
00264 
00265    Surface& image;
00266    void paintBar( const MapRenderer::FieldRenderInfo& fieldInfo, const SPoint& pos, int position, int max, int FromTop, int color, bool OverrideColor  )
00267    {
00268            float FlLength = ((float)29 / (float)max * position);
00269            int length = int(floor(FlLength));
00270            // int maxlength = 29;
00271            int paintcolor;
00272            if (OverrideColor == true) {
00273                    if (length > 20)
00274                            paintcolor = 0x00FF04;
00275                    else if (length > 10)
00276                            paintcolor = 0xFBFF00;
00277                    else if (length >= 0)
00278                            paintcolor = 0xFF0400;
00279            }
00280            else paintcolor = color;
00281        paintFilledRectangle<4>( fieldInfo.surface, SPoint( pos.x + 9 , pos.y + FromTop), length, 3,  ColorMerger_ColoredOverwrite<4>( paintcolor ) );
00282    };
00283 
00284 
00285    public: 
00286       UnitInfoLayer() : image ( IconRepository::getIcon("unitinfobg.png")) {} ;
00287       bool onLayer( int layer ) { return layer == 17; };
00288       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00289 };
00290 
00291 void UnitInfoLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00292 {
00293 
00294 
00295      if ( fieldInfo.visibility > visible_ago) {
00296        if ( fieldInfo.fld->vehicle ) {
00297            if ( ( fieldInfo.fld->vehicle->getOwner() == fieldInfo.playerView ) || (fieldInfo.visibility == visible_all) || ((fieldInfo.fld->vehicle->height >= chschwimmend) && (fieldInfo.fld->vehicle->height <= chhochfliegend))) {
00298           MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaMerge> blitter;
00299                         //paint the BGimage
00300                         blitter.blit( image, fieldInfo.surface, pos);
00301                         //paint the bars
00302                         //1. damage / health
00303                         paintBar( fieldInfo, pos, 100-fieldInfo.fld->vehicle->damage, 100, 1,  0, true );
00304                         //2. fuel
00305                         paintBar( fieldInfo, pos, fieldInfo.fld->vehicle->getTank().fuel, fieldInfo.fld->vehicle->getStorageCapacity().fuel, 4,  0xFFB700, false );
00306          }
00307       }   
00308    }
00309 }
00310 
00311 //The class UnitTraining paints the traininglevel at the bottom of the unit
00312 class UnitTrainingLayer : public MapLayer {
00313 
00314    public: 
00315       bool onLayer( int layer ) { return layer == 17; };
00316       void paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos );
00317 };
00318 
00319 
00320 void UnitTrainingLayer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00321 {
00322     if ( fieldInfo.visibility > visible_ago) {
00323       if ( fieldInfo.fld->vehicle ) {
00324            if ( ( fieldInfo.fld->vehicle->getOwner() == fieldInfo.playerView ) || (fieldInfo.visibility == visible_all) || ((fieldInfo.fld->vehicle->height >= chschwimmend) && (fieldInfo.fld->vehicle->height <= chhochfliegend))) {
00325 
00326          MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaMerge> blitter;
00327                 ASCString training = "unitlevel-" + ASCString::toString(fieldInfo.fld->vehicle->experience+1) +".png";
00328                 blitter.blit( IconRepository::getIcon(training), fieldInfo.surface, pos);
00329            }
00330          
00331       }   
00332    }
00333 }
00334 
00335 class WeaponRange : public SearchFields
00336 {
00337    public:
00338       int run ( const Vehicle* veh );
00339       void testfield ( const MapCoordinate& mc )
00340       {
00341          gamemap->getField( mc )->tempw = 1;
00342       };
00343       WeaponRange ( GameMap* _gamemap ) : SearchFields ( _gamemap )
00344       {}
00345       ;
00346 };
00347 
00348 int  WeaponRange :: run ( const Vehicle* veh )
00349 {
00350    int found = 0;
00351    if ( fieldvisiblenow ( getfield ( veh->xpos, veh->ypos )))
00352       for ( int i = 0; i < veh->typ->weapons.count; i++ ) {
00353          if ( veh->typ->weapons.weapon[i].shootable() ) {
00354             initsearch ( veh->getPosition(), veh->typ->weapons.weapon[i].maxdistance/minmalq, (veh->typ->weapons.weapon[i].mindistance+maxmalq-1)/maxmalq );
00355             startsearch();
00356             found++;
00357          }
00358       }
00359    return found;
00360 }
00361 
00362 
00363  
00364 
00365 
00366 MapRenderer::ViewPort::ViewPort( int x1, int y1, int x2, int y2 ) 
00367 { 
00368    this->x1 = x1; 
00369    this->y1 = y1; 
00370    this->x2 = x2; 
00371    this->y2 = y2; 
00372 };
00373 
00374 MapRenderer::ViewPort::ViewPort()
00375 {
00376 };
00377 
00378 MapRenderer :: MapRenderer()  
00379 { 
00380    readData(); 
00381 };
00382 
00383 
00384 void MapRenderer::readData()
00385 {
00386    if ( !icons.mapBackground.valid() ) {
00387       icons.mapBackground = IconRepository::getIcon("mapbkgr.raw");
00388       icons.notVisible    = IconRepository::getIcon("hexinvis.raw");
00389       icons.markField     = IconRepository::getIcon("markedfield.png");
00390       icons.markField.detectColorKey();
00391       icons.markFieldDark = IconRepository::getIcon("markedfielddark.png");
00392    }
00393 }
00394 
00395 
00396 /*
00397   layer:
00398     0: terrain
00399     1: below everything objects
00400     2: deep submerged units and building
00401     3: deep submerged objects
00402     4: submerged units and buildings
00403     5: submerged objects
00404     6: floating  units and buildings
00405     7: floating  objects
00406     8: ground    units and buildings
00407     9: ground    objects
00408    10: low flying units and buildings
00409    11: low flying objects
00410    12: flying units and buildings
00411    13: flying objects
00412    14: high flying units and buildings
00413    15: high flying objects
00414    16: orbiting units
00415    17: orbiting objects
00416    18  view obstructions
00417 */
00418 
00419 int MapRenderer::bitmappedHeight2pass( int height )
00420 {
00421    return getFirstBit(height) * 2 + 2;
00422 }
00423 
00424 
00425 void MapRenderer::paintSingleField( const MapRenderer::FieldRenderInfo& fieldInfo,  int layer, const SPoint& pos )
00426 {
00427 
00428    int binaryUnitHeight = 0;
00429    if ( layer > 1 ) 
00430       if ( !(layer & 1 ))
00431          binaryUnitHeight = 1 << (( layer-2)/2);
00432    
00433    MapField* fld = fieldInfo.fld;
00434 
00435    if ( layer == 0 && fieldInfo.visibility >= visible_ago )
00436       fld->typ->paint ( fieldInfo.surface, pos );
00437 
00438 
00439    if ( fieldInfo.visibility > visible_ago ) {
00440 
00441       /* display buildings */
00442       if ( fld->building  &&  (fld->building->typ->height & binaryUnitHeight) && fld->building->visible )
00443          if ((fieldInfo.visibility == visible_all) || (fld->building->typ->height >= chschwimmend) || ( fld->building->getOwner() == fieldInfo.playerView ))
00444             fld->building->paintSingleField( fieldInfo.surface, pos, fld->building->getLocalCoordinate( fieldInfo.pos ));
00445 
00446 
00447       /* display units */
00448       if ( fld->vehicle  &&  (fld->vehicle->height == binaryUnitHeight))
00449          if ( ( fld->vehicle->getOwner() == fieldInfo.playerView ) || (fieldInfo.visibility == visible_all) || ((fld->vehicle->height >= chschwimmend) && (fld->vehicle->height <= chhochfliegend)))
00450             fld->vehicle->paint( fieldInfo.surface, pos );
00451 
00452    }
00453 
00454    // display objects
00455    if ( layer & 1 )
00456       for ( MapField::ObjectContainer::iterator o = fld->objects.begin(); o != fld->objects.end(); o++ ) {
00457          int h = o->typ->imageHeight;
00458          if ( fieldInfo.visibility > visible_ago || (o->typ->visibleago && fieldInfo.visibility >= visible_ago ))
00459             if (  h >= ((layer-1)/2)*30 && h < (layer-1)/2*30+30 )
00460                o->display ( fieldInfo.surface, pos, fld->getWeather() );
00461       }
00462 
00463 
00464 
00465 
00466    if ( fieldInfo.visibility > visible_ago ) {
00467       /* display mines */
00468       
00469       if ( fieldInfo.visibility == visible_all )
00470          if ( !fld->mines.empty() && layer == 7 ) {
00471             for ( MapField::MineContainer::const_iterator i = fld->mines.begin(); i != fld->mines.end(); ++i )
00472                i->paint( fieldInfo.surface, pos );
00473          }
00474      
00475 
00476 
00477       /* display marked fields */
00478 
00479       if ( layer == 18 ) {
00480          if ( fld->a.temp && tempsvisible )
00481             fieldInfo.surface.Blit( icons.markField, pos );
00482          else
00483             if ( fld->a.temp2 && tempsvisible )
00484                fieldInfo.surface.Blit( icons.markFieldDark, pos );
00485       }
00486 
00487 
00488    } else {
00489       if (fieldInfo.visibility == visible_ago ) {
00490          if ( fld->building  &&  (fld->building->typ->height & binaryUnitHeight) && fld->building->visible )
00491             if ((fieldInfo.visibility == visible_all) || (fld->building->typ->height >= chschwimmend) || ( fld->building->getOwner() == fieldInfo.playerView ))
00492                fld->building->paintSingleField( fieldInfo.surface, pos, fld->building->getLocalCoordinate( fieldInfo.pos ));
00493 
00494       }
00495    }
00496 
00497 
00498    // display view obstructions
00499    if ( layer == 18 ) {
00500       if ( fieldInfo.visibility == visible_ago) {
00501          MegaBlitter<1,colorDepth,ColorTransform_None,ColorMerger_AlphaShadow> blitter;
00502          // PG_Point pnt = ClientToScreen( 0,0 );
00503          blitter.blit( icons.notVisible, fieldInfo.surface, pos);
00504          /*
00505                          // putspriteimage( r + unitrightshift , yp + unitdownshift , view.va8);
00506                          putshadow( r, yp, icons.view.nv8, &xlattables.a.dark2 );
00507                          if ( fld->a.temp && tempsvisible )
00508                             putspriteimage(  r, yp, cursor.markfield);
00509                          else
00510                             if ( fld->a.temp2 && tempsvisible )
00511                                putspriteimage(  r, yp, xlatpict ( &xlattables.a.dark2 , cursor.markfield));
00512           
00513          */
00514       } else
00515          if ( fieldInfo.visibility == visible_not) {
00516             fieldInfo.surface.Blit( icons.notVisible, pos );
00517             /*
00518                             if ( ( fld->a.temp || fld->a.temp2 ) && tempsvisible )
00519                                   putspriteimage(  r, yp, cursor.markfield);
00520             */
00521 
00522          }
00523 
00524    }
00525    
00526    for ( LayerRenderer::iterator i = layerRenderer.begin(); i != layerRenderer.end(); ++i )
00527       if ( (*i)->isActive() && (*i)->onLayer(layer))
00528          (*i)->paintSingleField( fieldInfo , layer, pos );
00529 
00530 }
00531 
00532 
00533 void MapRenderer::paintBackground( Surface& surf, const ViewPort& viewPort )
00534 {
00535    for (int y= viewPort.y1; y < viewPort.y2; ++y )
00536       for ( int x=viewPort.x1; x < viewPort.x2; ++x ) 
00537          paintBackgroundField( surf, getFieldPos(x,y) );
00538 }
00539 
00540 void MapRenderer::paintBackgroundField( Surface& surf, SPoint pos )
00541 {
00542    surf.Blit( icons.mapBackground, pos );
00543 }
00544 
00545 
00546 
00547 void MapRenderer::paintTerrain( Surface& surf, GameMap* actmap, int playerView, const ViewPort& viewPort, const MapCoordinate& offset )
00548 {
00549    FieldRenderInfo fieldRenderInfo( surf, actmap );
00550    fieldRenderInfo.playerView = playerView;
00551 
00552    GraphicSetManager::Instance().setActive ( actmap->graphicset );
00553 
00554    for (int pass = 0; pass <= 18 ;pass++ ) {
00555       for (int y= viewPort.y1; y < viewPort.y2; ++y )
00556          for ( int x=viewPort.x1; x < viewPort.x2; ++x ) {
00557             fieldRenderInfo.pos = MapCoordinate( offset.x + x, offset.y + y ); 
00558             fieldRenderInfo.fld = actmap->getField ( fieldRenderInfo.pos );
00559             SPoint pos = getFieldPos(x,y);
00560             if ( fieldRenderInfo.fld ) {
00561                fieldRenderInfo.visibility = fieldVisibility ( fieldRenderInfo.fld, playerView );
00562                paintSingleField( fieldRenderInfo, pass, pos );
00563             } else
00564                if ( pass == 0 )
00565                   paintBackgroundField( surf, pos );
00566 
00567          }
00568       additionalItemDisplayHook( surf, pass );
00569    }
00570    
00571 }
00572 
00573 
00574 
00575 void benchMapDisplay()
00576 {/*
00577    int t = ticker;
00578    for ( int i = 0; i < 20; ++i )
00579       repaintMap();
00580 
00581    int t2 = ticker;
00582    
00583    for ( int i = 0; i< 20; ++i)
00584       theGlobalMapDisplay->Redraw();
00585    
00586    int t3 = ticker;
00587 
00588    ASCString s;
00589    s.format("update map: %d \nupdate widget: %d \n%f fps", t2-t,t3-t2, 20.0 / float(t3-t) * 100 );
00590    displaymessage(s, 1 );
00591    */
00592 }
00593 
00594 
00595 MapDisplayPG* MapDisplayPG::theMapDisplay = NULL;
00596 MapDisplayPG* theGlobalMapDisplay = NULL;
00597 
00598 MapDisplayPG::MapDisplayPG ( MainScreenWidget *parent, const PG_Rect r )
00599       : PG_Widget ( parent, r, false ) ,
00600       zoom(-1),
00601       surface(NULL),
00602       lastDisplayedMap(NULL),
00603       offset(0,0),
00604       dirty(Map),
00605       additionalUnit(NULL),
00606       disableKeyboardCursorMovement(false),
00607       signalPrio(0),
00608       cursor(this),
00609       lock(0)
00610 {
00611    SetDirtyUpdate(true);
00612    dataLoaderTicker();
00613    
00614    readData();
00615    
00616    dataLoaderTicker();
00617    
00618    setNewZoom( CGameOptions::Instance()->mapzoom );
00619 
00620    repaintMap.connect( SigC::slot( *this, &MapDisplayPG::updateWidget ));
00621 
00622    PG_Application::GetApp()->sigKeyDown.connect( SigC::slot( *this, &MapDisplayPG::keyboardHandler ));
00623 
00624    SetName( "THEMapDisplay");
00625 
00626    dataLoaderTicker();
00627    SDL_Surface* ws = GetWidgetSurface ();
00628    if ( ws ) {
00629       Surface s = Surface::Wrap( ws );
00630       s.assignDefaultPalette();
00631    }
00632    
00633    MapRenderer::additionalItemDisplayHook.connect( SigC::slot( *this, &MapDisplayPG::displayAddons ));
00634    
00635    upperLeftSourceBlitCorner = SPoint( getFieldPosX(0,0), getFieldPosY(0,0));
00636 
00637    theMapDisplay = this;
00638    theGlobalMapDisplay = this;
00639    dataLoaderTicker();
00640    
00641    addMapLayer( new ResourceGraphLayer(), "resources" );
00642    addMapLayer( new ContainerInfoLayer(), "container" );
00643    addMapLayer( new PipeLayer()         , "pipes" );
00644    addMapLayer( new ReactionFireLayer() , "reactionfire" );
00645    addMapLayer( new UnitInfoLayer()     , "unitinfo" );
00646    addMapLayer( new UnitTrainingLayer() , "unittraining" );
00647 
00648    parent->lockOptionsChanged.connect( SigC::slot( *this, &MapDisplayPG::lockOptionsChanged ));
00649    GameMap::sigMapDeletion.connect( SigC::slot( *this, &MapDisplayPG::sigMapDeleted ));
00650 }
00651 
00652 
00653 
00654 void MapDisplayPG::lockOptionsChanged( int options )
00655 {
00656    if ( options & MainScreenWidget::LockOptions::MapControl )  
00657       EnableReceiver(false);
00658    else  
00659       EnableReceiver(true);
00660 }
00661 
00662 void MapDisplayPG::sigMapDeleted( GameMap& deletedMap )
00663 {
00664    if ( &deletedMap == lastDisplayedMap ) { 
00665       paintBackground();
00666       Update();
00667    }
00668 }
00669 
00670 
00671 MapDisplayPG::~MapDisplayPG ()
00672 {
00673    if ( surface ) {
00674       delete surface;
00675       surface = NULL;
00676    }
00677 }
00678 
00679 
00680 MapDisplayPG::Icons MapDisplayPG::icons;
00681 
00682 
00683 void MapDisplayPG::readData()
00684 {
00685    if ( !icons.cursor.valid() ) {
00686       icons.cursor = IconRepository::getIcon( "curshex.png" );
00687       icons.fieldShape = IconRepository::getIcon("hexinvis.raw");
00688    }
00689 }
00690 
00691 
00692 void MapDisplayPG::setNewZoom( int zoom )
00693 {
00694    if ( zoom > 100 )
00695       zoom = 100;
00696    if ( zoom < 20 )
00697       zoom = 20;
00698 
00699    if ( zoom == this->zoom )
00700       return;
00701    
00702    this->zoom = zoom;
00703 
00704    field.numx = int( ceil(float(Width()) * 100  / zoom / fielddistx) );
00705    field.numy = int( ceil(float(Height()) * 100 / zoom / fielddisty) );
00706 
00707    field.viewPort.x1 = -1;
00708    field.viewPort.y1 = -1;
00709    field.viewPort.x2 = field.numx + 1;
00710    field.viewPort.y2 = field.numy + 1;
00711 
00712    if ( field.numy & 1 )
00713       field.numy += 1;
00714 
00715    delete surface;
00716    surface = new Surface( Surface::createSurface ( field.numx * fielddistx + 2 * surfaceBorder, (field.numy - 1) * fielddisty + fieldysize +  2 * surfaceBorder, colorDepth*8 ));
00717 
00718    dirty = Map;
00719    if ( zoom != CGameOptions::Instance()->mapzoom ) {
00720       CGameOptions::Instance()->mapzoom = zoom;
00721       CGameOptions::Instance()->setChanged();
00722    }
00723    newZoom( zoom );
00724 }
00725 
00726 
00727 void MapDisplayPG::fillSurface( int playerView )
00728 {
00729    checkViewPosition( offset );
00730    if ( !lock ) {
00731       paintTerrain( *surface, actmap, playerView, field.viewPort, offset );
00732       lastDisplayedMap = actmap;
00733    }
00734    else
00735       paintBackground();
00736    dirty = Curs;
00737 }
00738 
00739 void MapDisplayPG::paintBackground( )
00740 {
00741    MapRenderer::paintBackground( *surface, field.viewPort );
00742    lastDisplayedMap = NULL;
00743 }
00744 
00745 
00746 
00747 void MapDisplayPG::checkViewPosition( MapCoordinate& offset )
00748 {
00749    if ( offset.x + field.numx >= actmap->xsize +1 )
00750       offset.x = max(0,actmap->xsize - field.numx +1 );
00751 
00752    if ( offset.y + field.numy >= actmap->ysize +4)
00753       offset.y = max(0,actmap->ysize - field.numy +4);
00754 
00755    if ( offset.y & 1 )
00756       offset.y -= 1;
00757 
00758    if ( offset.x < 0 )
00759       offset.x = 0;
00760 
00761    if ( offset.y < 0 )
00762       offset.y = 0;
00763 }
00764 
00765 
00766 
00767 
00768 template<int pixelSize>
00769 class PixSel : public SourcePixelSelector_CacheZoom<pixelSize, SourcePixelSelector_DirectRectangle<pixelSize> >
00770 {}
00771 ;
00772 
00773 
00774 void MapDisplayPG::updateMap(bool force )
00775 {
00776    if ( !actmap )
00777       return;
00778       
00779    if ( dirty > Curs || force ) 
00780       fillSurface( actmap->getPlayerView() );
00781 }
00782 
00783 void MapDisplayPG::updateWidget()
00784 {
00785    updateMap(true);
00786    Update(true);
00787 }
00788 
00789 
00790 
00791 void MapDisplayPG::blitInternalSurface( SDL_Surface* dest, const SPoint& pnt, const PG_Rect& dstClip )
00792 {
00793    if ( zoom != 100 ) {
00794       float fzoom = float(zoom) / 100.0;
00795       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,PixSel,TargetPixelSelector_Rect> blitter;
00796       blitter.setZoom( fzoom );
00797       blitter.initSource( *surface );
00798 
00799       // SourcePixelSelector
00800       blitter.setSrcRectangle( upperLeftSourceBlitCorner, int(float(Width()) / fzoom), int(float(Height()) / fzoom));
00801 
00802       PG_Rect clip= dstClip.IntersectRect( dest->clip_rect );
00803       blitter.setTargetRect( clip );
00804       
00805       Surface s = Surface::Wrap( dest );
00806       blitter.blit( *surface, s, SPoint(pnt.x, pnt.y ));
00807    } else {
00808       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectRectangle,TargetPixelSelector_Rect> blitter;
00809       blitter.initSource( *surface );
00810       
00811       // SourcePixelSelector
00812       blitter.setSrcRectangle( upperLeftSourceBlitCorner, Width(), Height() );
00813       
00814       PG_Rect clip= dstClip.IntersectRect( dest->clip_rect );
00815       blitter.setTargetRect( clip );
00816       
00817       Surface s = Surface::Wrap( dest );
00818       blitter.blit( *surface, s, SPoint(pnt.x, pnt.y ));
00819    }   
00820    
00821 }
00822 
00823 
00824 void MapDisplayPG::displayCursor()
00825 {
00826    displayCursor( *this );
00827 }
00828 
00829 void MapDisplayPG::displayCursor( const PG_Rect& dst )
00830 {
00831    if ( !actmap )
00832       return;
00833 
00834    if ( dst.w <= 0 || dst.h <= 0 )
00835       return;
00836       
00837    int x = cursor.pos().x - offset.x;
00838    int y = cursor.pos().y  - offset.y;
00839    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 ) {
00840       // surface->Blit( icons.cursor, getFieldPos(x,y));
00841       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectZoom,TargetPixelSelector_Rect> blitter;
00842       blitter.setZoom( float(zoom) / 100.0 );
00843 
00844       PG_Rect clip= dst.IntersectRect( PG_Application::GetScreen()->clip_rect );
00845 
00846       if ( clip.w && clip.h ) {
00847          blitter.setTargetRect ( clip );
00848    
00849          Surface s = Surface::Wrap( PG_Application::GetScreen() );
00850          SPoint pos = widget2screen ( internal2widget( mapViewPos2internalPos( MapCoordinate(x,y))));
00851          blitter.blit( icons.cursor, s, pos );
00852       }
00853    }
00854 }
00855 
00856 
00857 void MapDisplayPG::UpdateRect( const PG_Rect& rect )
00858 {
00859    SPoint p = widget2screen (  SPoint( rect.x, rect.y));
00860    PG_Rect sc ( p.x, p.y, rect.w, rect.h );
00861    sc = sc.IntersectRect( *this );
00862    eventBlit( GetWidgetSurface (), rect, sc );
00863    if ( sc.w && sc.h )
00864       PG_Application::UpdateRect(PG_Application::GetScreen(), sc.x, sc.y, sc.w, sc.h );
00865 }
00866 
00867 
00868 void MapDisplayPG::eventBlit(SDL_Surface* srf, const PG_Rect& src, const PG_Rect& dst)
00869 {
00870    if ( !GetWidgetSurface ()) {
00871       if ( dirty > Nothing )
00872          updateMap();
00873 
00874       PG_Point pnt = ClientToScreen( 0,0 );
00875       blitInternalSurface( PG_Application::GetScreen(), SPoint(pnt.x,pnt.y), dst );
00876    } else {
00877       PG_Widget::eventBlit(srf,src,dst);
00878    }
00879 
00880    if ( !cursor.invisible )
00881       displayCursor( dst );
00882 
00883 
00884 }
00885 
00886 
00887 SPoint MapDisplayPG::mapGlobalPos2internalPos ( const MapCoordinate& pos )
00888 {
00889    return getFieldPos( pos.x - offset.x, pos.y - offset.y );
00890 }
00891 
00892 SPoint MapDisplayPG::mapViewPos2internalPos ( const MapCoordinate& pos )
00893 {
00894    return getFieldPos( pos.x, pos.y );
00895 }
00896 
00897 
00898 SPoint MapDisplayPG::internal2widget( const SPoint& pos )
00899 {
00900    return SPoint( int(ceil(float(pos.x - surfaceBorder) * zoom / 100.0)), int(ceil(float(pos.y - surfaceBorder) * zoom / 100.0)));
00901 }
00902 
00903 SPoint MapDisplayPG::widget2screen( const SPoint& pos )
00904 {
00905    PG_Point p = ClientToScreen ( pos.x, pos.y );
00906    return SPoint ( p.x, p.y );
00907 }
00908 
00909 
00910 MapCoordinate MapDisplayPG::screenPos2mapPos( const SPoint& pos )
00911 {
00912    PG_Point pnt = ScreenToClient( pos.x, pos.y );
00913    if ( pnt.x >= 0 && pnt.y >= 0 && pnt.x < Width() && pnt.y < Height() )
00914       return widgetPos2mapPos ( SPoint( pnt.x, pnt.y ));
00915    else
00916       return MapCoordinate();
00917 }
00918 
00919 MapCoordinate MapDisplayPG::widgetPos2mapPos( const SPoint& pos )
00920 {
00921    int x = int( float(pos.x) * 100 / zoom ) + surfaceBorder;
00922    int y = int( float(pos.y) * 100 / zoom ) + surfaceBorder;
00923 
00924    for (int yy= field.viewPort.y1; yy < field.viewPort.y2; ++yy )
00925       for ( int xx=field.viewPort.x1; xx < field.viewPort.x2; ++xx ) {
00926          int x1 = getFieldPosX(xx,yy);
00927          int y1 = getFieldPosY(xx,yy);
00928          if ( x >= x1 && x < x1+ fieldsizex && y >= y1 && y < y1+fieldsizey )
00929             if ( icons.fieldShape.GetPixel(x-x1,y-y1) != 255 )
00930                return MapCoordinate(xx+offset.x,yy+offset.y);
00931       }
00932 
00933    return MapCoordinate();
00934 }
00935 
00936 MapCoordinate MapDisplayPG::upperLeftCorner()
00937 {
00938    return offset;       
00939 }
00940 
00941 MapCoordinate MapDisplayPG::lowerRightCorner()
00942 {
00943    return MapCoordinate( offset.x + field.numx , offset.y + field.numy );
00944 }
00945 
00946 
00947 bool MapDisplayPG::centerOnField( const MapCoordinate& mc )
00948 {
00949    if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
00950       return false;
00951       
00952    MapCoordinate newpos ( mc.x - field.numx / 2,  mc.y - field.numy / 2 );
00953 
00954    checkViewPosition( newpos );
00955 
00956    if ( newpos != offset  ) {
00957       offset = newpos;
00958       dirty = Map;
00959       Redraw();
00960       viewChanged();
00961    }
00962    return true;
00963 
00964 }
00965 
00966 void MapDisplayPG::redrawMapAtCursor ( const MapCoordinate& oldpos )
00967 {
00968    if ( oldpos.valid() ) {
00969       SPoint p = internal2widget( mapGlobalPos2internalPos( oldpos ));
00970       UpdateRect( PG_Rect( p.x, p.y, fieldsizex, fieldsizey ) );
00971    }
00972          
00973    SPoint p = internal2widget( mapGlobalPos2internalPos( cursor.pos() ));
00974    UpdateRect( PG_Rect( p.x, p.y, fieldsizex, fieldsizey ) );
00975 }
00976 
00977 
00978 int MapDisplayPG::setSignalPriority( int priority )
00979 {
00980    int old = signalPrio;
00981    signalPrio = priority;
00982    return old;
00983 }
00984 
00985 void filterQueuedZoomEvents()
00986 {
00987    SDL_Event event;
00988    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 ))
00989       PG_Application::GetEventSupplier()->PollEvent ( &event );
00990 }
00991 
00992 bool MapDisplayPG::eventMouseButtonDown (const SDL_MouseButtonEvent *button)
00993 {
00994    MapCoordinate mc = screenPos2mapPos( SPoint(button->x, button->y));
00995 
00996    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.zoomoutbutton ) {
00997       changeZoom( 10 );
00998    
00999       MapCoordinate newpos = screenPos2mapPos( SPoint(button->x, button->y));
01000       MapCoordinate newOffset ( offset.x - ( newpos.x - mc.x ), offset.y - ( newpos.y - mc.y ));
01001       checkViewPosition( newOffset );
01002       offset = newOffset;
01003 
01004       viewChanged();
01005       repaintMap();
01006       filterQueuedZoomEvents();
01007       return true;
01008    }
01009 
01010    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.zoominbutton ) {
01011       changeZoom( -10 );
01012 
01013       MapCoordinate newpos = screenPos2mapPos( SPoint(button->x, button->y));
01014       MapCoordinate newOffset ( offset.x - ( newpos.x - mc.x ), offset.y - ( newpos.y - mc.y ));
01015       checkViewPosition( newOffset );
01016       offset = newOffset;
01017 
01018       viewChanged();
01019       repaintMap();
01020       filterQueuedZoomEvents();
01021       return true;
01022    }
01023 
01024 
01025    if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
01026       return false;
01027 
01028    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.fieldmarkbutton ) {
01029       MapCoordinate oldpos = cursor.pos();
01030       bool changed = cursor.pos() != mc;
01031       cursor.pos() = mc;
01032       cursor.invisible = 0;
01033       dirty = Curs;
01034 
01035       updateFieldInfo();
01036 
01037       if ( changed )
01038          redrawMapAtCursor( oldpos );
01039 
01040       mouseButtonOnField( mc, SPoint(button->x, button->y), changed, button->button, signalPrio );
01041       return true;
01042       
01043    }
01044 
01045    if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == CGameOptions::Instance()->mouse.centerbutton ) {
01046       return centerOnField( mc );
01047    }
01048 
01049    mouseButtonOnField( mc, SPoint(button->x, button->y), false, button->button, signalPrio );
01050    
01051    return false;
01052 }
01053 
01054 bool MapDisplayPG::eventMouseMotion (const SDL_MouseMotionEvent *button)
01055 {
01056    MapCoordinate mc = screenPos2mapPos( SPoint(button->x, button->y));
01057    if ( !(mc.valid() && mc.x < actmap->xsize && mc.y < actmap->ysize ))
01058       return false;
01059       
01060    if ( button->type == SDL_MOUSEMOTION && (button->state == SDL_BUTTON( CGameOptions::Instance()->mouse.fieldmarkbutton) )) {
01061       bool changed = cursor.pos() != mc;
01062       if ( changed ) {
01063          MapCoordinate oldpos = cursor.pos();
01064          cursor.pos() = mc;
01065          cursor.invisible = 0;
01066          dirty = Curs;
01067 
01068          redrawMapAtCursor( oldpos );
01069          cursorMoved();
01070 
01071          mouseDraggedToField( mc, SPoint(button->x, button->y), changed, signalPrio );
01072    
01073          return true;
01074      }
01075    }
01076    return false;
01077 }
01078 
01079 
01080 bool MapDisplayPG::eventMouseButtonUp (const SDL_MouseButtonEvent *button)
01081 {
01082    return false;
01083 }
01084 
01085 
01086 bool MapDisplayPG::fieldCompletelyInViewX( const MapCoordinate& pos )
01087 {
01088    SPoint internal = mapGlobalPos2internalPos( pos);
01089    SPoint s = widget2screen( internal2widget( internal ));
01090    SPoint s2 = widget2screen( internal2widget( internal + SPoint(fieldsizex,fieldsizey) ));
01091    return s.x >= my_xpos && s2.x < my_xpos + my_width;
01092 }
01093 
01094 bool MapDisplayPG::fieldCompletelyInViewY( const MapCoordinate& pos )
01095 {
01096    SPoint internal = mapGlobalPos2internalPos( pos);
01097    SPoint s = widget2screen( internal2widget( internal ));
01098    SPoint s2 = widget2screen( internal2widget( internal + SPoint(fieldsizex,fieldsizey) ));
01099    return s.y >= my_ypos && s2.y < my_ypos + my_height;
01100 }
01101 
01102 bool MapDisplayPG::fieldCompletelyInView( const MapCoordinate& pos )
01103 {
01104    // for performance-reasons we don't call the above two methods
01105    SPoint internal = mapGlobalPos2internalPos( pos);
01106    SPoint s = widget2screen( internal2widget( internal ));
01107    SPoint s2 = widget2screen( internal2widget( internal + SPoint(fieldsizex,fieldsizey) ));
01108    return (s.y >= my_ypos && s2.y < my_ypos + my_height) && (s.x >= my_xpos && s2.x < my_xpos + my_width);
01109 
01110 }
01111 
01112 
01113 bool MapDisplayPG::fieldInView(const MapCoordinate& mc )
01114 {
01115    if ( mc.x < offset.x || mc.y < offset.y || mc.x >= offset.x + field.numx || mc.y >= offset.y +  field.numy || !fieldCompletelyInView(mc) )
01116       return false;
01117    else
01118       return true;
01119 }
01120 
01121 
01122 
01123 Surface MapDisplayPG::createMovementBufferSurface()
01124 {
01125    Surface s = Surface::createSurface( 2*surfaceBorder + effectiveMovementSurfaceWidth, 2*surfaceBorder + effectiveMovementSurfaceHeight, 8*colorDepth, 0x00ffffff ) ;
01126    s.SetColorKey( SDL_SRCCOLORKEY, 0xffffff);
01127    return s;
01128 }
01129 
01130 
01131 void MapDisplayPG::initMovementStructure()
01132 {
01133    if ( !movementMask[0].mask.valid() ) 
01134       for ( int dir = 0; dir < sidenum; ++dir ) {
01135          movementMask[dir].mask = createMovementBufferSurface();
01136          MapCoordinate start;
01137          if ( dir >= 2 && dir <= 4 )
01138             start = MapCoordinate( 1, 2 );
01139          else
01140             start = MapCoordinate( 1, 4 );
01141 
01142          MapCoordinate dest = getNeighbouringFieldCoordinate( start, dir );
01143 
01144          for ( int i = 0; i < sidenum; ++i)
01145             movementMask[dir].mask.Blit( icons.fieldShape, getFieldPos2( getNeighbouringFieldCoordinate( start, i )));
01146          for ( int i = 0; i < sidenum; ++i)
01147             movementMask[dir].mask.Blit( icons.fieldShape, getFieldPos2( getNeighbouringFieldCoordinate( dest, i )));
01148 
01149          SPoint pix = getFieldPos2( start );
01150          movementMask[dir].startFieldPos = pix;
01151 
01152          pix.x += fieldsizex/2;
01153          pix.y += fieldsizey/2;
01154          movementMask[dir].mask.SetColorKey( SDL_SRCCOLORKEY, movementMask[dir].mask.GetPixel( pix ) & ~movementMask[dir].mask.GetPixelFormat().Amask());
01155       }
01156 }
01157 
01158 
01159 template<int pixelsize>
01160 class SourcePixelSelector_DirectSubRectangle
01161 {
01162    typedef typename PixelSize2Type<pixelsize>::PixelType PixelType;
01163    int x,y,x1,y1;
01164    int w,h;
01165    PG_Rect innerRect;
01166    int outerwidth;
01167 
01168    const PixelType* pointer;
01169    const PixelType* startPointer;
01170    int pitch;
01171    int linelength;
01172    const Surface* surface;
01173    protected:
01174       SourcePixelSelector_DirectSubRectangle() : x(0),y(0),x1(0),y1(0),w(0),h(0),outerwidth(0),pointer(NULL), surface(NULL)
01175       {}
01176       ;
01177 
01178       int getWidth()
01179       {
01180          return min(w, surface->w() -x1 );
01181       };
01182       int getHeight()
01183       {
01184          return min(h, surface->h()-y1 );
01185       };
01186 
01187 
01188       void init ( const Surface& srv )
01189       {
01190          surface = &srv;
01191          startPointer = pointer = (const PixelType*)(srv.pixels());
01192          linelength = srv.pitch()/sizeof(PixelType);
01193          pitch = linelength - w -1  ;
01194          y = y1;
01195          x = x1;
01196          pointer += x1 + y1 * linelength;
01197          outerwidth = getWidth();
01198       };
01199 
01200       PixelType getPixel(int x, int y)
01201       {
01202          x += x1;
01203          y += y1;
01204          if ( x >= 0 && y >= 0 && x < surface->w() && y < surface->h() )
01205             return surface->GetPixel(SPoint(x,y));
01206          else
01207             return surface->GetPixelFormat().colorkey();
01208       };
01209 
01210 
01211       PixelType nextPixel()
01212       {
01213          ++x;
01214          return *(pointer++);
01215       };
01216 
01217 
01218       void skipWholeLine()
01219       {
01220          pointer += linelength;
01221          ++y;
01222       };
01223 
01224       void skipPixels( int pixNum )
01225       {
01226          pointer += pixNum;
01227          x += pixNum;
01228       };
01229 
01230       int getSourcePixelSkip()
01231       {
01232          if ( y < innerRect.y )
01233             return outerwidth - (x - x1);
01234          else
01235             if ( y >= innerRect.y + innerRect.h )
01236                return outerwidth - (x - x1);
01237             else
01238                if ( x < innerRect.x )
01239                   return innerRect.x - x;
01240                else
01241                   if ( x >= innerRect.x + innerRect.w )
01242                      return outerwidth - (x - x1);
01243                   else
01244                      return 0;
01245        
01246       };
01247       
01248       void nextLine()
01249       {
01250          pointer = startPointer + x1 + (y++) * linelength;
01251          x = x1;
01252       };
01253 
01254    public:
01255       void setSrcRectangle( SPoint pos, int width, int height )
01256       {
01257          x1 = pos.x;
01258          y1 = pos.y;
01259          w = width;
01260          h = height;
01261       };
01262       void setInnerSrcRectangle( const PG_Rect& rect )
01263       {
01264          innerRect = rect;
01265       };
01266 
01267 };
01268 
01269 template<int pixelSize>
01270 class MovePixSel : public SourcePixelSelector_CacheZoom<pixelSize, SourcePixelSelector_DirectSubRectangle<pixelSize> >
01271 {}
01272 ;
01273 
01274 
01275 void MapDisplayPG::displayMovementStep( Movement& movement, int percentage  )
01276 {
01277 #ifdef debugmapdisplay
01278    surface->Fill( 0xff00ff00);
01279 #endif
01280 
01281    FieldRenderInfo fieldRenderInfo( *surface, movement.veh->getMap() );
01282    fieldRenderInfo.playerView = movement.playerView;
01283    for (int pass = 0; pass <= 18 ;pass++ ) {
01284       for ( int i = 0; i < movement.actualFieldNum; ++i ) {
01285          SPoint pos = movement.touchedFields[i].surfPos;
01286          fieldRenderInfo.pos = movement.touchedFields[i].mapPos;
01287          fieldRenderInfo.fld = movement.actmap->getField ( fieldRenderInfo.pos );
01288          if ( fieldRenderInfo.fld ) {
01289             fieldRenderInfo.visibility = fieldVisibility ( fieldRenderInfo.fld, fieldRenderInfo.playerView );
01290 
01291             paintSingleField( fieldRenderInfo, pass, pos );
01292          }
01293       }
01294       
01295       if ( pass >= 2 && pass < 18 )
01296          if ( !(pass & 1 ))
01297             if ( movement.veh->height & (1 << (( pass-2)/2))) {
01298                SPoint pos;
01299                pos.x = movement.from.x + (movement.to.x - movement.from.x) * percentage/100;
01300                pos.y = movement.from.y + (movement.to.y - movement.from.y) * percentage/100;
01301                int shadow = 0;
01302                if ( movement.fromShadow >= 0 && movement.toShadow >= 0 )
01303                   shadow = movement.fromShadow + (movement.toShadow - movement.fromShadow) * percentage/100;
01304                movement.veh->paint( *surface, pos, false, shadow );
01305             }
01306    }
01307 
01308 #ifdef debugmapdisplay
01309    MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_Plain,TargetPixelSelector_Valid> alphaBlitter;
01310    alphaBlitter.blit( *movement.mask, *surface, movement.maskPosition);
01311 #endif
01312    
01313    PG_Rect targetArea  ( widget2screen( SPoint( 0, 0 )).x, widget2screen( SPoint( 0, 0 )).y, Width(), Height() );
01314    Surface s = Surface::Wrap( PG_Application::GetScreen() );
01315    
01316 #ifdef debugmapdisplay
01317    s.Fill( 0xff00ff );
01318 #endif
01319 
01320    if ( zoom != 100 ) {
01321       float fzoom = float(zoom) / 100.0;
01322       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,MovePixSel,TargetPixelSelector_Rect> blitter;
01323       blitter.setZoom( fzoom );
01324       blitter.initSource( *surface );
01325       
01326       blitter.setSrcRectangle( SPoint( getFieldPosX(0,0), getFieldPosY(0,0)), int(float(Width()) / fzoom), int(float(Height()) / fzoom));
01327       blitter.setInnerSrcRectangle( movement.blitViewPortInternal  );
01328       
01329       blitter.setTargetRect( targetArea );
01330       blitter.blit( *surface, s, movement.targetBlitPos );
01331    } else {
01332       MegaBlitter<colorDepth,colorDepth,ColorTransform_None,ColorMerger_AlphaOverwrite,SourcePixelSelector_DirectSubRectangle,TargetPixelSelector_Rect> blitter;
01333       blitter.initSource( *surface );
01334       
01335       blitter.setSrcRectangle( SPoint( getFieldPosX(0,0), getFieldPosY(0,0)), Width(), Height() );
01336       blitter.setInnerSrcRectangle( movement.blitViewPortInternal  );
01337       
01338       blitter.setTargetRect( targetArea  );
01339       blitter.blit( *surface, s, movement.targetBlitPos );
01340    }
01341 
01342 #ifdef debugmapdisplay
01343    rectangle<4>( s, SPoint(targetArea.x, targetArea.y), targetArea.w, targetArea.h, ColorMerger_ColoredOverwrite<4>( 0x00ffff ), ColorMerger_ColoredOverwrite<4>( 0x00ffff ) );
01344    rectangle<4>( s, SPoint(movement.blitViewPortScreen.x, movement.blitViewPortScreen.y), movement.blitViewPortScreen.w, movement.blitViewPortScreen.h, ColorMerger_ColoredOverwrite<4>( 0x0000ff ), ColorMerger_ColoredOverwrite<4>( 0x0000ff ) );
01345    PG_Application::UpdateRect(PG_Application::GetScreen(), 0, 0, PG_Application::GetScreen()->w, PG_Application::GetScreen()->h );
01346 #else   
01347    PG_Application::UpdateRect(PG_Application::GetScreen(), movement.blitViewPortScreen.x, movement.blitViewPortScreen.y, movement.blitViewPortScreen.w, movement.blitViewPortScreen.h );
01348 #endif
01349 }
01350 
01351 
01352 
01353 
01354 
01355 bool ccompare( const MapCoordinate& a, const MapCoordinate& b )
01356 {
01357    return a.y < b.y || (a.y == b.y && a.x < b.x);
01358 }   
01359 
01360 
01361 void MapDisplayPG::displayUnitMovement( GameMap* actmap, Vehicle* veh, const MapCoordinate3D& from, const MapCoordinate3D& to, int duration )
01362 {
01363    static int col = 0xff;
01364    
01365 #ifdef debugmapdisplay
01366    col += 30;
01367    if ( col > 255 )
01368       col -= 255;
01369 #endif
01370 
01371    surface->Fill( col << 8 );
01372    
01373    if ( !fieldInView( from ) && !fieldInView( to ))
01374       return;
01375 
01376    if ( from.x == to.x && from.y == to.y && from.getBitmappedHeight() <= chschwimmend && to.getBitmappedHeight() <= chschwimmend )
01377       // we don't animate a descending or ascending submarine without movement
01378       return;
01379 
01380    int startTime = ticker;
01381    int endTime = startTime + duration;
01382    
01383    // initialisation that is only executed the first time the code runs here
01384    initMovementStructure();
01385 
01386    int dir = getdirection( from, to );
01387    
01388    if ( from.x == to.x && from.y == to.y )
01389       dir = -1;  // changing height vertically
01390    else   
01391       veh->direction = dir;
01392    
01393    typedef vector< MapCoordinate > TouchedFields;
01394    TouchedFields touchedFields;
01395 
01396    touchedFields.push_back ( from );
01397    for ( int ii = 0; ii < sidenum; ++ii ) {
01398       MapCoordinate p = getNeighbouringFieldCoordinate(from, ii);
01399       if ( fieldInView( p ) )
01400          touchedFields.push_back ( p );
01401    }
01402       
01403    if ( dir != -1 ) {
01404       if ( fieldInView( to ))
01405          touchedFields.push_back ( to);
01406 
01407       for ( int ii = 0; ii < sidenum; ++ii ) {
01408          MapCoordinate p = getNeighbouringFieldCoordinate(to, ii);
01409          if ( fieldInView( p ) )
01410             touchedFields.push_back ( p );
01411       }
01412    }
01413    
01414 
01415    // now we have all fields that are touched during movement in a list
01416    // let's sort it
01417 
01418    sort(   touchedFields.begin(), touchedFields.end(), ccompare );
01419    
01420    Movement movement;
01421    int i = 0;
01422    for ( TouchedFields::iterator j = touchedFields.begin(); j != touchedFields.end(); ++j )  {
01423       if ( i == 0 || movement.touchedFields[i-1].mapPos != *j ) {
01424          movement.touchedFields[i].mapPos = *j;
01425          movement.touchedFields[i].surfPos = mapGlobalPos2internalPos( *j );
01426          ++i;
01427       }
01428    }
01429    movement.actualFieldNum = i;
01430            
01431    movement.veh = veh;
01432    movement.from = mapGlobalPos2internalPos( from );
01433    movement.to = mapGlobalPos2internalPos( to );
01434 
01435    const int maxShadowWidth = 32;
01436    SPoint p1 = SPoint( min( movement.from.x, movement.to.x), min( movement.from.y, movement.to.y) );
01437    movement.blitViewPortInternal  = PG_Rect( p1.x, p1.y, max( movement.from.x, movement.to.x) - p1.x + maxShadowWidth + fieldsizex,
01438                                                          max( movement.from.y, movement.to.y) - p1.y + maxShadowWidth + fieldsizey );
01439 
01440    movement.blitViewPortInternal = movement.blitViewPortInternal.IntersectRect( PG_Rect( 0, 0, surface->w(), surface->h() ) );
01441    movement.targetBlitPos = widget2screen ( SPoint( 0, 0));
01442    SPoint a = widget2screen( internal2widget( SPoint( movement.blitViewPortInternal.x, movement.blitViewPortInternal.y )));
01443    SPoint b = widget2screen( internal2widget( SPoint( movement.blitViewPortInternal.x + movement.blitViewPortInternal.w, movement.blitViewPortInternal.y + movement.blitViewPortInternal.h )));
01444 
01445    
01446    movement.blitViewPortScreen = PG_Rect( a.x, a.y, b.x - a.x + 1, b.y - a.y + 1 );
01447    movement.blitViewPortScreen = movement.blitViewPortScreen.IntersectRect( PG_Rect( 0, 0, PG_Application::GetScreenWidth(), PG_Application::GetScreenHeight() ));
01448 
01449    movement.toShadow  = ContainerBase::calcShadowDist( to.getNumericalHeight() );
01450    movement.fromShadow  = ContainerBase::calcShadowDist( from.getNumericalHeight() );
01451    
01452    movement.actmap = actmap;
01453    
01454    if ( dir < 0 ) {
01455       movement.mask = &movementMask[0].mask;
01456       movement.maskPosition = mapGlobalPos2internalPos( from ) -  movementMask[0].startFieldPos;
01457    } else {
01458       movement.mask = &movementMask[dir].mask;
01459       movement.maskPosition = mapGlobalPos2internalPos( from ) -  movementMask[dir].startFieldPos;
01460    }
01461    
01462    movement.playerView = actmap->getPlayerView();
01463    
01464    int loopCounter = 0;
01465 #ifdef debugmapdisplay
01466    int loopStartTicker = ticker;
01467 #endif
01468 
01469    while ( ticker < endTime ) {
01470       displayMovementStep( movement, (ticker - startTime) * 100 / duration );
01471       ++loopCounter;
01472    }
01473 
01474    if( duration )
01475       displayMovementStep( movement, 100 );
01476    
01477 #ifdef debugmapdisplay
01478    cout << (float(loopCounter) / float(ticker - loopStartTicker) * 100) << " / " << (float(loopCounter) / float(ticker - startTime) * 100) << " fps \n";
01479 #endif
01480 }
01481 
01482 void MapDisplayPG::displayAddons( Surface& surf, int pass)
01483 {
01484    if( additionalUnit ) 
01485       if ( pass == bitmappedHeight2pass( additionalUnit->height ) )  {
01486          SPoint p = mapViewPos2internalPos( additionalUnit->getPosition() - offset );
01487          if ( p.x >= 0 && p.y >= 0 && p.x + fieldsizex + ContainerBase::calcShadowDist(getFirstBit(chsatellit)) < surf.w() && p.y + fieldsizey  + ContainerBase::calcShadowDist(getFirstBit(chsatellit)) < surf.h() )
01488             additionalUnit->paint( surf, p, false, -1 );
01489       }
01490 
01491 }
01492 
01493 MapCoordinate& MapDisplayPG::Cursor::pos()
01494 {
01495    if ( actmap )
01496       return actmap->getCursor();
01497    else {
01498       static MapCoordinate mc;
01499       return mc;
01500    }
01501 }
01502 
01503 void MapDisplayPG::scrollMap( int dir )
01504 {
01505    if ( !actmap )
01506       return;
01507 
01508    MapCoordinate oldOffset = offset;
01509 
01510    const int stepWidth = 2;
01511 
01512 
01513    if ( dir == 7 || dir == 0 || dir == 1 )
01514       offset.y -= 2 * stepWidth;
01515 
01516    if ( dir >= 1 && dir <= 3 )
01517       offset.x += stepWidth;
01518 
01519    if ( dir >= 3 && dir <= 5 )
01520       offset.y += 2 * stepWidth;
01521 
01522    if ( dir >= 5 && dir <= 7)
01523       offset.x -= stepWidth;
01524    
01525    checkViewPosition( offset );
01526 
01527    if ( offset != oldOffset ) {
01528       dirty = Map;
01529       Update();
01530       viewChanged();
01531    }
01532 }
01533 
01534 
01535 void MapDisplayPG::moveCursor( int dir, int step )
01536 {
01537    MapCoordinate pos = cursor.pos();
01538 
01539    switch ( dir ) {
01540       case 0:  pos.y -= 2 * step;
01541                break;
01542       case 1:  pos.y -= 1 * step;
01543                if ( !(pos.y & 1) )
01544                   pos.x += 1 * step;
01545                break;         
01546       case 2:  if ( step & 1 ) {
01547                   if ( pos.y & 1 ) {
01548                      if ( pos.x < actmap->xsize-1 ) {
01549                         pos.x += 1 * step;
01550                         pos.y -= 1 * step;
01551                      }
01552                   } else
01553                      pos.y += 1 * step;
01554                } else
01555                   pos.x += step/2;
01556                break;
01557       case 3:  pos.y += 1 * step;
01558                if ( !(pos.y & 1) )
01559                   pos.x += 1 * step;
01560                break;
01561       case 4:  pos.y += 2 * step;
01562                break;
01563       case 5:  pos.y += 1 * step;
01564                if ( pos.y & 1 )
01565                   pos.x -= 1 * step;
01566                break;
01567       case 6:  if ( step & 1) {
01568                   if ( pos.y & 1 ) {
01569                      pos.y -= 1 * step;
01570                   } else {
01571                      if ( pos.x > 0 ) {
01572                         pos.x -= 1 * step;
01573                         pos.y += 1 * step;
01574                      }
01575                   }
01576                } else
01577                   pos.x -= step/2;
01578                break;
01579       case 7:  pos.y -= 1 * step;
01580                if ( pos.y & 1 )
01581                   pos.x -= 1 * step;
01582                break;
01583    }
01584 
01585    if ( pos.x >= actmap->xsize )
01586       pos.x = actmap->xsize -1;
01587 
01588    if ( pos.x < 0 )
01589       pos.x = 0;
01590 
01591    if ( pos.y >= actmap->ysize )
01592       pos.y = actmap->ysize -1;
01593 
01594    if ( pos.y < 0 )
01595       pos.y = 0;
01596 
01597    if ( pos != cursor.pos() ) {
01598       MapCoordinate oldpos = cursor.pos();
01599       cursor.invisible = 0;
01600       dirty = Curs;
01601 
01602       cursor.pos() = pos;
01603 
01604       MapCoordinate oldOffset = offset;
01605 
01606       if ( pos.x < offset.x )
01607          offset.x = max( 0, pos.x );
01608 
01609       if ( pos.y < offset.y )
01610          offset.y = min( 0, pos.y & ~1);
01611 
01612       if ( pos.x > offset.x + field.numx - 2  || !fieldCompletelyInViewX( pos ))
01613          offset.x = pos.x - field.numx + 6;
01614 
01615       if ( pos.y > offset.y + field.numy - 2 || !fieldCompletelyInViewY( pos ))
01616          offset.y = (pos.y - field.numy + 8) & ~1;
01617 
01618       if ( offset != oldOffset )
01619          dirty = Map;
01620 
01621       checkViewPosition( offset );
01622       
01623       cursorMoved();
01624       if ( offset != oldOffset ) {
01625          Update();
01626          viewChanged();
01627       } else {
01628          redrawMapAtCursor( oldpos );
01629          /*
01630          SPoint p = internal2widget( mapGlobalPos2internalPos( oldpos ));
01631          UpdateRect( PG_Rect( p.x, p.y, fieldsizex, fieldsizey ) );
01632          
01633          p = internal2widget( mapGlobalPos2internalPos( pos ));
01634          UpdateRect( PG_Rect( p.x, p.y, fieldsizex, fieldsizey ) );
01635          */
01636       }
01637    }
01638 }
01639 
01640 
01641 bool MapDisplayPG::keyboardHandler( const SDL_KeyboardEvent* keyEvent)
01642 {
01643    if ( !keyEvent || !actmap )
01644       return false;
01645 
01646    int keyStateNum;
01647    Uint8* keyStates = SDL_GetKeyState ( &keyStateNum );
01648 
01649    if ( keyEvent->type == SDL_KEYDOWN ) {
01650       if ( !disableKeyboardCursorMovement ) {
01651          if ( keyEvent->keysym.sym == SDLK_RIGHT && keyStates[SDLK_RIGHT] ) {
01652             moveCursor(2, 1);
01653             return true;
01654          }
01655          if ( keyEvent->keysym.sym == SDLK_LEFT  && keyStates[SDLK_LEFT]  ) {
01656             moveCursor(6, 1);
01657             return true;
01658          }
01659          if ( (keyEvent->keysym.sym == SDLK_UP  && keyStates[SDLK_UP] ) || ( keyEvent->keysym.sym == SDLK_KP8  && keyStates[SDLK_KP8] )) {
01660             moveCursor(0, 1);
01661             return true;
01662          }
01663          if ( (keyEvent->keysym.sym == SDLK_DOWN  && keyStates[SDLK_DOWN]) || (keyEvent->keysym.sym == SDLK_KP2  && keyStates[SDLK_KP2] )) {
01664             moveCursor(4, 1);
01665             return true;
01666          }
01667          if ( keyEvent->keysym.sym == SDLK_KP6  && keyStates[SDLK_KP6] ) {
01668             moveCursor(2, 2);
01669             return true;
01670          }
01671          if ( keyEvent->keysym.sym == SDLK_KP4 && keyStates[SDLK_KP4] ) {
01672             moveCursor(6, 2);
01673             return true;
01674          }
01675          if ( keyEvent->keysym.sym == SDLK_KP7  && keyStates[SDLK_KP7] ) {
01676             moveCursor(7, 1);
01677             return true;
01678          }
01679          if ( keyEvent->keysym.sym == SDLK_KP9  && keyStates[SDLK_KP9]) {
01680             moveCursor(1, 1);
01681             return true;
01682          }
01683          if ( keyEvent->keysym.sym == SDLK_KP1  && keyStates[SDLK_KP1]) {
01684             moveCursor(5, 1);
01685             return true;
01686          }
01687          if ( keyEvent->keysym.sym == SDLK_KP3  && keyStates[SDLK_KP3]) {
01688             moveCursor(3, 1);
01689             return true;
01690          }
01691          
01692       }   
01693    }
01694    return false;
01695 }
01696 
01697 
01698 void MapDisplayPG::registerAdditionalUnit( Vehicle* veh )
01699 {
01700    additionalUnit = veh;
01701 }
01702 
01703 void MapDisplayPG::addMapLayer( MapLayer* layer, const ASCString& name )
01704 {
01705    MapRenderer::addMapLayer( layer );
01706    layerMap[name] = layer;
01707    layer->setActive(false);
01708 }
01709 
01710 void MapDisplayPG::activateMapLayer( const ASCString& name, bool active )
01711 {
01712    LayerMap::iterator i = layerMap.find( name );
01713    if ( i != layerMap.end() ) {
01714       i->second->setActive( active );
01715       layerChanged( active, name );
01716    }   
01717 }
01718 
01719 void MapDisplayPG::toggleMapLayer( const ASCString& name )
01720 {
01721    LayerMap::iterator i = layerMap.find( name );
01722    if ( i != layerMap.end() ) {
01723       i->second->setActive( !i->second->isActive() );
01724       layerChanged( i->second->isActive(), name );
01725    }
01726 }
01727 
01728 bool MapDisplayPG::layerActive( const ASCString& name )
01729 {
01730    LayerMap::iterator i = layerMap.find( name );
01731    if ( i != layerMap.end() ) 
01732       return i->second->isActive();
01733    else
01734       return false;
01735 }
01736 
01737 
01738 void MapDisplayPG::getActiveLayers( vector<ASCString>& list )
01739 {
01740    list.clear();
01741    for ( LayerMap::iterator i = layerMap.begin(); i != layerMap.end(); ++i )
01742       if ( i->second->isActive() )
01743          list.push_back( i->first );
01744 }
01745 
01746 
01747 
01748 
01749 MapDisplayPG::CursorHiding::CursorHiding()
01750 {
01751    if ( theMapDisplay )
01752       ++theMapDisplay->cursor.invisible;
01753 }
01754 
01755 MapDisplayPG::CursorHiding::~CursorHiding()
01756 {
01757    if ( theMapDisplay ) {
01758       --theMapDisplay->cursor.invisible;
01759       if ( !theMapDisplay->cursor.invisible )
01760          theMapDisplay->displayCursor();
01761    }
01762 }
01763 
01764 
01765 void MapDisplayPG::Cursor::goTo( const MapCoordinate& cursorPosition, const MapCoordinate& upperLeftScreenCorner )
01766 {
01767    bool redraw = false;
01768    
01769    if ( upperLeftScreenCorner.valid() )
01770       if ( upperLeftScreenCorner != mapDisplay->offset ) {
01771          redraw = true;
01772          mapDisplay->offset = upperLeftScreenCorner;
01773       }
01774    
01775    MapCoordinate oldpos = pos();
01776    if ( !mapDisplay->fieldInView( cursorPosition) )
01777       mapDisplay->centerOnField(cursorPosition);
01778    
01779    pos()=cursorPosition;
01780    
01781    if ( pos() != oldpos || redraw) {
01782       invisible = 0;
01783       mapDisplay->dirty = MapDisplayPG::Curs;
01784       mapDisplay->Update();
01785       // mapDisplay->updateWidget();
01786    }
01787 }
01788 
01789 void MapDisplayPG::Cursor::goTo( const MapCoordinate& position )
01790 {
01791    MapCoordinate oldpos = pos();
01792    if ( !mapDisplay->fieldInView( position) )
01793       mapDisplay->centerOnField(position);
01794    pos()=position;
01795    
01796    if ( pos() != oldpos ) {
01797       invisible = 0;
01798       mapDisplay->dirty = MapDisplayPG::Curs;
01799       mapDisplay->Update();
01800       // mapDisplay->updateWidget();
01801    }
01802       
01803 }
01804 
01805 
01806 
01807 
01808 
01809 int lockdisplaymap = 0;
01810 
01811 
01812 
01813 void MapDisplayPG::LockDisplay::raiseLock()
01814 {
01815    if ( theMapDisplay ) {
01816       ++theMapDisplay->lock;
01817       theMapDisplay->dirty = Map;
01818       theMapDisplay->Update();
01819    }
01820    lockMapdisplay();
01821 
01822 }
01823 
01824 
01825 MapDisplayPG::LockDisplay::LockDisplay( bool dummy ) : isDummy( dummy )
01826 {
01827    if ( !dummy )
01828       raiseLock();      
01829 }
01830 
01831 MapDisplayPG::LockDisplay::~LockDisplay()
01832 {
01833    if ( !isDummy ) {
01834       if ( theMapDisplay ) {
01835          --theMapDisplay->lock;
01836          if ( !theMapDisplay->lock  ) {
01837             theMapDisplay->dirty = Map;
01838             theMapDisplay->Update();
01839          }
01840       }
01841       if ( !theMapDisplay->lock )
01842          unlockMapdisplay();
01843    }
01844 }
01845 
01846 
01847 

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