home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / MAP.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  22.7 KB  |  1,043 lines

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