12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 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 3 of the License, or
- (at your option) any later version.
- Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- #include "qe3.h"
- int mapModified; // 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 mess this 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;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void Map_RestoreBetween(void) {
- if (g_pParentWnd->ActiveXY() && g_bRestoreBetween) {
- g_pParentWnd->ActiveXY()->Paste();
- }
- return;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- 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) {
- common->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);
- common->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;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- int Map_GetUniqueEntityID(const char *prefix, const char *eclass) {
- entity_t *ent;
- int id = 0;
- for (ent = entities.next; ent != &entities; ent = ent->next) {
- if (!strcmp(eclass, ValueForKey(ent, "classname"))) {
- const char *name = ValueForKey(ent, "name");
- if (name && name[0]) {
- const char *buf;
- if (prefix && *prefix) {
- buf = va("%s_%s_", prefix, eclass);
- } else {
- buf = va("%s_", eclass);
- }
- int len = strlen(buf);
- if ( idStr::Cmpn(name, buf, len) == 0 ) {
- int j = atoi(name + len);
- if (j > id) {
- id = j;
- }
- }
- }
- }
- }
- return id + 1;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool Entity_NameIsUnique(const char *name) {
- entity_t *ent;
- if (name == NULL) {
- return false;
- }
- for (ent = entities.next; ent != &entities; ent = ent->next) {
- const char *testName = ValueForKey(ent, "name");
- if (testName) {
- if ( idStr::Icmp(name, testName) == 0 ) {
- return false;
- }
- }
- }
- return true;
- }
- /*
- =======================================================================================================================
- Map_Free
- =======================================================================================================================
- */
- void Map_Free(void) {
- g_bRestoreBetween = false;
- if (selected_brushes.next && (selected_brushes.next != &selected_brushes)) {
- if (g_pParentWnd->MessageBox("Copy selection?", "", MB_YESNO) == IDYES) {
- Map_SaveBetween();
- }
- }
- // clear all the render and sound system data
- g_qeglobals.rw->InitFromMap( NULL );
- g_qeglobals.sw->ClearAllSoundEmitters();
- 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, false);
- }
- while (selected_brushes.next != &selected_brushes) {
- Brush_Free(selected_brushes.next, false);
- }
- while (filtered_brushes.next != &filtered_brushes) {
- Brush_Free(filtered_brushes.next, false);
- }
- 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;
- }
- brush_t *BrushFromMapPatch(idMapPatch *mappatch, idVec3 origin) {
- patchMesh_t *pm = MakeNewPatch(mappatch->GetWidth(), mappatch->GetHeight());
- pm->d_texture = Texture_ForName(mappatch->GetMaterial());
- for (int i = 0; i < mappatch->GetWidth(); i++) {
- for (int j = 0; j < mappatch->GetHeight(); j++) {
- pm->ctrl(i, j).xyz = (*mappatch)[j * mappatch->GetWidth() + i].xyz + origin;
- pm->ctrl(i, j).st = (*mappatch)[j * mappatch->GetWidth() + i].st;
- }
- }
- pm->horzSubdivisions = mappatch->GetHorzSubdivisions();
- pm->vertSubdivisions = mappatch->GetVertSubdivisions();
- pm->explicitSubdivisions = mappatch->GetExplicitlySubdivided();
- if (mappatch->epairs.GetNumKeyVals()) {
- pm->epairs = new idDict;
- *pm->epairs = mappatch->epairs;
- }
- brush_t *b = AddBrushForPatch(pm, false);
- return b;
- }
- brush_t *BrushFromMapBrush(idMapBrush *mapbrush, idVec3 origin) {
- brush_t *b = NULL;
- if (mapbrush) {
- b = Brush_Alloc();
- int count = mapbrush->GetNumSides();
- for (int i = 0; i < count; i++) {
- idMapBrushSide *side = mapbrush->GetSide(i);
- face_t *f = Face_Alloc();
- f->next = NULL;
- if (!b->brush_faces) {
- b->brush_faces = f;
- }
- else {
- face_t *scan;
- for (scan = b->brush_faces; scan->next; scan = scan->next) {
- ;
- }
- scan->next = f;
- }
- f->plane = side->GetPlane();
- f->originalPlane = f->plane;
- f->dirty = false;
- idWinding w;
- w.BaseForPlane(f->plane);
- for (int j = 0; j < 3; j++) {
- f->planepts[j].x = w[j].x + origin.x;
- f->planepts[j].y = w[j].y + origin.y;
- f->planepts[j].z = w[j].z + origin.z;
- }
- idVec3 mat[2];
- side->GetTextureMatrix(mat[0], mat[1]);
- f->brushprimit_texdef.coords[0][0] = mat[0][0];
- f->brushprimit_texdef.coords[0][1] = mat[0][1];
- f->brushprimit_texdef.coords[0][2] = mat[0][2];
- f->brushprimit_texdef.coords[1][0] = mat[1][0];
- f->brushprimit_texdef.coords[1][1] = mat[1][1];
- f->brushprimit_texdef.coords[1][2] = mat[1][2];
- f->texdef.SetName(side->GetMaterial());
- }
- }
- return b;
- }
- entity_t *EntityFromMapEntity(idMapEntity *mapent, CWaitDlg *dlg) {
- entity_t *ent = NULL;
- if (mapent) {
- ent = Entity_New();
- ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
- ent->origin.Zero();
- ent->epairs = mapent->epairs;
- GetVectorForKey(ent, "origin", ent->origin);
- int count = mapent->GetNumPrimitives();
- long lastUpdate = 0;
- idStr status;
- for (int i = 0; i < count; i++) {
- idMapPrimitive *prim = mapent->GetPrimitive(i);
- if (prim) {
- // update 20 times a second
- if ( (GetTickCount() - lastUpdate) > 50 ) {
- lastUpdate = GetTickCount();
- if (prim->GetType() == idMapPrimitive::TYPE_BRUSH) {
- sprintf(status, "Reading primitive %i (brush)", i);
- } else if (prim->GetType() == idMapPrimitive::TYPE_PATCH) {
- sprintf(status, "Reading primitive %i (patch)", i);
- }
- dlg->SetText(status, true);
- }
- if ( dlg->CancelPressed() ) {
- return ent;
- }
- brush_t *b = NULL;
- if (prim->GetType() == idMapPrimitive::TYPE_BRUSH) {
- idMapBrush *mapbrush = reinterpret_cast<idMapBrush*>(prim);
- b = BrushFromMapBrush(mapbrush, ent->origin);
- } else if (prim->GetType() == idMapPrimitive::TYPE_PATCH) {
- idMapPatch *mappatch = reinterpret_cast<idMapPatch*>(prim);
- b = BrushFromMapPatch(mappatch, ent->origin);
- }
- if (b) {
- b->owner = ent;
- // add to the end of the entity chain
- b->onext = &ent->brushes;
- b->oprev = ent->brushes.oprev;
- ent->brushes.oprev->onext = b;
- ent->brushes.oprev = b;
- }
- }
- }
- }
- return ent;
- }
- extern entity_t *Entity_PostParse(entity_t *ent, brush_t *pList);
- /*
- =======================================================================================================================
- Map_LoadFile
- =======================================================================================================================
- */
- void Map_LoadFile(const char *filename) {
- entity_t *ent;
- CWaitDlg dlg;
- idStr fileStr, status;
- idMapFile mapfile;
- Sys_BeginWait();
- Select_Deselect();
- dlg.AllowCancel( true );
- idStr( filename ).ExtractFileName( fileStr );
- sprintf( status, "Loading %s...", fileStr.c_str() );
- dlg.SetWindowText( status );
- sprintf( status, "Reading file %s...", fileStr.c_str() );
- dlg.SetText( status );
- // SetInspectorMode(W_CONSOLE);
- fileStr = filename;
- fileStr.BackSlashesToSlashes();
- common->Printf( "Map_LoadFile: %s\n", fileStr.c_str() );
- Map_Free();
- g_qeglobals.d_parsed_brushes = 0;
- strcpy( currentmap, filename );
- if(mapfile.Parse(filename, true, true)) {
- g_qeglobals.bNeedConvert = false;
- g_qeglobals.bOldBrushes = false;
- g_qeglobals.bPrimitBrushes = false;
- g_qeglobals.mapVersion = 1.0;
- long lastUpdate = 0;
- int count = mapfile.GetNumEntities();
- for (int i = 0; i < count; i++) {
- idMapEntity *mapent = mapfile.GetEntity(i);
- if (mapent) {
- idStr classname = mapent->epairs.GetString("classname");
- // Update 20 times a second
- if ( (GetTickCount() - lastUpdate) > 50 ) {
- lastUpdate = GetTickCount();
- sprintf(status, "Loading entity %i (%s)...", i, classname.c_str());
- dlg.SetText(status);
- }
- if ( dlg.CancelPressed() ) {
- Sys_Status("Map load cancelled.\n");
- Map_New();
- return;
- }
- if (classname == "worldspawn") {
- world_entity = EntityFromMapEntity(mapent, &dlg);
- Entity_PostParse(world_entity, &active_brushes);
- } else {
- ent = EntityFromMapEntity(mapent, &dlg);
- Entity_PostParse(ent, &active_brushes);
- Entity_Name(ent, true);
- // 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++;
- }
- }
- }
- }
- if (!world_entity) {
- Sys_Status("No worldspawn in map.\n");
- Map_New();
- return;
- }
- common->Printf("--- LoadMapFile ---\n");
- common->Printf("%s\n", fileStr.c_str());
- common->Printf("%5i brushes\n", g_qeglobals.d_parsed_brushes);
- common->Printf("%5i entities\n", g_qeglobals.d_num_entities);
- dlg.SetText("Restoring Between");
- Map_RestoreBetween();
- dlg.SetText("Building Brush Data");
- common->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();
- mapModified = 0;
- if (GetFileAttributes(filename) & FILE_ATTRIBUTE_READONLY) {
- fileStr += " (read only) ";
- }
- Sys_SetTitle(fileStr);
- Texture_ShowInuse();
- if (g_pParentWnd->GetCamera()->GetRenderMode()) {
- g_pParentWnd->GetCamera()->BuildRendererState();
- }
- Sys_EndWait();
- Sys_UpdateWindows(W_ALL);
- }
- void Map_VerifyCurrentMap(const char *map) {
- if ( idStr::Icmp( map, currentmap ) != 0 ) {
- Map_LoadFile( map );
- }
- }
- idMapPrimitive *BrushToMapPrimitive( const brush_t *b, const idVec3 &origin ) {
- if ( b->pPatch ) {
- idMapPatch *patch = new idMapPatch( b->pPatch->width * 6, b->pPatch->height * 6 );
- patch->SetSize( b->pPatch->width, b->pPatch->height );
- for ( int i = 0; i < b->pPatch->width; i++ ) {
- for ( int j = 0; j < b->pPatch->height; j++ ) {
- (*patch)[j*patch->GetWidth()+i].xyz = b->pPatch->ctrl(i, j).xyz - origin;
- (*patch)[j*patch->GetWidth()+i].st = b->pPatch->ctrl(i, j).st;
- }
- }
- patch->SetExplicitlySubdivided( b->pPatch->explicitSubdivisions );
- if ( b->pPatch->explicitSubdivisions ) {
- patch->SetHorzSubdivisions( b->pPatch->horzSubdivisions );
- patch->SetVertSubdivisions( b->pPatch->vertSubdivisions );
- }
- patch->SetMaterial( b->pPatch->d_texture->GetName() );
- if ( b->pPatch->epairs ) {
- patch->epairs = *b->pPatch->epairs;
- }
- return patch;
- }
- else {
- idMapBrush *mapbrush = new idMapBrush;
- for ( face_t *f = b->brush_faces; f; f = f->next ) {
- idMapBrushSide *side = new idMapBrushSide;
- idPlane plane;
- if ( f->dirty ) {
- f->planepts[0] -= origin;
- f->planepts[1] -= origin;
- f->planepts[2] -= origin;
- plane.FromPoints( f->planepts[0], f->planepts[1], f->planepts[2], false );
- f->planepts[0] += origin;
- f->planepts[1] += origin;
- f->planepts[2] += origin;
- } else {
- plane = f->originalPlane;
- }
- side->SetPlane( plane );
- side->SetMaterial( f->d_texture->GetName() );
- idVec3 mat[2];
- mat[0][0] = f->brushprimit_texdef.coords[0][0];
- mat[0][1] = f->brushprimit_texdef.coords[0][1];
- mat[0][2] = f->brushprimit_texdef.coords[0][2];
- mat[1][0] = f->brushprimit_texdef.coords[1][0];
- mat[1][1] = f->brushprimit_texdef.coords[1][1];
- mat[1][2] = f->brushprimit_texdef.coords[1][2];
- side->SetTextureMatrix(mat);
- mapbrush->AddSide(side);
- mapbrush->epairs = b->epairs;
- }
- return mapbrush;
- }
- }
- idMapEntity *EntityToMapEntity(entity_t *e, bool use_region, CWaitDlg *dlg) {
- idMapEntity *mapent = new idMapEntity;
- mapent->epairs = e->epairs;
- idStr status;
- int count = 0;
- long lastUpdate = 0;
- if ( !EntityHasModel( e ) ) {
- for ( brush_t *b = e->brushes.onext; b != &e->brushes; b = b->onext ) {
- count++;
- if ( e->eclass->fixedsize && !b->entityModel ) {
- continue;
- }
- if ( !use_region || !Map_IsBrushFiltered( b ) ) {
- // Update 20 times a second
- if ( GetTickCount() - lastUpdate > 50 ) {
- lastUpdate = GetTickCount();
- if ( b->pPatch ) {
- sprintf( status, "Adding primitive %i (patch)", count );
- dlg->SetText( status, true );
- } else {
- sprintf( status, "Adding primitive %i (brush)", count );
- dlg->SetText( status, true );
- }
- }
- idMapPrimitive *prim = BrushToMapPrimitive( b, e->origin );
- if ( prim ) {
- mapent->AddPrimitive( prim );
- }
- }
- }
- }
- return mapent;
- }
- /*
- =======================================================================================================================
- Map_SaveFile
- =======================================================================================================================
- */
- bool Map_SaveFile(const char *filename, bool use_region, bool autosave) {
- entity_t *e, *next;
- idStr temp;
- int count;
- brush_t *b;
- idStr status;
- int len = strlen(filename);
- WIN32_FIND_DATA FileData;
- if (FindFirstFile(filename, &FileData) != INVALID_HANDLE_VALUE) {
- // the file exists;
- if (len > 0 && GetFileAttributes(filename) & FILE_ATTRIBUTE_READONLY) {
- g_pParentWnd->MessageBox("File is read only", "Read Only", MB_OK);
- return false;
- }
- }
- if (filename == NULL || len == 0 || (filename && stricmp(filename, "unnamed.map") == 0)) {
- CFileDialog dlgSave(FALSE,"map",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Map Files (*.map)|*.map||",AfxGetMainWnd());
- if (dlgSave.DoModal() == IDOK) {
- filename = dlgSave.m_ofn.lpstrFile;
- strcpy(currentmap, filename);
- }
- else {
- return false;
- }
- }
- MEMORYSTATUSEX statex;
- statex.dwLength = sizeof (statex);
- GlobalMemoryStatusEx (&statex);
- if ( statex.dwMemoryLoad > 95 ) {
- g_pParentWnd->MessageBox("Physical memory is over 95% utilized. Consider saving and restarting", "Memory");
- }
- CWaitDlg dlg;
- Pointfile_Clear();
- temp = filename;
- temp.BackSlashesToSlashes();
- if ( !use_region ) {
- idStr backup;
- backup = temp;
- backup.StripFileExtension();
- backup.SetFileExtension( ".bak" );
- if ( _unlink(backup) != 0 && errno != 2 ) { // errno 2 means the file doesn't exist, which we don't care about
- g_pParentWnd->MessageBox( va("Unable to delete %s: %s", backup.c_str(), strerror(errno) ), "File Error" );
- }
- if ( rename(filename, backup) != 0 ) {
- g_pParentWnd->MessageBox( va("Unable to rename %s to %s: %s", filename, backup.c_str(), strerror(errno) ), "File Error" );
- }
- }
- common->Printf("Map_SaveFile: %s\n", filename);
- idStr mapFile;
- bool localFile = (strstr(filename, ":") != NULL);
- if (autosave || localFile) {
- mapFile = filename;
- } else {
- mapFile = fileSystem->OSPathToRelativePath( filename );
- }
- if (use_region) {
- AddRegionBrushes();
- }
- idMapFile map;
- world_entity->origin.Zero();
- idMapEntity *mapentity = EntityToMapEntity(world_entity, use_region, &dlg);
- dlg.SetText("Saving worldspawn...");
- map.AddEntity(mapentity);
- if ( use_region ) {
- idStr buf;
- sprintf( buf, "{\n\"classname\" \"info_player_start\"\n\"origin\"\t \"%i %i %i\"\n\"angle\"\t \"%i\"\n}\n",
- (int)g_pParentWnd->GetCamera()->Camera().origin[0],
- (int)g_pParentWnd->GetCamera()->Camera().origin[1],
- (int)g_pParentWnd->GetCamera()->Camera().origin[2],
- (int)g_pParentWnd->GetCamera()->Camera().angles[YAW] );
- idLexer src( LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
- src.LoadMemory( buf, buf.Length(), "regionbuf" );
- idMapEntity *playerstart = idMapEntity::Parse( src );
- map.AddEntity( playerstart );
- }
- count = -1;
- for ( e = entities.next; e != &entities; e = next ) {
- count++;
- next = e->next;
- if (e->brushes.onext == &e->brushes) {
- Entity_Free(e); // no brushes left, so remove it
- }
- else {
- if (use_region) {
- for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
- if (!Map_IsBrushFiltered(b)) {
- break; // got one
- }
- }
- if (b == &e->brushes) {
- continue; // nothing visible
- }
- }
- idVec3 origin;
- if (!GetVectorForKey(e, "origin", origin)) {
- idStr text;
- VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin);
- sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
- SetKeyValue(e, "origin", text);
- }
- if (use_region && !idStr::Icmp(ValueForKey(e, "classname"), "info_player_start")) {
- continue;
- }
-
- idStr classname = e->epairs.GetString("classname");
- sprintf(status, "Saving entity %i (%s)...", count, classname.c_str());
- dlg.SetText(status);
- map.AddEntity(EntityToMapEntity(e, use_region, &dlg));
- count++;
- }
- }
- mapFile.StripFileExtension();
- idStr mapExt = (use_region) ? ".reg" : ".map";
- sprintf(status, "Writing file %s.%s...", mapFile.c_str(), mapExt.c_str());
- dlg.SetText(status);
- map.Write(mapFile, mapExt, !(autosave || localFile));
- mapModified = 0;
- if (use_region) {
- RemoveRegionBrushes();
- }
- if (!strstr(temp, "autosave")) {
- Sys_SetTitle(temp);
- }
- Sys_Status("Saved.\n", 0);
- return true;
- }
- /*
- =======================================================================================================================
- Map_New
- =======================================================================================================================
- */
- void Map_New(void) {
- common->Printf("Map_New\n");
- Map_Free();
- Patch_Cleanup();
- g_Inspectors->entityDlg.SetEditEntity ( NULL );
- world_entity = Entity_New();
- 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();
- Sys_UpdateWindows(W_ALL);
- mapModified = 0;
- g_qeglobals.mapVersion = MAP_VERSION;
- }
- bool region_active;
- idVec3 region_mins(MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD);
- idVec3 region_maxs(MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD);
- brush_t *region_sides[6];
- /*
- =======================================================================================================================
- AddRegionBrushes a regioned map will have temp walls put up at the region boundary
- =======================================================================================================================
- */
- void AddRegionBrushes(void) {
- idVec3 mins, maxs;
- int i;
- texdef_t td;
- if (!region_active) {
- return;
- }
- memset(&td, 0, sizeof(td));
- td = g_qeglobals.d_texturewin.texdef;
- // strcpy (td.name, "REGION");
- td.SetName("textures/REGION");
- const int REGION_WIDTH = 1024;
- mins[0] = region_mins[0] - REGION_WIDTH;
- maxs[0] = region_mins[0] + 1;
- mins[1] = region_mins[1] - REGION_WIDTH;
- maxs[1] = region_maxs[1] + REGION_WIDTH;
- 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] + REGION_WIDTH;
- region_sides[1] = Brush_Create(mins, maxs, &td);
- mins[0] = region_mins[0] - REGION_WIDTH;
- maxs[0] = region_maxs[0] + REGION_WIDTH;
- mins[1] = region_mins[1] - REGION_WIDTH;
- 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] + REGION_WIDTH;
- region_sides[3] = Brush_Create(mins, maxs, &td);
- mins = region_mins;
- maxs = region_maxs;
- maxs[2] = mins[2] + REGION_WIDTH;
- region_sides[4] = Brush_Create(mins, maxs, &td);
- mins = region_mins;
- maxs = region_maxs;
- mins[2] = maxs[2] - REGION_WIDTH;
- region_sides[5] = Brush_Create(mins, maxs, &td);
- for (i = 0; i < 6; 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 < 6; i++) {
- Brush_Free(region_sides[i]);
- }
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool Map_IsBrushFiltered(brush_t *b) {
- int i;
- if (!region_active) {
- return false;
- }
- 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_Status("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;
- Patch_Deselect();
- // 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(idStr &rStr) {
- // make a unique target value
- int maxtarg = 0;
- for (entity_t * e = entities.next; e != &entities; e = e->next) {
- const char *tn = ValueForKey(e, "name");
- 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;
- }
- }
- }
- }
-
- sprintf(rStr, "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, bool renameEntities) {
- 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;
- g_qeglobals.mapVersion = 1.0;
- if (GetToken(true)) {
- if (stricmp(token, "Version") == 0) {
- GetToken(false);
- g_qeglobals.mapVersion = atof(token);
- common->Printf("Map version: %1.2f\n", g_qeglobals.mapVersion);
- } else {
- UngetToken();
- }
- }
- idDict RemappedNames; // since I can't use "map <string, string>"... sigh. So much for STL...
- 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)) {
- idStr key;
- UniqueTargetName(key);
- strKey = key;
- mapStr.SetAt(str, strKey);
- }
- strTarget = strKey;
- SetKeyValue(ent, "target", strTarget.GetBuffer(0));
- }
- }
- /*
- * str = ValueForKey(ent, "name"); if (str.GetLength() > 0) { if
- * (FindEntity("name", str.GetBuffer(0))) { if (!mapStr.Lookup(str, strKey)) {
- * UniqueTargetName(strKey); mapStr.SetAt(str, strKey); } Entity_SetName(ent,
- * strKey.GetBuffer(0)); } }
- */
- CString cstrNameOld = ValueForKey(ent, "name");
- Entity_Name(ent, renameEntities);
- CString cstrNameNew = ValueForKey(ent, "name");
- if (cstrNameOld != cstrNameNew)
- {
- RemappedNames.Set(cstrNameOld, cstrNameNew);
- }
- //
- // 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);
- }
- }
- }
- // now iterate through the remapped names, and see if there are any target-connections that need remaking...
- //
- // (I could probably write this in half the size with STL, but WTF, work with what we have...)
- //
- int iNumKeyVals = RemappedNames.GetNumKeyVals();
- for (int iKeyVal=0; iKeyVal < iNumKeyVals; iKeyVal++)
- {
- const idKeyValue *pKeyVal = RemappedNames.GetKeyVal( iKeyVal );
- LPCSTR psOldName = pKeyVal->GetKey().c_str();
- LPCSTR psNewName = pKeyVal->GetValue().c_str();
- entity_t *pEntOld = FindEntity("name", psOldName); // original ent we cloned from
- entity_t *pEntNew = FindEntity("name", psNewName); // cloned ent
- if (pEntOld && pEntNew)
- {
- CString cstrTargetNameOld = ValueForKey(pEntOld, "target");
- if (!cstrTargetNameOld.IsEmpty())
- {
- // ok, this ent was targeted at another ent, so it's clone needs updating to point to
- // the clone of that target, so...
- //
- entity_t *pEntOldTarget = FindEntity("name", cstrTargetNameOld);
- if ( pEntOldTarget )
- {
- LPCSTR psNewTargetName = RemappedNames.GetString( cstrTargetNameOld );
- if (psNewTargetName && psNewTargetName[0])
- {
- SetKeyValue(pEntNew, "target", psNewTargetName);
- }
- }
- }
- }
- }
- }
- //
- // ::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();
- mapModified = 1;
- Undo_End();
- }
- //
- // =======================================================================================================================
- // Map_ImportFile
- // =======================================================================================================================
- //
- void Map_ImportFile(char *fileName) {
- char *buf;
- idStr temp;
- Sys_BeginWait();
- temp = fileName;
- temp.BackSlashesToSlashes();
- if (LoadFile( temp, (void **) &buf) != -1) {
- Map_ImportBuffer(buf);
- Mem_Free( buf );
- Map_BuildBrushData();
- }
- Sys_UpdateWindows(W_ALL);
- mapModified = 1;
- Sys_EndWait();
- }
- //
- // =======================================================================================================================
- // Map_SaveSelected Saves selected world brushes and whole entities with partial/full selections
- // =======================================================================================================================
- //
- void Map_SaveSelected(char *fileName) {
- entity_t *e, *next;
- FILE *f;
- idStr temp;
- int count;
- temp = fileName;
- temp.BackSlashesToSlashes();
- f = fopen(temp, "w");
- if ( !f ) {
- common->Printf( "ERROR!!!! Couldn't open %s\n", temp.c_str() );
- return;
- }
- // write version
- g_qeglobals.mapVersion = MAP_VERSION;
- fprintf( f, "Version %1.2f\n", MAP_VERSION );
- // write world entity second
- world_entity->origin.Zero();
- 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 version
- g_qeglobals.mapVersion = MAP_VERSION;
- MemFile_fprintf(pMemFile, "Version %1.2f\n", MAP_VERSION);
- // write world entity first
- world_entity->origin.Zero();
- 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);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- /*
- ================
- WriteFileString
- ================
- */
- bool WriteFileString( FILE *fp, char *string, ... ) {
- long i;
- unsigned long u;
- double f;
- char *str;
- idStr buf;
- va_list argPtr;
- va_start( argPtr, string );
- while( *string ) {
- switch( *string ) {
- case '%':
- string++;
- while ( (*string >= '0' && *string <= '9') ||
- *string == '.' || *string == '-' || *string == '+' || *string == '#') {
- string++;
- }
- switch( *string ) {
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- f = va_arg( argPtr, double );
- sprintf( buf, "%1.10f", f );
- buf.StripTrailing( '0' );
- buf.StripTrailing( '.' );
- fprintf( fp, "%s", buf.c_str() );
- break;
- case 'd':
- case 'i':
- i = va_arg( argPtr, long );
- fprintf( fp, "%d", i );
- break;
- case 'u':
- u = va_arg( argPtr, unsigned long );
- fprintf( fp, "%u", u );
- break;
- case 'o':
- u = va_arg( argPtr, unsigned long );
- fprintf( fp, "%o", u );
- break;
- case 'x':
- u = va_arg( argPtr, unsigned long );
- fprintf( fp, "%x", u );
- break;
- case 'X':
- u = va_arg( argPtr, unsigned long );
- fprintf( fp, "%X", u );
- break;
- case 'c':
- i = va_arg( argPtr, long );
- fprintf( fp, "%c", (char) i );
- break;
- case 's':
- str = va_arg( argPtr, char * );
- fprintf( fp, "%s", str );
- break;
- case '%':
- fprintf( fp, "%%" );
- break;
- default:
- common->Error( "WriteFileString: invalid %%%c", *string );
- break;
- }
- string++;
- break;
- case '\\':
- string++;
- switch( *string ) {
- case 't':
- fprintf( fp, "\t" );
- break;
- case 'n':
- fprintf( fp, "\n" );
- default:
- common->Error( "WriteFileString: unknown escape character \'%c\'", *string );
- break;
- }
- string++;
- break;
- default:
- fprintf( fp, "%c", *string );
- string++;
- break;
- }
- }
- va_end( argPtr );
- return true;
- }
- /*
- ================
- MemFile_fprintf
- ================
- */
- void MemFile_fprintf( CMemFile *pMemFile, const char *string, ... ) {
- char Buffer[4096];
- long i;
- unsigned long u;
- double f;
- char *str;
- idStr buf, out;
- va_list argPtr;
- char *buff = Buffer;
- va_start( argPtr, string );
- while( *string ) {
- switch( *string ) {
- case '%':
- string++;
- while ( (*string >= '0' && *string <= '9') ||
- *string == '.' || *string == '-' || *string == '+' || *string == '#') {
- string++;
- }
- switch( *string ) {
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- f = va_arg( argPtr, double );
- sprintf( buf, "%1.10f", f );
- buf.StripTrailing( '0' );
- buf.StripTrailing( '.' );
- sprintf( buff, "%s", buf.c_str() );
- break;
- case 'd':
- case 'i':
- i = va_arg( argPtr, long );
- sprintf( buff, "%d", i );
- break;
- case 'u':
- u = va_arg( argPtr, unsigned long );
- sprintf( buff, "%u", u );
- break;
- case 'o':
- u = va_arg( argPtr, unsigned long );
- sprintf( buff, "%o", u );
- break;
- case 'x':
- u = va_arg( argPtr, unsigned long );
- sprintf( buff, "%x", u );
- break;
- case 'X':
- u = va_arg( argPtr, unsigned long );
- sprintf( buff, "%X", u );
- break;
- case 'c':
- i = va_arg( argPtr, long );
- sprintf( buff, "%c", (char) i );
- break;
- case 's':
- str = va_arg( argPtr, char * );
- sprintf( buff, "%s", str );
- break;
- case '%':
- sprintf( buff, "%%" );
- break;
- default:
- common->Error( "MemFile_fprintf: invalid %%%c", *string );
- break;
- }
- string++;
- break;
- case '\\':
- string++;
- switch( *string ) {
- case 't':
- sprintf( buff, "\t" );
- break;
- case 'n':
- sprintf( buff, "\n" );
- default:
- common->Error( "MemFile_fprintf: unknown escape character \'%c\'", *string );
- break;
- }
- string++;
- break;
- default:
- sprintf( buff, "%c", *string );
- string++;
- break;
- }
- buff = Buffer + strlen(Buffer);
- }
- va_end( argPtr );
- out = Buffer;
- pMemFile->Write( out.c_str(), out.Length() );
- }
|