private static void Terminate(bool unexpected) { if (!initialized) return; if (unexpected) { Log.Core.WriteError("DualityApp terminated unexpectedly"); } else { if (isUpdating) { terminateScheduled = true; return; } if (environment == ExecutionEnvironment.Editor && execContext == ExecutionContext.Game) { Scene.Current.Dispose(); Log.Core.Write("DualityApp Sandbox terminated"); terminateScheduled = false; return; } if (execContext != ExecutionContext.Editor) { OnTerminating(); SaveUserData(); } sound.Dispose(); sound = null; ClearPlugins(); Profile.SaveTextReport(environment == ExecutionEnvironment.Editor ? "perflog_editor.txt" : "perflog.txt"); Log.Core.Write("DualityApp terminated"); } // Terminate Logfile if (logfile != null) { Log.Game.RemoveOutput(logfileOutput); Log.Core.RemoveOutput(logfileOutput); Log.Editor.RemoveOutput(logfileOutput); logfileOutput = null; logfile.Flush(); logfile.Close(); logfile = null; } initialized = false; execContext = ExecutionContext.Terminated; }
/// <summary> /// Initializes this DualityApp. Should be called before performing any operations withing Duality. /// </summary> /// <param name="context">The <see cref="ExecutionContext"/> in which Duality runs.</param> /// <param name="args"> /// Command line arguments to run this DualityApp with. /// Usually these are just the ones from the host application, passed on. /// </param> public static void Init(ExecutionEnvironment env = ExecutionEnvironment.Unknown, ExecutionContext context = ExecutionContext.Unknown, string[] args = null) { if (initialized) return; // Set main thread mainThread = Thread.CurrentThread; // Process command line options if (args != null) { int logArgIndex = args.IndexOfFirst("logfile"); if (logArgIndex != -1 && logArgIndex + 1 < args.Length) logArgIndex++; else logArgIndex = -1; // Enter debug mode if (args.Contains(CmdArgDebug)) System.Diagnostics.Debugger.Launch(); // Run from editor if (args.Contains(CmdArgEditor)) runFromEditor = true; // Set logfile path if (logArgIndex != -1) { logfilePath = args[logArgIndex]; if (string.IsNullOrWhiteSpace(Path.GetExtension(logfilePath))) logfilePath += ".txt"; } } environment = env; execContext = context; // Initialize Logfile try { logfile = new StreamWriter(logfilePath); logfile.AutoFlush = true; logfileOutput = new TextWriterLogOutput(logfile); Log.Game.AddOutput(logfileOutput); Log.Core.AddOutput(logfileOutput); Log.Editor.AddOutput(logfileOutput); } catch (Exception e) { Log.Core.WriteWarning("Text Logfile unavailable: {0}", Log.Exception(e)); } // Assure Duality is properly terminated in any case and register additional AppDomain events AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; sound = new SoundDevice(); LoadPlugins(); LoadAppData(); LoadUserData(); // Determine available and default graphics modes int[] aaLevels = new int[] { 0, 2, 4, 6, 8, 16 }; foreach (int samplecount in aaLevels) { GraphicsMode mode = new GraphicsMode(32, 24, 0, samplecount, new OpenTK.Graphics.ColorFormat(0), 2, false); if (!availModes.Contains(mode)) availModes.Add(mode); } int highestAALevel = MathF.RoundToInt(MathF.Log(MathF.Max(availModes.Max(m => m.Samples), 1.0f), 2.0f)); int targetAALevel = highestAALevel; if (appData.MultisampleBackBuffer) { switch (userData.AntialiasingQuality) { case AAQuality.High: targetAALevel = highestAALevel; break; case AAQuality.Medium: targetAALevel = highestAALevel / 2; break; case AAQuality.Low: targetAALevel = highestAALevel / 4; break; case AAQuality.Off: targetAALevel = 0; break; } } else { targetAALevel = 0; } int targetSampleCount = MathF.RoundToInt(MathF.Pow(2.0f, targetAALevel)); defaultMode = availModes.LastOrDefault(m => m.Samples <= targetSampleCount) ?? availModes.Last(); // Initial changed event OnAppDataChanged(); OnUserDataChanged(); Formatter.InitDefaultMethod(); joysticks.AddGlobalDevices(); gamepads.AddGlobalDevices(); Log.Core.Write( "DualityApp initialized" + Environment.NewLine + "Debug Mode: {0}" + Environment.NewLine + "Command line arguments: {1}" + Environment.NewLine + "Is64BitProcess: {2}", System.Diagnostics.Debugger.IsAttached, args != null ? args.ToString(", ") : "null", Environment.Is64BitProcess); initialized = true; InitPlugins(); }
/// <summary> /// Terminates this DualityApp. This does not end the current Process, but will instruct the engine to /// leave main loop and message processing as soon as possible. /// </summary> public static void Terminate() { if (!initialized) { return; } if (isUpdating) { terminateScheduled = true; return; } if (environment == ExecutionEnvironment.Editor && execContext == ExecutionContext.Game) { Scene.Current.Dispose(); Logs.Core.Write("DualityApp terminated in sandbox mode."); terminateScheduled = false; return; } if (execContext != ExecutionContext.Editor) { OnTerminating(); SaveUserData(); } // Signal that the game simulation has ended. if (execContext == ExecutionContext.Game) { pluginManager.InvokeGameEnded(); } // Dispose all content that is still loaded ContentProvider.ClearContent(); // Discard plugin data (Resources, current Scene) ahead of time. Otherwise, it'll get shut down in ClearPlugins, after the backend is gone. pluginManager.DiscardPluginData(); sound.Dispose(); sound = null; ShutdownBackend(ref graphicsBack); ShutdownBackend(ref audioBack); pluginManager.ClearPlugins(); // Since this performs file system operations, it needs to happen before shutting down the system backend. Profile.SaveTextReport(environment == ExecutionEnvironment.Editor ? "perflog_editor.txt" : "perflog.txt"); ShutdownBackend(ref systemBack); // Shut down the plugin manager and plugin loader pluginManager.Terminate(); pluginManager.PluginsRemoving -= pluginManager_PluginsRemoving; pluginManager.PluginsRemoved -= pluginManager_PluginsRemoved; assemblyLoader.Terminate(); assemblyLoader = null; Logs.Core.Write("DualityApp terminated"); initialized = false; execContext = ExecutionContext.Terminated; }
/// <summary> /// Initializes this DualityApp. Should be called before performing any operations within Duality. /// </summary> /// <param name="context">The <see cref="ExecutionContext"/> in which Duality runs.</param> /// <param name="commandLineArgs"> /// Command line arguments to run this DualityApp with. /// Usually these are just the ones from the host application, passed on. /// </param> public static void Init(ExecutionEnvironment env, ExecutionContext context, IPluginLoader plugins, string[] commandLineArgs) { if (initialized) { return; } // Process command line options if (commandLineArgs != null) { // Enter debug mode if (commandLineArgs.Contains(CmdArgDebug)) { System.Diagnostics.Debugger.Launch(); } // Run from editor if (commandLineArgs.Contains(CmdArgEditor)) { runFromEditor = true; } } environment = env; execContext = context; // Initialize the plugin manager { pluginLoader = plugins ?? new Duality.Backend.Dummy.DummyPluginLoader(); Log.Core.Write("Using '{0}' to load plugins.", pluginLoader.GetType().Name); pluginLoader.Init(); // Log assembly loading data for diagnostic purposes { Log.Core.Write("Currently Loaded Assemblies:" + Environment.NewLine + "{0}", pluginLoader.LoadedAssemblies.ToString( assembly => " " + Log.Assembly(assembly), Environment.NewLine)); Log.Core.Write("Plugin Base Directories:" + Environment.NewLine + "{0}", pluginLoader.BaseDirectories.ToString( path => " " + path, Environment.NewLine)); Log.Core.Write("Available Assembly Paths:" + Environment.NewLine + "{0}", pluginLoader.AvailableAssemblyPaths.ToString( path => " " + path, Environment.NewLine)); } pluginManager.Init(pluginLoader); pluginManager.PluginsReady += pluginManager_PluginsReady; pluginManager.PluginsRemoving += pluginManager_PluginsRemoving; pluginManager.PluginsRemoved += pluginManager_PluginsRemoved; } // Load all plugins. This needs to be done first, so backends and Types can be located. pluginManager.LoadPlugins(); // Initialize the system backend for system info and file system access InitBackend(out systemBack); // Load application and user data and submit a change event, so all settings are applied LoadAppData(); LoadUserData(); OnAppDataChanged(); OnUserDataChanged(); // Initialize the graphics backend InitBackend(out graphicsBack); // Initialize the audio backend InitBackend(out audioBack); sound = new SoundDevice(); // Initialize all core plugins, this may allocate Resources or establish references between plugins pluginManager.InitPlugins(); initialized = true; // Write environment specs as a debug log Log.Core.Write( "DualityApp initialized" + Environment.NewLine + "Debug Mode: {0}" + Environment.NewLine + "Command line arguments: {1}", System.Diagnostics.Debugger.IsAttached, commandLineArgs != null ? commandLineArgs.ToString(", ") : "null"); }
/// <summary> /// Initializes this DualityApp. Should be called before performing any operations within Duality. /// </summary> /// <param name="context">The <see cref="ExecutionContext"/> in which Duality runs.</param> /// <param name="commandLineArgs"> /// Command line arguments to run this DualityApp with. /// Usually these are just the ones from the host application, passed on. /// </param> public static void Init(ExecutionEnvironment env, ExecutionContext context, IAssemblyLoader plugins, string[] commandLineArgs) { if (initialized) { return; } // Process command line options if (commandLineArgs != null) { // Enter debug mode if (commandLineArgs.Contains(CmdArgDebug)) { System.Diagnostics.Debugger.Launch(); } // Run from editor if (commandLineArgs.Contains(CmdArgEditor)) { runFromEditor = true; } } // If the core was compiled in debug mode and a debugger is attached, log // to the Debug channel, so we can put the VS output window to good use. #if DEBUG bool isDebugging = System.Diagnostics.Debugger.IsAttached; if (isDebugging) { // Only add a new Debug output if we don't already have one, and don't // log to a Console channel either. VS will automatically redirect Console // output to the Output window when debugging a non-Console application, // and we don't want to end up with double log entries. bool hasDebugOut = Logs.GlobalOutput.OfType <DebugLogOutput>().Any(); bool hasConsoleOut = Logs.GlobalOutput.OfType <TextWriterLogOutput>().Any(w => w.GetType().Name.Contains("Console")); if (!hasDebugOut && !hasConsoleOut) { Logs.AddGlobalOutput(new DebugLogOutput()); } } #endif environment = env; execContext = context; // Initialize the plugin manager { assemblyLoader = plugins ?? new Duality.Backend.Dummy.DummyAssemblyLoader(); Logs.Core.Write("Using '{0}' to load plugins.", assemblyLoader.GetType().Name); assemblyLoader.Init(); // Log assembly loading data for diagnostic purposes { Logs.Core.Write("Currently Loaded Assemblies:" + Environment.NewLine + "{0}", assemblyLoader.LoadedAssemblies.ToString( assembly => " " + LogFormat.Assembly(assembly), Environment.NewLine)); Logs.Core.Write("Plugin Base Directories:" + Environment.NewLine + "{0}", assemblyLoader.BaseDirectories.ToString( path => " " + path, Environment.NewLine)); Logs.Core.Write("Available Assembly Paths:" + Environment.NewLine + "{0}", assemblyLoader.AvailableAssemblyPaths.ToString( path => " " + path, Environment.NewLine)); } pluginManager.Init(assemblyLoader); pluginManager.PluginsRemoving += pluginManager_PluginsRemoving; pluginManager.PluginsRemoved += pluginManager_PluginsRemoved; } // Load all plugins. This needs to be done first, so backends and Types can be located. pluginManager.LoadPlugins(); // Initialize the system backend for system info and file system access InitBackend(out systemBack); // Load application and user data and submit a change event, so all settings are applied LoadAppData(); LoadUserData(); OnAppDataChanged(); OnUserDataChanged(); // Initialize the graphics backend InitBackend(out graphicsBack); // Initialize the audio backend InitBackend(out audioBack); sound = new SoundDevice(); // Initialize all core plugins, this may allocate Resources or establish references between plugins pluginManager.InitPlugins(); initialized = true; // Write environment specs as a debug log Logs.Core.Write( "DualityApp initialized" + Environment.NewLine + "Debug Mode: {0}" + Environment.NewLine + "Command line arguments: {1}", System.Diagnostics.Debugger.IsAttached, commandLineArgs != null ? commandLineArgs.ToString(", ") : "null"); }