예제 #1
0
        partial void DisposeTexture()
        {
            //check if another sprite is using the same texture
            if (!string.IsNullOrEmpty(FilePath)) //file can be empty if the sprite is created directly from a Texture2D instance
            {
                lock (list)
                {
                    foreach (Sprite s in LoadedSprites)
                    {
                        if (s.FullPath == FullPath)
                        {
                            return;
                        }
                    }
                }
            }

            //if not, free the texture
            if (texture != null)
            {
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    texture.Dispose();
                });
                texture = null;
            }
        }
예제 #2
0
        public static Texture2D FromStream(Stream fileStream, bool preMultiplyAlpha = true, string path = null)
        {
            try
            {
                int    width = 0; int height = 0; int channels = 0;
                byte[] textureData = null;
                textureData = Texture2D.TextureDataFromStream(fileStream, out width, out height, out channels);
                if (preMultiplyAlpha)
                {
                    PreMultiplyAlpha(ref textureData);
                }
                Texture2D tex = null;
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    tex = new Texture2D(_graphicsDevice, width, height);
                    tex.SetData(textureData);
                });
                return(tex);
            }
            catch (Exception e)
            {
#if WINDOWS
                if (e is SharpDX.SharpDXException)
                {
                    throw;
                }
#endif

                DebugConsole.ThrowError("Loading texture from stream failed!", e);
                return(null);
            }
        }
예제 #3
0
        public static void StopCoroutines(string name)
        {
            lock (Coroutines)
            {
                Coroutines.ForEach(c =>
                {
                    if (c.Name == name)
                    {
                        c.AbortRequested = true;
                        if (c.Thread != null)
                        {
                            bool joined = false;
                            while (!joined)
                            {
#if CLIENT
                                CrossThread.ProcessTasks();
#endif
                                joined = c.Thread.Join(TimeSpan.FromMilliseconds(500));
                            }
                        }
                    }
                });
                Coroutines.RemoveAll(c => c.Name == name);
            }
        }
예제 #4
0
        static void Main(string[] args)
        {
            string executableDir = "";

#if !DEBUG
            AppDomain currentDomain = AppDomain.CurrentDomain;
            currentDomain.UnhandledException += new UnhandledExceptionEventHandler(CrashHandler);
#endif

#if LINUX
            setLinuxEnv();
#endif

            Game          = null;
            executableDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
            Directory.SetCurrentDirectory(executableDir);
            SteamManager.Initialize();
            EnableNvOptimus();
            Game = new GameMain(args);
            Game.Run();
            Game.Dispose();
            FreeNvOptimus();

            CrossThread.ProcessTasks();
        }
예제 #5
0
        public static Texture2D FromStream(Stream fileStream, string path = null, bool mipmap = false)
        {
            try
            {
                int    width = 0; int height = 0; int channels = 0;
                byte[] textureData = null;
                textureData = Texture2D.TextureDataFromStream(fileStream, out width, out height, out channels);

                Texture2D tex = null;
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    tex = new Texture2D(_graphicsDevice, width, height, mipmap, SurfaceFormat.Color);
                    tex.SetData(textureData);
                });
                return(tex);
            }
            catch (Exception e)
            {
#if WINDOWS
                if (e is SharpDX.SharpDXException)
                {
                    throw;
                }
#endif

                DebugConsole.ThrowError("Loading texture from stream failed!", e);
                return(null);
            }
        }
예제 #6
0
 public static Texture2D FromStream(Stream fileStream, bool preMultiplyAlpha = true, string path = null)
 {
     try
     {
         int    width = 0; int height = 0; int channels = 0;
         byte[] textureData = null;
         Task   loadTask    = Task.Run(() =>
         {
             textureData = Texture2D.TextureDataFromStream(fileStream, out width, out height, out channels);
         });
         bool success = loadTask.Wait(10000);
         if (!success)
         {
             DebugConsole.ThrowError("Failed to load texture data from " + (path ?? "stream") + ": timed out");
             return(null);
         }
         if (preMultiplyAlpha)
         {
             PreMultiplyAlpha(ref textureData);
         }
         Texture2D tex = null;
         CrossThread.RequestExecutionOnMainThread(() =>
         {
             tex = new Texture2D(_graphicsDevice, width, height);
             tex.SetData(textureData);
         });
         return(tex);
     }
     catch (Exception e)
     {
         DebugConsole.ThrowError("Loading texture from stream failed!", e);
         return(null);
     }
 }
예제 #7
0
        public static Texture2D LoadTexture(string file, bool preMultiplyAlpha = true)
        {
            if (string.IsNullOrWhiteSpace(file))
            {
                Texture2D t = null;
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    t = new Texture2D(GameMain.GraphicsDeviceManager.GraphicsDevice, 1, 1);
                });
                return(t);
            }
            file = Path.GetFullPath(file);
            foreach (Sprite s in list)
            {
                if (s.FullPath == file && s.texture != null)
                {
                    return(s.texture);
                }
            }

            if (File.Exists(file))
            {
                ToolBox.IsProperFilenameCase(file);
                return(TextureLoader.FromFile(file, preMultiplyAlpha));
            }
            else
            {
                DebugConsole.ThrowError("Sprite \"" + file + "\" not found!");
            }

            return(null);
        }
