initial
git-svn-id: svn://svn.icculus.org/netradiant/trunk@1 61c419a2-8eb2-4b30-bcec-8cead039b335
This commit is contained in:
407
radiant/eclass_def.cpp
Normal file
407
radiant/eclass_def.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
Copyright (C) 1999-2006 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 "eclass_def.h"
|
||||
|
||||
#include "iscriplib.h"
|
||||
#include "ifilesystem.h"
|
||||
#include "iarchive.h"
|
||||
|
||||
#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";
|
||||
}
|
||||
void Eclass_ScanFile (EntityClassCollector& collector, const char *filename);
|
||||
|
||||
|
||||
#include "modulesystem/singletonmodule.h"
|
||||
|
||||
class EntityClassDefDependencies : public GlobalShaderCacheModuleRef, public GlobalScripLibModuleRef
|
||||
{
|
||||
};
|
||||
|
||||
class EclassDefAPI
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
typedef SingletonModule<EclassDefAPI, EntityClassDefDependencies> EclassDefModule;
|
||||
typedef Static<EclassDefModule> StaticEclassDefModule;
|
||||
StaticRegisterModule staticRegisterEclassDef(StaticEclassDefModule::instance());
|
||||
|
||||
|
||||
#include "string/string.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
const char *debugname;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#include "eclasslib.h"
|
||||
|
||||
/*
|
||||
|
||||
the classname, color triple, and bounding box are parsed out of comments
|
||||
A ? size means take the exact brush size.
|
||||
|
||||
/ *QUAKED <classname> (0 0 0) ?
|
||||
/ *QUAKED <classname> (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
|
||||
e->fixedsize = true;
|
||||
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 (int i=0 ; i<2 ; i++)
|
||||
{
|
||||
while (*text != ')')
|
||||
{
|
||||
if (!*text) {
|
||||
return 0;
|
||||
}
|
||||
text++;
|
||||
}
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
char parms[256];
|
||||
// get the flags
|
||||
{
|
||||
// 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 (EntityClassCollector& collector, const char *filename)
|
||||
{
|
||||
EntityClass *e;
|
||||
|
||||
TextFileInputStream inputFile(filename);
|
||||
if(inputFile.failed())
|
||||
{
|
||||
globalErrorStream() << "ScanFile: " << filename << " not found\n";
|
||||
return;
|
||||
}
|
||||
globalOutputStream() << "ScanFile: " << filename << "\n";
|
||||
|
||||
enum EParserState
|
||||
{
|
||||
eParseDefault,
|
||||
eParseSolidus,
|
||||
eParseComment,
|
||||
eParseQuakeED,
|
||||
eParseEntityClass,
|
||||
eParseEntityClassEnd,
|
||||
} state = eParseDefault;
|
||||
const char* quakeEd = "QUAKED";
|
||||
const char* p = 0;
|
||||
StringBuffer buffer;
|
||||
SingleCharacterInputStream<TextFileInputStream> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user