2010-09-09 11:46:38 +00:00
|
|
|
#include <dirent.h>
|
2003-03-18 19:48:24 +00:00
|
|
|
|
2010-09-09 11:46:38 +00:00
|
|
|
#include "QF/quakeio.h"
|
|
|
|
#include "QF/script.h"
|
|
|
|
#include "QF/sys.h"
|
|
|
|
#include "QF/va.h"
|
|
|
|
|
|
|
|
#include "EntityClass.h"
|
2003-03-18 19:48:24 +00:00
|
|
|
|
|
|
|
@implementation EntityClass
|
|
|
|
|
2010-09-09 11:46:38 +00:00
|
|
|
static int
|
2010-09-11 10:03:41 +00:00
|
|
|
parse_vector (script_t * script, vec3_t vec)
|
2010-09-09 11:46:38 +00:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (!Script_GetToken (script, 0))
|
|
|
|
return 0;
|
2010-09-12 10:46:41 +00:00
|
|
|
if (strcmp (Script_Token (script), "("))
|
2010-09-09 11:46:38 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
r = sscanf (script->p, "%f %f %f)", &vec[0], &vec[1], &vec[2]);
|
|
|
|
if (r != 3)
|
|
|
|
return 0;
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2010-09-12 10:46:41 +00:00
|
|
|
while (strcmp (Script_Token (script), ")")) {
|
2010-09-09 11:46:38 +00:00
|
|
|
if (!Script_GetToken (script, 0))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
// 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
|
|
|
|
|
2010-09-12 09:12:02 +00:00
|
|
|
-initFromText:(const char *) text source:(const char *) filename
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
2010-09-09 11:46:38 +00:00
|
|
|
const char *t;
|
|
|
|
size_t len;
|
|
|
|
int i;
|
|
|
|
script_t *script;
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
[super init];
|
2010-09-11 10:03:41 +00:00
|
|
|
|
|
|
|
text += strlen ("/*QUAKED ");
|
2010-09-09 11:46:38 +00:00
|
|
|
|
|
|
|
script = Script_New ();
|
|
|
|
Script_Start (script, filename, text);
|
|
|
|
|
|
|
|
// grab the name
|
|
|
|
if (!Script_GetToken (script, 0))
|
|
|
|
return 0;
|
2010-09-12 10:46:41 +00:00
|
|
|
if (!strcmp (Script_Token (script), "*/"))
|
2010-09-09 11:46:38 +00:00
|
|
|
return 0;
|
2010-09-12 10:46:41 +00:00
|
|
|
name = strdup (Script_Token (script));
|
2010-09-09 11:46:38 +00:00
|
|
|
|
|
|
|
// grab the color
|
|
|
|
if (!parse_vector (script, color))
|
|
|
|
return 0;
|
2010-09-11 10:03:41 +00:00
|
|
|
// get the size
|
2010-09-12 10:46:41 +00:00
|
|
|
if (!Script_GetToken (script, 0))
|
|
|
|
return 0;
|
|
|
|
if (!strcmp (Script_Token (script), "(")) {
|
2010-09-09 11:46:38 +00:00
|
|
|
Script_UngetToken (script);
|
|
|
|
if (!parse_vector (script, mins))
|
|
|
|
return 0;
|
|
|
|
if (!parse_vector (script, maxs))
|
|
|
|
return 0;
|
2003-03-18 19:48:24 +00:00
|
|
|
esize = esize_fixed;
|
2010-09-12 10:46:41 +00:00
|
|
|
} else if (!strcmp (Script_Token (script), "?")) {
|
2010-09-09 11:46:38 +00:00
|
|
|
// use the brushes
|
2003-03-18 19:48:24 +00:00
|
|
|
esize = esize_model;
|
2010-09-09 11:46:38 +00:00
|
|
|
} else {
|
|
|
|
return 0;
|
2003-03-18 19:48:24 +00:00
|
|
|
}
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2010-09-09 11:46:38 +00:00
|
|
|
// get the flags
|
|
|
|
// any remaining words on the line are parm flags
|
|
|
|
for (i = 0; i < MAX_FLAGS; i++) {
|
|
|
|
if (!Script_TokenAvailable (script, 0))
|
2003-03-18 19:48:24 +00:00
|
|
|
break;
|
2010-09-09 11:46:38 +00:00
|
|
|
Script_GetToken (script, 0);
|
2010-09-12 10:46:41 +00:00
|
|
|
flagnames[i] = strdup (Script_Token (script));
|
2010-09-09 11:46:38 +00:00
|
|
|
}
|
|
|
|
while (Script_TokenAvailable (script, 0))
|
|
|
|
Script_GetToken (script, 0);
|
2003-03-18 19:48:24 +00:00
|
|
|
|
|
|
|
// find the length until close comment
|
2010-09-12 10:46:41 +00:00
|
|
|
for (t = script->p; t[0] && !(t[0] == '*' && t[1] == '/'); t++)
|
|
|
|
;
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
// copy the comment block out
|
2010-09-09 11:46:38 +00:00
|
|
|
len = t - text;
|
|
|
|
comments = malloc (len + 1);
|
2003-03-18 19:48:24 +00:00
|
|
|
memcpy (comments, text, len);
|
|
|
|
comments[len] = 0;
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2010-09-11 10:03:41 +00:00
|
|
|
-(esize_t) esize
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
|
|
|
return esize;
|
|
|
|
}
|
|
|
|
|
2010-09-28 09:41:38 +00:00
|
|
|
-(const char *) classname
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2010-09-11 10:03:41 +00:00
|
|
|
-(float *) mins
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
|
|
|
return mins;
|
|
|
|
}
|
|
|
|
|
2010-09-11 10:03:41 +00:00
|
|
|
-(float *) maxs
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
|
|
|
return maxs;
|
|
|
|
}
|
|
|
|
|
2010-09-11 10:03:41 +00:00
|
|
|
-(float *) drawColor
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
|
|
|
return color;
|
|
|
|
}
|
|
|
|
|
2010-09-28 09:41:38 +00:00
|
|
|
-(const char *) comments
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
|
|
|
return comments;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-28 09:41:38 +00:00
|
|
|
-(const char *) flagName:(unsigned) flagnum
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
|
|
|
if (flagnum >= MAX_FLAGS)
|
2010-09-09 11:46:38 +00:00
|
|
|
Sys_Error ("EntityClass flagName: bad number");
|
2003-03-18 19:48:24 +00:00
|
|
|
return flagnames[flagnum];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
//===========================================================================
|
|
|
|
|
2010-09-12 07:25:25 +00:00
|
|
|
#define THING EntityClassList
|
|
|
|
#include "THING+NSArray.m"
|
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
@implementation EntityClassList
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
insertEC:
|
|
|
|
=================
|
|
|
|
*/
|
2010-09-11 10:03:41 +00:00
|
|
|
- (void) insertEC:ec
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
2010-09-28 09:41:38 +00:00
|
|
|
const char *name;
|
2010-09-11 10:03:41 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
name =[ec classname];
|
|
|
|
for (i = 0; i <[self count]; i++) {
|
|
|
|
if (strcasecmp (name,[[self objectAtIndex:i] classname]) < 0) {
|
2003-03-18 19:48:24 +00:00
|
|
|
[self insertObject: ec atIndex:i];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-09-11 10:03:41 +00:00
|
|
|
[self addObject:ec];
|
2003-03-18 19:48:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
scanFile
|
|
|
|
=================
|
|
|
|
*/
|
2010-09-28 09:41:38 +00:00
|
|
|
-(void) scanFile:(const char *) filename
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
2010-09-11 10:03:41 +00:00
|
|
|
int size, line;
|
|
|
|
char *data;
|
|
|
|
id cl;
|
|
|
|
int i;
|
|
|
|
char path[1024];
|
|
|
|
QFile *file;
|
2010-09-09 11:46:38 +00:00
|
|
|
|
2010-09-11 10:03:41 +00:00
|
|
|
sprintf (path, "%s/%s", source_path, filename);
|
2010-09-09 11:46:38 +00:00
|
|
|
|
|
|
|
file = Qopen (path, "rt");
|
|
|
|
if (!file)
|
|
|
|
return;
|
|
|
|
size = Qfilesize (file);
|
|
|
|
data = malloc (size + 1);
|
|
|
|
size = Qread (file, data, size);
|
|
|
|
data[size] = 0;
|
|
|
|
Qclose (file);
|
|
|
|
|
|
|
|
line = 1;
|
2010-09-11 10:03:41 +00:00
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
if (!strncmp (data + i, "/*QUAKED", 8)) {
|
|
|
|
cl =[[EntityClass alloc] initFromText:(data + i)
|
|
|
|
source:va ("%s:%d", filename, line)];
|
2003-03-18 19:48:24 +00:00
|
|
|
if (cl)
|
2010-09-11 10:03:41 +00:00
|
|
|
[self insertEC:cl];
|
2010-09-09 11:46:38 +00:00
|
|
|
} else if (data[i] == '\n') {
|
|
|
|
line++;
|
2003-03-18 19:48:24 +00:00
|
|
|
}
|
2010-09-09 11:46:38 +00:00
|
|
|
}
|
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
free (data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
scanDirectory
|
|
|
|
=================
|
|
|
|
*/
|
2010-09-11 10:03:41 +00:00
|
|
|
-(void) scanDirectory
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
2010-09-11 10:03:41 +00:00
|
|
|
int count, i;
|
2010-09-09 11:46:38 +00:00
|
|
|
struct dirent **namelist, *ent;
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
[self removeAllObjects];
|
2010-09-11 10:03:41 +00:00
|
|
|
|
|
|
|
count = scandir (source_path, &namelist, NULL, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
int len;
|
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
ent = namelist[i];
|
|
|
|
len = strlen (ent->d_name);
|
|
|
|
if (len <= 3)
|
|
|
|
continue;
|
2010-09-11 10:03:41 +00:00
|
|
|
if (!strcmp (ent->d_name + len - 3, ".qc"))
|
|
|
|
[self scanFile:ent->d_name];
|
2003-03-18 19:48:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-11 10:03:41 +00:00
|
|
|
id entity_classes_i;
|
2003-03-18 19:48:24 +00:00
|
|
|
|
|
|
|
|
2010-09-28 09:41:38 +00:00
|
|
|
-initForSourceDirectory:(const char *) path
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
2010-09-12 07:25:25 +00:00
|
|
|
self = [super init];
|
|
|
|
array = [[NSMutableArray alloc] init];
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2010-09-28 09:41:38 +00:00
|
|
|
source_path = strdup (path); //FIXME leak?
|
2003-03-18 19:48:24 +00:00
|
|
|
[self scanDirectory];
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
entity_classes_i = self;
|
2010-09-11 10:03:41 +00:00
|
|
|
|
|
|
|
nullclass =[[EntityClass alloc]
|
|
|
|
initFromText: "/*QUAKED UNKNOWN_CLASS (0 0.5 0) ?*/" source:va ("%s:%d", __FILE__,
|
|
|
|
__LINE__ -
|
|
|
|
1)];
|
2003-03-18 19:48:24 +00:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2010-09-27 15:29:16 +00:00
|
|
|
-(id) classForName:(const char *) name
|
2003-03-18 19:48:24 +00:00
|
|
|
{
|
2010-09-11 10:03:41 +00:00
|
|
|
int i;
|
|
|
|
id o;
|
|
|
|
|
|
|
|
for (i = 0; i <[self count]; i++) {
|
|
|
|
o =[self objectAtIndex:i];
|
|
|
|
if (!strcmp (name,[o classname]))
|
2003-03-18 19:48:24 +00:00
|
|
|
return o;
|
|
|
|
}
|
2010-09-11 10:03:41 +00:00
|
|
|
|
2003-03-18 19:48:24 +00:00
|
|
|
return nullclass;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@end
|