Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

MAP.CPP

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // map.c
00023 
00024 #include "stdafx.h"
00025 #include "qe3.h"
00026 #include "PrefsDlg.h"
00027 
00028 qboolean    modified;       // for quit confirmation (0 = clean, 1 = unsaved,
00029                             // 2 = autosaved, but not regular saved) 
00030 
00031 char        currentmap[1024];
00032 
00033 
00034 brush_t active_brushes;     // brushes currently being displayed
00035 brush_t selected_brushes;   // highlighted
00036 
00037 face_t  *selected_face;
00038 brush_t *selected_face_brush;
00039 
00040 brush_t filtered_brushes;   // brushes that have been filtered or regioned
00041 
00042 entity_t    entities;       // head/tail of doubly linked list
00043 
00044 entity_t    *world_entity = NULL; // "classname" "worldspawn" !
00045 
00046 void AddRegionBrushes (void);
00047 void RemoveRegionBrushes (void);
00048 
00049 
00050 void DupLists()
00051 {
00052   DWORD dw = GetTickCount();
00053 
00054 }
00055 
00056 /*
00057 =============================================================
00058 
00059   Cross map selection saving
00060 
00061   this could fuck up if you have only part of a complex entity selected...
00062 =============================================================
00063 */
00064 
00065 brush_t     between_brushes;
00066 entity_t    between_entities;
00067 
00068 bool g_bRestoreBetween = false;
00069 
00070 void Map_SaveBetween (void)
00071 {
00072 
00073     if (g_pParentWnd->ActiveXY())
00074   {
00075     g_bRestoreBetween = true;
00076     g_pParentWnd->ActiveXY()->Copy();
00077   }
00078   return;
00079 
00080 #if 0
00081 
00082     brush_t     *b;
00083     entity_t    *e, *e2;
00084 
00085     between_brushes.next = selected_brushes.next;
00086     between_brushes.prev = selected_brushes.prev;
00087     between_brushes.next->prev = &between_brushes;
00088     between_brushes.prev->next = &between_brushes;
00089 
00090     between_entities.next = between_entities.prev = &between_entities;
00091     selected_brushes.next = selected_brushes.prev = &selected_brushes;
00092 
00093     for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
00094     {
00095         e = b->owner;
00096         if (e == world_entity)
00097             b->owner = NULL;
00098         else
00099         {
00100             for (e2=between_entities.next ; e2 != &between_entities ; e2=e2->next)
00101                 if (e2 == e)
00102                     goto next;  // allready got the entity
00103             // move the entity over
00104             e->prev->next = e->next;
00105             e->next->prev = e->prev;
00106             e->next = between_entities.next;
00107             e->prev = &between_entities;
00108             e->next->prev = e;
00109             e->prev->next = e;
00110         }
00111 next: ;
00112     }
00113 #endif
00114 }
00115 
00116 void Map_RestoreBetween (void)
00117 {
00118     if (g_pParentWnd->ActiveXY() && g_bRestoreBetween)
00119     g_pParentWnd->ActiveXY()->Paste();
00120   return;
00121 
00122 #if 0  
00123   entity_t  *head, *tail;
00124     brush_t     *b;
00125 
00126     if (!between_brushes.next)
00127         return;
00128 
00129     for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
00130     {
00131         if (!b->owner)
00132         {
00133             b->owner = world_entity;
00134             b->onext = world_entity->brushes.onext;
00135             b->oprev = &world_entity->brushes;
00136             b->onext->oprev = b;
00137             b->oprev->onext = b;
00138         }
00139     }
00140 
00141     selected_brushes.next = between_brushes.next;
00142     selected_brushes.prev = between_brushes.prev;
00143     selected_brushes.next->prev = &selected_brushes;
00144     selected_brushes.prev->next = &selected_brushes;
00145 
00146     head = between_entities.next;
00147     tail = between_entities.prev;
00148 
00149     if (head != tail)
00150     {
00151         entities.prev->next = head;
00152         head->prev = entities.prev;
00153         tail->next = &entities;
00154         entities.prev = tail;
00155     }
00156 
00157     between_brushes.next = NULL;
00158     between_entities.next = NULL;
00159 #endif
00160 }
00161 
00162 //============================================================================
00163 
00164 bool CheckForTinyBrush(brush_t* b, int n, float fSize)
00165 {
00166   bool bTiny = false;
00167     for (int i=0 ; i<3 ; i++)
00168     {
00169     if (b->maxs[i] - b->mins[i] < fSize)
00170       bTiny = true;
00171   }
00172   if (bTiny)
00173     Sys_Printf("Possible problem brush (too small) #%i ", n);
00174   return bTiny;
00175 }
00176 
00177 void Map_BuildBrushData(void)
00178 {
00179     brush_t *b, *next;
00180 
00181     if (active_brushes.next == NULL)
00182         return;
00183 
00184     Sys_BeginWait ();   // this could take a while
00185 
00186   int n = 0;
00187     for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
00188     {
00189         next = b->next;
00190         Brush_Build( b, true, false, false );
00191         if (!b->brush_faces || (g_PrefsDlg.m_bCleanTiny && CheckForTinyBrush(b, n++, g_PrefsDlg.m_fTinySize)))
00192         {
00193             Brush_Free (b);
00194             Sys_Printf ("Removed degenerate brush\n");
00195         }
00196     }
00197     Sys_EndWait();
00198 }
00199 
00200 entity_t *Map_FindClass (char *cname)
00201 {
00202     entity_t    *ent;
00203 
00204     for (ent = entities.next ; ent != &entities ; ent=ent->next)
00205     {
00206         if (!strcmp(cname, ValueForKey (ent, "classname")))
00207             return ent;
00208     }
00209     return NULL;
00210 }
00211 
00212 /*
00213 ================
00214 Map_Free
00215 ================
00216 */
00217 void Map_Free (void)
00218 {
00219   g_bRestoreBetween = false;
00220     if (selected_brushes.next &&
00221         (selected_brushes.next != &selected_brushes) )
00222     {
00223     if (MessageBox(g_qeglobals.d_hwndMain, "Copy selection?", "", MB_YESNO) == IDYES)
00224           Map_SaveBetween ();
00225     }
00226 
00227     Texture_ClearInuse ();
00228     Pointfile_Clear ();
00229     strcpy (currentmap, "unnamed.map");
00230     Sys_SetTitle (currentmap);
00231     g_qeglobals.d_num_entities = 0;
00232     g_qeglobals.d_numterrapoints = 0;
00233 
00234     if (!active_brushes.next)
00235     {   // first map
00236         active_brushes.prev = active_brushes.next = &active_brushes;
00237         selected_brushes.prev = selected_brushes.next = &selected_brushes;
00238         filtered_brushes.prev = filtered_brushes.next = &filtered_brushes;
00239 
00240         entities.prev = entities.next = &entities;
00241     }
00242     else
00243     {
00244         while (active_brushes.next != &active_brushes)
00245             Brush_Free (active_brushes.next);
00246         while (selected_brushes.next != &selected_brushes)
00247             Brush_Free (selected_brushes.next);
00248         while (filtered_brushes.next != &filtered_brushes)
00249             Brush_Free (filtered_brushes.next);
00250 
00251         while (entities.next != &entities)
00252             Entity_Free (entities.next);
00253     }
00254 
00255   if (world_entity)
00256     Entity_Free(world_entity);
00257     world_entity = NULL;
00258 }
00259 
00260 entity_t *AngledEntity()
00261 {
00262   entity_t *ent = Map_FindClass ("info_player_start");
00263     if (!ent)
00264   {
00265         ent = Map_FindClass ("info_player_deathmatch");
00266   }
00267   if (!ent)
00268   {
00269         ent = Map_FindClass ("info_player_deathmatch");
00270   }
00271   if (!ent)
00272   {
00273     ent = Map_FindClass ("team_CTF_redplayer");
00274   }
00275   if (!ent)
00276   {
00277     ent = Map_FindClass ("team_CTF_blueplayer");
00278   }
00279   if (!ent)
00280   {
00281     ent = Map_FindClass ("team_CTF_redspawn");
00282   }
00283   if (!ent)
00284   {
00285     ent = Map_FindClass ("team_CTF_bluespawn");
00286   }
00287   return ent;
00288 }
00289 
00290 
00291 
00292 /*
00293 ================
00294 Map_LoadFile
00295 ================
00296 */
00297 void Map_LoadFile (char *filename)
00298 {
00299     char        *buf;
00300     entity_t    *ent;
00301     char         temp[1024];
00302 
00303     Sys_BeginWait ();
00304     Select_Deselect();
00305     //SetInspectorMode(W_CONSOLE);
00306 
00307     QE_ConvertDOSToUnixName( temp, filename );
00308     Sys_Printf ("Map_LoadFile: %s\n", temp );
00309 
00310     Map_Free ();
00311     //++timo FIXME: maybe even easier to have Group_Init called from Map_Free?
00312     Group_Init();
00313 
00314     g_qeglobals.d_parsed_brushes = 0;
00315     strcpy (currentmap, filename);
00316 
00317     if (LoadFile (filename, (void **)&buf) != -1)
00318     {
00319 
00320         StartTokenParsing (buf);
00321         g_qeglobals.d_num_entities = 0;
00322 
00323         // Timo
00324         // will be used in Entity_Parse to detect if a conversion between brush formats is needed
00325         g_qeglobals.bNeedConvert = false;
00326         g_qeglobals.bOldBrushes = false;
00327         g_qeglobals.bPrimitBrushes = false;
00328 
00329         while (1)
00330         {
00331             ent = Entity_Parse (false, &active_brushes);
00332             if (!ent)
00333                 break;
00334             if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
00335             {
00336                 if (world_entity)
00337                     Sys_Printf ("WARNING: multiple worldspawn\n");
00338                 world_entity = ent;
00339             }
00340             else if (!strcmp(ValueForKey (ent, "classname"), "group_info"))
00341       {
00342         // it's a group thing!
00343         Group_Add(ent);
00344         Entity_Free(ent);
00345       }
00346       else
00347             {
00348                 // add the entity to the end of the entity list
00349                 ent->next = &entities;
00350                 ent->prev = entities.prev;
00351                 entities.prev->next = ent;
00352                 entities.prev = ent;
00353                 g_qeglobals.d_num_entities++;
00354             }
00355         }
00356     }
00357 
00358   free (buf);
00359 
00360     if (!world_entity)
00361     {
00362         Sys_Printf ("No worldspawn in map.\n");
00363         Map_New ();
00364         return;
00365     }
00366 
00367     Sys_Printf ("--- LoadMapFile ---\n");
00368     Sys_Printf ("%s\n", temp );
00369 
00370     Sys_Printf ("%5i brushes\n",  g_qeglobals.d_parsed_brushes );
00371     Sys_Printf ("%5i entities\n", g_qeglobals.d_num_entities);
00372 
00373     Map_RestoreBetween ();
00374 
00375     Sys_Printf ("Map_BuildAllDisplayLists\n");
00376     Map_BuildBrushData();
00377 
00378     // reset the "need conversion" flag
00379     // conversion to the good format done in Map_BuildBrushData
00380     g_qeglobals.bNeedConvert=false;
00381 
00382     //
00383     // move the view to a start position
00384     //
00385   ent = AngledEntity();
00386 
00387   g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
00388     if (ent)
00389     {
00390         GetVectorForKey (ent, "origin", g_pParentWnd->GetCamera()->Camera().origin);
00391         GetVectorForKey (ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin());
00392         g_pParentWnd->GetCamera()->Camera().angles[YAW] = FloatForKey (ent, "angle");
00393     }
00394     else
00395     {
00396         g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
00397         VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
00398         VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
00399     }
00400 
00401     Map_RegionOff ();
00402 
00403 
00404     modified = false;
00405     Sys_SetTitle (temp);
00406 
00407     Texture_ShowInuse ();
00408 
00409     Sys_EndWait();
00410     Sys_UpdateWindows (W_ALL);
00411 
00412 }
00413 
00414 /*
00415 ===========
00416 Map_SaveFile
00417 ===========
00418 */
00419 void Map_SaveFile (char *filename, qboolean use_region )
00420 {
00421     entity_t    *e, *next;
00422     FILE        *f;
00423     char         temp[1024];
00424     int         count;
00425 
00426   if (filename == NULL || strlen(filename) == 0)
00427   {
00428     CFileDialog dlgSave(FALSE, "map", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Map Files (*.map)|*.map||", AfxGetMainWnd());
00429     if (dlgSave.DoModal() == IDOK)
00430       filename = strdup(dlgSave.m_ofn.lpstrFile);
00431     else 
00432       return;
00433   }
00434 
00435     Pointfile_Clear ();
00436     QE_ConvertDOSToUnixName( temp, filename );
00437 
00438     if (!use_region)
00439     {
00440         char    backup[1024];
00441 
00442         // rename current to .bak
00443         strcpy (backup, filename);
00444         StripExtension (backup);
00445         strcat (backup, ".bak");
00446         _unlink (backup);
00447         rename (filename, backup);
00448     }
00449 
00450     Sys_Printf ("Map_SaveFile: %s\n", filename);
00451 
00452     f = fopen(filename, "w");
00453 
00454     if (!f)
00455     {
00456         Sys_Printf ("ERROR!!!! Couldn't open %s\n", filename);
00457         return;
00458     }
00459 
00460     if (use_region)
00461   {
00462         AddRegionBrushes ();
00463   }
00464 
00465     // write world entity first
00466     Entity_Write (world_entity, f, use_region);
00467 
00468     // then write all other ents
00469     count = 1;
00470     for (e=entities.next ; e != &entities ; e=next)
00471     {
00472         next = e->next;
00473         if (e->brushes.onext == &e->brushes)
00474     {
00475             Entity_Free (e);    // no brushes left, so remove it
00476     }
00477         else
00478     {
00479         fprintf (f, "// entity %i\n", count);
00480         count++;
00481             Entity_Write (e, f, use_region);
00482     }
00483     }
00484 
00485     // save the group info stuff
00486     Group_Save(f);
00487 
00488     fclose (f);
00489 
00490     if (use_region)
00491         RemoveRegionBrushes ();
00492 
00493     Sys_Printf ("Saved.\n");
00494     modified = false;
00495 
00496     if ( !strstr( temp, "autosave" ) )
00497         Sys_SetTitle (temp);
00498 
00499     if (!use_region)
00500     {
00501         time_t  timer;
00502         FILE    *f;
00503 
00504         time (&timer);
00505         MessageBeep (MB_ICONEXCLAMATION);
00506         f = fopen ("c:/tstamps.log", "a");
00507         if (f)
00508         {
00509             fprintf (f, "%s", filename);
00510             //fprintf (f, "%4i : %35s : %s", g_qeglobals.d_workcount, filename, ctime(&timer));
00511             fclose (f);
00512             g_qeglobals.d_workcount = 0;
00513         }
00514         fclose (f);
00515         Sys_Status ("Saved.\n", 0);
00516     }
00517     
00518   //Curve_WriteFile (filename);     //.trinity
00519   //Patch_WriteFile (filename);
00520 }
00521 
00522 /*
00523 ===========
00524 Map_New
00525 ===========
00526 */
00527 void Map_New (void)
00528 {
00529     Sys_Printf ("Map_New\n");
00530     Map_Free ();
00531 
00532   Patch_Cleanup();
00533 
00534     world_entity = (entity_s*)qmalloc(sizeof(*world_entity));
00535     world_entity->brushes.onext = 
00536         world_entity->brushes.oprev = &world_entity->brushes;
00537     SetKeyValue (world_entity, "classname", "worldspawn");
00538     world_entity->eclass = Eclass_ForName ("worldspawn", true);
00539 
00540     g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
00541     g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
00542     VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
00543     g_pParentWnd->GetCamera()->Camera().origin[2] = 48;
00544     VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
00545 
00546     Map_RestoreBetween ();
00547 
00548   Group_Init();
00549 
00550     Sys_UpdateWindows (W_ALL);
00551     modified = false;
00552 }
00553 
00554 /*
00555 ===========================================================
00556 
00557   REGION
00558 
00559 ===========================================================
00560 */
00561 
00562 qboolean    region_active;
00563 vec3_t  region_mins = {MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD};
00564 vec3_t  region_maxs = {MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD};
00565 
00566 brush_t *region_sides[4];
00567 /*
00568 ===========
00569 AddRegionBrushes
00570 
00571 a regioned map will have temp walls put up at the region boundary
00572 ===========
00573 */
00574 void AddRegionBrushes (void)
00575 {
00576     vec3_t  mins, maxs;
00577     int     i;
00578     texdef_t    td;
00579 
00580     if (!region_active)
00581         return;
00582 
00583     memset (&td, 0, sizeof(td));
00584     //strcpy (td.name, "REGION");
00585     td.SetName("REGION");
00586 
00587     mins[0] = region_mins[0] - 16;
00588     maxs[0] = region_mins[0] + 1;
00589     mins[1] = region_mins[1] - 16;
00590     maxs[1] = region_maxs[1] + 16;
00591     mins[2] = MIN_WORLD_COORD;
00592     maxs[2] = MAX_WORLD_COORD;
00593     region_sides[0] = Brush_Create (mins, maxs, &td);
00594 
00595     mins[0] = region_maxs[0] - 1;
00596     maxs[0] = region_maxs[0] + 16;
00597     region_sides[1] = Brush_Create (mins, maxs, &td);
00598 
00599     mins[0] = region_mins[0] - 16;
00600     maxs[0] = region_maxs[0] + 16;
00601     mins[1] = region_mins[1] - 16;
00602     maxs[1] = region_mins[1] + 1;
00603     region_sides[2] = Brush_Create (mins, maxs, &td);
00604 
00605     mins[1] = region_maxs[1] - 1;
00606     maxs[1] = region_maxs[1] + 16;
00607     region_sides[3] = Brush_Create (mins, maxs, &td);
00608 
00609     for (i=0 ; i<4 ; i++)
00610     {
00611         Brush_AddToList (region_sides[i], &selected_brushes);
00612         Entity_LinkBrush (world_entity, region_sides[i]);
00613         Brush_Build( region_sides[i] );
00614     }
00615 }
00616 
00617 void RemoveRegionBrushes (void)
00618 {
00619     int     i;
00620 
00621     if (!region_active)
00622         return;
00623     for (i=0 ; i<4 ; i++)
00624         Brush_Free (region_sides[i]);
00625 }
00626 
00627 
00628 qboolean Map_IsBrushFiltered (brush_t *b)
00629 {
00630     int     i;
00631 
00632     for (i=0 ; i<3 ; i++)
00633     {
00634         if (b->mins[i] > region_maxs[i])
00635             return true;
00636         if (b->maxs[i] < region_mins[i])
00637             return true;
00638     }
00639     return false;
00640 }
00641 
00642 /*
00643 ===========
00644 Map_RegionOff
00645 
00646 Other filtering options may still be on
00647 ===========
00648 */
00649 void Map_RegionOff (void)
00650 {
00651     brush_t *b, *next;
00652     int         i;
00653 
00654     region_active = false;
00655     for (i=0 ; i<3 ; i++)
00656     {
00657         region_maxs[i] = MAX_WORLD_COORD;//4096;
00658         region_mins[i] = MIN_WORLD_COORD;//-4096;
00659     }
00660     
00661     for (b=filtered_brushes.next ; b != &filtered_brushes ; b=next)
00662     {
00663         next = b->next;
00664         if (Map_IsBrushFiltered (b))
00665             continue;       // still filtered
00666         Brush_RemoveFromList (b);
00667     if (active_brushes.next == NULL || active_brushes.prev == NULL)
00668     {
00669       active_brushes.next = &active_brushes;
00670       active_brushes.prev = &active_brushes;
00671     }
00672         Brush_AddToList (b, &active_brushes);
00673     }
00674 
00675     Sys_UpdateWindows (W_ALL);
00676 }
00677 
00678 void Map_ApplyRegion (void)
00679 {
00680     brush_t *b, *next;
00681 
00682     region_active = true;
00683     for (b=active_brushes.next ; b != &active_brushes ; b=next)
00684     {
00685         next = b->next;
00686         if (!Map_IsBrushFiltered (b))
00687             continue;       // still filtered
00688         Brush_RemoveFromList (b);
00689         Brush_AddToList (b, &filtered_brushes);
00690     }
00691 
00692     Sys_UpdateWindows (W_ALL);
00693 }
00694 
00695 
00696 /*
00697 ========================
00698 Map_RegionSelectedBrushes
00699 ========================
00700 */
00701 void Map_RegionSelectedBrushes (void)
00702 {
00703     Map_RegionOff ();
00704 
00705     if (selected_brushes.next == &selected_brushes)  // nothing selected
00706   {
00707     Sys_Printf("Tried to region with no selection...\n");
00708     return;
00709   }
00710     region_active = true;
00711     Select_GetBounds (region_mins, region_maxs);
00712 
00713     // move the entire active_brushes list to filtered_brushes
00714     filtered_brushes.next = active_brushes.next;
00715     filtered_brushes.prev = active_brushes.prev;
00716     filtered_brushes.next->prev = &filtered_brushes;
00717     filtered_brushes.prev->next = &filtered_brushes;
00718 
00719     // move the entire selected_brushes list to active_brushes
00720     active_brushes.next = selected_brushes.next;
00721     active_brushes.prev = selected_brushes.prev;
00722     active_brushes.next->prev = &active_brushes;
00723     active_brushes.prev->next = &active_brushes;
00724 
00725     // clear selected_brushes
00726     selected_brushes.next = selected_brushes.prev = &selected_brushes;
00727 
00728     Sys_UpdateWindows (W_ALL);
00729 }
00730 
00731 
00732 /*
00733 ===========
00734 Map_RegionXY
00735 ===========
00736 */
00737 void Map_RegionXY (void)
00738 {
00739     Map_RegionOff ();
00740 
00741     region_mins[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] - 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
00742     region_maxs[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] + 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
00743     region_mins[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] - 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
00744     region_maxs[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] + 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
00745     region_mins[2] = -MIN_WORLD_COORD;
00746     region_maxs[2] = MAX_WORLD_COORD;
00747     Map_ApplyRegion ();
00748 }
00749 
00750 /*
00751 ===========
00752 Map_RegionTallBrush
00753 ===========
00754 */
00755 void Map_RegionTallBrush (void)
00756 {
00757     brush_t *b;
00758 
00759     if (!QE_SingleBrush ())
00760         return;
00761 
00762     b = selected_brushes.next;
00763 
00764     Map_RegionOff ();
00765 
00766     VectorCopy (b->mins, region_mins);
00767     VectorCopy (b->maxs, region_maxs);
00768     region_mins[2] = MIN_WORLD_COORD;
00769     region_maxs[2] = MAX_WORLD_COORD;
00770 
00771 
00772     Select_Delete ();
00773     Map_ApplyRegion ();
00774 }
00775 /*
00776 ===========
00777 Map_RegionBrush
00778 ===========
00779 */
00780 void Map_RegionBrush (void)
00781 {
00782     brush_t *b;
00783 
00784     if (!QE_SingleBrush ())
00785         return;
00786 
00787     b = selected_brushes.next;
00788 
00789     Map_RegionOff ();
00790 
00791     VectorCopy (b->mins, region_mins);
00792     VectorCopy (b->maxs, region_maxs);
00793 
00794     Select_Delete ();
00795     Map_ApplyRegion ();
00796 }
00797 
00798 
00799 
00800 void UniqueTargetName(CString& rStr)
00801 {
00802     // make a unique target value
00803     int maxtarg = 0;
00804     for (entity_t* e=entities.next ; e != &entities ; e=e->next)
00805     {
00806         char* tn = ValueForKey (e, "targetname");
00807         if (tn && tn[0])
00808         {
00809             int targetnum = atoi(tn+1);
00810             if (targetnum > maxtarg)
00811                 maxtarg = targetnum;
00812         }
00813     else
00814     {
00815           tn = ValueForKey (e, "target");
00816           if (tn && tn[0])
00817           {
00818               int targetnum = atoi(tn+1);
00819               if (targetnum > maxtarg)
00820                   maxtarg = targetnum;
00821           }
00822     }
00823     }
00824   rStr.Format("t%i", maxtarg+1);
00825 }
00826 
00827 //
00828 //================
00829 //Map_ImportFile
00830 // Timo 09/01/99 : called by CXYWnd::Paste & Map_ImportFile
00831 // if Map_ImportFile ( prefab ), the buffer may contain brushes in old format ( conversion needed )
00832 //================
00833 //
00834 void Map_ImportBuffer (char* buf)
00835 {
00836     entity_t* ent;
00837     brush_t* b = NULL;
00838     CPtrArray ptrs;
00839 
00840     Select_Deselect();
00841 
00842     Undo_Start("import buffer");
00843 
00844     g_qeglobals.d_parsed_brushes = 0;
00845     if (buf)
00846     {
00847         CMapStringToString mapStr;
00848         StartTokenParsing (buf);
00849         g_qeglobals.d_num_entities = 0;
00850 
00851         // Timo
00852         // will be used in Entity_Parse to detect if a conversion between brush formats is needed
00853         g_qeglobals.bNeedConvert = false;
00854         g_qeglobals.bOldBrushes = false;
00855         g_qeglobals.bPrimitBrushes = false;
00856 
00857         while (1)
00858         {
00859 
00860             // use the selected brushes list as it's handy
00861             //ent = Entity_Parse (false, &selected_brushes);
00862             ent = Entity_Parse (false, &active_brushes);
00863             if (!ent)
00864                 break;
00865             //end entity for undo
00866             Undo_EndEntity(ent);
00867             //end brushes for undo
00868             for(b = ent->brushes.onext; b && b != &ent->brushes; b = b->onext)
00869             {
00870                 Undo_EndBrush(b);
00871             }
00872 
00873             if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
00874             {
00875                 // world brushes need to be added to the current world entity
00876 
00877                 b=ent->brushes.onext;
00878                 while (b && b != &ent->brushes)
00879                 {
00880                     brush_t* bNext = b->onext;
00881                     Entity_UnlinkBrush(b);
00882                     Entity_LinkBrush(world_entity, b);
00883                     ptrs.Add(b);
00884                     b = bNext;
00885                 }
00886             }
00887             else
00888             {
00889                 // the following bit remaps conflicting target/targetname key/value pairs
00890                 CString str = ValueForKey(ent, "target");
00891                 CString strKey;
00892                 CString strTarget("");
00893                 if (str.GetLength() > 0)
00894                 {
00895                     if (FindEntity("target", str.GetBuffer(0)))
00896                     {
00897                         if (!mapStr.Lookup(str, strKey))
00898                         {
00899                             UniqueTargetName(strKey);
00900                             mapStr.SetAt(str, strKey);
00901                         }
00902                         strTarget = strKey;
00903                         SetKeyValue(ent, "target", strTarget.GetBuffer(0));
00904                     }
00905                 }
00906                 str = ValueForKey(ent, "targetname");
00907                 if (str.GetLength() > 0)
00908                 {
00909                     if (FindEntity("targetname", str.GetBuffer(0)))
00910                     {
00911                         if (!mapStr.Lookup(str, strKey))
00912                         {
00913                             UniqueTargetName(strKey);
00914                             mapStr.SetAt(str, strKey);
00915                         }
00916                         SetKeyValue(ent, "targetname", strKey.GetBuffer(0));
00917                     }
00918                 }
00919                 //if (strTarget.GetLength() > 0)
00920                 //  SetKeyValue(ent, "target", strTarget.GetBuffer(0));
00921 
00922                 // add the entity to the end of the entity list
00923                 ent->next = &entities;
00924                 ent->prev = entities.prev;
00925                 entities.prev->next = ent;
00926                 entities.prev = ent;
00927                 g_qeglobals.d_num_entities++;
00928 
00929                 for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
00930                 {
00931                     ptrs.Add(b);
00932                 }
00933             }
00934         }
00935     }
00936 
00937     //::ShowWindow(g_qeglobals.d_hwndEntity, FALSE);
00938     //::LockWindowUpdate(g_qeglobals.d_hwndEntity);
00939     g_bScreenUpdates = false; 
00940     for (int i = 0; i < ptrs.GetSize(); i++)
00941     {
00942         Brush_Build(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
00943         Select_Brush(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
00944     }
00945     //::LockWindowUpdate(NULL);
00946     g_bScreenUpdates = true; 
00947 
00948     ptrs.RemoveAll();
00949 
00950     // reset the "need conversion" flag
00951     // conversion to the good format done in Map_BuildBrushData
00952     g_qeglobals.bNeedConvert=false;
00953 
00954     Sys_UpdateWindows (W_ALL);
00955   //Sys_MarkMapModified();
00956     modified = true;
00957 
00958     Undo_End();
00959 
00960 }
00961 
00962 
00963 //
00964 //================
00965 //Map_ImportFile
00966 //================
00967 //
00968 void Map_ImportFile (char *filename)
00969 {
00970   char* buf;
00971     char temp[1024];
00972     Sys_BeginWait ();
00973     QE_ConvertDOSToUnixName( temp, filename );
00974   if (LoadFile (filename, (void **)&buf) != -1)
00975   {
00976     Map_ImportBuffer(buf);
00977     free(buf);
00978     Map_BuildBrushData();
00979   }
00980     Sys_UpdateWindows (W_ALL);
00981     modified = true;
00982     Sys_EndWait();
00983 }
00984 
00985 //
00986 //===========
00987 //Map_SaveSelected
00988 //===========
00989 //
00990 // Saves selected world brushes and whole entities with partial/full selections
00991 //
00992 void Map_SaveSelected(char* pFilename)
00993 {
00994     entity_t    *e, *next;
00995     FILE *f;
00996     char temp[1024];
00997     int count;
00998 
00999     QE_ConvertDOSToUnixName(temp, pFilename);
01000     f = fopen(pFilename, "w");
01001 
01002     if (!f)
01003     {
01004         Sys_Printf ("ERROR!!!! Couldn't open %s\n", pFilename);
01005         return;
01006     }
01007 
01008     // write world entity first
01009     Entity_WriteSelected(world_entity, f);
01010 
01011     // then write all other ents
01012     count = 1;
01013     for (e=entities.next ; e != &entities ; e=next)
01014     {
01015     fprintf (f, "// entity %i\n", count);
01016     count++;
01017         Entity_WriteSelected(e, f);
01018         next = e->next;
01019     }
01020     fclose (f);
01021 }
01022 
01023 
01024 //
01025 //===========
01026 //Map_SaveSelected
01027 //===========
01028 //
01029 // Saves selected world brushes and whole entities with partial/full selections
01030 //
01031 void Map_SaveSelected(CMemFile* pMemFile, CMemFile* pPatchFile)
01032 {
01033     entity_t    *e, *next;
01034     int count;
01035     CString strTemp;
01036   
01037     // write world entity first
01038     Entity_WriteSelected(world_entity, pMemFile);
01039 
01040     // then write all other ents
01041     count = 1;
01042     for (e=entities.next ; e != &entities ; e=next)
01043     {
01044         MemFile_fprintf(pMemFile, "// entity %i\n", count);
01045         count++;
01046         Entity_WriteSelected(e, pMemFile);
01047         next = e->next;
01048     }
01049 
01050   //if (pPatchFile)
01051   //  Patch_WriteFile(pPatchFile);
01052 }
01053 
01054 
01055 void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...)
01056 {
01057   char Buffer[4096];
01058   va_list args;
01059     va_start (args,pText);
01060   vsprintf(Buffer, pText, args);
01061   pMemFile->Write(Buffer, strlen(Buffer));
01062 }

Generated on Thu Aug 25 12:38:33 2005 for Quake III Arena by  doxygen 1.3.9.1