X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=radiant%2Feclass_def.cpp;h=8637b4800c186e1ff3c23d260fe904779ca4fc7f;hb=refs%2Fheads%2FTimePath%2FMakefile;hp=d598886070a2ec2857ee33060ae703c3d1e7c1a8;hpb=5265d3cc1517566910718738ee6fa48e2466d3ea;p=xonotic%2Fnetradiant.git diff --git a/radiant/eclass_def.cpp b/radiant/eclass_def.cpp index d5988860..8637b480 100644 --- a/radiant/eclass_def.cpp +++ b/radiant/eclass_def.cpp @@ -1,306 +1,389 @@ /* -Copyright (C) 1999-2007 id Software, Inc. and contributors. -For a list of contributors, see the accompanying CONTRIBUTORS file. - -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 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 -*/ - -#include "cmdlib.h" - -#include "synapse.h" -#define USE_QERTABLE_DEFINE -#include "qerplugin.h" -#define USE_ECLASSMANAGER_DEFINE -#include "ieclass.h" -#define USE_SCRIPLIBTABLE_DEFINE -#include "iscriplib.h" + Copyright (C) 1999-2006 Id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. -#define __VFSTABLENAME g_FileSystemTable_def -#define USE_VFSTABLE_DEFINE -#include "ifilesystem.h" + 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. -#include "eclass_def.h" + 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. -/*! \file eclass_def.cpp - \brief .def entity description format - implements parsing for .def entity format - this is statically linked into the radiant core as we always need it, but really considered - as an idependant module by the rest of the core. "ECLASS_MAJOR" "def" -*/ + 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 + */ -_QERScripLibTable g_ScripLibTable; -_EClassManagerTable g_EClassManagerTable; -_QERFuncTable_1 g_FuncTable; -_QERFileSystemTable g_FileSystemTable_def; +#include "eclass_def.h" -CSynapseBuiltinClientDef eclass_def; +#include "iscriplib.h" +#include "ifilesystem.h" +#include "iarchive.h" -// forward declare, I'm cheap -void Eclass_ScanFile (char *filename); +#include "eclasslib.h" +#include "stream/stringstream.h" +#include "stream/textfilestream.h" +#include "modulesystem/moduleregistry.h" +#include "os/path.h" -const char* EClass_GetExtension() -{ - return "def"; +const char* EClass_GetExtension(){ + return "def"; } +void Eclass_ScanFile( EntityClassCollector& collector, const char *filename ); + -void CSynapseBuiltinClientDef::EnumerateInterfaces(CSynapseServer *server) +#include "modulesystem/singletonmodule.h" + +class EntityClassDefDependencies : public GlobalShaderCacheModuleRef, public GlobalScripLibModuleRef { - AddAPI(SCRIPLIB_MAJOR, NULL, sizeof(g_ScripLibTable), SYN_REQUIRE, &g_ScripLibTable); - AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable); - AddAPI(ECLASSMANAGER_MAJOR, NULL, sizeof(g_EClassManagerTable), SYN_REQUIRE, &g_EClassManagerTable); - // hardcode the minor for now, we can still add it to the synapse.config at some point - AddAPI(VFS_MAJOR, "pk3", sizeof(g_FileSystemTable_def), SYN_REQUIRE, &g_FileSystemTable_def); - - AddAPI(ECLASS_MAJOR, "def", sizeof(_EClassTable)); -} +}; -bool CSynapseBuiltinClientDef::RequestAPI(APIDescriptor_t *pAPI) +class EclassDefAPI { - if (!strcmp(pAPI->major_name, ECLASS_MAJOR)) - { - _EClassTable* pTable= static_cast<_EClassTable*>(pAPI->mpTable); - pTable->m_pfnScanFile = &Eclass_ScanFile; - pTable->m_pfnGetExtension = &EClass_GetExtension; - - return true; - } - - Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo()); - return false; +EntityClassScanner m_eclassdef; +public: +typedef EntityClassScanner Type; +STRING_CONSTANT( Name, "def" ); + +EclassDefAPI(){ + m_eclassdef.scanFile = &Eclass_ScanFile; + m_eclassdef.getExtension = &EClass_GetExtension; } +EntityClassScanner* getTable(){ + return &m_eclassdef; +} +}; -#include "version.h" +typedef SingletonModule EclassDefModule; +typedef Static StaticEclassDefModule; +StaticRegisterModule staticRegisterEclassDef( StaticEclassDefModule::instance() ); -const char* CSynapseBuiltinClientDef::GetInfo() -{ - return "Builtin .def module built " __DATE__ " " RADIANT_VERSION; + +#include "string/string.h" + +#include + + +char com_token[1024]; +bool com_eof; + +/* + ============== + COM_Parse + + Parse a token out of a string + ============== + */ +const char *COM_Parse( const char *data ){ + int c; + int len; + + len = 0; + com_token[0] = 0; + + if ( !data ) { + return 0; + } + +// skip whitespace +skipwhite: + while ( ( c = *data ) <= ' ' ) + { + if ( c == 0 ) { + com_eof = true; + return 0; // end of file; + } + data++; + } + +// skip // comments + if ( c == '/' && data[1] == '/' ) { + while ( *data && *data != '\n' ) + data++; + goto skipwhite; + } + + +// handle quoted strings specially + if ( c == '\"' ) { + data++; + do + { + c = *data++; + if ( c == '\"' ) { + com_token[len] = 0; + return data; + } + com_token[len] = c; + len++; + } while ( 1 ); + } + +// parse single characters + if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) { + com_token[len] = c; + len++; + com_token[len] = 0; + return data + 1; + } + +// parse a regular word + do + { + com_token[len] = c; + data++; + len++; + c = *data; + if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) { + break; + } + } while ( c > 32 ); + + com_token[len] = 0; + return data; +} + +const char* Get_COM_Token(){ + return com_token; } -// ------------------------------------------------------------------------------------------------ -qboolean eclass_found; -char *debugname; +const char *debugname; -void setSpecialLoad(eclass_t *e, const char* pWhat, char*& p) -{ - // Hydra: removed some amazingly bad cstring usage, whoever wrote that - // needs to be taken out and shot. - - char *pText = NULL; - char *where = NULL; - - p = NULL; // incase we don't find what we're looking for. - where = strstr(e->comments,pWhat); - if (!where) - return; - - pText = where + strlen(pWhat); - if (*pText == '\"') - pText++; - - where = strchr(pText,'\"'); - if (where) - { - int len = (where-pText); - p = new char[len + 1]; - strncpy(p,pText,len); - p[len]=0; // just to make sure, as most implementations of strncpy don't null terminate - } - else - p = strdup(pText); +void setSpecialLoad( EntityClass *e, const char* pWhat, CopiedString& p ){ + // Hydra: removed some amazingly bad cstring usage, whoever wrote that + // needs to be taken out and shot. + + const char *pText = 0; + const char *where = 0; + + where = strstr( e->comments(),pWhat ); + if ( !where ) { + return; + } + + pText = where + strlen( pWhat ); + if ( *pText == '\"' ) { + pText++; + } + + where = strchr( pText,'\"' ); + if ( where ) { + p = StringRange( pText, where ); + } + else + { + p = pText; + } } -eclass_t *Eclass_InitFromText (char *text) -{ - char *t; - int len; - int r, i; - char parms[256], *p; - eclass_t *e; - char color[128]; - - e = (eclass_t*)malloc(sizeof(*e)); - memset (e, 0, sizeof(*e)); - - text += strlen("/*QUAKED "); - - // grab the name - text = COM_Parse (text); - e->name = (char*)malloc (strlen(Get_COM_Token())+1); - strcpy (e->name, Get_COM_Token()); - debugname = e->name; - - // grab the color, reformat as texture name - r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]); - if (r != 3) { - return e; - } - sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]); - //strcpy (e->texdef.name, color); - e->texdef.SetName(color); - - while (*text != ')') - { - if (!*text) { +#include "eclasslib.h" + +/* + + the classname, color triple, and bounding box are parsed out of comments + A ? size means take the exact brush size. + + / *QUAKED (0 0 0) ? + / *QUAKED (0 0 0) (-8 -8 -8) (8 8 8) + + Flag names can follow the size description: + + / *QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY + + */ + +EntityClass *Eclass_InitFromText( const char *text ){ + EntityClass* e = Eclass_Alloc(); + e->free = &Eclass_Free; + + // grab the name + text = COM_Parse( text ); + e->m_name = Get_COM_Token(); + debugname = e->name(); + + { + // grab the color, reformat as texture name + int r = sscanf( text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2] ); + if ( r != 3 ) { return e; - } + } + eclass_capture_state( e ); + } + + while ( *text != ')' ) + { + if ( !*text ) { + return 0; + } text++; } text++; - - // get the size - text = COM_Parse (text); - if (Get_COM_Token()[0] == '(') - { // parse the size as two vectors + + // get the size + text = COM_Parse( text ); + if ( Get_COM_Token()[0] == '(' ) { // parse the size as two vectors e->fixedsize = true; - r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2], - &e->maxs[0], &e->maxs[1], &e->maxs[2]); - if (r != 6) { - return e; - } + int r = sscanf( text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2], + &e->maxs[0], &e->maxs[1], &e->maxs[2] ); + if ( r != 6 ) { + return 0; + } - for (i=0 ; i<2 ; i++) + for ( int i = 0 ; i < 2 ; i++ ) { - while (*text != ')') + while ( *text != ')' ) { - if (!*text) { - return e; - } + if ( !*text ) { + return 0; + } text++; } text++; } } - - // get the flags - - // copy to the first /n - p = parms; - while (*text && *text != '\n') - *p++ = *text++; - *p = 0; - text++; - - // any remaining words are parm flags - p = parms; - for (i=0 ; iflagnames[i], Get_COM_Token()); - } - - // find the length until close comment - for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++) - ; - - // copy the comment block out - len = t-text; - e->comments = (char*)malloc (len+1); - memcpy (e->comments, text, len); -#ifdef _WIN32 - // the win32 Gtk widgets are expecting text stuff to be in unix format (that is CR only instead of DOS's CR/LF) - // we convert on the fly by replacing the LF with a ' ' (yeah I'm cheap) - for (i=0 ; icomments[i] = ' '; - else - e->comments[i] = text[i]; -#endif - e->comments[len] = 0; - - setSpecialLoad(e, "model=", e->modelpath); - setSpecialLoad(e, "skin=", e->skinpath); - char *pFrame = NULL; - setSpecialLoad(e, "frame=", pFrame); - if (pFrame != NULL) - { - e->nFrame = atoi(pFrame); - delete pFrame; //Hydra - Fixed memory leak! - } - - if(!e->skinpath) - setSpecialLoad(e, "texture=", e->skinpath); - - // setup show flags - e->nShowFlags = 0; - if (strcmpi(e->name, "light") == 0 || strcmpi(e->name, "dlight") == 0 || strcmpi(e->name, "lightjunior") == 0) - { - e->nShowFlags |= ECLASS_LIGHT; - } - - if ( (strnicmp(e->name, "info_player", strlen("info_player")) == 0) - ||(strnicmp(e->name, "path_corner", strlen("path_corner")) == 0) - ||(strnicmp(e->name, "team_ctf", strlen("team_ctf")) == 0) - ||(strnicmp(e->name, "misc_teleporter_dest", strlen("misc_teleporter_dest")) == 0) - ) - { - e->nShowFlags |= ECLASS_ANGLE; - } - if (strcmpi(e->name, "path") == 0) - { - e->nShowFlags |= ECLASS_PATH; - } - if (strcmpi(e->name, "misc_model") == 0) - { - e->nShowFlags |= ECLASS_MISCMODEL; - } - - - return e; + // copy to the first /n + char* p = parms; + while ( *text && *text != '\n' ) + *p++ = *text++; + *p = 0; + text++; + } + + { + // any remaining words are parm flags + const char* p = parms; + for ( std::size_t i = 0 ; i < MAX_FLAGS ; i++ ) + { + p = COM_Parse( p ); + if ( !p ) { + break; + } + strcpy( e->flagnames[i], Get_COM_Token() ); + } + } + + e->m_comments = text; + + setSpecialLoad( e, "model=", e->m_modelpath ); + StringOutputStream buffer( string_length( e->m_modelpath.c_str() ) ); + buffer << PathCleaned( e->m_modelpath.c_str() ); + e->m_modelpath = buffer.c_str(); + + if ( !e->fixedsize ) { + EntityClass_insertAttribute( *e, "angle", EntityClassAttribute( "direction", "Direction", "0" ) ); + } + else + { + EntityClass_insertAttribute( *e, "angle", EntityClassAttribute( "angle", "Yaw Angle", "0" ) ); + } + EntityClass_insertAttribute( *e, "model", EntityClassAttribute( "model", "Model" ) ); + EntityClass_insertAttribute( *e, "noise", EntityClassAttribute( "sound", "Sound" ) ); + + return e; } -void Eclass_ScanFile (char *filename) -{ - int size; - char *data; - eclass_t *e; - int i; - char temp[1024]; - - QE_ConvertDOSToUnixName( temp, filename ); - - size = vfsLoadFullPathFile(filename, (void**)&data); - if (size <= 0) - { - Sys_FPrintf (SYS_ERR, "Eclass_ScanFile: %s not found\n", filename); - return; - } - Sys_Printf ("ScanFile: %s\n", temp); - eclass_found = false; - for (i=0 ; i bufferedInput( inputFile ); + for (;; ) + { + char c; + if ( !bufferedInput.readChar( c ) ) { + break; + } + + switch ( state ) + { + case eParseDefault: + if ( c == '/' ) { + state = eParseSolidus; + } + break; + case eParseSolidus: + if ( c == '/' ) { + state = eParseComment; + } + else if ( c == '*' ) { + p = quakeEd; + state = eParseQuakeED; + } + break; + case eParseComment: + if ( c == '\n' ) { + state = eParseDefault; + } + break; + case eParseQuakeED: + if ( c == *p ) { + if ( *( ++p ) == '\0' ) { + state = eParseEntityClass; + } + } + else + { + state = eParseDefault; + } + break; + case eParseEntityClass: + if ( c == '*' ) { + state = eParseEntityClassEnd; + } + else + { + buffer.push_back( c ); + } + break; + case eParseEntityClassEnd: + if ( c == '/' ) { + e = Eclass_InitFromText( buffer.c_str() ); + state = eParseDefault; + if ( e ) { + collector.insert( e ); + } + else{ + globalErrorStream() << "Error parsing: " << debugname << " in " << filename << "\n"; + } + + buffer.clear(); + state = eParseDefault; + } + else + { + buffer.push_back( '*' ); + buffer.push_back( c ); + state = eParseEntityClass; + } + break; + } + } }