entity.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake 2 Tools source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "qe3.h"
  19. char *ValueForKey (entity_t *ent, char *key)
  20. {
  21. epair_t *ep;
  22. for (ep=ent->epairs ; ep ; ep=ep->next)
  23. if (!strcmp (ep->key, key) )
  24. return ep->value;
  25. return "";
  26. }
  27. void SetKeyValue (entity_t *ent, char *key, char *value)
  28. {
  29. epair_t *ep;
  30. if (ent == NULL)
  31. return;
  32. if (!key || !key[0])
  33. return;
  34. for (ep=ent->epairs ; ep ; ep=ep->next)
  35. if (!strcmp (ep->key, key) )
  36. {
  37. free (ep->value);
  38. ep->value = qmalloc(strlen(value)+1);
  39. strcpy (ep->value, value);
  40. return;
  41. }
  42. ep = qmalloc (sizeof(*ep));
  43. ep->next = ent->epairs;
  44. ent->epairs = ep;
  45. ep->key = qmalloc(strlen(key)+1);
  46. strcpy (ep->key, key);
  47. ep->value = qmalloc(strlen(value)+1);
  48. strcpy (ep->value, value);
  49. }
  50. void DeleteKey (entity_t *ent, char *key)
  51. {
  52. epair_t **ep, *next;
  53. ep = &ent->epairs;
  54. while (*ep)
  55. {
  56. next = *ep;
  57. if ( !strcmp (next->key, key) )
  58. {
  59. *ep = next->next;
  60. free(next->key);
  61. free(next->value);
  62. free(next);
  63. return;
  64. }
  65. ep = &next->next;
  66. }
  67. }
  68. float FloatForKey (entity_t *ent, char *key)
  69. {
  70. char *k;
  71. k = ValueForKey (ent, key);
  72. return atof(k);
  73. }
  74. int IntForKey (entity_t *ent, char *key)
  75. {
  76. char *k;
  77. k = ValueForKey (ent, key);
  78. return atoi(k);
  79. }
  80. void GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
  81. {
  82. char *k;
  83. k = ValueForKey (ent, key);
  84. sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
  85. }
  86. /*
  87. ===============
  88. Entity_Free
  89. Frees the entity and any brushes is has.
  90. The entity is removed from the global entities list.
  91. ===============
  92. */
  93. void Entity_Free (entity_t *e)
  94. {
  95. epair_t *ep, *next;
  96. while (e->brushes.onext != &e->brushes)
  97. Brush_Free (e->brushes.onext);
  98. if (e->next)
  99. {
  100. e->next->prev = e->prev;
  101. e->prev->next = e->next;
  102. }
  103. for (ep = e->epairs ; ep ; ep=next)
  104. {
  105. next = ep->next;
  106. free (ep);
  107. }
  108. free (e);
  109. }
  110. /*
  111. =================
  112. ParseEpair
  113. =================
  114. */
  115. epair_t *ParseEpair (void)
  116. {
  117. epair_t *e;
  118. e = qmalloc (sizeof(*e));
  119. e->key = qmalloc(strlen(token)+1);
  120. strcpy (e->key, token);
  121. GetToken (false);
  122. e->value = qmalloc(strlen(token)+1);
  123. strcpy (e->value, token);
  124. return e;
  125. }
  126. /*
  127. ================
  128. Entity_Parse
  129. If onlypairs is set, the classname info will not
  130. be looked up, and the entity will not be added
  131. to the global list. Used for parsing the project.
  132. ================
  133. */
  134. entity_t *Entity_Parse (qboolean onlypairs)
  135. {
  136. entity_t *ent;
  137. eclass_t *e;
  138. brush_t *b;
  139. vec3_t mins, maxs;
  140. epair_t *ep;
  141. qboolean has_brushes;
  142. if (!GetToken (true))
  143. return NULL;
  144. if (strcmp (token, "{") )
  145. Error ("ParseEntity: { not found");
  146. ent = qmalloc (sizeof(*ent));
  147. ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
  148. do
  149. {
  150. if (!GetToken (true))
  151. Error ("ParseEntity: EOF without closing brace");
  152. if (!strcmp (token, "}") )
  153. break;
  154. if (!strcmp (token, "{") )
  155. {
  156. b = Brush_Parse ();
  157. b->owner = ent;
  158. // add to the end of the entity chain
  159. b->onext = &ent->brushes;
  160. b->oprev = ent->brushes.oprev;
  161. ent->brushes.oprev->onext = b;
  162. ent->brushes.oprev = b;
  163. }
  164. else
  165. {
  166. ep = ParseEpair ();
  167. ep->next = ent->epairs;
  168. ent->epairs = ep;
  169. }
  170. } while (1);
  171. if (onlypairs)
  172. return ent;
  173. if (ent->brushes.onext == &ent->brushes)
  174. has_brushes = false;
  175. else
  176. has_brushes = true;
  177. GetVectorForKey (ent, "origin", ent->origin);
  178. e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
  179. ent->eclass = e;
  180. if (e->fixedsize)
  181. { // fixed size entity
  182. if (ent->brushes.onext != &ent->brushes)
  183. {
  184. printf ("Warning: Fixed size entity with brushes\n");
  185. #if 0
  186. while (ent->brushes.onext != &ent->brushes)
  187. { // FIXME: this will free the entity and crash!
  188. Brush_Free (b);
  189. }
  190. #endif
  191. ent->brushes.next = ent->brushes.prev = &ent->brushes;
  192. }
  193. // create a custom brush
  194. VectorAdd (e->mins, ent->origin, mins);
  195. VectorAdd (e->maxs, ent->origin, maxs);
  196. b = Brush_Create (mins, maxs, &e->texdef);
  197. b->owner = ent;
  198. b->onext = ent->brushes.onext;
  199. b->oprev = &ent->brushes;
  200. ent->brushes.onext->oprev = b;
  201. ent->brushes.onext = b;
  202. }
  203. else
  204. { // brush entity
  205. if (ent->brushes.next == &ent->brushes)
  206. printf ("Warning: Brush entity with no brushes\n");
  207. }
  208. // add all the brushes to the main list
  209. for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
  210. {
  211. b->next = active_brushes.next;
  212. active_brushes.next->prev = b;
  213. b->prev = &active_brushes;
  214. active_brushes.next = b;
  215. }
  216. return ent;
  217. }
  218. /*
  219. ============
  220. Entity_Write
  221. ============
  222. */
  223. void Entity_Write (entity_t *e, FILE *f, qboolean use_region)
  224. {
  225. epair_t *ep;
  226. brush_t *b;
  227. vec3_t origin;
  228. char text[128];
  229. int count;
  230. // if none of the entities brushes are in the region,
  231. // don't write the entity at all
  232. if (use_region)
  233. {
  234. // in region mode, save the camera position as playerstart
  235. if ( !strcmp(ValueForKey (e, "classname"), "info_player_start") )
  236. {
  237. fprintf (f, "{\n");
  238. fprintf (f, "\"classname\" \"info_player_start\"\n");
  239. fprintf (f, "\"origin\" \"%i %i %i\"\n", (int)camera.origin[0],
  240. (int)camera.origin[1], (int)camera.origin[2]);
  241. fprintf (f, "\"angle\" \"%i\"\n", (int)camera.angles[YAW]);
  242. fprintf (f, "}\n");
  243. return;
  244. }
  245. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  246. if (!Map_IsBrushFiltered(b))
  247. break; // got one
  248. if (b == &e->brushes)
  249. return; // nothing visible
  250. }
  251. // if fixedsize, calculate a new origin based on the current
  252. // brush position
  253. if (e->eclass->fixedsize)
  254. {
  255. VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
  256. sprintf (text, "%i %i %i", (int)origin[0],
  257. (int)origin[1], (int)origin[2]);
  258. SetKeyValue (e, "origin", text);
  259. }
  260. fprintf (f, "{\n");
  261. for (ep = e->epairs ; ep ; ep=ep->next)
  262. fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
  263. if (!e->eclass->fixedsize)
  264. {
  265. count = 0;
  266. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  267. {
  268. if (!use_region || !Map_IsBrushFiltered (b))
  269. {
  270. fprintf (f, "// brush %i\n", count);
  271. count++;
  272. Brush_Write (b, f);
  273. }
  274. }
  275. }
  276. fprintf (f, "}\n");
  277. }
  278. /*
  279. ============
  280. Entity_Create
  281. Creates a new entity out of the selected_brushes list.
  282. If the entity class is fixed size, the brushes are only
  283. used to find a midpoint. Otherwise, the brushes have
  284. their ownershi[ transfered to the new entity.
  285. ============
  286. */
  287. entity_t *Entity_Create (eclass_t *c)
  288. {
  289. entity_t *e;
  290. brush_t *b;
  291. vec3_t mins, maxs;
  292. int i;
  293. // check to make sure the brushes are ok
  294. for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  295. if (b->owner != world_entity)
  296. {
  297. Sys_Printf ("Entity NOT created, brushes not all from world\n");
  298. Sys_Beep ();
  299. return NULL;
  300. }
  301. // create it
  302. e = qmalloc(sizeof(*e));
  303. e->brushes.onext = e->brushes.oprev = &e->brushes;
  304. e->eclass = c;
  305. SetKeyValue (e, "classname", c->name);
  306. // add the entity to the entity list
  307. e->next = entities.next;
  308. entities.next = e;
  309. e->next->prev = e;
  310. e->prev = &entities;
  311. if (c->fixedsize)
  312. {
  313. //
  314. // just use the selection for positioning
  315. //
  316. b = selected_brushes.next;
  317. for (i=0 ; i<3 ; i++)
  318. e->origin[i] = b->mins[i] - c->mins[i];
  319. // create a custom brush
  320. VectorAdd (c->mins, e->origin, mins);
  321. VectorAdd (c->maxs, e->origin, maxs);
  322. b = Brush_Create (mins, maxs, &c->texdef);
  323. Entity_LinkBrush (e, b);
  324. // delete the current selection
  325. Select_Delete ();
  326. // select the new brush
  327. b->next = b->prev = &selected_brushes;
  328. selected_brushes.next = selected_brushes.prev = b;
  329. Brush_Build( b );
  330. }
  331. else
  332. {
  333. //
  334. // change the selected brushes over to the new entity
  335. //
  336. for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  337. {
  338. Entity_UnlinkBrush (b);
  339. Entity_LinkBrush (e, b);
  340. Brush_Build( b ); // so the key brush gets a name
  341. }
  342. }
  343. Sys_UpdateWindows (W_ALL);
  344. return e;
  345. }
  346. /*
  347. ===========
  348. Entity_LinkBrush
  349. ===========
  350. */
  351. void Entity_LinkBrush (entity_t *e, brush_t *b)
  352. {
  353. if (b->oprev || b->onext)
  354. Error ("Entity_LinkBrush: Allready linked");
  355. b->owner = e;
  356. b->onext = e->brushes.onext;
  357. b->oprev = &e->brushes;
  358. e->brushes.onext->oprev = b;
  359. e->brushes.onext = b;
  360. }
  361. /*
  362. ===========
  363. Entity_UnlinkBrush
  364. ===========
  365. */
  366. void Entity_UnlinkBrush (brush_t *b)
  367. {
  368. if (!b->owner || !b->onext || !b->oprev)
  369. Error ("Entity_UnlinkBrush: Not currently linked");
  370. b->onext->oprev = b->oprev;
  371. b->oprev->onext = b->onext;
  372. b->onext = b->oprev = NULL;
  373. b->owner = NULL;
  374. }
  375. /*
  376. ===========
  377. Entity_Clone
  378. ===========
  379. */
  380. entity_t *Entity_Clone (entity_t *e)
  381. {
  382. entity_t *n;
  383. epair_t *ep, *np;
  384. n = qmalloc(sizeof(*n));
  385. n->brushes.onext = n->brushes.oprev = &n->brushes;
  386. n->eclass = e->eclass;
  387. // add the entity to the entity list
  388. n->next = entities.next;
  389. entities.next = n;
  390. n->next->prev = n;
  391. n->prev = &entities;
  392. for (ep = e->epairs ; ep ; ep=ep->next)
  393. {
  394. np = qmalloc(sizeof(*np));
  395. np->key = copystring(ep->key);
  396. np->value = copystring(ep->value);
  397. np->next = n->epairs;
  398. n->epairs = np;
  399. }
  400. return n;
  401. }
  402. int GetUniqueTargetId(int iHint)
  403. {
  404. int iMin, iMax, i;
  405. BOOL fFound;
  406. entity_t *pe;
  407. fFound = FALSE;
  408. pe = entities.next;
  409. iMin = 0;
  410. iMax = 0;
  411. for (; pe != NULL && pe != &entities ; pe = pe->next)
  412. {
  413. i = IntForKey(pe, "target");
  414. if (i)
  415. {
  416. iMin = min(i, iMin);
  417. iMax = max(i, iMax);
  418. if (i == iHint)
  419. fFound = TRUE;
  420. }
  421. }
  422. if (fFound)
  423. return iMax + 1;
  424. else
  425. return iHint;
  426. }
  427. entity_t *FindEntity(char *pszKey, char *pszValue)
  428. {
  429. entity_t *pe;
  430. pe = entities.next;
  431. for (; pe != NULL && pe != &entities ; pe = pe->next)
  432. {
  433. if (!strcmp(ValueForKey(pe, pszKey), pszValue))
  434. return pe;
  435. }
  436. return NULL;
  437. }
  438. entity_t *FindEntityInt(char *pszKey, int iValue)
  439. {
  440. entity_t *pe;
  441. pe = entities.next;
  442. for (; pe != NULL && pe != &entities ; pe = pe->next)
  443. {
  444. if (IntForKey(pe, pszKey) == iValue)
  445. return pe;
  446. }
  447. return NULL;
  448. }