예제 #8
0
        public static Texture2D FromStream(System.IO.Stream stream, string path = null, bool compress = true, bool mipmap = false)
        {
            try
            {
                path = path.CleanUpPath();
                byte[] textureData = null;
                textureData = Texture2D.TextureDataFromStream(stream, out int width, out int height, out int channels);

                SurfaceFormat format = SurfaceFormat.Color;
                if (GameMain.Config.TextureCompressionEnabled && compress)
                {
                    if (((width & 0x03) == 0) && ((height & 0x03) == 0))
                    {
                        textureData = CompressDxt5(textureData, width, height);
                        format      = SurfaceFormat.Dxt5;
                        mipmap      = false;
                    }
                    else
                    {
                        DebugConsole.NewMessage($"Could not compress a texture because the dimensions aren't a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})", Color.Orange);
                    }
                }

                if (((width & 0x03) != 0) || ((height & 0x03) != 0))
                {
                    DebugConsole.AddWarning($"Cannot compress a texture because the dimensions are not a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})");
                }

                Texture2D tex = null;
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    if (cancelAll)
                    {
                        return;
                    }
                    tex = new Texture2D(_graphicsDevice, width, height, mipmap, format);
                    tex.SetData(textureData);
                });
                return(tex);
            }
            catch (Exception e)
            {
#if WINDOWS
                if (e is SharpDX.SharpDXException)
                {
                    throw;
                }
#endif

                DebugConsole.ThrowError(string.IsNullOrEmpty(path) ? "Loading texture from stream failed!" :
                                        "Loading texture \"" + path + "\" failed!", e);
                return(null);
            }
        }
예제 #9
0
        private static Texture2D GetTexture(SpriteBatch spriteBatch)
        {
            if (_whitePixelTexture == null)
            {
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    _whitePixelTexture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
                    _whitePixelTexture.SetData(new[] { Color.White });
                });
            }

            return(_whitePixelTexture);
        }
예제 #10
0
        public static void Init(GraphicsDevice graphicsDevice, bool needsBmp = false)
        {
            _graphicsDevice = graphicsDevice;

            Color[] data = new Color[32 * 32];
            for (int i = 0; i < 32 * 32; i++)
            {
                data[i] = Color.Magenta;
            }

            CrossThread.RequestExecutionOnMainThread(() =>
            {
                PlaceHolderTexture = new Texture2D(graphicsDevice, 32, 32);
                PlaceHolderTexture.SetData(data);
            });
        }
예제 #11
0
        private static void HandleCoroutineStopping(Func <CoroutineHandle, bool> filter)
        {
            foreach (CoroutineHandle coroutine in Coroutines)
            {
                if (filter(coroutine))
                {
                    coroutine.AbortRequested = true;
                    if (coroutine.Thread != null)
                    {
                        bool joined = false;
                        while (!joined)
                        {
#if CLIENT
                            CrossThread.ProcessTasks();
#endif
                            joined = coroutine.Thread.Join(TimeSpan.FromMilliseconds(500));
                        }
                    }
                }
            }
        }
예제 #12
0
        public static Texture2D LoadTexture(string file, out Sprite reusedSprite, bool compress = true)
        {
            reusedSprite = null;
            if (string.IsNullOrWhiteSpace(file))
            {
                Texture2D t = null;
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    t = new Texture2D(GameMain.GraphicsDeviceManager.GraphicsDevice, 1, 1);
                });
                return(t);
            }
            string fullPath = Path.GetFullPath(file);

            foreach (Sprite s in LoadedSprites)
            {
                if (s.FullPath == fullPath && s.texture != null && !s.texture.IsDisposed)
                {
                    reusedSprite = s;
                    return(s.texture);
                }
            }

            if (File.Exists(file))
            {
                if (!ToolBox.IsProperFilenameCase(file))
                {
#if DEBUG
                    DebugConsole.ThrowError("Texture file \"" + file + "\" has incorrect case!");
#endif
                }
                return(TextureLoader.FromFile(file, compress));
            }
            else
            {
                DebugConsole.ThrowError($"Sprite \"{file}\" not found! {Environment.StackTrace.CleanupStackTrace()}");
            }

            return(null);
        }
예제 #13
0
파일: Map.cs 프로젝트: marcelb/Barotrauma
        partial void GenerateNoiseMapProjSpecific()
        {
            if (noiseTexture == null)
            {
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    noiseTexture    = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
                    rawNoiseTexture = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
                });
                rawNoiseSprite = new Sprite(rawNoiseTexture, null, null);
            }

            Color[] crackTextureData    = new Color[generationParams.NoiseResolution * generationParams.NoiseResolution];
            Color[] noiseTextureData    = new Color[generationParams.NoiseResolution * generationParams.NoiseResolution];
            Color[] rawNoiseTextureData = new Color[generationParams.NoiseResolution * generationParams.NoiseResolution];
            for (int x = 0; x < generationParams.NoiseResolution; x++)
            {
                for (int y = 0; y < generationParams.NoiseResolution; y++)
                {
                    noiseTextureData[x + y * generationParams.NoiseResolution]    = Color.Lerp(Color.Black, Color.Transparent, Noise[x, y]);
                    rawNoiseTextureData[x + y * generationParams.NoiseResolution] = Color.Lerp(Color.Black, Color.White, Rand.Range(0.0f, 1.0f));
                }
            }

            float   mapRadius = size / 2;
            Vector2 mapCenter = Vector2.One * mapRadius;

            foreach (LocationConnection connection in connections)
            {
                float centerDist = Vector2.Distance(connection.CenterPos, mapCenter);

                Vector2 connectionStart  = connection.Locations[0].MapPosition;
                Vector2 connectionEnd    = connection.Locations[1].MapPosition;
                float   connectionLength = Vector2.Distance(connectionStart, connectionEnd);
                int     iterations       = (int)(Math.Sqrt(connectionLength * generationParams.ConnectionIndicatorIterationMultiplier));
                connection.CrackSegments = MathUtils.GenerateJaggedLine(
                    connectionStart, connectionEnd,
                    iterations, connectionLength * generationParams.ConnectionIndicatorDisplacementMultiplier);

                iterations = (int)(Math.Sqrt(connectionLength * generationParams.ConnectionIterationMultiplier));
                var visualCrackSegments = MathUtils.GenerateJaggedLine(
                    connectionStart, connectionEnd,
                    iterations, connectionLength * generationParams.ConnectionDisplacementMultiplier);

                float totalLength = Vector2.Distance(visualCrackSegments[0][0], visualCrackSegments.Last()[1]);
                for (int i = 0; i < visualCrackSegments.Count; i++)
                {
                    Vector2 start = visualCrackSegments[i][0] * (generationParams.NoiseResolution / (float)size);
                    Vector2 end   = visualCrackSegments[i][1] * (generationParams.NoiseResolution / (float)size);

                    float length = Vector2.Distance(start, end);
                    for (float x = 0; x < 1; x += 1.0f / length)
                    {
                        Vector2 pos = Vector2.Lerp(start, end, x);
                        SetNoiseColorOnArea(pos, MathHelper.Clamp((int)(totalLength / 30), 2, 5) + Rand.Range(-1, 1), Color.Transparent);
                    }
                }
            }

            void SetNoiseColorOnArea(Vector2 pos, int dist, Color color)
            {
                for (int x = -dist; x < dist; x++)
                {
                    for (int y = -dist; y < dist; y++)
                    {
                        float d = 1.0f - new Vector2(x, y).Length() / dist;
                        if (d <= 0)
                        {
                            continue;
                        }

                        int xIndex = (int)pos.X + x;
                        if (xIndex < 0 || xIndex >= generationParams.NoiseResolution)
                        {
                            continue;
                        }
                        int yIndex = (int)pos.Y + y;
                        if (yIndex < 0 || yIndex >= generationParams.NoiseResolution)
                        {
                            continue;
                        }

                        float perlin = (float)PerlinNoise.CalculatePerlin(
                            xIndex / (float)generationParams.NoiseResolution * 100.0f,
                            yIndex / (float)generationParams.NoiseResolution * 100.0f, 0);

                        byte a = Math.Max(crackTextureData[xIndex + yIndex * generationParams.NoiseResolution].A, (byte)((d * perlin) * 255));

                        crackTextureData[xIndex + yIndex * generationParams.NoiseResolution].A = a;
                    }
                }
            }

            for (int i = 0; i < noiseTextureData.Length; i++)
            {
                float darken    = noiseTextureData[i].A / 255.0f;
                Color pathColor = Color.Lerp(Color.White, Color.Transparent, noiseTextureData[i].A / 255.0f);
                noiseTextureData[i] =
                    Color.Lerp(noiseTextureData[i], pathColor, crackTextureData[i].A / 255.0f * 0.5f);
            }

            CrossThread.RequestExecutionOnMainThread(() =>
            {
                noiseTexture.SetData(noiseTextureData);
                rawNoiseTexture.SetData(rawNoiseTextureData);
            });
        }
