stk-code_catmod/src/herring_manager.cpp
hikerstk 2dc36390fa 1) Removed the old m_curr_pos sg* data structure from kart.
2) Replaced several sg* data structures and function parameters with
   plib independent data structures.
3) Some code cleanup, updated gpl license to 3 in a file or two.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2132 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-06-20 09:34:35 +00:00

368 lines
12 KiB
C++

// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdexcept>
#include <string>
#include <sstream>
#include "user_config.hpp"
#include "herring_manager.hpp"
#include "file_manager.hpp"
#include "loader.hpp"
#include "material_manager.hpp"
#include "material.hpp"
#include "kart.hpp"
#include "string_utils.hpp"
#include "translation.hpp"
#if defined(WIN32) && !defined(__CYGWIN__)
# define snprintf _snprintf
#endif
/** Simple shadow class, only used here for default herrings. */
class Shadow
{
ssgBranch *sh ;
public:
Shadow ( float x1, float x2, float y1, float y2 ) ;
ssgEntity *getRoot () { return sh ; }
}
; // Shadow
//-----------------------------------------------------------------------------
Shadow::Shadow ( float x1, float x2, float y1, float y2 )
{
ssgVertexArray *va = new ssgVertexArray () ; sgVec3 v ;
ssgNormalArray *na = new ssgNormalArray () ; sgVec3 n ;
ssgColourArray *ca = new ssgColourArray () ; sgVec4 c ;
ssgTexCoordArray *ta = new ssgTexCoordArray () ; sgVec2 t ;
sgSetVec4 ( c, 0.0f, 0.0f, 0.0f, 1.0f ) ; ca->add(c) ;
sgSetVec3 ( n, 0.0f, 0.0f, 1.0f ) ; na->add(n) ;
sgSetVec3 ( v, x1, y1, 0.10f ) ; va->add(v) ;
sgSetVec3 ( v, x2, y1, 0.10f ) ; va->add(v) ;
sgSetVec3 ( v, x1, y2, 0.10f ) ; va->add(v) ;
sgSetVec3 ( v, x2, y2, 0.10f ) ; va->add(v) ;
sgSetVec2 ( t, 0.0f, 0.0f ) ; ta->add(t) ;
sgSetVec2 ( t, 1.0f, 0.0f ) ; ta->add(t) ;
sgSetVec2 ( t, 0.0f, 1.0f ) ; ta->add(t) ;
sgSetVec2 ( t, 1.0f, 1.0f ) ; ta->add(t) ;
sh = new ssgBranch ;
sh -> clrTraversalMaskBits ( SSGTRAV_ISECT|SSGTRAV_HOT ) ;
sh -> setName ( "Shadow" ) ;
ssgVtxTable *gs = new ssgVtxTable ( GL_TRIANGLE_STRIP, va, na, ta, ca ) ;
gs -> clrTraversalMaskBits ( SSGTRAV_ISECT|SSGTRAV_HOT ) ;
gs -> setState ( fuzzy_gst ) ;
sh -> addKid ( gs ) ;
sh -> ref () ; /* Make sure it doesn't get deleted by mistake */
} // Shadow
//=============================================================================
HerringManager* herring_manager;
typedef std::map<std::string,ssgEntity*>::const_iterator CI_type;
HerringManager::HerringManager()
{
m_all_models.clear();
// The actual loading is done in loadDefaultHerrings
} // HerringManager
//-----------------------------------------------------------------------------
void HerringManager::removeTextures()
{
for(AllHerringType::iterator i =m_all_herrings.begin();
i!=m_all_herrings.end(); i++)
{
delete *i;
}
m_all_herrings.clear();
for(CI_type i=m_all_models.begin(); i!=m_all_models.end(); ++i)
{
ssgDeRefDelete(i->second);
}
m_all_models.clear();
callback_manager->clear(CB_HERRING);
} // removeTextures
//-----------------------------------------------------------------------------
HerringManager::~HerringManager()
{
for(CI_type i=m_all_models.begin(); i!=m_all_models.end(); ++i)
{
ssgDeRefDelete(i->second);
}
} // ~HerringManager
//-----------------------------------------------------------------------------
void HerringManager::loadDefaultHerrings()
{
// Load all models. This can't be done in the constructor,
// since the file_manager isn't ready at that stage.
// -------------------------------------------------------
std::set<std::string> files;
file_manager->listFiles(files, file_manager->getHerringDir(),
/*is_full_path*/true,
/*make_full_path*/true);
for(std::set<std::string>::iterator i = files.begin();
i != files.end(); ++i)
{
if(!StringUtils::has_suffix(*i, ".ac")) continue;
ssgEntity* h = loader->load(*i, CB_HERRING,
/*optimise*/true,
/*full_path*/true);
std::string shortName = StringUtils::basename(StringUtils::without_extension(*i));
h->ref();
h->setName(shortName.c_str());
m_all_models[shortName] = h;
} // for i
// Load the old, internal only models
// ----------------------------------
sgVec3 yellow = { 1.0f, 1.0f, 0.4f }; CreateDefaultHerring(yellow, "OLD_GOLD" );
sgVec3 cyan = { 0.4f, 1.0f, 1.0f }; CreateDefaultHerring(cyan , "OLD_SILVER");
sgVec3 red = { 0.8f, 0.0f, 0.0f }; CreateDefaultHerring(red , "OLD_RED" );
sgVec3 green = { 0.0f, 0.8f, 0.0f }; CreateDefaultHerring(green , "OLD_GREEN" );
setDefaultHerringStyle();
} // loadDefaultHerrings
//-----------------------------------------------------------------------------
void HerringManager::setDefaultHerringStyle()
{
// This should go in an internal, system wide configuration file
const std::string DEFAULT_NAMES[4] = {"bonusblock", "banana",
"goldcoin", "silvercoin"};
bool bError=0;
char msg[MAX_ERROR_MESSAGE_LENGTH];
for(int i=HE_RED; i<=HE_SILVER; i++)
{
m_herring_model[i] = m_all_models[DEFAULT_NAMES[i]];
if(!m_herring_model[i])
{
snprintf(msg, sizeof(msg),
"Herring model '%s' is missing (see herring_manager)!\n",
DEFAULT_NAMES[i].c_str());
bError=1;
break;
} // if !m_herring_model
} // for i
if(bError)
{
fprintf(stderr, "The following models are available:\n");
for(CI_type i=m_all_models.begin(); i!=m_all_models.end(); ++i)
{
if(i->second)
{
if(i->first.substr(0,3)=="OLD")
{
fprintf(stderr," %s internally only.\n",i->first.c_str());
}
else
{
fprintf(stderr, " %s in models/herrings/%s.ac.\n",
i->first.c_str(),
i->first.c_str());
}
} // if i->second
}
throw std::runtime_error(msg);
exit(-1);
} // if bError
} // setDefaultHerringStyle
//-----------------------------------------------------------------------------
Herring* HerringManager::newHerring(herringType type, const Vec3& xyz)
{
Herring* h = new Herring(type, xyz, m_herring_model[type]);
m_all_herrings.push_back(h);
return h;
} // newHerring
//-----------------------------------------------------------------------------
void HerringManager::hitHerring(Kart* kart)
{
for(AllHerringType::iterator i =m_all_herrings.begin();
i!=m_all_herrings.end(); i++)
{
if((*i)->wasEaten()) continue;
if((*i)->hitKart(kart))
{
(*i)->isEaten();
kart->collectedHerring(*i);
} // if hit
} // for m_all_herrings
} // hitHerring
//-----------------------------------------------------------------------------
/** Remove all herring instances, and the track specific models. This is used
* just before a new track is loaded and a race is started.
*/
void HerringManager::cleanup()
{
for(AllHerringType::iterator i =m_all_herrings.begin();
i!=m_all_herrings.end(); i++)
{
delete *i;
}
m_all_herrings.clear();
setDefaultHerringStyle();
// Then load the default style from the user_config file
// -----------------------------------------------------
// This way if a herring is not defined in the herringstyle-file, the
// default (i.e. old herring) is used.
try
{
// FIXME: This should go in a system-wide configuration file,
// and only one of this and the hard-coded settings in
// setDefaultHerringStyle are necessary!!!
loadHerringStyle(user_config->m_herring_style);
}
catch(std::runtime_error)
{
fprintf(stderr,"The herring style '%s' in your configuration file does not exist.\nIt is ignored.\n",
user_config->m_herring_style.c_str());
user_config->m_herring_style="";
}
try
{
loadHerringStyle(m_user_filename);
}
catch(std::runtime_error)
{
fprintf(stderr,"The herring style '%s' specified on the command line does not exist.\nIt is ignored.\n",
m_user_filename.c_str());
m_user_filename=""; // reset to avoid further warnings.
}
} // cleanup
//-----------------------------------------------------------------------------
/** Remove all herring instances, and the track specific models. This is used
* just before a new track is loaded and a race is started
*/
void HerringManager::reset()
{
for(AllHerringType::iterator i =m_all_herrings.begin();
i!=m_all_herrings.end(); i++)
{
(*i)->reset();
} // for i
} // reset
//-----------------------------------------------------------------------------
void HerringManager::update(float delta)
{
for(AllHerringType::iterator i =m_all_herrings.begin();
i!=m_all_herrings.end(); i++)
{
(*i)->update(delta);
} // for m_all_herrings
} // delta
//-----------------------------------------------------------------------------
void HerringManager::CreateDefaultHerring(sgVec3 colour, std::string name)
{
ssgVertexArray *va = new ssgVertexArray () ; sgVec3 v ;
ssgNormalArray *na = new ssgNormalArray () ; sgVec3 n ;
ssgColourArray *ca = new ssgColourArray () ; sgVec4 c ;
ssgTexCoordArray *ta = new ssgTexCoordArray () ; sgVec2 t ;
sgSetVec3(v, -0.5f, 0.0f, 0.0f ) ; va->add(v) ;
sgSetVec3(v, 0.5f, 0.0f, 0.0f ) ; va->add(v) ;
sgSetVec3(v, -0.5f, 0.0f, 0.5f ) ; va->add(v) ;
sgSetVec3(v, 0.5f, 0.0f, 0.5f ) ; va->add(v) ;
sgSetVec3(v, -0.5f, 0.0f, 0.0f ) ; va->add(v) ;
sgSetVec3(v, 0.5f, 0.0f, 0.0f ) ; va->add(v) ;
sgSetVec3(n, 0.0f, 1.0f, 0.0f ) ; na->add(n) ;
sgCopyVec3 ( c, colour ) ; c[ 3 ] = 1.0f ; ca->add(c) ;
sgSetVec2(t, 0.0f, 0.0f ) ; ta->add(t) ;
sgSetVec2(t, 1.0f, 0.0f ) ; ta->add(t) ;
sgSetVec2(t, 0.0f, 1.0f ) ; ta->add(t) ;
sgSetVec2(t, 1.0f, 1.0f ) ; ta->add(t) ;
sgSetVec2(t, 0.0f, 0.0f ) ; ta->add(t) ;
sgSetVec2(t, 1.0f, 0.0f ) ; ta->add(t) ;
ssgLeaf *gset = new ssgVtxTable ( GL_TRIANGLE_STRIP, va, na, ta, ca ) ;
gset->setState(material_manager->getMaterial("herring.rgb")->getState()) ;
Shadow* sh = new Shadow ( -0.5f, 0.5f, -0.25f, 0.25f ) ;
ssgTransform* tr = new ssgTransform () ;
tr -> addKid ( sh -> getRoot () ) ;
tr -> addKid ( gset ) ;
tr -> ref () ; /* Make sure it doesn't get deleted by mistake */
m_all_models[name] = tr;
} // CreateDefaultHerring
//-----------------------------------------------------------------------------
void HerringManager::loadHerringStyle(const std::string filename)
{
if(filename.length()==0) return;
const lisp::Lisp* root = 0;
lisp::Parser parser;
root = parser.parse(file_manager->getConfigFile(filename + ".herring"));
const lisp::Lisp* herring_node = root->getLisp("herring");
if(!herring_node)
{
char msg[MAX_ERROR_MESSAGE_LENGTH];
snprintf(msg, sizeof(msg), "Couldn't load map '%s': no herring node.",
filename.c_str());
delete root;
throw std::runtime_error(msg);
delete root;
}
setHerring(herring_node, "red", HE_RED );
setHerring(herring_node, "green", HE_GREEN );
setHerring(herring_node, "gold" ,HE_GOLD );
setHerring(herring_node, "silver",HE_SILVER);
delete root;
} // loadHerringStyle
//-----------------------------------------------------------------------------
void HerringManager::setHerring(const lisp::Lisp *herring_node,
const char *colour, herringType type)
{
std::string name;
herring_node->get(colour, name);
if(name.size()>0)
{
m_herring_model[type]=m_all_models[name];
}
} // setHerring