2007-06-14 23:31:57 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program 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 .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Text ;
using System.Windows.Forms ;
using System.IO ;
using System.Reflection ;
using CodeImp.DoomBuilder.Interface ;
using CodeImp.DoomBuilder.IO ;
using CodeImp.DoomBuilder.Map ;
2007-06-15 18:30:55 +00:00
using CodeImp.DoomBuilder.Editing ;
using System.Diagnostics ;
using CodeImp.DoomBuilder.Rendering ;
2007-10-05 11:17:58 +00:00
using CodeImp.DoomBuilder.Data ;
2007-10-14 21:31:45 +00:00
using CodeImp.DoomBuilder.Controls ;
2007-06-14 23:31:57 +00:00
#endregion
namespace CodeImp.DoomBuilder
{
internal class MapManager : IDisposable
{
#region = = = = = = = = = = = = = = = = = = Constants
2007-10-13 14:05:45 +00:00
// Map header name in temporary file
2007-06-24 18:56:43 +00:00
private const string TEMP_MAP_HEADER = "TEMPMAP" ;
2007-10-13 14:05:45 +00:00
private const string BUILD_MAP_HEADER = "MAP01" ;
2007-10-14 15:44:55 +00:00
public const string CONFIG_MAP_HEADER = "~MAP" ;
2007-06-24 18:56:43 +00:00
2007-10-13 14:05:45 +00:00
// Save modes
public const int SAVE_NORMAL = 0 ;
public const int SAVE_AS = 1 ;
public const int SAVE_INTO = 2 ;
public const int SAVE_TEST = 3 ;
2007-06-14 23:31:57 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Status
private bool changed ;
// Map information
private string filetitle ;
private string filepathname ;
2007-10-13 14:05:45 +00:00
private string temppath ;
2007-10-05 11:17:58 +00:00
private MapSet map ;
2007-10-13 14:05:45 +00:00
private MapSetIO io ;
2007-06-14 23:31:57 +00:00
private MapOptions options ;
2007-09-27 22:55:03 +00:00
private ConfigurationInfo configinfo ;
2007-06-14 23:31:57 +00:00
private Configuration config ;
2007-10-20 12:34:27 +00:00
private GameConfigurationCache configsettings ;
2007-10-05 11:17:58 +00:00
private DataManager data ;
2007-06-15 18:30:55 +00:00
private EditMode mode ;
2007-09-17 21:22:46 +00:00
private D3DGraphics graphics ;
2007-06-24 18:56:43 +00:00
private WAD tempwad ;
2007-10-20 12:34:27 +00:00
private MapSelection selection ;
2007-06-15 18:30:55 +00:00
2007-06-14 23:31:57 +00:00
// Disposing
private bool isdisposed = false ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public string FilePathName { get { return filepathname ; } }
public string FileTitle { get { return filetitle ; } }
2007-10-13 14:05:45 +00:00
public string TempPath { get { return temppath ; } }
2007-06-14 23:31:57 +00:00
public MapOptions Options { get { return options ; } }
2007-10-05 11:17:58 +00:00
public MapSet Map { get { return map ; } }
2007-06-15 18:30:55 +00:00
public EditMode Mode { get { return mode ; } }
2007-10-07 22:21:47 +00:00
public DataManager Data { get { return data ; } }
2007-10-14 21:31:45 +00:00
public bool IsChanged { get { return changed ; } set { changed | = value ; } }
2007-06-14 23:31:57 +00:00
public bool IsDisposed { get { return isdisposed ; } }
2007-09-17 21:22:46 +00:00
public D3DGraphics Graphics { get { return graphics ; } }
2007-10-07 22:21:47 +00:00
public Configuration Configuration { get { return config ; } }
2007-10-20 12:34:27 +00:00
public GameConfigurationCache Settings { get { return configsettings ; } }
public MapSelection Selection { get { return selection ; } }
2007-06-15 22:38:42 +00:00
2007-06-14 23:31:57 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
2007-06-26 08:47:19 +00:00
// Constructor
2007-06-15 18:30:55 +00:00
public MapManager ( )
2007-06-14 23:31:57 +00:00
{
// We have no destructor
GC . SuppressFinalize ( this ) ;
2007-10-20 12:34:27 +00:00
// Basic objects
selection = new MapSelection ( ) ;
2007-06-14 23:31:57 +00:00
}
// Diposer
public void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
2007-10-20 19:50:03 +00:00
// Change to no mode
ChangeMode ( null ) ;
2007-10-14 21:31:45 +00:00
// Unbind any methods
ActionAttribute . UnbindMethods ( this ) ;
2007-06-14 23:31:57 +00:00
// Dispose
2007-10-05 11:17:58 +00:00
General . WriteLogLine ( "Unloading data resources..." ) ;
2007-06-14 23:31:57 +00:00
data . Dispose ( ) ;
2007-10-05 11:17:58 +00:00
General . WriteLogLine ( "Closing temporary file..." ) ;
tempwad . Dispose ( ) ;
General . WriteLogLine ( "Unloading map data..." ) ;
map . Dispose ( ) ;
General . WriteLogLine ( "Stopping graphics device..." ) ;
2007-06-15 18:30:55 +00:00
graphics . Dispose ( ) ;
2007-10-20 12:34:27 +00:00
2007-06-24 18:56:43 +00:00
// Remove temp file
2007-10-13 14:05:45 +00:00
General . WriteLogLine ( "Removing temporary directory..." ) ;
try { Directory . Delete ( temppath , true ) ; } catch ( Exception e )
{
General . WriteLogLine ( e . GetType ( ) . Name + ": " + e . Message ) ;
General . WriteLogLine ( "Failed to remove temporary directory!" ) ;
}
2007-06-24 18:56:43 +00:00
2007-10-20 12:34:27 +00:00
// Basic objects
selection . Dispose ( ) ;
2007-06-24 18:56:43 +00:00
// We may spend some time to clean things up here
GC . Collect ( ) ;
2007-06-14 23:31:57 +00:00
// Done
isdisposed = true ;
}
}
#endregion
2007-10-14 15:44:55 +00:00
#region = = = = = = = = = = = = = = = = = = New / Open
2007-06-15 18:30:55 +00:00
// Initializes for a new map
public bool InitializeNewMap ( MapOptions options )
{
2007-10-05 10:00:15 +00:00
string tempfile ;
2007-10-13 14:05:45 +00:00
string iointerface ;
2007-10-05 10:00:15 +00:00
2007-06-15 18:30:55 +00:00
// Apply settings
this . filetitle = "unnamed.wad" ;
this . filepathname = "" ;
this . changed = false ;
this . options = options ;
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Creating new map '" + options . CurrentName + "' with configuration '" + options . ConfigFile + "'" ) ;
2007-10-13 14:05:45 +00:00
// Create temporary path
temppath = General . MakeTempDirname ( ) ;
Directory . CreateDirectory ( temppath ) ;
General . WriteLogLine ( "Temporary directory: " + temppath ) ;
2007-07-07 09:40:34 +00:00
// Initiate graphics
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Initializing graphics device..." ) ;
2007-09-17 21:22:46 +00:00
graphics = new D3DGraphics ( General . MainWindow . Display ) ;
2007-07-07 09:40:34 +00:00
if ( ! graphics . Initialize ( ) ) return false ;
// Load game configuration
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Loading game configuration..." ) ;
2007-09-27 22:55:03 +00:00
configinfo = General . GetConfigurationInfo ( options . ConfigFile ) ;
2007-06-15 18:30:55 +00:00
config = General . LoadGameConfiguration ( options . ConfigFile ) ;
2007-10-20 12:34:27 +00:00
configsettings = new GameConfigurationCache ( config ) ;
2007-06-15 18:30:55 +00:00
2007-07-07 09:40:34 +00:00
// Create map data
2007-10-05 11:17:58 +00:00
map = new MapSet ( ) ;
2007-07-07 09:40:34 +00:00
2007-06-26 08:47:19 +00:00
// Create temp wadfile
2007-10-13 14:05:45 +00:00
tempfile = General . MakeTempFilename ( temppath ) ;
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Creating temporary file: " + tempfile ) ;
tempwad = new WAD ( tempfile ) ;
2007-10-13 14:05:45 +00:00
// Read the map from temp file
iointerface = config . ReadSetting ( "formatinterface" , "" ) ;
General . WriteLogLine ( "Initializing map format interface " + iointerface + "..." ) ;
2007-10-13 16:58:55 +00:00
io = MapSetIO . Create ( iointerface , tempwad , this ) ;
2007-06-26 08:47:19 +00:00
2007-10-14 17:48:15 +00:00
// Create required lumps
General . WriteLogLine ( "Creating map data structures..." ) ;
tempwad . Insert ( TEMP_MAP_HEADER , 0 , 0 ) ;
io . Write ( map , TEMP_MAP_HEADER , 1 ) ;
CreateRequiredLumps ( tempwad , TEMP_MAP_HEADER ) ;
2007-10-05 11:17:58 +00:00
// Load data manager
General . WriteLogLine ( "Loading data resources..." ) ;
data = new DataManager ( ) ;
data . Load ( configinfo . Resources , options . Resources ) ;
2007-10-14 21:31:45 +00:00
// Bind any methods
ActionAttribute . BindMethods ( this ) ;
2007-06-15 18:30:55 +00:00
// Set default mode
2007-10-20 01:04:47 +00:00
ChangeMode ( new VerticesMode ( ) ) ;
2007-06-15 18:30:55 +00:00
// Success
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Map creation done" ) ;
2007-06-15 18:30:55 +00:00
return true ;
}
2007-06-16 19:53:51 +00:00
// Initializes for an existing map
public bool InitializeOpenMap ( string filepathname , MapOptions options )
{
2007-06-24 18:56:43 +00:00
WAD mapwad ;
2007-10-05 10:00:15 +00:00
string tempfile ;
string iointerface ;
2007-10-05 11:17:58 +00:00
DataLocation maplocation ;
2007-06-24 18:56:43 +00:00
2007-06-16 19:53:51 +00:00
// Apply settings
this . filetitle = Path . GetFileName ( filepathname ) ;
this . filepathname = filepathname ;
this . changed = false ;
this . options = options ;
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Opening map '" + options . CurrentName + "' with configuration '" + options . ConfigFile + "'" ) ;
2007-10-13 14:05:45 +00:00
// Create temporary path
temppath = General . MakeTempDirname ( ) ;
Directory . CreateDirectory ( temppath ) ;
General . WriteLogLine ( "Temporary directory: " + temppath ) ;
2007-07-07 09:40:34 +00:00
// Initiate graphics
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Initializing graphics device..." ) ;
2007-09-17 21:22:46 +00:00
graphics = new D3DGraphics ( General . MainWindow . Display ) ;
2007-07-07 09:40:34 +00:00
if ( ! graphics . Initialize ( ) ) return false ;
// Load game configuration
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Loading game configuration..." ) ;
configinfo = General . GetConfigurationInfo ( options . ConfigFile ) ;
2007-06-16 19:53:51 +00:00
config = General . LoadGameConfiguration ( options . ConfigFile ) ;
2007-10-20 12:34:27 +00:00
configsettings = new GameConfigurationCache ( config ) ;
2007-06-16 19:53:51 +00:00
2007-07-07 09:40:34 +00:00
// Create map data
2007-10-05 11:17:58 +00:00
map = new MapSet ( ) ;
2007-07-07 09:40:34 +00:00
2007-06-24 18:56:43 +00:00
// Create temp wadfile
2007-10-13 14:05:45 +00:00
tempfile = General . MakeTempFilename ( temppath ) ;
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Creating temporary file: " + tempfile ) ;
tempwad = new WAD ( tempfile ) ;
2007-07-07 09:40:34 +00:00
2007-06-24 18:56:43 +00:00
// Now open the map file
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Opening source file: " + filepathname ) ;
2007-06-24 18:56:43 +00:00
mapwad = new WAD ( filepathname , true ) ;
// Copy the map lumps to the temp file
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Copying map lumps to temporary file..." ) ;
2007-06-24 18:56:43 +00:00
CopyLumpsByType ( mapwad , options . CurrentName , tempwad , TEMP_MAP_HEADER ,
true , true , true , true ) ;
// Close the map file
mapwad . Dispose ( ) ;
// Read the map from temp file
2007-10-05 10:00:15 +00:00
iointerface = config . ReadSetting ( "formatinterface" , "" ) ;
General . WriteLogLine ( "Initializing map format interface " + iointerface + "..." ) ;
2007-10-13 16:58:55 +00:00
io = MapSetIO . Create ( iointerface , tempwad , this ) ;
2007-10-13 14:05:45 +00:00
General . WriteLogLine ( "Reading map data structures from file..." ) ;
map = io . Read ( map , TEMP_MAP_HEADER ) ;
2007-06-16 19:53:51 +00:00
2007-07-07 09:40:34 +00:00
// Update structures
2007-10-05 11:17:58 +00:00
map . Update ( ) ;
// Load data manager
General . WriteLogLine ( "Loading data resources..." ) ;
data = new DataManager ( ) ;
maplocation = new DataLocation ( DataLocation . RESOURCE_WAD , filepathname , false , false ) ;
data . Load ( configinfo . Resources , options . Resources , maplocation ) ;
2007-10-14 21:31:45 +00:00
// Bind any methods
ActionAttribute . BindMethods ( this ) ;
2007-06-16 19:53:51 +00:00
// Set default mode
2007-10-20 01:04:47 +00:00
ChangeMode ( new VerticesMode ( ) ) ;
2007-06-16 19:53:51 +00:00
2007-10-20 01:04:47 +00:00
// Center map in screen
( General . Map . Mode as ClassicMode ) . CenterInScreen ( ) ;
2007-06-16 19:53:51 +00:00
// Success
2007-10-05 10:00:15 +00:00
General . WriteLogLine ( "Map loading done" ) ;
2007-06-16 19:53:51 +00:00
return true ;
}
2007-06-15 18:30:55 +00:00
#endregion
2007-10-13 14:05:45 +00:00
#region = = = = = = = = = = = = = = = = = = Save
// Initializes for an existing map
2007-10-14 15:44:55 +00:00
public bool SaveMap ( string newfilepathname , int savemode )
2007-10-13 14:05:45 +00:00
{
MapSet outputset ;
2007-10-14 21:31:45 +00:00
string nodebuildername , oldstatus , settingsfile ;
Configuration mapsettings ;
2007-10-14 15:44:55 +00:00
WAD targetwad ;
int index ;
2007-10-14 17:48:15 +00:00
bool includenodes ;
2007-10-14 21:35:49 +00:00
string origmapname ;
2007-10-14 17:48:15 +00:00
General . WriteLogLine ( "Saving map to file: " + newfilepathname ) ;
2007-10-13 14:05:45 +00:00
// Make a copy of the map data
outputset = map . Clone ( ) ;
// Do we need sidedefs compression?
if ( map . Sidedefs . Count > io . MaxSidedefs )
{
// Compress sidedefs
outputset . CompressSidedefs ( ) ;
// Check if it still doesnt fit
if ( map . Sidedefs . Count > io . MaxSidedefs )
{
// Problem! Can't save the map like this!
General . ShowErrorMessage ( "Unable to save the map: There are too many unique sidedefs!" , MessageBoxButtons . OK ) ;
return false ;
}
}
// TODO: Check for more limitations
// Write to temporary file
General . WriteLogLine ( "Writing map data structures to file..." ) ;
2007-10-14 15:44:55 +00:00
index = tempwad . FindLumpIndex ( TEMP_MAP_HEADER ) ;
if ( index = = - 1 ) index = 0 ;
io . Write ( outputset , TEMP_MAP_HEADER , index ) ;
2007-10-13 14:05:45 +00:00
// Get the corresponding nodebuilder
if ( savemode = = SAVE_TEST ) nodebuildername = configinfo . NodebuilderTest ;
else nodebuildername = configinfo . NodebuilderSave ;
// Build the nodes
2007-10-14 18:11:03 +00:00
oldstatus = General . MainWindow . GetCurrentSatus ( ) ;
General . MainWindow . DisplayStatus ( "Building map nodes..." ) ;
2007-10-13 14:05:45 +00:00
if ( ( nodebuildername ! = null ) & & ( nodebuildername ! = "" ) )
2007-10-14 18:11:03 +00:00
includenodes = BuildNodes ( nodebuildername , true ) ;
2007-10-14 17:48:15 +00:00
else
includenodes = false ;
2007-10-14 18:11:03 +00:00
General . MainWindow . DisplayStatus ( oldstatus ) ;
2007-10-13 14:05:45 +00:00
// Suspend data resources
data . Suspend ( ) ;
2007-10-15 05:08:39 +00:00
try
2007-10-14 17:48:15 +00:00
{
2007-10-15 05:08:39 +00:00
// Except when saving INTO another file,
// kill the target file if it is different from source file
if ( ( savemode ! = SAVE_INTO ) & & ( newfilepathname ! = filepathname ) )
{
// Kill target file
if ( File . Exists ( newfilepathname ) ) File . Delete ( newfilepathname ) ;
// Kill .dbs settings file
settingsfile = newfilepathname . Substring ( 0 , newfilepathname . Length - 4 ) + ".dbs" ;
if ( File . Exists ( settingsfile ) ) File . Delete ( settingsfile ) ;
}
2007-10-14 21:31:45 +00:00
2007-10-15 05:08:39 +00:00
// On Save AS we have to copy the previous file to the new file
if ( ( savemode = = SAVE_AS ) & & ( filepathname ! = "" ) )
{
// Copy if original file still exists
if ( File . Exists ( filepathname ) ) File . Copy ( filepathname , newfilepathname , true ) ;
}
// Open the target file
targetwad = new WAD ( newfilepathname ) ;
2007-10-14 17:48:15 +00:00
}
2007-10-15 05:08:39 +00:00
catch ( IOException )
2007-10-14 15:44:55 +00:00
{
2007-10-15 05:08:39 +00:00
General . ShowErrorMessage ( "IO Error while writing target file: " + newfilepathname + ". Please make sure the location is accessible and not in use by another program." , MessageBoxButtons . OK ) ;
data . Resume ( ) ;
General . WriteLogLine ( "Map saving failed" ) ;
return false ;
}
catch ( UnauthorizedAccessException )
{
General . ShowErrorMessage ( "Error while accessing target file: " + newfilepathname + ". Please make sure the location is accessible and not in use by another program." , MessageBoxButtons . OK ) ;
data . Resume ( ) ;
General . WriteLogLine ( "Map saving failed" ) ;
return false ;
2007-10-14 15:44:55 +00:00
}
2007-10-14 21:35:49 +00:00
// Determine original map name
if ( options . PreviousName ! = "" ) origmapname = options . PreviousName ;
else origmapname = options . CurrentName ;
2007-10-14 15:44:55 +00:00
// Copy map lumps to target file
2007-10-14 21:35:49 +00:00
CopyLumpsByType ( tempwad , TEMP_MAP_HEADER , targetwad , origmapname , true , true , includenodes , true ) ;
2007-10-14 15:44:55 +00:00
// Was the map lump name renamed?
if ( ( options . PreviousName ! = options . CurrentName ) & &
( options . PreviousName ! = "" ) )
{
General . WriteLogLine ( "Renaming map lump name from " + options . PreviousName + " to " + options . CurrentName ) ;
// Find the map header in target
index = targetwad . FindLumpIndex ( options . PreviousName ) ;
if ( index > - 1 )
{
// Rename the map lump name
targetwad . Lumps [ index ] . Rename ( options . CurrentName ) ;
options . PreviousName = "" ;
}
else
{
// Houston, we've got a problem!
General . ShowErrorMessage ( "Error renaming map lump name: the original map lump could not be found!" , MessageBoxButtons . OK ) ;
options . CurrentName = options . PreviousName ;
options . PreviousName = "" ;
}
}
// Done with the target file
targetwad . Dispose ( ) ;
2007-10-13 14:05:45 +00:00
// Resume data resources
data . Resume ( ) ;
2007-10-14 21:31:45 +00:00
try
{
// Open or create the map settings
settingsfile = newfilepathname . Substring ( 0 , newfilepathname . Length - 4 ) + ".dbs" ;
if ( File . Exists ( settingsfile ) )
mapsettings = new Configuration ( settingsfile , true ) ;
else
mapsettings = new Configuration ( true ) ;
// Write settings
mapsettings . WriteSetting ( "type" , "Doom Builder Map Settings Configuration" ) ;
mapsettings . WriteSetting ( "gameconfig" , options . ConfigFile ) ;
options . Resources . WriteToConfig ( mapsettings , "maps." + options . CurrentName + ".resources" ) ;
// Save settings
mapsettings . SaveConfiguration ( settingsfile ) ;
}
catch ( Exception e )
{
// Warning only
General . WriteLogLine ( "WARNING: " + e . GetType ( ) . Name + ": " + e . Message ) ;
General . WriteLogLine ( "WARNING: Could not write the map settings configuration file!" ) ;
}
// Was the map saved in a different file? And not for testing purpose?
if ( ( savemode ! = SAVE_TEST ) & & ( newfilepathname ! = filepathname ) )
{
// Keep new filename
filepathname = newfilepathname ;
filetitle = Path . GetFileName ( filepathname ) ;
// Changes saved
changed = false ;
// Reload resources
ReloadResources ( ) ;
}
2007-10-13 14:05:45 +00:00
// Success!
2007-10-14 17:48:15 +00:00
General . WriteLogLine ( "Map saving done" ) ;
2007-10-13 14:05:45 +00:00
return true ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Nodebuild
// This builds the nodes in the temproary file with the given configuration name
2007-10-14 18:11:03 +00:00
private bool BuildNodes ( string nodebuildername , bool failaswarning )
2007-10-13 14:05:45 +00:00
{
NodebuilderInfo nodebuilder ;
string tempfile1 , tempfile2 ;
bool lumpnodebuild , lumpallowempty , lumpscomplete ;
IDictionary maplumps ;
WAD buildwad ;
int srcindex ;
2007-10-14 18:11:03 +00:00
2007-10-13 14:05:45 +00:00
// Find the nodebuilder
nodebuilder = General . GetNodebuilderByName ( nodebuildername ) ;
if ( nodebuilder = = null )
{
// Problem! Can't find that nodebuilder!
2007-10-14 18:11:03 +00:00
General . ShowWarningMessage ( "Unable to build the nodes: The configured nodebuilder cannot be found.\nPlease check your game configuration settings!" , MessageBoxButtons . OK ) ;
2007-10-13 14:05:45 +00:00
return false ;
}
else
{
// Make a temporary file for the nodebuilder
tempfile1 = General . MakeTempFilename ( temppath ) ;
General . WriteLogLine ( "Creating temporary build file: " + tempfile1 ) ;
buildwad = new WAD ( tempfile1 ) ;
// Copy lumps to buildwad
General . WriteLogLine ( "Copying map lumps to temporary build file..." ) ;
CopyLumpsByType ( tempwad , TEMP_MAP_HEADER , buildwad , BUILD_MAP_HEADER , true , false , false , true ) ;
// Close buildwad
buildwad . Dispose ( ) ;
// Does the nodebuilder require an output file?
if ( nodebuilder . HasSpecialOutputFile )
{
// Make a temporary output file for the nodebuilder
tempfile2 = General . MakeTempFilename ( temppath ) ;
General . WriteLogLine ( "Creating temporary output file: " + tempfile2 ) ;
}
else
{
// Output file is same as input file
tempfile2 = tempfile1 ;
}
// Run the nodebuilder
if ( nodebuilder . Run ( temppath , Path . GetFileName ( tempfile1 ) , Path . GetFileName ( tempfile2 ) ) )
{
// Open the output file
buildwad = new WAD ( tempfile2 ) ;
// Find the map header in source
srcindex = buildwad . FindLumpIndex ( BUILD_MAP_HEADER ) ;
if ( srcindex > - 1 )
{
// Go for all the map lump names
lumpscomplete = true ;
maplumps = config . ReadSetting ( "maplumpnames" , new Hashtable ( ) ) ;
foreach ( DictionaryEntry ml in maplumps )
{
// Read lump settings from map config
lumpnodebuild = config . ReadSetting ( "maplumpnames." + ml . Key + ".nodebuild" , false ) ;
lumpallowempty = config . ReadSetting ( "maplumpnames." + ml . Key + ".allowempty" , false ) ;
// Check if this lump should exist
if ( lumpnodebuild & & ! lumpallowempty )
{
// Find the lump in the source
if ( buildwad . FindLump ( ml . Key . ToString ( ) , srcindex , srcindex + maplumps . Count + 2 ) = = null )
{
// Missing a lump!
lumpscomplete = false ;
break ;
}
}
}
}
else
{
// Cannot find header
lumpscomplete = false ;
}
// Output lumps complete?
if ( lumpscomplete )
{
// Copy nodebuilder lumps to temp file
General . WriteLogLine ( "Copying nodebuilder lumps to temporary file..." ) ;
CopyLumpsByType ( buildwad , BUILD_MAP_HEADER , tempwad , TEMP_MAP_HEADER , false , false , true , false ) ;
}
else
{
2007-10-14 18:11:03 +00:00
// Nodebuilder did not build the lumps!
if ( failaswarning )
General . ShowWarningMessage ( "Unable to build the nodes: The nodebuilder failed to build the expected data structures.\nThe map will be saved without the nodes." , MessageBoxButtons . OK ) ;
else
General . ShowErrorMessage ( "Unable to build the nodes: The nodebuilder failed to build the expected data structures." , MessageBoxButtons . OK ) ;
2007-10-13 14:05:45 +00:00
}
// Done with the build wad
buildwad . Dispose ( ) ;
// Remove temp files
General . WriteLogLine ( "Removing temporary files..." ) ;
if ( File . Exists ( tempfile1 ) ) File . Delete ( tempfile1 ) ;
if ( File . Exists ( tempfile2 ) ) File . Delete ( tempfile2 ) ;
return lumpscomplete ;
}
else
{
// Remove temp files
General . WriteLogLine ( "Removing temporary files..." ) ;
if ( File . Exists ( tempfile1 ) ) File . Delete ( tempfile1 ) ;
if ( File . Exists ( tempfile2 ) ) File . Delete ( tempfile2 ) ;
return false ;
}
}
}
#endregion
2007-10-14 15:44:55 +00:00
#region = = = = = = = = = = = = = = = = = = Lumps
2007-06-15 18:30:55 +00:00
2007-10-14 17:48:15 +00:00
// This creates empty lumps for those required
private void CreateRequiredLumps ( WAD target , string mapname )
{
int headerindex , insertindex , targetindex ;
string lumpname ;
bool lumprequired ;
IDictionary maplumps ;
// Find the map header in target
headerindex = target . FindLumpIndex ( mapname ) ;
if ( headerindex = = - 1 )
{
// If this header doesnt exists in the target
// then insert at the end of the target
headerindex = target . Lumps . Count ;
}
// Begin inserting at target header index
insertindex = headerindex ;
// Go for all the map lump names
maplumps = config . ReadSetting ( "maplumpnames" , new Hashtable ( ) ) ;
foreach ( DictionaryEntry ml in maplumps )
{
// Read lump settings from map config
lumprequired = config . ReadSetting ( "maplumpnames." + ml . Key + ".required" , false ) ;
// Check if this lump is required
if ( lumprequired )
{
// Get the lump name
lumpname = ml . Key . ToString ( ) ;
if ( lumpname = = CONFIG_MAP_HEADER ) lumpname = mapname ;
// Check if the lump is missing at the target
targetindex = FindSpecificLump ( target , lumpname , headerindex , mapname , maplumps ) ;
if ( targetindex = = - 1 )
{
// Determine target index
insertindex + + ;
if ( insertindex > target . Lumps . Count ) insertindex = target . Lumps . Count ;
// Create new, emtpy lump
General . WriteLogLine ( lumpname + " is required! Created empty lump." ) ;
target . Insert ( lumpname , insertindex , 0 ) ;
}
else
{
// Move insert index
insertindex = targetindex ;
}
}
}
}
2007-06-24 18:56:43 +00:00
// This copies specific map lumps from one WAD to another
private void CopyLumpsByType ( WAD source , string sourcemapname ,
WAD target , string targetmapname ,
bool copyrequired , bool copyblindcopy ,
bool copynodebuild , bool copyscript )
2007-06-15 18:30:55 +00:00
{
2007-06-24 18:56:43 +00:00
bool lumprequired , lumpblindcopy , lumpnodebuild ;
2007-10-14 15:44:55 +00:00
string lumpscript , srclumpname , tgtlumpname ;
int srcheaderindex , tgtheaderindex , targetindex , sourceindex , lumpindex ;
2007-06-24 18:56:43 +00:00
IDictionary maplumps ;
Lump lump , newlump ;
2007-06-15 18:30:55 +00:00
2007-06-24 18:56:43 +00:00
// Find the map header in target
2007-10-14 15:44:55 +00:00
tgtheaderindex = target . FindLumpIndex ( targetmapname ) ;
if ( tgtheaderindex = = - 1 )
2007-10-13 14:05:45 +00:00
{
// If this header doesnt exists in the target
// then insert at the end of the target
2007-10-14 15:44:55 +00:00
tgtheaderindex = target . Lumps . Count ;
2007-10-13 14:05:45 +00:00
}
2007-10-14 15:44:55 +00:00
// Begin inserting at target header index
targetindex = tgtheaderindex ;
2007-06-24 18:56:43 +00:00
// Find the map header in source
2007-10-14 15:44:55 +00:00
srcheaderindex = source . FindLumpIndex ( sourcemapname ) ;
if ( srcheaderindex > - 1 )
2007-06-15 18:30:55 +00:00
{
2007-06-24 18:56:43 +00:00
// Copy the map header from source to target
2007-10-14 15:44:55 +00:00
//newlump = target.Insert(targetmapname, tgtindex++, source.Lumps[srcindex].Length);
//source.Lumps[srcindex].CopyTo(newlump);
2007-06-24 18:56:43 +00:00
// Go for all the map lump names
maplumps = config . ReadSetting ( "maplumpnames" , new Hashtable ( ) ) ;
foreach ( DictionaryEntry ml in maplumps )
{
// Read lump settings from map config
lumprequired = config . ReadSetting ( "maplumpnames." + ml . Key + ".required" , false ) ;
lumpblindcopy = config . ReadSetting ( "maplumpnames." + ml . Key + ".blindcopy" , false ) ;
lumpnodebuild = config . ReadSetting ( "maplumpnames." + ml . Key + ".nodebuild" , false ) ;
lumpscript = config . ReadSetting ( "maplumpnames." + ml . Key + ".script" , "" ) ;
// Check if this lump should be copied
if ( ( lumprequired & & copyrequired ) | | ( lumpblindcopy & & copyblindcopy ) | |
2007-10-19 14:27:46 +00:00
( lumpnodebuild & & copynodebuild ) | | ( ( lumpscript . Length ! = 0 ) & & copyscript ) )
2007-06-24 18:56:43 +00:00
{
2007-10-14 15:44:55 +00:00
// Get the lump name
srclumpname = ml . Key . ToString ( ) ;
tgtlumpname = ml . Key . ToString ( ) ;
if ( srclumpname = = CONFIG_MAP_HEADER ) srclumpname = sourcemapname ;
if ( tgtlumpname = = CONFIG_MAP_HEADER ) tgtlumpname = targetmapname ;
2007-06-24 18:56:43 +00:00
// Find the lump in the source
2007-10-14 15:44:55 +00:00
sourceindex = FindSpecificLump ( source , srclumpname , srcheaderindex , sourcemapname , maplumps ) ;
if ( sourceindex > - 1 )
2007-06-24 18:56:43 +00:00
{
2007-10-14 15:44:55 +00:00
// Remove lump at target
lumpindex = RemoveSpecificLump ( target , tgtlumpname , tgtheaderindex , targetmapname , maplumps ) ;
// Determine target index
// When original lump was found and removed then insert at that position
// otherwise insert after last insertion position
if ( lumpindex > - 1 ) targetindex = lumpindex ; else targetindex + + ;
if ( targetindex > target . Lumps . Count ) targetindex = target . Lumps . Count ;
2007-06-24 18:56:43 +00:00
// Copy the lump to the target
2007-10-14 15:44:55 +00:00
//General.WriteLogLine(srclumpname + " copying as " + tgtlumpname);
lump = source . Lumps [ sourceindex ] ;
newlump = target . Insert ( tgtlumpname , targetindex , lump . Length ) ;
2007-06-24 18:56:43 +00:00
lump . CopyTo ( newlump ) ;
}
2007-10-05 11:17:58 +00:00
else
{
General . WriteLogLine ( "WARNING: " + ml . Key . ToString ( ) + " should be copied but was not found!" ) ;
}
2007-06-24 18:56:43 +00:00
}
}
2007-06-15 18:30:55 +00:00
}
2007-06-24 18:56:43 +00:00
}
2007-10-14 15:44:55 +00:00
// This finds a lump within the range of known lump names
// Returns -1 when the lump cannot be found
2007-10-14 17:48:15 +00:00
public static int FindSpecificLump ( WAD source , string lumpname , int mapheaderindex , string mapheadername , IDictionary maplumps )
2007-06-24 18:56:43 +00:00
{
2007-10-14 15:44:55 +00:00
// Use the configured map lump names to find the specific lump within range,
// because when an unknown lump is met, this search must stop.
2007-06-24 18:56:43 +00:00
2007-10-14 15:44:55 +00:00
// Go for all lumps in order to find the specified lump
for ( int i = 0 ; i < maplumps . Count + 1 ; i + + )
{
// Still within bounds?
if ( ( mapheaderindex + i ) < source . Lumps . Count )
2007-06-24 18:56:43 +00:00
{
2007-10-14 15:44:55 +00:00
// Check if this is a known lump name
if ( maplumps . Contains ( source . Lumps [ mapheaderindex + i ] . Name ) | |
( maplumps . Contains ( CONFIG_MAP_HEADER ) & & ( source . Lumps [ mapheaderindex + i ] . Name = = mapheadername ) ) )
2007-06-24 18:56:43 +00:00
{
2007-10-14 15:44:55 +00:00
// Is this the lump we are looking for?
if ( source . Lumps [ mapheaderindex + i ] . Name = = lumpname )
{
// Return this index
return mapheaderindex + i ;
}
2007-06-24 18:56:43 +00:00
}
else
{
2007-10-14 15:44:55 +00:00
// Unknown lump hit, abort search
break ;
2007-06-24 18:56:43 +00:00
}
}
2007-06-15 18:30:55 +00:00
}
2007-10-14 15:44:55 +00:00
// Nothing found
return - 1 ;
}
// This removes a specific lump and returns the position where the lump was removed
// Returns -1 when the lump could not be found
2007-10-14 17:48:15 +00:00
public static int RemoveSpecificLump ( WAD source , string lumpname , int mapheaderindex , string mapheadername , IDictionary maplumps )
2007-10-14 15:44:55 +00:00
{
int lumpindex ;
// Find the specific lump index
lumpindex = FindSpecificLump ( source , lumpname , mapheaderindex , mapheadername , maplumps ) ;
if ( lumpindex > - 1 )
{
// Remove this lump
//General.WriteLogLine(lumpname + " removed");
source . RemoveAt ( lumpindex ) ;
}
else
{
// Lump not found
2007-10-14 17:48:15 +00:00
//General.WriteLogLine("WARNING: " + lumpname + " should be removed but was not found!");
2007-10-14 15:44:55 +00:00
}
// Return result
return lumpindex ;
2007-06-24 18:56:43 +00:00
}
2007-10-14 15:44:55 +00:00
#endregion
2007-10-20 19:50:03 +00:00
#region = = = = = = = = = = = = = = = = = = Editing Modes
// This changes the editing mode.
// Order in which events occur for the old and new modes:
//
// - Constructor of new mode is called
// - Disengage of old mode is called
// ----- Mode switches -----
// - Engage of new mode is called
// - Dispose of old mode is called
//
public void ChangeMode ( EditMode newmode )
{
EditMode oldmode = mode ;
// Log info
if ( newmode ! = null )
General . WriteLogLine ( "Switching edit mode to " + newmode . GetType ( ) . Name + "..." ) ;
else
General . WriteLogLine ( "Stopping edit mode..." ) ;
// Disenagage old mode
if ( oldmode ! = null ) oldmode . Disengage ( ) ;
// Apply new mode
mode = newmode ;
// Engage new mode
if ( newmode ! = null ) newmode . Engage ( ) ;
// Dispose old mode
if ( mode ! = null ) mode . Dispose ( ) ;
// Redraw the display
General . MainWindow . RedrawDisplay ( ) ;
}
// This switches to vertices mode
[Action(Action.VERTICESMODE)]
public void SwitchVerticesMode ( )
{
// Change to vertices mode
ChangeMode ( new VerticesMode ( ) ) ;
}
// This switches to linedefs mode
[Action(Action.LINEDEFSMODE)]
public void SwitchLinedefsMode ( )
{
// Change to linedefs mode
ChangeMode ( new LinedefsMode ( ) ) ;
}
// This switches to sectors mode
[Action(Action.SECTORSMODE)]
public void SwitchSectorsMode ( )
{
// Change to sectors mode
ChangeMode ( new SectorsMode ( ) ) ;
}
#endregion
2007-10-14 15:44:55 +00:00
#region = = = = = = = = = = = = = = = = = = Methods
2007-10-13 14:05:45 +00:00
2007-10-14 21:31:45 +00:00
// This reloads resources
[Action(Action.RELOADRESOURCES)]
public void ReloadResources ( )
{
DataLocation maplocation ;
string oldstatus ;
Cursor oldcursor ;
// Keep old display info
oldstatus = General . MainWindow . GetCurrentSatus ( ) ;
oldcursor = Cursor . Current ;
// Show status
General . MainWindow . DisplayStatus ( "Reloading data resources..." ) ;
Cursor . Current = Cursors . WaitCursor ;
// Reload game configuration
General . WriteLogLine ( "Reloading game configuration..." ) ;
configinfo = General . GetConfigurationInfo ( options . ConfigFile ) ;
config = General . LoadGameConfiguration ( options . ConfigFile ) ;
2007-10-20 12:34:27 +00:00
configsettings = new GameConfigurationCache ( config ) ;
2007-10-14 21:31:45 +00:00
// Reload data resources
General . WriteLogLine ( "Reloading data resources..." ) ;
data . Dispose ( ) ;
data = new DataManager ( ) ;
maplocation = new DataLocation ( DataLocation . RESOURCE_WAD , filepathname , false , false ) ;
data . Load ( configinfo . Resources , options . Resources , maplocation ) ;
// Reset status
General . MainWindow . DisplayStatus ( oldstatus ) ;
Cursor . Current = oldcursor ;
}
2007-10-20 19:50:03 +00:00
2007-10-14 21:31:45 +00:00
// Game Configuration action
[Action(Action.MAPOPTIONS)]
public void ShowMapOptions ( )
{
// Show map options dialog
MapOptionsForm optionsform = new MapOptionsForm ( options ) ;
if ( optionsform . ShowDialog ( General . MainWindow ) = = DialogResult . OK )
{
// Update interface
General . MainWindow . UpdateInterface ( ) ;
2007-10-20 19:50:03 +00:00
2007-10-14 21:31:45 +00:00
// Reload resources
ReloadResources ( ) ;
}
// Done
optionsform . Dispose ( ) ;
}
2007-10-14 15:44:55 +00:00
2007-06-14 23:31:57 +00:00
#endregion
}
}