map.cpp
来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 1,043 行 · 第 1/2 页
CPP
1,043 行
// 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];
#define MAX_WORLD_COORD 128*1024
#define MIN_WORLD_COORD -128*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;
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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?