2009-04-19 18:07:22 +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 ;
2015-07-01 23:09:34 +00:00
using System.Diagnostics ;
using System.Drawing ;
2016-05-20 15:04:00 +00:00
using System.Globalization ;
2015-07-01 23:09:34 +00:00
using System.IO ;
using System.Reflection ;
using System.Runtime.InteropServices ;
2015-04-02 10:57:08 +00:00
using System.Security.AccessControl ;
using System.Security.Principal ;
2009-04-19 18:07:22 +00:00
using System.Text ;
2015-07-01 23:09:34 +00:00
using System.Threading ;
2009-04-19 18:07:22 +00:00
using System.Windows.Forms ;
2015-07-01 23:09:34 +00:00
using CodeImp.DoomBuilder.Actions ;
using CodeImp.DoomBuilder.Config ;
2011-07-26 20:06:38 +00:00
using CodeImp.DoomBuilder.Data ;
2015-07-01 23:09:34 +00:00
using CodeImp.DoomBuilder.Editing ;
2009-04-19 18:07:22 +00:00
using CodeImp.DoomBuilder.IO ;
using CodeImp.DoomBuilder.Map ;
2015-07-01 23:09:34 +00:00
using CodeImp.DoomBuilder.Plugins ;
2009-04-19 18:07:22 +00:00
using CodeImp.DoomBuilder.Rendering ;
2015-07-01 23:09:34 +00:00
using CodeImp.DoomBuilder.Types ;
using CodeImp.DoomBuilder.Windows ;
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder
{
public static class General
{
2019-08-29 15:56:12 +00:00
#region = = = = = = = = = = = = = = = = = = API Declarations
2009-04-19 18:07:22 +00:00
2019-08-29 19:04:50 +00:00
#if NO_WIN32
internal static bool LockWindowUpdate ( IntPtr hwnd ) { return true ; }
internal static bool MessageBeep ( MessageBeepType type ) { return true ; }
internal static void ZeroMemory ( IntPtr dest , int size ) { }
internal static int SendMessage ( IntPtr hwnd , uint Msg , IntPtr wParam , IntPtr lParam ) { return 0 ; }
2019-12-29 19:48:11 +00:00
internal static int PostMessage ( IntPtr hwnd , uint Msg , IntPtr wParam , IntPtr lParam ) { return 0 ; }
2019-08-29 19:04:50 +00:00
#else
2019-08-29 15:56:12 +00:00
[DllImport("user32.dll")]
2009-04-19 18:07:22 +00:00
internal static extern bool LockWindowUpdate ( IntPtr hwnd ) ;
[DllImport("kernel32.dll", EntryPoint = "RtlZeroMemory", SetLastError = false)]
internal static extern void ZeroMemory ( IntPtr dest , int size ) ;
2016-10-28 21:07:33 +00:00
//[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
//internal static extern unsafe void CopyMemory(void* dst, void* src, uint length);
2009-04-19 18:07:22 +00:00
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
2018-04-14 13:55:21 +00:00
internal static extern int SendMessage ( IntPtr hwnd , uint Msg , IntPtr wParam , IntPtr lParam ) ;
2009-04-19 18:07:22 +00:00
2019-12-29 19:48:11 +00:00
[DllImport("user32.dll", EntryPoint = "PostMessage", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern int PostMessage ( IntPtr hwnd , uint Msg , IntPtr wParam , IntPtr lParam ) ;
[DllImport("user32.dll", SetLastError = true)]
2009-04-19 18:07:22 +00:00
internal static extern bool MessageBeep ( MessageBeepType type ) ;
2016-03-18 12:52:12 +00:00
//[DllImport("kernel32.dll")]
//internal extern static IntPtr LoadLibrary(string filename);
2009-04-19 18:07:22 +00:00
2016-03-18 12:52:12 +00:00
//[DllImport("kernel32.dll")]
//internal extern static bool FreeLibrary(IntPtr moduleptr);
2009-04-19 18:07:22 +00:00
2016-03-18 12:52:12 +00:00
//[DllImport("user32.dll")]
/ * internal static extern IntPtr CreateWindowEx ( uint exstyle , string classname , string windowname , uint style ,
2009-04-19 18:07:22 +00:00
int x , int y , int width , int height , IntPtr parentptr , int menu ,
2016-03-18 12:52:12 +00:00
IntPtr instanceptr , string param ) ; * /
2009-04-19 18:07:22 +00:00
2016-03-18 12:52:12 +00:00
//[DllImport("user32.dll")]
//internal static extern bool DestroyWindow(IntPtr windowptr);
2009-04-19 18:07:22 +00:00
2016-03-18 12:52:12 +00:00
//[DllImport("user32.dll")]
//internal static extern int SetWindowPos(IntPtr windowptr, int insertafterptr, int x, int y, int cx, int cy, int flags);
2009-04-19 18:07:22 +00:00
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern uint GetShortPathName ( [ MarshalAs ( UnmanagedType . LPTStr ) ] string longpath , [ MarshalAs ( UnmanagedType . LPTStr ) ] StringBuilder shortpath , uint buffersize ) ;
2013-08-29 10:05:50 +00:00
//[DllImport("user32.dll")]
//internal static extern int SetScrollInfo(IntPtr windowptr, int bar, IntPtr scrollinfo, bool redraw);
2009-04-19 18:07:22 +00:00
2013-08-29 10:05:50 +00:00
//[DllImport("user32.dll")]
//internal static extern int GetScrollInfo(IntPtr windowptr, int bar, IntPtr scrollinfo);
2019-08-29 19:04:50 +00:00
#endif
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constants
// SendMessage API
internal const int WM_USER = 0x400 ;
2019-12-29 19:48:11 +00:00
internal const int WM_UIACTION = WM_USER + 1 ;
2009-04-19 18:07:22 +00:00
internal const int WM_SYSCOMMAND = 0x112 ;
2017-03-25 01:47:18 +00:00
internal const int WM_MOUSEHWHEEL = 0x020E ; // [ZZ]
internal const int SC_KEYMENU = 0xF100 ;
2009-04-19 18:07:22 +00:00
internal const int CB_SETITEMHEIGHT = 0x153 ;
2013-08-29 10:05:50 +00:00
//internal const int CB_SHOWDROPDOWN = 0x14F;
//internal const int EM_GETSCROLLPOS = WM_USER + 221;
//internal const int EM_SETSCROLLPOS = WM_USER + 222;
//internal const int SB_HORZ = 0;
//internal const int SB_VERT = 1;
//internal const int SB_CTL = 2;
//internal const int SIF_RANGE = 0x1;
//internal const int SIF_PAGE = 0x2;
//internal const int SIF_POS = 0x4;
//internal const int SIF_DISABLENOSCROLL = 0x8;
//internal const int SIF_TRACKPOS = 0x16;
//internal const int SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS;
2009-04-19 18:07:22 +00:00
// Files and Folders
2012-04-17 19:13:47 +00:00
private const string SETTINGS_FILE = "GZBuilder.cfg" ;
2015-04-02 10:57:08 +00:00
private const string DEFAULT_SETTINGS_FILE = "GZBuilder.default.cfg" ; //mxd
2009-04-19 18:07:22 +00:00
private const string SETTINGS_DIR = "Doom Builder" ;
2012-04-17 19:13:47 +00:00
private const string LOG_FILE = "GZBuilder.log" ;
2009-04-19 18:07:22 +00:00
private const string GAME_CONFIGS_DIR = "Configurations" ;
private const string COMPILERS_DIR = "Compilers" ;
private const string PLUGINS_DIR = "Plugins" ;
private const string SCRIPTS_DIR = "Scripting" ;
2014-08-07 10:20:35 +00:00
private const string SCREENSHOTS_DIR = "Screenshots" ; //mxd
2014-05-13 09:43:58 +00:00
private const string SNIPPETS_DIR = "Snippets" ; //mxd
2015-09-25 13:20:53 +00:00
private const string MAP_RESTORE_DIR = "Restore" ; //mxd
2009-04-19 18:07:22 +00:00
private const string SPRITES_DIR = "Sprites" ;
2015-12-30 13:58:58 +00:00
private const string TEXTURES_DIR = "Textures" ; //mxd
2009-04-19 18:07:22 +00:00
private const string HELP_FILE = "Refmanual.chm" ;
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Files and Folders
private static string apppath ;
private static string settingspath ;
2015-09-25 13:20:53 +00:00
private static string restorepath ; //mxd
2009-04-19 18:07:22 +00:00
private static string logfile ;
private static string temppath ;
private static string configspath ;
private static string compilerspath ;
private static string scriptspath ;
2014-05-13 09:43:58 +00:00
private static string snippetspath ; //mxd
2014-08-07 10:20:35 +00:00
private static string screenshotspath ; //mxd
2009-04-19 18:07:22 +00:00
private static string pluginspath ;
private static string spritespath ;
2015-12-30 13:58:58 +00:00
private static string texturespath ; //mxd
2009-04-19 18:07:22 +00:00
// Main objects
private static Assembly thisasm ;
private static MainForm mainwindow ;
private static ProgramConfiguration settings ;
private static MapManager map ;
private static EditingManager editing ;
private static ActionManager actions ;
2014-01-23 13:36:51 +00:00
private static HintsManager hints ; //mxd
2009-04-19 18:07:22 +00:00
private static PluginManager plugins ;
private static ColorCollection colors ;
private static TypesManager types ;
private static ErrorLogger errorlogger ;
2016-12-28 12:24:58 +00:00
private static string commithash ; //mxd. Git commit hash
2015-09-25 13:20:53 +00:00
//private static Mutex appmutex;
2009-04-19 18:07:22 +00:00
// Configurations
private static List < ConfigurationInfo > configs ;
private static List < CompilerInfo > compilers ;
private static List < NodebuilderInfo > nodebuilders ;
private static Dictionary < string , ScriptConfiguration > scriptconfigs ;
2014-07-11 10:13:26 +00:00
private static Dictionary < string , ScriptConfiguration > compiledscriptconfigs ; //mxd
2009-04-19 18:07:22 +00:00
// States
private static bool debugbuild ;
// Command line arguments
private static string [ ] cmdargs ;
2014-02-18 14:04:14 +00:00
private static string autoloadfile ;
private static string autoloadmap ;
private static string autoloadconfig ;
private static bool autoloadstrictpatches ;
private static DataLocationList autoloadresources ;
2009-04-19 18:07:22 +00:00
private static bool delaymainwindow ;
2010-09-15 19:57:12 +00:00
private static bool nosettings ;
2015-04-02 10:57:08 +00:00
private static bool portablemode ; //mxd
2009-04-19 18:07:22 +00:00
2013-07-10 12:41:49 +00:00
//misc
2014-10-23 08:18:14 +00:00
private static readonly Random random = new Random ( ) ; //mxd
2013-07-10 12:41:49 +00:00
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public static Assembly ThisAssembly { get { return thisasm ; } }
public static string AppPath { get { return apppath ; } }
public static string TempPath { get { return temppath ; } }
public static string ConfigsPath { get { return configspath ; } }
2013-08-29 10:05:50 +00:00
internal static string SettingsPath { get { return settingspath ; } } //mxd
2015-09-25 13:20:53 +00:00
internal static string MapRestorePath { get { return restorepath ; } } //mxd
2013-12-02 09:26:09 +00:00
internal static string LogFile { get { return logfile ; } } //mxd
2009-04-19 18:07:22 +00:00
public static string CompilersPath { get { return compilerspath ; } }
public static string PluginsPath { get { return pluginspath ; } }
public static string SpritesPath { get { return spritespath ; } }
2015-12-30 13:58:58 +00:00
internal static string TexturesPath { get { return texturespath ; } } //mxd
2014-05-13 09:43:58 +00:00
public static string SnippetsPath { get { return snippetspath ; } } //mxd
2014-08-07 10:20:35 +00:00
public static string DefaultScreenshotsPath { get { return screenshotspath ; } } //mxd
2014-02-18 14:04:14 +00:00
public static ICollection < string > CommandArgs { get { return Array . AsReadOnly ( cmdargs ) ; } }
2009-04-19 18:07:22 +00:00
internal static MainForm MainWindow { get { return mainwindow ; } }
public static IMainForm Interface { get { return mainwindow ; } }
public static ProgramConfiguration Settings { get { return settings ; } }
public static ColorCollection Colors { get { return colors ; } }
internal static List < ConfigurationInfo > Configs { get { return configs ; } }
internal static List < NodebuilderInfo > Nodebuilders { get { return nodebuilders ; } }
internal static List < CompilerInfo > Compilers { get { return compilers ; } }
internal static Dictionary < string , ScriptConfiguration > ScriptConfigs { get { return scriptconfigs ; } }
2014-07-11 10:13:26 +00:00
internal static Dictionary < string , ScriptConfiguration > CompiledScriptConfigs { get { return compiledscriptconfigs ; } } //mxd
2009-04-19 18:07:22 +00:00
public static MapManager Map { get { return map ; } }
public static ActionManager Actions { get { return actions ; } }
2014-01-23 13:36:51 +00:00
public static HintsManager Hints { get { return hints ; } } //mxd
2013-09-11 09:47:53 +00:00
internal static PluginManager Plugins { get { return plugins ; } }
2009-04-19 18:07:22 +00:00
public static bool DebugBuild { get { return debugbuild ; } }
internal static TypesManager Types { get { return types ; } }
public static string AutoLoadFile { get { return autoloadfile ; } }
public static string AutoLoadMap { get { return autoloadmap ; } }
public static string AutoLoadConfig { get { return autoloadconfig ; } }
2011-07-26 20:06:38 +00:00
public static bool AutoLoadStrictPatches { get { return autoloadstrictpatches ; } }
public static DataLocationList AutoLoadResources { get { return new DataLocationList ( autoloadresources ) ; } }
2009-04-19 18:07:22 +00:00
public static bool DelayMainWindow { get { return delaymainwindow ; } }
2010-09-15 19:57:12 +00:00
public static bool NoSettings { get { return nosettings ; } }
2009-04-19 18:07:22 +00:00
public static EditingManager Editing { get { return editing ; } }
public static ErrorLogger ErrorLogger { get { return errorlogger ; } }
2016-12-28 12:24:58 +00:00
public static string CommitHash { get { return commithash ; } } //mxd
2012-05-11 12:28:20 +00:00
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Configurations
// This returns the game configuration info by filename
internal 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 ;
}
// This loads and returns a game configuration
2014-12-03 23:15:26 +00:00
private static Configuration LoadGameConfiguration ( string filename )
2009-04-19 18:07:22 +00:00
{
// Make the full filepathname
string filepathname = Path . Combine ( configspath , filename ) ;
// Load configuration
try
{
// Try loading the configuration
2014-02-18 14:04:14 +00:00
Configuration cfg = new Configuration ( filepathname , true ) ;
2009-04-19 18:07:22 +00:00
// Check for erors
2009-07-28 13:40:30 +00:00
if ( cfg . ErrorResult )
2009-04-19 18:07:22 +00:00
{
// Error in configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the game configuration file \"" + filename + "\". " +
2009-07-28 14:04:14 +00:00
"Error in file \"" + cfg . ErrorFile + "\" near line " + cfg . ErrorLine + ": " + cfg . ErrorDescription ) ;
2009-04-19 18:07:22 +00:00
return null ;
}
// Check if this is a Doom Builder 2 config
2014-02-18 14:04:14 +00:00
if ( cfg . ReadSetting ( "type" , "" ) ! = "Doom Builder 2 Game Configuration" )
2009-04-19 18:07:22 +00:00
{
// Old configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the game configuration file \"" + filename + "\". " +
"This configuration is not a Doom Builder 2 game configuration." ) ;
return null ;
}
2014-02-18 14:04:14 +00:00
// Return config
return cfg ;
2009-04-19 18:07:22 +00:00
}
2009-05-10 16:02:08 +00:00
catch ( Exception e )
2009-04-19 18:07:22 +00:00
{
// Unable to load configuration
2009-05-10 16:02:08 +00:00
errorlogger . Add ( ErrorType . Error , "Unable to load the game configuration file \"" + filename + "\". " + e . GetType ( ) . Name + ": " + e . Message ) ;
General . WriteLog ( e . StackTrace ) ;
2009-04-19 18:07:22 +00:00
return null ;
}
}
// This loads all game configurations
private static void LoadAllGameConfigurations ( )
{
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Loading game configurations..." ) ;
// Make array
configs = new List < ConfigurationInfo > ( ) ;
// Go for all cfg files in the configurations directory
2014-02-18 14:04:14 +00:00
string [ ] filenames = Directory . GetFiles ( configspath , "*.cfg" , SearchOption . TopDirectoryOnly ) ;
2009-04-19 18:07:22 +00:00
foreach ( string filepath in filenames )
{
// Check if it can be loaded
2015-12-28 15:01:53 +00:00
Configuration cfg = LoadGameConfiguration ( Path . GetFileName ( filepath ) ) ;
2009-04-19 18:07:22 +00:00
if ( cfg ! = null )
{
2015-12-28 15:01:53 +00:00
string fullfilename = Path . GetFileName ( filepath ) ;
2009-04-19 18:07:22 +00:00
ConfigurationInfo cfginfo = new ConfigurationInfo ( cfg , fullfilename ) ;
// Add to lists
2016-02-22 08:04:06 +00:00
General . WriteLogLine ( "Registered game configuration \"" + cfginfo . Name + "\" from \"" + fullfilename + "\"" ) ;
2009-04-19 18:07:22 +00:00
configs . Add ( cfginfo ) ;
}
}
2014-02-19 09:55:05 +00:00
// Sort the configs
configs . Sort ( ) ;
2009-04-19 18:07:22 +00:00
}
// This loads all nodebuilder configurations
private static void LoadAllNodebuilderConfigurations ( )
{
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Loading nodebuilder configurations..." ) ;
// Make array
nodebuilders = new List < NodebuilderInfo > ( ) ;
// Go for all cfg files in the compilers directory
2014-02-18 14:04:14 +00:00
string [ ] filenames = Directory . GetFiles ( compilerspath , "*.cfg" , SearchOption . AllDirectories ) ;
2009-04-19 18:07:22 +00:00
foreach ( string filepath in filenames )
{
try
{
// Try loading the configuration
2015-12-28 15:01:53 +00:00
Configuration cfg = new Configuration ( filepath , true ) ;
2009-04-19 18:07:22 +00:00
// Check for erors
2009-07-28 13:40:30 +00:00
if ( cfg . ErrorResult )
2009-04-19 18:07:22 +00:00
{
// Error in configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the compiler configuration file \"" + Path . GetFileName ( filepath ) + "\". " +
2013-09-11 09:47:53 +00:00
"Error in file \"" + cfg . ErrorFile + "\" near line " + cfg . ErrorLine + ": " + cfg . ErrorDescription ) ;
2009-04-19 18:07:22 +00:00
}
else
{
// Get structures
2015-12-28 15:01:53 +00:00
IDictionary builderslist = cfg . ReadSetting ( "nodebuilders" , new Hashtable ( ) ) ;
2009-04-19 18:07:22 +00:00
foreach ( DictionaryEntry de in builderslist )
{
// Check if this is a structure
if ( de . Value is IDictionary )
{
try
{
// Make nodebuilder info
nodebuilders . Add ( new NodebuilderInfo ( Path . GetFileName ( filepath ) , de . Key . ToString ( ) , cfg ) ) ;
}
catch ( Exception e )
{
// Unable to load configuration
2016-02-22 08:04:06 +00:00
errorlogger . Add ( ErrorType . Error , "Unable to load the nodebuilder configuration \"" + de . Key + "\" from \"" + Path . GetFileName ( filepath ) + "\". Error: " + e . Message ) ;
2009-04-19 18:07:22 +00:00
}
}
}
}
}
catch ( Exception )
{
// Unable to load configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the compiler configuration file \"" + Path . GetFileName ( filepath ) + "\"." ) ;
}
}
// Sort the list
nodebuilders . Sort ( ) ;
}
// This loads all script configurations
private static void LoadAllScriptConfigurations ( )
{
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Loading script configurations..." ) ;
// Make collection
2014-02-26 14:11:06 +00:00
scriptconfigs = new Dictionary < string , ScriptConfiguration > ( StringComparer . Ordinal ) ;
2014-07-11 10:13:26 +00:00
compiledscriptconfigs = new Dictionary < string , ScriptConfiguration > ( StringComparer . Ordinal ) ; //mxd
2009-04-19 18:07:22 +00:00
// Go for all cfg files in the scripts directory
2015-12-27 21:54:50 +00:00
string [ ] filenames = Directory . GetFiles ( scriptspath , "*.cfg" , SearchOption . TopDirectoryOnly ) ;
2009-04-19 18:07:22 +00:00
foreach ( string filepath in filenames )
{
try
{
// Try loading the configuration
2015-12-27 21:54:50 +00:00
Configuration cfg = new Configuration ( filepath , true ) ;
2009-04-19 18:07:22 +00:00
// Check for erors
2009-07-28 13:40:30 +00:00
if ( cfg . ErrorResult )
2009-04-19 18:07:22 +00:00
{
// Error in configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the script configuration file \"" + Path . GetFileName ( filepath ) + "\". " +
2009-07-28 14:04:14 +00:00
"Error in file \"" + cfg . ErrorFile + "\" near line " + cfg . ErrorLine + ": " + cfg . ErrorDescription ) ;
2009-04-19 18:07:22 +00:00
}
else
{
try
{
// Make script configuration
ScriptConfiguration scfg = new ScriptConfiguration ( cfg ) ;
string filename = Path . GetFileName ( filepath ) ;
scriptconfigs . Add ( filename . ToLowerInvariant ( ) , scfg ) ;
2014-07-11 10:13:26 +00:00
//mxd. Store acc compilers in a separate dictionary
if ( scfg . ScriptType = = ScriptType . ACS )
compiledscriptconfigs . Add ( filename . ToLowerInvariant ( ) , scfg ) ;
2009-04-19 18:07:22 +00:00
}
catch ( Exception e )
{
// Unable to load configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the script configuration \"" + Path . GetFileName ( filepath ) + "\". Error: " + e . Message ) ;
}
}
}
catch ( Exception e )
{
// Unable to load configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the script configuration file \"" + Path . GetFileName ( filepath ) + "\". Error: " + e . Message ) ;
2010-08-18 12:19:37 +00:00
General . WriteLogLine ( e . StackTrace ) ;
2009-04-19 18:07:22 +00:00
}
}
}
// This loads all compiler configurations
private static void LoadAllCompilerConfigurations ( )
{
2014-02-26 14:11:06 +00:00
Dictionary < string , CompilerInfo > addedcompilers = new Dictionary < string , CompilerInfo > ( StringComparer . Ordinal ) ;
2009-04-19 18:07:22 +00:00
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Loading compiler configurations..." ) ;
// Make array
compilers = new List < CompilerInfo > ( ) ;
// Go for all cfg files in the compilers directory
2015-12-27 21:54:50 +00:00
string [ ] filenames = Directory . GetFiles ( compilerspath , "*.cfg" , SearchOption . AllDirectories ) ;
2009-04-19 18:07:22 +00:00
foreach ( string filepath in filenames )
{
try
{
// Try loading the configuration
2015-12-27 21:54:50 +00:00
Configuration cfg = new Configuration ( filepath , true ) ;
2009-04-19 18:07:22 +00:00
// Check for erors
2009-07-28 13:40:30 +00:00
if ( cfg . ErrorResult )
2009-04-19 18:07:22 +00:00
{
// Error in configuration
errorlogger . Add ( ErrorType . Error , "Unable to load the compiler configuration file \"" + Path . GetFileName ( filepath ) + "\". " +
2009-07-28 14:04:14 +00:00
"Error in file \"" + cfg . ErrorFile + "\" near line " + cfg . ErrorLine + ": " + cfg . ErrorDescription ) ;
2009-04-19 18:07:22 +00:00
}
else
{
// Get structures
2015-12-27 21:54:50 +00:00
IDictionary compilerslist = cfg . ReadSetting ( "compilers" , new Hashtable ( ) ) ;
2009-04-19 18:07:22 +00:00
foreach ( DictionaryEntry de in compilerslist )
{
// Check if this is a structure
if ( de . Value is IDictionary )
{
// Make compiler info
CompilerInfo info = new CompilerInfo ( Path . GetFileName ( filepath ) , de . Key . ToString ( ) , Path . GetDirectoryName ( filepath ) , cfg ) ;
if ( ! addedcompilers . ContainsKey ( info . Name ) )
{
compilers . Add ( info ) ;
addedcompilers . Add ( info . Name , info ) ;
}
else
{
errorlogger . Add ( ErrorType . Error , "Compiler \"" + info . Name + "\" is defined more than once. The first definition in " + addedcompilers [ info . Name ] . FileName + " will be used." ) ;
}
}
}
}
}
2009-05-10 16:02:08 +00:00
catch ( Exception e )
2009-04-19 18:07:22 +00:00
{
// Unable to load configuration
2009-05-10 16:02:08 +00:00
errorlogger . Add ( ErrorType . Error , "Unable to load the compiler configuration file \"" + Path . GetFileName ( filepath ) + "\". " + e . GetType ( ) . Name + ": " + e . Message ) ;
2010-08-18 12:19:37 +00:00
General . WriteLogLine ( e . StackTrace ) ;
2009-04-19 18:07:22 +00:00
}
}
}
// This returns a nodebuilder by name
internal static NodebuilderInfo GetNodebuilderByName ( string name )
{
// Go for all nodebuilders
foreach ( NodebuilderInfo n in nodebuilders )
{
// Name matches?
if ( n . Name = = name ) return n ;
}
// Cannot find that nodebuilder
return null ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Startup
// Main program entry
[STAThread]
internal static void Main ( string [ ] args )
{
// Determine states
#if DEBUG
debugbuild = true ;
#else
debugbuild = false ;
2014-02-18 14:04:14 +00:00
//mxd. Custom exception dialog.
AppDomain . CurrentDomain . UnhandledException + = CurrentDomainOnUnhandledException ;
Application . ThreadException + = Application_ThreadException ;
2009-04-19 18:07:22 +00:00
#endif
2013-08-29 10:05:50 +00:00
2009-04-19 18:07:22 +00:00
// Enable OS visual styles
Application . EnableVisualStyles ( ) ;
2016-02-01 22:04:00 +00:00
Application . SetCompatibleTextRenderingDefault ( false ) ; //mxd
//Application.DoEvents(); // This must be here to work around a .NET bug
2016-05-20 15:04:00 +00:00
//mxd. Set CultureInfo
Thread . CurrentThread . CurrentCulture = CultureInfo . InvariantCulture ;
2009-05-04 16:07:14 +00:00
2009-04-19 18:07:22 +00:00
// Set current thread name
Thread . CurrentThread . Name = "Main Application" ;
2009-05-04 16:07:14 +00:00
// Application is running
2015-09-25 13:20:53 +00:00
//appmutex = new Mutex(false, "gzdoombuilder"); //"doombuilder2"
2009-04-19 18:07:22 +00:00
// Get a reference to this assembly
thisasm = Assembly . GetExecutingAssembly ( ) ;
// Find application path
2015-01-03 18:43:37 +00:00
apppath = Path . GetDirectoryName ( Application . ExecutablePath ) ; //mxd. What was the point of using Uri here (other than to prevent lauching from a shared folder)?
2015-04-02 10:57:08 +00:00
// Parse command-line arguments
ParseCommandLineArgs ( args ) ;
2009-04-19 18:07:22 +00:00
// Setup directories
temppath = Path . GetTempPath ( ) ;
2015-04-02 10:57:08 +00:00
settingspath = ( portablemode ? apppath : Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) , SETTINGS_DIR ) ) ; //mxd
2015-09-25 13:20:53 +00:00
restorepath = Path . Combine ( settingspath , MAP_RESTORE_DIR ) ;
2009-04-19 18:07:22 +00:00
configspath = Path . Combine ( apppath , GAME_CONFIGS_DIR ) ;
compilerspath = Path . Combine ( apppath , COMPILERS_DIR ) ;
pluginspath = Path . Combine ( apppath , PLUGINS_DIR ) ;
scriptspath = Path . Combine ( apppath , SCRIPTS_DIR ) ;
2014-05-13 09:43:58 +00:00
snippetspath = Path . Combine ( apppath , SNIPPETS_DIR ) ; //mxd
2014-08-07 10:20:35 +00:00
screenshotspath = Path . Combine ( apppath , SCREENSHOTS_DIR ) . Replace ( Path . AltDirectorySeparatorChar , Path . DirectorySeparatorChar ) ; //mxd
2009-04-19 18:07:22 +00:00
spritespath = Path . Combine ( apppath , SPRITES_DIR ) ;
2015-12-30 13:58:58 +00:00
texturespath = Path . Combine ( apppath , TEXTURES_DIR ) ; //mxd
2009-04-19 18:07:22 +00:00
logfile = Path . Combine ( settingspath , LOG_FILE ) ;
// Make program settings directory if missing
2015-04-02 10:57:08 +00:00
if ( ! portablemode & & ! Directory . Exists ( settingspath ) ) Directory . CreateDirectory ( settingspath ) ;
2016-12-28 12:24:58 +00:00
//mxd. Get git commit hash
var hashes = ( AssemblyHashAttribute [ ] ) thisasm . GetCustomAttributes ( typeof ( AssemblyHashAttribute ) , false ) ;
if ( hashes . Length = = 1 )
{
commithash = hashes [ 0 ] . CommitHash ;
}
else
{
WriteLogLine ( "Unable to determine commit hash. Missing AssemblyHashAttribute?" ) ;
commithash = "0000000" ;
}
2009-04-19 18:07:22 +00:00
// Remove the previous log file and start logging
if ( File . Exists ( logfile ) ) File . Delete ( logfile ) ;
2018-05-27 01:25:16 +00:00
string platform = Environment . Is64BitProcess ? "x64" : "x86" ;
2019-12-24 07:12:45 +00:00
General . WriteLogLine ( "Ultimate Doom Builder R" + thisasm . GetName ( ) . Version . Revision + " (" + platform + ", " + commithash + ") startup" ) ; //mxd
2016-01-15 18:20:47 +00:00
General . WriteLogLine ( "Application path: \"" + apppath + "\"" ) ;
General . WriteLogLine ( "Temporary path: \"" + temppath + "\"" ) ;
General . WriteLogLine ( "Local settings path: \"" + settingspath + "\"" ) ;
General . WriteLogLine ( "Command-line arguments: \"" + string . Join ( " " , args ) + "\"" ) ; //mxd
2009-04-19 18:07:22 +00:00
// Load configuration
General . WriteLogLine ( "Loading program configuration..." ) ;
settings = new ProgramConfiguration ( ) ;
2015-04-02 10:57:08 +00:00
string defaultsettingsfile = Path . Combine ( apppath , DEFAULT_SETTINGS_FILE ) ;
2010-09-15 19:57:12 +00:00
string usersettingsfile = nosettings ? defaultsettingsfile : Path . Combine ( settingspath , SETTINGS_FILE ) ;
if ( settings . Load ( usersettingsfile , defaultsettingsfile ) )
2009-04-19 18:07:22 +00:00
{
// Create error logger
errorlogger = new ErrorLogger ( ) ;
// Create action manager
actions = new ActionManager ( ) ;
// Bind static methods to actions
General . Actions . BindMethods ( typeof ( General ) ) ;
2014-01-23 13:36:51 +00:00
//mxd. Create hints manager
hints = new HintsManager ( ) ;
2009-04-19 18:07:22 +00:00
// Initialize static classes
MapSet . Initialize ( ) ;
2019-09-02 07:06:33 +00:00
2009-04-19 18:07:22 +00:00
// Create main window
General . WriteLogLine ( "Loading main interface window..." ) ;
mainwindow = new MainForm ( ) ;
2009-07-19 20:30:15 +00:00
mainwindow . SetupInterface ( ) ;
2009-04-19 18:07:22 +00:00
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
mainwindow . UpdateThingsFilters ( ) ;
2009-04-19 18:07:22 +00:00
if ( ! delaymainwindow )
{
// Show main window
General . WriteLogLine ( "Showing main interface window..." ) ;
mainwindow . Show ( ) ;
mainwindow . Update ( ) ;
}
// Load plugin manager
General . WriteLogLine ( "Loading plugins..." ) ;
plugins = new PluginManager ( ) ;
plugins . LoadAllPlugins ( ) ;
// Load game configurations
General . WriteLogLine ( "Loading game configurations..." ) ;
LoadAllGameConfigurations ( ) ;
// Create editing modes
General . WriteLogLine ( "Creating editing modes manager..." ) ;
editing = new EditingManager ( ) ;
// Now that all settings have been combined (core & plugins) apply the defaults
General . WriteLogLine ( "Applying configuration settings..." ) ;
actions . ApplyDefaultShortcutKeys ( ) ;
mainwindow . ApplyShortcutKeys ( ) ;
foreach ( ConfigurationInfo info in configs ) info . ApplyDefaults ( null ) ;
// Load compiler configurations
General . WriteLogLine ( "Loading compiler configurations..." ) ;
LoadAllCompilerConfigurations ( ) ;
// Load nodebuilder configurations
General . WriteLogLine ( "Loading nodebuilder configurations..." ) ;
LoadAllNodebuilderConfigurations ( ) ;
// Load script configurations
General . WriteLogLine ( "Loading script configurations..." ) ;
LoadAllScriptConfigurations ( ) ;
// Load color settings
General . WriteLogLine ( "Loading color settings..." ) ;
colors = new ColorCollection ( settings . Config ) ;
// Create types manager
General . WriteLogLine ( "Creating types manager..." ) ;
types = new TypesManager ( ) ;
// Do auto map loading when window is delayed
2016-02-01 22:04:00 +00:00
if ( delaymainwindow ) mainwindow . PerformAutoMapLoading ( ) ;
2009-04-19 18:07:22 +00:00
// All done
General . WriteLogLine ( "Startup done" ) ;
mainwindow . DisplayReady ( ) ;
// Show any errors if preferred
if ( errorlogger . IsErrorAdded )
{
2016-02-22 08:04:06 +00:00
mainwindow . DisplayStatus ( StatusType . Warning , "There were errors during program startup!" ) ;
2009-04-19 18:07:22 +00:00
if ( ! delaymainwindow & & General . Settings . ShowErrorsWindow ) mainwindow . ShowErrors ( ) ;
}
2013-07-10 12:41:49 +00:00
2014-02-19 09:55:05 +00:00
//mxd. Check enabled game configuration
bool noneenabled = true ;
2014-12-03 23:15:26 +00:00
for ( int i = 0 ; i < configs . Count ; i + + )
{
if ( configs [ i ] . Enabled )
{
2014-02-19 09:55:05 +00:00
noneenabled = false ;
break ;
}
}
2014-12-03 23:15:26 +00:00
if ( noneenabled )
{
if ( MessageBox . Show ( "No game configurations are currently enabled.\nPlease enable at least one game configuration" , "Warning" , MessageBoxButtons . OK ) = = DialogResult . OK )
2014-02-19 09:55:05 +00:00
mainwindow . ShowConfiguration ( ) ;
}
2015-07-01 23:09:34 +00:00
2015-09-25 13:20:53 +00:00
//mxd. Check backup files
if ( Directory . Exists ( restorepath ) )
{
foreach ( string backup in Directory . GetFiles ( restorepath , "*.restore" ) )
{
// Remove if created more than a month ago
if ( ( DateTime . Now - File . GetLastWriteTime ( backup ) ) . TotalDays > 30 )
{
File . Delete ( backup ) ;
2016-02-22 08:04:06 +00:00
WriteLogLine ( "Removed \"" + backup + "\" map backup." ) ;
2015-09-25 13:20:53 +00:00
}
}
}
2015-07-01 23:09:34 +00:00
//mxd. Check for updates?
2015-09-06 22:15:21 +00:00
if ( General . Settings . CheckForUpdates ) UpdateChecker . PerformCheck ( false ) ;
2009-04-19 18:07:22 +00:00
// Run application from the main window
Application . Run ( mainwindow ) ;
}
else
{
// Terminate
Terminate ( false ) ;
}
}
// This parses the command line arguments
private static void ParseCommandLineArgs ( string [ ] args )
{
2011-07-26 20:06:38 +00:00
autoloadresources = new DataLocationList ( ) ;
2009-04-19 18:07:22 +00:00
// Keep a copy
cmdargs = args ;
// Make a queue so we can parse the values from left to right
Queue < string > argslist = new Queue < string > ( args ) ;
// Parse list
while ( argslist . Count > 0 )
{
// Get next arg
string curarg = argslist . Dequeue ( ) ;
// Delay window?
if ( string . Compare ( curarg , "-DELAYWINDOW" , true ) = = 0 )
{
// Delay showing the main window
delaymainwindow = true ;
}
2010-09-15 19:57:12 +00:00
// No settings?
else if ( string . Compare ( curarg , "-NOSETTINGS" , true ) = = 0 )
{
// Don't load or save program settings
nosettings = true ;
}
2009-04-19 18:07:22 +00:00
// Map name info?
else if ( string . Compare ( curarg , "-MAP" , true ) = = 0 )
{
// Store next arg as map name information
autoloadmap = argslist . Dequeue ( ) ;
}
// Config name info?
else if ( ( string . Compare ( curarg , "-CFG" , true ) = = 0 ) | |
2010-09-15 19:57:12 +00:00
( string . Compare ( curarg , "-CONFIG" , true ) = = 0 ) )
2009-04-19 18:07:22 +00:00
{
// Store next arg as config filename information
autoloadconfig = argslist . Dequeue ( ) ;
}
2011-07-26 20:06:38 +00:00
// Strict patches rules?
else if ( string . Compare ( curarg , "-STRICTPATCHES" , true ) = = 0 )
{
autoloadstrictpatches = true ;
}
2015-04-02 10:57:08 +00:00
//mxd. Portable mode?
else if ( string . Compare ( curarg , "-PORTABLE" , true ) = = 0 )
{
// Can we write stuff to apppath?
try
{
WindowsIdentity identity = WindowsIdentity . GetCurrent ( ) ;
if ( identity ! = null )
{
WindowsPrincipal principal = new WindowsPrincipal ( identity ) ;
DirectorySecurity security = Directory . GetAccessControl ( apppath ) ;
AuthorizationRuleCollection authrules = security . GetAccessRules ( true , true , typeof ( SecurityIdentifier ) ) ;
foreach ( FileSystemAccessRule accessrule in authrules )
{
SecurityIdentifier id = accessrule . IdentityReference as SecurityIdentifier ;
if ( id = = null | | ! principal . IsInRole ( id ) ) continue ;
if ( ( FileSystemRights . WriteData & accessrule . FileSystemRights ) ! = FileSystemRights . WriteData ) continue ;
if ( accessrule . AccessControlType = = AccessControlType . Allow )
{
portablemode = true ;
}
else if ( accessrule . AccessControlType = = AccessControlType . Deny )
{
//Deny usually overrides any Allow
portablemode = false ;
break ;
}
}
}
}
2015-04-03 12:05:37 +00:00
catch ( Exception ) { }
2015-04-02 10:57:08 +00:00
// Warn the user?
2016-02-22 08:04:06 +00:00
if ( ! portablemode ) ShowWarningMessage ( "Failed to enable portable mode.\nMake sure you have write premission for \"" + apppath + "\" directory." , MessageBoxButtons . OK ) ;
2015-04-02 10:57:08 +00:00
}
2011-07-26 20:06:38 +00:00
// Resource?
else if ( string . Compare ( curarg , "-RESOURCE" , true ) = = 0 )
{
DataLocation dl = new DataLocation ( ) ;
// Parse resource type
string resourcetype = argslist . Dequeue ( ) ;
if ( string . Compare ( resourcetype , "WAD" , true ) = = 0 )
dl . type = DataLocation . RESOURCE_WAD ;
else if ( string . Compare ( resourcetype , "DIR" , true ) = = 0 )
dl . type = DataLocation . RESOURCE_DIRECTORY ;
else if ( string . Compare ( resourcetype , "PK3" , true ) = = 0 )
dl . type = DataLocation . RESOURCE_PK3 ;
else
{
General . WriteLogLine ( "Unexpected resource type \"" + resourcetype + "\" in program parameters. Expected \"wad\", \"dir\" or \"pk3\"." ) ;
break ;
}
// We continue parsing args until an existing filename is found
// all other arguments must be one of the optional keywords.
while ( string . IsNullOrEmpty ( dl . location ) )
{
curarg = argslist . Dequeue ( ) ;
if ( ( string . Compare ( curarg , "ROOTTEXTURES" , true ) = = 0 ) & &
( dl . type = = DataLocation . RESOURCE_DIRECTORY ) )
{
// Load images in the root directory of the resource as textures
dl . option1 = true ;
}
else if ( ( string . Compare ( curarg , "ROOTFLATS" , true ) = = 0 ) & &
( dl . type = = DataLocation . RESOURCE_DIRECTORY ) )
{
// Load images in the root directory of the resource as flats
dl . option2 = true ;
}
else if ( ( string . Compare ( curarg , "STRICTPATCHES" , true ) = = 0 ) & &
( dl . type = = DataLocation . RESOURCE_WAD ) )
{
// Use strict rules for patches
dl . option1 = true ;
}
else if ( string . Compare ( curarg , "NOTEST" , true ) = = 0 )
{
// Exclude this resource from testing parameters
dl . notfortesting = true ;
}
else
{
// This must be an existing file, or it is an invalid argument
if ( dl . type = = DataLocation . RESOURCE_DIRECTORY )
{
if ( Directory . Exists ( curarg ) )
dl . location = curarg ;
}
else
{
if ( File . Exists ( curarg ) )
dl . location = curarg ;
}
if ( string . IsNullOrEmpty ( dl . location ) )
{
General . WriteLogLine ( "Unexpected argument \"" + curarg + "\" in program parameters. Expected a valid resource option or a resource filename." ) ;
break ;
}
}
}
// Add resource to list
if ( ! string . IsNullOrEmpty ( dl . location ) )
autoloadresources . Add ( dl ) ;
}
2009-04-19 18:07:22 +00:00
// Every other arg
else
{
// No command to load file yet?
if ( autoloadfile = = null )
{
// Check if this is a file we can load
if ( File . Exists ( curarg ) )
{
// Load this file!
autoloadfile = curarg . Trim ( ) ;
}
else
{
// Note in the log that we cannot find this file
2010-09-04 11:19:37 +00:00
General . WriteLogLine ( "Cannot find the specified file \"" + curarg + "\"" ) ;
2009-04-19 18:07:22 +00:00
}
}
}
}
}
// This cancels automatic map loading
internal static void CancelAutoMapLoad ( )
{
autoloadfile = null ;
}
2019-08-29 15:56:12 +00:00
#endregion
2009-04-19 18:07:22 +00:00
2019-08-29 15:56:12 +00:00
#region = = = = = = = = = = = = = = = = = = Terminate
2009-04-19 18:07:22 +00:00
// This is for plugins to use
public static void Exit ( bool properexit )
{
// Plugin wants to exit nicely?
if ( properexit )
{
// Close dialog forms first
while ( ( Form . ActiveForm ! = mainwindow ) & & ( Form . ActiveForm ! = null ) )
Form . ActiveForm . Close ( ) ;
// Close main window
mainwindow . Close ( ) ;
}
else
{
// Terminate, no questions asked
Terminate ( true ) ;
}
}
// This terminates the program
internal static void Terminate ( bool properexit )
{
// Terminate properly?
if ( properexit )
{
2016-10-08 21:09:55 +00:00
General . WriteLogLine ( "Termination requested" ) ;
2009-04-19 18:07:22 +00:00
// Unbind static methods from actions
General . Actions . UnbindMethods ( typeof ( General ) ) ;
// Save colors
2016-01-20 17:54:56 +00:00
if ( colors ! = null ) colors . SaveColors ( settings . Config ) ;
2009-04-19 18:07:22 +00:00
// Save action controls
actions . SaveSettings ( ) ;
// Save game configuration settings
2016-01-20 17:54:56 +00:00
if ( configs ! = null ) foreach ( ConfigurationInfo ci in configs ) ci . SaveSettings ( ) ;
2009-04-19 18:07:22 +00:00
// Save settings configuration
2010-09-15 19:57:12 +00:00
if ( ! General . NoSettings )
settings . Save ( Path . Combine ( settingspath , SETTINGS_FILE ) ) ;
2009-04-19 18:07:22 +00:00
// Clean up
2015-09-16 12:10:43 +00:00
if ( map ! = null ) { map . Dispose ( ) ; map = null ; }
if ( editing ! = null ) { editing . Dispose ( ) ; editing = null ; }
2015-10-09 21:57:32 +00:00
if ( plugins ! = null ) { plugins . Dispose ( ) ; plugins = null ; }
2015-09-16 12:10:43 +00:00
if ( mainwindow ! = null ) { mainwindow . Dispose ( ) ; mainwindow = null ; }
if ( actions ! = null ) { actions . Dispose ( ) ; actions = null ; }
if ( types ! = null ) { types . Dispose ( ) ; types = null ; }
2016-03-14 10:25:27 +00:00
2009-04-19 18:07:22 +00:00
// Application ends here and now
General . WriteLogLine ( "Termination done" ) ;
Application . Exit ( ) ;
}
else
{
// Just end now
General . WriteLogLine ( "Immediate program termination" ) ;
Application . Exit ( ) ;
}
// Die.
Process . GetCurrentProcess ( ) . Kill ( ) ;
}
2019-08-29 15:56:12 +00:00
#endregion
2009-04-19 18:07:22 +00:00
2019-08-29 15:56:12 +00:00
#region = = = = = = = = = = = = = = = = = = Management
2009-04-19 18:07:22 +00:00
// This creates a new map
[BeginAction("newmap")]
internal static void NewMap ( )
{
MapOptions newoptions = new MapOptions ( ) ;
2014-11-25 11:52:01 +00:00
2009-04-19 18:07:22 +00:00
// Cancel volatile mode, if any
2014-10-23 08:18:14 +00:00
editing . DisengageVolatileMode ( ) ;
2009-04-19 18:07:22 +00:00
// Ask the user to save changes (if any)
2014-10-23 08:18:14 +00:00
if ( AskSaveMap ( ) )
2009-04-19 18:07:22 +00:00
{
// Open map options dialog
2014-11-25 11:52:01 +00:00
MapOptionsForm optionswindow = new MapOptionsForm ( newoptions , true ) ;
2009-04-19 18:07:22 +00:00
if ( optionswindow . ShowDialog ( mainwindow ) = = DialogResult . OK )
{
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Creating new map..." ) ;
Cursor . Current = Cursors . WaitCursor ;
// Clear the display
mainwindow . ClearDisplay ( ) ;
2014-01-17 13:48:06 +00:00
mainwindow . RemoveHintsDocker ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Trash the current map, if any
if ( map ! = null ) map . Dispose ( ) ;
2009-07-22 15:16:28 +00:00
// Let the plugins know
plugins . OnMapNewBegin ( ) ;
2009-04-19 18:07:22 +00:00
2014-11-25 11:52:01 +00:00
// Clear old errors (mxd)
errorlogger . Clear ( ) ;
2009-04-19 18:07:22 +00:00
// Create map manager with given options
map = new MapManager ( ) ;
2015-03-23 14:19:23 +00:00
if ( map . InitializeNewMap ( newoptions ) )
{
settings . FindDefaultDrawSettings ( ) ; //mxd
// Let the plugins know
plugins . OnMapNewEnd ( ) ;
// All done
mainwindow . SetupInterface ( ) ;
mainwindow . RedrawDisplay ( ) ;
mainwindow . UpdateThingsFilters ( ) ;
2015-07-30 23:48:16 +00:00
mainwindow . UpdateLinedefColorPresets ( ) ; //mxd
2015-03-23 14:19:23 +00:00
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
mainwindow . AddHintsDocker ( ) ; //mxd
2015-03-23 14:19:23 +00:00
mainwindow . UpdateGZDoomPanel ( ) ; //mxd
mainwindow . HideInfo ( ) ; //mxd
}
else
2009-04-19 18:07:22 +00:00
{
// Unable to create map manager
map . Dispose ( ) ;
map = null ;
// Show splash logo on display
mainwindow . ShowSplashDisplay ( ) ;
}
if ( errorlogger . IsErrorAdded )
{
// Show any errors if preferred
mainwindow . DisplayStatus ( StatusType . Warning , "There were errors during loading!" ) ;
2014-10-23 08:18:14 +00:00
if ( ! delaymainwindow & & settings . ShowErrorsWindow ) mainwindow . ShowErrors ( ) ;
2009-04-19 18:07:22 +00:00
}
else
mainwindow . DisplayReady ( ) ;
2016-11-10 19:18:06 +00:00
//mxd. Also reset the clock...
MainWindow . ResetClock ( ) ;
2009-04-19 18:07:22 +00:00
Cursor . Current = Cursors . Default ;
}
}
}
// This closes the current map
[BeginAction("closemap")]
internal static void ActionCloseMap ( ) { CloseMap ( ) ; }
internal static bool CloseMap ( )
{
// Cancel volatile mode, if any
2014-10-23 08:18:14 +00:00
editing . DisengageVolatileMode ( ) ;
2009-04-19 18:07:22 +00:00
// Ask the user to save changes (if any)
2014-10-23 08:18:14 +00:00
if ( AskSaveMap ( ) )
2009-04-19 18:07:22 +00:00
{
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Closing map..." ) ;
2014-10-23 08:18:14 +00:00
WriteLogLine ( "Unloading map..." ) ;
2009-04-19 18:07:22 +00:00
Cursor . Current = Cursors . WaitCursor ;
// Trash the current map
if ( map ! = null ) map . Dispose ( ) ;
map = null ;
// Clear errors
2014-10-23 08:18:14 +00:00
errorlogger . Clear ( ) ;
2015-01-11 19:42:57 +00:00
//mxd. Clear Console
#if DEBUG
DebugConsole . Clear ( ) ;
#endif
2009-04-19 18:07:22 +00:00
// Show splash logo on display
mainwindow . ShowSplashDisplay ( ) ;
// Done
Cursor . Current = Cursors . Default ;
editing . UpdateCurrentEditModes ( ) ;
2009-07-19 20:30:15 +00:00
mainwindow . SetupInterface ( ) ;
2009-04-19 18:07:22 +00:00
mainwindow . RedrawDisplay ( ) ;
mainwindow . HideInfo ( ) ;
2009-07-05 10:26:57 +00:00
mainwindow . UpdateThingsFilters ( ) ;
2013-09-11 09:47:53 +00:00
//mxd
2015-07-30 23:48:16 +00:00
mainwindow . UpdateLinedefColorPresets ( ) ;
2014-01-08 09:46:57 +00:00
mainwindow . RemoveHintsDocker ( ) ;
2013-09-11 09:47:53 +00:00
mainwindow . UpdateGZDoomPanel ( ) ;
2009-04-19 18:07:22 +00:00
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
mainwindow . DisplayReady ( ) ;
2014-10-23 08:18:14 +00:00
WriteLogLine ( "Map unload done" ) ;
2009-04-19 18:07:22 +00:00
return true ;
}
else
{
// User cancelled
return false ;
}
}
// This loads a map from file
[BeginAction("openmap")]
internal static void OpenMap ( )
{
// Cancel volatile mode, if any
2014-10-23 08:18:14 +00:00
editing . DisengageVolatileMode ( ) ;
2009-04-19 18:07:22 +00:00
// Open map file dialog
2014-03-20 13:04:28 +00:00
OpenFileDialog openfile = new OpenFileDialog ( ) ;
2009-04-19 18:07:22 +00:00
openfile . Filter = "Doom WAD Files (*.wad)|*.wad" ;
openfile . Title = "Open Map" ;
2014-05-05 09:59:20 +00:00
if ( ! string . IsNullOrEmpty ( settings . LastUsedMapFolder ) & & Directory . Exists ( settings . LastUsedMapFolder ) ) //mxd
2016-03-14 10:25:27 +00:00
{
openfile . RestoreDirectory = true ;
openfile . InitialDirectory = settings . LastUsedMapFolder ;
}
2009-04-19 18:07:22 +00:00
openfile . AddExtension = false ;
openfile . CheckFileExists = true ;
openfile . Multiselect = false ;
openfile . ValidateNames = true ;
if ( openfile . ShowDialog ( mainwindow ) = = DialogResult . OK )
{
// Update main window
mainwindow . Update ( ) ;
// Open map file
2011-07-26 20:06:38 +00:00
OpenMapFile ( openfile . FileName , null ) ;
2009-04-19 18:07:22 +00:00
}
2009-04-26 21:38:45 +00:00
openfile . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
}
2013-07-23 14:25:03 +00:00
2014-12-03 09:06:05 +00:00
//mxd. This loads a different map from same wad file without reloading resources
2013-07-23 14:25:03 +00:00
[BeginAction("openmapincurrentwad")]
2014-10-23 08:18:14 +00:00
internal static void OpenMapInCurrentWad ( )
{
2015-12-28 15:01:53 +00:00
if ( map = = null | | string . IsNullOrEmpty ( map . FilePathName ) | | ! File . Exists ( map . FilePathName ) )
2014-10-23 08:18:14 +00:00
{
2014-03-23 09:24:42 +00:00
Interface . DisplayStatus ( StatusType . Warning , "Unable to open map from current WAD!" ) ;
return ;
}
2013-07-25 12:39:40 +00:00
// Cancel volatile mode, if any
Editing . DisengageVolatileMode ( ) ;
// Ask the user to save changes (if any)
if ( ! AskSaveMap ( ) ) return ;
2013-07-23 14:25:03 +00:00
2013-07-25 12:39:40 +00:00
// Open map options dialog
ChangeMapForm changemapwindow = new ChangeMapForm ( map . FilePathName , map . Options ) ;
if ( changemapwindow . ShowDialog ( mainwindow ) ! = DialogResult . OK ) return ;
// Display status
2016-02-22 08:04:06 +00:00
mainwindow . DisplayStatus ( StatusType . Busy , "Switching to map \"" + changemapwindow . Options . CurrentName + "\"..." ) ;
WriteLogLine ( "Switching to map \"" + changemapwindow . Options . CurrentName + "\"..." ) ;
2013-07-25 12:39:40 +00:00
Cursor . Current = Cursors . WaitCursor ;
2015-09-16 12:10:43 +00:00
// Let the plugins know
plugins . OnMapCloseBegin ( ) ;
2013-07-25 12:39:40 +00:00
// Clear the display
mainwindow . ClearDisplay ( ) ;
2014-01-17 13:48:06 +00:00
mainwindow . RemoveHintsDocker ( ) ; //mxd
2013-07-25 12:39:40 +00:00
2015-07-13 11:20:02 +00:00
//mxd. Close the script editor
map . CloseScriptEditor ( false ) ;
2013-07-25 12:39:40 +00:00
// Let the plugins know
2015-09-16 12:10:43 +00:00
plugins . OnMapCloseEnd ( ) ;
2013-07-25 12:39:40 +00:00
plugins . OnMapOpenBegin ( ) ;
// Clear old errors
ErrorLogger . Clear ( ) ;
if ( ! map . InitializeSwitchMap ( changemapwindow . Options ) ) return ;
2014-10-23 08:18:14 +00:00
// Clear undo history
map . UndoRedo . ClearAllUndos ( ) ;
map . UndoRedo . ClearAllRedos ( ) ;
2013-11-21 10:53:11 +00:00
settings . FindDefaultDrawSettings ( ) ; //mxd
2013-07-25 12:39:40 +00:00
// Let the plugins know
plugins . OnMapOpenEnd ( ) ;
// All done
mainwindow . SetupInterface ( ) ;
mainwindow . RedrawDisplay ( ) ;
mainwindow . UpdateThingsFilters ( ) ;
2015-07-30 23:48:16 +00:00
mainwindow . UpdateLinedefColorPresets ( ) ; //mxd
2013-07-25 12:39:40 +00:00
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
mainwindow . HideInfo ( ) ;
2014-01-08 09:46:57 +00:00
mainwindow . AddHintsDocker ( ) ; //mxd
2014-10-23 08:18:14 +00:00
mainwindow . UpdateGZDoomPanel ( ) ; //mxd
2013-07-23 14:25:03 +00:00
2014-10-23 08:18:14 +00:00
if ( errorlogger . IsErrorAdded )
2013-07-25 12:39:40 +00:00
{
// Show any errors if preferred
mainwindow . DisplayStatus ( StatusType . Warning , "There were errors during loading!" ) ;
2015-12-28 15:01:53 +00:00
if ( ! delaymainwindow & & Settings . ShowErrorsWindow )
2013-07-25 12:39:40 +00:00
mainwindow . ShowErrors ( ) ;
2014-10-23 08:18:14 +00:00
}
else
{
2013-07-25 12:39:40 +00:00
mainwindow . DisplayReady ( ) ;
}
Cursor . Current = Cursors . Default ;
2013-07-23 14:25:03 +00:00
}
2009-04-19 18:07:22 +00:00
// This opens the specified file
2011-07-26 20:06:38 +00:00
internal static void OpenMapFile ( string filename , MapOptions options )
2009-04-19 18:07:22 +00:00
{
// Cancel volatile mode, if any
2014-10-23 08:18:14 +00:00
editing . DisengageVolatileMode ( ) ;
2009-04-19 18:07:22 +00:00
// Ask the user to save changes (if any)
2014-10-23 08:18:14 +00:00
if ( AskSaveMap ( ) )
2009-04-19 18:07:22 +00:00
{
// Open map options dialog
2014-03-20 13:04:28 +00:00
OpenMapOptionsForm openmapwindow = ( options ! = null ? new OpenMapOptionsForm ( filename , options ) : new OpenMapOptionsForm ( filename ) ) ;
2011-07-26 20:06:38 +00:00
2009-04-19 18:07:22 +00:00
if ( openmapwindow . ShowDialog ( mainwindow ) = = DialogResult . OK )
OpenMapFileWithOptions ( filename , openmapwindow . Options ) ;
}
}
// This opens the specified file without dialog
internal static void OpenMapFileWithOptions ( string filename , MapOptions options )
{
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Opening map file..." ) ;
Cursor . Current = Cursors . WaitCursor ;
// Clear the display
mainwindow . ClearDisplay ( ) ;
2014-01-17 13:48:06 +00:00
mainwindow . RemoveHintsDocker ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Trash the current map, if any
if ( map ! = null ) map . Dispose ( ) ;
2009-07-22 15:16:28 +00:00
// Let the plugins know
plugins . OnMapOpenBegin ( ) ;
2013-07-25 12:39:40 +00:00
// mxd. Clear old errors
2014-10-23 08:18:14 +00:00
errorlogger . Clear ( ) ;
2009-04-19 18:07:22 +00:00
// Create map manager with given options
map = new MapManager ( ) ;
if ( map . InitializeOpenMap ( filename , options ) )
{
// Add recent file
mainwindow . AddRecentFile ( filename ) ;
2012-10-03 18:46:13 +00:00
//mxd
2013-04-11 09:27:16 +00:00
mainwindow . UpdateGZDoomPanel ( ) ;
2014-05-05 09:59:20 +00:00
settings . LastUsedMapFolder = Path . GetDirectoryName ( filename ) ;
2014-09-17 12:46:47 +00:00
settings . FindDefaultDrawSettings ( ) ;
// Let the plugins know
plugins . OnMapOpenEnd ( ) ;
// All done
mainwindow . SetupInterface ( ) ;
mainwindow . UpdateThingsFilters ( ) ;
2015-07-30 23:48:16 +00:00
mainwindow . UpdateLinedefColorPresets ( ) ; //mxd
2014-09-17 12:46:47 +00:00
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
mainwindow . HideInfo ( ) ;
2014-09-17 12:46:47 +00:00
mainwindow . AddHintsDocker ( ) ; //mxd
2015-03-11 11:38:25 +00:00
2015-07-09 22:32:12 +00:00
//mxd. Center map in screen or on stored coordinates. Done here to avoid the view jerking around when updating the interface.
2016-03-18 12:52:12 +00:00
ClassicMode mode = Editing . Mode as ClassicMode ;
if ( mode ! = null )
2015-07-09 22:32:12 +00:00
{
if ( options ! = null & & options . ViewPosition . IsFinite ( ) & & ! float . IsNaN ( options . ViewScale ) )
mode . CenterOnCoordinates ( options . ViewPosition , options . ViewScale ) ;
else
mode . CenterInScreen ( ) ;
}
2015-03-11 11:38:25 +00:00
mainwindow . RedrawDisplay ( ) ;
2009-04-19 18:07:22 +00:00
}
else
{
// Unable to create map manager
map . Dispose ( ) ;
map = null ;
// Show splash logo on display
mainwindow . ShowSplashDisplay ( ) ;
}
if ( errorlogger . IsErrorAdded )
{
// Show any errors if preferred
mainwindow . DisplayStatus ( StatusType . Warning , "There were errors during loading!" ) ;
2014-10-23 08:18:14 +00:00
if ( ! delaymainwindow & & settings . ShowErrorsWindow ) mainwindow . ShowErrors ( ) ;
2009-04-19 18:07:22 +00:00
}
else
mainwindow . DisplayReady ( ) ;
Cursor . Current = Cursors . Default ;
}
// This saves the current map
// Returns tre when saved, false when cancelled or failed
[BeginAction("savemap")]
internal static void ActionSaveMap ( ) { SaveMap ( ) ; }
internal static bool SaveMap ( )
{
2014-03-23 09:24:42 +00:00
if ( map = = null ) return false ;
2014-03-23 09:08:51 +00:00
bool result = false ;
2009-04-19 18:07:22 +00:00
// Cancel volatile mode, if any
2014-10-23 08:18:14 +00:00
editing . DisengageVolatileMode ( ) ;
2009-04-19 18:07:22 +00:00
// Check if a wad file is known
2016-02-01 22:04:00 +00:00
if ( string . IsNullOrEmpty ( map . FilePathName ) )
2009-04-19 18:07:22 +00:00
{
// Call to SaveMapAs
result = SaveMapAs ( ) ;
}
else
{
2014-09-24 11:47:52 +00:00
//mxd. Do we need to save the map?
2015-12-28 15:01:53 +00:00
if ( ! map . MapSaveRequired ( map . FilePathName , SavePurpose . Normal ) )
2014-09-24 11:47:52 +00:00
{
// Still save settings file
result = map . SaveSettingsFile ( map . FilePathName ) ;
// Display status
2014-11-25 11:52:01 +00:00
mainwindow . DisplayStatus ( StatusType . Info , "Map is up to date. Updated map settings file." ) ;
2014-09-24 11:47:52 +00:00
// All done
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
return result ;
2014-09-24 11:47:52 +00:00
}
2009-04-19 18:07:22 +00:00
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Saving map file..." ) ;
Cursor . Current = Cursors . WaitCursor ;
// Set this to false so we can see if errors are added
2014-10-23 08:18:14 +00:00
errorlogger . IsErrorAdded = false ;
2009-04-19 18:07:22 +00:00
// Save the map
2014-10-23 08:18:14 +00:00
plugins . OnMapSaveBegin ( SavePurpose . Normal ) ;
2009-08-23 13:55:49 +00:00
if ( map . SaveMap ( map . FilePathName , SavePurpose . Normal ) )
2009-04-19 18:07:22 +00:00
{
// Add recent file
mainwindow . AddRecentFile ( map . FilePathName ) ;
result = true ;
}
2014-10-23 08:18:14 +00:00
plugins . OnMapSaveEnd ( SavePurpose . Normal ) ;
2009-04-19 18:07:22 +00:00
// All done
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
if ( errorlogger . IsErrorAdded )
2009-04-19 18:07:22 +00:00
{
// Show any errors if preferred
mainwindow . DisplayStatus ( StatusType . Warning , "There were errors during saving!" ) ;
2014-10-23 08:18:14 +00:00
if ( ! delaymainwindow & & settings . ShowErrorsWindow ) mainwindow . ShowErrors ( ) ;
2009-04-19 18:07:22 +00:00
}
2016-02-24 11:34:35 +00:00
else if ( result )
{
2009-04-19 18:07:22 +00:00
mainwindow . DisplayStatus ( StatusType . Info , "Map saved in " + map . FileTitle + "." ) ;
2016-02-24 11:34:35 +00:00
}
else
{
mainwindow . DisplayStatus ( StatusType . Info , "Map saving cancelled." ) ; //mxd
}
2009-04-19 18:07:22 +00:00
Cursor . Current = Cursors . Default ;
}
2016-08-29 10:06:16 +00:00
//mxd. Also reset the clock...
MainWindow . ResetClock ( ) ;
2009-04-19 18:07:22 +00:00
return result ;
}
// This saves the current map as a different file
// Returns tre when saved, false when cancelled or failed
[BeginAction("savemapas")]
internal static void ActionSaveMapAs ( ) { SaveMapAs ( ) ; }
internal static bool SaveMapAs ( )
{
2014-03-23 09:24:42 +00:00
if ( map = = null ) return false ;
2014-03-23 09:08:51 +00:00
bool result = false ;
2010-08-01 20:52:56 +00:00
2009-04-19 18:07:22 +00:00
// Cancel volatile mode, if any
2014-10-23 08:18:14 +00:00
editing . DisengageVolatileMode ( ) ;
2009-04-19 18:07:22 +00:00
// Show save as dialog
2014-03-23 09:08:51 +00:00
SaveFileDialog savefile = new SaveFileDialog ( ) ;
2009-04-19 18:07:22 +00:00
savefile . Filter = "Doom WAD Files (*.wad)|*.wad" ;
savefile . Title = "Save Map As" ;
savefile . AddExtension = true ;
savefile . CheckPathExists = true ;
savefile . OverwritePrompt = true ;
savefile . ValidateNames = true ;
2013-03-26 12:31:07 +00:00
savefile . FileName = map . FileTitle ; //mxd
2016-03-14 10:25:27 +00:00
if ( map . FilePathName . Length > 0 ) //mxd
{
savefile . RestoreDirectory = true ;
savefile . InitialDirectory = Path . GetDirectoryName ( map . FilePathName ) ;
}
2009-04-19 18:07:22 +00:00
if ( savefile . ShowDialog ( mainwindow ) = = DialogResult . OK )
{
2010-08-12 14:21:06 +00:00
// Check if we're saving to the same file as the original.
// Because some muppets use Save As even when saving to the same file.
2010-08-13 05:47:55 +00:00
string currentfilename = ( map . FilePathName . Length > 0 ) ? Path . GetFullPath ( map . FilePathName ) . ToLowerInvariant ( ) : "" ;
2010-08-12 14:21:06 +00:00
string savefilename = Path . GetFullPath ( savefile . FileName ) . ToLowerInvariant ( ) ;
if ( currentfilename = = savefilename )
2009-04-19 18:07:22 +00:00
{
2010-08-12 14:21:06 +00:00
SaveMap ( ) ;
2009-04-19 18:07:22 +00:00
}
2010-08-12 14:21:06 +00:00
else
2009-04-19 18:07:22 +00:00
{
2010-08-12 14:21:06 +00:00
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Saving map file..." ) ;
Cursor . Current = Cursors . WaitCursor ;
// Set this to false so we can see if errors are added
2014-10-23 08:18:14 +00:00
errorlogger . IsErrorAdded = false ;
2010-08-12 14:21:06 +00:00
// Save the map
2014-10-23 08:18:14 +00:00
plugins . OnMapSaveBegin ( SavePurpose . AsNewFile ) ;
2010-08-12 14:21:06 +00:00
if ( map . SaveMap ( savefile . FileName , SavePurpose . AsNewFile ) )
{
// Add recent file
mainwindow . AddRecentFile ( map . FilePathName ) ;
2014-05-05 09:59:20 +00:00
settings . LastUsedMapFolder = Path . GetDirectoryName ( map . FilePathName ) ; //mxd
2010-08-12 14:21:06 +00:00
result = true ;
}
2014-10-23 08:18:14 +00:00
plugins . OnMapSaveEnd ( SavePurpose . AsNewFile ) ;
2010-08-12 14:21:06 +00:00
// All done
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
if ( errorlogger . IsErrorAdded )
2010-08-12 14:21:06 +00:00
{
// Show any errors if preferred
mainwindow . DisplayStatus ( StatusType . Warning , "There were errors during saving!" ) ;
2016-02-24 11:34:35 +00:00
if ( ! delaymainwindow & & settings . ShowErrorsWindow ) mainwindow . ShowErrors ( ) ;
2010-08-12 14:21:06 +00:00
}
2016-02-24 11:34:35 +00:00
else if ( result )
{
2010-08-12 14:21:06 +00:00
mainwindow . DisplayStatus ( StatusType . Info , "Map saved in " + map . FileTitle + "." ) ;
2016-02-24 11:34:35 +00:00
}
else
{
mainwindow . DisplayStatus ( StatusType . Info , "Map saving cancelled." ) ; //mxd
}
2010-08-12 14:21:06 +00:00
Cursor . Current = Cursors . Default ;
2009-04-19 18:07:22 +00:00
}
}
2009-04-26 21:38:45 +00:00
savefile . Dispose ( ) ;
2016-08-29 10:06:16 +00:00
//mxd. Also reset the clock...
MainWindow . ResetClock ( ) ;
2009-04-19 18:07:22 +00:00
return result ;
}
// This saves the current map as a different file
// Returns tre when saved, false when cancelled or failed
[BeginAction("savemapinto")]
internal static void ActionSaveMapInto ( ) { SaveMapInto ( ) ; }
internal static bool SaveMapInto ( )
{
2014-03-23 09:24:42 +00:00
if ( map = = null ) return false ;
2014-03-23 09:08:51 +00:00
bool result = false ;
2010-08-01 20:52:56 +00:00
2009-04-19 18:07:22 +00:00
// Cancel volatile mode, if any
2014-10-23 08:18:14 +00:00
editing . DisengageVolatileMode ( ) ;
2009-04-19 18:07:22 +00:00
// Show save as dialog
2014-03-23 09:08:51 +00:00
SaveFileDialog savefile = new SaveFileDialog ( ) ;
2009-04-19 18:07:22 +00:00
savefile . Filter = "Doom WAD Files (*.wad)|*.wad" ;
savefile . Title = "Save Map Into" ;
savefile . AddExtension = true ;
savefile . CheckPathExists = true ;
savefile . OverwritePrompt = false ;
savefile . ValidateNames = true ;
if ( savefile . ShowDialog ( mainwindow ) = = DialogResult . OK )
{
// Display status
mainwindow . DisplayStatus ( StatusType . Busy , "Saving map file..." ) ;
Cursor . Current = Cursors . WaitCursor ;
// Set this to false so we can see if errors are added
2014-10-23 08:18:14 +00:00
errorlogger . IsErrorAdded = false ;
2009-04-19 18:07:22 +00:00
// Save the map
2014-10-23 08:18:14 +00:00
plugins . OnMapSaveBegin ( SavePurpose . IntoFile ) ;
2009-08-23 13:55:49 +00:00
if ( map . SaveMap ( savefile . FileName , SavePurpose . IntoFile ) )
2009-04-19 18:07:22 +00:00
{
// Add recent file
mainwindow . AddRecentFile ( map . FilePathName ) ;
result = true ;
}
2014-10-23 08:18:14 +00:00
plugins . OnMapSaveEnd ( SavePurpose . IntoFile ) ;
2009-04-19 18:07:22 +00:00
// All done
mainwindow . UpdateInterface ( ) ;
2017-02-07 18:02:31 +00:00
if ( errorlogger . IsErrorAdded )
2009-04-19 18:07:22 +00:00
{
// Show any errors if preferred
mainwindow . DisplayStatus ( StatusType . Warning , "There were errors during saving!" ) ;
2014-10-23 08:18:14 +00:00
if ( ! delaymainwindow & & settings . ShowErrorsWindow ) mainwindow . ShowErrors ( ) ;
2009-04-19 18:07:22 +00:00
}
2016-02-24 11:34:35 +00:00
else if ( result )
{
mainwindow . DisplayStatus ( StatusType . Info , "Map saved in " + map . FileTitle + "." ) ;
}
2009-04-19 18:07:22 +00:00
else
2016-02-24 11:34:35 +00:00
{
mainwindow . DisplayStatus ( StatusType . Info , "Map saving cancelled." ) ; //mxd
}
2009-04-19 18:07:22 +00:00
Cursor . Current = Cursors . Default ;
}
2009-04-26 21:38:45 +00:00
savefile . Dispose ( ) ;
2016-08-29 10:06:16 +00:00
//mxd. Also reset the clock...
MainWindow . ResetClock ( ) ;
2009-04-19 18:07:22 +00:00
return result ;
}
// This asks to save the map if needed
// Returns false when action was cancelled
internal static bool AskSaveMap ( )
{
// Map open and not saved?
if ( map ! = null )
{
if ( map . IsChanged )
{
// Ask to save changes
2014-10-23 08:18:14 +00:00
DialogResult result = MessageBox . Show ( mainwindow , "Do you want to save changes to " + map . FileTitle + " (" + map . Options . CurrentName + ")?" , Application . ProductName , MessageBoxButtons . YesNoCancel , MessageBoxIcon . Question ) ;
2009-04-19 18:07:22 +00:00
if ( result = = DialogResult . Yes )
{
// Save map
if ( SaveMap ( ) )
{
// Ask to save changes to scripts
return map . AskSaveScriptChanges ( ) ;
}
else
{
// Failed to save map
return false ;
}
}
else if ( result = = DialogResult . Cancel )
{
// Abort
return false ;
}
else
{
// Ask to save changes to scripts
return map . AskSaveScriptChanges ( ) ;
}
}
else
{
// Ask to save changes to scripts
return map . AskSaveScriptChanges ( ) ;
}
}
else
{
return true ;
}
}
2019-08-29 15:56:12 +00:00
#endregion
2009-04-19 18:07:22 +00:00
2019-08-29 15:56:12 +00:00
#region = = = = = = = = = = = = = = = = = = Debug
2009-04-19 18:07:22 +00:00
// This shows a major failure
public static void Fail ( string message )
{
2014-10-23 08:18:14 +00:00
WriteLogLine ( "FAIL: " + message ) ;
2012-05-11 12:28:20 +00:00
#if DEBUG
2009-04-19 18:07:22 +00:00
Debug . Fail ( message ) ;
2012-05-11 12:28:20 +00:00
#else
2014-10-23 08:18:14 +00:00
//mxd. Lets notify the user about our Epic Failure before crashing...
2013-09-11 09:47:53 +00:00
ShowErrorMessage ( message , MessageBoxButtons . OK ) ;
2012-05-11 12:28:20 +00:00
#endif
2009-04-19 18:07:22 +00:00
Terminate ( false ) ;
}
// This outputs log information
public static void WriteLogLine ( string line )
{
2013-12-17 13:18:44 +00:00
#if DEBUG
2014-11-13 09:43:39 +00:00
// Output to consoles
2009-04-19 18:07:22 +00:00
Console . WriteLine ( line ) ;
2014-12-03 23:15:26 +00:00
DebugConsole . WriteLine ( DebugMessageType . LOG , line ) ; //mxd
2013-12-17 13:18:44 +00:00
#endif
2009-04-19 18:07:22 +00:00
// Write to log file
try { File . AppendAllText ( logfile , line + Environment . NewLine ) ; }
catch ( Exception ) { }
}
// This outputs log information
public static void WriteLog ( string text )
{
2013-12-17 13:18:44 +00:00
#if DEBUG
2014-11-13 09:43:39 +00:00
// Output to consoles
2009-04-19 18:07:22 +00:00
Console . Write ( text ) ;
2014-12-03 23:15:26 +00:00
DebugConsole . Write ( DebugMessageType . LOG , text ) ;
2013-12-17 13:18:44 +00:00
#endif
2009-04-19 18:07:22 +00:00
// Write to log file
try { File . AppendAllText ( logfile , text ) ; }
catch ( Exception ) { }
}
2019-08-29 15:56:12 +00:00
#endregion
2009-04-19 18:07:22 +00:00
2019-08-29 15:56:12 +00:00
#region = = = = = = = = = = = = = = = = = = Tools
2009-04-19 18:07:22 +00:00
// This swaps two pointers
public static void Swap < T > ( ref T a , ref T b )
{
T t = a ;
a = b ;
b = t ;
}
2009-08-14 10:45:22 +00:00
// This calculates the bits needed for a number
public static int BitsForInt ( int v )
{
2014-10-23 08:18:14 +00:00
int [ ] LOGTABLE = new [ ] {
2009-08-14 10:45:22 +00:00
0 , 0 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 } ;
int r ; // r will be lg(v)
int t , tt ;
if ( Int2Bool ( tt = v > > 16 ) )
{
r = Int2Bool ( t = tt > > 8 ) ? 24 + LOGTABLE [ t ] : 16 + LOGTABLE [ tt ] ;
}
else
{
r = Int2Bool ( t = v > > 8 ) ? 8 + LOGTABLE [ t ] : LOGTABLE [ v ] ;
}
return r ;
}
2009-04-19 18:07:22 +00:00
// This clamps a value
public static float Clamp ( float value , float min , float max )
{
return Math . Min ( Math . Max ( min , value ) , max ) ;
}
2020-05-18 16:14:54 +00:00
// This clamps a value
public static double Clamp ( double value , double min , double max )
{
return Math . Min ( Math . Max ( min , value ) , max ) ;
}
2009-04-19 18:07:22 +00:00
// This clamps a value
public static int Clamp ( int value , int min , int max )
{
return Math . Min ( Math . Max ( min , value ) , max ) ;
}
// This clamps a value
public static byte Clamp ( byte value , byte min , byte max )
{
return Math . Min ( Math . Max ( min , value ) , max ) ;
}
2012-05-11 12:28:20 +00:00
2013-09-11 09:47:53 +00:00
//mxd. This clamps angle between 0 and 359
2014-10-23 08:18:14 +00:00
public static int ClampAngle ( int angle )
{
2016-09-07 17:46:25 +00:00
angle % = 360 ;
if ( angle < 0 ) angle + = 360 ;
return angle ;
2013-09-11 09:47:53 +00:00
}
2012-06-26 08:54:25 +00:00
2013-09-11 09:47:53 +00:00
//mxd. This clamps angle between 0 and 359
2014-10-23 08:18:14 +00:00
public static float ClampAngle ( float angle )
{
2016-09-07 17:46:25 +00:00
angle % = 360 ;
if ( angle < 0 ) angle + = 360 ;
return angle ;
2013-07-10 12:41:49 +00:00
}
2020-05-18 16:14:54 +00:00
// This clamps angle between 0 and 359
public static double ClampAngle ( double angle )
{
angle % = 360 ;
if ( angle < 0 ) angle + = 360 ;
return angle ;
}
2013-07-10 12:41:49 +00:00
//mxd
2014-10-23 08:18:14 +00:00
public static int Random ( int min , int max )
{
2013-07-11 11:43:49 +00:00
return random . Next ( min , max + 1 ) ; //because max is never rolled
2013-07-10 12:41:49 +00:00
}
2013-07-10 13:40:18 +00:00
//mxd
2014-10-23 08:18:14 +00:00
public static float Random ( float min , float max )
{
2013-07-10 13:40:18 +00:00
return ( float ) Math . Round ( min + ( max - min ) * random . NextDouble ( ) , 2 ) ;
}
2020-05-22 19:39:18 +00:00
public static double Random ( double min , double max )
{
return Math . Round ( min + ( max - min ) * random . NextDouble ( ) , 2 ) ;
}
2009-04-19 18:07:22 +00:00
// This returns an element from a collection by index
public static T GetByIndex < T > ( ICollection < T > collection , int index )
{
IEnumerator < T > e = collection . GetEnumerator ( ) ;
for ( int i = - 1 ; i < index ; i + + ) e . MoveNext ( ) ;
return e . Current ;
}
// This returns the next power of 2
2016-01-11 13:00:52 +00:00
/ * public static int NextPowerOf2 ( int v )
2009-04-19 18:07:22 +00:00
{
int p = 0 ;
// Continue increasing until higher than v
while ( Math . Pow ( 2 , p ) < v ) p + + ;
// Return power
return ( int ) Math . Pow ( 2 , p ) ;
2016-01-11 13:00:52 +00:00
} * /
//mxd. This returns the next power of 2. Taken from http://bits.stephan-brumme.com/roundUpToNextPowerOfTwo.html
public static int NextPowerOf2 ( int x )
{
x - - ;
x | = x > > 1 ; // handle 2 bit numbers
x | = x > > 2 ; // handle 4 bit numbers
x | = x > > 4 ; // handle 8 bit numbers
x | = x > > 8 ; // handle 16 bit numbers
x | = x > > 16 ; // handle 32 bit numbers
x + + ;
return x ;
2009-04-19 18:07:22 +00:00
}
// Convert bool to integer
internal static int Bool2Int ( bool v )
{
return v ? 1 : 0 ;
}
// Convert integer to bool
internal static bool Int2Bool ( int v )
{
return ( v ! = 0 ) ;
}
// This shows a message and logs the message
public static DialogResult ShowErrorMessage ( string message , MessageBoxButtons buttons )
{
2015-10-02 23:15:29 +00:00
return ShowErrorMessage ( message , buttons , true ) ;
}
// This shows a message and logs the message
public static DialogResult ShowErrorMessage ( string message , MessageBoxButtons buttons , bool log )
{
//mxd. Log the message?
if ( log ) WriteLogLine ( message ) ;
2009-04-19 18:07:22 +00:00
// Use normal cursor
2014-10-23 08:18:14 +00:00
Cursor oldcursor = Cursor . Current ;
2009-04-19 18:07:22 +00:00
Cursor . Current = Cursors . Default ;
// Show message
IWin32Window window = null ;
if ( ( Form . ActiveForm ! = null ) & & Form . ActiveForm . Visible ) window = Form . ActiveForm ;
2014-10-23 08:18:14 +00:00
DialogResult result = MessageBox . Show ( window , message , Application . ProductName , buttons , MessageBoxIcon . Error ) ;
2009-04-19 18:07:22 +00:00
// Restore old cursor
Cursor . Current = oldcursor ;
// Return result
return result ;
}
// This shows a message and logs the message
public static DialogResult ShowWarningMessage ( string message , MessageBoxButtons buttons )
{
2015-10-02 23:15:29 +00:00
return ShowWarningMessage ( message , buttons , MessageBoxDefaultButton . Button1 , true ) ;
2009-04-19 18:07:22 +00:00
}
// This shows a message and logs the message
public static DialogResult ShowWarningMessage ( string message , MessageBoxButtons buttons , MessageBoxDefaultButton defaultbutton )
{
2015-10-02 23:15:29 +00:00
return ShowWarningMessage ( message , buttons , defaultbutton , true ) ;
}
// This shows a message and logs the message
public static DialogResult ShowWarningMessage ( string message , MessageBoxButtons buttons , MessageBoxDefaultButton defaultbutton , bool log )
{
//mxd. Log the message?
if ( log ) WriteLogLine ( message ) ;
2009-04-19 18:07:22 +00:00
// Use normal cursor
2014-10-23 08:18:14 +00:00
Cursor oldcursor = Cursor . Current ;
2009-04-19 18:07:22 +00:00
Cursor . Current = Cursors . Default ;
// Show message
IWin32Window window = null ;
if ( ( Form . ActiveForm ! = null ) & & Form . ActiveForm . Visible ) window = Form . ActiveForm ;
2014-10-23 08:18:14 +00:00
DialogResult result = MessageBox . Show ( window , message , Application . ProductName , buttons , MessageBoxIcon . Warning , defaultbutton ) ;
2009-04-19 18:07:22 +00:00
// Restore old cursor
Cursor . Current = oldcursor ;
// Return result
return result ;
}
// This shows the reference manual
public static void ShowHelp ( string pagefile )
{
ShowHelp ( pagefile , HELP_FILE ) ;
}
// This shows the reference manual
public static void ShowHelp ( string pagefile , string chmfile )
{
// Check if the file can be found in the root
string filepathname = Path . Combine ( apppath , chmfile ) ;
if ( ! File . Exists ( filepathname ) )
{
// Check if the file exists in the plugins directory
filepathname = Path . Combine ( pluginspath , chmfile ) ;
if ( ! File . Exists ( filepathname ) )
{
// Fail
WriteLogLine ( "ERROR: Can't find the help file \"" + chmfile + "\"" ) ;
return ;
}
}
// Show help file
Help . ShowHelp ( mainwindow , filepathname , HelpNavigator . Topic , pagefile ) ;
}
// This returns a unique temp filename
internal static string MakeTempFilename ( string tempdir )
{
return MakeTempFilename ( tempdir , "tmp" ) ;
}
// This returns a unique temp filename
internal static string MakeTempFilename ( string tempdir , string extension )
{
string filename ;
2014-03-10 14:35:38 +00:00
const string chars = "abcdefghijklmnopqrstuvwxyz1234567890" ;
2009-04-19 18:07:22 +00:00
do
{
// Generate a filename
filename = "" ;
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < 8 ; i + + ) filename + = chars [ Random ( 0 , chars . Length - 1 ) ] ;
2009-04-19 18:07:22 +00:00
filename = Path . Combine ( tempdir , filename + "." + extension ) ;
}
// Continue while file is not unique
while ( File . Exists ( filename ) | | Directory . Exists ( filename ) ) ;
// Return the filename
return filename ;
}
// This returns a unique temp directory name
internal static string MakeTempDirname ( )
{
string dirname ;
const string chars = "abcdefghijklmnopqrstuvwxyz1234567890" ;
do
{
// Generate a filename
dirname = "" ;
2015-12-28 15:01:53 +00:00
for ( int i = 0 ; i < 8 ; i + + ) dirname + = chars [ Random ( 0 , chars . Length - 1 ) ] ;
2009-04-19 18:07:22 +00:00
dirname = Path . Combine ( temppath , dirname ) ;
}
// Continue while file is not unique
while ( File . Exists ( dirname ) | | Directory . Exists ( dirname ) ) ;
// Return the filename
return dirname ;
}
// This shows an image in a panel either zoomed or centered depending on size
public static void DisplayZoomedImage ( Panel panel , Image image )
{
// Image not null?
if ( image ! = null )
{
2014-11-25 11:52:01 +00:00
// Set the image
panel . BackgroundImage = image ;
// Display zoomed
panel . BackgroundImageLayout = ImageLayout . Zoom ;
2009-04-19 18:07:22 +00:00
}
}
// This calculates the new rectangle when one is scaled into another keeping aspect ratio
public static RectangleF MakeZoomedRect ( Size source , RectangleF target )
{
2014-01-30 14:52:08 +00:00
return MakeZoomedRect ( new SizeF ( source . Width , source . Height ) , target ) ;
2009-04-19 18:07:22 +00:00
}
// This calculates the new rectangle when one is scaled into another keeping aspect ratio
public static RectangleF MakeZoomedRect ( Size source , Rectangle target )
{
2014-01-30 14:52:08 +00:00
return MakeZoomedRect ( new SizeF ( source . Width , source . Height ) ,
new RectangleF ( target . Left , target . Top , target . Width , target . Height ) ) ;
2009-04-19 18:07:22 +00:00
}
// This calculates the new rectangle when one is scaled into another keeping aspect ratio
public static RectangleF MakeZoomedRect ( SizeF source , RectangleF target )
{
float scale ;
// Image fits?
2014-10-23 08:18:14 +00:00
if ( ( source . Width < = target . Width ) & & ( source . Height < = target . Height ) )
2009-04-19 18:07:22 +00:00
{
// Just center
scale = 1.0f ;
}
// Image is wider than tall?
else if ( ( source . Width - target . Width ) > ( source . Height - target . Height ) )
{
// Scale down by width
scale = target . Width / source . Width ;
}
else
{
// Scale down by height
scale = target . Height / source . Height ;
}
// Return centered and scaled
return new RectangleF ( target . Left + ( target . Width - source . Width * scale ) * 0.5f ,
target . Top + ( target . Height - source . Height * scale ) * 0.5f ,
source . Width * scale , source . Height * scale ) ;
}
// This opens a URL in the default browser
public static void OpenWebsite ( string url )
{
2017-02-03 07:15:54 +00:00
// [ZZ] note: it may break. no idea why it was done like it was done.
string url2 = url . ToLowerInvariant ( ) ;
if ( ! url2 . StartsWith ( "http://" ) & & ! url2 . StartsWith ( "https://" ) & & ! url2 . StartsWith ( "ftp://" ) & & ! url2 . StartsWith ( "mailto:" ) )
return ;
System . Diagnostics . Process . Start ( url ) ;
/ *
2009-04-19 18:07:22 +00:00
RegistryKey key = null ;
Process p = null ;
string browser ;
try
{
// Get the registry key where default browser is stored
key = Registry . ClassesRoot . OpenSubKey ( @"HTTP\shell\open\command" , false ) ;
// Trim off quotes
browser = key . GetValue ( null ) . ToString ( ) . ToLower ( ) . Replace ( "\"" , "" ) ;
// String doesnt end in EXE?
if ( ! browser . EndsWith ( "exe" ) )
{
// Get rid of everything after the ".exe"
browser = browser . Substring ( 0 , browser . LastIndexOf ( ".exe" ) + 4 ) ;
}
}
finally
{
// Clean up
if ( key ! = null ) key . Close ( ) ;
}
try
{
// Fork a process
p = new Process ( ) ;
p . StartInfo . FileName = browser ;
p . StartInfo . Arguments = url ;
p . Start ( ) ;
}
catch ( Exception ) { }
// Clean up
2017-02-03 07:15:54 +00:00
if ( p ! = null ) p . Dispose ( ) ; * /
}
2009-04-19 18:07:22 +00:00
// This returns the short path name for a file
public static string GetShortFilePath ( string longpath )
{
2019-08-29 19:04:50 +00:00
#if NO_WIN32
return longpath ;
#else
2014-02-20 12:36:09 +00:00
const int maxlen = 256 ;
2009-04-19 18:07:22 +00:00
StringBuilder shortname = new StringBuilder ( maxlen ) ;
2014-02-20 12:36:09 +00:00
GetShortPathName ( longpath , shortname , maxlen ) ;
2009-04-19 18:07:22 +00:00
return shortname . ToString ( ) ;
2019-08-29 19:04:50 +00:00
#endif
2009-04-19 18:07:22 +00:00
}
2016-05-12 13:56:25 +00:00
2019-12-25 17:45:19 +00:00
public static string GetLinuxFilePath ( string longpath )
{
string linuxpath ;
linuxpath = longpath . Replace ( '\\' , '/' ) ;
string wineprefix = Environment . GetEnvironmentVariable ( "WINEPREFIX" ) ;
if ( linuxpath . Substring ( 0 , 2 ) = = "C:" )
{
linuxpath = wineprefix + "/drive_c" + linuxpath . Substring ( 2 ) ;
}
else if ( linuxpath . Substring ( 0 , 2 ) = = "Z:" )
{
linuxpath = linuxpath . Substring ( 2 ) ;
}
return linuxpath ;
}
2016-05-12 13:56:25 +00:00
//mxd
internal static ScriptConfiguration GetScriptConfiguration ( ScriptType type )
{
if ( type = = ScriptType . ACS )
{
// Return map-defined compiler
string compiler = ( ! string . IsNullOrEmpty ( Map . Options . ScriptCompiler ) ? Map . Options . ScriptCompiler : Map . ConfigSettings . DefaultScriptCompiler ) ;
foreach ( KeyValuePair < string , ScriptConfiguration > group in scriptconfigs )
{
if ( group . Key = = compiler ) return group . Value ;
}
}
else
{
// Just pick the first one from the list
foreach ( ScriptConfiguration cfg in scriptconfigs . Values )
{
if ( cfg . ScriptType = = type ) return cfg ;
}
}
return null ;
}
2016-10-08 21:09:55 +00:00
//mxd
public static bool CheckWritePremissions ( string path )
{
2017-03-14 18:31:04 +00:00
try
{
string testFile = path + "/GZDBWriteTest.tmp" ;
if ( File . Exists ( testFile ) )
File . Delete ( testFile ) ;
FileStream fs = File . OpenWrite ( testFile ) ;
fs . Close ( ) ;
File . Delete ( testFile ) ;
return true ;
}
2017-03-15 06:52:53 +00:00
catch ( Exception )
2017-03-14 18:31:04 +00:00
{
return false ;
}
}
2009-04-19 18:07:22 +00:00
2019-08-29 15:56:12 +00:00
#endregion
2013-08-29 10:05:50 +00:00
2019-08-29 15:56:12 +00:00
#region = = = = = = = = = = = = = = = = = = mxd . Uncaught exceptions handling
2013-08-29 10:05:50 +00:00
2016-03-16 23:26:53 +00:00
// In some cases the program can remain operational after these
2014-10-23 08:18:14 +00:00
private static void Application_ThreadException ( object sender , ThreadExceptionEventArgs e )
{
try
{
2016-03-16 23:26:53 +00:00
// Try handling it in user-friendy way...
2016-04-27 09:13:07 +00:00
ExceptionDialog dlg = new ExceptionDialog ( e ) ;
2013-08-29 10:05:50 +00:00
dlg . Setup ( ) ;
2016-03-16 23:26:53 +00:00
if ( dlg . ShowDialog ( ) = = DialogResult . Cancel ) Terminate ( false ) ;
2014-10-23 08:18:14 +00:00
}
2016-03-16 23:26:53 +00:00
catch
2014-10-23 08:18:14 +00:00
{
2016-03-16 23:26:53 +00:00
string exceptionmsg ;
// Try getting exception details...
try { exceptionmsg = "Fatal Windows Forms error occurred: " + e . Exception . Message + "\n\nStack Trace:\n" + e . Exception . StackTrace ; }
2016-05-04 14:02:13 +00:00
catch ( Exception exc ) { exceptionmsg = "Failed to get initial exception details: " + exc . Message + "\n\nStack Trace:\n" + exc . StackTrace ; }
2016-03-16 23:26:53 +00:00
// Try logging it...
try { WriteLogLine ( exceptionmsg ) ; } catch { }
// Try displaying it to the user...
2016-10-28 21:07:33 +00:00
try { MessageBox . Show ( exceptionmsg , "Fatal Windows Forms Error" , MessageBoxButtons . OK , MessageBoxIcon . Stop ) ; }
2016-03-16 23:26:53 +00:00
finally { Process . GetCurrentProcess ( ) . Kill ( ) ; }
2013-08-29 10:05:50 +00:00
}
}
2016-03-16 23:26:53 +00:00
// These are usually unrecoverable
2014-09-29 20:49:41 +00:00
private static void CurrentDomainOnUnhandledException ( object sender , UnhandledExceptionEventArgs e )
{
2016-03-16 23:26:53 +00:00
try
2014-09-29 20:49:41 +00:00
{
2016-03-16 23:26:53 +00:00
// Try handling it in user-friendy way...
2016-04-27 09:13:07 +00:00
ExceptionDialog dlg = new ExceptionDialog ( e ) ;
2013-08-29 10:05:50 +00:00
dlg . Setup ( ) ;
2016-03-16 23:26:53 +00:00
if ( dlg . ShowDialog ( ) = = DialogResult . Cancel ) Terminate ( false ) ;
}
catch
2014-09-29 20:49:41 +00:00
{
2016-03-16 23:26:53 +00:00
string exceptionmsg ;
// Try getting exception details...
try
2014-09-29 20:49:41 +00:00
{
2016-06-03 20:22:07 +00:00
Exception ex = ( Exception ) e . ExceptionObject ;
exceptionmsg = "Fatal Non-UI error:\n" + ex . Message + "\n\nStack Trace:\n" + ex . StackTrace ;
2016-03-16 23:26:53 +00:00
}
catch ( Exception exc )
2014-09-29 20:49:41 +00:00
{
2016-06-03 20:22:07 +00:00
exceptionmsg = "Failed to get initial exception details:\n" + exc . Message + "\n\nStack Trace:\n" + exc . StackTrace ;
2013-08-29 10:05:50 +00:00
}
2016-03-16 23:26:53 +00:00
// Try logging it...
try { WriteLogLine ( exceptionmsg ) ; } catch { }
// Try displaying it to the user...
2016-10-28 21:07:33 +00:00
try { MessageBox . Show ( exceptionmsg , "Fatal Non-UI Error" , MessageBoxButtons . OK , MessageBoxIcon . Stop ) ; }
2016-03-16 23:26:53 +00:00
finally { Process . GetCurrentProcess ( ) . Kill ( ) ; }
2013-08-29 10:05:50 +00:00
}
}
2019-08-29 15:56:12 +00:00
#endregion
2013-08-29 10:05:50 +00:00
2009-04-19 18:07:22 +00:00
}
}