ENTITY.CPP 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena 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 III Arena 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 Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "stdafx.h"
  19. #include "qe3.h"
  20. //
  21. int g_entityId = 1;
  22. char *ValueForKey ( epair_t *&e, const char *key)
  23. {
  24. epair_t *ep;
  25. for (ep=e ; ep ; ep=ep->next)
  26. {
  27. if (!strcmp (ep->key, key) )
  28. {
  29. return ep->value;
  30. }
  31. }
  32. return "";
  33. }
  34. char *ValueForKey (entity_t *ent, const char *key)
  35. {
  36. return ValueForKey(ent->epairs, key);
  37. }
  38. void TrackMD3Angles(entity_t *e, const char *key, const char *value)
  39. {
  40. if (strcmpi(key, "angle") != 0)
  41. {
  42. return;
  43. }
  44. if (e->eclass->fixedsize && e->eclass->nShowFlags & ECLASS_MISCMODEL)
  45. {
  46. float a = FloatForKey (e, "angle");
  47. float b = atof(value);
  48. if (a != b)
  49. {
  50. vec3_t vAngle;
  51. vAngle[0] = vAngle[1] = 0;
  52. vAngle[2] = -a;
  53. Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
  54. vAngle[2] = b;
  55. Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
  56. }
  57. }
  58. }
  59. void SetKeyValue (epair_t *&e, const char *key, const char *value)
  60. {
  61. epair_t *ep;
  62. for (ep=e ; ep ; ep=ep->next)
  63. {
  64. if (!strcmp (ep->key, key) )
  65. {
  66. free (ep->value);
  67. ep->value = (char*)qmalloc(strlen(value)+1);
  68. strcpy (ep->value, value);
  69. return;
  70. }
  71. }
  72. ep = (epair_t*)qmalloc (sizeof(*ep));
  73. ep->next = e;
  74. e = ep;
  75. ep->key = (char*)qmalloc(strlen(key)+1);
  76. strcpy (ep->key, key);
  77. ep->value = (char*)qmalloc(strlen(value)+1);
  78. strcpy (ep->value, value);
  79. }
  80. void SetKeyValue (entity_t *ent, const char *key, const char *value)
  81. {
  82. if (ent == NULL)
  83. return;
  84. if (!key || !key[0])
  85. return;
  86. TrackMD3Angles(ent, key, value);
  87. SetKeyValue(ent->epairs, key, value);
  88. }
  89. void DeleteKey (epair_t *&e, const char *key)
  90. {
  91. epair_t **ep, *next;
  92. ep = &e;
  93. while (*ep)
  94. {
  95. next = *ep;
  96. if ( !strcmp (next->key, key) )
  97. {
  98. *ep = next->next;
  99. free(next->key);
  100. free(next->value);
  101. free(next);
  102. return;
  103. }
  104. ep = &next->next;
  105. }
  106. }
  107. void DeleteKey (entity_t *ent, const char *key)
  108. {
  109. DeleteKey(ent->epairs, key);
  110. }
  111. float FloatForKey (entity_t *ent, const char *key)
  112. {
  113. char *k;
  114. k = ValueForKey (ent, key);
  115. return atof(k);
  116. }
  117. int IntForKey (entity_t *ent, const char *key)
  118. {
  119. char *k;
  120. k = ValueForKey (ent, key);
  121. return atoi(k);
  122. }
  123. void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
  124. {
  125. char *k;
  126. k = ValueForKey (ent, key);
  127. sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
  128. }
  129. /*
  130. ===============
  131. Entity_FreeEpairs
  132. Frees the entity epairs.
  133. ===============
  134. */
  135. void Entity_FreeEpairs(entity_t *e)
  136. {
  137. epair_t *ep, *next;
  138. for (ep = e->epairs; ep; ep = next)
  139. {
  140. next = ep->next;
  141. free (ep->key);
  142. free (ep->value);
  143. free (ep);
  144. }
  145. e->epairs = NULL;
  146. }
  147. /*
  148. ===========
  149. Entity_AddToList
  150. ===========
  151. */
  152. void Entity_AddToList(entity_t *e, entity_t *list)
  153. {
  154. if (e->next || e->prev)
  155. Error ("Entity_AddToList: allready linked");
  156. e->next = list->next;
  157. list->next->prev = e;
  158. list->next = e;
  159. e->prev = list;
  160. }
  161. /*
  162. ===========
  163. Entity_RemoveFromList
  164. ===========
  165. */
  166. void Entity_RemoveFromList (entity_t *e)
  167. {
  168. if (!e->next || !e->prev)
  169. Error ("Entity_RemoveFromList: not linked");
  170. e->next->prev = e->prev;
  171. e->prev->next = e->next;
  172. e->next = e->prev = NULL;
  173. }
  174. /*
  175. ===============
  176. Entity_Free
  177. Frees the entity and any brushes is has.
  178. The entity is removed from the global entities list.
  179. ===============
  180. */
  181. void Entity_Free (entity_t *e)
  182. {
  183. // do we have a plugin entity ?
  184. if ( e->pPlugEnt )
  185. {
  186. e->pPlugEnt->DecRef();
  187. e->pPlugEnt = NULL;
  188. }
  189. while (e->brushes.onext != &e->brushes)
  190. Brush_Free (e->brushes.onext);
  191. if (e->next)
  192. {
  193. e->next->prev = e->prev;
  194. e->prev->next = e->next;
  195. }
  196. Entity_FreeEpairs(e);
  197. free (e);
  198. }
  199. /*
  200. =================
  201. Entity_MemorySize
  202. =================
  203. */
  204. int Entity_MemorySize(entity_t *e)
  205. {
  206. epair_t *ep;
  207. int size = 0;
  208. for (ep = e->epairs; ep; ep = ep->next)
  209. {
  210. size += _msize(ep->key);
  211. size += _msize(ep->value);
  212. size += _msize(ep);
  213. }
  214. size += _msize(e);
  215. return size;
  216. }
  217. /*
  218. =================
  219. ParseEpair
  220. =================
  221. */
  222. epair_t *ParseEpair (void)
  223. {
  224. epair_t *e;
  225. e = (epair_t*)qmalloc (sizeof(*e));
  226. e->key = (char*)qmalloc(strlen(token)+1);
  227. strcpy (e->key, token);
  228. GetToken (false);
  229. e->value = (char*)qmalloc(strlen(token)+1);
  230. strcpy (e->value, token);
  231. return e;
  232. }
  233. /*
  234. ================
  235. Entity_Parse
  236. If onlypairs is set, the classname info will not
  237. be looked up, and the entity will not be added
  238. to the global list. Used for parsing the project.
  239. ================
  240. */
  241. entity_t *Entity_Parse (qboolean onlypairs, brush_t* pList)
  242. {
  243. entity_t *ent;
  244. eclass_t *e;
  245. brush_t *b;
  246. vec3_t mins, maxs;
  247. epair_t *ep;
  248. qboolean has_brushes;
  249. if (!GetToken (true))
  250. return NULL;
  251. if (strcmp (token, "{") )
  252. Error ("ParseEntity: { not found");
  253. ent = (entity_t*)qmalloc (sizeof(*ent));
  254. ent->entityId = g_entityId++;
  255. ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
  256. int n = 0;
  257. do
  258. {
  259. if (!GetToken (true))
  260. {
  261. Warning ("ParseEntity: EOF without closing brace");
  262. return NULL;
  263. }
  264. if (!strcmp (token, "}") )
  265. break;
  266. if (!strcmp (token, "{") )
  267. {
  268. b = Brush_Parse ();
  269. if (b != NULL)
  270. {
  271. b->owner = ent;
  272. // add to the end of the entity chain
  273. b->onext = &ent->brushes;
  274. b->oprev = ent->brushes.oprev;
  275. ent->brushes.oprev->onext = b;
  276. ent->brushes.oprev = b;
  277. }
  278. else
  279. {
  280. break;
  281. }
  282. }
  283. else
  284. {
  285. ep = ParseEpair ();
  286. ep->next = ent->epairs;
  287. ent->epairs = ep;
  288. }
  289. } while (1);
  290. // group info entity?
  291. if (strcmp(ValueForKey (ent, "classname"), "group_info") == 0)
  292. return ent;
  293. if (onlypairs)
  294. return ent;
  295. if (ent->brushes.onext == &ent->brushes)
  296. has_brushes = false;
  297. else
  298. has_brushes = true;
  299. GetVectorForKey (ent, "origin", ent->origin);
  300. e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
  301. ent->eclass = e;
  302. if ( e->nShowFlags & ECLASS_PLUGINENTITY )
  303. {
  304. // locate the plugin
  305. CPlugIn * pPlug = g_pParentWnd->GetPlugInMgr().PluginForModule( e->hPlug );
  306. if (pPlug)
  307. {
  308. // create the plugin entity
  309. IPluginEntity* pPlugEnt = pPlug->CreatePluginEntity( ent );
  310. if (pPlugEnt)
  311. {
  312. ent->pPlugEnt = pPlugEnt;
  313. // the brush is used to select and move
  314. pPlugEnt->GetBounds( mins, maxs );
  315. }
  316. else
  317. {
  318. // give it a default bounding box
  319. SetKeyValue (ent, "model", "");
  320. mins[0] = -4; mins[1] = -4; mins[2] = -4;
  321. maxs[0] = 4; maxs[1] = 4; maxs[2] = 4;
  322. VectorAdd( mins, ent->origin, mins );
  323. VectorAdd( maxs, ent->origin, maxs );
  324. }
  325. b = Brush_Create (mins, maxs, &ent->eclass->texdef);
  326. Entity_LinkBrush (ent, b);
  327. Brush_Build( b, true );
  328. }
  329. else
  330. Sys_Printf("WARNING: plugin lookup failed for plugin entities\n");
  331. }
  332. else if (e->fixedsize)
  333. { // fixed size entity
  334. if (ent->brushes.onext != &ent->brushes)
  335. {
  336. printf ("Warning: Fixed size entity with brushes\n");
  337. #if 0
  338. while (ent->brushes.onext != &ent->brushes)
  339. { // FIXME: this will free the entity and crash!
  340. Brush_Free (b);
  341. }
  342. #endif
  343. ent->brushes.next = ent->brushes.prev = &ent->brushes;
  344. }
  345. // create a custom brush
  346. VectorAdd (e->mins, ent->origin, mins);
  347. VectorAdd (e->maxs, ent->origin, maxs);
  348. float a = 0;
  349. if (e->nShowFlags & ECLASS_MISCMODEL)
  350. {
  351. char* p = ValueForKey(ent, "model");
  352. if (p != NULL && strlen(p) > 0)
  353. {
  354. vec3_t vMin, vMax;
  355. a = FloatForKey (ent, "angle");
  356. if (GetCachedModel(ent, p, vMin, vMax))
  357. {
  358. // create a custom brush
  359. VectorAdd (ent->md3Class->mins, ent->origin, mins);
  360. VectorAdd (ent->md3Class->maxs, ent->origin, maxs);
  361. }
  362. }
  363. }
  364. b = Brush_Create (mins, maxs, &e->texdef);
  365. if (a)
  366. {
  367. vec3_t vAngle;
  368. vAngle[0] = vAngle[1] = 0;
  369. vAngle[2] = a;
  370. Brush_Rotate(b, vAngle, ent->origin, false);
  371. }
  372. b->owner = ent;
  373. b->onext = ent->brushes.onext;
  374. b->oprev = &ent->brushes;
  375. ent->brushes.onext->oprev = b;
  376. ent->brushes.onext = b;
  377. }
  378. else
  379. { // brush entity
  380. if (ent->brushes.next == &ent->brushes)
  381. printf ("Warning: Brush entity with no brushes\n");
  382. }
  383. // add all the brushes to the main list
  384. if (pList)
  385. {
  386. for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
  387. {
  388. b->next = pList->next;
  389. pList->next->prev = b;
  390. b->prev = pList;
  391. pList->next = b;
  392. }
  393. }
  394. return ent;
  395. }
  396. void VectorMidpoint(vec3_t va, vec3_t vb, vec3_t& out)
  397. {
  398. for (int i = 0; i < 3; i++)
  399. out[i] = va[i] + ((vb[i] - va[i]) / 2);
  400. }
  401. /*
  402. ============
  403. Entity_Write
  404. ============
  405. */
  406. void Entity_Write (entity_t *e, FILE *f, qboolean use_region)
  407. {
  408. epair_t *ep;
  409. brush_t *b;
  410. vec3_t origin;
  411. char text[128];
  412. int count;
  413. // if none of the entities brushes are in the region,
  414. // don't write the entity at all
  415. if (use_region)
  416. {
  417. // in region mode, save the camera position as playerstart
  418. if ( !strcmp(ValueForKey (e, "classname"), "info_player_start") )
  419. {
  420. fprintf (f, "{\n");
  421. fprintf (f, "\"classname\" \"info_player_start\"\n");
  422. fprintf (f, "\"origin\" \"%i %i %i\"\n", (int)g_pParentWnd->GetCamera()->Camera().origin[0],
  423. (int)g_pParentWnd->GetCamera()->Camera().origin[1], (int)g_pParentWnd->GetCamera()->Camera().origin[2]);
  424. fprintf (f, "\"angle\" \"%i\"\n", (int)g_pParentWnd->GetCamera()->Camera().angles[YAW]);
  425. fprintf (f, "}\n");
  426. return;
  427. }
  428. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  429. if (!Map_IsBrushFiltered(b))
  430. break; // got one
  431. if (b == &e->brushes)
  432. return; // nothing visible
  433. }
  434. if ( e->eclass->nShowFlags & ECLASS_PLUGINENTITY )
  435. {
  436. // NOTE: the whole brush placement / origin stuff is a mess
  437. VectorCopy( e->origin, origin );
  438. sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  439. SetKeyValue (e, "origin", text);
  440. }
  441. // if fixedsize, calculate a new origin based on the current
  442. // brush position
  443. else if (e->eclass->fixedsize)
  444. {
  445. if (e->eclass->nShowFlags & ECLASS_MISCMODEL && e->md3Class != NULL)
  446. {
  447. VectorCopy(e->origin, origin);
  448. //VectorSubtract (e->brushes.onext->mins, e->md3Class->mins, origin);
  449. }
  450. else
  451. {
  452. VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
  453. }
  454. sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  455. SetKeyValue (e, "origin", text);
  456. }
  457. fprintf (f, "{\n");
  458. for (ep = e->epairs ; ep ; ep=ep->next)
  459. fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
  460. if (!e->eclass->fixedsize)
  461. {
  462. count = 0;
  463. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  464. {
  465. if (!use_region || !Map_IsBrushFiltered (b))
  466. {
  467. fprintf (f, "// brush %i\n", count);
  468. count++;
  469. Brush_Write (b, f);
  470. }
  471. }
  472. }
  473. fprintf (f, "}\n");
  474. }
  475. qboolean IsBrushSelected(brush_t* bSel)
  476. {
  477. for (brush_t* b = selected_brushes.next ;b != NULL && b != &selected_brushes; b = b->next)
  478. {
  479. if (b == bSel)
  480. return true;
  481. }
  482. return false;
  483. }
  484. //
  485. //============
  486. //Entity_WriteSelected
  487. //============
  488. //
  489. void Entity_WriteSelected(entity_t *e, FILE *f)
  490. {
  491. epair_t *ep;
  492. brush_t *b;
  493. vec3_t origin;
  494. char text[128];
  495. int count;
  496. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  497. if (IsBrushSelected(b))
  498. break; // got one
  499. if (b == &e->brushes)
  500. return; // nothing selected
  501. // if fixedsize, calculate a new origin based on the current
  502. // brush position
  503. if (e->eclass->fixedsize)
  504. {
  505. if (e->eclass->nShowFlags & ECLASS_MISCMODEL && e->md3Class != NULL)
  506. {
  507. VectorCopy(e->origin, origin);
  508. //VectorSubtract (e->brushes.onext->mins, e->md3Class->mins, origin);
  509. }
  510. else
  511. {
  512. VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
  513. }
  514. sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  515. SetKeyValue (e, "origin", text);
  516. }
  517. fprintf (f, "{\n");
  518. for (ep = e->epairs ; ep ; ep=ep->next)
  519. fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
  520. if (!e->eclass->fixedsize)
  521. {
  522. count = 0;
  523. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  524. {
  525. if (IsBrushSelected(b))
  526. {
  527. fprintf (f, "// brush %i\n", count);
  528. count++;
  529. Brush_Write (b, f);
  530. }
  531. }
  532. }
  533. fprintf (f, "}\n");
  534. }
  535. //
  536. //============
  537. //Entity_WriteSelected to a CMemFile
  538. //============
  539. //
  540. void Entity_WriteSelected(entity_t *e, CMemFile* pMemFile)
  541. {
  542. epair_t *ep;
  543. brush_t *b;
  544. vec3_t origin;
  545. char text[128];
  546. int count;
  547. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  548. if (IsBrushSelected(b))
  549. break; // got one
  550. if (b == &e->brushes)
  551. return; // nothing selected
  552. // if fixedsize, calculate a new origin based on the current
  553. // brush position
  554. if (e->eclass->fixedsize)
  555. {
  556. if (e->eclass->nShowFlags & ECLASS_MISCMODEL && e->md3Class != NULL)
  557. {
  558. //VectorSubtract (e->brushes.onext->mins, e->md3Class->mins, origin);
  559. VectorCopy(e->origin, origin);
  560. }
  561. else
  562. {
  563. VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
  564. }
  565. sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  566. SetKeyValue (e, "origin", text);
  567. }
  568. MemFile_fprintf(pMemFile, "{\n");
  569. for (ep = e->epairs ; ep ; ep=ep->next)
  570. MemFile_fprintf(pMemFile, "\"%s\" \"%s\"\n", ep->key, ep->value);
  571. if (!e->eclass->fixedsize)
  572. {
  573. count = 0;
  574. for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  575. {
  576. if (IsBrushSelected(b))
  577. {
  578. MemFile_fprintf(pMemFile, "// brush %i\n", count);
  579. count++;
  580. Brush_Write (b, pMemFile);
  581. }
  582. }
  583. }
  584. MemFile_fprintf(pMemFile, "}\n");
  585. }
  586. /*
  587. ============
  588. Entity_Create
  589. Creates a new entity out of the selected_brushes list.
  590. If the entity class is fixed size, the brushes are only
  591. used to find a midpoint. Otherwise, the brushes have
  592. their ownership transfered to the new entity.
  593. ============
  594. */
  595. entity_t *Entity_Create (eclass_t *c)
  596. {
  597. entity_t *e;
  598. brush_t *b;
  599. vec3_t mins, maxs;
  600. int i;
  601. // check to make sure the brushes are ok
  602. for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  603. {
  604. if (b->owner != world_entity)
  605. {
  606. Sys_Printf ("Entity NOT created, brushes not all from world\n");
  607. Sys_Beep ();
  608. return NULL;
  609. }
  610. }
  611. // create it
  612. e = (entity_t*)qmalloc(sizeof(*e));
  613. e->entityId = g_entityId++;
  614. e->brushes.onext = e->brushes.oprev = &e->brushes;
  615. e->eclass = c;
  616. SetKeyValue (e, "classname", c->name);
  617. // add the entity to the entity list
  618. Entity_AddToList(e, &entities);
  619. // plugin entity ?
  620. if (c->nShowFlags & ECLASS_PLUGINENTITY)
  621. {
  622. // locate the plugin
  623. CPlugIn * pPlug = g_pParentWnd->GetPlugInMgr().PluginForModule( c->hPlug );
  624. if (pPlug)
  625. {
  626. //
  627. // just use the selection for positioning
  628. //
  629. b = selected_brushes.next;
  630. for (i=0 ; i<3 ; i++)
  631. e->origin[i] = b->mins[i] - c->mins[i];
  632. // create the plugin entity
  633. IPluginEntity* pPlugEnt = pPlug->CreatePluginEntity( e );
  634. if (pPlugEnt)
  635. {
  636. e->pPlugEnt = pPlugEnt;
  637. // the brush is used to select and move
  638. pPlugEnt->GetBounds( mins, maxs );
  639. b = Brush_Create (mins, maxs, &c->texdef);
  640. Entity_LinkBrush (e, b);
  641. // delete the current selection
  642. Select_Delete ();
  643. // select the new brush
  644. b->next = b->prev = &selected_brushes;
  645. selected_brushes.next = selected_brushes.prev = b;
  646. Brush_Build( b );
  647. }
  648. }
  649. else
  650. {
  651. Sys_Printf( "WARNING: plugin lookup failed while creating a plugin entitiy in Entity_Create\n" );
  652. return NULL;
  653. }
  654. }
  655. else if (c->fixedsize)
  656. {
  657. //
  658. // just use the selection for positioning
  659. //
  660. b = selected_brushes.next;
  661. for (i=0 ; i<3 ; i++)
  662. e->origin[i] = b->mins[i] - c->mins[i];
  663. // create a custom brush
  664. VectorAdd (c->mins, e->origin, mins);
  665. VectorAdd (c->maxs, e->origin, maxs);
  666. b = Brush_Create (mins, maxs, &c->texdef);
  667. Entity_LinkBrush (e, b);
  668. // delete the current selection
  669. Select_Delete ();
  670. // select the new brush
  671. b->next = b->prev = &selected_brushes;
  672. selected_brushes.next = selected_brushes.prev = b;
  673. Brush_Build( b );
  674. }
  675. else
  676. {
  677. //
  678. // change the selected brushes over to the new entity
  679. //
  680. for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  681. {
  682. Entity_UnlinkBrush (b);
  683. Entity_LinkBrush (e, b);
  684. Brush_Build( b ); // so the key brush gets a name
  685. }
  686. }
  687. Sys_UpdateWindows (W_ALL);
  688. return e;
  689. }
  690. /*
  691. ===========
  692. Entity_LinkBrush
  693. ===========
  694. */
  695. void Entity_LinkBrush (entity_t *e, brush_t *b)
  696. {
  697. if (b->oprev || b->onext)
  698. Error ("Entity_LinkBrush: Allready linked");
  699. b->owner = e;
  700. b->onext = e->brushes.onext;
  701. b->oprev = &e->brushes;
  702. e->brushes.onext->oprev = b;
  703. e->brushes.onext = b;
  704. }
  705. /*
  706. ===========
  707. Entity_UnlinkBrush
  708. ===========
  709. */
  710. void Entity_UnlinkBrush (brush_t *b)
  711. {
  712. //if (!b->owner || !b->onext || !b->oprev)
  713. if (!b->onext || !b->oprev)
  714. Error ("Entity_UnlinkBrush: Not currently linked");
  715. b->onext->oprev = b->oprev;
  716. b->oprev->onext = b->onext;
  717. b->onext = b->oprev = NULL;
  718. b->owner = NULL;
  719. }
  720. /*
  721. ===========
  722. Entity_Clone
  723. ===========
  724. */
  725. entity_t *Entity_Clone (entity_t *e)
  726. {
  727. entity_t *n;
  728. epair_t *ep, *np;
  729. n = (entity_t*)qmalloc(sizeof(*n));
  730. n->entityId = g_entityId++;
  731. n->brushes.onext = n->brushes.oprev = &n->brushes;
  732. n->eclass = e->eclass;
  733. // add the entity to the entity list
  734. Entity_AddToList(n, &entities);
  735. for (ep = e->epairs ; ep ; ep=ep->next)
  736. {
  737. np = (epair_t*)qmalloc(sizeof(*np));
  738. np->key = copystring(ep->key);
  739. np->value = copystring(ep->value);
  740. np->next = n->epairs;
  741. n->epairs = np;
  742. }
  743. return n;
  744. }
  745. int GetUniqueTargetId(int iHint)
  746. {
  747. int iMin, iMax, i;
  748. BOOL fFound;
  749. entity_t *pe;
  750. fFound = FALSE;
  751. pe = entities.next;
  752. iMin = 0;
  753. iMax = 0;
  754. for (; pe != NULL && pe != &entities ; pe = pe->next)
  755. {
  756. i = IntForKey(pe, "target");
  757. if (i)
  758. {
  759. iMin = min(i, iMin);
  760. iMax = max(i, iMax);
  761. if (i == iHint)
  762. fFound = TRUE;
  763. }
  764. }
  765. if (fFound)
  766. return iMax + 1;
  767. else
  768. return iHint;
  769. }
  770. entity_t *FindEntity(char *pszKey, char *pszValue)
  771. {
  772. entity_t *pe;
  773. pe = entities.next;
  774. for (; pe != NULL && pe != &entities ; pe = pe->next)
  775. {
  776. if (!strcmp(ValueForKey(pe, pszKey), pszValue))
  777. return pe;
  778. }
  779. return NULL;
  780. }
  781. entity_t *FindEntityInt(char *pszKey, int iValue)
  782. {
  783. entity_t *pe;
  784. pe = entities.next;
  785. for (; pe != NULL && pe != &entities ; pe = pe->next)
  786. {
  787. if (IntForKey(pe, pszKey) == iValue)
  788. return pe;
  789. }
  790. return NULL;
  791. }