예제 #14
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds;
            int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step);

            if (Timing.Accumulator > Timing.Step * 6.0)
            {
                //if the game's running too slowly then we have no choice
                //but to skip a bunch of steps
                //otherwise it snowballs and becomes unplayable
                Timing.Accumulator = Timing.Step;
            }

            CrossThread.ProcessTasks();

            PlayerInput.UpdateVariable();

            if (SoundManager != null)
            {
                if (WindowActive || !Config.MuteOnFocusLost)
                {
                    SoundManager.ListenerGain = SoundManager.CompressionDynamicRangeGain;
                }
                else
                {
                    SoundManager.ListenerGain = 0.0f;
                }
            }

            while (Timing.Accumulator >= Timing.Step)
            {
                Timing.TotalTime += Timing.Step;

                Stopwatch sw = new Stopwatch();
                sw.Start();

                fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly;
                TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16);
                fixedTime.ElapsedGameTime = addTime;
                fixedTime.TotalGameTime.Add(addTime);
                base.Update(fixedTime);

                PlayerInput.Update(Timing.Step);


                if (loadingScreenOpen)
                {
                    //reset accumulator if loading
                    // -> less choppy loading screens because the screen is rendered after each update
                    // -> no pause caused by leftover time in the accumulator when starting a new shift
                    ResetFrameTime();

                    if (!TitleScreen.PlayingSplashScreen)
                    {
                        SoundPlayer.Update((float)Timing.Step);
                    }

                    if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
                        (!waitForKeyHit || ((PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.PrimaryMouseButtonClicked()) && WindowActive)))
                    {
                        loadingScreenOpen = false;
                    }

#if DEBUG
                    if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && (Config.AutomaticQuickStartEnabled || Config.AutomaticCampaignLoadEnabled) && FirstLoad && !PlayerInput.KeyDown(Keys.LeftShift))
                    {
                        loadingScreenOpen = false;
                        FirstLoad         = false;

                        if (Config.AutomaticQuickStartEnabled)
                        {
                            MainMenuScreen.QuickStart();
                        }
                        else if (Config.AutomaticCampaignLoadEnabled)
                        {
                            IEnumerable <string> saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Singleplayer);

                            if (saveFiles.Count() > 0)
                            {
                                saveFiles = saveFiles.OrderBy(file => File.GetLastWriteTime(file));
                                try
                                {
                                    SaveUtil.LoadGame(saveFiles.Last());
                                }
                                catch (Exception e)
                                {
                                    DebugConsole.ThrowError("Loading save \"" + saveFiles.Last() + "\" failed", e);
                                    return;
                                }
                            }
                        }
                    }
