Back to index

supertuxkart  0.5+dfsg1
herring_manager.cpp
Go to the documentation of this file.
00001 //  $Id: herring_manager.cpp 2111 2008-05-31 07:04:30Z cosmosninja $
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2006 Joerg Henrichs
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include <stdexcept>
00021 #include <string>
00022 #include <sstream>
00023 #include "user_config.hpp"
00024 #include "herring_manager.hpp"
00025 #include "file_manager.hpp"
00026 #include "loader.hpp"
00027 #include "material_manager.hpp"
00028 #include "material.hpp"
00029 #include "kart.hpp"
00030 #include "string_utils.hpp"
00031 #include "translation.hpp"
00032 #if defined(WIN32) && !defined(__CYGWIN__)
00033 #  define snprintf _snprintf
00034 #endif
00035 
00036 class Shadow
00037 {
00038     ssgBranch *sh ;
00039 
00040 public:
00041     Shadow ( float x1, float x2, float y1, float y2 ) ;
00042     ssgEntity *getRoot () { return sh ; }
00043 }
00044 ;   // Shadow
00045 
00046 //-----------------------------------------------------------------------------
00047 Shadow::Shadow ( float x1, float x2, float y1, float y2 )
00048 {
00049     ssgVertexArray   *va = new ssgVertexArray   () ; sgVec3 v ;
00050     ssgNormalArray   *na = new ssgNormalArray   () ; sgVec3 n ;
00051     ssgColourArray   *ca = new ssgColourArray   () ; sgVec4 c ;
00052     ssgTexCoordArray *ta = new ssgTexCoordArray () ; sgVec2 t ;
00053 
00054     sgSetVec4 ( c, 0.0f, 0.0f, 0.0f, 1.0f ) ; ca->add(c) ;
00055     sgSetVec3 ( n, 0.0f, 0.0f, 1.0f ) ; na->add(n) ;
00056 
00057     sgSetVec3 ( v, x1, y1, 0.10f ) ; va->add(v) ;
00058     sgSetVec3 ( v, x2, y1, 0.10f ) ; va->add(v) ;
00059     sgSetVec3 ( v, x1, y2, 0.10f ) ; va->add(v) ;
00060     sgSetVec3 ( v, x2, y2, 0.10f ) ; va->add(v) ;
00061 
00062     sgSetVec2 ( t, 0.0f, 0.0f ) ; ta->add(t) ;
00063     sgSetVec2 ( t, 1.0f, 0.0f ) ; ta->add(t) ;
00064     sgSetVec2 ( t, 0.0f, 1.0f ) ; ta->add(t) ;
00065     sgSetVec2 ( t, 1.0f, 1.0f ) ; ta->add(t) ;
00066 
00067     sh = new ssgBranch ;
00068     sh -> clrTraversalMaskBits ( SSGTRAV_ISECT|SSGTRAV_HOT ) ;
00069 
00070     sh -> setName ( "Shadow" ) ;
00071 
00072     ssgVtxTable *gs = new ssgVtxTable ( GL_TRIANGLE_STRIP, va, na, ta, ca ) ;
00073 
00074     gs -> clrTraversalMaskBits ( SSGTRAV_ISECT|SSGTRAV_HOT ) ;
00075     gs -> setState ( fuzzy_gst ) ;
00076     sh -> addKid ( gs ) ;
00077     sh -> ref () ; /* Make sure it doesn't get deleted by mistake */
00078 }   // Shadow
00079 
00080 //=============================================================================
00081 HerringManager* herring_manager;
00082 typedef std::map<std::string,ssgEntity*>::const_iterator CI_type;
00083 
00084 HerringManager::HerringManager()
00085 {
00086     m_all_models.clear();
00087     // The actual loading is done in loadDefaultHerrings
00088 }   // HerringManager
00089 
00090 //-----------------------------------------------------------------------------
00091 void HerringManager::removeTextures()
00092 {
00093     for(AllHerringType::iterator i =m_all_herrings.begin();
00094         i!=m_all_herrings.end();  i++)
00095     {
00096         delete *i;
00097     }
00098     m_all_herrings.clear();
00099 
00100     for(CI_type i=m_all_models.begin(); i!=m_all_models.end(); ++i)
00101     {
00102         ssgDeRefDelete(i->second);
00103     }
00104     m_all_models.clear();
00105     callback_manager->clear(CB_HERRING);
00106 }   // removeTextures
00107 
00108 //-----------------------------------------------------------------------------
00109 HerringManager::~HerringManager()
00110 {
00111     for(CI_type i=m_all_models.begin(); i!=m_all_models.end(); ++i)
00112     {
00113         ssgDeRefDelete(i->second);
00114     }
00115 }   // ~HerringManager
00116 
00117 //-----------------------------------------------------------------------------
00118 void HerringManager::loadDefaultHerrings()
00119 {
00120     // Load all models. This can't be done in the constructor, 
00121     // since the file_manager isn't ready at that stage.
00122     // -------------------------------------------------------
00123     std::set<std::string> files;
00124     file_manager->listFiles(files, file_manager->getHerringDir(),
00125                             /*is_full_path*/true, 
00126                             /*make_full_path*/true);
00127     for(std::set<std::string>::iterator i  = files.begin();
00128             i != files.end();  ++i)
00129         {
00130             if(!StringUtils::has_suffix(*i, ".ac")) continue;
00131             ssgEntity*  h         = loader->load(*i, CB_HERRING, 
00132                                                  /*optimise*/true, 
00133                                                  /*full_path*/true);
00134             std::string shortName = StringUtils::basename(StringUtils::without_extension(*i));
00135             h->ref();
00136             h->setName(shortName.c_str());
00137             m_all_models[shortName] = h;
00138         }   // for i
00139 
00140 
00141     // Load the old, internal only models
00142     // ----------------------------------
00143     sgVec3 yellow = { 1.0f, 1.0f, 0.4f }; CreateDefaultHerring(yellow, "OLD_GOLD"  );
00144     sgVec3 cyan   = { 0.4f, 1.0f, 1.0f }; CreateDefaultHerring(cyan  , "OLD_SILVER");
00145     sgVec3 red    = { 0.8f, 0.0f, 0.0f }; CreateDefaultHerring(red   , "OLD_RED"   );
00146     sgVec3 green  = { 0.0f, 0.8f, 0.0f }; CreateDefaultHerring(green , "OLD_GREEN" );
00147 
00148     setDefaultHerringStyle();
00149 }   // loadDefaultHerrings
00150 
00151 //-----------------------------------------------------------------------------
00152 void HerringManager::setDefaultHerringStyle()
00153 {
00154     // This should go in an internal, system wide configuration file
00155     const std::string DEFAULT_NAMES[4] = {"bonusblock", "banana",
00156                                    "goldcoin",   "silvercoin"};
00157 
00158     bool bError=0;
00159     char msg[MAX_ERROR_MESSAGE_LENGTH];
00160     for(int i=HE_RED; i<=HE_SILVER; i++)
00161     {
00162         m_herring_model[i] = m_all_models[DEFAULT_NAMES[i]];
00163         if(!m_herring_model[i])
00164         {
00165             snprintf(msg, sizeof(msg), 
00166                      "Herring model '%s' is missing (see herring_manager)!\n",
00167                      DEFAULT_NAMES[i].c_str());
00168             bError=1;
00169             break;
00170         }   // if !m_herring_model
00171     }   // for i
00172     if(bError)
00173     {
00174         fprintf(stderr, "The following models are available:\n");
00175         for(CI_type i=m_all_models.begin(); i!=m_all_models.end(); ++i)
00176         {
00177             if(i->second)
00178             {
00179                 if(i->first.substr(0,3)=="OLD")
00180                 {
00181                     fprintf(stderr,"   %s internally only.\n",i->first.c_str());
00182                 }
00183                 else
00184                 {
00185                     fprintf(stderr, "   %s in models/herrings/%s.ac.\n",
00186                             i->first.c_str(),
00187                             i->first.c_str());
00188                 }
00189             }  // if i->second
00190         }
00191         throw std::runtime_error(msg);
00192         exit(-1);
00193     }   // if bError
00194 
00195 }   // setDefaultHerringStyle
00196 
00197 //-----------------------------------------------------------------------------
00198 Herring* HerringManager::newHerring(herringType type, sgVec3* xyz)
00199 {
00200     Herring* h = new Herring(type, xyz, m_herring_model[type]);
00201     m_all_herrings.push_back(h);
00202     return h;
00203 }   // newHerring
00204 
00205 //-----------------------------------------------------------------------------
00206 void  HerringManager::hitHerring(Kart* kart)
00207 {
00208     for(AllHerringType::iterator i =m_all_herrings.begin();
00209         i!=m_all_herrings.end();  i++)
00210     {
00211         if((*i)->wasEaten()) continue;
00212         if((*i)->hitKart(kart))
00213         {
00214             (*i)->isEaten();
00215             kart->collectedHerring(*i);
00216         }   // if hit
00217     }   // for m_all_herrings
00218 }   // hitHerring
00219 
00220 //-----------------------------------------------------------------------------
00224 void HerringManager::cleanup()
00225 {
00226     for(AllHerringType::iterator i =m_all_herrings.begin();
00227         i!=m_all_herrings.end();  i++)
00228     {
00229         delete *i;
00230     }
00231     m_all_herrings.clear();
00232 
00233     setDefaultHerringStyle();
00234 
00235     // Then load the default style from the user_config file
00236     // -----------------------------------------------------
00237     // This way if a herring is not defined in the herringstyle-file, the
00238     // default (i.e. old herring) is used.
00239     try
00240     {
00241         // FIXME: This should go in a system-wide configuration file,
00242         //        and only one of this and the hard-coded settings in
00243         //        setDefaultHerringStyle are necessary!!!
00244         loadHerringStyle(user_config->m_herring_style);
00245     }
00246     catch(std::runtime_error)
00247     {
00248         fprintf(stderr,"The herring style '%s' in your configuration file does not exist.\nIt is ignored.\n",
00249                 user_config->m_herring_style.c_str());
00250         user_config->m_herring_style="";
00251     }
00252 
00253     try
00254     {
00255         loadHerringStyle(m_user_filename);
00256     }
00257     catch(std::runtime_error)
00258     {
00259         fprintf(stderr,"The herring style '%s' specified on the command line does not exist.\nIt is ignored.\n",
00260                 m_user_filename.c_str());
00261         m_user_filename="";  // reset to avoid further warnings.
00262     }
00263 
00264 }   // cleanup
00265 
00266 //-----------------------------------------------------------------------------
00270 void HerringManager::reset()
00271 {
00272     for(AllHerringType::iterator i =m_all_herrings.begin();
00273         i!=m_all_herrings.end();  i++)
00274     {
00275         (*i)->reset();
00276     }  // for i
00277 }   // reset
00278 
00279 //-----------------------------------------------------------------------------
00280 void HerringManager::update(float delta)
00281 {
00282     for(AllHerringType::iterator i =m_all_herrings.begin();
00283         i!=m_all_herrings.end();  i++)
00284     {
00285         (*i)->update(delta);
00286     }   // for m_all_herrings
00287 }   // delta
00288 
00289 //-----------------------------------------------------------------------------
00290 void HerringManager::CreateDefaultHerring(sgVec3 colour, std::string name)
00291 {
00292     ssgVertexArray   *va = new ssgVertexArray   () ; sgVec3 v ;
00293     ssgNormalArray   *na = new ssgNormalArray   () ; sgVec3 n ;
00294     ssgColourArray   *ca = new ssgColourArray   () ; sgVec4 c ;
00295     ssgTexCoordArray *ta = new ssgTexCoordArray () ; sgVec2 t ;
00296 
00297     sgSetVec3(v, -0.5f, 0.0f, 0.0f ) ; va->add(v) ;
00298     sgSetVec3(v,  0.5f, 0.0f, 0.0f ) ; va->add(v) ;
00299     sgSetVec3(v, -0.5f, 0.0f, 0.5f ) ; va->add(v) ;
00300     sgSetVec3(v,  0.5f, 0.0f, 0.5f ) ; va->add(v) ;
00301     sgSetVec3(v, -0.5f, 0.0f, 0.0f ) ; va->add(v) ;
00302     sgSetVec3(v,  0.5f, 0.0f, 0.0f ) ; va->add(v) ;
00303 
00304     sgSetVec3(n,  0.0f,  1.0f,  0.0f ) ; na->add(n) ;
00305 
00306     sgCopyVec3 ( c, colour ) ; c[ 3 ] = 1.0f ; ca->add(c) ;
00307 
00308     sgSetVec2(t, 0.0f, 0.0f ) ; ta->add(t) ;
00309     sgSetVec2(t, 1.0f, 0.0f ) ; ta->add(t) ;
00310     sgSetVec2(t, 0.0f, 1.0f ) ; ta->add(t) ;
00311     sgSetVec2(t, 1.0f, 1.0f ) ; ta->add(t) ;
00312     sgSetVec2(t, 0.0f, 0.0f ) ; ta->add(t) ;
00313     sgSetVec2(t, 1.0f, 0.0f ) ; ta->add(t) ;
00314 
00315 
00316     ssgLeaf *gset = new ssgVtxTable ( GL_TRIANGLE_STRIP, va, na, ta, ca ) ;
00317 
00318     gset->setState(material_manager->getMaterial("herring.rgb")->getState()) ;
00319 
00320     Shadow* sh = new Shadow ( -0.5f, 0.5f, -0.25f, 0.25f ) ;
00321 
00322     ssgTransform* tr = new ssgTransform () ;
00323 
00324     tr -> addKid ( sh -> getRoot () ) ;
00325     tr -> addKid ( gset ) ;
00326     tr -> ref () ; /* Make sure it doesn't get deleted by mistake */
00327     m_all_models[name] = tr;
00328 
00329 }   // CreateDefaultHerring
00330 
00331 //-----------------------------------------------------------------------------
00332 void HerringManager::loadHerringStyle(const std::string filename)
00333 {
00334     if(filename.length()==0) return;
00335     const lisp::Lisp* root = 0;
00336     lisp::Parser parser;
00337     
00338     root = parser.parse(file_manager->getConfigFile(filename + ".herring"));
00339 
00340     const lisp::Lisp* herring_node = root->getLisp("herring");
00341     if(!herring_node)
00342     {
00343         char msg[MAX_ERROR_MESSAGE_LENGTH];
00344         snprintf(msg, sizeof(msg), "Couldn't load map '%s': no herring node.",
00345                  filename.c_str());
00346        delete root;
00347         throw std::runtime_error(msg);
00348         delete root;
00349     }
00350     setHerring(herring_node, "red",   HE_RED   );
00351     setHerring(herring_node, "green", HE_GREEN );
00352     setHerring(herring_node, "gold"  ,HE_GOLD  );
00353     setHerring(herring_node, "silver",HE_SILVER);
00354     delete root;
00355 }   // loadHerringStyle
00356 
00357 //-----------------------------------------------------------------------------
00358 void HerringManager::setHerring(const lisp::Lisp *herring_node,
00359                                 const char *colour, herringType type)
00360 {
00361     std::string name;
00362     herring_node->get(colour, name);
00363     if(name.size()>0)
00364     {
00365         m_herring_model[type]=m_all_models[name];
00366     }
00367 }   // setHerring