]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/radiant/ECLASS.CPP
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / tools / radiant / ECLASS.CPP
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "qe3.h"
33 #include "io.h"
34 #include "../../renderer/tr_local.h"
35
36 struct evarPrefix_t {
37         int type;
38         const char *prefix;
39 };
40
41 const evarPrefix_t EvarPrefixes[] = {
42         { EVAR_STRING,  "editor_var " },
43         { EVAR_INT,             "editor_int " },
44         { EVAR_FLOAT,   "editor_float " },
45         { EVAR_BOOL,    "editor_bool " },
46         { EVAR_COLOR,   "editor_color " },
47         { EVAR_MATERIAL,"editor_mat " },
48         { EVAR_MODEL,   "editor_model " },
49         { EVAR_GUI,             "editor_gui " },
50         { EVAR_SOUND,   "editor_snd "}
51 };
52
53 const int NumEvarPrefixes = sizeof(EvarPrefixes) / sizeof(evarPrefix_t);
54
55 eclass_t        *eclass = NULL;
56 eclass_t        *eclass_bad = NULL;
57 char            eclass_directory[1024];
58
59 // md3 cache for misc_models
60 eclass_t *g_md3Cache = NULL;
61
62 /*
63
64 the classname, color triple, and bounding box are parsed out of comments
65 A ? size means take the exact brush size.
66
67 /*QUAKED <classname> (0 0 0) ?
68 /*QUAKED <classname> (0 0 0) (-8 -8 -8) (8 8 8)
69
70 Flag names can follow the size description:
71
72 /*QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY
73
74 */
75
76 void CleanEntityList( eclass_t *&pList ) {
77         while (pList) {
78                 eclass_t* pTemp = pList->next;
79                 delete pList;
80                 pList = pTemp;
81         }
82         pList = NULL;
83 }
84
85
86 void CleanUpEntities()
87 {
88         CleanEntityList(eclass);
89         CleanEntityList(g_md3Cache);
90
91         if ( eclass_bad ) {
92                 delete eclass_bad;
93                 eclass_bad = NULL;
94         }
95 }
96
97 void ExtendBounds(idVec3 v, idVec3 &vMin, idVec3 &vMax)
98 {
99         for (int i = 0 ;i < 3 ;i++)
100         {
101                 float   f = v[i];
102                 
103     if (f < vMin[i])
104     {
105                         vMin[i] = f;
106     }
107
108     if (f > vMax[i])
109     {
110                         vMax[i] = f;
111     }
112         }
113 }
114
115 bool LoadModel(const char *pLocation, eclass_t *e, idVec3 &vMin, idVec3 &vMax, const char *pSkin)
116 {
117         vMin[0] = vMin[1] = vMin[2] = 999999;
118         vMax[0] = vMax[1] = vMax[2] = -999999;
119
120         if (strstr(pLocation, ".ase") != NULL)  // FIXME: not correct!
121         {
122                 idBounds b;
123                 e->modelHandle = renderModelManager->FindModel( pLocation );
124                 b = e->modelHandle->Bounds( NULL );
125                 VectorCopy(b[0], vMin);
126                 VectorCopy(b[1], vMax);
127                 return true;
128         }
129         return false;
130 }
131
132 eclass_t *EClass_Alloc( void ) {
133         eclass_t *e;
134         e = new eclass_t;
135         if ( e == NULL ) {
136                 return NULL;
137         }
138         e->fixedsize = false;
139         e->unknown = false;
140         e->mins.Zero();
141         e->maxs.Zero();
142         e->color.Zero();
143         memset( &e->texdef, 0, sizeof( e->texdef ) );
144         e->modelHandle = NULL;
145         e->entityModel = NULL;
146         e->nFrame = 0;
147         e->nShowFlags = 0;
148         e->hPlug = 0;
149         e->next = NULL;
150         return e;
151 }
152
153
154 eclass_t *EClass_InitFromDict( const idDict *d, const char *name ) {
155         eclass_t                        *e;
156         const idKeyValue        *kv;
157
158         // only include entityDefs with "editor_" values in them
159         if ( !d->MatchPrefix( "editor_" ) ) {
160                 return NULL;
161         }
162
163         e = EClass_Alloc();
164         if ( !e ) {
165                 return NULL;
166         }
167
168         e->defArgs = *d;
169
170         idStr str;
171         idStr text;
172         idStr varname;
173         idStr defaultStr;
174
175         e->name = name;
176         d->GetVector("editor_color", "0 0 1", e->color);
177
178         d->GetString("editor_mins", "", str);
179         if (str != "?") {
180                 d->GetVector("editor_mins", "0 0 0", e->mins);
181                 d->GetVector("editor_maxs", "0 0 0", e->maxs);
182                 e->fixedsize = true;
183         } else {
184                 e->fixedsize = false;
185         }
186
187
188         d->GetString("editor_material", "", e->defMaterial);
189
190         //str = d->GetString("model");
191         //if (str.Length()) {
192         //      e->entityModel = renderModelManager->FindModel(str);
193         //}
194         
195         str = "";
196
197         // concatenate all editor usage comments
198         text = "";
199         kv = d->MatchPrefix( "editor_usage" );
200         while( kv != NULL ) {
201                 text += kv->GetValue();
202                 if ( !kv->GetValue().Length() || ( text[ text.Length() - 1 ] != '\n' ) ) {
203                         text += "\n";
204                 }
205                 kv = d->MatchPrefix( "editor_usage", kv );
206         }
207
208         e->desc = text;
209
210         str += "Spawn args:\n";
211         for (int i = 0; i < NumEvarPrefixes; i++) {
212                 kv = d->MatchPrefix(EvarPrefixes[i].prefix);
213                 while (kv) {
214                         evar_t ev;
215                         kv->GetKey().Right( kv->GetKey().Length() - strlen(EvarPrefixes[i].prefix), ev.name );
216                         ev.desc = kv->GetValue();
217                         ev.type = EvarPrefixes[i].type;
218                         e->vars.Append(ev);
219                         kv = d->MatchPrefix(EvarPrefixes[i].prefix, kv);
220                 }
221         }
222
223 /*
224         while( kv != NULL ) {
225                 kv->key.Right( kv->key.Length() - 11, varname );
226                 str += va( "'%s':\t %s", varname.c_str(), kv->value.c_str() );
227                 if ( d->GetString( varname, "", defaultStr ) && defaultStr.Length() ) {
228                         str += va( "  Default '%s'.", defaultStr.c_str() );
229                 }
230                 str += "\n";
231                 kv = d->MatchPrefix( "editor_var ", kv );
232         }
233
234         e->comments = Mem_CopyString( str.c_str() );
235 */
236
237         
238         // concatenate all variable comments
239         kv = d->MatchPrefix( "editor_copy" );
240         while (kv) {
241                 const char *temp = d->GetString(kv->GetValue());
242                 if (temp && *temp) {
243                         e->args.Set(kv->GetValue(), d->GetString(kv->GetValue()));
244                 }
245                 kv = d->MatchPrefix("editor_copy", kv);
246         }
247
248         // setup show flags
249         e->nShowFlags = 0;
250         if (d->GetBool("editor_rotatable")) {
251                 e->nShowFlags |= ECLASS_ROTATABLE;
252         }
253
254         if (d->GetBool("editor_showangle")) {
255                 e->nShowFlags |= ECLASS_ANGLE;
256         }
257
258         if (d->GetBool("editor_mover")) {
259                 e->nShowFlags |= ECLASS_MOVER;
260         }
261
262         if (d->GetBool("editor_env") || idStr::Icmpn(e->name, "env_", 4) == 0) {
263                 e->nShowFlags |= (ECLASS_ENV | ECLASS_ROTATABLE);
264                 if (d->GetBool("editor_ragdoll")) {
265                         e->defArgs.Set("model", "");
266                 }
267         }
268
269         if (d->GetBool("editor_combatnode")) {
270                 e->nShowFlags |= ECLASS_COMBATNODE;
271         }
272
273         if (d->GetBool("editor_light")) {
274                 e->nShowFlags |= ECLASS_LIGHT;
275         }
276
277         if ( idStr::Icmp(e->name, "light") == 0 ) {
278                 e->nShowFlags |= ECLASS_LIGHT;
279         } else if ( idStr::Icmp(e->name, "path") == 0 ) {
280                 e->nShowFlags |= ECLASS_PATH;
281         } else if ( idStr::Icmp(e->name, "target_null") == 0 ) {
282                 e->nShowFlags |= ECLASS_CAMERAVIEW;
283         } else if ( idStr::Icmp(e->name, "worldspawn") == 0 ) {
284                 e->nShowFlags |= ECLASS_WORLDSPAWN;
285         } else if ( idStr::Icmp(e->name, "speaker") == 0 ) {
286                 e->nShowFlags |= ECLASS_SPEAKER;
287         } else if ( idStr::Icmp( e->name, "func_emitter" ) == 0 || idStr::Icmp( e->name, "func_splat" ) == 0 ) {
288                 e->nShowFlags |= ECLASS_PARTICLE;
289         } else if ( idStr::Icmp(e->name, "func_liquid") == 0 ) {
290                 e->nShowFlags |= ECLASS_LIQUID;
291         } 
292
293         return e;
294 }
295
296 void EClass_InsertSortedList(eclass_t *&pList, eclass_t *e)
297 {
298         eclass_t        *s;
299         
300         if (!pList)
301         {
302                 pList = e;
303                 return;
304         }
305
306
307         s = pList;
308         if (stricmp (e->name, s->name) < 0)
309         {
310                 e->next = s;
311                 pList = e;
312                 return;
313         }
314
315         do
316         {
317                 if (!s->next || stricmp (e->name, s->next->name) < 0)
318                 {
319                         e->next = s->next;
320                         s->next = e;
321                         return;
322                 }
323                 s=s->next;
324         } while (1);
325 }
326
327 /*
328 =================
329 Eclass_InsertAlphabetized
330 =================
331 */
332 void Eclass_InsertAlphabetized (eclass_t *e)
333 {
334 #if 1
335   EClass_InsertSortedList(eclass, e);
336 #else
337         eclass_t        *s;
338         
339         if (!eclass)
340         {
341                 eclass = e;
342                 return;
343         }
344
345
346         s = eclass;
347         if (stricmp (e->name, s->name) < 0)
348         {
349                 e->next = s;
350                 eclass = e;
351                 return;
352         }
353
354         do
355         {
356                 if (!s->next || stricmp (e->name, s->next->name) < 0)
357                 {
358                         e->next = s->next;
359                         s->next = e;
360                         return;
361                 }
362                 s=s->next;
363         } while (1);
364 #endif
365 }
366
367
368 void Eclass_InitForSourceDirectory (const char *path)
369 {
370         int c = declManager->GetNumDecls(DECL_ENTITYDEF);
371         for (int i = 0; i < c; i++) {
372                 const idDeclEntityDef *def = static_cast<const idDeclEntityDef *>( declManager->DeclByIndex( DECL_ENTITYDEF, i ) );
373                 if ( def ) {
374                         eclass_t *e = EClass_InitFromDict( &def->dict, def->GetName() );
375                         if ( e ) {
376                                 Eclass_InsertAlphabetized (e);
377                         }
378                 }
379         }
380
381         eclass_bad = EClass_Alloc();
382         if ( !eclass_bad ) {
383                 return;
384         }
385         eclass_bad->color.x = 0.0f;
386         eclass_bad->color.y = 0.5f;
387         eclass_bad->color.z = 0.0f;
388         eclass_bad->fixedsize = false;
389         eclass_bad->name = Mem_CopyString( "UKNOWN ENTITY CLASS" );
390 }
391
392 eclass_t *Eclass_ForName (const char *name, bool has_brushes)
393 {
394         eclass_t        *e;
395         char buff[1024];
396
397         if (!name) {
398                 return eclass_bad;
399         }
400
401         for ( e = eclass; e; e = e->next ) {
402                 if ( !strcmp( name, e->name ) ) {
403                         return e;
404                 }
405         }
406
407         e = EClass_Alloc();
408         if ( !e ) {
409                 return NULL;
410         }
411         e->name = Mem_CopyString( name );
412         sprintf(buff, "%s not found in def/*.def\n", name);
413         e->comments = Mem_CopyString( buff );
414         e->color.x = 0.0f;
415         e->color.y = 0.5f;
416         e->color.z = 0.0f;
417         e->fixedsize = !has_brushes;
418         e->mins.x = e->mins.y = e->mins.z = -8.0f;
419         e->maxs.x = e->maxs.y = e->maxs.z = 8.0f;
420         Eclass_InsertAlphabetized( e );
421
422         return e;
423 }
424
425
426 eclass_t* GetCachedModel(entity_t *pEntity, const char *pName, idVec3 &vMin, idVec3 &vMax)
427 {
428         eclass_t *e = NULL;
429         if (pName == NULL || strlen(pName) == 0) {
430                 return NULL;
431         }
432
433         for (e = g_md3Cache; e ; e = e->next) {
434                 if (!strcmp (pName, e->name)) {
435                         pEntity->md3Class = e;
436                         VectorCopy(e->mins, vMin);
437                         VectorCopy(e->maxs, vMax);
438                         return e;
439             }
440         }
441
442         e = (eclass_t*)Mem_ClearedAlloc(sizeof(*e));
443         memset (e, 0, sizeof(*e));
444         e->name = Mem_CopyString( pName );
445         e->color[0] = e->color[2] = 0.85f;
446         if (LoadModel(pName, e, vMin, vMax, NULL)) {
447                 EClass_InsertSortedList(g_md3Cache, e);
448                 VectorCopy(vMin, e->mins);
449                 VectorCopy(vMax, e->maxs);
450                 pEntity->md3Class = e;
451                 return e;
452         }
453         return NULL;
454 }