#endif

                    if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
                    {
                        throw new LoadingException(loadingCoroutine.Exception);
                    }
                }
                else if (hasLoaded)
                {
                    if (ConnectLobby != 0)
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        Steam.SteamManager.JoinLobby(ConnectLobby, true);

                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }
                    else if (!string.IsNullOrWhiteSpace(ConnectEndpoint))
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint);
                        Client = new GameClient(Config.PlayerName,
                                                serverSteamId != 0 ? null : ConnectEndpoint,
                                                serverSteamId,
                                                string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName);
                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }

                    SoundPlayer.Update((float)Timing.Step);

                    if (PlayerInput.KeyHit(Keys.Escape) && WindowActive)
                    {
                        // Check if a text input is selected.
                        if (GUI.KeyboardDispatcher.Subscriber != null)
                        {
                            if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox)
                            {
                                textBox.Deselect();
                            }
                            GUI.KeyboardDispatcher.Subscriber = null;
                        }
                        //if a verification prompt (are you sure you want to x) is open, close it
                        else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
                                 GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
                        {
                            ((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
                        }
                        else if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary &&
                                 roundSummary.ContinueButton != null &&
                                 roundSummary.ContinueButton.Visible)
                        {
                            GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
                        }
                        else if (Tutorial.Initialized && Tutorial.ContentRunning)
                        {
                            (GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
                        }
                        else if (GameSession.IsTabMenuOpen)
                        {
                            gameSession.ToggleTabMenu();
                        }
                        else if (GUI.PauseMenuOpen)
                        {
                            GUI.TogglePauseMenu();
                        }
                        //open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
                        else if ((Character.Controlled == null || !itemHudActive())
                                 //TODO: do we need to check Inventory.SelectedSlot?
                                 && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null &&
                                 !CrewManager.IsCommandInterfaceOpen &&
                                 !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null))
                        {
                            // Otherwise toggle pausing, unless another window/interface is open.
                            GUI.TogglePauseMenu();
                        }
예제 #15
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Timing.TotalTime    = gameTime.TotalGameTime.TotalSeconds;
            Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds;
            int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step);

            if (Timing.Accumulator > Timing.Step * 6.0)
            {
                //if the game's running too slowly then we have no choice
                //but to skip a bunch of steps
                //otherwise it snowballs and becomes unplayable
                Timing.Accumulator = Timing.Step;
            }

            CrossThread.ProcessTasks();

            PlayerInput.UpdateVariable();

            bool paused = true;

            if (SoundManager != null)
            {
                if (WindowActive || !Config.MuteOnFocusLost)
                {
                    SoundManager.ListenerGain = SoundManager.CompressionDynamicRangeGain;
                }
                else
                {
                    SoundManager.ListenerGain = 0.0f;
                }
            }

            while (Timing.Accumulator >= Timing.Step)
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();

                fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly;
                TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16);
                fixedTime.ElapsedGameTime = addTime;
                fixedTime.TotalGameTime.Add(addTime);
                base.Update(fixedTime);

                PlayerInput.Update(Timing.Step);


                if (loadingScreenOpen)
                {
                    //reset accumulator if loading
                    // -> less choppy loading screens because the screen is rendered after each update
                    // -> no pause caused by leftover time in the accumulator when starting a new shift
                    GameMain.ResetFrameTime();

                    if (!TitleScreen.PlayingSplashScreen)
                    {
                        SoundPlayer.Update((float)Timing.Step);
                    }

                    if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
                        (!waitForKeyHit || ((PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked()) && WindowActive)))
                    {
                        loadingScreenOpen = false;
                    }

                    if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
                    {
                        string errMsg = "Loading was interrupted due to an error";
                        if (loadingCoroutine.Exception != null)
                        {
                            errMsg += ": " + loadingCoroutine.Exception.Message + "\n" + loadingCoroutine.Exception.StackTrace;
                        }
                        throw new Exception(errMsg);
                    }
                }
                else if (hasLoaded)
                {
                    if (ConnectLobby != 0)
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        Steam.SteamManager.JoinLobby(ConnectLobby, true);

                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }
                    else if (!string.IsNullOrWhiteSpace(ConnectEndpoint))
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint);
                        Client = new GameClient(SteamManager.GetUsername(),
                                                serverSteamId != 0 ? null : ConnectEndpoint,
                                                serverSteamId,
                                                string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName);
                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }

                    SoundPlayer.Update((float)Timing.Step);

                    if (PlayerInput.KeyHit(Keys.Escape) && WindowActive)
                    {
                        // Check if a text input is selected.
                        if (GUI.KeyboardDispatcher.Subscriber != null)
                        {
                            if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox)
                            {
                                textBox.Deselect();
                            }
                            GUI.KeyboardDispatcher.Subscriber = null;
                        }
                        //if a verification prompt (are you sure you want to x) is open, close it
                        else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
                                 GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
                        {
                            ((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
                        }
                        else if (Tutorial.Initialized && Tutorial.ContentRunning)
                        {
                            (GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
                        }
                        else if (GUI.PauseMenuOpen)
                        {
                            GUI.TogglePauseMenu();
                        }
                        else if ((Character.Controlled?.SelectedConstruction == null || !Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null)) &&
                                 Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null)
                        {
                            // Otherwise toggle pausing, unless another window/interface is open.
                            GUI.TogglePauseMenu();
                        }
                    }

                    GUI.ClearUpdateList();
                    paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning) &&
                             (NetworkMember == null || !NetworkMember.GameStarted);

#if !DEBUG
                    if (NetworkMember == null && !WindowActive && !paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost)
                    {
                        GUI.TogglePauseMenu();
                        paused = true;
                    }
#endif

                    Screen.Selected.AddToGUIUpdateList();

                    if (Client != null)
                    {
                        Client.AddToGUIUpdateList();
                    }

                    DebugConsole.AddToGUIUpdateList();

                    DebugConsole.Update(this, (float)Timing.Step);
                    paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted));

                    if (!paused)
                    {
                        Screen.Selected.Update(Timing.Step);
                    }
                    else if (Tutorial.Initialized && Tutorial.ContentRunning)
                    {
                        (GameSession.GameMode as TutorialMode).Update((float)Timing.Step);
                    }

                    if (NetworkMember != null)
                    {
                        NetworkMember.Update((float)Timing.Step);
                    }

                    GUI.Update((float)Timing.Step);
                }

                CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step);

                SteamManager.Update((float)Timing.Step);

                SoundManager?.Update();

                Timing.Accumulator -= Timing.Step;

                sw.Stop();
                PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks);
                PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks / (float)TimeSpan.TicksPerMillisecond);
                PerformanceCounter.UpdateIterationsGraph.Update(updateIterations);
            }

            if (!paused)
            {
                Timing.Alpha = Timing.Accumulator / Timing.Step;
            }
        }
