250 lines
6.8 KiB
C++
250 lines
6.8 KiB
C++
|
// $Id$
|
||
|
//
|
||
|
// SuperTuxKart - a fun racing game with go-kart
|
||
|
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
|
||
|
//
|
||
|
// 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 "loader.hpp"
|
||
|
#include "material_manager.hpp"
|
||
|
#include "material.hpp"
|
||
|
#include "translation.hpp"
|
||
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
||
|
# define snprintf _snprintf
|
||
|
#endif
|
||
|
|
||
|
ssgState *fuzzy_gst;
|
||
|
|
||
|
MaterialManager *material_manager=0;
|
||
|
|
||
|
MaterialManager::MaterialManager()
|
||
|
{
|
||
|
/* Create list - and default material zero */
|
||
|
|
||
|
m_materials.reserve(100);
|
||
|
// We can't call init/loadMaterial here, since the global variable
|
||
|
// material_manager has not yet been initialised, and
|
||
|
// material_manager is used in the Material constructor.
|
||
|
// Therefore, the code for loading the material had to
|
||
|
// be moved into a separate function.
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int MaterialManager::addEntity(Material *m)
|
||
|
{
|
||
|
m_materials.push_back(m);
|
||
|
return m_materials.size()-1;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void MaterialManager::reInit()
|
||
|
{
|
||
|
for(std::vector<Material*>::const_iterator i=m_materials.begin();
|
||
|
i!=m_materials.end(); i++)
|
||
|
{
|
||
|
delete *i;
|
||
|
}
|
||
|
m_materials.clear();
|
||
|
loadMaterial();
|
||
|
} // reInit
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void MaterialManager::loadMaterial()
|
||
|
{
|
||
|
// Create the default/empty material. The Material
|
||
|
// constructor will add the material to (this) material_manager
|
||
|
new Material ();
|
||
|
|
||
|
char fname [ 1000 ] ;
|
||
|
|
||
|
sprintf ( fname, "data/materials.dat" ) ;
|
||
|
std::string path = loader->getPath(fname);
|
||
|
FILE *fd = fopen ( path.c_str(), "r" ) ;
|
||
|
|
||
|
if ( fd == NULL )
|
||
|
{
|
||
|
char msg[MAX_ERROR_MESSAGE_LENGTH];
|
||
|
snprintf(msg, sizeof(msg), "FATAL: File '%s' not found\n", fname);
|
||
|
throw std::runtime_error(msg);
|
||
|
}
|
||
|
|
||
|
while ( parseMaterial ( fd ) )
|
||
|
/* Read file */ ;
|
||
|
|
||
|
fclose ( fd ) ;
|
||
|
|
||
|
ssgSetAppStateCallback ( getAppState ) ;
|
||
|
fuzzy_gst = getMaterial("fuzzy.rgb")->getState();
|
||
|
} // MaterialManager
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
char* MaterialManager::parseFileName(char **str)
|
||
|
{
|
||
|
char *p = *str ;
|
||
|
|
||
|
/* Skip leading spaces */
|
||
|
while ( *p <= ' ' && *p != '\0' ) p++ ;
|
||
|
|
||
|
/* Skip blank lines and comments */
|
||
|
if ( *p == '#' || *p == '\0' )
|
||
|
return NULL ;
|
||
|
|
||
|
if ( *p != '"' )
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Material file entries must start with '\"'\n"
|
||
|
"ERROR: Offending line is '%s'\n", *str);
|
||
|
return NULL ;
|
||
|
}
|
||
|
|
||
|
/* Filename? */
|
||
|
char *f = ++p ;
|
||
|
while ( *p != '"' && *p != '\0' ) p++ ;
|
||
|
|
||
|
if ( *p != '"' )
|
||
|
{
|
||
|
fprintf(stderr,
|
||
|
"ERROR: Unterminated string constant '%s' in materials file.\n", *str ) ;
|
||
|
return NULL ;
|
||
|
}
|
||
|
|
||
|
*p = '\0' ;
|
||
|
*str = ++p ;
|
||
|
|
||
|
return f ;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int MaterialManager::parseMaterial ( FILE *fd )
|
||
|
{
|
||
|
char str [ 1024 ] ;
|
||
|
|
||
|
while ( ! feof ( fd ) )
|
||
|
{
|
||
|
char *s = str ;
|
||
|
|
||
|
if ( fgets ( s, 1024, fd ) == NULL )
|
||
|
return false ;
|
||
|
|
||
|
s [ strlen(s) - 1 ] = '\0' ;
|
||
|
|
||
|
char *f = parseFileName ( & s ) ;
|
||
|
|
||
|
if ( f != NULL )
|
||
|
{
|
||
|
new Material ( f, s ) ;
|
||
|
return true ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false ;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
Material *MaterialManager::getMaterial ( ssgLeaf *l )
|
||
|
{
|
||
|
return m_materials[l -> getExternalPropertyIndex ()] ;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
Material *MaterialManager::getMaterial ( const char* fname )
|
||
|
{
|
||
|
if ( fname == NULL || fname[0] == '\0' )
|
||
|
{
|
||
|
// This happens while reading the stk_config file, which contains
|
||
|
// kart_properties information (but no icon file): since at this
|
||
|
// stage loadMaterial() hasn't been called, an exception can be
|
||
|
// triggered here (as it happened with visual c++), when
|
||
|
// m_materials[0] is accessed.
|
||
|
if(m_materials.size()>=1) return m_materials[0];
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//This copy is made so the original fname is not modified
|
||
|
char *fname_copy = strdup(fname);
|
||
|
const char *fn;
|
||
|
/* Remove all leading path information. */
|
||
|
|
||
|
for ( fn = & fname_copy [ strlen ( fname_copy ) - 1 ] ;
|
||
|
fn != fname_copy && *fn != '/' ; fn-- )
|
||
|
/* Search back for a '/' */ ;
|
||
|
|
||
|
if ( *fn == '/' )
|
||
|
fn++ ;
|
||
|
|
||
|
char basename [ 1024 ] ;
|
||
|
|
||
|
strcpy ( basename, fn ) ;
|
||
|
free(fname_copy);
|
||
|
|
||
|
/* Remove last trailing extension. */
|
||
|
|
||
|
char* fno;
|
||
|
for ( fno = & basename [ strlen ( basename ) - 1 ] ; fno != basename &&
|
||
|
*fno != '.' ; fno-- )
|
||
|
/* Search back for a '.' */ ;
|
||
|
|
||
|
if ( *fno == '.' )
|
||
|
*fno = '\0' ;
|
||
|
|
||
|
|
||
|
char *fname2;
|
||
|
|
||
|
for ( int i = 0 ; i < getNumEntities () ; i++ )
|
||
|
{
|
||
|
fname2 = m_materials[i]-> getTexFname () ;
|
||
|
|
||
|
if ( fname2 != NULL && fname2[0] != '\0' )
|
||
|
{
|
||
|
char *fn2 ;
|
||
|
|
||
|
/* Remove all leading path information. */
|
||
|
|
||
|
for ( fn2 = & fname2 [ strlen ( fname2 ) -1 ] ; fn2 != fname2 &&
|
||
|
*fn2 != '/' ; fn2-- )
|
||
|
/* Search back for a '/' */ ;
|
||
|
|
||
|
if ( *fn2 == '/' )
|
||
|
fn2++ ;
|
||
|
|
||
|
char basename2 [ 1024 ] ;
|
||
|
|
||
|
strcpy ( basename2, fn2 ) ;
|
||
|
|
||
|
/* Remove last trailing extension. */
|
||
|
|
||
|
for ( fn2 = & basename2 [ strlen ( basename2 ) - 1 ] ; fn2 != basename2 &&
|
||
|
*fn2 != '.' ; fn2-- )
|
||
|
/* Search back for a '.' */ ;
|
||
|
|
||
|
if ( *fn2 == '.' )
|
||
|
*fn2 = '\0' ;
|
||
|
|
||
|
if ( strcmp ( basename, basename2 ) == 0 )
|
||
|
return m_materials[i] ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL ;
|
||
|
}
|
||
|
|
||
|
//=============================================================================
|
||
|
ssgState *getAppState ( char *fname )
|
||
|
{
|
||
|
Material *m = material_manager->getMaterial ( fname ) ;
|
||
|
return ( m == NULL ) ? NULL : m -> getState () ;
|
||
|
}
|
||
|
|