Пример #1
0
        public static void Run()
        {
            int initialVSyncSetting = 0;

            try {
                initialVSyncSetting = GL.GetBufferSwapInterval();
                GameConfig.Load();

                GameDebugger.EngineLog(LogLevel.Debug, "Running application specific configuration event handlers");
                if (ConfigureEvent != null)
                {
                    ConfigureEvent();
                }

                GameDebugger.EngineLog(LogLevel.Debug, "Opening display device '{0}'", GameConfig.DisplayDevice);
                IDisplayDevice cur_dev = API.GetDisplayDevice(GameConfig.DisplayDevice);
                // GameDebugger.Log("Primary display device {0}", cur_dev.ToString());
                if (GameConfig.DisplayDevice != null && !GameConfig.DisplayDevice.Equals(cur_dev.Id))
                {
                    GameConfig.DisplayDevice = null;                     // needed to save a "primary display device" setting since the one in config was not found
                }
                List <IMonitor> monitors = cur_dev.GetMonitors();
                if (monitors == null || monitors.Count == 0)
                {
                    throw new UserFriendlyException("No monitors could be found on the selected device. Could there be a bug somewhere?", "Failed initializing graphics");
                }
                IMonitor first_monitor = monitors[0];
                // foreach( Rectangle mon in monitors )
                //	GameDebugger.Log("\tMonitor at {0}", mon.ToString());

                // Thanks to someone in Microsoft determining current refresh rate and bits per pixel of a monitor is quite a pain in the ass
                int current_width        = first_monitor.Width;
                int current_height       = first_monitor.Height;
                int current_bpp          = first_monitor.BitsPerPixel;
                int current_refresh_rate = first_monitor.RefreshRate;

                int cfg_width        = (GameConfig.ResX <= 0 || GameConfig.ResY <= 0) ? current_width : GameConfig.ResX;
                int cfg_height       = (GameConfig.ResX <= 0 || GameConfig.ResY <= 0) ? current_height : GameConfig.ResY;
                int cfg_bpp          = (GameConfig.BitsPerPixel <= 0) ? current_bpp : GameConfig.BitsPerPixel;
                int cfg_refresh_rate = (GameConfig.RefreshRate <= 0) ? current_refresh_rate : GameConfig.RefreshRate;

                // GameDebugger.Log("Searching for {0}bit {1}x{2} @{3}", GameConfig.BitsPerPixel, GameConfig.ResX, GameConfig.ResY, GameConfig.RefreshRate);

                if (GameConfig.FullScreen)
                {
                    List <IDisplayMode> modes = cur_dev.GetModes();
                    if (modes == null || modes.Count == 0)
                    {
                        throw new Exception(String.Format("Device {0} is invalid and has no modes suitable for graphics", cur_dev.ToString()));
                    }

                    IDisplayMode selected_mode = null;
                    foreach (IDisplayMode mode in modes)
                    {
                        // GameDebugger.Log("\t{0}", mode.ToString()); // Uncomment this to log all supported video modes for the chosen display device
                        if (cfg_width == mode.Width &&
                            cfg_height == mode.Height &&
                            cfg_bpp == mode.BitsPerPixel &&
                            cfg_refresh_rate == mode.RefreshRate)
                        {
                            selected_mode = mode;
                            // GameDebugger.Log("Selected mode: {0}", selected_mode.ToString());
                            //break;
                        }
                    }

                    if (selected_mode == null)
                    {
                        // in case the mode in the config is specified incorrectly we try to use current screen settings. also reset config so later it won't try this bothersome thing
                        GameConfig.ResX         = -1;
                        GameConfig.ResY         = -1;
                        GameConfig.BitsPerPixel = -1;
                        GameConfig.RefreshRate  = -1;
                        foreach (IDisplayMode mode in modes)
                        {
                            //GameDebugger.Log("\t{0}", mode.ToString());
                            if (current_width == mode.Width &&
                                current_height == mode.Height &&
                                current_bpp == mode.BitsPerPixel &&
                                current_refresh_rate == mode.RefreshRate)
                            {
                                selected_mode = mode;
                                break;
                            }
                        }
                    }

                    if (selected_mode == null)
                    {
                        // this should not happen but still ... if no current resolution we deperately search for any 1024x768x32 mode (should be present on all computers by now)
                        foreach (IDisplayMode mode in modes)
                        {
                            //GameDebugger.Log("\t{0}", mode.ToString());
                            if (1024 == mode.Width &&
                                768 == mode.Height &&
                                32 == mode.BitsPerPixel)
                            {
                                selected_mode = mode;
                                break;
                            }
                        }
                    }

                    //
                    if (selected_mode == null)
                    {
                        // OMG this is totally f****d up! just pick out the first one :|
                        selected_mode = modes[0];
                    }

                    if (selected_mode.Width != current_width ||
                        selected_mode.Height != current_height ||
                        selected_mode.BitsPerPixel != current_bpp ||
                        selected_mode.RefreshRate != current_refresh_rate)
                    {
                        // TODO: add support for non full screen modes
                        if (selected_mode.Set(true))
                        {
                            current_width        = selected_mode.Width;
                            current_height       = selected_mode.Height;
                            current_bpp          = selected_mode.BitsPerPixel;
                            current_refresh_rate = selected_mode.RefreshRate;
                        }

                        // After changing resolution monitor positions will change so we have to read them again!
                        monitors = cur_dev.GetMonitors();
                        if (monitors == null || monitors.Count == 0)
                        {
                            throw new Exception("No monitors could be found on the selected device. Could there be a bug somewhere?");
                        }
                        first_monitor = monitors[0];
                    }
                }
                else
                {
                    Size2 size = API.AdjustWindowSize(cfg_width, cfg_height);
                    current_width  = size.Width;
                    current_height = size.Height;
                }

                // GameDebugger.Log("{0},{1}-{2},{3}", first_monitor.X, first_monitor.Y, current_width, current_height);

                using (IOpenGLWindow window = GL.CreateWindow(null, first_monitor.X, first_monitor.Y, current_width, current_height)) {
                    m_Window = window;
                    window.BeforeRenderFrameEvent += OnBeforeFrame;
                    window.RenderFrameEvent       += OnFrame;
                    window.AfterRenderFrameEvent  += OnAfterFrame;
                    window.ResizeEvent            += OnResize;

                    m_Keyboard = IL.FirstKeyboardDevice;

                    Mouse         = IL.FirstMouseDevice;
                    Mouse.Window  = window;                    // mouse must be attached to window before showing since it watches move and resize events
                    Mouse.Visible = GameConfig.ShowHardwareCursor;
                    Mouse.Clipped = GameConfig.ClipMouseCursor;

                    window.Show();

                    GL.SetBufferSwapInterval(GameConfig.VSync ? 1 : 0);
                    GameConfig.VSyncChangedEvent += OnVSyncSettingChanged;

                    OnLoad();
                    if (LoadEvent != null)
                    {
                        LoadEvent();
                    }
                    // GameDebugger.Log("Running main loop at last");
                    Application.Run();
                    // GameDebugger.Log("ByeBye!");
                }
            }

            catch (Exception ex) {
                GameDebugger.EngineLog(LogLevel.Error, "IGE or application has crashed!");
                GameDebugger.EngineLog(LogLevel.Error, ex);
            }

            finally {
                try {
                    CacheableObject.DisposeAll();
                }
                catch (Exception ex) {
                    GameDebugger.EngineLog(LogLevel.Error, "IGE automatic resource unloading has crashed!");
                    GameDebugger.EngineLog(LogLevel.Error, ex);
                }

                try {
                    if (UnloadEvent != null)
                    {
                        UnloadEvent();
                    }
                }
                catch (Exception ex) {
                    GameDebugger.Log(LogLevel.Error, "Application has crashed on UnloadEvent!");
                    GameDebugger.Log(LogLevel.Error, ex);
                }

                try {
                    OnUnload();
                }
                catch (Exception ex) {
                    GameDebugger.EngineLog(LogLevel.Error, "IGE final unloading has crashed!");
                    GameDebugger.EngineLog(LogLevel.Error, ex);
                }

                try {
                    GameConfig.Save();
                }
                catch (Exception ex) {
                    GameDebugger.EngineLog(LogLevel.Error, "IGE could not automatically save the configuration!");
                    GameDebugger.EngineLog(LogLevel.Error, ex);
                }

                try { GameConfig.VSyncChangedEvent -= OnVSyncSettingChanged; } catch {}

                GL.SetBufferSwapInterval(initialVSyncSetting);
                m_Window = null;
            }
        }