예제 #16
0
        public void End()
        {
            if (isDisposed)
            {
                return;
            }
            //sort commands according to the sorting
            //mode given in the last Begin call
            switch (currentSortMode)
            {
            case SpriteSortMode.FrontToBack:
                commandList.Sort((c1, c2) =>
                {
                    return(c1.Depth <c2.Depth ? -1
                                     : c1.Depth> c2.Depth ? 1
                             : c1.Index <c2.Index ? 1
                                         : c1.Index> c2.Index ? -1
                             : 0);
                });
                break;

            case SpriteSortMode.BackToFront:
                commandList.Sort((c1, c2) =>
                {
                    return(c1.Depth <c2.Depth ? 1
                                     : c1.Depth> c2.Depth ? -1
                             : c1.Index <c2.Index ? 1
                                         : c1.Index> c2.Index ? -1
                             : 0);
                });
                break;
            }

            //try to place commands of the same texture
            //contiguously for optimal buffer generation
            //while maintaining the same visual result
            for (int i = 1; i < commandList.Count; i++)
            {
                if (commandList[i].Texture != commandList[i - 1].Texture)
                {
                    for (int j = i - 1; j >= 0; j--)
                    {
                        if (commandList[j].Texture == commandList[i].Texture)
                        {
                            //no commands between i and j overlap with
                            //i, therefore we can safely sift i down to
                            //make a contiguous block
                            commandList.SiftElement(i, j + 1);
                            break;
                        }
                        else if (commandList[j].Overlaps(commandList[i]))
                        {
                            //an overlapping command was found, therefore
                            //attempting to sift this one down would change
                            //the visual result
                            break;
                        }
                    }
                }
            }

            if (isDisposed)
            {
                return;
            }
            //each contiguous block of commands of the same texture
            //requires a vertex buffer to be rendered
            CrossThread.RequestExecutionOnMainThread(() =>
            {
                if (commandList.Count == 0)
                {
                    return;
                }
                int startIndex = 0;
                for (int i = 1; i < commandList.Count; i++)
                {
                    if (commandList[i].Texture != commandList[startIndex].Texture)
                    {
                        maxSpriteCount = Math.Max(maxSpriteCount, i - startIndex);
                        recordedBuffers.Add(new RecordedBuffer(commandList, startIndex, i - startIndex));
                        startIndex = i;
                    }
                }
                recordedBuffers.Add(new RecordedBuffer(commandList, startIndex, commandList.Count - startIndex));
                maxSpriteCount = Math.Max(maxSpriteCount, commandList.Count - startIndex);
            });

            commandList.Clear();

            ReadyToRender = true;
        }
예제 #17
0
        /// <summary>
        /// Renders the font into at least one texture atlas, which is simply a collection of all glyphs in the ranges defined by charRanges.
        /// Don't call this too often or with very large sizes.
        /// </summary>
        /// <param name="gd">Graphics device, required to create textures.</param>
        /// <param name="charRanges">Character ranges between each even element with their corresponding odd element. Default is 0x20 to 0xFFFF.</param>
        /// <param name="texDims">Texture dimensions. Default is 512x512.</param>
        /// <param name="baseChar">Base character used to shift all other characters downwards when rendering. Defaults to T.</param>
        public void RenderAtlas(GraphicsDevice gd, uint[] charRanges = null, int texDims = 1024, uint baseChar = 0x54)
        {
            if (DynamicLoading)
            {
                return;
            }

            if (charRanges == null)
            {
                charRanges = new uint[] { 0x20, 0xFFFF };
            }
            this.charRanges = charRanges;
            this.texDims    = texDims;
            this.baseChar   = baseChar;

            textures.ForEach(t => t.Dispose());
            textures.Clear();
            texCoords.Clear();

            uint[] pixelBuffer = new uint[texDims * texDims];
            for (int i = 0; i < texDims * texDims; i++)
            {
                pixelBuffer[i] = 0;
            }

            CrossThread.RequestExecutionOnMainThread(() =>
            {
                textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
            });
            int texIndex = 0;

            Vector2 currentCoords = Vector2.Zero;
            int     nextY         = 0;

            lock (mutex)
            {
                face.SetPixelSizes(0, size);
                face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
                baseHeight = face.Glyph.Metrics.Height.ToInt32();

                for (int i = 0; i < charRanges.Length; i += 2)
                {
                    uint start = charRanges[i];
                    uint end   = charRanges[i + 1];
                    for (uint j = start; j <= end; j++)
                    {
                        uint glyphIndex = face.GetCharIndex(j);
                        if (glyphIndex == 0)
                        {
                            continue;
                        }
                        face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                        if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
                        {
                            if (face.Glyph.Metrics.HorizontalAdvance > 0)
                            {
                                //glyph is empty, but char still applies advance
                                GlyphData blankData = new GlyphData();
                                blankData.advance  = (float)face.Glyph.Metrics.HorizontalAdvance;
                                blankData.texIndex = -1; //indicates no texture because the glyph is empty
                                texCoords.Add(j, blankData);
                            }
                            continue;
                        }
                        //stacktrace doesn't really work that well when RenderGlyph throws an exception
                        face.Glyph.RenderGlyph(RenderMode.Normal);
                        byte[] bitmap      = face.Glyph.Bitmap.BufferData;
                        int    glyphWidth  = face.Glyph.Bitmap.Width;
                        int    glyphHeight = bitmap.Length / glyphWidth;

                        //if (glyphHeight>lineHeight) lineHeight=glyphHeight;

                        if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1)
                        {
                            throw new Exception(filename + ", " + size.ToString() + ", " + (char)j + "; Glyph dimensions exceed texture atlas dimensions");
                        }

                        nextY = Math.Max(nextY, glyphHeight + 2);

                        if (currentCoords.X + glyphWidth + 2 > texDims - 1)
                        {
                            currentCoords.X  = 0;
                            currentCoords.Y += nextY;
                            nextY            = 0;
                        }
                        if (currentCoords.Y + glyphHeight + 2 > texDims - 1)
                        {
                            currentCoords.X = 0;
                            currentCoords.Y = 0;
                            CrossThread.RequestExecutionOnMainThread(() =>
                            {
                                textures[texIndex].SetData <uint>(pixelBuffer);
                                textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
                            });
                            texIndex++;
                            for (int k = 0; k < texDims * texDims; k++)
                            {
                                pixelBuffer[k] = 0;
                            }
                        }

                        GlyphData newData = new GlyphData
                        {
                            advance    = (float)face.Glyph.Metrics.HorizontalAdvance,
                            texIndex   = texIndex,
                            texCoords  = new Rectangle((int)currentCoords.X, (int)currentCoords.Y, glyphWidth, glyphHeight),
                            drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop)
                        };
                        texCoords.Add(j, newData);

                        for (int y = 0; y < glyphHeight; y++)
                        {
                            for (int x = 0; x < glyphWidth; x++)
                            {
                                byte byteColor = bitmap[x + y * glyphWidth];
                                pixelBuffer[((int)currentCoords.X + x) + ((int)currentCoords.Y + y) * texDims] = (uint)(byteColor << 24 | 0x00ffffff);
                            }
                        }

                        currentCoords.X += glyphWidth + 2;
                    }
                    CrossThread.RequestExecutionOnMainThread(() =>
                    {
                        textures[texIndex].SetData <uint>(pixelBuffer);
                    });
                }
            }
        }
