Beispiel #1
0
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Cursor.Current = Cursors.WaitCursor;

            try
            {
                // Set up the graphics interface.
                _graphics = new GorgonGraphics();

                // Create our 2D renderer to display the image.
                _2D = _graphics.Output.Create2DRenderer(this, 1280, 800);

                // Center the window on the screen.
                Screen currentMonitor = Screen.FromControl(this);
                Location = new Point(currentMonitor.WorkingArea.Left + (currentMonitor.WorkingArea.Width / 2 - Width / 2),
                                     currentMonitor.WorkingArea.Top + (currentMonitor.WorkingArea.Height / 2 - Height / 2));

                // Load our base texture.
                _image = _graphics.Textures.FromMemory <GorgonTexture2D>("SourceTexture",
                                                                         Resources.SourceTexture,
                                                                         new GorgonCodecDDS());


                // Load the custom codec.
                if (!LoadCodec())
                {
                    GorgonDialogs.ErrorBox(this, "Unable to load the useless image codec plug-in.");
                    Gorgon.Quit();
                    return;
                }

                // Convert the image to our custom codec.
                ConvertImage();

                // Set up our idle time processing.
                Gorgon.ApplicationIdleLoopMethod = () =>
                {
                    _2D.Clear(Color.White);

                    // Draw to the window.
                    Draw();

                    // Render with a vsync interval of 2 (typically 30 FPS).
                    // We're not making an action game here.
                    _2D.Render(2);
                    return(true);
                };
            }
            catch (Exception ex)
            {
                GorgonDialogs.ErrorBox(this, ex);
                Gorgon.Quit();
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Handles the ParentChanged event of the Window control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void Window_ParentChanged(object sender, EventArgs e)
        {
            try
            {
                // If the actual control has changed parents, update the top level control.
                if (sender == Settings.Window)
                {
                    var newTopLevelParent = Gorgon.GetTopLevelControl(Settings.Window);

                    if (newTopLevelParent != _topLevelControl)
                    {
                        _topLevelControl.ParentChanged -= Window_ParentChanged;

                        // If we're not at the top of the chain, then find out which window is and set it up
                        // to handle changes to its hierarchy.
                        if (newTopLevelParent != Settings.Window)
                        {
                            _topLevelControl = newTopLevelParent;
                            _topLevelControl.ParentChanged += Window_ParentChanged;
                        }
                    }
                }

                if (_parentForm != null)
                {
                    _parentForm.ResizeBegin -= _parentForm_ResizeBegin;
                    _parentForm.ResizeEnd   -= _parentForm_ResizeEnd;
                }

                _parentForm = Gorgon.GetTopLevelForm(Settings.Window);

                if (_parentForm == null)
                {
                    return;
                }

                _parentForm.ResizeBegin += _parentForm_ResizeBegin;
                _parentForm.ResizeEnd   += _parentForm_ResizeEnd;
            }
            catch (Exception ex)
            {
#if DEBUG
                GorgonException.Catch(ex,
                                      () =>
                                      GorgonDialogs.ErrorBox(_parentForm,
                                                             string.Format(Resources.GORGFX_CATASTROPHIC_ERROR, Gorgon.Log.LogPath),
                                                             null,
                                                             ex));

                // If we fail in here, then we have a terminal error in Gorgon, don't risk further corruption.
                Gorgon.Quit();
#else
                GorgonException.Catch(ex);
#endif
            }
        }
Beispiel #3
0
        /// <summary>
        /// Handles the Resize event of the Window control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void Window_Resize(object sender, EventArgs e)
        {
            // If we're in a manual resize operation, then don't call this method just yet.
            if (_isInResize)
            {
                return;
            }

            // Attempt to get the parent form if we don't have one yet.
            if (_parentForm == null)
            {
                _parentForm              = Gorgon.GetTopLevelForm(Settings.Window);
                _parentForm.ResizeBegin += _parentForm_ResizeBegin;
                _parentForm.ResizeEnd   += _parentForm_ResizeEnd;
            }

            if ((!AutoResize) || ((_parentForm != null) && (_parentForm.WindowState == FormWindowState.Minimized)))
            {
                return;
            }

            // Only do this if the size has changed, if we're just restoring the window, then don't bother.
            if (((GISwapChain == null)) || (Settings.Window.ClientSize.Width <= 0) || (Settings.Window.ClientSize.Height <= 0))
            {
                return;
            }

            try
            {
                // Resize the video mode.
                Settings.VideoMode = new GorgonVideoMode(Settings.Window.ClientSize.Width,
                                                         Settings.Window.ClientSize.Height,
                                                         Settings.VideoMode.Format,
                                                         Settings.VideoMode.RefreshRateNumerator,
                                                         Settings.VideoMode.RefreshRateDenominator);
                ResizeBuffers();
            }
            catch (Exception ex)
            {
#if DEBUG
                GorgonException.Catch(ex,
                                      () =>
                                      GorgonDialogs.ErrorBox(_parentForm,
                                                             string.Format(Resources.GORGFX_CATASTROPHIC_ERROR, Gorgon.Log.LogPath),
                                                             null,
                                                             ex));

                // If we fail in here, then we have a terminal error in Gorgon, don't risk further corruption.
                Gorgon.Quit();
#else
                // Log the exception.
                GorgonException.Catch(ex);
#endif
            }
        }
Beispiel #4
0
        /// <summary>
        /// Function to initialize the scratch files area.
        /// </summary>
        private void InitializeScratchArea()
        {
            ScratchArea.ScratchPath = Program.Settings.ScratchPath;

            EditorLogging.Print("Creating scratch area at \"{0}\"", LoggingLevel.Verbose, ScratchArea.ScratchPath);

            _splash.UpdateVersion(Resources.GOREDIT_TEXT_CREATING_SCRATCH);

            // Ensure that we're not being clever and trying to mess up our system.
            if (ScratchArea.CanAccessScratch(Program.Settings.ScratchPath) == ScratchAccessibility.SystemArea)
            {
                GorgonDialogs.ErrorBox(null, Resources.GOREDIT_ERR_CANNOT_USESYS_SCRATCH);
            }
            else
            {
                // Destroy previous scratch area files if possible.
                // Do not do this when we have it set to a system area, this will keep us from
                // destroying anything critical.
                ScratchArea.CleanOldScratchAreas();
            }

            // Ensure we can actually access the scratch area.
            while (ScratchArea.CanAccessScratch(Program.Settings.ScratchPath) != ScratchAccessibility.Accessible)
            {
                EditorLogging.Print("Could not access scratch area at \"{0}\"", LoggingLevel.Verbose, Program.Settings.ScratchPath);

                if (ScratchArea.SetScratchLocation() == ScratchAccessibility.Canceled)
                {
                    // Exit the application if we cancel.
                    MainForm.Dispose();
                    Gorgon.Quit();
                    return;
                }

                EditorLogging.Print("Setting scratch area to \"{0}\".", LoggingLevel.Verbose, Program.Settings.ScratchPath);

                // Update with the new scratch path.
                Program.Settings.Save();
            }

            ScratchArea.InitializeScratch();

            // Get only the providers that are not disabled.
            var plugIns = from plugIn in Gorgon.PlugIns
                          where plugIn is GorgonFileSystemProviderPlugIn &&
                          PlugIns.UserDisabledPlugIns.All(name => !string.Equals(name, plugIn.Name, StringComparison.OrdinalIgnoreCase))
                          select plugIn;

            foreach (GorgonPlugIn plugIn in plugIns)
            {
                ScratchArea.ScratchFiles.Providers.LoadProvider(plugIn.Name);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try
            {
                Cursor = Cursors.WaitCursor;

                // Initialize.
                Initialize();
            }
            catch (Exception ex)
            {
                GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(this, ex));
                Gorgon.Quit();
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
Beispiel #6
0
        /// <summary>
        /// Handles the Deactivate event of the _parentForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void _parentForm_Deactivate(object sender, EventArgs e)
        {
            try
            {
                if ((GISwapChain == null) || (!Graphics.ResetFullscreenOnFocus))
                {
                    return;
                }

                Graphics.GetFullScreenSwapChains();

                // Reset the video mode to windowed.
                // Note:  For some reason, this is different than it was on SlimDX.  I never had to do this before, but with
                // SharpDX I now have to handle the transition from full screen to windowed manually.
                if (!GISwapChain.IsFullScreen)
                {
                    return;
                }

                GISwapChain.SetFullscreenState(false, null);
                Settings.IsWindowed = true;
                ((Form)Settings.Window).WindowState = FormWindowState.Minimized;
            }
            catch (Exception ex)
            {
#if DEBUG
                GorgonException.Catch(ex,
                                      () =>
                                      GorgonDialogs.ErrorBox(_parentForm,
                                                             string.Format(Resources.GORGFX_CATASTROPHIC_ERROR, Gorgon.Log.LogPath),
                                                             null,
                                                             ex));

                // If we fail in here, then we have a terminal error in Gorgon, don't risk further corruption.
                Gorgon.Quit();
#else
                GorgonException.Catch(ex);
#endif
            }
        }
Beispiel #7
0
        /// <summary>
        /// Handles the Activated event of the _parentForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void _parentForm_Activated(object sender, EventArgs e)
        {
            try
            {
                if ((GISwapChain == null) || (!Graphics.ResetFullscreenOnFocus))
                {
                    return;
                }

                Graphics.GetFullScreenSwapChains();

                if (GISwapChain.IsFullScreen)
                {
                    return;
                }

                ((Form)Settings.Window).WindowState = FormWindowState.Normal;
                // Get the current video output.
                GISwapChain.SetFullscreenState(true, null);
                Settings.IsWindowed = false;
            }
            catch (Exception ex)
            {
#if DEBUG
                GorgonException.Catch(ex,
                                      () =>
                                      GorgonDialogs.ErrorBox(_parentForm,
                                                             string.Format(Resources.GORGFX_CATASTROPHIC_ERROR, Gorgon.Log.LogPath),
                                                             null,
                                                             ex));

                // If we fail in here, then we have a terminal error in Gorgon, don't risk further corruption.
                Gorgon.Quit();
#else
                GorgonException.Catch(ex);
#endif
            }
        }
Beispiel #8
0
        private void UpdateDeferred(GorgonConstantBuffer constantBuffer)
        {
            _tasks.Add(Task.Run(() =>
            {
                var wvp = new WVPBuffer
                {
                    Projection = _wvp.Projection,
                    View       = _wvp.View
                };

                if (!_bouncy[0])
                {
                    _positions[0] = new Vector3(_positions[0].X + 1.0f * GorgonTiming.Delta,
                                                _positions[0].Y - 2.5f * GorgonTiming.Delta,
                                                _positions[0].Z + 1.85f * GorgonTiming.Delta);
                }
                else
                {
                    _positions[0] = new Vector3(_positions[0].X - 1.0f * GorgonTiming.Delta,
                                                _positions[0].Y + 2.5f * GorgonTiming.Delta,
                                                _positions[0].Z - 1.85f * GorgonTiming.Delta);
                }

                if ((_positions[0].X > 2.0f) ||
                    (_positions[0].Y < -2.0f) ||
                    (_positions[0].Z > 6.0))
                {
                    _bouncy[0] = true;
                }

                if ((_positions[0].X < -2.0f) ||
                    (_positions[0].Y > 2.0f) ||
                    (_positions[0].Z < 1.0f))
                {
                    _bouncy[0] = false;
                }

                Matrix.Translation(ref _positions[0], out wvp.World);
                Matrix.Transpose(ref wvp.World, out wvp.World);

                constantBuffer.Update(ref wvp, _deferred[0]);

                _deferred[0].Output.DrawIndexed(0, 0, 6);
                _commands[0] = _deferred[0].FinalizeDeferred();
            }));

            _tasks.Add(Task.Run(() =>
            {
                var wvp = new WVPBuffer();
                Matrix rot;
                Quaternion quat;
                wvp.Projection = _wvp.Projection;
                wvp.View       = _wvp.View;

                if (!_bouncy[1])
                {
                    _positions[1].Z += (30.0f * GorgonTiming.Delta);
                    _positions[1].Y += (15.0f * GorgonTiming.Delta);
                    _positions[1].X += (10.0f * GorgonTiming.Delta);
                }
                else
                {
                    _positions[1].Z -= (15.0f * GorgonTiming.Delta);
                    _positions[1].Y -= (30.0f * GorgonTiming.Delta);
                    _positions[1].X -= (25.0f * GorgonTiming.Delta);
                }

                if (_positions[1].Z > 195.0f)
                {
                    _bouncy[1]      = true;
                    _positions[1].Z = 195.0f;
                }

                if (_positions[1].Z < 0.0f)
                {
                    _bouncy[1]      = true;
                    _positions[1].Z = 0.0f;
                }

                Quaternion.RotationYawPitchRoll(_positions[1].Y.Radians(), _positions[1].X.Radians() * 0, _positions[1].Z.Radians() * 0, out quat);
                Matrix.RotationQuaternion(ref quat, out rot);
                Matrix.Translation(-2.0f, 0.0f, 6.0f, out wvp.World);
                Matrix.Multiply(ref rot, ref wvp.World, out wvp.World);

                Matrix.Transpose(ref wvp.World, out wvp.World);

                constantBuffer.Update(ref wvp, _deferred[1]);

                _deferred[1].Output.DrawIndexed(0, 0, 6);
                _commands[1] = _deferred[1].FinalizeDeferred();
            }));

            try
            {
                Action runDeferred = async() =>
                {
                    var task = await Task.WhenAny(_tasks);

                    _tasks.Remove(task);

                    await task;
                };

                while (_tasks.Count > 0)
                {
                    runDeferred();

                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                GorgonDialogs.ErrorBox(null, ex);
                Gorgon.Quit();
            }
        }
Beispiel #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AppContext"/> class.
        /// </summary>
        public AppContext()
        {
            float startTime = GorgonTiming.SecondsSinceStart;

            try
            {
                PlugIns.DefaultImageEditorPlugIn = Program.Settings.DefaultImageEditor;

                _splash  = new FormSplash();
                MainForm = new FormMain();

                _splash.Show();
                _splash.Refresh();

                // Fade in our splash screen.
                FadeSplashScreen(true, 500.0f);

                EditorLogging.Open();

                InitializeGraphics();
                InitializePlugIns();
                InitializeScratchArea();
                InitializeInput();

                FileManagement.InitializeFileTypes();

                // Load the last opened file.
                if ((Program.Settings.AutoLoadLastFile) && (!string.IsNullOrWhiteSpace(Program.Settings.LastEditorFile)))
                {
                    LoadLastFile();
                }

                // Set up the default pane.
                _splash.UpdateVersion(Resources.GOREDIT_TEXT_LOAD_DEFAULT);
                ContentManagement.DefaultContentType = typeof(DefaultContent);
                ContentManagement.LoadDefaultContentPane();

                // Keep showing the splash screen.
                while ((GorgonTiming.SecondsSinceStart - startTime) < 3)
                {
                    Thread.Sleep(1);
                }

                FadeSplashScreen(false, 250.0f);

                // Bring up our application form.
                MainForm.Show();
            }
            catch (Exception ex)
            {
                GorgonDialogs.ErrorBox(null, ex);

                if ((MainForm != null) && (!MainForm.IsDisposed))
                {
                    MainForm.Dispose();
                }

                // Signal quit.
                Gorgon.Quit();
            }
            finally
            {
                if (_splash != null)
                {
                    _splash.Dispose();
                }
                _splash = null;
            }
        }
Beispiel #10
0
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try
            {
                // Set our default cursor.
                _currentCursor = Resources.hand_icon;

                // Load our raw input plug-in assembly.
                Gorgon.PlugIns.LoadPlugInAssembly(Program.PlugInPath + "Gorgon.Input.Raw.DLL");

                // Create our input factory.
                _factory = GorgonInputFactory.CreateInputFactory("GorgonLibrary.Input.GorgonRawPlugIn");

                // Get our device info.
                // This function is called when the factory is created.
                // However, I'm calling it here just to show that it exists.
                _factory.EnumerateDevices();

                // Validate, even though it's highly unlikely we'll run into these.
                if (_factory.PointingDevices.Count == 0)
                {
                    GorgonDialogs.ErrorBox(this, "There were no mice detected on this computer.  The application requires a mouse.");
                    Gorgon.Quit();
                }

                if (_factory.KeyboardDevices.Count == 0)
                {
                    GorgonDialogs.ErrorBox(this, "There were no keyboards detected on this computer.  The application requires a keyboard.");
                    Gorgon.Quit();
                }

                // Get our input devices.
                CreateMouse();
                CreateKeyboard();
                CreateJoystick();

                // When the display area changes size, update the spray effect
                // and limit the mouse.
                panelDisplay.Resize += panelDisplay_Resize;

                // Set the initial range of the mouse cursor.
                _mouse.PositionRange = Rectangle.Round(panelDisplay.ClientRectangle);

                // Set up our spray object.
                _spray  = new Spray(panelDisplay.ClientSize);
                _cursor = new MouseCursor(panelDisplay)
                {
                    Hotspot = new Point(-16, -3)
                };

                // Set up our idle method.
                Gorgon.ApplicationIdleLoopMethod = Idle;
            }
            catch (Exception ex)
            {
                // We do this here instead of just calling the dialog because this
                // function will send the exception to the Gorgon log file.
                GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(this, ex));
                Gorgon.Quit();
            }
        }
Beispiel #11
0
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try
            {
                // Load the XInput plug-in assembly.
                Gorgon.PlugIns.LoadPlugInAssembly(Program.PlugInPath + "Gorgon.Input.XInput.dll");

                // Create our factory.
                _factory = GorgonInputFactory.CreateInputFactory("GorgonLibrary.Input.GorgonXInputPlugIn");

                // Ensure that we have and XBox controller to work with.
                if (_factory.JoystickDevices.Count == 0)
                {
                    GorgonDialogs.ErrorBox(this, "No XBox controllers were found on this system.\nThis example requires an XBox controller.");
                    Gorgon.Quit();
                    return;
                }

                // Enumerate the active joysticks.  We'll only take 3 of the 4 available xbox controllers.
                _joystick      = new GorgonJoystick[3];
                _stickPosition = new PointF[_joystick.Count];
                _sprayStates   = new SprayCan[_joystick.Count];

                for (int i = 0; i < _joystick.Count; i++)
                {
                    var joystick = _factory.CreateJoystick(this, _factory.JoystickDevices[i].Name);

                    // Set a dead zone on the joystick.
                    // A dead zone will stop input from the joystick until it reaches the outside
                    // of the specified coordinates.
                    joystick.DeadZone.X          = new GorgonRange(joystick.Capabilities.XAxisRange.Minimum / 4, joystick.Capabilities.XAxisRange.Maximum / 4);
                    joystick.DeadZone.Y          = new GorgonRange(joystick.Capabilities.YAxisRange.Minimum / 4, joystick.Capabilities.YAxisRange.Maximum / 4);
                    joystick.DeadZone.SecondaryX = new GorgonRange(joystick.Capabilities.XAxisRange.Minimum / 128, joystick.Capabilities.XAxisRange.Maximum / 128);
                    joystick.DeadZone.SecondaryY = new GorgonRange(joystick.Capabilities.YAxisRange.Minimum / 128, joystick.Capabilities.YAxisRange.Maximum / 128);

                    _joystick[i] = joystick;

                    // Start at a random spot.
                    _stickPosition[i] = new Point(GorgonRandom.RandomInt32(64, panelDisplay.ClientSize.Width - 64), GorgonRandom.RandomInt32(64, panelDisplay.ClientSize.Height - 64));

                    // Turn off spray for all controllers.
                    _sprayStates[i] = new SprayCan(joystick, i);
                }

                // Check for connected controllers.
                while (!_joystick.Any(item => item.IsConnected))
                {
                    if (MessageBox.Show(this,
                                        "There are no XBox controllers connected.\nPlease plug in an XBox controller and click OK.",
                                        "No Controllers", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.Cancel)
                    {
                        continue;
                    }

                    Gorgon.Quit();
                    return;
                }

                // Get the graphics interface for our panel.
                _surface = new DrawingSurface(panelDisplay);

                // Set up our idle loop.
                Gorgon.ApplicationIdleLoopMethod += Idle;
            }
            catch (Exception ex)
            {
                // We do this here instead of just calling the dialog because this
                // function will send the exception to the Gorgon log file.
                GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(this, ex));
                Gorgon.Quit();
            }
        }
Beispiel #12
0
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load"></see> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try
            {
                // Load the plug-in assembly.
                Gorgon.PlugIns.LoadPlugInAssembly(Program.PlugInPath + "Gorgon.Input.Raw.DLL");

                // Create the factory.
                _input = GorgonInputFactory.CreateInputFactory("GorgonLibrary.Input.GorgonRawPlugIn");

                // Create mouse, keyboard and joystick interfaces.
                _keyboard     = _input.CreateKeyboard(this);
                _mouse        = _input.CreatePointingDevice(this);
                _joystickList = new GorgonJoystick[_input.JoystickDevices.Count];

                // Create each joystick interface.
                for (int i = 0; i < _joystickList.Length; i++)
                {
                    _joystickList[i] = _input.CreateJoystick(this, _input.JoystickDevices[i].Name);
                }

                // Create the graphics interface.
                _graphics = new GorgonGraphics();
                _screen   = _graphics.Output.CreateSwapChain("Screen", new GorgonSwapChainSettings
                {
                    Size       = Settings.Default.Resolution,
                    Format     = BufferFormat.R8G8B8A8_UIntNormal,
                    IsWindowed = Settings.Default.IsWindowed
                });

                // For the backup image. Used to make it as large as the monitor that we're on.
                Screen currentScreen = Screen.FromHandle(Handle);

                // Relocate the window to the center of the screen.
                Location = new Point(currentScreen.Bounds.Left + (currentScreen.WorkingArea.Width / 2) - ClientSize.Width / 2,
                                     currentScreen.Bounds.Top + (currentScreen.WorkingArea.Height / 2) - ClientSize.Height / 2);


                // Create the 2D renderer.
                _2D = _graphics.Output.Create2DRenderer(_screen);

                // Create the text font.
                _font = _graphics.Fonts.CreateFont("Arial_9pt", new GorgonFontSettings
                {
                    FontFamilyName   = "Arial",
                    FontStyle        = FontStyle.Bold,
                    AntiAliasingMode = FontAntiAliasMode.AntiAlias,
                    FontHeightMode   = FontHeightMode.Points,
                    Size             = 9.0f
                });

                // Enable the mouse.
                Cursor                          = Cursors.Cross;
                _mouse.Enabled                  = true;
                _mouse.Exclusive                = false;
                _mouse.PointingDeviceDown      += MouseInput;
                _mouse.PointingDeviceMove      += MouseInput;
                _mouse.PointingDeviceWheelMove += _mouse_PointingDeviceWheelMove;

                // Enable the keyboard.
                _keyboard.Enabled   = true;
                _keyboard.Exclusive = false;
                _keyboard.KeyDown  += _keyboard_KeyDown;

                // Create text sprite.
                _messageSprite       = _2D.Renderables.CreateText("Message", _font, "Using mouse and keyboard.");
                _messageSprite.Color = Color.Black;

                // Create a back buffer.
                _backBuffer = _graphics.Output.CreateRenderTarget("BackBuffer", new GorgonRenderTarget2DSettings
                {
                    Width  = _screen.Settings.Width,
                    Height = _screen.Settings.Height,
                    Format = BufferFormat.R8G8B8A8_UIntNormal
                });
                _backBuffer.Clear(Color.White);

                var settings = new GorgonTexture2DSettings
                {
                    Width  = currentScreen.Bounds.Width,
                    Height = currentScreen.Bounds.Height,
                    Format = BufferFormat.R8G8B8A8_UIntNormal,
                    Usage  = BufferUsage.Staging
                };

                // Clear our backup image to white to match our primary screen.
                _backupImage = _graphics.Textures.CreateTexture("Backup", settings);
                using (var textureData = _backupImage.Lock(BufferLockFlags.Write))
                {
                    textureData.Data.Fill(0xFF);
                }

                // Set the mouse range and position.
                Cursor.Position = PointToScreen(new Point(Settings.Default.Resolution.Width / 2, Settings.Default.Resolution.Height / 2));
                _mouse.SetPosition(Settings.Default.Resolution.Width / 2, Settings.Default.Resolution.Height / 2);
                _mouse.SetPositionRange(0, 0, Settings.Default.Resolution.Width, Settings.Default.Resolution.Height);

                // Set gorgon events.
                _screen.AfterStateTransition += (sender, args) =>
                {
                    OnResizeEnd(EventArgs.Empty);

                    // Reposition after a state change.
                    if (!args.IsWindowed)
                    {
                        return;
                    }

                    Screen monitor = Screen.FromHandle(Handle);
                    Location = new Point(monitor.Bounds.Left + (monitor.WorkingArea.Width / 2) - args.Width / 2,
                                         monitor.Bounds.Top + (monitor.WorkingArea.Height / 2) - args.Height / 2);
                    Cursor.Position = PointToScreen(Point.Round(_mouse.Position));
                };
                Gorgon.ApplicationIdleLoopMethod = Gorgon_Idle;
            }
            catch (Exception ex)
            {
                GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(this, ex));
                Gorgon.Quit();
            }
        }