2007-06-13 19:39:38 +00:00
2007-06-14 23:31:57 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
2007-06-13 19:39:38 +00:00
/ *
* 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 .
*
* /
2007-06-14 23:31:57 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
2007-06-13 19:39:38 +00:00
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 ;
2007-06-14 23:31:57 +00:00
using CodeImp.DoomBuilder.Map ;
2007-06-15 22:38:42 +00:00
using CodeImp.DoomBuilder.Geometry ;
2007-06-24 18:56:43 +00:00
using System.Runtime.InteropServices ;
2007-06-24 22:53:41 +00:00
using CodeImp.DoomBuilder.Controls ;
2007-06-14 23:31:57 +00:00
#endregion
2007-06-13 19:39:38 +00:00
namespace CodeImp.DoomBuilder
{
internal static class General
{
2007-06-24 18:56:43 +00:00
#region = = = = = = = = = = = = = = = = = = API Declarations
[DllImport("user32.dll")]
public static extern int LockWindowUpdate ( IntPtr hwnd ) ;
2007-09-17 21:22:46 +00:00
[DllImport("kernel32.dll", EntryPoint="RtlZeroMemory", SetLastError=false)]
public static extern void ZeroMemory ( IntPtr dest , int size ) ;
2007-09-23 22:01:21 +00:00
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
internal static extern unsafe void CopyMemory ( void * dst , void * src , UIntPtr length ) ;
[DllImport("kernel32.dll", SetLastError = true)]
internal static unsafe extern void * VirtualAlloc ( IntPtr lpAddress , UIntPtr dwSize , uint flAllocationType , uint flProtect ) ;
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe extern bool VirtualFree ( void * lpAddress , UIntPtr dwSize , uint dwFreeType ) ;
2007-06-24 18:56:43 +00:00
#endregion
2007-06-13 19:39:38 +00:00
#region = = = = = = = = = = = = = = = = = = Constants
2007-09-23 22:01:21 +00:00
// Memory APIs
public const uint MEM_COMMIT = 0x1000 ;
public const uint MEM_RESERVE = 0x2000 ;
public const uint MEM_DECOMMIT = 0x4000 ;
public const uint MEM_RELEASE = 0x8000 ;
public const uint MEM_RESET = 0x80000 ;
public const uint MEM_TOP_DOWN = 0x100000 ;
public const uint MEM_PHYSICAL = 0x400000 ;
public const uint PAGE_NOACCESS = 0x01 ;
public const uint PAGE_READONLY = 0x02 ;
public const uint PAGE_READWRITE = 0x04 ;
public const uint PAGE_WRITECOPY = 0x08 ;
public const uint PAGE_EXECUTE = 0x10 ;
public const uint PAGE_EXECUTE_READ = 0x20 ;
public const uint PAGE_EXECUTE_READWRITE = 0x40 ;
public const uint PAGE_EXECUTE_WRITECOPY = 0x80 ;
public const uint PAGE_GUARD = 0x100 ;
public const uint PAGE_NOCACHE = 0x200 ;
public const uint PAGE_WRITECOMBINE = 0x400 ;
2007-06-13 19:39:38 +00:00
// Files and Folders
private const string SETTINGS_CONFIG_FILE = "Builder.cfg" ;
2007-06-14 14:44:18 +00:00
private const string GAME_CONFIGS_DIR = "Configurations" ;
2007-09-28 08:56:18 +00:00
private const string COMPILERS_DIR = "Compilers" ;
2007-06-13 19:39:38 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Files and Folders
private static string apppath ;
private static string temppath ;
2007-06-14 14:44:18 +00:00
private static string configspath ;
2007-09-28 08:56:18 +00:00
private static string compilerspath ;
2007-06-13 19:39:38 +00:00
// Main objects
2007-06-15 18:30:55 +00:00
private static Assembly thisasm ;
2007-06-13 19:39:38 +00:00
private static MainForm mainwindow ;
private static Configuration settings ;
2007-06-14 23:31:57 +00:00
private static MapManager map ;
2007-06-24 22:53:41 +00:00
private static ActionManager actions ;
2007-06-14 23:31:57 +00:00
2007-06-14 14:44:18 +00:00
// Configurations
2007-06-14 23:31:57 +00:00
private static List < ConfigurationInfo > configs ;
2007-09-28 08:56:18 +00:00
private static List < NodebuilderInfo > nodebuilders ;
2007-06-14 14:44:18 +00:00
2007-06-13 19:39:38 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
2007-06-15 18:30:55 +00:00
public static Assembly ThisAssembly { get { return thisasm ; } }
2007-06-13 19:39:38 +00:00
public static string AppPath { get { return apppath ; } }
public static string TempPath { get { return temppath ; } }
2007-06-14 14:44:18 +00:00
public static string ConfigsPath { get { return configspath ; } }
2007-09-28 08:56:18 +00:00
public static string CompilersPath { get { return compilerspath ; } }
2007-06-13 19:39:38 +00:00
public static MainForm MainWindow { get { return mainwindow ; } }
public static Configuration Settings { get { return settings ; } }
2007-06-14 23:31:57 +00:00
public static List < ConfigurationInfo > Configs { get { return configs ; } }
2007-09-28 08:56:18 +00:00
public static List < NodebuilderInfo > Nodebuilders { get { return nodebuilders ; } }
2007-06-14 23:31:57 +00:00
public static MapManager Map { get { return map ; } }
2007-06-24 22:53:41 +00:00
public static ActionManager Actions { get { return actions ; } }
2007-06-14 23:31:57 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Configurations
2007-09-27 22:55:03 +00:00
// This returns the game configuration info by filename
public static ConfigurationInfo GetConfigurationInfo ( string filename )
{
// Go for all config infos
foreach ( ConfigurationInfo ci in configs )
{
// Check if filename matches
if ( string . Compare ( Path . GetFileNameWithoutExtension ( ci . Filename ) ,
Path . GetFileNameWithoutExtension ( filename ) , true ) = = 0 )
{
// Return this info
return ci ;
}
}
// None found
return null ;
}
2007-06-14 23:31:57 +00:00
// This loads and returns a game configuration
public static Configuration LoadGameConfiguration ( string filename )
{
Configuration cfg ;
// Make the full filepathname
string filepathname = Path . Combine ( configspath , filename ) ;
// Load configuration
try
{
// Try loading the configuration
cfg = new Configuration ( filepathname , true ) ;
// Check for erors
if ( cfg . ErrorResult ! = 0 )
{
// Error in configuration
MessageBox . Show ( mainwindow , "Unable to load the game configuration file \"" + filename + "\".\n" +
"Error near line " + cfg . ErrorLine + ": " + cfg . ErrorDescription ,
Application . ProductName , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return null ;
}
2007-09-27 22:55:03 +00:00
// Check if this is a Doom Builder 2 config
2007-06-16 19:53:51 +00:00
else if ( cfg . ReadSetting ( "type" , "" ) ! = "Doom Builder 2 Game Configuration" )
{
// Old configuration
MessageBox . Show ( mainwindow , "Unable to load the game configuration file \"" + filename + "\".\n" +
"This configuration is not a Doom Builder 2 game configuration." ,
Application . ProductName , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return null ;
}
2007-06-14 23:31:57 +00:00
else
{
// Return config
return cfg ;
}
}
catch ( Exception )
{
// Unable to load configuration
MessageBox . Show ( mainwindow , "Unable to load the game configuration file \"" + filename + "\"." ,
Application . ProductName , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
return null ;
}
}
// This finds all game configurations
private static void FindGameConfigurations ( )
{
Configuration cfg ;
string [ ] filenames ;
string name , fullfilename ;
// Display status
mainwindow . DisplayStatus ( "Loading game configurations..." ) ;
2007-06-13 19:39:38 +00:00
2007-06-14 23:31:57 +00:00
// Make array
configs = new List < ConfigurationInfo > ( ) ;
2007-09-28 08:56:18 +00:00
// Go for all cfg files in the configurations directory
2007-06-14 23:31:57 +00:00
filenames = Directory . GetFiles ( configspath , "*.cfg" , SearchOption . TopDirectoryOnly ) ;
foreach ( string filepath in filenames )
{
// Check if it can be loaded
2007-06-16 19:53:51 +00:00
cfg = LoadGameConfiguration ( Path . GetFileName ( filepath ) ) ;
2007-06-14 23:31:57 +00:00
if ( cfg ! = null )
{
// Get name and filename
name = cfg . ReadSetting ( "game" , "<unnamed game>" ) ;
fullfilename = Path . GetFileName ( filepath ) ;
// Add to lists
configs . Add ( new ConfigurationInfo ( name , fullfilename ) ) ;
}
}
// Sort the configurations list
configs . Sort ( ) ;
}
2007-09-28 08:56:18 +00:00
// This finds all nodebuilder configurations
private static void FindNodebuilderConfigurations ( )
{
Configuration cfg ;
string [ ] filenames ;
// Display status
mainwindow . DisplayStatus ( "Loading nodebuilder configurations..." ) ;
// Make array
nodebuilders = new List < NodebuilderInfo > ( ) ;
// Go for all cfg files in the compilers directory
filenames = Directory . GetFiles ( compilerspath , "*.cfg" , SearchOption . TopDirectoryOnly ) ;
foreach ( string filepath in filenames )
{
try
{
// Try loading the configuration
cfg = new Configuration ( filepath , true ) ;
// Check for erors
if ( cfg . ErrorResult ! = 0 )
{
// Error in configuration
MessageBox . Show ( mainwindow , "Unable to load the nodebuilder configuration file \"" + filepath + "\".\n" +
"Error near line " + cfg . ErrorLine + ": " + cfg . ErrorDescription ,
Application . ProductName , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
}
else
{
// Make nodebuilder info
2007-09-29 15:43:59 +00:00
nodebuilders . Add ( new NodebuilderInfo ( cfg , filepath ) ) ;
2007-09-28 08:56:18 +00:00
}
}
catch ( Exception )
{
// Unable to load configuration
MessageBox . Show ( mainwindow , "Unable to load the nodebuilder configuration file \"" + filepath + "\"." ,
Application . ProductName , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
}
}
// Sort the configurations list
configs . Sort ( ) ;
}
2007-06-13 19:39:38 +00:00
#endregion
2007-06-14 14:44:18 +00:00
#region = = = = = = = = = = = = = = = = = = Startup
2007-06-13 19:39:38 +00:00
// Main program entry
2007-06-15 10:18:03 +00:00
[STAThread]
2007-06-13 19:39:38 +00:00
public static void Main ( string [ ] args )
{
2007-06-15 18:30:55 +00:00
Uri localpath ;
// Get a reference to this assembly
thisasm = Assembly . GetExecutingAssembly ( ) ;
2007-06-13 19:39:38 +00:00
// Find application path
2007-06-15 18:30:55 +00:00
localpath = new Uri ( Path . GetDirectoryName ( thisasm . GetName ( ) . CodeBase ) ) ;
2007-06-13 19:39:38 +00:00
apppath = Uri . UnescapeDataString ( localpath . AbsolutePath ) ;
2007-09-28 08:56:18 +00:00
// Setup directories
2007-06-13 19:39:38 +00:00
temppath = Path . GetTempPath ( ) ;
2007-06-14 14:44:18 +00:00
configspath = Path . Combine ( apppath , GAME_CONFIGS_DIR ) ;
2007-09-28 08:56:18 +00:00
compilerspath = Path . Combine ( apppath , COMPILERS_DIR ) ;
2007-06-14 14:44:18 +00:00
2007-06-13 19:39:38 +00:00
// Load configuration
if ( ! File . Exists ( Path . Combine ( apppath , SETTINGS_CONFIG_FILE ) ) ) throw ( new FileNotFoundException ( "Unable to find the program configuration \"" + SETTINGS_CONFIG_FILE + "\"." ) ) ;
2007-09-27 22:55:03 +00:00
settings = new Configuration ( Path . Combine ( apppath , SETTINGS_CONFIG_FILE ) , true ) ;
2007-06-13 19:39:38 +00:00
2007-06-24 22:53:41 +00:00
// Create action manager
actions = new ActionManager ( ) ;
2007-06-26 06:01:52 +00:00
// Bind static methods to actions
ActionAttribute . BindMethods ( typeof ( General ) ) ;
2007-06-25 14:42:23 +00:00
2007-06-13 19:39:38 +00:00
// Create main window
mainwindow = new MainForm ( ) ;
2007-06-16 19:53:51 +00:00
mainwindow . UpdateMenus ( ) ;
2007-06-14 15:35:37 +00:00
2007-06-13 19:39:38 +00:00
// Show main window
mainwindow . Show ( ) ;
2007-06-14 14:44:18 +00:00
mainwindow . Update ( ) ;
// Load game configurations
2007-06-14 23:31:57 +00:00
FindGameConfigurations ( ) ;
2007-09-28 08:56:18 +00:00
// Load nodebuilder configurations
FindNodebuilderConfigurations ( ) ;
2007-06-13 19:39:38 +00:00
// Run application from the main window
2007-06-14 14:44:18 +00:00
mainwindow . DisplayReady ( ) ;
2007-06-13 19:39:38 +00:00
Application . Run ( mainwindow ) ;
}
#endregion
2007-06-14 15:35:37 +00:00
#region = = = = = = = = = = = = = = = = = = Terminate
// This terminates the program
public static void Terminate ( )
{
2007-06-26 06:01:52 +00:00
// Unbind static methods from actions
ActionAttribute . UnbindMethods ( typeof ( General ) ) ;
2007-06-25 14:42:23 +00:00
2007-06-14 15:35:37 +00:00
// Clean up
mainwindow . Dispose ( ) ;
2007-06-24 22:53:41 +00:00
actions . Dispose ( ) ;
2007-06-14 15:35:37 +00:00
2007-09-30 19:37:57 +00:00
// Save action controls
actions . SaveSettings ( ) ;
2007-09-27 22:55:03 +00:00
// Save game configuration settings
foreach ( ConfigurationInfo ci in configs ) ci . SaveSettings ( ) ;
2007-06-14 15:35:37 +00:00
// Save settings configuration
settings . SaveConfiguration ( Path . Combine ( apppath , SETTINGS_CONFIG_FILE ) ) ;
// Application ends here and now
Application . Exit ( ) ;
}
#endregion
2007-06-14 23:31:57 +00:00
#region = = = = = = = = = = = = = = = = = = Management
// This creates a new map
2007-06-26 06:01:52 +00:00
[Action(Action.NEWMAP)]
2007-06-25 14:42:23 +00:00
public static void NewMap ( )
2007-06-14 23:31:57 +00:00
{
2007-06-25 14:42:23 +00:00
MapOptions newoptions = new MapOptions ( ) ;
2007-06-14 23:31:57 +00:00
MapOptionsForm optionswindow ;
2007-07-07 09:40:34 +00:00
2007-06-25 14:42:23 +00:00
// Ask the user to save changes (if any)
if ( General . AskSaveMap ( ) )
2007-06-16 19:53:51 +00:00
{
// Open map options dialog
2007-06-25 14:42:23 +00:00
optionswindow = new MapOptionsForm ( newoptions ) ;
if ( optionswindow . ShowDialog ( mainwindow ) = = DialogResult . OK )
2007-06-14 23:31:57 +00:00
{
2007-06-15 10:18:03 +00:00
// Display status
2007-06-25 14:42:23 +00:00
mainwindow . DisplayStatus ( "Creating new map..." ) ;
2007-06-16 19:53:51 +00:00
2007-06-15 10:18:03 +00:00
// Clear the display
mainwindow . ClearDisplay ( ) ;
2007-06-16 19:53:51 +00:00
2007-06-15 10:18:03 +00:00
// Trash the current map, if any
if ( map ! = null ) map . Dispose ( ) ;
// Create map manager with given options
2007-06-15 18:30:55 +00:00
map = new MapManager ( ) ;
2007-06-25 14:42:23 +00:00
if ( map . InitializeNewMap ( newoptions ) )
{
// Done
mainwindow . UpdateMenus ( ) ;
mainwindow . DisplayReady ( ) ;
}
else
2007-06-15 18:30:55 +00:00
{
// Unable to create map manager
map . Dispose ( ) ;
map = null ;
// Show splash logo on display
mainwindow . ShowSplashDisplay ( ) ;
// Failed
mainwindow . UpdateMenus ( ) ;
mainwindow . DisplayReady ( ) ;
}
2007-06-14 23:31:57 +00:00
}
2007-06-15 10:18:03 +00:00
}
2007-06-25 14:42:23 +00:00
}
2007-06-16 19:53:51 +00:00
2007-06-25 14:42:23 +00:00
// This closes the current map
2007-06-26 06:01:52 +00:00
[Action(Action.CLOSEMAP)]
2007-06-25 14:42:23 +00:00
public static void CloseMap ( )
{
// Ask the user to save changes (if any)
if ( General . AskSaveMap ( ) )
{
// Display status
mainwindow . DisplayStatus ( "Closing map..." ) ;
// Trash the current map
if ( map ! = null ) map . Dispose ( ) ;
map = null ;
// Show splash logo on display
mainwindow . ShowSplashDisplay ( ) ;
// Done
mainwindow . UpdateMenus ( ) ;
mainwindow . DisplayReady ( ) ;
}
}
// This loads a map from file
2007-06-26 06:01:52 +00:00
[Action(Action.OPENMAP)]
2007-06-25 14:42:23 +00:00
public static void OpenMap ( )
{
OpenFileDialog openfile ;
OpenMapOptionsForm openmapwindow ;
// Ask the user to save changes (if any)
if ( General . AskSaveMap ( ) )
{
// Open map file dialog
openfile = new OpenFileDialog ( ) ;
openfile . Filter = "Doom WAD Files (*.wad)|*.wad" ;
openfile . Title = "Open Map" ;
if ( openfile . ShowDialog ( mainwindow ) = = DialogResult . OK )
{
// Update main window
mainwindow . Update ( ) ;
// Open map options dialog
openmapwindow = new OpenMapOptionsForm ( openfile . FileName ) ;
if ( openmapwindow . ShowDialog ( mainwindow ) = = DialogResult . OK )
{
// Display status
mainwindow . DisplayStatus ( "Opening map file..." ) ;
// Clear the display
mainwindow . ClearDisplay ( ) ;
// Trash the current map, if any
if ( map ! = null ) map . Dispose ( ) ;
// Create map manager with given options
map = new MapManager ( ) ;
if ( map . InitializeOpenMap ( openfile . FileName , openmapwindow . Options ) )
{
// Done
mainwindow . UpdateMenus ( ) ;
mainwindow . DisplayReady ( ) ;
}
else
{
// Unable to create map manager
map . Dispose ( ) ;
map = null ;
// Show splash logo on display
mainwindow . ShowSplashDisplay ( ) ;
// Failed
mainwindow . UpdateMenus ( ) ;
mainwindow . DisplayReady ( ) ;
}
}
}
}
2007-06-15 10:18:03 +00:00
}
// This asks to save the map if needed
// Returns false when action was cancelled
2007-06-16 19:53:51 +00:00
public static bool AskSaveMap ( )
2007-06-15 10:18:03 +00:00
{
DialogResult result ;
// Map open and not saved?
if ( ( map ! = null ) & & map . IsChanged )
{
// Ask to save changes
result = MessageBox . Show ( mainwindow , "Do you want to save changes to " + map . FileTitle + " (" + map . Options . CurrentName + ")?" , Application . ProductName , MessageBoxButtons . YesNoCancel , MessageBoxIcon . Question ) ;
if ( result = = DialogResult . Yes )
{
// TODO: Save map
2007-06-14 23:31:57 +00:00
2007-06-15 10:18:03 +00:00
}
else if ( result = = DialogResult . Cancel )
{
// Abort
return false ;
}
}
// Continue
return true ;
}
2007-06-14 23:31:57 +00:00
#endregion
2007-06-24 18:56:43 +00:00
#region = = = = = = = = = = = = = = = = = = Tools
// This returns a unique temp filename
public static string MakeTempFilename ( )
{
string filename ;
string chars = "abcdefghijklmnopqrstuvwxyz1234567890" ;
Random rnd = new Random ( ) ;
int i ;
do
{
// Generate a filename
filename = "" ;
for ( i = 0 ; i < 8 ; i + + ) filename + = chars [ rnd . Next ( chars . Length ) ] ;
filename = Path . Combine ( temppath , filename + ".tmp" ) ;
}
// Continue while file is not unique
while ( File . Exists ( filename ) ) ;
// Return the filename
return filename ;
}
#endregion
2007-06-13 19:39:38 +00:00
}
}
2007-09-28 08:56:18 +00:00