X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=radiant%2Feclass_fgd.cpp;h=7ef05b5521dbd97eed1fbb119723b7f34ef3139c;hb=dcc68affa33fc45d4d49eb5bfaa92ef9f567a13c;hp=b92afbfc6f1980a9676bfcf37edd338a5e517e71;hpb=83113718a4fb6a8e2318841f16f8a0b0eb85675c;p=xonotic%2Fnetradiant.git diff --git a/radiant/eclass_fgd.cpp b/radiant/eclass_fgd.cpp index b92afbfc..7ef05b55 100644 --- a/radiant/eclass_fgd.cpp +++ b/radiant/eclass_fgd.cpp @@ -39,679 +39,654 @@ #include "stringio.h" #include "stream/textfilestream.h" -namespace -{ -typedef std::map EntityClasses; -EntityClasses g_EntityClassFGD_classes; -typedef std::map BaseClasses; -BaseClasses g_EntityClassFGD_bases; -EntityClass *g_EntityClassFGD_bad = 0; -typedef std::map ListAttributeTypes; -ListAttributeTypes g_listTypesFGD; +namespace { + typedef std::map EntityClasses; + EntityClasses g_EntityClassFGD_classes; + typedef std::map BaseClasses; + BaseClasses g_EntityClassFGD_bases; + EntityClass *g_EntityClassFGD_bad = 0; + typedef std::map ListAttributeTypes; + ListAttributeTypes g_listTypesFGD; } -void EntityClassFGD_clear(){ - for ( BaseClasses::iterator i = g_EntityClassFGD_bases.begin(); i != g_EntityClassFGD_bases.end(); ++i ) - { - ( *i ).second->free( ( *i ).second ); - } - g_EntityClassFGD_bases.clear(); - g_listTypesFGD.clear(); +void EntityClassFGD_clear() +{ + for (BaseClasses::iterator i = g_EntityClassFGD_bases.begin(); i != g_EntityClassFGD_bases.end(); ++i) { + (*i).second->free((*i).second); + } + g_EntityClassFGD_bases.clear(); + g_listTypesFGD.clear(); } -EntityClass* EntityClassFGD_insertUniqueBase( EntityClass* entityClass ){ - std::pair result = g_EntityClassFGD_bases.insert( BaseClasses::value_type( entityClass->name(), entityClass ) ); - if ( !result.second ) { - globalErrorStream() << "duplicate base class: " << makeQuoted( entityClass->name() ) << "\n"; - //eclass_capture_state(entityClass); - //entityClass->free(entityClass); - } - return ( *result.first ).second; +EntityClass *EntityClassFGD_insertUniqueBase(EntityClass *entityClass) +{ + std::pair result = g_EntityClassFGD_bases.insert( + BaseClasses::value_type(entityClass->name(), entityClass)); + if (!result.second) { + globalErrorStream() << "duplicate base class: " << makeQuoted(entityClass->name()) << "\n"; + //eclass_capture_state(entityClass); + //entityClass->free(entityClass); + } + return (*result.first).second; } -EntityClass* EntityClassFGD_insertUnique( EntityClass* entityClass ){ - EntityClassFGD_insertUniqueBase( entityClass ); - std::pair result = g_EntityClassFGD_classes.insert( EntityClasses::value_type( entityClass->name(), entityClass ) ); - if ( !result.second ) { - globalErrorStream() << "duplicate entity class: " << makeQuoted( entityClass->name() ) << "\n"; - eclass_capture_state( entityClass ); - entityClass->free( entityClass ); - } - return ( *result.first ).second; +EntityClass *EntityClassFGD_insertUnique(EntityClass *entityClass) +{ + EntityClassFGD_insertUniqueBase(entityClass); + std::pair result = g_EntityClassFGD_classes.insert( + EntityClasses::value_type(entityClass->name(), entityClass)); + if (!result.second) { + globalErrorStream() << "duplicate entity class: " << makeQuoted(entityClass->name()) << "\n"; + eclass_capture_state(entityClass); + entityClass->free(entityClass); + } + return (*result.first).second; } -void EntityClassFGD_forEach( EntityClassVisitor& visitor ){ - for ( EntityClasses::iterator i = g_EntityClassFGD_classes.begin(); i != g_EntityClassFGD_classes.end(); ++i ) - { - visitor.visit( ( *i ).second ); - } +void EntityClassFGD_forEach(EntityClassVisitor &visitor) +{ + for (EntityClasses::iterator i = g_EntityClassFGD_classes.begin(); i != g_EntityClassFGD_classes.end(); ++i) { + visitor.visit((*i).second); + } } -inline bool EntityClassFGD_parseToken( Tokeniser& tokeniser, const char* token ){ - return string_equal( tokeniser.getToken(), token ); +inline bool EntityClassFGD_parseToken(Tokeniser &tokeniser, const char *token) +{ + return string_equal(tokeniser.getToken(), token); } const char *PARSE_ERROR = "error parsing entity class definition"; -void EntityClassFGD_parseSplitString( Tokeniser& tokeniser, CopiedString& string ){ - StringOutputStream buffer( 256 ); - for (;; ) - { - buffer << tokeniser.getToken(); - if ( !string_equal( tokeniser.getToken(), "+" ) ) { - tokeniser.ungetToken(); - string = buffer.c_str(); - return; - } - } +void EntityClassFGD_parseSplitString(Tokeniser &tokeniser, CopiedString &string) +{ + StringOutputStream buffer(256); + for (;;) { + buffer << tokeniser.getToken(); + if (!string_equal(tokeniser.getToken(), "+")) { + tokeniser.ungetToken(); + string = buffer.c_str(); + return; + } + } } -void EntityClassFGD_parseClass( Tokeniser& tokeniser, bool fixedsize, bool isBase ){ - EntityClass* entityClass = Eclass_Alloc(); - entityClass->free = &Eclass_Free; - entityClass->fixedsize = fixedsize; - entityClass->inheritanceResolved = false; - entityClass->mins = Vector3( -8, -8, -8 ); - entityClass->maxs = Vector3( 8, 8, 8 ); - - for (;; ) - { - const char* property = tokeniser.getToken(); - if ( string_equal( property, "=" ) ) { - break; - } - else if ( string_equal( property, "base" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - for (;; ) - { - const char* base = tokeniser.getToken(); - if ( string_equal( base, ")" ) ) { - break; - } - else if ( !string_equal( base, "," ) ) { - entityClass->m_parent.push_back( base ); - } - } - } - else if ( string_equal( property, "size" ) ) { - entityClass->sizeSpecified = true; - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - Tokeniser_getFloat( tokeniser, entityClass->mins.x() ); - Tokeniser_getFloat( tokeniser, entityClass->mins.y() ); - Tokeniser_getFloat( tokeniser, entityClass->mins.z() ); - const char* token = tokeniser.getToken(); - if ( string_equal( token, "," ) ) { - Tokeniser_getFloat( tokeniser, entityClass->maxs.x() ); - Tokeniser_getFloat( tokeniser, entityClass->maxs.y() ); - Tokeniser_getFloat( tokeniser, entityClass->maxs.z() ); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - else - { - entityClass->maxs = entityClass->mins; - vector3_negate( entityClass->mins ); - ASSERT_MESSAGE( string_equal( token, ")" ), "" ); - } - } - else if ( string_equal( property, "color" ) ) { - entityClass->colorSpecified = true; - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - Tokeniser_getFloat( tokeniser, entityClass->color.x() ); - entityClass->color.x() /= 256.0; - Tokeniser_getFloat( tokeniser, entityClass->color.y() ); - entityClass->color.y() /= 256.0; - Tokeniser_getFloat( tokeniser, entityClass->color.z() ); - entityClass->color.z() /= 256.0; - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - else if ( string_equal( property, "iconsprite" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - StringOutputStream buffer( 256 ); - buffer << PathCleaned( tokeniser.getToken() ); - entityClass->m_modelpath = buffer.c_str(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - else if ( string_equal( property, "sprite" ) - || string_equal( property, "decal" ) - // hl2 below - || string_equal( property, "overlay" ) - || string_equal( property, "light" ) - || string_equal( property, "keyframe" ) - || string_equal( property, "animator" ) - || string_equal( property, "quadbounds" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - // hl2 below - else if ( string_equal( property, "sphere" ) - || string_equal( property, "sweptplayerhull" ) - || string_equal( property, "studio" ) - || string_equal( property, "studioprop" ) - || string_equal( property, "lightprop" ) - || string_equal( property, "lightcone" ) - || string_equal( property, "sidelist" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - if ( string_equal( tokeniser.getToken(), ")" ) ) { - tokeniser.ungetToken(); - } - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - else if ( string_equal( property, "line" ) - || string_equal( property, "cylinder" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - //const char* r = - tokeniser.getToken(); - //const char* g = - tokeniser.getToken(); - //const char* b = - tokeniser.getToken(); - for (;; ) - { - if ( string_equal( tokeniser.getToken(), ")" ) ) { - tokeniser.ungetToken(); - break; - } - //const char* name = - tokeniser.getToken(); - } - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - else if ( string_equal( property, "wirebox" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - //const char* mins = - tokeniser.getToken(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "," ), PARSE_ERROR ); - //const char* maxs = - tokeniser.getToken(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - else if ( string_equal( property, "halfgridsnap" ) ) { - } - else - { - ERROR_MESSAGE( PARSE_ERROR ); - } - } - - entityClass->m_name = tokeniser.getToken(); - - if ( !isBase ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ":" ), PARSE_ERROR ); - - EntityClassFGD_parseSplitString( tokeniser, entityClass->m_comments ); - } - - tokeniser.nextLine(); - - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "[" ), PARSE_ERROR ); - - tokeniser.nextLine(); - - for (;; ) - { - CopiedString key = tokeniser.getToken(); - if ( string_equal( key.c_str(), "]" ) ) { - tokeniser.nextLine(); - break; - } - - if ( string_equal_nocase( key.c_str(), "input" ) - || string_equal_nocase( key.c_str(), "output" ) ) { - const char* name = tokeniser.getToken(); - if ( !string_equal( name, "(" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - //const char* type = - tokeniser.getToken(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - const char* descriptionSeparator = tokeniser.getToken(); - if ( string_equal( descriptionSeparator, ":" ) ) { - CopiedString description; - EntityClassFGD_parseSplitString( tokeniser, description ); - } - else - { - tokeniser.ungetToken(); - } - tokeniser.nextLine(); - continue; - } - } - - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - CopiedString type = tokeniser.getToken(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - - if ( string_equal_nocase( type.c_str(), "flags" ) ) { - EntityClassAttribute attribute; - - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "=" ), PARSE_ERROR ); - tokeniser.nextLine(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "[" ), PARSE_ERROR ); - tokeniser.nextLine(); - for (;; ) - { - const char* flag = tokeniser.getToken(); - if ( string_equal( flag, "]" ) ) { - tokeniser.nextLine(); - break; - } - else - { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ":" ), PARSE_ERROR ); - //const char* name = - tokeniser.getToken(); - { - const char* defaultSeparator = tokeniser.getToken(); - if ( string_equal( defaultSeparator, ":" ) ) { - tokeniser.getToken(); - { - const char* descriptionSeparator = tokeniser.getToken(); - if ( string_equal( descriptionSeparator, ":" ) ) { - EntityClassFGD_parseSplitString( tokeniser, attribute.m_description ); - } - else - { - tokeniser.ungetToken(); - } - } - } - else - { - tokeniser.ungetToken(); - } - } - } - tokeniser.nextLine(); - } - EntityClass_insertAttribute( *entityClass, key.c_str(), attribute ); - } - else if ( string_equal_nocase( type.c_str(), "choices" ) ) { - EntityClassAttribute attribute; - - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ":" ), PARSE_ERROR ); - attribute.m_name = tokeniser.getToken(); - const char* valueSeparator = tokeniser.getToken(); - if ( string_equal( valueSeparator, ":" ) ) { - const char* value = tokeniser.getToken(); - if ( !string_equal( value, ":" ) ) { - attribute.m_value = value; - } - else - { - tokeniser.ungetToken(); - } - { - const char* descriptionSeparator = tokeniser.getToken(); - if ( string_equal( descriptionSeparator, ":" ) ) { - EntityClassFGD_parseSplitString( tokeniser, attribute.m_description ); - } - else - { - tokeniser.ungetToken(); - } - } - } - else - { - tokeniser.ungetToken(); - } - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "=" ), PARSE_ERROR ); - tokeniser.nextLine(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "[" ), PARSE_ERROR ); - tokeniser.nextLine(); - - StringOutputStream listTypeName( 64 ); - listTypeName << entityClass->m_name.c_str() << "_" << attribute.m_name.c_str(); - attribute.m_type = listTypeName.c_str(); - - ListAttributeType& listType = g_listTypesFGD[listTypeName.c_str()]; - - for (;; ) - { - const char* value = tokeniser.getToken(); - if ( string_equal( value, "]" ) ) { - tokeniser.nextLine(); - break; - } - else - { - CopiedString tmp( value ); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ":" ), PARSE_ERROR ); - const char* name = tokeniser.getToken(); - listType.push_back( name, tmp.c_str() ); - } - tokeniser.nextLine(); - } - - for ( ListAttributeType::const_iterator i = listType.begin(); i != listType.end(); ++i ) - { - if ( string_equal( attribute.m_value.c_str(), ( *i ).first.c_str() ) ) { - attribute.m_value = ( *i ).second.c_str(); - } - } - - EntityClass_insertAttribute( *entityClass, key.c_str(), attribute ); - } - else if ( string_equal_nocase( type.c_str(), "decal" ) ) { - } - else if ( string_equal_nocase( type.c_str(), "string" ) - || string_equal_nocase( type.c_str(), "integer" ) - || string_equal_nocase( type.c_str(), "studio" ) - || string_equal_nocase( type.c_str(), "sprite" ) - || string_equal_nocase( type.c_str(), "color255" ) - || string_equal_nocase( type.c_str(), "target_source" ) - || string_equal_nocase( type.c_str(), "target_destination" ) - || string_equal_nocase( type.c_str(), "sound" ) - // hl2 below - || string_equal_nocase( type.c_str(), "angle" ) - || string_equal_nocase( type.c_str(), "origin" ) - || string_equal_nocase( type.c_str(), "float" ) - || string_equal_nocase( type.c_str(), "node_dest" ) - || string_equal_nocase( type.c_str(), "filterclass" ) - || string_equal_nocase( type.c_str(), "vector" ) - || string_equal_nocase( type.c_str(), "sidelist" ) - || string_equal_nocase( type.c_str(), "material" ) - || string_equal_nocase( type.c_str(), "vecline" ) - || string_equal_nocase( type.c_str(), "axis" ) - || string_equal_nocase( type.c_str(), "npcclass" ) - || string_equal_nocase( type.c_str(), "target_name_or_class" ) - || string_equal_nocase( type.c_str(), "pointentityclass" ) - || string_equal_nocase( type.c_str(), "scene" ) ) { - if ( !string_equal( tokeniser.getToken(), "readonly" ) ) { - tokeniser.ungetToken(); - } - - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ":" ), PARSE_ERROR ); - const char* attributeType = "string"; - if ( string_equal_nocase( type.c_str(), "studio" ) ) { - attributeType = "model"; - } - - EntityClassAttribute attribute; - attribute.m_type = attributeType; - attribute.m_name = tokeniser.getToken(); - - const char* defaultSeparator = tokeniser.getToken(); - if ( string_equal( defaultSeparator, ":" ) ) { - const char* value = tokeniser.getToken(); - if ( !string_equal( value, ":" ) ) { - attribute.m_value = value; - } - else - { - tokeniser.ungetToken(); - } - - { - const char* descriptionSeparator = tokeniser.getToken(); - if ( string_equal( descriptionSeparator, ":" ) ) { - EntityClassFGD_parseSplitString( tokeniser, attribute.m_description ); - } - else - { - tokeniser.ungetToken(); - } - } - } - else - { - tokeniser.ungetToken(); - } - EntityClass_insertAttribute( *entityClass, key.c_str(), attribute ); - } - else - { - ERROR_MESSAGE( "unknown key type: " << makeQuoted( type.c_str() ) ); - } - tokeniser.nextLine(); - } - - if ( isBase ) { - EntityClassFGD_insertUniqueBase( entityClass ); - } - else - { - EntityClassFGD_insertUnique( entityClass ); - } +void EntityClassFGD_parseClass(Tokeniser &tokeniser, bool fixedsize, bool isBase) +{ + EntityClass *entityClass = Eclass_Alloc(); + entityClass->free = &Eclass_Free; + entityClass->fixedsize = fixedsize; + entityClass->inheritanceResolved = false; + entityClass->mins = Vector3(-8, -8, -8); + entityClass->maxs = Vector3(8, 8, 8); + + for (;;) { + const char *property = tokeniser.getToken(); + if (string_equal(property, "=")) { + break; + } else if (string_equal(property, "base")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + for (;;) { + const char *base = tokeniser.getToken(); + if (string_equal(base, ")")) { + break; + } else if (!string_equal(base, ",")) { + entityClass->m_parent.push_back(base); + } + } + } else if (string_equal(property, "size")) { + entityClass->sizeSpecified = true; + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + Tokeniser_getFloat(tokeniser, entityClass->mins.x()); + Tokeniser_getFloat(tokeniser, entityClass->mins.y()); + Tokeniser_getFloat(tokeniser, entityClass->mins.z()); + const char *token = tokeniser.getToken(); + if (string_equal(token, ",")) { + Tokeniser_getFloat(tokeniser, entityClass->maxs.x()); + Tokeniser_getFloat(tokeniser, entityClass->maxs.y()); + Tokeniser_getFloat(tokeniser, entityClass->maxs.z()); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } else { + entityClass->maxs = entityClass->mins; + vector3_negate(entityClass->mins); + ASSERT_MESSAGE(string_equal(token, ")"), ""); + } + } else if (string_equal(property, "color")) { + entityClass->colorSpecified = true; + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + Tokeniser_getFloat(tokeniser, entityClass->color.x()); + entityClass->color.x() /= 256.0; + Tokeniser_getFloat(tokeniser, entityClass->color.y()); + entityClass->color.y() /= 256.0; + Tokeniser_getFloat(tokeniser, entityClass->color.z()); + entityClass->color.z() /= 256.0; + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } else if (string_equal(property, "iconsprite")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + StringOutputStream buffer(256); + buffer << PathCleaned(tokeniser.getToken()); + entityClass->m_modelpath = buffer.c_str(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } else if (string_equal(property, "sprite") + || string_equal(property, "decal") + // hl2 below + || string_equal(property, "overlay") + || string_equal(property, "light") + || string_equal(property, "keyframe") + || string_equal(property, "animator") + || string_equal(property, "quadbounds")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } + // hl2 below + else if (string_equal(property, "sphere") + || string_equal(property, "sweptplayerhull") + || string_equal(property, "studio") + || string_equal(property, "studioprop") + || string_equal(property, "lightprop") + || string_equal(property, "lightcone") + || string_equal(property, "sidelist")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + if (string_equal(tokeniser.getToken(), ")")) { + tokeniser.ungetToken(); + } + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } else if (string_equal(property, "line") + || string_equal(property, "cylinder")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + //const char* r = + tokeniser.getToken(); + //const char* g = + tokeniser.getToken(); + //const char* b = + tokeniser.getToken(); + for (;;) { + if (string_equal(tokeniser.getToken(), ")")) { + tokeniser.ungetToken(); + break; + } + //const char* name = + tokeniser.getToken(); + } + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } else if (string_equal(property, "wirebox")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + //const char* mins = + tokeniser.getToken(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ","), PARSE_ERROR); + //const char* maxs = + tokeniser.getToken(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } else if (string_equal(property, "halfgridsnap")) { + } else { + ERROR_MESSAGE(PARSE_ERROR); + } + } + + entityClass->m_name = tokeniser.getToken(); + + if (!isBase) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR); + + EntityClassFGD_parseSplitString(tokeniser, entityClass->m_comments); + } + + tokeniser.nextLine(); + + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "["), PARSE_ERROR); + + tokeniser.nextLine(); + + for (;;) { + CopiedString key = tokeniser.getToken(); + if (string_equal(key.c_str(), "]")) { + tokeniser.nextLine(); + break; + } + + if (string_equal_nocase(key.c_str(), "input") + || string_equal_nocase(key.c_str(), "output")) { + const char *name = tokeniser.getToken(); + if (!string_equal(name, "(")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + //const char* type = + tokeniser.getToken(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + const char *descriptionSeparator = tokeniser.getToken(); + if (string_equal(descriptionSeparator, ":")) { + CopiedString description; + EntityClassFGD_parseSplitString(tokeniser, description); + } else { + tokeniser.ungetToken(); + } + tokeniser.nextLine(); + continue; + } + } + + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + CopiedString type = tokeniser.getToken(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + + if (string_equal_nocase(type.c_str(), "flags")) { + EntityClassAttribute attribute; + + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "="), PARSE_ERROR); + tokeniser.nextLine(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "["), PARSE_ERROR); + tokeniser.nextLine(); + for (;;) { + const char *flag = tokeniser.getToken(); + if (string_equal(flag, "]")) { + tokeniser.nextLine(); + break; + } else { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR); + //const char* name = + tokeniser.getToken(); + { + const char *defaultSeparator = tokeniser.getToken(); + if (string_equal(defaultSeparator, ":")) { + tokeniser.getToken(); + { + const char *descriptionSeparator = tokeniser.getToken(); + if (string_equal(descriptionSeparator, ":")) { + EntityClassFGD_parseSplitString(tokeniser, attribute.m_description); + } else { + tokeniser.ungetToken(); + } + } + } else { + tokeniser.ungetToken(); + } + } + } + tokeniser.nextLine(); + } + EntityClass_insertAttribute(*entityClass, key.c_str(), attribute); + } else if (string_equal_nocase(type.c_str(), "choices")) { + EntityClassAttribute attribute; + + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR); + attribute.m_name = tokeniser.getToken(); + const char *valueSeparator = tokeniser.getToken(); + if (string_equal(valueSeparator, ":")) { + const char *value = tokeniser.getToken(); + if (!string_equal(value, ":")) { + attribute.m_value = value; + } else { + tokeniser.ungetToken(); + } + { + const char *descriptionSeparator = tokeniser.getToken(); + if (string_equal(descriptionSeparator, ":")) { + EntityClassFGD_parseSplitString(tokeniser, attribute.m_description); + } else { + tokeniser.ungetToken(); + } + } + } else { + tokeniser.ungetToken(); + } + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "="), PARSE_ERROR); + tokeniser.nextLine(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "["), PARSE_ERROR); + tokeniser.nextLine(); + + StringOutputStream listTypeName(64); + listTypeName << entityClass->m_name.c_str() << "_" << attribute.m_name.c_str(); + attribute.m_type = listTypeName.c_str(); + + ListAttributeType &listType = g_listTypesFGD[listTypeName.c_str()]; + + for (;;) { + const char *value = tokeniser.getToken(); + if (string_equal(value, "]")) { + tokeniser.nextLine(); + break; + } else { + CopiedString tmp(value); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR); + const char *name = tokeniser.getToken(); + listType.push_back(name, tmp.c_str()); + } + tokeniser.nextLine(); + } + + for (ListAttributeType::const_iterator i = listType.begin(); i != listType.end(); ++i) { + if (string_equal(attribute.m_value.c_str(), (*i).first.c_str())) { + attribute.m_value = (*i).second.c_str(); + } + } + + EntityClass_insertAttribute(*entityClass, key.c_str(), attribute); + } else if (string_equal_nocase(type.c_str(), "decal")) { + } else if (string_equal_nocase(type.c_str(), "string") + || string_equal_nocase(type.c_str(), "integer") + || string_equal_nocase(type.c_str(), "studio") + || string_equal_nocase(type.c_str(), "sprite") + || string_equal_nocase(type.c_str(), "color255") + || string_equal_nocase(type.c_str(), "target_source") + || string_equal_nocase(type.c_str(), "target_destination") + || string_equal_nocase(type.c_str(), "sound") + // hl2 below + || string_equal_nocase(type.c_str(), "angle") + || string_equal_nocase(type.c_str(), "origin") + || string_equal_nocase(type.c_str(), "float") + || string_equal_nocase(type.c_str(), "node_dest") + || string_equal_nocase(type.c_str(), "filterclass") + || string_equal_nocase(type.c_str(), "vector") + || string_equal_nocase(type.c_str(), "sidelist") + || string_equal_nocase(type.c_str(), "material") + || string_equal_nocase(type.c_str(), "vecline") + || string_equal_nocase(type.c_str(), "axis") + || string_equal_nocase(type.c_str(), "npcclass") + || string_equal_nocase(type.c_str(), "target_name_or_class") + || string_equal_nocase(type.c_str(), "pointentityclass") + || string_equal_nocase(type.c_str(), "scene")) { + if (!string_equal(tokeniser.getToken(), "readonly")) { + tokeniser.ungetToken(); + } + + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ":"), PARSE_ERROR); + const char *attributeType = "string"; + if (string_equal_nocase(type.c_str(), "studio")) { + attributeType = "model"; + } + + EntityClassAttribute attribute; + attribute.m_type = attributeType; + attribute.m_name = tokeniser.getToken(); + + const char *defaultSeparator = tokeniser.getToken(); + if (string_equal(defaultSeparator, ":")) { + const char *value = tokeniser.getToken(); + if (!string_equal(value, ":")) { + attribute.m_value = value; + } else { + tokeniser.ungetToken(); + } + + { + const char *descriptionSeparator = tokeniser.getToken(); + if (string_equal(descriptionSeparator, ":")) { + EntityClassFGD_parseSplitString(tokeniser, attribute.m_description); + } else { + tokeniser.ungetToken(); + } + } + } else { + tokeniser.ungetToken(); + } + EntityClass_insertAttribute(*entityClass, key.c_str(), attribute); + } else { + ERROR_MESSAGE("unknown key type: " << makeQuoted(type.c_str())); + } + tokeniser.nextLine(); + } + + if (isBase) { + EntityClassFGD_insertUniqueBase(entityClass); + } else { + EntityClassFGD_insertUnique(entityClass); + } } -void EntityClassFGD_loadFile( const char* filename ); - -void EntityClassFGD_parse( TextInputStream& inputStream, const char* path ){ - Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser( inputStream ); - - tokeniser.nextLine(); - - for (;; ) - { - const char* blockType = tokeniser.getToken(); - if ( blockType == 0 ) { - break; - } - if ( string_equal( blockType, "@SolidClass" ) ) { - EntityClassFGD_parseClass( tokeniser, false, false ); - } - else if ( string_equal( blockType, "@BaseClass" ) ) { - EntityClassFGD_parseClass( tokeniser, false, true ); - } - else if ( string_equal( blockType, "@PointClass" ) - // hl2 below - || string_equal( blockType, "@KeyFrameClass" ) - || string_equal( blockType, "@MoveClass" ) - || string_equal( blockType, "@FilterClass" ) - || string_equal( blockType, "@NPCClass" ) ) { - EntityClassFGD_parseClass( tokeniser, true, false ); - } - // hl2 below - else if ( string_equal( blockType, "@include" ) ) { - StringOutputStream includePath( 256 ); - includePath << StringRange( path, path_get_filename_start( path ) ); - includePath << tokeniser.getToken(); - EntityClassFGD_loadFile( includePath.c_str() ); - } - else if ( string_equal( blockType, "@mapsize" ) ) { - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); - //const char* min = - tokeniser.getToken(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "," ), PARSE_ERROR ); - //const char* max = - tokeniser.getToken(); - ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); - } - else - { - ERROR_MESSAGE( "unknown block type: " << makeQuoted( blockType ) ); - } - } - - tokeniser.release(); +void EntityClassFGD_loadFile(const char *filename); + +void EntityClassFGD_parse(TextInputStream &inputStream, const char *path) +{ + Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(inputStream); + + tokeniser.nextLine(); + + for (;;) { + const char *blockType = tokeniser.getToken(); + if (blockType == 0) { + break; + } + if (string_equal(blockType, "@SolidClass")) { + EntityClassFGD_parseClass(tokeniser, false, false); + } else if (string_equal(blockType, "@BaseClass")) { + EntityClassFGD_parseClass(tokeniser, false, true); + } else if (string_equal(blockType, "@PointClass") + // hl2 below + || string_equal(blockType, "@KeyFrameClass") + || string_equal(blockType, "@MoveClass") + || string_equal(blockType, "@FilterClass") + || string_equal(blockType, "@NPCClass")) { + EntityClassFGD_parseClass(tokeniser, true, false); + } + // hl2 below + else if (string_equal(blockType, "@include")) { + StringOutputStream includePath(256); + includePath << StringRange(path, path_get_filename_start(path)); + includePath << tokeniser.getToken(); + EntityClassFGD_loadFile(includePath.c_str()); + } else if (string_equal(blockType, "@mapsize")) { + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, "("), PARSE_ERROR); + //const char* min = + tokeniser.getToken(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ","), PARSE_ERROR); + //const char* max = + tokeniser.getToken(); + ASSERT_MESSAGE(EntityClassFGD_parseToken(tokeniser, ")"), PARSE_ERROR); + } else { + ERROR_MESSAGE("unknown block type: " << makeQuoted(blockType)); + } + } + + tokeniser.release(); } -void EntityClassFGD_loadFile( const char* filename ){ - TextFileInputStream file( filename ); - if ( !file.failed() ) { - globalOutputStream() << "parsing entity classes from " << makeQuoted( filename ) << "\n"; +void EntityClassFGD_loadFile(const char *filename) +{ + TextFileInputStream file(filename); + if (!file.failed()) { + globalOutputStream() << "parsing entity classes from " << makeQuoted(filename) << "\n"; - EntityClassFGD_parse( file, filename ); - } + EntityClassFGD_parse(file, filename); + } } -EntityClass* EntityClassFGD_findOrInsert( const char *name, bool has_brushes ){ - ASSERT_NOTNULL( name ); +EntityClass *EntityClassFGD_findOrInsert(const char *name, bool has_brushes) +{ + ASSERT_NOTNULL(name); - if ( string_empty( name ) ) { - return g_EntityClassFGD_bad; - } + if (string_empty(name)) { + return g_EntityClassFGD_bad; + } - EntityClasses::iterator i = g_EntityClassFGD_classes.find( name ); - if ( i != g_EntityClassFGD_classes.end() - //&& string_equal((*i).first, name) - ) { - return ( *i ).second; - } + EntityClasses::iterator i = g_EntityClassFGD_classes.find(name); + if (i != g_EntityClassFGD_classes.end() + //&& string_equal((*i).first, name) + ) { + return (*i).second; + } - EntityClass* e = EntityClass_Create_Default( name, has_brushes ); - return EntityClassFGD_insertUnique( e ); + EntityClass *e = EntityClass_Create_Default(name, has_brushes); + return EntityClassFGD_insertUnique(e); } -const ListAttributeType* EntityClassFGD_findListType( const char *name ){ - ListAttributeTypes::iterator i = g_listTypesFGD.find( name ); - if ( i != g_listTypesFGD.end() ) { - return &( *i ).second; - } - return 0; +const ListAttributeType *EntityClassFGD_findListType(const char *name) +{ + ListAttributeTypes::iterator i = g_listTypesFGD.find(name); + if (i != g_listTypesFGD.end()) { + return &(*i).second; + } + return 0; } -void EntityClassFGD_resolveInheritance( EntityClass* derivedClass ){ - if ( derivedClass->inheritanceResolved == false ) { - derivedClass->inheritanceResolved = true; - for ( StringList::iterator j = derivedClass->m_parent.begin(); j != derivedClass->m_parent.end(); ++j ) - { - BaseClasses::iterator i = g_EntityClassFGD_bases.find( ( *j ).c_str() ); - if ( i == g_EntityClassFGD_bases.end() ) { - globalErrorStream() << "failed to find entityDef " << makeQuoted( ( *j ).c_str() ) << " inherited by " << makeQuoted( derivedClass->m_name.c_str() ) << "\n"; - } - else - { - EntityClass* parentClass = ( *i ).second; - EntityClassFGD_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; - } - - for ( EntityClassAttributes::iterator k = parentClass->m_attributes.begin(); k != parentClass->m_attributes.end(); ++k ) - { - EntityClass_insertAttribute( *derivedClass, ( *k ).first.c_str(), ( *k ).second ); - } - } - } - } +void EntityClassFGD_resolveInheritance(EntityClass *derivedClass) +{ + if (derivedClass->inheritanceResolved == false) { + derivedClass->inheritanceResolved = true; + for (StringList::iterator j = derivedClass->m_parent.begin(); j != derivedClass->m_parent.end(); ++j) { + BaseClasses::iterator i = g_EntityClassFGD_bases.find((*j).c_str()); + if (i == g_EntityClassFGD_bases.end()) { + globalErrorStream() << "failed to find entityDef " << makeQuoted((*j).c_str()) << " inherited by " + << makeQuoted(derivedClass->m_name.c_str()) << "\n"; + } else { + EntityClass *parentClass = (*i).second; + EntityClassFGD_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; + } + + for (EntityClassAttributes::iterator k = parentClass->m_attributes.begin(); + k != parentClass->m_attributes.end(); ++k) { + EntityClass_insertAttribute(*derivedClass, (*k).first.c_str(), (*k).second); + } + } + } + } } -class EntityClassFGD : public ModuleObserver -{ -std::size_t m_unrealised; -ModuleObservers m_observers; +class EntityClassFGD : public ModuleObserver { + std::size_t m_unrealised; + ModuleObservers m_observers; public: -EntityClassFGD() : m_unrealised( 3 ){ -} -void realise(){ - if ( --m_unrealised == 0 ) { - StringOutputStream filename( 256 ); - filename << GlobalRadiant().getGameToolsPath() << GlobalRadiant().getGameName() << "/halflife.fgd"; - EntityClassFGD_loadFile( filename.c_str() ); - - { - for ( EntityClasses::iterator i = g_EntityClassFGD_classes.begin(); i != g_EntityClassFGD_classes.end(); ++i ) - { - EntityClassFGD_resolveInheritance( ( *i ).second ); - if ( ( *i ).second->fixedsize && string_empty( ( *i ).second->m_modelpath.c_str() ) ) { - if ( !( *i ).second->sizeSpecified ) { - globalErrorStream() << "size not specified for entity class: " << makeQuoted( ( *i ).second->m_name.c_str() ) << '\n'; - } - if ( !( *i ).second->colorSpecified ) { - globalErrorStream() << "color not specified for entity class: " << makeQuoted( ( *i ).second->m_name.c_str() ) << '\n'; - } - } - } - } - { - for ( BaseClasses::iterator i = g_EntityClassFGD_bases.begin(); i != g_EntityClassFGD_bases.end(); ++i ) - { - eclass_capture_state( ( *i ).second ); - } - } - - m_observers.realise(); - } -} -void unrealise(){ - if ( ++m_unrealised == 1 ) { - m_observers.unrealise(); - EntityClassFGD_clear(); - } -} -void attach( ModuleObserver& observer ){ - m_observers.attach( observer ); -} -void detach( ModuleObserver& observer ){ - m_observers.detach( observer ); -} + EntityClassFGD() : m_unrealised(3) + { + } + + void realise() + { + if (--m_unrealised == 0) { + StringOutputStream filename(256); + filename << GlobalRadiant().getGameToolsPath() << GlobalRadiant().getGameName() << "/halflife.fgd"; + EntityClassFGD_loadFile(filename.c_str()); + + { + for (EntityClasses::iterator i = g_EntityClassFGD_classes.begin(); + i != g_EntityClassFGD_classes.end(); ++i) { + EntityClassFGD_resolveInheritance((*i).second); + if ((*i).second->fixedsize && string_empty((*i).second->m_modelpath.c_str())) { + if (!(*i).second->sizeSpecified) { + globalErrorStream() << "size not specified for entity class: " + << makeQuoted((*i).second->m_name.c_str()) << '\n'; + } + if (!(*i).second->colorSpecified) { + globalErrorStream() << "color not specified for entity class: " + << makeQuoted((*i).second->m_name.c_str()) << '\n'; + } + } + } + } + { + for (BaseClasses::iterator i = g_EntityClassFGD_bases.begin(); i != g_EntityClassFGD_bases.end(); ++i) { + eclass_capture_state((*i).second); + } + } + + m_observers.realise(); + } + } + + void unrealise() + { + if (++m_unrealised == 1) { + m_observers.unrealise(); + EntityClassFGD_clear(); + } + } + + void attach(ModuleObserver &observer) + { + m_observers.attach(observer); + } + + void detach(ModuleObserver &observer) + { + m_observers.detach(observer); + } }; EntityClassFGD g_EntityClassFGD; -void EntityClassFGD_attach( ModuleObserver& observer ){ - g_EntityClassFGD.attach( observer ); +void EntityClassFGD_attach(ModuleObserver &observer) +{ + g_EntityClassFGD.attach(observer); } -void EntityClassFGD_detach( ModuleObserver& observer ){ - g_EntityClassFGD.detach( observer ); + +void EntityClassFGD_detach(ModuleObserver &observer) +{ + g_EntityClassFGD.detach(observer); } -void EntityClassFGD_realise(){ - g_EntityClassFGD.realise(); +void EntityClassFGD_realise() +{ + g_EntityClassFGD.realise(); } -void EntityClassFGD_unrealise(){ - g_EntityClassFGD.unrealise(); + +void EntityClassFGD_unrealise() +{ + g_EntityClassFGD.unrealise(); } -void EntityClassFGD_construct(){ - // start by creating the default unknown eclass - g_EntityClassFGD_bad = EClass_Create( "UNKNOWN_CLASS", Vector3( 0.0f, 0.5f, 0.0f ), "" ); +void EntityClassFGD_construct() +{ + // start by creating the default unknown eclass + g_EntityClassFGD_bad = EClass_Create("UNKNOWN_CLASS", Vector3(0.0f, 0.5f, 0.0f), ""); - EntityClassFGD_realise(); + EntityClassFGD_realise(); } -void EntityClassFGD_destroy(){ - EntityClassFGD_unrealise(); +void EntityClassFGD_destroy() +{ + EntityClassFGD_unrealise(); - g_EntityClassFGD_bad->free( g_EntityClassFGD_bad ); + g_EntityClassFGD_bad->free(g_EntityClassFGD_bad); } -class EntityClassFGDDependencies : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef, public GlobalRadiantModuleRef -{ +class EntityClassFGDDependencies + : public GlobalFileSystemModuleRef, public GlobalShaderCacheModuleRef, public GlobalRadiantModuleRef { }; -class EntityClassFGDAPI -{ -EntityClassManager m_eclassmanager; +class EntityClassFGDAPI { + EntityClassManager m_eclassmanager; public: -typedef EntityClassManager Type; -STRING_CONSTANT( Name, "halflife" ); - -EntityClassFGDAPI(){ - EntityClassFGD_construct(); - - m_eclassmanager.findOrInsert = &EntityClassFGD_findOrInsert; - m_eclassmanager.findListType = &EntityClassFGD_findListType; - m_eclassmanager.forEach = &EntityClassFGD_forEach; - m_eclassmanager.attach = &EntityClassFGD_attach; - m_eclassmanager.detach = &EntityClassFGD_detach; - m_eclassmanager.realise = &EntityClassFGD_realise; - m_eclassmanager.unrealise = &EntityClassFGD_unrealise; - - Radiant_attachGameToolsPathObserver( g_EntityClassFGD ); - Radiant_attachGameNameObserver( g_EntityClassFGD ); -} -~EntityClassFGDAPI(){ - Radiant_detachGameNameObserver( g_EntityClassFGD ); - Radiant_detachGameToolsPathObserver( g_EntityClassFGD ); - - EntityClassFGD_destroy(); -} -EntityClassManager* getTable(){ - return &m_eclassmanager; -} + typedef EntityClassManager Type; + + STRING_CONSTANT(Name, "halflife"); + + EntityClassFGDAPI() + { + EntityClassFGD_construct(); + + m_eclassmanager.findOrInsert = &EntityClassFGD_findOrInsert; + m_eclassmanager.findListType = &EntityClassFGD_findListType; + m_eclassmanager.forEach = &EntityClassFGD_forEach; + m_eclassmanager.attach = &EntityClassFGD_attach; + m_eclassmanager.detach = &EntityClassFGD_detach; + m_eclassmanager.realise = &EntityClassFGD_realise; + m_eclassmanager.unrealise = &EntityClassFGD_unrealise; + + Radiant_attachGameToolsPathObserver(g_EntityClassFGD); + Radiant_attachGameNameObserver(g_EntityClassFGD); + } + + ~EntityClassFGDAPI() + { + Radiant_detachGameNameObserver(g_EntityClassFGD); + Radiant_detachGameToolsPathObserver(g_EntityClassFGD); + + EntityClassFGD_destroy(); + } + + EntityClassManager *getTable() + { + return &m_eclassmanager; + } }; #include "modulesystem/singletonmodule.h" @@ -719,4 +694,4 @@ EntityClassManager* getTable(){ typedef SingletonModule EntityClassFGDModule; typedef Static StaticEntityClassFGDModule; -StaticRegisterModule staticRegisterEntityClassFGD( StaticEntityClassFGDModule::instance() ); +StaticRegisterModule staticRegisterEntityClassFGD(StaticEntityClassFGDModule::instance());