Md3Player.cpp

Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /////////////////////////////////////////////////////////////////////////////
00003 //
00004 // Md3Player.cpp -- Copyright (c) 2006-2007 David Henry
00005 // last modification: may. 7, 2007
00006 //
00007 // This code is licenced under the MIT license.
00008 //
00009 // This software is provided "as is" without express or implied
00010 // warranties. You may freely copy and compile this source into
00011 // applications you distribute provided that the copyright text
00012 // below is included in the resulting source code.
00013 //
00014 // Implementation of MD3 Player Classes.
00015 //
00016 /////////////////////////////////////////////////////////////////////////////
00017 
00018 #ifdef _WIN32
00019 #define WIN32_LEAN_AND_MEAN
00020 #include <windows.h>
00021 #endif
00022 
00023 #include <GL/gl.h>
00024 #include <GL/glu.h>
00025 #include <iostream>
00026 #include <cctype>
00027 #include <sstream>
00028 #include <dirent.h>
00029 #include <sys/types.h>
00030 
00031 using std::cout;
00032 using std::cerr;
00033 using std::endl;
00034 
00035 #include "Md3Player.h"
00036 #include "TextureManager.h"
00037 
00038 #ifdef _WIN32
00039 const char kSeparator = '\\';
00040 #else
00041 const char kSeparator = '/';
00042 #endif
00043 
00044 
00045 /////////////////////////////////////////////////////////////////////////////
00046 //
00047 // class Md3PlayerSkin implementation.
00048 //
00049 /////////////////////////////////////////////////////////////////////////////
00050 
00051 // --------------------------------------------------------------------------
00052 // Md3PlayerSkin::Md3PlayerSkin
00053 //
00054 // Constructor.  Load a skin given a path and its name.
00055 // For each portion of the player, load the adequate .skin file.
00056 // --------------------------------------------------------------------------
00057 
00058 Md3PlayerSkin::Md3PlayerSkin (const string &path, const string &name)
00059   throw (Md3Exception)
00060   : _path (path), _name (name)
00061 {
00062   // Load lower part's textures
00063   loadSkinFile (path + "lower_" + name + ".skin", _lowerTextures);
00064 
00065   // Load upper part's textures
00066   loadSkinFile (path + "upper_" + name + ".skin", _upperTextures);
00067 
00068   // Load head's textures
00069   loadSkinFile (path + "head_" + name + ".skin", _headTextures);
00070 }
00071 
00072 
00073 // --------------------------------------------------------------------------
00074 // Md3PlayerSkin::~Md3PlayerSkin
00075 //
00076 // Destructor.  Free allocated memory for the skin.
00077 // boost:shared_ptr should do it for us.
00078 // --------------------------------------------------------------------------
00079 
00080 Md3PlayerSkin::~Md3PlayerSkin ()
00081 {
00082 }
00083 
00084 
00085 // --------------------------------------------------------------------------
00086 // Md3PlayerSkin::loadSkinFile
00087 //
00088 // Constructor.  Load a skin file and initialize a TexMap object given
00089 // by reference.  The TexMap will contain a texture associated to each
00090 // mesh found in the skin file.
00091 // --------------------------------------------------------------------------
00092 
00093 void
00094 Md3PlayerSkin::loadSkinFile (const string &filename, TexMap &tmap)
00095   throw (Md3Exception)
00096 {
00097   // Open the skin file
00098   std::ifstream ifs (filename.c_str(), std::ios::in | std::ios::binary);
00099 
00100   if (ifs.fail ()) {
00101     fprintf(stderr, "Bad file: %s\n", filename.c_str());
00102     throw Md3Exception ("Couldn't open skin file", filename);
00103   }
00104 
00105   // Get texture manager
00106   Texture2DManager *texMgr = Texture2DManager::getInstance ();
00107 
00108   // Read the file
00109   while (!ifs.eof ())
00110     {
00111       string meshname, texname, buffer;
00112 
00113       // Read mesh name and texture name
00114       std::getline (ifs, meshname, ',');
00115       ifs >> texname;
00116 
00117       // If this is a valid mesh name, load the texture
00118       if (!meshname.empty () && !texname.empty ()
00119           && meshname.compare (0, 4, "tag_") != 0)
00120         {
00121           // Replace the path from the .skin file with the path
00122           // where the player's .skin file is
00123           long start = texname.find_last_of ('/') + 1;
00124           long end = texname.length () - start;
00125           texname.assign (texname, start, end);
00126           texname = _path + texname;
00127 
00128           // Load the texture
00129           Texture2D *tex = texMgr->load (texname);
00130 
00131           tmap.insert (TexMap::value_type (meshname, tex));
00132         }
00133 
00134       // Eat up rest of the line
00135       std::getline (ifs, buffer);
00136     }
00137 
00138   ifs.close ();
00139 }
00140 
00141 
00142 // --------------------------------------------------------------------------
00143 // Md3PlayerSkin::setModelTextures
00144 //
00145 // Setup textures for the specified model from the given Texture Map.
00146 // --------------------------------------------------------------------------
00147 
00148 void
00149 Md3PlayerSkin::setModelTextures (Md3Model *model, const TexMap &tmap) const
00150 {
00151   for (TexMap::const_iterator itor = tmap.begin ();
00152        itor != tmap.end (); ++itor)
00153     model->setTexture (itor->first, itor->second);
00154 }
00155 
00156 
00157 /////////////////////////////////////////////////////////////////////////////
00158 //
00159 // class Md3Weapon implementation.
00160 //
00161 /////////////////////////////////////////////////////////////////////////////
00162 
00163 // --------------------------------------------------------------------------
00164 // Md3Weapon::Md3Weapon
00165 //
00166 // Constructor.  Load a weapon given a path and the level of details.
00167 // --------------------------------------------------------------------------
00168 
00169 Md3Weapon::Md3Weapon (const string &path, Md3PlayerLOD lod)
00170   throw (Md3Exception)
00171   : _path (path), _scale (1.0f), _lod (lod)
00172 {
00173   string suffix, modelpath;
00174 
00175   // Add trailing slash to path name if not present
00176   if (_path.find_last_of (kSeparator) < _path.length () - 1)
00177     _path += kSeparator;
00178 
00179   // Extract name from the path
00180   _name.assign (_path, 0, _path.find_last_of (kSeparator));
00181   _name.assign (_name, _name.find_last_of (kSeparator) + 1, _name.length ());
00182 
00183   // Get model file suffix from LOD
00184   switch (lod)
00185     {
00186     case kLodLow:
00187       suffix = "_2";
00188       break;
00189 
00190     case kLodMedium:
00191       suffix = "_1";
00192       break;
00193 
00194     case kLodHigh:
00195       break;
00196     }
00197 
00198   // Load models
00199   modelpath = _path + _name + suffix + ".md3";
00200   _weapon = Md3ModelPtr (new Md3Model (modelpath));
00201   _weapon->loadShaders ();
00202 
00203   modelpath = _path + _name + suffix + "_barrel.md3";
00204   std::ifstream ftest (modelpath.c_str (), std::ios::in);
00205   if (!ftest.fail ())
00206     {
00207       // The barrel model exists, load it
00208       ftest.close ();
00209 
00210       _barrel = Md3ModelPtr (new Md3Model (modelpath));
00211       _barrel->loadShaders ();
00212 
00213       // Create links between weapon and barrel
00214       _weapon->link ("tag_barrel", _barrel.get ());
00215     }
00216 }
00217 
00218 
00219 // --------------------------------------------------------------------------
00220 // Md3Weapon::~Md3Weapon
00221 //
00222 // Destructor.
00223 // --------------------------------------------------------------------------
00224 
00225 Md3Weapon::~Md3Weapon ()
00226 {
00227 }
00228 
00229 
00230 // --------------------------------------------------------------------------
00231 // Md3Weapon::draw
00232 //
00233 // Draw the weapon model.  Don't call this function if you want to
00234 // draw the weapon attached to a player: the player will draw it itself.
00235 // --------------------------------------------------------------------------
00236 
00237 void
00238 Md3Weapon::draw () const
00239 {
00240   // Set scale parameter
00241   scaleModels ();
00242 
00243   // Draw the models
00244   glPushMatrix ();
00245     glRotatef (-90.0, 1.0, 0.0, 0.0);
00246     glRotatef (-90.0, 0.0, 0.0, 1.0);
00247 
00248     _weapon->draw ();
00249   glPopMatrix ();
00250 }
00251 
00252 
00253 // --------------------------------------------------------------------------
00254 // Md3Weapon::scaleModels
00255 //
00256 // Set the current scale factor to weapon's models (call this before
00257 // rendering).
00258 // --------------------------------------------------------------------------
00259 
00260 void
00261 Md3Weapon::scaleModels () const
00262 {
00263   _weapon->setScale (_scale);
00264 
00265   if (_barrel)
00266     _barrel->setScale (_scale);
00267 }
00268 
00269 
00270 // --------------------------------------------------------------------------
00271 // Md3Weapon::linkToModel
00272 //
00273 // Link weapon model to the given model at "tag_weapon".  The target
00274 // model should be player's upper model.
00275 // --------------------------------------------------------------------------
00276 
00277 void
00278 Md3Weapon::linkToModel (Md3Model *model)
00279 {
00280   if (model)
00281     model->link ("tag_weapon", _weapon.get ());
00282 }
00283 
00284 
00285 /////////////////////////////////////////////////////////////////////////////
00286 //
00287 // struct Md3Player::Md3AnimState implementation.
00288 //
00289 /////////////////////////////////////////////////////////////////////////////
00290 
00291 // --------------------------------------------------------------------------
00292 // Md3Player::Md3AnimState::Md3AnimState
00293 //
00294 // Constructor.
00295 // --------------------------------------------------------------------------
00296 
00297 Md3Player::Md3AnimState::Md3AnimState ()
00298   : anim (NULL), curr_time (0.0f), old_time (0.0f),
00299     curr_frame (0), next_frame (0), interp (0.0f)
00300 {
00301 }
00302 
00303 
00304 // --------------------------------------------------------------------------
00305 // Md3Player::Md3AnimState::setup
00306 //
00307 // Initialize member variables given a player animation.
00308 // --------------------------------------------------------------------------
00309 
00310 void
00311 Md3Player::Md3AnimState::setup (Md3PlayerAnim_t *a)
00312 {
00313   // short-circuit: do nothing if we're already using this animation
00314   if (anim == a)
00315           return;
00316 
00317   // okay, animation is changing: reset
00318   anim = a;
00319   curr_frame = a->first;
00320   next_frame = a->first;
00321   interp = 0.0f;
00322 }
00323 
00324 
00325 // --------------------------------------------------------------------------
00326 // Md3Player::Md3AnimState::update
00327 //
00328 // Update current frame, next frame and interpolation percent given a
00329 // delta time.
00330 // --------------------------------------------------------------------------
00331 
00332 void
00333 Md3Player::Md3AnimState::update (float dt)
00334 {
00335   curr_time += dt;
00336 
00337   if ((curr_time - old_time) > (1.0 / anim->fps))
00338     {
00339       curr_frame = next_frame;
00340       next_frame++;
00341 
00342       if (next_frame > (anim->first + anim->num - 1))
00343         next_frame = anim->first;
00344 
00345       old_time = curr_time;
00346     }
00347 
00348   interp = anim->fps * (curr_time - old_time);
00349 }
00350 
00351 
00352 /////////////////////////////////////////////////////////////////////////////
00353 //
00354 // class Md3Player implementation.
00355 //
00356 /////////////////////////////////////////////////////////////////////////////
00357 
00358 // --------------------------------------------------------------------------
00359 // Md3Player::Md3Player
00360 //
00361 // Constructor.  Load a player given a path.  Load player's models,
00362 // animations and skins.
00363 // --------------------------------------------------------------------------
00364 
00365 Md3Player::Md3Player (const string &path, Md3PlayerLOD lod)
00366   throw (Md3Exception)
00367   : _weapon (NULL), _path (path), _scale (1.0f), _lod (lod)
00368 {
00369   // Add trailing slash to path name if not present
00370   if (_path.find_last_of (kSeparator) < _path.length () - 1)
00371     _path += kSeparator;
00372 
00373   // Extract name from the path
00374   _name.assign (_path, 0, _path.find_last_of (kSeparator));
00375   _name.assign (_name, _name.find_last_of (kSeparator) + 1, _name.length ());
00376 
00377   // Load models
00378   loadModels (_path);
00379 
00380   // Load animations
00381   loadAnimations (_path);
00382 
00383   // Load skins
00384   loadSkins (_path);
00385 }
00386 
00387 
00388 // --------------------------------------------------------------------------
00389 // Md3Player::~Md3Player
00390 //
00391 // Destructor.  Free allocated memory for the MD3 player.
00392 // --------------------------------------------------------------------------
00393 
00394 Md3Player::~Md3Player ()
00395 {
00396 }
00397 
00398 
00399 // --------------------------------------------------------------------------
00400 // Md3Player::draw
00401 //
00402 // Draw player's animated models.
00403 // --------------------------------------------------------------------------
00404 
00405 void
00406 Md3Player::draw () const
00407 {
00408   // Set scale parameter
00409   _lower->setScale (_scale);
00410   _upper->setScale (_scale);
00411   _head->setScale (_scale);
00412 
00413   if (_weapon)
00414     _weapon->scaleModels ();
00415 
00416   // Set current skin's textures
00417   if (_currentSkin)
00418     {
00419       _currentSkin->setLowerTextures (_lower.get ());
00420       _currentSkin->setUpperTextures (_upper.get ());
00421       _currentSkin->setHeadTextures (_head.get ());
00422     }
00423 
00424   // Set animation parameters
00425   const Md3AnimState &low = _lowerAnim;
00426   const Md3AnimState &upp = _upperAnim;
00427 
00428   _lower->setupAnimation (low.curr_frame, low.next_frame, low.interp);
00429   _upper->setupAnimation (upp.curr_frame, upp.next_frame, upp.interp);
00430 
00431   // Draw the models
00432   glPushMatrix ();
00433     glRotatef (-90.0, 1.0, 0.0, 0.0);
00434     glRotatef (-90.0, 0.0, 0.0, 1.0);
00435 
00436     _lower->draw ();
00437   glPopMatrix ();
00438 }
00439 
00440 
00441 // --------------------------------------------------------------------------
00442 // Md3Player::renderFrame
00443 //
00444 // Draw player's models at a given frame.
00445 // --------------------------------------------------------------------------
00446 
00447 void
00448 Md3Player::renderFrame (int upperFrame, int lowerFrame) const
00449 {
00450   // Set scale parameter
00451   _lower->setScale (_scale);
00452   _upper->setScale (_scale);
00453   _head->setScale (_scale);
00454 
00455   if (_weapon)
00456     _weapon->scaleModels ();
00457 
00458   // Set current skin's textures
00459   if (_currentSkin)
00460     {
00461       _currentSkin->setLowerTextures (_lower.get ());
00462       _currentSkin->setUpperTextures (_upper.get ());
00463       _currentSkin->setHeadTextures (_head.get ());
00464     }
00465 
00466   // Set animation parameters
00467   _lower->setupAnimation (lowerFrame, lowerFrame, 0.0f);
00468   _upper->setupAnimation (upperFrame, upperFrame, 0.0f);
00469 
00470   // Draw the models
00471   glPushMatrix ();
00472     glRotatef (-90.0, 1.0, 0.0, 0.0);
00473     glRotatef (-90.0, 0.0, 0.0, 1.0);
00474 
00475     _lower->draw ();
00476   glPopMatrix ();
00477 }
00478 
00479 
00480 // --------------------------------------------------------------------------
00481 // Md3Player::animate
00482 //
00483 // Animate player's models.
00484 // --------------------------------------------------------------------------
00485 
00486 void
00487 Md3Player::animate (float dt)
00488 {
00489   _lowerAnim.update (dt);
00490   _upperAnim.update (dt);
00491 }
00492 
00493 
00494 // --------------------------------------------------------------------------
00495 // Md3Player::setAnimation
00496 //
00497 // Set player's current animation.
00498 // --------------------------------------------------------------------------
00499 
00500 void
00501 Md3Player::setAnimation (Md3PlayerAnimType type)
00502 {
00503   if ((type >= kBothDeath1) && (type <= kBothDead3))
00504     {
00505       _lowerAnim.setup (&_anims[type]);
00506       _upperAnim.setup (&_anims[type]);
00507     }
00508   else if ((type >= kTorsoGesture) && (type <= kTorsoStand2))
00509     {
00510       _upperAnim.setup (&_anims[type]);
00511     }
00512   else if ((type >= kLegsWalkCr) && (type <= kLegsTurn))
00513     {
00514       _lowerAnim.setup (&_anims[type]);
00515     }
00516 }
00517 
00518 
00519 // --------------------------------------------------------------------------
00520 // Md3Player::setSkin
00521 //
00522 // Set player's current skin.  If the skin does not exist, current
00523 // skin is set to NULL.
00524 // --------------------------------------------------------------------------
00525 
00526 void
00527 Md3Player::setSkin (const string &name)
00528 {
00529   SkinMap::iterator itor = _skins.find (name);
00530   if (itor != _skins.end ())
00531     {
00532       _currentSkin = itor->second.get ();
00533       _currentSkinName = itor->first;
00534     }
00535   else
00536     {
00537       _currentSkin = NULL;
00538     }
00539 }
00540 
00541 
00542 // --------------------------------------------------------------------------
00543 // Md3Player::linkWeapon
00544 //
00545 // Set weapon model to the player, and link the weapon to player's models.
00546 // --------------------------------------------------------------------------
00547 
00548 void
00549 Md3Player::linkWeapon (Md3Weapon *weapon)
00550 {
00551   _weapon = weapon;
00552 
00553   if (_weapon)
00554     _weapon->linkToModel (_upper.get ());
00555 }
00556 
00557 
00558 // --------------------------------------------------------------------------
00559 // Md3Player::unlinkWeapon
00560 //
00561 // Unset player's weapon.
00562 // --------------------------------------------------------------------------
00563 
00564 void
00565 Md3Player::unlinkWeapon ()
00566 {
00567   if (_weapon)
00568     {
00569       _upper->unlink ("tag_weapon");
00570       _weapon = NULL;
00571     }
00572 }
00573 
00574 
00575 
00576 
00577 // --------------------------------------------------------------------------
00578 // Md3Player::getAnimationState
00579 //
00580 // Retrieve the animation state of the given area (upper/lower)
00581 // --------------------------------------------------------------------------
00582 
00583 void
00584 Md3Player::getAnimationState
00585 (
00586 eAnimationArea area,
00587 Md3AnimState_t& state
00588 )
00589 {
00590         if (eAnimationArea_Upper == area) {
00591                 setState(_upperAnim, state);
00592         } else if (eAnimationArea_Lower == area) {
00593                 setState(_lowerAnim, state);
00594         }
00595 }
00596 
00597 
00598 
00599 void
00600 Md3Player::setState
00601 (
00602 const Md3AnimState& anim,
00603 Md3AnimState_t& state
00604 )
00605 {
00606         state.animationIndex = anim.anim->index;
00607         state.time = anim.curr_time;
00608 }
00609 
00610 
00611 
00612 // --------------------------------------------------------------------------
00613 // Md3Player::setAnimationState
00614 //
00615 // sets the given animation state
00616 // --------------------------------------------------------------------------
00617 
00618 void
00619 Md3Player::setAnimationState
00620 (
00621 eAnimationArea area,
00622 const Md3AnimState_t& state
00623 )
00624 {
00625         Md3PlayerAnim_t * anim = &_anims[state.animationIndex];
00626         if (eAnimationArea_Upper == area) {
00627                 updateAnim(_upperAnim, state, anim);
00628         } else if (eAnimationArea_Lower == area) {
00629                 updateAnim(_lowerAnim, state, anim);
00630         }
00631 }
00632 
00633 
00634 
00635 void
00636 Md3Player::updateAnim
00637 (
00638 Md3AnimState& anim,
00639 const Md3AnimState_t& state,
00640 Md3PlayerAnim_t * a
00641 )
00642 {
00643         anim.anim = a;
00644         anim.curr_time = state.time;
00645         anim.old_time = 0;
00646 }
00647 
00648 
00649 
00650 // --------------------------------------------------------------------------
00651 // Md3Player::loadModels
00652 //
00653 // Load player's models from the path directory.
00654 // --------------------------------------------------------------------------
00655 
00656 void
00657 Md3Player::loadModels (const string &path)
00658   throw (Md3Exception)
00659 {
00660   string suffix, modelpath;
00661 
00662   // Get model file suffix from LOD
00663   switch (_lod)
00664     {
00665     case kLodLow:
00666       suffix = "_2.md3";
00667       break;
00668 
00669     case kLodMedium:
00670       suffix = "_1.md3";
00671       break;
00672 
00673     case kLodHigh:
00674       suffix = ".md3";
00675       break;
00676     }
00677 
00678   // Load models
00679   modelpath = _path + "lower" + suffix;
00680   _lower = Md3ModelPtr (new Md3Model (modelpath));
00681 
00682   modelpath = _path + "upper" + suffix;
00683   _upper = Md3ModelPtr (new Md3Model (modelpath));
00684 
00685   modelpath = _path + "head" + suffix;
00686   _head = Md3ModelPtr (new Md3Model (modelpath));
00687 
00688   // Create links between the models
00689   _lower->link ("tag_torso", _upper.get ());
00690   _upper->link ("tag_head", _head.get ());
00691 }
00692 
00693 
00694 // --------------------------------------------------------------------------
00695 // Md3Player::loadAnimations
00696 //
00697 // Load animations from the animation.cfg file.
00698 // NOTE: Some animations.cfg files may be broken, i.e. they give wrong
00699 // frame indices or wrong frame number for an animation (which is
00700 // greater or equal than the number of frames of the models).
00701 // We don't fix those files.
00702 // --------------------------------------------------------------------------
00703 
00704 void
00705 Md3Player::loadAnimations (const string &path)
00706   throw (Md3Exception)
00707 {
00708   string filename (path + "animation.cfg");
00709   string token, buffer;
00710   int index = 0;
00711 
00712   // Open the animation file
00713   std::ifstream ifs (filename.c_str(), std::ios::in | std::ios::binary);
00714 
00715   if (ifs.fail ())
00716     throw Md3Exception ("Couldn't open animation file", filename);
00717 
00718   // Read animation lines
00719   while (!ifs.eof ())
00720     {
00721       // Parse the file line by line
00722       std::getline (ifs, buffer);
00723       std::istringstream line (buffer);
00724 
00725       // Get first char of the line
00726       char c = line.peek ();
00727 
00728       // If the first token is a numeric, then this line
00729       // contains animation infos
00730       if (std::isdigit (c))
00731         {
00732           _anims[index].index = index;
00733           line >> _anims[index].first;
00734           line >> _anims[index].num;
00735           line >> _anims[index].looping;
00736           line >> _anims[index].fps;
00737           index++;
00738         }
00739     }
00740 
00741   ifs.close ();
00742 
00743   // Skip "Torso" frames for the "Legs" animations
00744   int skip = _anims[kLegsWalkCr].first - _anims[kTorsoGesture].first;
00745 
00746   for (int i = kLegsWalkCr; i < kMaxAnimations; ++i)
00747     _anims[i].first -= skip;
00748 }
00749 
00750 
00751 // --------------------------------------------------------------------------
00752 // Md3Player::loadSkins
00753 //
00754 // Load player's skins from the path directory and set the default
00755 // skin as player's current skin.
00756 // --------------------------------------------------------------------------
00757 
00758 void
00759 Md3Player::loadSkins (const string &path)
00760   throw (Md3Exception)
00761 {
00762   // Open the directory
00763   DIR *dd = opendir (path.c_str ());
00764   if (!dd)
00765     throw Md3Exception ("Couldn't open dir", path);
00766 
00767   dirent *dit;
00768 
00769   // Read directory for textures
00770   while ((dit = readdir (dd)) != NULL)
00771     {
00772       const string filename (dit->d_name);
00773       const string fileext (".skin");
00774       const string pattern ("head_");
00775 
00776       // Filter ".skin" files
00777       if (filename.length () - fileext.length ()
00778           == filename.find (fileext))
00779         {
00780           // Now we should have 3 skin files for a player skin:
00781           // one for upper portion, one for lower and one for head.
00782           // We'll just take one of them to extract the skin name.
00783 
00784           // Filter "head_*.skin" files
00785           if (filename.compare (0, pattern.length (), pattern) == 0)
00786             {
00787               // Extract skin name from filename
00788               const string name (filename, pattern.length (),
00789                    filename.find (fileext) - pattern.length ());
00790 
00791               // Load new skin
00792               Md3PlayerSkinPtr skin (new Md3PlayerSkin (path, name));
00793               _skins.insert (SkinMap::value_type (name, skin));
00794             }
00795         }
00796     }
00797 
00798   // Close directory
00799   closedir (dd);
00800 
00801   // Set the default skin as current player's skin
00802   setSkin ("default");
00803 
00804   // If there is no skin named "default", use the first enry in the map
00805   if (_currentSkin == NULL)
00806     {
00807       _currentSkin = _skins.begin ()->second.get ();
00808       _currentSkinName = _skins.begin ()->first;
00809     }
00810 }