stk-code_catmod/src/loader.cpp

224 lines
6.8 KiB
C++
Raw Normal View History

// $Id: loader.cpp 1610 2008-03-01 03:18:53Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// (C) 2008 Steve Baker, 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 2
// 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 <sstream>
#include <sys/stat.h>
#include <string>
#ifdef WIN32
# include <io.h>
# include <stdio.h>
# ifndef __CYGWIN__
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
// Some portabilty defines
# endif
#endif
#include "loader.hpp"
#include "moving_physics.hpp"
#include "moving_texture.hpp"
#include "material_manager.hpp"
#include "file_manager.hpp"
#include "material.hpp"
Loader* loader = 0;
Loader::Loader()
{
m_current_callback_type = CB_COLLECTABLE;
} // Loader
//-----------------------------------------------------------------------------
Loader::~Loader()
{
} // ~Loader
//-----------------------------------------------------------------------------
void Loader::makeModelPath(char* path, const char* FNAME) const
{
if(m_is_full_path)
{
strcpy(path, FNAME);
return;
}
std::string p=file_manager->getModelFile(FNAME);
strcpy(path, p.c_str());
return;
} // makeModelPath
//-----------------------------------------------------------------------------
/** Loads a .ac model
*
* Loads the .ac model 'filename'. Callbacks contained in this file
* are stored in the callback class t. If optimise is set to false,
* the file will not be flattened, which is necessary for the kart
* models - flattening them will remove the wheel nodes, withouth
* which the wheels do not rotate.
*
* \param filename File to load
*
* \param t Callback category for callbacks included in this
* file (see callback_manager.hpp)
*
* \param optimise Default is true. If set to false, the model will not
* be flattened.
*/
ssgEntity *Loader::load(const std::string& filename, CallbackType t,
bool optimise, bool is_full_path)
{
m_current_callback_type = t;
m_is_full_path = is_full_path;
ssgEntity *obj = optimise ? ssgLoad (filename.c_str(), this)
: ssgLoadAC(filename.c_str(), this);
preProcessObj(obj, false);
return obj;
} // load
//-----------------------------------------------------------------------------
void Loader::preProcessObj ( ssgEntity *n, bool mirror )
{
if ( n == NULL ) return ;
n -> dirtyBSphere () ;
if ( n -> isAKindOf ( ssgTypeLeaf() ) )
{
if ( mirror )
for ( int i = 0 ; i < ((ssgLeaf *)n) -> getNumVertices () ; i++ )
((ssgLeaf *)n) -> getVertex ( i ) [ 0 ] *= -1.0f ;
material_manager->getMaterial((ssgLeaf *) n ) -> applyToLeaf ( (ssgLeaf *) n ) ;
return ;
}
if ( mirror && n -> isAKindOf ( ssgTypeTransform () ) )
{
sgMat4 xform ;
((ssgTransform *)n) -> getTransform ( xform ) ;
xform [ 0 ][ 0 ] *= -1.0f ;
xform [ 1 ][ 0 ] *= -1.0f ;
xform [ 2 ][ 0 ] *= -1.0f ;
xform [ 3 ][ 0 ] *= -1.0f ;
((ssgTransform *)n) -> setTransform ( xform ) ;
}
ssgBranch *b = (ssgBranch *) n ;
for ( int i = 0 ; i < b -> getNumKids () ; i++ )
preProcessObj ( b -> getKid ( i ), mirror ) ;
}
//-----------------------------------------------------------------------------
ssgBranch *Loader::animInit (char *data ) const
{
while ( ! isdigit ( *data ) && *data != '\0' )
data++ ;
const int START_LIM = strtol(data, &data, 0 );
const int END_LIM = strtol(data, &data, 0 );
const float TIME_LIM = (float)strtod(data, &data );
while ( *data <= ' ' && *data != '\0' )
data++ ;
char mode = toupper ( *data ) ;
ssgTimedSelector *br = new ssgTimedSelector;
br->setLimits (START_LIM+1, END_LIM+1 ) ;
br->setDuration(TIME_LIM ) ;
br->setMode ((mode=='O') ? SSG_ANIM_ONESHOT
: (mode=='S') ? SSG_ANIM_SWING
: SSG_ANIM_SHUTTLE ) ;
br->control (SSG_ANIM_START ) ;
return br;
} // animInit
//-----------------------------------------------------------------------------
/** Handle userdata that is stored in the model files. Mostly the userdata
* indicates that a special branch is to be created (e.g. a ssgCutout instead
* of the standard branch). But some userdata indicate that callbacks need
* to be created, which are then handled by the callback manager.
*/
ssgBranch *Loader::createBranch(char *data) const
{
if ( data == NULL || data[0] != '@' ) return NULL;
data++ ; /* Skip the '@' */
if ( strncmp("billboard", data, strlen("billboard") ) == 0 )
return new ssgCutout();
if ( strncmp("DONT_DELETE", data, strlen("DONT_DELETE") ) == 0 )
{
printf("DONT\n");
ssgBranch *br = new ssgTransform();
br->setUserData(new ssgBase());
return br;
}
if ( strncmp("invisible", data, strlen("invisible") ) == 0 )
return new ssgInvisible();
if ( strncmp ( "switch", data, strlen ( "switch" ) ) == 0 )
{
ssgSelector *sel = new ssgSelector();
sel->select(0);
return sel;
}
if ( strncmp ( "animate", data, strlen ( "animate" ) ) == 0 )
return animInit(data);
if ( strncmp ( "autodcs", data, strlen ( "autodcs" ) ) == 0 )
{
ssgTransform *br = new ssgTransform();
Callback *c = new MovingTexture(data, br);
br->setUserData(new ssgBase());
callback_manager->addCallback(c, m_current_callback_type);
return br;
}
if ( strncmp ( "autotex", data, strlen ( "autotex" ) ) == 0 )
{
ssgTexTrans *br = new ssgTexTrans();
Callback *c = new MovingTexture(data, br);
callback_manager->addCallback(c, m_current_callback_type);
return br;
}
if(strncmp("physics", data, strlen("physics")) == 0)
{
MovingPhysics *mp = new MovingPhysics(std::string(data));
callback_manager->addCallback(mp, m_current_callback_type);
return mp;
}
fprintf(stderr, "Warning: Ignoring userdata '%s'\n", data);
return NULL ;
} // createBranch