/* =========== 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] = g_MaxWorldCoord - 64; region_mins[i] = g_MinWorldCoord + 64; } 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 ); b->bFiltered = FilterBrush( b ); } Sys_UpdateWindows( W_ALL ); }
/* ======================================================================================================================= 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); }
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; }
/* ======================================================================================================================= ======================================================================================================================= */ 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 ); }
/*! filters out the region brushes if necessary returns true if this entity as a whole is out of the region (if all brushes are filtered out, then the entity will be completely dropped .. except if it's worldspawn of course) */ bool FilterChildren( entity_t *ent, bool bRegionOnly = false, bool bSelectedOnly = false ){ if ( ent->brushes.onext == &ent->brushes ) { return false; } // entity without a brush, ignore it... this can be caused by Undo // filter fixedsize ents by their eclass bounding box // don't add their brushes if ( ent->eclass->fixedsize ) { if ( bSelectedOnly && !IsBrushSelected( ent->brushes.onext ) ) { return false; } if ( bRegionOnly && region_active ) { for ( int i = 0 ; i < 3 ; i++ ) { if ( ( ent->origin[i] + ent->eclass->mins[i] ) > region_maxs[i] ) { return false; } if ( ( ent->origin[i] + ent->eclass->maxs[i] ) < region_mins[i] ) { return false; } } } } else { for ( brush_t *b = ent->brushes.onext ; b != &ent->brushes ; b = b->onext ) { // set flag to use brushprimit_texdef if ( g_qeglobals.m_bBrushPrimitMode ) { b->bBrushDef = true; } else{ b->bBrushDef = false; } // add brush, unless it's excluded by region if ( !( bRegionOnly && Map_IsBrushFiltered( b ) ) && !( bSelectedOnly && !IsBrushSelected( b ) ) ) { ( (CPtrArray*)ent->pData )->Add( b ); } } if ( ( (CPtrArray*)ent->pData )->GetSize() <= 0 ) { return false; } } return true; }
/* ======================================================================================================================= 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; }
/* ======================================================================================================================= Entity_Write ======================================================================================================================= */ void Entity_Write(entity_t *e, FILE *f, bool use_region) { brush_t *b; idVec3 origin; char text[128]; int count; // if none of the entities brushes are in the region, don't write the entity at all if (use_region) { // in region mode, save the camera position as playerstart if (!strcmp(ValueForKey(e, "classname"), "info_player_start")) { fprintf(f, "{\n"); fprintf(f, "\"classname\" \"info_player_start\"\n"); fprintf ( f, "\"origin\" \"%i %i %i\"\n", (int)g_pParentWnd->GetCamera()->Camera().origin[0], (int)g_pParentWnd->GetCamera()->Camera().origin[1], (int)g_pParentWnd->GetCamera()->Camera().origin[2] ); fprintf(f, "\"angle\" \"%i\"\n", (int)g_pParentWnd->GetCamera()->Camera().angles[YAW]); fprintf(f, "}\n"); return; } for (b = e->brushes.onext; b != &e->brushes; b = b->onext) { if (!Map_IsBrushFiltered(b)) { break; // got one } } if (b == &e->brushes) { return; // nothing visible } } if (e->eclass->nShowFlags & ECLASS_PLUGINENTITY) { // NOTE: the whole brush placement / origin stuff is a mess VectorCopy(e->origin, origin); sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); SetKeyValue(e, "origin", text); } // if fixedsize, calculate a new origin based on the current brush position else if (e->eclass->fixedsize || EntityHasModel(e)) { if (!GetVectorForKey(e, "origin", origin)) { 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); } } fprintf(f, "{\n"); count = e->epairs.GetNumKeyVals(); for (int j = 0; j < count; j++) { fprintf(f, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str()); } if (!EntityHasModel(e)) { count = 0; for (b = e->brushes.onext; b != &e->brushes; b = b->onext) { if (e->eclass->fixedsize && !b->entityModel) { continue; } if (!use_region || !Map_IsBrushFiltered(b)) { fprintf(f, "// brush %i\n", count); count++; Brush_Write( b, f, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) ); } } } fprintf(f, "}\n"); }
/* ============ Entity_Write ============ */ void Entity_Write (entity_t *e, FILE *f, qboolean use_region) { epair_t *ep; brush_t *b; vec3_t origin; char text[128]; int count; // if none of the entities brushes are in the region, // don't write the entity at all if (use_region) { // in region mode, save the camera position as playerstart if ( !strcmp(ValueForKey (e, "classname"), "info_player_start") ) { // see if this ent is entirely within the region first... // bool bWithinRegion = true; for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) if (Map_IsBrushFiltered(b)) bWithinRegion = false; // if the player_start is NOT within the region, then use the camera position instead, else keep it... // if (!bWithinRegion || !GetYesNo("\"player_info_start\" found within region, keep it?\n\n( 'NO' will generate a new one from the current camera position )")) { fprintf (f, "{\n"); fprintf (f, "\"classname\" \"info_player_start\"\n"); fprintf (f, "\"origin\" \"%i %i %i\"\n", (int)g_pParentWnd->GetCamera()->Camera().origin[0], (int)g_pParentWnd->GetCamera()->Camera().origin[1], (int)g_pParentWnd->GetCamera()->Camera().origin[2]); fprintf (f, "\"angle\" \"%i\"\n", (int)g_pParentWnd->GetCamera()->Camera().angles[YAW]); fprintf (f, "}\n"); return; } } for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) if (!Map_IsBrushFiltered(b)) break; // got one if (b == &e->brushes) return; // nothing visible } // if fixedsize, calculate a new origin based on the current // brush position if (e->eclass->fixedsize) { #ifdef SOF // I know these 2 do the same thing, but if that VectorSubtract ever gets re-instated it'll break ours -slc if (strnicmp(e->eclass->name, "misc_", 5) == 0 || strnicmp(e->eclass->name, "light_", 6) == 0 || strnicmp(e->eclass->name, "m_", 2) == 0 || strnicmp(e->eclass->name, "item_weapon_", 12)== 0 || strnicmp(e->eclass->name, "item_ammo_", 10)== 0 ) { VectorCopy(e->origin, origin); } #else if (strnicmp(e->eclass->name, "misc_model",10) == 0 && e->md3Class != NULL) { VectorCopy(e->origin, origin); //VectorSubtract (e->brushes.onext->mins, e->md3Class->mins, origin); } #endif else { 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); } fprintf (f, "{\n"); for (ep = e->epairs ; ep ; ep=ep->next) fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value); if (!e->eclass->fixedsize) { count = 0; for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) { if (!use_region || !Map_IsBrushFiltered (b)) { fprintf (f, "// brush %i\n", count); count++; Brush_Write (b, f); } } } fprintf (f, "}\n"); }