aboutsummaryrefslogtreecommitdiffstats
path: root/q3radiant/MAP.CPP
diff options
context:
space:
mode:
Diffstat (limited to 'q3radiant/MAP.CPP')
-rwxr-xr-xq3radiant/MAP.CPP1062
1 files changed, 1062 insertions, 0 deletions
diff --git a/q3radiant/MAP.CPP b/q3radiant/MAP.CPP
new file mode 100755
index 0000000..8207c54
--- /dev/null
+++ b/q3radiant/MAP.CPP
@@ -0,0 +1,1062 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// map.c
+
+#include "stdafx.h"
+#include "qe3.h"
+#include "PrefsDlg.h"
+
+qboolean modified; // for quit confirmation (0 = clean, 1 = unsaved,
+ // 2 = autosaved, but not regular saved)
+
+char currentmap[1024];
+
+
+brush_t active_brushes; // brushes currently being displayed
+brush_t selected_brushes; // highlighted
+
+face_t *selected_face;
+brush_t *selected_face_brush;
+
+brush_t filtered_brushes; // brushes that have been filtered or regioned
+
+entity_t entities; // head/tail of doubly linked list
+
+entity_t *world_entity = NULL; // "classname" "worldspawn" !
+
+void AddRegionBrushes (void);
+void RemoveRegionBrushes (void);
+
+
+void DupLists()
+{
+ DWORD dw = GetTickCount();
+
+}
+
+/*
+=============================================================
+
+ Cross map selection saving
+
+ this could fuck up if you have only part of a complex entity selected...
+=============================================================
+*/
+
+brush_t between_brushes;
+entity_t between_entities;
+
+bool g_bRestoreBetween = false;
+
+void Map_SaveBetween (void)
+{
+
+ if (g_pParentWnd->ActiveXY())
+ {
+ g_bRestoreBetween = true;
+ g_pParentWnd->ActiveXY()->Copy();
+ }
+ return;
+
+#if 0
+
+ brush_t *b;
+ entity_t *e, *e2;
+
+ between_brushes.next = selected_brushes.next;
+ between_brushes.prev = selected_brushes.prev;
+ between_brushes.next->prev = &between_brushes;
+ between_brushes.prev->next = &between_brushes;
+
+ between_entities.next = between_entities.prev = &between_entities;
+ selected_brushes.next = selected_brushes.prev = &selected_brushes;
+
+ for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
+ {
+ e = b->owner;
+ if (e == world_entity)
+ b->owner = NULL;
+ else
+ {
+ for (e2=between_entities.next ; e2 != &between_entities ; e2=e2->next)
+ if (e2 == e)
+ goto next; // allready got the entity
+ // move the entity over
+ e->prev->next = e->next;
+ e->next->prev = e->prev;
+ e->next = between_entities.next;
+ e->prev = &between_entities;
+ e->next->prev = e;
+ e->prev->next = e;
+ }
+next: ;
+ }
+#endif
+}
+
+void Map_RestoreBetween (void)
+{
+ if (g_pParentWnd->ActiveXY() && g_bRestoreBetween)
+ g_pParentWnd->ActiveXY()->Paste();
+ return;
+
+#if 0
+ entity_t *head, *tail;
+ brush_t *b;
+
+ if (!between_brushes.next)
+ return;
+
+ for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
+ {
+ if (!b->owner)
+ {
+ b->owner = world_entity;
+ b->onext = world_entity->brushes.onext;
+ b->oprev = &world_entity->brushes;
+ b->onext->oprev = b;
+ b->oprev->onext = b;
+ }
+ }
+
+ selected_brushes.next = between_brushes.next;
+ selected_brushes.prev = between_brushes.prev;
+ selected_brushes.next->prev = &selected_brushes;
+ selected_brushes.prev->next = &selected_brushes;
+
+ head = between_entities.next;
+ tail = between_entities.prev;
+
+ if (head != tail)
+ {
+ entities.prev->next = head;
+ head->prev = entities.prev;
+ tail->next = &entities;
+ entities.prev = tail;
+ }
+
+ between_brushes.next = NULL;
+ between_entities.next = NULL;
+#endif
+}
+
+//============================================================================
+
+bool CheckForTinyBrush(brush_t* b, int n, float fSize)
+{
+ bool bTiny = false;
+ for (int i=0 ; i<3 ; i++)
+ {
+ if (b->maxs[i] - b->mins[i] < fSize)
+ bTiny = true;
+ }
+ if (bTiny)
+ Sys_Printf("Possible problem brush (too small) #%i ", n);
+ return bTiny;
+}
+
+void Map_BuildBrushData(void)
+{
+ brush_t *b, *next;
+
+ if (active_brushes.next == NULL)
+ return;
+
+ Sys_BeginWait (); // this could take a while
+
+ int n = 0;
+ for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
+ {
+ next = b->next;
+ Brush_Build( b, true, false, false );
+ if (!b->brush_faces || (g_PrefsDlg.m_bCleanTiny && CheckForTinyBrush(b, n++, g_PrefsDlg.m_fTinySize)))
+ {
+ Brush_Free (b);
+ Sys_Printf ("Removed degenerate brush\n");
+ }
+ }
+ Sys_EndWait();
+}
+
+entity_t *Map_FindClass (char *cname)
+{
+ entity_t *ent;
+
+ for (ent = entities.next ; ent != &entities ; ent=ent->next)
+ {
+ if (!strcmp(cname, ValueForKey (ent, "classname")))
+ return ent;
+ }
+ return NULL;
+}
+
+/*
+================
+Map_Free
+================
+*/
+void Map_Free (void)
+{
+ g_bRestoreBetween = false;
+ if (selected_brushes.next &&
+ (selected_brushes.next != &selected_brushes) )
+ {
+ if (MessageBox(g_qeglobals.d_hwndMain, "Copy selection?", "", MB_YESNO) == IDYES)
+ Map_SaveBetween ();
+ }
+
+ Texture_ClearInuse ();
+ Pointfile_Clear ();
+ strcpy (currentmap, "unnamed.map");
+ Sys_SetTitle (currentmap);
+ g_qeglobals.d_num_entities = 0;
+ g_qeglobals.d_numterrapoints = 0;
+
+ if (!active_brushes.next)
+ { // first map
+ active_brushes.prev = active_brushes.next = &active_brushes;
+ selected_brushes.prev = selected_brushes.next = &selected_brushes;
+ filtered_brushes.prev = filtered_brushes.next = &filtered_brushes;
+
+ entities.prev = entities.next = &entities;
+ }
+ else
+ {
+ while (active_brushes.next != &active_brushes)
+ Brush_Free (active_brushes.next);
+ while (selected_brushes.next != &selected_brushes)
+ Brush_Free (selected_brushes.next);
+ while (filtered_brushes.next != &filtered_brushes)
+ Brush_Free (filtered_brushes.next);
+
+ while (entities.next != &entities)
+ Entity_Free (entities.next);
+ }
+
+ if (world_entity)
+ Entity_Free(world_entity);
+ world_entity = NULL;
+}
+
+entity_t *AngledEntity()
+{
+ entity_t *ent = Map_FindClass ("info_player_start");
+ if (!ent)
+ {
+ ent = Map_FindClass ("info_player_deathmatch");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("info_player_deathmatch");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_redplayer");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_blueplayer");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_redspawn");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_bluespawn");
+ }
+ return ent;
+}
+
+
+
+/*
+================
+Map_LoadFile
+================
+*/
+void Map_LoadFile (char *filename)
+{
+ char *buf;
+ entity_t *ent;
+ char temp[1024];
+
+ Sys_BeginWait ();
+ Select_Deselect();
+ //SetInspectorMode(W_CONSOLE);
+
+ QE_ConvertDOSToUnixName( temp, filename );
+ Sys_Printf ("Map_LoadFile: %s\n", temp );
+
+ Map_Free ();
+ //++timo FIXME: maybe even easier to have Group_Init called from Map_Free?
+ Group_Init();
+
+ g_qeglobals.d_parsed_brushes = 0;
+ strcpy (currentmap, filename);
+
+ if (LoadFile (filename, (void **)&buf) != -1)
+ {
+
+ StartTokenParsing (buf);
+ g_qeglobals.d_num_entities = 0;
+
+ // Timo
+ // will be used in Entity_Parse to detect if a conversion between brush formats is needed
+ g_qeglobals.bNeedConvert = false;
+ g_qeglobals.bOldBrushes = false;
+ g_qeglobals.bPrimitBrushes = false;
+
+ while (1)
+ {
+ ent = Entity_Parse (false, &active_brushes);
+ if (!ent)
+ break;
+ if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
+ {
+ if (world_entity)
+ Sys_Printf ("WARNING: multiple worldspawn\n");
+ world_entity = ent;
+ }
+ else if (!strcmp(ValueForKey (ent, "classname"), "group_info"))
+ {
+ // it's a group thing!
+ Group_Add(ent);
+ Entity_Free(ent);
+ }
+ else
+ {
+ // add the entity to the end of the entity list
+ ent->next = &entities;
+ ent->prev = entities.prev;
+ entities.prev->next = ent;
+ entities.prev = ent;
+ g_qeglobals.d_num_entities++;
+ }
+ }
+ }
+
+ free (buf);
+
+ if (!world_entity)
+ {
+ Sys_Printf ("No worldspawn in map.\n");
+ Map_New ();
+ return;
+ }
+
+ Sys_Printf ("--- LoadMapFile ---\n");
+ Sys_Printf ("%s\n", temp );
+
+ Sys_Printf ("%5i brushes\n", g_qeglobals.d_parsed_brushes );
+ Sys_Printf ("%5i entities\n", g_qeglobals.d_num_entities);
+
+ Map_RestoreBetween ();
+
+ Sys_Printf ("Map_BuildAllDisplayLists\n");
+ Map_BuildBrushData();
+
+ // reset the "need conversion" flag
+ // conversion to the good format done in Map_BuildBrushData
+ g_qeglobals.bNeedConvert=false;
+
+ //
+ // move the view to a start position
+ //
+ ent = AngledEntity();
+
+ g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
+ if (ent)
+ {
+ GetVectorForKey (ent, "origin", g_pParentWnd->GetCamera()->Camera().origin);
+ GetVectorForKey (ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin());
+ g_pParentWnd->GetCamera()->Camera().angles[YAW] = FloatForKey (ent, "angle");
+ }
+ else
+ {
+ g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
+ VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
+ VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
+ }
+
+ Map_RegionOff ();
+
+
+ modified = false;
+ Sys_SetTitle (temp);
+
+ Texture_ShowInuse ();
+
+ Sys_EndWait();
+ Sys_UpdateWindows (W_ALL);
+
+}
+
+/*
+===========
+Map_SaveFile
+===========
+*/
+void Map_SaveFile (char *filename, qboolean use_region )
+{
+ entity_t *e, *next;
+ FILE *f;
+ char temp[1024];
+ int count;
+
+ if (filename == NULL || strlen(filename) == 0)
+ {
+ CFileDialog dlgSave(FALSE, "map", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Map Files (*.map)|*.map||", AfxGetMainWnd());
+ if (dlgSave.DoModal() == IDOK)
+ filename = strdup(dlgSave.m_ofn.lpstrFile);
+ else
+ return;
+ }
+
+ Pointfile_Clear ();
+ QE_ConvertDOSToUnixName( temp, filename );
+
+ if (!use_region)
+ {
+ char backup[1024];
+
+ // rename current to .bak
+ strcpy (backup, filename);
+ StripExtension (backup);
+ strcat (backup, ".bak");
+ _unlink (backup);
+ rename (filename, backup);
+ }
+
+ Sys_Printf ("Map_SaveFile: %s\n", filename);
+
+ f = fopen(filename, "w");
+
+ if (!f)
+ {
+ Sys_Printf ("ERROR!!!! Couldn't open %s\n", filename);
+ return;
+ }
+
+ if (use_region)
+ {
+ AddRegionBrushes ();
+ }
+
+ // write world entity first
+ Entity_Write (world_entity, f, use_region);
+
+ // then write all other ents
+ count = 1;
+ for (e=entities.next ; e != &entities ; e=next)
+ {
+ next = e->next;
+ if (e->brushes.onext == &e->brushes)
+ {
+ Entity_Free (e); // no brushes left, so remove it
+ }
+ else
+ {
+ fprintf (f, "// entity %i\n", count);
+ count++;
+ Entity_Write (e, f, use_region);
+ }
+ }
+
+ // save the group info stuff
+ Group_Save(f);
+
+ fclose (f);
+
+ if (use_region)
+ RemoveRegionBrushes ();
+
+ Sys_Printf ("Saved.\n");
+ modified = false;
+
+ if ( !strstr( temp, "autosave" ) )
+ Sys_SetTitle (temp);
+
+ if (!use_region)
+ {
+ time_t timer;
+ FILE *f;
+
+ time (&timer);
+ MessageBeep (MB_ICONEXCLAMATION);
+ f = fopen ("c:/tstamps.log", "a");
+ if (f)
+ {
+ fprintf (f, "%s", filename);
+ //fprintf (f, "%4i : %35s : %s", g_qeglobals.d_workcount, filename, ctime(&timer));
+ fclose (f);
+ g_qeglobals.d_workcount = 0;
+ }
+ fclose (f);
+ Sys_Status ("Saved.\n", 0);
+ }
+
+ //Curve_WriteFile (filename); //.trinity
+ //Patch_WriteFile (filename);
+}
+
+/*
+===========
+Map_New
+===========
+*/
+void Map_New (void)
+{
+ Sys_Printf ("Map_New\n");
+ Map_Free ();
+
+ Patch_Cleanup();
+
+ world_entity = (entity_s*)qmalloc(sizeof(*world_entity));
+ world_entity->brushes.onext =
+ world_entity->brushes.oprev = &world_entity->brushes;
+ SetKeyValue (world_entity, "classname", "worldspawn");
+ world_entity->eclass = Eclass_ForName ("worldspawn", true);
+
+ g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
+ g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
+ VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
+ g_pParentWnd->GetCamera()->Camera().origin[2] = 48;
+ VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
+
+ Map_RestoreBetween ();
+
+ Group_Init();
+
+ Sys_UpdateWindows (W_ALL);
+ modified = false;
+}
+
+/*
+===========================================================
+
+ REGION
+
+===========================================================
+*/
+
+qboolean region_active;
+vec3_t region_mins = {MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD};
+vec3_t region_maxs = {MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD};
+
+brush_t *region_sides[4];
+/*
+===========
+AddRegionBrushes
+
+a regioned map will have temp walls put up at the region boundary
+===========
+*/
+void AddRegionBrushes (void)
+{
+ vec3_t mins, maxs;
+ int i;
+ texdef_t td;
+
+ if (!region_active)
+ return;
+
+ memset (&td, 0, sizeof(td));
+ //strcpy (td.name, "REGION");
+ td.SetName("REGION");
+
+ mins[0] = region_mins[0] - 16;
+ maxs[0] = region_mins[0] + 1;
+ mins[1] = region_mins[1] - 16;
+ maxs[1] = region_maxs[1] + 16;
+ mins[2] = MIN_WORLD_COORD;
+ maxs[2] = MAX_WORLD_COORD;
+ region_sides[0] = Brush_Create (mins, maxs, &td);
+
+ mins[0] = region_maxs[0] - 1;
+ maxs[0] = region_maxs[0] + 16;
+ region_sides[1] = Brush_Create (mins, maxs, &td);
+
+ mins[0] = region_mins[0] - 16;
+ maxs[0] = region_maxs[0] + 16;
+ mins[1] = region_mins[1] - 16;
+ maxs[1] = region_mins[1] + 1;
+ region_sides[2] = Brush_Create (mins, maxs, &td);
+
+ mins[1] = region_maxs[1] - 1;
+ maxs[1] = region_maxs[1] + 16;
+ region_sides[3] = Brush_Create (mins, maxs, &td);
+
+ for (i=0 ; i<4 ; i++)
+ {
+ Brush_AddToList (region_sides[i], &selected_brushes);
+ Entity_LinkBrush (world_entity, region_sides[i]);
+ Brush_Build( region_sides[i] );
+ }
+}
+
+void RemoveRegionBrushes (void)
+{
+ int i;
+
+ if (!region_active)
+ return;
+ for (i=0 ; i<4 ; i++)
+ Brush_Free (region_sides[i]);
+}
+
+
+qboolean Map_IsBrushFiltered (brush_t *b)
+{
+ int i;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ if (b->mins[i] > region_maxs[i])
+ return true;
+ if (b->maxs[i] < region_mins[i])
+ return true;
+ }
+ return false;
+}
+
+/*
+===========
+Map_RegionOff
+
+Other filtering options may still be on
+===========
+*/
+void Map_RegionOff (void)
+{
+ brush_t *b, *next;
+ int i;
+
+ region_active = false;
+ for (i=0 ; i<3 ; i++)
+ {
+ region_maxs[i] = MAX_WORLD_COORD;//4096;
+ region_mins[i] = MIN_WORLD_COORD;//-4096;
+ }
+
+ for (b=filtered_brushes.next ; b != &filtered_brushes ; b=next)
+ {
+ next = b->next;
+ if (Map_IsBrushFiltered (b))
+ continue; // still filtered
+ Brush_RemoveFromList (b);
+ if (active_brushes.next == NULL || active_brushes.prev == NULL)
+ {
+ active_brushes.next = &active_brushes;
+ active_brushes.prev = &active_brushes;
+ }
+ Brush_AddToList (b, &active_brushes);
+ }
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Map_ApplyRegion (void)
+{
+ brush_t *b, *next;
+
+ region_active = true;
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+ if (!Map_IsBrushFiltered (b))
+ continue; // still filtered
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &filtered_brushes);
+ }
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+========================
+Map_RegionSelectedBrushes
+========================
+*/
+void Map_RegionSelectedBrushes (void)
+{
+ Map_RegionOff ();
+
+ if (selected_brushes.next == &selected_brushes) // nothing selected
+ {
+ Sys_Printf("Tried to region with no selection...\n");
+ return;
+ }
+ region_active = true;
+ Select_GetBounds (region_mins, region_maxs);
+
+ // move the entire active_brushes list to filtered_brushes
+ filtered_brushes.next = active_brushes.next;
+ filtered_brushes.prev = active_brushes.prev;
+ filtered_brushes.next->prev = &filtered_brushes;
+ filtered_brushes.prev->next = &filtered_brushes;
+
+ // move the entire selected_brushes list to active_brushes
+ active_brushes.next = selected_brushes.next;
+ active_brushes.prev = selected_brushes.prev;
+ active_brushes.next->prev = &active_brushes;
+ active_brushes.prev->next = &active_brushes;
+
+ // clear selected_brushes
+ selected_brushes.next = selected_brushes.prev = &selected_brushes;
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+===========
+Map_RegionXY
+===========
+*/
+void Map_RegionXY (void)
+{
+ Map_RegionOff ();
+
+ region_mins[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] - 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
+ region_maxs[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] + 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
+ region_mins[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] - 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
+ region_maxs[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] + 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
+ region_mins[2] = -MIN_WORLD_COORD;
+ region_maxs[2] = MAX_WORLD_COORD;
+ Map_ApplyRegion ();
+}
+
+/*
+===========
+Map_RegionTallBrush
+===========
+*/
+void Map_RegionTallBrush (void)
+{
+ brush_t *b;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ b = selected_brushes.next;
+
+ Map_RegionOff ();
+
+ VectorCopy (b->mins, region_mins);
+ VectorCopy (b->maxs, region_maxs);
+ region_mins[2] = MIN_WORLD_COORD;
+ region_maxs[2] = MAX_WORLD_COORD;
+
+
+ Select_Delete ();
+ Map_ApplyRegion ();
+}
+/*
+===========
+Map_RegionBrush
+===========
+*/
+void Map_RegionBrush (void)
+{
+ brush_t *b;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ b = selected_brushes.next;
+
+ Map_RegionOff ();
+
+ VectorCopy (b->mins, region_mins);
+ VectorCopy (b->maxs, region_maxs);
+
+ Select_Delete ();
+ Map_ApplyRegion ();
+}
+
+
+
+void UniqueTargetName(CString& rStr)
+{
+ // make a unique target value
+ int maxtarg = 0;
+ for (entity_t* e=entities.next ; e != &entities ; e=e->next)
+ {
+ char* tn = ValueForKey (e, "targetname");
+ if (tn && tn[0])
+ {
+ int targetnum = atoi(tn+1);
+ if (targetnum > maxtarg)
+ maxtarg = targetnum;
+ }
+ else
+ {
+ tn = ValueForKey (e, "target");
+ if (tn && tn[0])
+ {
+ int targetnum = atoi(tn+1);
+ if (targetnum > maxtarg)
+ maxtarg = targetnum;
+ }
+ }
+ }
+ rStr.Format("t%i", maxtarg+1);
+}
+
+//
+//================
+//Map_ImportFile
+// Timo 09/01/99 : called by CXYWnd::Paste & Map_ImportFile
+// if Map_ImportFile ( prefab ), the buffer may contain brushes in old format ( conversion needed )
+//================
+//
+void Map_ImportBuffer (char* buf)
+{
+ entity_t* ent;
+ brush_t* b = NULL;
+ CPtrArray ptrs;
+
+ Select_Deselect();
+
+ Undo_Start("import buffer");
+
+ g_qeglobals.d_parsed_brushes = 0;
+ if (buf)
+ {
+ CMapStringToString mapStr;
+ StartTokenParsing (buf);
+ g_qeglobals.d_num_entities = 0;
+
+ // Timo
+ // will be used in Entity_Parse to detect if a conversion between brush formats is needed
+ g_qeglobals.bNeedConvert = false;
+ g_qeglobals.bOldBrushes = false;
+ g_qeglobals.bPrimitBrushes = false;
+
+ while (1)
+ {
+
+ // use the selected brushes list as it's handy
+ //ent = Entity_Parse (false, &selected_brushes);
+ ent = Entity_Parse (false, &active_brushes);
+ if (!ent)
+ break;
+ //end entity for undo
+ Undo_EndEntity(ent);
+ //end brushes for undo
+ for(b = ent->brushes.onext; b && b != &ent->brushes; b = b->onext)
+ {
+ Undo_EndBrush(b);
+ }
+
+ if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
+ {
+ // world brushes need to be added to the current world entity
+
+ b=ent->brushes.onext;
+ while (b && b != &ent->brushes)
+ {
+ brush_t* bNext = b->onext;
+ Entity_UnlinkBrush(b);
+ Entity_LinkBrush(world_entity, b);
+ ptrs.Add(b);
+ b = bNext;
+ }
+ }
+ else
+ {
+ // the following bit remaps conflicting target/targetname key/value pairs
+ CString str = ValueForKey(ent, "target");
+ CString strKey;
+ CString strTarget("");
+ if (str.GetLength() > 0)
+ {
+ if (FindEntity("target", str.GetBuffer(0)))
+ {
+ if (!mapStr.Lookup(str, strKey))
+ {
+ UniqueTargetName(strKey);
+ mapStr.SetAt(str, strKey);
+ }
+ strTarget = strKey;
+ SetKeyValue(ent, "target", strTarget.GetBuffer(0));
+ }
+ }
+ str = ValueForKey(ent, "targetname");
+ if (str.GetLength() > 0)
+ {
+ if (FindEntity("targetname", str.GetBuffer(0)))
+ {
+ if (!mapStr.Lookup(str, strKey))
+ {
+ UniqueTargetName(strKey);
+ mapStr.SetAt(str, strKey);
+ }
+ SetKeyValue(ent, "targetname", strKey.GetBuffer(0));
+ }
+ }
+ //if (strTarget.GetLength() > 0)
+ // SetKeyValue(ent, "target", strTarget.GetBuffer(0));
+
+ // add the entity to the end of the entity list
+ ent->next = &entities;
+ ent->prev = entities.prev;
+ entities.prev->next = ent;
+ entities.prev = ent;
+ g_qeglobals.d_num_entities++;
+
+ for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
+ {
+ ptrs.Add(b);
+ }
+ }
+ }
+ }
+
+ //::ShowWindow(g_qeglobals.d_hwndEntity, FALSE);
+ //::LockWindowUpdate(g_qeglobals.d_hwndEntity);
+ g_bScreenUpdates = false;
+ for (int i = 0; i < ptrs.GetSize(); i++)
+ {
+ Brush_Build(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
+ Select_Brush(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
+ }
+ //::LockWindowUpdate(NULL);
+ g_bScreenUpdates = true;
+
+ ptrs.RemoveAll();
+
+ // reset the "need conversion" flag
+ // conversion to the good format done in Map_BuildBrushData
+ g_qeglobals.bNeedConvert=false;
+
+ Sys_UpdateWindows (W_ALL);
+ //Sys_MarkMapModified();
+ modified = true;
+
+ Undo_End();
+
+}
+
+
+//
+//================
+//Map_ImportFile
+//================
+//
+void Map_ImportFile (char *filename)
+{
+ char* buf;
+ char temp[1024];
+ Sys_BeginWait ();
+ QE_ConvertDOSToUnixName( temp, filename );
+ if (LoadFile (filename, (void **)&buf) != -1)
+ {
+ Map_ImportBuffer(buf);
+ free(buf);
+ Map_BuildBrushData();
+ }
+ Sys_UpdateWindows (W_ALL);
+ modified = true;
+ Sys_EndWait();
+}
+
+//
+//===========
+//Map_SaveSelected
+//===========
+//
+// Saves selected world brushes and whole entities with partial/full selections
+//
+void Map_SaveSelected(char* pFilename)
+{
+ entity_t *e, *next;
+ FILE *f;
+ char temp[1024];
+ int count;
+
+ QE_ConvertDOSToUnixName(temp, pFilename);
+ f = fopen(pFilename, "w");
+
+ if (!f)
+ {
+ Sys_Printf ("ERROR!!!! Couldn't open %s\n", pFilename);
+ return;
+ }
+
+ // write world entity first
+ Entity_WriteSelected(world_entity, f);
+
+ // then write all other ents
+ count = 1;
+ for (e=entities.next ; e != &entities ; e=next)
+ {
+ fprintf (f, "// entity %i\n", count);
+ count++;
+ Entity_WriteSelected(e, f);
+ next = e->next;
+ }
+ fclose (f);
+}
+
+
+//
+//===========
+//Map_SaveSelected
+//===========
+//
+// Saves selected world brushes and whole entities with partial/full selections
+//
+void Map_SaveSelected(CMemFile* pMemFile, CMemFile* pPatchFile)
+{
+ entity_t *e, *next;
+ int count;
+ CString strTemp;
+
+ // write world entity first
+ Entity_WriteSelected(world_entity, pMemFile);
+
+ // then write all other ents
+ count = 1;
+ for (e=entities.next ; e != &entities ; e=next)
+ {
+ MemFile_fprintf(pMemFile, "// entity %i\n", count);
+ count++;
+ Entity_WriteSelected(e, pMemFile);
+ next = e->next;
+ }
+
+ //if (pPatchFile)
+ // Patch_WriteFile(pPatchFile);
+}
+
+
+void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...)
+{
+ char Buffer[4096];
+ va_list args;
+ va_start (args,pText);
+ vsprintf(Buffer, pText, args);
+ pMemFile->Write(Buffer, strlen(Buffer));
+} \ No newline at end of file