예제 #18
0
        public void DynamicRenderAtlas(GraphicsDevice gd, uint character, int texDims = 1024, uint baseChar = 0x54)
        {
            if (System.Threading.Thread.CurrentThread != GameMain.MainThread)
            {
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    DynamicRenderAtlas(gd, character, texDims, baseChar);
                });
                return;
            }

            byte[]      bitmap;
            int         glyphWidth; int glyphHeight;
            Fixed26Dot6 horizontalAdvance;
            Vector2     drawOffset;

            lock (mutex)
            {
                if (texCoords.ContainsKey(character))
                {
                    return;
                }
                if (textures.Count == 0)
                {
                    this.texDims  = texDims;
                    this.baseChar = baseChar;
                    face.SetPixelSizes(0, size);
                    face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
                    baseHeight = face.Glyph.Metrics.Height.ToInt32();
                    textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
                }

                uint glyphIndex = face.GetCharIndex(character);
                if (glyphIndex == 0)
                {
                    return;
                }

                face.SetPixelSizes(0, size);
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
                {
                    if (face.Glyph.Metrics.HorizontalAdvance > 0)
                    {
                        //glyph is empty, but char still applies advance
                        GlyphData blankData = new GlyphData();
                        blankData.advance  = (float)face.Glyph.Metrics.HorizontalAdvance;
                        blankData.texIndex = -1; //indicates no texture because the glyph is empty
                        texCoords.Add(character, blankData);
                    }
                    return;
                }

                //stacktrace doesn't really work that well when RenderGlyph throws an exception
                face.Glyph.RenderGlyph(RenderMode.Normal);
                bitmap            = (byte[])face.Glyph.Bitmap.BufferData.Clone();
                glyphWidth        = face.Glyph.Bitmap.Width;
                glyphHeight       = bitmap.Length / glyphWidth;
                horizontalAdvance = face.Glyph.Metrics.HorizontalAdvance;
                drawOffset        = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop);

                if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1)
                {
                    throw new Exception(filename + ", " + size.ToString() + ", " + (char)character + "; Glyph dimensions exceed texture atlas dimensions");
                }

                currentDynamicAtlasNextY = Math.Max(currentDynamicAtlasNextY, glyphHeight + 2);
                if (currentDynamicAtlasCoords.X + glyphWidth + 2 > texDims - 1)
                {
                    currentDynamicAtlasCoords.X  = 0;
                    currentDynamicAtlasCoords.Y += currentDynamicAtlasNextY;
                    currentDynamicAtlasNextY     = 0;
                }
                //no more room in current texture atlas, create a new one
                if (currentDynamicAtlasCoords.Y + glyphHeight + 2 > texDims - 1)
                {
                    currentDynamicAtlasCoords.X = 0;
                    currentDynamicAtlasCoords.Y = 0;
                    currentDynamicAtlasNextY    = 0;
                    textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
                    currentDynamicPixelBuffer = null;
                }

                GlyphData newData = new GlyphData
                {
                    advance    = (float)horizontalAdvance,
                    texIndex   = textures.Count - 1,
                    texCoords  = new Rectangle((int)currentDynamicAtlasCoords.X, (int)currentDynamicAtlasCoords.Y, glyphWidth, glyphHeight),
                    drawOffset = drawOffset
                };
                texCoords.Add(character, newData);

                if (currentDynamicPixelBuffer == null)
                {
                    currentDynamicPixelBuffer = new uint[texDims * texDims];
                    textures[newData.texIndex].GetData <uint>(currentDynamicPixelBuffer, 0, texDims * texDims);
                }

                for (int y = 0; y < glyphHeight; y++)
                {
                    for (int x = 0; x < glyphWidth; x++)
                    {
                        byte byteColor = bitmap[x + y * glyphWidth];
                        currentDynamicPixelBuffer[((int)currentDynamicAtlasCoords.X + x) + ((int)currentDynamicAtlasCoords.Y + y) * texDims] = (uint)(byteColor << 24 | 0x00ffffff);
                    }
                }
                textures[newData.texIndex].SetData <uint>(currentDynamicPixelBuffer);

                currentDynamicAtlasCoords.X += glyphWidth + 2;
            }
        }
