jedi-outcast/utils/Radiant/materials.cpp
2013-04-22 15:25:59 +10:00

534 lines
9.6 KiB
C++

// Filename:- materials.cpp
//
// (File contains stuff imported from SoFED to fill in the materials dialogue box, only applies to SOF)
//
#include "stdafx.h" // including these for what would otherwise be blank under Q3 keeps .PCHs working better.
#include "Radiant.h"
// Note: this file contains some stuff that's duplicated in other files (eg parse.cpp), but the code here has so
// many fiddly differences (and is only loaded to fill in one dialogue in the SOF compile-version of this editor
// that I've just kepy it all self-contained here, so it can be ripped out and disposed off later when the project
// is done.
#ifdef SOF // may as well hide entire file except for SOF mode
#include "materials.h"
#include "direct.h"
//#include "cmdlib.h"
//#include "scriplib.h"
#define BASEDIRNAME "base"
#define PATHSEPERATOR '/'
/*
=============================================================================
PARSING STUFF
=============================================================================
*/
typedef struct
{
char filename[1024];
char *buffer,*script_p,*end_p;
int line;
} script_t;
#define MAX_INCLUDES 8
script_t scriptstack[MAX_INCLUDES];
script_t *script;
int sof_scriptline;
char sof_token[MAXTOKEN];
qboolean endofscript;
qboolean tokenready; // only true if UnGetScriptToken was just called
// protos...
//
void AddScriptToStack (char *filename);
void LoadScriptFile (char *filename);
void ParseFromMemory (char *buffer, int size);
void UnGetScriptToken (void);
qboolean EndOfScript (qboolean crossline);
qboolean GetScriptToken (qboolean crossline);
qboolean ScriptTokenAvailable (void);
char *ExpandPath (char *path);
extern char sof_token[MAXTOKEN];
extern int sof_scriptline;
void StartTokenParsing (char *data);
qboolean GetToken (qboolean crossline);
void UngetToken (void);
qboolean TokenAvailable (void);
void Q_getwd (char *out)
{
#ifdef WIN32
_getcwd (out, 256);
strcat (out, "\\");
#else
getwd (out);
strcat (out, "/");
#endif
}
/*
qdir will hold the path up to the quake directory, including the slash
f:\quake\
/raid/quake/
gamedir will hold qdir + the game directory (id1, id2, etc)
*/
char qdir[1024];
char gamedir[1024];
void SetQdirFromPath (char *path)
{
char temp[1024];
char *c;
int len;
if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
{ // path is partial
Q_getwd (temp);
strcat (temp, path);
path = temp;
}
// search for "quake2" in path
#if 1
len = strlen(BASEDIRNAME);
for (c=path+strlen(path)-1 ; c != path ; c--)
{
if (!Q_strncasecmp (c, BASEDIRNAME, len))
{
strncpy (qdir, path, c-path);
Sys_Printf ("qdir: %s\n", qdir);
while (*c)
{
if (*c == '/' || *c == '\\')
{
strncpy (gamedir, path, c+1-path);
Sys_Printf ("gamedir: %s\n", gamedir);
return;
}
c++;
}
// assert(0);
Error ("Gamedir at root in %s", path);
return;
}
}
// assert(0);
Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
#else
len = strlen(BASEDIRNAME);
for (c=path+strlen(path)-1 ; c != path ; c--)
if (!Q_strncasecmp (c, BASEDIRNAME, len))
{
strncpy (qdir, path, c+len+1-path);
qprintf ("qdir: %s\n", qdir);
c += len+1;
while (*c)
{
if (*c == '/' || *c == '\\')
{
strncpy (gamedir, path, c+1-path);
qprintf ("gamedir: %s\n", gamedir);
return;
}
c++;
}
Error ("No gamedir in %s", path);
return;
}
Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
#endif
}
materialtype_t defaultmaterialtypes[] =
{
{"gravel", MATERIAL_GRAVEL},
{"metal", MATERIAL_METAL},
{"stone", MATERIAL_STONE},
{"wood", MATERIAL_WOOD},
{NULL, 0}
};
materialtype_t *materialtypes = NULL;// defaultmaterialtypes;
void QFile_ReadMaterialTypes(char* filename)
{
int i;
FILE *f;
if (materialtypes != defaultmaterialtypes)
{
if (materialtypes)
free(materialtypes);
materialtypes = (materialtype_t*)malloc(256 * sizeof(materialtype_t));
}
f = fopen (filename, "rb");
if (!f)
{
materialtypes = defaultmaterialtypes;
return;
}
fclose (f);
LoadScriptFile(filename);
i = 0;
do
{
GetScriptToken (true);
if (endofscript)
{
break;
}
if (strcmp(sof_token, "material") != 0)
{
while (ScriptTokenAvailable())
{
GetScriptToken(false);
}
}
else
{
GetScriptToken(false);
materialtypes[i].name = (char*)malloc(strlen(sof_token) + 1);
strcpy(materialtypes[i].name, sof_token);
GetScriptToken (false);
materialtypes[i].value = atoi(sof_token);
}
}
while (i++ < 255);
materialtypes[i].name = NULL;
materialtypes[i].value = 0;
}
char *ExpandPath (char *path)
{
static char full[1024];
if (!qdir)
Error ("ExpandPath called without qdir set");
if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
return path;
sprintf (full, "%s%s", qdir, path);
return full;
}
/*
==============
AddScriptToStack
==============
*/
void AddScriptToStack (char *filename)
{
int size;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, ExpandPath (filename) );
size = LoadFile (script->filename, (void **)&script->buffer);
printf ("entering %s\n", script->filename);
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
}
/*
==============
LoadScriptFile
==============
*/
void LoadScriptFile (char *filename)
{
script = scriptstack;
AddScriptToStack (filename);
endofscript = false;
tokenready = false;
}
/*
==============
ParseFromMemory
==============
*/
void ParseFromMemory (char *buffer, int size)
{
script = scriptstack;
script++;
if (script == &scriptstack[MAX_INCLUDES])
Error ("script file exceeded MAX_INCLUDES");
strcpy (script->filename, "memory buffer" );
script->buffer = buffer;
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
endofscript = false;
tokenready = false;
}
/*
==============
UnGetScriptToken
Signals that the current sof_token was not used, and should be reported
for the next GetScriptToken. Note that
GetScriptToken (true);
UnGetScriptToken ();
GetScriptToken (false);
could cross a line boundary.
==============
*/
void UnGetScriptToken (void)
{
tokenready = true;
}
qboolean EndOfScript (qboolean crossline)
{
if (!crossline)
Error ("Line %i is incomplete\n",sof_scriptline);
if (!strcmp (script->filename, "memory buffer"))
{
endofscript = true;
return false;
}
free (script->buffer);
if (script == scriptstack+1)
{
endofscript = true;
return false;
}
script--;
sof_scriptline = script->line;
printf ("returning to %s\n", script->filename);
return GetScriptToken (crossline);
}
/*
==============
GetScriptToken
==============
*/
qboolean GetScriptToken (qboolean crossline)
{
char *token_p;
if (tokenready) // is a sof_token allready waiting?
{
tokenready = false;
return true;
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
//
// skip space
//
skipspace:
while (*script->script_p <= 32)
{
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
if (*script->script_p++ == '\n')
{
if (!crossline)
Error ("Line %i is incomplete\n",sof_scriptline);
sof_scriptline = script->line++;
}
}
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
// ; # // comments
if (*script->script_p == ';' || *script->script_p == '#'
|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
{
if (!crossline)
Error ("Line %i is incomplete\n",sof_scriptline);
while (*script->script_p++ != '\n')
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
goto skipspace;
}
// /* */ comments
if (script->script_p[0] == '/' && script->script_p[1] == '*')
{
if (!crossline)
Error ("Line %i is incomplete\n",sof_scriptline);
script->script_p+=2;
while (script->script_p[0] != '*' && script->script_p[1] != '/')
{
script->script_p++;
if (script->script_p >= script->end_p)
return EndOfScript (crossline);
}
script->script_p += 2;
goto skipspace;
}
//
// copy sof_token
//
token_p = sof_token;
if (*script->script_p == '"')
{
// quoted sof_token
script->script_p++;
while (*script->script_p != '"')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &sof_token[MAXTOKEN])
Error ("Token too large on line %i\n",sof_scriptline);
}
script->script_p++;
}
else // regular sof_token
while ( *script->script_p > 32 && *script->script_p != ';')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &sof_token[MAXTOKEN])
Error ("Token too large on line %i\n",sof_scriptline);
}
*token_p = 0;
if (!strcmp (sof_token, "$include"))
{
GetScriptToken (false);
AddScriptToStack (sof_token);
return GetScriptToken (crossline);
}
return true;
}
/*
==============
ScriptTokenAvailable
Returns true if there is another sof_token on the line
==============
*/
qboolean ScriptTokenAvailable (void)
{
char *search_p;
search_p = script->script_p;
if (search_p >= script->end_p)
return false;
while ( *search_p <= 32)
{
if (*search_p == '\n')
return false;
search_p++;
if (search_p == script->end_p)
return false;
}
if (*search_p == ';')
return false;
return true;
}
char *ExpandArg (char *path)
{
static char full[1024];
if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
{
Q_getwd (full);
strcat (full, path);
}
else
strcpy (full, path);
return full;
}
#endif // #ifdef SOF
///////////////////// eof //////////////////////////