X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=radiant%2Feclass_doom3.cpp;h=4c7525ea4fdb9219bd60c0b958946954c5b2db5a;hp=217c4ec5ff105a67f183ab29e05486a81fab2c48;hb=HEAD;hpb=231225d6f97d0b926b2e896e5783cccfbc7c5619 diff --git a/radiant/eclass_doom3.cpp b/radiant/eclass_doom3.cpp index 217c4ec5..b6a53440 100644 --- a/radiant/eclass_doom3.cpp +++ b/radiant/eclass_doom3.cpp @@ -1,23 +1,23 @@ /* -Copyright (C) 2001-2006, William Joseph. -All Rights Reserved. + Copyright (C) 2001-2006, William Joseph. + All Rights Reserved. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant 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. + GtkRadiant 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. -GtkRadiant 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. + GtkRadiant 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 GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include "eclass_doom3.h" @@ -41,851 +41,746 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA class RawString { - const char* m_value; +const char* m_value; public: - RawString(const char* value) : m_value(value) - { - } - const char* c_str() const - { - return m_value; - } +RawString( const char* value ) : m_value( value ){ +} +const char* c_str() const { + return m_value; +} }; -inline bool operator<(const RawString& self, const RawString& other) -{ - return string_less_nocase(self.c_str(), other.c_str()); +inline bool operator<( const RawString& self, const RawString& other ){ + return string_less_nocase( self.c_str(), other.c_str() ); } typedef std::map EntityClasses; EntityClasses g_EntityClassDoom3_classes; -EntityClass *g_EntityClassDoom3_bad = 0; +EntityClass *g_EntityClassDoom3_bad = 0; -void EntityClassDoom3_clear() -{ - for(EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i) - { - (*i).second->free((*i).second); - } - g_EntityClassDoom3_classes.clear(); +void EntityClassDoom3_clear(){ + for ( EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i ) + { + ( *i ).second->free( ( *i ).second ); + } + g_EntityClassDoom3_classes.clear(); } // entityClass will be inserted only if another of the same name does not already exist. // if entityClass was inserted, the same object is returned, otherwise the already-existing object is returned. -EntityClass* EntityClassDoom3_insertUnique(EntityClass* entityClass) -{ - return (*g_EntityClassDoom3_classes.insert(EntityClasses::value_type(entityClass->name(), entityClass)).first).second; +EntityClass* EntityClassDoom3_insertUnique( EntityClass* entityClass ){ + return ( *g_EntityClassDoom3_classes.insert( EntityClasses::value_type( entityClass->name(), entityClass ) ).first ).second; } -void EntityClassDoom3_forEach(EntityClassVisitor& visitor) -{ - for(EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i) - { - visitor.visit((*i).second); - } +void EntityClassDoom3_forEach( EntityClassVisitor& visitor ){ + for ( EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i ) + { + visitor.visit( ( *i ).second ); + } } -inline void printParseError(const char* message) -{ - globalErrorStream() << message; +inline void printParseError( const char* message ){ + globalErrorStream() << message; } -#define PARSE_RETURN_FALSE_IF_FAIL(expression) if(!(expression)) { printParseError(FILE_LINE "\nparse failed: " #expression "\n"); return false; } else +#define PARSE_RETURN_FALSE_IF_FAIL( expression ) do{ if ( !( expression ) ) { printParseError( FILE_LINE "\nparse failed: " # expression "\n" ); return false; } }while( 0 ) -bool EntityClassDoom3_parseToken(Tokeniser& tokeniser) -{ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL(token != 0); - return true; +bool EntityClassDoom3_parseToken( Tokeniser& tokeniser ){ + const char* token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); + return true; } -bool EntityClassDoom3_parseToken(Tokeniser& tokeniser, const char* string) -{ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL(token != 0); - return string_equal(token, string); +bool EntityClassDoom3_parseToken( Tokeniser& tokeniser, const char* string ){ + const char* token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); + return string_equal( token, string ); } -bool EntityClassDoom3_parseString(Tokeniser& tokeniser, const char*& s) -{ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL(token != 0); - s = token; - return true; +bool EntityClassDoom3_parseString( Tokeniser& tokeniser, const char*& s ){ + const char* token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); + s = token; + return true; } -bool EntityClassDoom3_parseString(Tokeniser& tokeniser, CopiedString& s) -{ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL(token != 0); - s = token; - return true; +bool EntityClassDoom3_parseString( Tokeniser& tokeniser, CopiedString& s ){ + const char* token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); + s = token; + return true; } -bool EntityClassDoom3_parseString(Tokeniser& tokeniser, StringOutputStream& s) -{ - const char* token = tokeniser.getToken(); - PARSE_RETURN_FALSE_IF_FAIL(token != 0); - s << token; - return true; +bool EntityClassDoom3_parseString( Tokeniser& tokeniser, StringOutputStream& s ){ + const char* token = tokeniser.getToken(); + PARSE_RETURN_FALSE_IF_FAIL( token != 0 ); + s << token; + return true; } -bool EntityClassDoom3_parseUnknown(Tokeniser& tokeniser) -{ - //const char* name = - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - - //globalOutputStream() << "parsing unknown block " << makeQuoted(name) << "\n"; - - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - std::size_t depth = 1; - for(;;) - { - const char* token; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); - if(string_equal(token, "}")) - { - if(--depth == 0) - { - tokeniser.nextLine(); - break; - } - } - else if(string_equal(token, "{")) - { - ++depth; - } - tokeniser.nextLine(); - } - return true; +bool EntityClassDoom3_parseUnknown( Tokeniser& tokeniser ){ + //const char* name = + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + + //globalOutputStream() << "parsing unknown block " << makeQuoted(name) << "\n"; + + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + std::size_t depth = 1; + for (;; ) + { + const char* token; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); + if ( string_equal( token, "}" ) ) { + if ( --depth == 0 ) { + tokeniser.nextLine(); + break; + } + } + else if ( string_equal( token, "{" ) ) { + ++depth; + } + tokeniser.nextLine(); + } + return true; } class Model { public: - bool m_resolved; - CopiedString m_mesh; - CopiedString m_skin; - CopiedString m_parent; - typedef std::map Anims; - Anims m_anims; - Model() : m_resolved(false) - { - } +bool m_resolved; +CopiedString m_mesh; +CopiedString m_skin; +CopiedString m_parent; +typedef std::map Anims; +Anims m_anims; +Model() : m_resolved( false ){ +} }; typedef std::map Models; Models g_models; -void Model_resolveInheritance(const char* name, Model& model) -{ - if(model.m_resolved == false) - { - model.m_resolved = true; - - if(!string_empty(model.m_parent.c_str())) - { - Models::iterator i = g_models.find(model.m_parent); - if(i == g_models.end()) - { - globalErrorStream() << "model " << name << " inherits unknown model " << model.m_parent.c_str() << "\n"; - } - else - { - Model_resolveInheritance((*i).first.c_str(), (*i).second); - model.m_mesh = (*i).second.m_mesh; - model.m_skin = (*i).second.m_skin; - } - } - } -} - -bool EntityClassDoom3_parseModel(Tokeniser& tokeniser) -{ - const char* name; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, name)); - - Model& model = g_models[name]; - - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - for(;;) - { - const char* parameter; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, parameter)); - if(string_equal(parameter, "}")) - { - tokeniser.nextLine(); - break; - } - else if(string_equal(parameter, "inherit")) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, model.m_parent)); - tokeniser.nextLine(); - } - else if(string_equal(parameter, "remove")) - { - //const char* remove = - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - tokeniser.nextLine(); - } - else if(string_equal(parameter, "mesh")) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, model.m_mesh)); - tokeniser.nextLine(); - } - else if(string_equal(parameter, "skin")) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, model.m_skin)); - tokeniser.nextLine(); - } - else if(string_equal(parameter, "offset")) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "(")); - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, ")")); - tokeniser.nextLine(); - } - else if(string_equal(parameter, "channel")) - { - //const char* channelName = - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "(")); - for(;;) - { - const char* end; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, end)); - if(string_equal(end, ")")) - { - tokeniser.nextLine(); - break; - } - } - } - else if(string_equal(parameter, "anim")) - { - CopiedString animName; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, animName)); - const char* animFile; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, animFile)); - model.m_anims.insert(Model::Anims::value_type(animName, animFile)); - - const char* token; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); - - while(string_equal(token, ",")) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, animFile)); - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); - } - - if(string_equal(token, "{")) - { - for(;;) - { - const char* end; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, end)); - if(string_equal(end, "}")) - { - tokeniser.nextLine(); - break; - } - tokeniser.nextLine(); - } - } - else - { - tokeniser.ungetToken(); - } - } - else - { - globalErrorStream() << "unknown model parameter: " << makeQuoted(parameter) << "\n"; - return false; - } - tokeniser.nextLine(); - } - return true; -} - -inline bool char_isSpaceOrTab(char c) -{ - return c == ' ' || c == '\t'; -} - -inline bool char_isNotSpaceOrTab(char c) -{ - return !char_isSpaceOrTab(c); +void Model_resolveInheritance( const char* name, Model& model ){ + if ( model.m_resolved == false ) { + model.m_resolved = true; + + if ( !string_empty( model.m_parent.c_str() ) ) { + Models::iterator i = g_models.find( model.m_parent ); + if ( i == g_models.end() ) { + globalErrorStream() << "model " << name << " inherits unknown model " << model.m_parent.c_str() << "\n"; + } + else + { + Model_resolveInheritance( ( *i ).first.c_str(), ( *i ).second ); + model.m_mesh = ( *i ).second.m_mesh; + model.m_skin = ( *i ).second.m_skin; + } + } + } +} + +bool EntityClassDoom3_parseModel( Tokeniser& tokeniser ){ + const char* name; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, name ) ); + + Model& model = g_models[name]; + + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + for (;; ) + { + const char* parameter; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, parameter ) ); + if ( string_equal( parameter, "}" ) ) { + tokeniser.nextLine(); + break; + } + else if ( string_equal( parameter, "inherit" ) ) { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, model.m_parent ) ); + tokeniser.nextLine(); + } + else if ( string_equal( parameter, "remove" ) ) { + //const char* remove = + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + tokeniser.nextLine(); + } + else if ( string_equal( parameter, "mesh" ) ) { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, model.m_mesh ) ); + tokeniser.nextLine(); + } + else if ( string_equal( parameter, "skin" ) ) { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, model.m_skin ) ); + tokeniser.nextLine(); + } + else if ( string_equal( parameter, "offset" ) ) { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "(" ) ); + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, ")" ) ); + tokeniser.nextLine(); + } + else if ( string_equal( parameter, "channel" ) ) { + //const char* channelName = + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "(" ) ); + for (;; ) + { + const char* end; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, end ) ); + if ( string_equal( end, ")" ) ) { + tokeniser.nextLine(); + break; + } + } + } + else if ( string_equal( parameter, "anim" ) ) { + CopiedString animName; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, animName ) ); + const char* animFile; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, animFile ) ); + model.m_anims.insert( Model::Anims::value_type( animName, animFile ) ); + + const char* token; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); + + while ( string_equal( token, "," ) ) + { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, animFile ) ); + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); + } + + if ( string_equal( token, "{" ) ) { + for (;; ) + { + const char* end; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, end ) ); + if ( string_equal( end, "}" ) ) { + tokeniser.nextLine(); + break; + } + tokeniser.nextLine(); + } + } + else + { + tokeniser.ungetToken(); + } + } + else + { + globalErrorStream() << "unknown model parameter: " << makeQuoted( parameter ) << "\n"; + return false; + } + tokeniser.nextLine(); + } + return true; +} + +inline bool char_isSpaceOrTab( char c ){ + return c == ' ' || c == '\t'; +} + +inline bool char_isNotSpaceOrTab( char c ){ + return !char_isSpaceOrTab( c ); } template -inline const char* string_find_if(const char* string, Predicate predicate) -{ - for(; *string != 0; ++string) - { - if(predicate(*string)) - { - return string; - } - } - return string; -} - -inline const char* string_findFirstSpaceOrTab(const char* string) -{ - return string_find_if(string, char_isSpaceOrTab); -} - -inline const char* string_findFirstNonSpaceOrTab(const char* string) -{ - return string_find_if(string, char_isNotSpaceOrTab); -} - - -static bool EntityClass_parse(EntityClass& entityClass, Tokeniser& tokeniser) -{ - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, entityClass.m_name)); - - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser, "{")); - tokeniser.nextLine(); - - StringOutputStream usage(256); - StringOutputStream description(256); - CopiedString* currentDescription = 0; - StringOutputStream* currentString = 0; - - for(;;) - { - const char* key; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, key)); - - const char* last = string_findFirstSpaceOrTab(key); - CopiedString first(StringRange(key, last)); - - if(!string_empty(last)) - { - last = string_findFirstNonSpaceOrTab(last); - } - - if(currentString != 0 && string_equal(key, "\\")) - { - tokeniser.nextLine(); - *currentString << " "; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, *currentString)); - continue; - } - - if(currentDescription != 0) - { - *currentDescription = description.c_str(); - description.clear(); - currentDescription = 0; - } - currentString = 0; - - if(string_equal(key, "}")) - { - tokeniser.nextLine(); - break; - } - else if(string_equal(key, "model")) - { - const char* token; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); - entityClass.fixedsize = true; - StringOutputStream buffer(256); - buffer << PathCleaned(token); - entityClass.m_modelpath = buffer.c_str(); - } - else if(string_equal(key, "editor_color")) - { - const char* value; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); - if(!string_empty(value)) - { - entityClass.colorSpecified = true; - bool success = string_parse_vector3(value, entityClass.color); - ASSERT_MESSAGE(success, "editor_color: parse error"); - } - } - else if(string_equal(key, "editor_ragdoll")) - { - //bool ragdoll = atoi(tokeniser.getToken()) != 0; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - } - else if(string_equal(key, "editor_mins")) - { - entityClass.sizeSpecified = true; - const char* value; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); - if(!string_empty(value) && !string_equal(value, "?")) - { - entityClass.fixedsize = true; - bool success = string_parse_vector3(value, entityClass.mins); - ASSERT_MESSAGE(success, "editor_mins: parse error"); - } - } - else if(string_equal(key, "editor_maxs")) - { - entityClass.sizeSpecified = true; - const char* value; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); - if(!string_empty(value) && !string_equal(value, "?")) - { - entityClass.fixedsize = true; - bool success = string_parse_vector3(value, entityClass.maxs); - ASSERT_MESSAGE(success, "editor_maxs: parse error"); - } - } - else if(string_equal(key, "editor_usage")) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, usage)); - currentString = &usage; - } - else if(string_equal_n(key, "editor_usage", 12)) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, usage)); - currentString = &usage; - } - else if(string_equal(key, "editor_rotatable") - || string_equal(key, "editor_showangle") - || string_equal(key, "editor_showangles") // typo? in prey movables.def - || string_equal(key, "editor_mover") - || string_equal(key, "editor_model") - || string_equal(key, "editor_material") - || string_equal(key, "editor_combatnode") - || (!string_empty(last) && string_equal(first.c_str(), "editor_gui")) - || string_equal_n(key, "editor_copy", 11)) - { - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - } - else if(!string_empty(last) && (string_equal(first.c_str(), "editor_var") || string_equal(first.c_str(), "editor_string"))) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "string"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(!string_empty(last) && string_equal(first.c_str(), "editor_float")) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "string"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(!string_empty(last) && string_equal(first.c_str(), "editor_snd")) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "sound"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(!string_empty(last) && string_equal(first.c_str(), "editor_bool")) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "boolean"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(!string_empty(last) && string_equal(first.c_str(), "editor_int")) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "integer"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(!string_empty(last) && string_equal(first.c_str(), "editor_model")) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "model"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(!string_empty(last) && string_equal(first.c_str(), "editor_color")) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "color"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(!string_empty(last) && (string_equal(first.c_str(), "editor_material") || string_equal(first.c_str(), "editor_mat"))) - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, last).second; - attribute.m_type = "shader"; - currentDescription = &attribute.m_description; - currentString = &description; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, description)); - } - else if(string_equal(key, "inherit")) - { - entityClass.inheritanceResolved = false; - ASSERT_MESSAGE(entityClass.m_parent.empty(), "only one 'inherit' supported per entityDef"); - const char* token; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, token)); - entityClass.m_parent.push_back(token); - } - // begin quake4-specific keys - else if(string_equal(key, "editor_targetonsel")) - { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - } - else if(string_equal(key, "editor_menu")) - { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - } - else if(string_equal(key, "editor_ignore")) - { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - } - // end quake4-specific keys - // begin ignore prey (unknown/unused?) entity keys - else if(string_equal(key, "editor_light") - || string_equal(key, "editor_def def_debrisspawner") - || string_equal(key, "editor_def def_drop") - || string_equal(key, "editor_def def_guihand") - || string_equal(key, "editor_def def_mine")) - { - //const char* value = - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseToken(tokeniser)); - } - // end ignore prey entity keys - else - { - CopiedString tmp(key); - ASSERT_MESSAGE(!string_equal_n(key, "editor_", 7), "unsupported editor key: " << makeQuoted(key)); - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, key).second; - attribute.m_type = "string"; - const char* value; - PARSE_RETURN_FALSE_IF_FAIL(EntityClassDoom3_parseString(tokeniser, value)); - if(string_equal(value, "}")) // hack for quake4 powerups.def bug - { - globalErrorStream() << "entityDef " << makeQuoted(entityClass.m_name.c_str()) << " key " << makeQuoted(tmp.c_str()) << " has no value\n"; - break; - } - else - { - attribute.m_value = value; - } - } - tokeniser.nextLine(); - } - - entityClass.m_comments = usage.c_str(); - - if(string_equal(entityClass.m_name.c_str(), "light")) - { - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, "light_radius").second; - attribute.m_type = "vector3"; - attribute.m_value = "300 300 300"; - } - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, "light_center").second; - attribute.m_type = "vector3"; - } - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, "noshadows").second; - attribute.m_type = "boolean"; - attribute.m_value = "0"; - } - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, "nospecular").second; - attribute.m_type = "boolean"; - attribute.m_value = "0"; - } - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, "nodiffuse").second; - attribute.m_type = "boolean"; - attribute.m_value = "0"; - } - { - EntityClassAttribute& attribute = EntityClass_insertAttribute(entityClass, "falloff").second; - attribute.m_type = "real"; - } - } - - return true; -} - -bool EntityClassDoom3_parseEntityDef(Tokeniser& tokeniser) -{ - EntityClass* entityClass = Eclass_Alloc(); - entityClass->free = &Eclass_Free; - - if(!EntityClass_parse(*entityClass, tokeniser)) - { - eclass_capture_state(entityClass); // finish constructing the entity so that it can be destroyed cleanly. - entityClass->free(entityClass); - return false; - } - - EntityClass* inserted = EntityClassDoom3_insertUnique(entityClass); - if(inserted != entityClass) - { - globalErrorStream() << "entityDef " << entityClass->name() << " is already defined, second definition ignored\n"; - eclass_capture_state(entityClass); // finish constructing the entity so that it can be destroyed cleanly. - entityClass->free(entityClass); - } - return true; -} - -bool EntityClassDoom3_parseBlock(Tokeniser& tokeniser, const char* blockType) -{ - if(string_equal(blockType, "entityDef")) - { - return EntityClassDoom3_parseEntityDef(tokeniser); - } - else if(string_equal(blockType, "model")) - { - return EntityClassDoom3_parseModel(tokeniser); - } - else - { - return EntityClassDoom3_parseUnknown(tokeniser); - } -} - -bool EntityClassDoom3_parse(TextInputStream& inputStream, const char* filename) -{ - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(inputStream); - - tokeniser.nextLine(); - - for(;;) - { - const char* blockType = tokeniser.getToken(); - if(blockType == 0) - { - return true; - } - CopiedString tmp(blockType); - if(!EntityClassDoom3_parseBlock(tokeniser, tmp.c_str())) - { - globalErrorStream() << GlobalFileSystem().findFile(filename) << filename << ":" << (unsigned int)tokeniser.getLine() << ": " << tmp.c_str() << " parse failed, skipping rest of file\n"; - return false; - } - } - - tokeniser.release(); -} - - -void EntityClassDoom3_loadFile(const char* filename) -{ - globalOutputStream() << "parsing entity classes from " << makeQuoted(filename) << "\n"; - - StringOutputStream fullname(256); - fullname << "def/" << filename; - - ArchiveTextFile* file = GlobalFileSystem().openTextFile(fullname.c_str()); - if(file != 0) - { - EntityClassDoom3_parse(file->getInputStream(), fullname.c_str()); - file->release(); - } -} - -EntityClass* EntityClassDoom3_findOrInsert(const char *name, bool has_brushes) -{ - ASSERT_NOTNULL(name); - - if(string_empty(name)) - { - return g_EntityClassDoom3_bad; - } - - EntityClasses::iterator i = g_EntityClassDoom3_classes.find(name); - if(i != g_EntityClassDoom3_classes.end() - //&& string_equal((*i).first, name) - ) - { - return (*i).second; - } - - EntityClass* e = EntityClass_Create_Default(name, has_brushes); - EntityClass* inserted = EntityClassDoom3_insertUnique(e); - ASSERT_MESSAGE(inserted == e, ""); - return inserted; -} - -const ListAttributeType* EntityClassDoom3_findListType(const char* name) -{ - return 0; -} - - -void EntityClass_resolveInheritance(EntityClass* derivedClass) -{ - if(derivedClass->inheritanceResolved == false) - { - derivedClass->inheritanceResolved = true; - EntityClasses::iterator i = g_EntityClassDoom3_classes.find(derivedClass->m_parent.front().c_str()); - if(i == g_EntityClassDoom3_classes.end()) - { - globalErrorStream() << "failed to find entityDef " << makeQuoted(derivedClass->m_parent.front().c_str()) << " inherited by " << makeQuoted(derivedClass->m_name.c_str()) << "\n"; - } - else - { - EntityClass* parentClass = (*i).second; - EntityClass_resolveInheritance(parentClass); - if(!derivedClass->colorSpecified) - { - derivedClass->colorSpecified = parentClass->colorSpecified; - derivedClass->color = parentClass->color; - } - if(!derivedClass->sizeSpecified) - { - derivedClass->sizeSpecified = parentClass->sizeSpecified; - derivedClass->mins = parentClass->mins; - derivedClass->maxs = parentClass->maxs; - derivedClass->fixedsize = parentClass->fixedsize; - } - - for(EntityClassAttributes::iterator j = parentClass->m_attributes.begin(); j != parentClass->m_attributes.end(); ++j) - { - EntityClass_insertAttribute(*derivedClass, (*j).first.c_str(), (*j).second); - } - } - } +inline const char* string_find_if( const char* string, Predicate predicate ){ + for (; *string != 0; ++string ) + { + if ( predicate( *string ) ) { + return string; + } + } + return string; +} + +inline const char* string_findFirstSpaceOrTab( const char* string ){ + return string_find_if( string, char_isSpaceOrTab ); +} + +inline const char* string_findFirstNonSpaceOrTab( const char* string ){ + return string_find_if( string, char_isNotSpaceOrTab ); +} + + +static bool EntityClass_parse( EntityClass& entityClass, Tokeniser& tokeniser ){ + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, entityClass.m_name ) ); + + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser, "{" ) ); + tokeniser.nextLine(); + + StringOutputStream usage( 256 ); + StringOutputStream description( 256 ); + CopiedString* currentDescription = 0; + StringOutputStream* currentString = 0; + + for (;; ) + { + const char* key; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, key ) ); + + const char* last = string_findFirstSpaceOrTab( key ); + CopiedString first( StringRange( key, last ) ); + + if ( !string_empty( last ) ) { + last = string_findFirstNonSpaceOrTab( last ); + } + + if ( currentString != 0 && string_equal( key, "\\" ) ) { + tokeniser.nextLine(); + *currentString << " "; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, *currentString ) ); + continue; + } + + if ( currentDescription != 0 ) { + *currentDescription = description.c_str(); + description.clear(); + currentDescription = 0; + } + currentString = 0; + + if ( string_equal( key, "}" ) ) { + tokeniser.nextLine(); + break; + } + else if ( string_equal( key, "model" ) ) { + const char* token; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); + entityClass.fixedsize = true; + StringOutputStream buffer( 256 ); + buffer << PathCleaned( token ); + entityClass.m_modelpath = buffer.c_str(); + } + else if ( string_equal( key, "editor_color" ) ) { + const char* value; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); + if ( !string_empty( value ) ) { + entityClass.colorSpecified = true; + bool success = string_parse_vector3( value, entityClass.color ); + ASSERT_MESSAGE( success, "editor_color: parse error" ); + } + } + else if ( string_equal( key, "editor_ragdoll" ) ) { + //bool ragdoll = atoi(tokeniser.getToken()) != 0; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + } + else if ( string_equal( key, "editor_mins" ) ) { + entityClass.sizeSpecified = true; + const char* value; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); + if ( !string_empty( value ) && !string_equal( value, "?" ) ) { + entityClass.fixedsize = true; + bool success = string_parse_vector3( value, entityClass.mins ); + ASSERT_MESSAGE( success, "editor_mins: parse error" ); + } + } + else if ( string_equal( key, "editor_maxs" ) ) { + entityClass.sizeSpecified = true; + const char* value; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); + if ( !string_empty( value ) && !string_equal( value, "?" ) ) { + entityClass.fixedsize = true; + bool success = string_parse_vector3( value, entityClass.maxs ); + ASSERT_MESSAGE( success, "editor_maxs: parse error" ); + } + } + else if ( string_equal( key, "editor_usage" ) ) { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) ); + currentString = &usage; + } + else if ( string_equal_n( key, "editor_usage", 12 ) ) { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, usage ) ); + currentString = &usage; + } + else if ( string_equal( key, "editor_rotatable" ) + || string_equal( key, "editor_showangle" ) + || string_equal( key, "editor_showangles" ) // typo? in prey movables.def + || string_equal( key, "editor_mover" ) + || string_equal( key, "editor_model" ) + || string_equal( key, "editor_material" ) + || string_equal( key, "editor_combatnode" ) + || ( !string_empty( last ) && string_equal( first.c_str(), "editor_gui" ) ) + || string_equal_n( key, "editor_copy", 11 ) ) { + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + } + else if ( !string_empty( last ) && ( string_equal( first.c_str(), "editor_var" ) || string_equal( first.c_str(), "editor_string" ) ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "string"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_float" ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "string"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_snd" ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "sound"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_bool" ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "boolean"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_int" ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "integer"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_model" ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "model"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( !string_empty( last ) && string_equal( first.c_str(), "editor_color" ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "color"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( !string_empty( last ) && ( string_equal( first.c_str(), "editor_material" ) || string_equal( first.c_str(), "editor_mat" ) ) ) { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, last ).second; + attribute.m_type = "shader"; + currentDescription = &attribute.m_description; + currentString = &description; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, description ) ); + } + else if ( string_equal( key, "inherit" ) ) { + entityClass.inheritanceResolved = false; + ASSERT_MESSAGE( entityClass.m_parent.empty(), "only one 'inherit' supported per entityDef" ); + const char* token; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); + entityClass.m_parent.push_back( token ); + } + // begin quake4-specific keys + else if ( string_equal( key, "editor_targetonsel" ) ) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + } + else if ( string_equal( key, "editor_menu" ) ) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + } + else if ( string_equal( key, "editor_ignore" ) ) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + } + // end quake4-specific keys + // begin ignore prey (unknown/unused?) entity keys + else if ( string_equal( key, "editor_light" ) + || string_equal( key, "editor_def def_debrisspawner" ) + || string_equal( key, "editor_def def_drop" ) + || string_equal( key, "editor_def def_guihand" ) + || string_equal( key, "editor_def def_mine" ) ) { + //const char* value = + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseToken( tokeniser ) ); + } + // end ignore prey entity keys + else + { + CopiedString tmp( key ); + if ( string_equal_n( key, "editor_", 7 ) ) { + globalErrorStream() << "unsupported editor key " << makeQuoted( key ) ; + } + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, key ).second; + attribute.m_type = "string"; + const char* value; + PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, value ) ); + if ( string_equal( value, "}" ) ) { // hack for quake4 powerups.def bug + globalErrorStream() << "entityDef " << makeQuoted( entityClass.m_name.c_str() ) << " key " << makeQuoted( tmp.c_str() ) << " has no value\n"; + break; + } + else + { + attribute.m_value = value; + } + } + tokeniser.nextLine(); + } + + entityClass.m_comments = usage.c_str(); + + if ( string_equal( entityClass.m_name.c_str(), "light" ) ) { + { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "light_radius" ).second; + attribute.m_type = "vector3"; + attribute.m_value = "300 300 300"; + } + { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "light_center" ).second; + attribute.m_type = "vector3"; + } + { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "noshadows" ).second; + attribute.m_type = "boolean"; + attribute.m_value = "0"; + } + { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "nospecular" ).second; + attribute.m_type = "boolean"; + attribute.m_value = "0"; + } + { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "nodiffuse" ).second; + attribute.m_type = "boolean"; + attribute.m_value = "0"; + } + { + EntityClassAttribute& attribute = EntityClass_insertAttribute( entityClass, "falloff" ).second; + attribute.m_type = "real"; + } + } + + return true; +} + +bool EntityClassDoom3_parseEntityDef( Tokeniser& tokeniser ){ + EntityClass* entityClass = Eclass_Alloc(); + entityClass->free = &Eclass_Free; + + if ( !EntityClass_parse( *entityClass, tokeniser ) ) { + eclass_capture_state( entityClass ); // finish constructing the entity so that it can be destroyed cleanly. + entityClass->free( entityClass ); + return false; + } + + EntityClass* inserted = EntityClassDoom3_insertUnique( entityClass ); + if ( inserted != entityClass ) { + globalErrorStream() << "entityDef " << entityClass->name() << " is already defined, second definition ignored\n"; + eclass_capture_state( entityClass ); // finish constructing the entity so that it can be destroyed cleanly. + entityClass->free( entityClass ); + } + return true; +} + +bool EntityClassDoom3_parseBlock( Tokeniser& tokeniser, const char* blockType ){ + if ( string_equal( blockType, "entityDef" ) ) { + return EntityClassDoom3_parseEntityDef( tokeniser ); + } + else if ( string_equal( blockType, "model" ) ) { + return EntityClassDoom3_parseModel( tokeniser ); + } + else + { + return EntityClassDoom3_parseUnknown( tokeniser ); + } +} + +bool EntityClassDoom3_parse( TextInputStream& inputStream, const char* filename ){ + Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser( inputStream ); + + tokeniser.nextLine(); + + for (;; ) + { + const char* blockType = tokeniser.getToken(); + if ( blockType == 0 ) { + return true; + } + CopiedString tmp( blockType ); + if ( !EntityClassDoom3_parseBlock( tokeniser, tmp.c_str() ) ) { + globalErrorStream() << GlobalFileSystem().findFile( filename ) << filename << ":" << (unsigned int)tokeniser.getLine() << ": " << tmp.c_str() << " parse failed, skipping rest of file\n"; + return false; + } + } + + tokeniser.release(); +} + + +void EntityClassDoom3_loadFile( const char* filename ){ + globalOutputStream() << "parsing entity classes from " << makeQuoted( filename ) << "\n"; + + StringOutputStream fullname( 256 ); + fullname << "def/" << filename; + + ArchiveTextFile* file = GlobalFileSystem().openTextFile( fullname.c_str() ); + if ( file != 0 ) { + EntityClassDoom3_parse( file->getInputStream(), fullname.c_str() ); + file->release(); + } +} + +EntityClass* EntityClassDoom3_findOrInsert( const char *name, bool has_brushes ){ + ASSERT_NOTNULL( name ); + + if ( string_empty( name ) ) { + return g_EntityClassDoom3_bad; + } + + EntityClasses::iterator i = g_EntityClassDoom3_classes.find( name ); + if ( i != g_EntityClassDoom3_classes.end() + //&& string_equal((*i).first, name) + ) { + return ( *i ).second; + } + + EntityClass* e = EntityClass_Create_Default( name, has_brushes ); + EntityClass* inserted = EntityClassDoom3_insertUnique( e ); + ASSERT_MESSAGE( inserted == e, "" ); + return inserted; +} + +const ListAttributeType* EntityClassDoom3_findListType( const char* name ){ + return 0; +} + + +void EntityClass_resolveInheritance( EntityClass* derivedClass ){ + if ( derivedClass->inheritanceResolved == false ) { + derivedClass->inheritanceResolved = true; + EntityClasses::iterator i = g_EntityClassDoom3_classes.find( derivedClass->m_parent.front().c_str() ); + if ( i == g_EntityClassDoom3_classes.end() ) { + globalErrorStream() << "failed to find entityDef " << makeQuoted( derivedClass->m_parent.front().c_str() ) << " inherited by " << makeQuoted( derivedClass->m_name.c_str() ) << "\n"; + } + else + { + EntityClass* parentClass = ( *i ).second; + EntityClass_resolveInheritance( parentClass ); + if ( !derivedClass->colorSpecified ) { + derivedClass->colorSpecified = parentClass->colorSpecified; + derivedClass->color = parentClass->color; + } + if ( !derivedClass->sizeSpecified ) { + derivedClass->sizeSpecified = parentClass->sizeSpecified; + derivedClass->mins = parentClass->mins; + derivedClass->maxs = parentClass->maxs; + derivedClass->fixedsize = parentClass->fixedsize; + } + + for ( EntityClassAttributes::iterator j = parentClass->m_attributes.begin(); j != parentClass->m_attributes.end(); ++j ) + { + EntityClass_insertAttribute( *derivedClass, ( *j ).first.c_str(), ( *j ).second ); + } + } + } } class EntityClassDoom3 : public ModuleObserver { - std::size_t m_unrealised; - ModuleObservers m_observers; +std::size_t m_unrealised; +ModuleObservers m_observers; public: - EntityClassDoom3() : m_unrealised(2) - { - } - void realise() - { - if(--m_unrealised == 0) - { - globalOutputStream() << "searching vfs directory " << makeQuoted("def") << " for *.def\n"; - GlobalFileSystem().forEachFile("def/", "def", FreeCaller1()); - - { - for(Models::iterator i = g_models.begin(); i != g_models.end(); ++i) - { - Model_resolveInheritance((*i).first.c_str(), (*i).second); - } - } - { - for(EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i) - { - EntityClass_resolveInheritance((*i).second); - if(!string_empty((*i).second->m_modelpath.c_str())) - { - Models::iterator j = g_models.find((*i).second->m_modelpath); - if(j != g_models.end()) - { - (*i).second->m_modelpath = (*j).second.m_mesh; - (*i).second->m_skin = (*j).second.m_skin; - } - } - eclass_capture_state((*i).second); - - StringOutputStream usage(256); - - usage << "-------- NOTES --------\n"; - - if(!string_empty((*i).second->m_comments.c_str())) - { - usage << (*i).second->m_comments.c_str() << "\n"; - } - - usage << "\n-------- KEYS --------\n"; - - for(EntityClassAttributes::iterator j = (*i).second->m_attributes.begin(); j != (*i).second->m_attributes.end(); ++j) - { - const char* name = EntityClassAttributePair_getName(*j); - const char* description = EntityClassAttributePair_getDescription(*j); - if(!string_equal(name, description)) - { - usage << EntityClassAttributePair_getName(*j) << " : " << EntityClassAttributePair_getDescription(*j) << "\n"; - } - } - - (*i).second->m_comments = usage.c_str(); - } - } - - m_observers.realise(); - } - } - void unrealise() - { - if(++m_unrealised == 1) - { - m_observers.unrealise(); - EntityClassDoom3_clear(); - } - } - void attach(ModuleObserver& observer) - { - m_observers.attach(observer); - } - void detach(ModuleObserver& observer) - { - m_observers.detach(observer); - } +EntityClassDoom3() : m_unrealised( 2 ){ +} +void realise(){ + if ( --m_unrealised == 0 ) { + globalOutputStream() << "searching vfs directory " << makeQuoted( "def" ) << " for *.def\n"; + GlobalFileSystem().forEachFile( "def/", "def", makeCallbackF(EntityClassDoom3_loadFile) ); + + { + for ( Models::iterator i = g_models.begin(); i != g_models.end(); ++i ) + { + Model_resolveInheritance( ( *i ).first.c_str(), ( *i ).second ); + } + } + { + for ( EntityClasses::iterator i = g_EntityClassDoom3_classes.begin(); i != g_EntityClassDoom3_classes.end(); ++i ) + { + EntityClass_resolveInheritance( ( *i ).second ); + if ( !string_empty( ( *i ).second->m_modelpath.c_str() ) ) { + Models::iterator j = g_models.find( ( *i ).second->m_modelpath ); + if ( j != g_models.end() ) { + ( *i ).second->m_modelpath = ( *j ).second.m_mesh; + ( *i ).second->m_skin = ( *j ).second.m_skin; + } + } + eclass_capture_state( ( *i ).second ); + + StringOutputStream usage( 256 ); + + usage << "-------- NOTES --------\n"; + + if ( !string_empty( ( *i ).second->m_comments.c_str() ) ) { + usage << ( *i ).second->m_comments.c_str() << "\n"; + } + + usage << "\n-------- KEYS --------\n"; + + for ( EntityClassAttributes::iterator j = ( *i ).second->m_attributes.begin(); j != ( *i ).second->m_attributes.end(); ++j ) + { + const char* name = EntityClassAttributePair_getName( *j ); + const char* description = EntityClassAttributePair_getDescription( *j ); + if ( !string_equal( name, description ) ) { + usage << EntityClassAttributePair_getName( *j ) << " : " << EntityClassAttributePair_getDescription( *j ) << "\n"; + } + } + + ( *i ).second->m_comments = usage.c_str(); + } + } + + m_observers.realise(); + } +} +void unrealise(){ + if ( ++m_unrealised == 1 ) { + m_observers.unrealise(); + EntityClassDoom3_clear(); + } +} +void attach( ModuleObserver& observer ){ + m_observers.attach( observer ); +} +void detach( ModuleObserver& observer ){ + m_observers.detach( observer ); +} }; EntityClassDoom3 g_EntityClassDoom3; -void EntityClassDoom3_attach(ModuleObserver& observer) -{ - g_EntityClassDoom3.attach(observer); +void EntityClassDoom3_attach( ModuleObserver& observer ){ + g_EntityClassDoom3.attach( observer ); } -void EntityClassDoom3_detach(ModuleObserver& observer) -{ - g_EntityClassDoom3.detach(observer); +void EntityClassDoom3_detach( ModuleObserver& observer ){ + g_EntityClassDoom3.detach( observer ); } -void EntityClassDoom3_realise() -{ - g_EntityClassDoom3.realise(); +void EntityClassDoom3_realise(){ + g_EntityClassDoom3.realise(); } -void EntityClassDoom3_unrealise() -{ - g_EntityClassDoom3.unrealise(); +void EntityClassDoom3_unrealise(){ + g_EntityClassDoom3.unrealise(); } -void EntityClassDoom3_construct() -{ - GlobalFileSystem().attach(g_EntityClassDoom3); +void EntityClassDoom3_construct(){ + GlobalFileSystem().attach( g_EntityClassDoom3 ); - // start by creating the default unknown eclass - g_EntityClassDoom3_bad = EClass_Create("UNKNOWN_CLASS", Vector3(0.0f, 0.5f, 0.0f), ""); + // start by creating the default unknown eclass + g_EntityClassDoom3_bad = EClass_Create( "UNKNOWN_CLASS", Vector3( 0.0f, 0.5f, 0.0f ), "" ); - EntityClassDoom3_realise(); + EntityClassDoom3_realise(); } -void EntityClassDoom3_destroy() -{ - EntityClassDoom3_unrealise(); +void EntityClassDoom3_destroy(){ + EntityClassDoom3_unrealise(); - g_EntityClassDoom3_bad->free(g_EntityClassDoom3_bad); + g_EntityClassDoom3_bad->free( g_EntityClassDoom3_bad ); - GlobalFileSystem().detach(g_EntityClassDoom3); + GlobalFileSystem().detach( g_EntityClassDoom3 ); } class EntityClassDoom3Dependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef @@ -894,31 +789,28 @@ class EntityClassDoom3Dependencies : public GlobalFileSystemModuleRef, public Gl class EntityClassDoom3API { - EntityClassManager m_eclassmanager; +EntityClassManager m_eclassmanager; public: - typedef EntityClassManager Type; - STRING_CONSTANT(Name, "doom3"); - - EntityClassDoom3API() - { - EntityClassDoom3_construct(); - - m_eclassmanager.findOrInsert = &EntityClassDoom3_findOrInsert; - m_eclassmanager.findListType = &EntityClassDoom3_findListType; - m_eclassmanager.forEach = &EntityClassDoom3_forEach; - m_eclassmanager.attach = &EntityClassDoom3_attach; - m_eclassmanager.detach = &EntityClassDoom3_detach; - m_eclassmanager.realise = &EntityClassDoom3_realise; - m_eclassmanager.unrealise = &EntityClassDoom3_unrealise; - } - ~EntityClassDoom3API() - { - EntityClassDoom3_destroy(); - } - EntityClassManager* getTable() - { - return &m_eclassmanager; - } +typedef EntityClassManager Type; +STRING_CONSTANT( Name, "doom3" ); + +EntityClassDoom3API(){ + EntityClassDoom3_construct(); + + m_eclassmanager.findOrInsert = &EntityClassDoom3_findOrInsert; + m_eclassmanager.findListType = &EntityClassDoom3_findListType; + m_eclassmanager.forEach = &EntityClassDoom3_forEach; + m_eclassmanager.attach = &EntityClassDoom3_attach; + m_eclassmanager.detach = &EntityClassDoom3_detach; + m_eclassmanager.realise = &EntityClassDoom3_realise; + m_eclassmanager.unrealise = &EntityClassDoom3_unrealise; +} +~EntityClassDoom3API(){ + EntityClassDoom3_destroy(); +} +EntityClassManager* getTable(){ + return &m_eclassmanager; +} }; #include "modulesystem/singletonmodule.h" @@ -926,4 +818,4 @@ public: typedef SingletonModule EntityClassDoom3Module; typedef Static StaticEntityClassDoom3Module; -StaticRegisterModule staticRegisterEntityClassDoom3(StaticEntityClassDoom3Module::instance()); +StaticRegisterModule staticRegisterEntityClassDoom3( StaticEntityClassDoom3Module::instance() );