MAP.CPP 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  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. // map.c
  19. #include "stdafx.h"
  20. #include "qe3.h"
  21. #include "PrefsDlg.h"
  22. qboolean modified; // for quit confirmation (0 = clean, 1 = unsaved,
  23. // 2 = autosaved, but not regular saved)
  24. char currentmap[1024];
  25. brush_t active_brushes; // brushes currently being displayed
  26. brush_t selected_brushes; // highlighted
  27. face_t *selected_face;
  28. brush_t *selected_face_brush;
  29. brush_t filtered_brushes; // brushes that have been filtered or regioned
  30. entity_t entities; // head/tail of doubly linked list
  31. entity_t *world_entity = NULL; // "classname" "worldspawn" !
  32. void AddRegionBrushes (void);
  33. void RemoveRegionBrushes (void);
  34. void DupLists()
  35. {
  36. DWORD dw = GetTickCount();
  37. }
  38. /*
  39. =============================================================
  40. Cross map selection saving
  41. this could fuck up if you have only part of a complex entity selected...
  42. =============================================================
  43. */
  44. brush_t between_brushes;
  45. entity_t between_entities;
  46. bool g_bRestoreBetween = false;
  47. void Map_SaveBetween (void)
  48. {
  49. if (g_pParentWnd->ActiveXY())
  50. {
  51. g_bRestoreBetween = true;
  52. g_pParentWnd->ActiveXY()->Copy();
  53. }
  54. return;
  55. #if 0
  56. brush_t *b;
  57. entity_t *e, *e2;
  58. between_brushes.next = selected_brushes.next;
  59. between_brushes.prev = selected_brushes.prev;
  60. between_brushes.next->prev = &between_brushes;
  61. between_brushes.prev->next = &between_brushes;
  62. between_entities.next = between_entities.prev = &between_entities;
  63. selected_brushes.next = selected_brushes.prev = &selected_brushes;
  64. for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
  65. {
  66. e = b->owner;
  67. if (e == world_entity)
  68. b->owner = NULL;
  69. else
  70. {
  71. for (e2=between_entities.next ; e2 != &between_entities ; e2=e2->next)
  72. if (e2 == e)
  73. goto next; // allready got the entity
  74. // move the entity over
  75. e->prev->next = e->next;
  76. e->next->prev = e->prev;
  77. e->next = between_entities.next;
  78. e->prev = &between_entities;
  79. e->next->prev = e;
  80. e->prev->next = e;
  81. }
  82. next: ;
  83. }
  84. #endif
  85. }
  86. void Map_RestoreBetween (void)
  87. {
  88. if (g_pParentWnd->ActiveXY() && g_bRestoreBetween)
  89. g_pParentWnd->ActiveXY()->Paste();
  90. return;
  91. #if 0
  92. entity_t *head, *tail;
  93. brush_t *b;
  94. if (!between_brushes.next)
  95. return;
  96. for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
  97. {
  98. if (!b->owner)
  99. {
  100. b->owner = world_entity;
  101. b->onext = world_entity->brushes.onext;
  102. b->oprev = &world_entity->brushes;
  103. b->onext->oprev = b;
  104. b->oprev->onext = b;
  105. }
  106. }
  107. selected_brushes.next = between_brushes.next;
  108. selected_brushes.prev = between_brushes.prev;
  109. selected_brushes.next->prev = &selected_brushes;
  110. selected_brushes.prev->next = &selected_brushes;
  111. head = between_entities.next;
  112. tail = between_entities.prev;
  113. if (head != tail)
  114. {
  115. entities.prev->next = head;
  116. head->prev = entities.prev;
  117. tail->next = &entities;
  118. entities.prev = tail;
  119. }
  120. between_brushes.next = NULL;
  121. between_entities.next = NULL;
  122. #endif
  123. }
  124. //============================================================================
  125. bool CheckForTinyBrush(brush_t* b, int n, float fSize)
  126. {
  127. bool bTiny = false;
  128. for (int i=0 ; i<3 ; i++)
  129. {
  130. if (b->maxs[i] - b->mins[i] < fSize)
  131. bTiny = true;
  132. }
  133. if (bTiny)
  134. Sys_Printf("Possible problem brush (too small) #%i ", n);
  135. return bTiny;
  136. }
  137. void Map_BuildBrushData(void)
  138. {
  139. brush_t *b, *next;
  140. if (active_brushes.next == NULL)
  141. return;
  142. Sys_BeginWait (); // this could take a while
  143. int n = 0;
  144. for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
  145. {
  146. next = b->next;
  147. Brush_Build( b, true, false, false );
  148. if (!b->brush_faces || (g_PrefsDlg.m_bCleanTiny && CheckForTinyBrush(b, n++, g_PrefsDlg.m_fTinySize)))
  149. {
  150. Brush_Free (b);
  151. Sys_Printf ("Removed degenerate brush\n");
  152. }
  153. }
  154. Sys_EndWait();
  155. }
  156. entity_t *Map_FindClass (char *cname)
  157. {
  158. entity_t *ent;
  159. for (ent = entities.next ; ent != &entities ; ent=ent->next)
  160. {
  161. if (!strcmp(cname, ValueForKey (ent, "classname")))
  162. return ent;
  163. }
  164. return NULL;
  165. }
  166. /*
  167. ================
  168. Map_Free
  169. ================
  170. */
  171. void Map_Free (void)
  172. {
  173. g_bRestoreBetween = false;
  174. if (selected_brushes.next &&
  175. (selected_brushes.next != &selected_brushes) )
  176. {
  177. if (MessageBox(g_qeglobals.d_hwndMain, "Copy selection?", "", MB_YESNO) == IDYES)
  178. Map_SaveBetween ();
  179. }
  180. Texture_ClearInuse ();
  181. Pointfile_Clear ();
  182. strcpy (currentmap, "unnamed.map");
  183. Sys_SetTitle (currentmap);
  184. g_qeglobals.d_num_entities = 0;
  185. g_qeglobals.d_numterrapoints = 0;
  186. if (!active_brushes.next)
  187. { // first map
  188. active_brushes.prev = active_brushes.next = &active_brushes;
  189. selected_brushes.prev = selected_brushes.next = &selected_brushes;
  190. filtered_brushes.prev = filtered_brushes.next = &filtered_brushes;
  191. entities.prev = entities.next = &entities;
  192. }
  193. else
  194. {
  195. while (active_brushes.next != &active_brushes)
  196. Brush_Free (active_brushes.next);
  197. while (selected_brushes.next != &selected_brushes)
  198. Brush_Free (selected_brushes.next);
  199. while (filtered_brushes.next != &filtered_brushes)
  200. Brush_Free (filtered_brushes.next);
  201. while (entities.next != &entities)
  202. Entity_Free (entities.next);
  203. }
  204. if (world_entity)
  205. Entity_Free(world_entity);
  206. world_entity = NULL;
  207. }
  208. entity_t *AngledEntity()
  209. {
  210. entity_t *ent = Map_FindClass ("info_player_start");
  211. if (!ent)
  212. {
  213. ent = Map_FindClass ("info_player_deathmatch");
  214. }
  215. if (!ent)
  216. {
  217. ent = Map_FindClass ("info_player_deathmatch");
  218. }
  219. if (!ent)
  220. {
  221. ent = Map_FindClass ("team_CTF_redplayer");
  222. }
  223. if (!ent)
  224. {
  225. ent = Map_FindClass ("team_CTF_blueplayer");
  226. }
  227. if (!ent)
  228. {
  229. ent = Map_FindClass ("team_CTF_redspawn");
  230. }
  231. if (!ent)
  232. {
  233. ent = Map_FindClass ("team_CTF_bluespawn");
  234. }
  235. return ent;
  236. }
  237. /*
  238. ================
  239. Map_LoadFile
  240. ================
  241. */
  242. void Map_LoadFile (char *filename)
  243. {
  244. char *buf;
  245. entity_t *ent;
  246. char temp[1024];
  247. Sys_BeginWait ();
  248. Select_Deselect();
  249. //SetInspectorMode(W_CONSOLE);
  250. QE_ConvertDOSToUnixName( temp, filename );
  251. Sys_Printf ("Map_LoadFile: %s\n", temp );
  252. Map_Free ();
  253. //++timo FIXME: maybe even easier to have Group_Init called from Map_Free?
  254. Group_Init();
  255. g_qeglobals.d_parsed_brushes = 0;
  256. strcpy (currentmap, filename);
  257. if (LoadFile (filename, (void **)&buf) != -1)
  258. {
  259. StartTokenParsing (buf);
  260. g_qeglobals.d_num_entities = 0;
  261. // Timo
  262. // will be used in Entity_Parse to detect if a conversion between brush formats is needed
  263. g_qeglobals.bNeedConvert = false;
  264. g_qeglobals.bOldBrushes = false;
  265. g_qeglobals.bPrimitBrushes = false;
  266. while (1)
  267. {
  268. ent = Entity_Parse (false, &active_brushes);
  269. if (!ent)
  270. break;
  271. if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
  272. {
  273. if (world_entity)
  274. Sys_Printf ("WARNING: multiple worldspawn\n");
  275. world_entity = ent;
  276. }
  277. else if (!strcmp(ValueForKey (ent, "classname"), "group_info"))
  278. {
  279. // it's a group thing!
  280. Group_Add(ent);
  281. Entity_Free(ent);
  282. }
  283. else
  284. {
  285. // add the entity to the end of the entity list
  286. ent->next = &entities;
  287. ent->prev = entities.prev;
  288. entities.prev->next = ent;
  289. entities.prev = ent;
  290. g_qeglobals.d_num_entities++;
  291. }
  292. }
  293. }
  294. free (buf);
  295. if (!world_entity)
  296. {
  297. Sys_Printf ("No worldspawn in map.\n");
  298. Map_New ();
  299. return;
  300. }
  301. Sys_Printf ("--- LoadMapFile ---\n");
  302. Sys_Printf ("%s\n", temp );
  303. Sys_Printf ("%5i brushes\n", g_qeglobals.d_parsed_brushes );
  304. Sys_Printf ("%5i entities\n", g_qeglobals.d_num_entities);
  305. Map_RestoreBetween ();
  306. Sys_Printf ("Map_BuildAllDisplayLists\n");
  307. Map_BuildBrushData();
  308. // reset the "need conversion" flag
  309. // conversion to the good format done in Map_BuildBrushData
  310. g_qeglobals.bNeedConvert=false;
  311. //
  312. // move the view to a start position
  313. //
  314. ent = AngledEntity();
  315. g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
  316. if (ent)
  317. {
  318. GetVectorForKey (ent, "origin", g_pParentWnd->GetCamera()->Camera().origin);
  319. GetVectorForKey (ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin());
  320. g_pParentWnd->GetCamera()->Camera().angles[YAW] = FloatForKey (ent, "angle");
  321. }
  322. else
  323. {
  324. g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
  325. VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
  326. VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
  327. }
  328. Map_RegionOff ();
  329. modified = false;
  330. Sys_SetTitle (temp);
  331. Texture_ShowInuse ();
  332. Sys_EndWait();
  333. Sys_UpdateWindows (W_ALL);
  334. }
  335. /*
  336. ===========
  337. Map_SaveFile
  338. ===========
  339. */
  340. void Map_SaveFile (char *filename, qboolean use_region )
  341. {
  342. entity_t *e, *next;
  343. FILE *f;
  344. char temp[1024];
  345. int count;
  346. if (filename == NULL || strlen(filename) == 0)
  347. {
  348. CFileDialog dlgSave(FALSE, "map", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Map Files (*.map)|*.map||", AfxGetMainWnd());
  349. if (dlgSave.DoModal() == IDOK)
  350. filename = strdup(dlgSave.m_ofn.lpstrFile);
  351. else
  352. return;
  353. }
  354. Pointfile_Clear ();
  355. QE_ConvertDOSToUnixName( temp, filename );
  356. if (!use_region)
  357. {
  358. char backup[1024];
  359. // rename current to .bak
  360. strcpy (backup, filename);
  361. StripExtension (backup);
  362. strcat (backup, ".bak");
  363. _unlink (backup);
  364. rename (filename, backup);
  365. }
  366. Sys_Printf ("Map_SaveFile: %s\n", filename);
  367. f = fopen(filename, "w");
  368. if (!f)
  369. {
  370. Sys_Printf ("ERROR!!!! Couldn't open %s\n", filename);
  371. return;
  372. }
  373. if (use_region)
  374. {
  375. AddRegionBrushes ();
  376. }
  377. // write world entity first
  378. Entity_Write (world_entity, f, use_region);
  379. // then write all other ents
  380. count = 1;
  381. for (e=entities.next ; e != &entities ; e=next)
  382. {
  383. next = e->next;
  384. if (e->brushes.onext == &e->brushes)
  385. {
  386. Entity_Free (e); // no brushes left, so remove it
  387. }
  388. else
  389. {
  390. fprintf (f, "// entity %i\n", count);
  391. count++;
  392. Entity_Write (e, f, use_region);
  393. }
  394. }
  395. // save the group info stuff
  396. Group_Save(f);
  397. fclose (f);
  398. if (use_region)
  399. RemoveRegionBrushes ();
  400. Sys_Printf ("Saved.\n");
  401. modified = false;
  402. if ( !strstr( temp, "autosave" ) )
  403. Sys_SetTitle (temp);
  404. if (!use_region)
  405. {
  406. time_t timer;
  407. FILE *f;
  408. time (&timer);
  409. MessageBeep (MB_ICONEXCLAMATION);
  410. f = fopen ("c:/tstamps.log", "a");
  411. if (f)
  412. {
  413. fprintf (f, "%s", filename);
  414. //fprintf (f, "%4i : %35s : %s", g_qeglobals.d_workcount, filename, ctime(&timer));
  415. fclose (f);
  416. g_qeglobals.d_workcount = 0;
  417. }
  418. fclose (f);
  419. Sys_Status ("Saved.\n", 0);
  420. }
  421. //Curve_WriteFile (filename); //.trinity
  422. //Patch_WriteFile (filename);
  423. }
  424. /*
  425. ===========
  426. Map_New
  427. ===========
  428. */
  429. void Map_New (void)
  430. {
  431. Sys_Printf ("Map_New\n");
  432. Map_Free ();
  433. Patch_Cleanup();
  434. world_entity = (entity_s*)qmalloc(sizeof(*world_entity));
  435. world_entity->brushes.onext =
  436. world_entity->brushes.oprev = &world_entity->brushes;
  437. SetKeyValue (world_entity, "classname", "worldspawn");
  438. world_entity->eclass = Eclass_ForName ("worldspawn", true);
  439. g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
  440. g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
  441. VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
  442. g_pParentWnd->GetCamera()->Camera().origin[2] = 48;
  443. VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
  444. Map_RestoreBetween ();
  445. Group_Init();
  446. Sys_UpdateWindows (W_ALL);
  447. modified = false;
  448. }
  449. /*
  450. ===========================================================
  451. REGION
  452. ===========================================================
  453. */
  454. qboolean region_active;
  455. vec3_t region_mins = {MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD};
  456. vec3_t region_maxs = {MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD};
  457. brush_t *region_sides[4];
  458. /*
  459. ===========
  460. AddRegionBrushes
  461. a regioned map will have temp walls put up at the region boundary
  462. ===========
  463. */
  464. void AddRegionBrushes (void)
  465. {
  466. vec3_t mins, maxs;
  467. int i;
  468. texdef_t td;
  469. if (!region_active)
  470. return;
  471. memset (&td, 0, sizeof(td));
  472. //strcpy (td.name, "REGION");
  473. td.SetName("REGION");
  474. mins[0] = region_mins[0] - 16;
  475. maxs[0] = region_mins[0] + 1;
  476. mins[1] = region_mins[1] - 16;
  477. maxs[1] = region_maxs[1] + 16;
  478. mins[2] = MIN_WORLD_COORD;
  479. maxs[2] = MAX_WORLD_COORD;
  480. region_sides[0] = Brush_Create (mins, maxs, &td);
  481. mins[0] = region_maxs[0] - 1;
  482. maxs[0] = region_maxs[0] + 16;
  483. region_sides[1] = Brush_Create (mins, maxs, &td);
  484. mins[0] = region_mins[0] - 16;
  485. maxs[0] = region_maxs[0] + 16;
  486. mins[1] = region_mins[1] - 16;
  487. maxs[1] = region_mins[1] + 1;
  488. region_sides[2] = Brush_Create (mins, maxs, &td);
  489. mins[1] = region_maxs[1] - 1;
  490. maxs[1] = region_maxs[1] + 16;
  491. region_sides[3] = Brush_Create (mins, maxs, &td);
  492. for (i=0 ; i<4 ; i++)
  493. {
  494. Brush_AddToList (region_sides[i], &selected_brushes);
  495. Entity_LinkBrush (world_entity, region_sides[i]);
  496. Brush_Build( region_sides[i] );
  497. }
  498. }
  499. void RemoveRegionBrushes (void)
  500. {
  501. int i;
  502. if (!region_active)
  503. return;
  504. for (i=0 ; i<4 ; i++)
  505. Brush_Free (region_sides[i]);
  506. }
  507. qboolean Map_IsBrushFiltered (brush_t *b)
  508. {
  509. int i;
  510. for (i=0 ; i<3 ; i++)
  511. {
  512. if (b->mins[i] > region_maxs[i])
  513. return true;
  514. if (b->maxs[i] < region_mins[i])
  515. return true;
  516. }
  517. return false;
  518. }
  519. /*
  520. ===========
  521. Map_RegionOff
  522. Other filtering options may still be on
  523. ===========
  524. */
  525. void Map_RegionOff (void)
  526. {
  527. brush_t *b, *next;
  528. int i;
  529. region_active = false;
  530. for (i=0 ; i<3 ; i++)
  531. {
  532. region_maxs[i] = MAX_WORLD_COORD;//4096;
  533. region_mins[i] = MIN_WORLD_COORD;//-4096;
  534. }
  535. for (b=filtered_brushes.next ; b != &filtered_brushes ; b=next)
  536. {
  537. next = b->next;
  538. if (Map_IsBrushFiltered (b))
  539. continue; // still filtered
  540. Brush_RemoveFromList (b);
  541. if (active_brushes.next == NULL || active_brushes.prev == NULL)
  542. {
  543. active_brushes.next = &active_brushes;
  544. active_brushes.prev = &active_brushes;
  545. }
  546. Brush_AddToList (b, &active_brushes);
  547. }
  548. Sys_UpdateWindows (W_ALL);
  549. }
  550. void Map_ApplyRegion (void)
  551. {
  552. brush_t *b, *next;
  553. region_active = true;
  554. for (b=active_brushes.next ; b != &active_brushes ; b=next)
  555. {
  556. next = b->next;
  557. if (!Map_IsBrushFiltered (b))
  558. continue; // still filtered
  559. Brush_RemoveFromList (b);
  560. Brush_AddToList (b, &filtered_brushes);
  561. }
  562. Sys_UpdateWindows (W_ALL);
  563. }
  564. /*
  565. ========================
  566. Map_RegionSelectedBrushes
  567. ========================
  568. */
  569. void Map_RegionSelectedBrushes (void)
  570. {
  571. Map_RegionOff ();
  572. if (selected_brushes.next == &selected_brushes) // nothing selected
  573. {
  574. Sys_Printf("Tried to region with no selection...\n");
  575. return;
  576. }
  577. region_active = true;
  578. Select_GetBounds (region_mins, region_maxs);
  579. // move the entire active_brushes list to filtered_brushes
  580. filtered_brushes.next = active_brushes.next;
  581. filtered_brushes.prev = active_brushes.prev;
  582. filtered_brushes.next->prev = &filtered_brushes;
  583. filtered_brushes.prev->next = &filtered_brushes;
  584. // move the entire selected_brushes list to active_brushes
  585. active_brushes.next = selected_brushes.next;
  586. active_brushes.prev = selected_brushes.prev;
  587. active_brushes.next->prev = &active_brushes;
  588. active_brushes.prev->next = &active_brushes;
  589. // clear selected_brushes
  590. selected_brushes.next = selected_brushes.prev = &selected_brushes;
  591. Sys_UpdateWindows (W_ALL);
  592. }
  593. /*
  594. ===========
  595. Map_RegionXY
  596. ===========
  597. */
  598. void Map_RegionXY (void)
  599. {
  600. Map_RegionOff ();
  601. region_mins[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] - 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
  602. region_maxs[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] + 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
  603. region_mins[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] - 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
  604. region_maxs[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] + 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
  605. region_mins[2] = -MIN_WORLD_COORD;
  606. region_maxs[2] = MAX_WORLD_COORD;
  607. Map_ApplyRegion ();
  608. }
  609. /*
  610. ===========
  611. Map_RegionTallBrush
  612. ===========
  613. */
  614. void Map_RegionTallBrush (void)
  615. {
  616. brush_t *b;
  617. if (!QE_SingleBrush ())
  618. return;
  619. b = selected_brushes.next;
  620. Map_RegionOff ();
  621. VectorCopy (b->mins, region_mins);
  622. VectorCopy (b->maxs, region_maxs);
  623. region_mins[2] = MIN_WORLD_COORD;
  624. region_maxs[2] = MAX_WORLD_COORD;
  625. Select_Delete ();
  626. Map_ApplyRegion ();
  627. }
  628. /*
  629. ===========
  630. Map_RegionBrush
  631. ===========
  632. */
  633. void Map_RegionBrush (void)
  634. {
  635. brush_t *b;
  636. if (!QE_SingleBrush ())
  637. return;
  638. b = selected_brushes.next;
  639. Map_RegionOff ();
  640. VectorCopy (b->mins, region_mins);
  641. VectorCopy (b->maxs, region_maxs);
  642. Select_Delete ();
  643. Map_ApplyRegion ();
  644. }
  645. void UniqueTargetName(CString& rStr)
  646. {
  647. // make a unique target value
  648. int maxtarg = 0;
  649. for (entity_t* e=entities.next ; e != &entities ; e=e->next)
  650. {
  651. char* tn = ValueForKey (e, "targetname");
  652. if (tn && tn[0])
  653. {
  654. int targetnum = atoi(tn+1);
  655. if (targetnum > maxtarg)
  656. maxtarg = targetnum;
  657. }
  658. else
  659. {
  660. tn = ValueForKey (e, "target");
  661. if (tn && tn[0])
  662. {
  663. int targetnum = atoi(tn+1);
  664. if (targetnum > maxtarg)
  665. maxtarg = targetnum;
  666. }
  667. }
  668. }
  669. rStr.Format("t%i", maxtarg+1);
  670. }
  671. //
  672. //================
  673. //Map_ImportFile
  674. // Timo 09/01/99 : called by CXYWnd::Paste & Map_ImportFile
  675. // if Map_ImportFile ( prefab ), the buffer may contain brushes in old format ( conversion needed )
  676. //================
  677. //
  678. void Map_ImportBuffer (char* buf)
  679. {
  680. entity_t* ent;
  681. brush_t* b = NULL;
  682. CPtrArray ptrs;
  683. Select_Deselect();
  684. Undo_Start("import buffer");
  685. g_qeglobals.d_parsed_brushes = 0;
  686. if (buf)
  687. {
  688. CMapStringToString mapStr;
  689. StartTokenParsing (buf);
  690. g_qeglobals.d_num_entities = 0;
  691. // Timo
  692. // will be used in Entity_Parse to detect if a conversion between brush formats is needed
  693. g_qeglobals.bNeedConvert = false;
  694. g_qeglobals.bOldBrushes = false;
  695. g_qeglobals.bPrimitBrushes = false;
  696. while (1)
  697. {
  698. // use the selected brushes list as it's handy
  699. //ent = Entity_Parse (false, &selected_brushes);
  700. ent = Entity_Parse (false, &active_brushes);
  701. if (!ent)
  702. break;
  703. //end entity for undo
  704. Undo_EndEntity(ent);
  705. //end brushes for undo
  706. for(b = ent->brushes.onext; b && b != &ent->brushes; b = b->onext)
  707. {
  708. Undo_EndBrush(b);
  709. }
  710. if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
  711. {
  712. // world brushes need to be added to the current world entity
  713. b=ent->brushes.onext;
  714. while (b && b != &ent->brushes)
  715. {
  716. brush_t* bNext = b->onext;
  717. Entity_UnlinkBrush(b);
  718. Entity_LinkBrush(world_entity, b);
  719. ptrs.Add(b);
  720. b = bNext;
  721. }
  722. }
  723. else
  724. {
  725. // the following bit remaps conflicting target/targetname key/value pairs
  726. CString str = ValueForKey(ent, "target");
  727. CString strKey;
  728. CString strTarget("");
  729. if (str.GetLength() > 0)
  730. {
  731. if (FindEntity("target", str.GetBuffer(0)))
  732. {
  733. if (!mapStr.Lookup(str, strKey))
  734. {
  735. UniqueTargetName(strKey);
  736. mapStr.SetAt(str, strKey);
  737. }
  738. strTarget = strKey;
  739. SetKeyValue(ent, "target", strTarget.GetBuffer(0));
  740. }
  741. }
  742. str = ValueForKey(ent, "targetname");
  743. if (str.GetLength() > 0)
  744. {
  745. if (FindEntity("targetname", str.GetBuffer(0)))
  746. {
  747. if (!mapStr.Lookup(str, strKey))
  748. {
  749. UniqueTargetName(strKey);
  750. mapStr.SetAt(str, strKey);
  751. }
  752. SetKeyValue(ent, "targetname", strKey.GetBuffer(0));
  753. }
  754. }
  755. //if (strTarget.GetLength() > 0)
  756. // SetKeyValue(ent, "target", strTarget.GetBuffer(0));
  757. // add the entity to the end of the entity list
  758. ent->next = &entities;
  759. ent->prev = entities.prev;
  760. entities.prev->next = ent;
  761. entities.prev = ent;
  762. g_qeglobals.d_num_entities++;
  763. for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
  764. {
  765. ptrs.Add(b);
  766. }
  767. }
  768. }
  769. }
  770. //::ShowWindow(g_qeglobals.d_hwndEntity, FALSE);
  771. //::LockWindowUpdate(g_qeglobals.d_hwndEntity);
  772. g_bScreenUpdates = false;
  773. for (int i = 0; i < ptrs.GetSize(); i++)
  774. {
  775. Brush_Build(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
  776. Select_Brush(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
  777. }
  778. //::LockWindowUpdate(NULL);
  779. g_bScreenUpdates = true;
  780. ptrs.RemoveAll();
  781. // reset the "need conversion" flag
  782. // conversion to the good format done in Map_BuildBrushData
  783. g_qeglobals.bNeedConvert=false;
  784. Sys_UpdateWindows (W_ALL);
  785. //Sys_MarkMapModified();
  786. modified = true;
  787. Undo_End();
  788. }
  789. //
  790. //================
  791. //Map_ImportFile
  792. //================
  793. //
  794. void Map_ImportFile (char *filename)
  795. {
  796. char* buf;
  797. char temp[1024];
  798. Sys_BeginWait ();
  799. QE_ConvertDOSToUnixName( temp, filename );
  800. if (LoadFile (filename, (void **)&buf) != -1)
  801. {
  802. Map_ImportBuffer(buf);
  803. free(buf);
  804. Map_BuildBrushData();
  805. }
  806. Sys_UpdateWindows (W_ALL);
  807. modified = true;
  808. Sys_EndWait();
  809. }
  810. //
  811. //===========
  812. //Map_SaveSelected
  813. //===========
  814. //
  815. // Saves selected world brushes and whole entities with partial/full selections
  816. //
  817. void Map_SaveSelected(char* pFilename)
  818. {
  819. entity_t *e, *next;
  820. FILE *f;
  821. char temp[1024];
  822. int count;
  823. QE_ConvertDOSToUnixName(temp, pFilename);
  824. f = fopen(pFilename, "w");
  825. if (!f)
  826. {
  827. Sys_Printf ("ERROR!!!! Couldn't open %s\n", pFilename);
  828. return;
  829. }
  830. // write world entity first
  831. Entity_WriteSelected(world_entity, f);
  832. // then write all other ents
  833. count = 1;
  834. for (e=entities.next ; e != &entities ; e=next)
  835. {
  836. fprintf (f, "// entity %i\n", count);
  837. count++;
  838. Entity_WriteSelected(e, f);
  839. next = e->next;
  840. }
  841. fclose (f);
  842. }
  843. //
  844. //===========
  845. //Map_SaveSelected
  846. //===========
  847. //
  848. // Saves selected world brushes and whole entities with partial/full selections
  849. //
  850. void Map_SaveSelected(CMemFile* pMemFile, CMemFile* pPatchFile)
  851. {
  852. entity_t *e, *next;
  853. int count;
  854. CString strTemp;
  855. // write world entity first
  856. Entity_WriteSelected(world_entity, pMemFile);
  857. // then write all other ents
  858. count = 1;
  859. for (e=entities.next ; e != &entities ; e=next)
  860. {
  861. MemFile_fprintf(pMemFile, "// entity %i\n", count);
  862. count++;
  863. Entity_WriteSelected(e, pMemFile);
  864. next = e->next;
  865. }
  866. //if (pPatchFile)
  867. // Patch_WriteFile(pPatchFile);
  868. }
  869. void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...)
  870. {
  871. char Buffer[4096];
  872. va_list args;
  873. va_start (args,pText);
  874. vsprintf(Buffer, pText, args);
  875. pMemFile->Write(Buffer, strlen(Buffer));
  876. }