예제 #19
0
        private IEnumerable <object> Load(bool isSeparateThread)
        {
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
            }

            while (TitleScreen.WaitForLanguageSelection)
            {
                yield return(CoroutineStatus.Running);
            }

            SoundManager = new Sounds.SoundManager();
            SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume, 0);
            SoundManager.SetCategoryGainMultiplier("voip", Math.Min(Config.VoiceChatVolume, 1.0f), 0);

            if (Config.EnableSplashScreen && !ConsoleArguments.Contains("-skipintro"))
            {
                var   pendingSplashScreens = TitleScreen.PendingSplashScreens;
                float baseVolume           = MathHelper.Clamp(Config.SoundVolume * 2.0f, 0.0f, 1.0f);
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_UTG.webm", baseVolume * 0.5f));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_FF.webm", baseVolume));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_Daedalic.webm", baseVolume * 0.1f));
            }

            //if not loading in a separate thread, wait for the splash screens to finish before continuing the loading
            //otherwise the videos will look extremely choppy
            if (!isSeparateThread)
            {
                while (TitleScreen.PlayingSplashScreen || TitleScreen.PendingSplashScreens.Count > 0)
                {
                    yield return(CoroutineStatus.Running);
                }
            }

            GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
            DebugConsole.Init();

            if (Config.AutoUpdateWorkshopItems)
            {
                bool waitingForWorkshopUpdates = true;
                bool result = false;
                TaskPool.Add(SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
                {
                    result = task.Result;
                    waitingForWorkshopUpdates = false;
                });

                while (waitingForWorkshopUpdates)
                {
                    yield return(CoroutineStatus.Running);
                }

                if (result)
                {
                    CrossThread.RequestExecutionOnMainThread(() =>
                    {
                        ContentPackage.LoadAll();
                        Config.ReloadContentPackages();
                    });
                }
            }


            if (SelectedPackages.None())
            {
                DebugConsole.Log("No content packages selected");
            }
            else
            {
                DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name)));
            }

#if DEBUG
            GameSettings.ShowUserStatisticsPrompt = false;
            GameSettings.SendUserStatistics       = false;
#endif

            InitUserStats();

            yield return(CoroutineStatus.Running);

            Debug.WriteLine("sounds");

            int i = 0;
            foreach (object crObj in SoundPlayer.Init())
            {
                CoroutineStatus status = (CoroutineStatus)crObj;
                if (status == CoroutineStatus.Success)
                {
                    break;
                }

                i++;
                TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
                                        1.0f :
                                        Math.Min(40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 40.0f);

                yield return(CoroutineStatus.Running);
            }

            TitleScreen.LoadState = 40.0f;
            yield return(CoroutineStatus.Running);

            LightManager = new Lights.LightManager(base.GraphicsDevice, Content);

            TitleScreen.LoadState = 41.0f;
            yield return(CoroutineStatus.Running);

            GUI.LoadContent();
            TitleScreen.LoadState = 42.0f;

            yield return(CoroutineStatus.Running);

            CharacterPrefab.LoadAll();
            MissionPrefab.Init();
            TraitorMissionPrefab.Init();
            MapEntityPrefab.Init();
            Tutorials.Tutorial.Init();
            MapGenerationParams.Init();
            LevelGenerationParams.LoadPresets();
            WreckAIConfig.LoadAll();
            ScriptedEventSet.LoadPrefabs();
            AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
            SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
            Order.Init();
            EventManagerSettings.Init();
            TitleScreen.LoadState = 50.0f;
            yield return(CoroutineStatus.Running);

            StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
            TitleScreen.LoadState = 53.0f;
            yield return(CoroutineStatus.Running);

            ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
            TitleScreen.LoadState = 55.0f;
            yield return(CoroutineStatus.Running);

            JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
            CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));

            NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));

            ItemAssemblyPrefab.LoadAll();
            TitleScreen.LoadState = 60.0f;
            yield return(CoroutineStatus.Running);

            GameModePreset.Init();

            SubmarineInfo.RefreshSavedSubs();

            TitleScreen.LoadState = 65.0f;
            yield return(CoroutineStatus.Running);

            GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);

            TitleScreen.LoadState = 68.0f;
            yield return(CoroutineStatus.Running);

            MainMenuScreen   = new MainMenuScreen(this);
            LobbyScreen      = new LobbyScreen();
            ServerListScreen = new ServerListScreen();

            TitleScreen.LoadState = 70.0f;
            yield return(CoroutineStatus.Running);

#if USE_STEAM
            SteamWorkshopScreen = new SteamWorkshopScreen();
            if (SteamManager.IsInitialized)
            {
                Steamworks.SteamFriends.OnGameRichPresenceJoinRequested += OnInvitedToGame;
                Steamworks.SteamFriends.OnGameLobbyJoinRequested        += OnLobbyJoinRequested;
            }
#endif

            SubEditorScreen = new SubEditorScreen();

            TitleScreen.LoadState = 75.0f;
            yield return(CoroutineStatus.Running);

            ParticleEditorScreen = new ParticleEditorScreen();

            TitleScreen.LoadState = 80.0f;
            yield return(CoroutineStatus.Running);

            LevelEditorScreen     = new LevelEditorScreen();
            SpriteEditorScreen    = new SpriteEditorScreen();
            CharacterEditorScreen = new CharacterEditor.CharacterEditorScreen();

            yield return(CoroutineStatus.Running);

            TitleScreen.LoadState = 85.0f;
            ParticleManager       = new ParticleManager(GameScreen.Cam);
            ParticleManager.LoadPrefabs();
            TitleScreen.LoadState = 88.0f;
            LevelObjectPrefab.LoadAll();

            TitleScreen.LoadState = 90.0f;
            yield return(CoroutineStatus.Running);

            DecalManager = new DecalManager();
            LocationType.Init();
            MainMenuScreen.Select();

            CheckContentPackage();

            foreach (string steamError in SteamManager.InitializationErrors)
            {
                new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError));
            }

            TitleScreen.LoadState = 100.0f;
            hasLoaded             = true;
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
            }
            yield return(CoroutineStatus.Success);
        }
예제 #20
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds;
            int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step);

            if (Timing.Accumulator > Timing.Step * 6.0)
            {
                //if the game's running too slowly then we have no choice
                //but to skip a bunch of steps
                //otherwise it snowballs and becomes unplayable
                Timing.Accumulator = Timing.Step;
            }

            CrossThread.ProcessTasks();

            PlayerInput.UpdateVariable();

            if (SoundManager != null)
            {
                if (WindowActive || !Config.MuteOnFocusLost)
                {
                    SoundManager.ListenerGain = SoundManager.CompressionDynamicRangeGain;
                }
                else
                {
                    SoundManager.ListenerGain = 0.0f;
                }
            }

            while (Timing.Accumulator >= Timing.Step)
            {
                Timing.TotalTime += Timing.Step;

                Stopwatch sw = new Stopwatch();
                sw.Start();

                fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly;
                TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16);
                fixedTime.ElapsedGameTime = addTime;
                fixedTime.TotalGameTime.Add(addTime);
                base.Update(fixedTime);

                PlayerInput.Update(Timing.Step);


                if (loadingScreenOpen)
                {
                    //reset accumulator if loading
                    // -> less choppy loading screens because the screen is rendered after each update
                    // -> no pause caused by leftover time in the accumulator when starting a new shift
                    GameMain.ResetFrameTime();

                    if (!TitleScreen.PlayingSplashScreen)
                    {
                        SoundPlayer.Update((float)Timing.Step);
                    }

                    if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
                        (!waitForKeyHit || ((PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.PrimaryMouseButtonClicked()) && WindowActive)))
                    {
                        loadingScreenOpen = false;
                    }

#if DEBUG
                    if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && Config.AutomaticQuickStartEnabled && FirstLoad)
                    {
                        loadingScreenOpen = false;
                        FirstLoad         = false;
                        MainMenuScreen.QuickStart();
                    }
#endif

                    if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
                    {
                        throw new LoadingException(loadingCoroutine.Exception);
                    }
                }
                else if (hasLoaded)
                {
                    if (ConnectLobby != 0)
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        Steam.SteamManager.JoinLobby(ConnectLobby, true);

                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }
                    else if (!string.IsNullOrWhiteSpace(ConnectEndpoint))
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint);
                        Client = new GameClient(Config.PlayerName,
                                                serverSteamId != 0 ? null : ConnectEndpoint,
                                                serverSteamId,
                                                string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName);
                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }

                    SoundPlayer.Update((float)Timing.Step);

                    if (PlayerInput.KeyHit(Keys.Escape) && WindowActive)
                    {
                        // Check if a text input is selected.
                        if (GUI.KeyboardDispatcher.Subscriber != null)
                        {
                            if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox)
                            {
                                textBox.Deselect();
                            }
                            GUI.KeyboardDispatcher.Subscriber = null;
                        }
                        //if a verification prompt (are you sure you want to x) is open, close it
                        else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
                                 GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
                        {
                            ((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
                        }
                        else if (Tutorial.Initialized && Tutorial.ContentRunning)
                        {
                            (GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
                        }
                        else if (GameSession.IsTabMenuOpen)
                        {
                            gameSession.ToggleTabMenu();
                        }
                        else if (GUI.PauseMenuOpen)
                        {
                            GUI.TogglePauseMenu();
                        }
                        //open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
                        else if ((Character.Controlled == null || !itemHudActive())
                                 //TODO: do we need to check Inventory.SelectedSlot?
                                 && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null &&
                                 !CrewManager.IsCommandInterfaceOpen &&
                                 !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null))
                        {
                            // Otherwise toggle pausing, unless another window/interface is open.
                            GUI.TogglePauseMenu();
                        }

                        bool itemHudActive()
                        {
                            if (Character.Controlled?.SelectedConstruction == null)
                            {
                                return(false);
                            }
                            return
                                (Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null) ||
                                 ((Character.Controlled.ViewTarget as Item)?.Prefab?.FocusOnSelected ?? false));
                        }
                    }

#if DEBUG
                    if (GameMain.NetworkMember == null)
                    {
                        if (PlayerInput.KeyHit(Keys.P) && !(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
                        {
                            DebugConsole.Paused = !DebugConsole.Paused;
                        }
                    }
#endif

                    GUI.ClearUpdateList();
                    Paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) &&
                             (NetworkMember == null || !NetworkMember.GameStarted);

#if !DEBUG
                    if (NetworkMember == null && !WindowActive && !Paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost)
                    {
                        GUI.TogglePauseMenu();
                        Paused = true;
                    }
#endif

                    Screen.Selected.AddToGUIUpdateList();

                    if (Client != null)
                    {
                        Client.AddToGUIUpdateList();
                    }

                    FileSelection.AddToGUIUpdateList();

                    DebugConsole.AddToGUIUpdateList();

                    DebugConsole.Update((float)Timing.Step);
                    Paused = Paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted));

                    if (!Paused)
                    {
                        Screen.Selected.Update(Timing.Step);
                    }
                    else if (Tutorial.Initialized && Tutorial.ContentRunning)
                    {
                        (GameSession.GameMode as TutorialMode).Update((float)Timing.Step);
                    }
                    else if (DebugConsole.Paused)
                    {
                        if (Screen.Selected.Cam == null)
                        {
                            DebugConsole.Paused = false;
                        }
                        else
                        {
                            Screen.Selected.Cam.MoveCamera((float)Timing.Step);
                        }
                    }

                    if (NetworkMember != null)
                    {
                        NetworkMember.Update((float)Timing.Step);
                    }

                    GUI.Update((float)Timing.Step);
                }

                CoroutineManager.Update((float)Timing.Step, Paused ? 0.0f : (float)Timing.Step);

                SteamManager.Update((float)Timing.Step);

                TaskPool.Update();

                SoundManager?.Update();

                Timing.Accumulator -= Timing.Step;

                sw.Stop();
                PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks);
                PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
                PerformanceCounter.UpdateIterationsGraph.Update(updateIterations);
            }

            if (!Paused)
            {
                Timing.Alpha = Timing.Accumulator / Timing.Step;
            }
        }