diff --git a/OpenRA.Mods.Common/Scripting/Media.cs b/OpenRA.Mods.Common/Scripting/Media.cs index 641b02e5e0..dae7e5fd35 100644 --- a/OpenRA.Mods.Common/Scripting/Media.cs +++ b/OpenRA.Mods.Common/Scripting/Media.cs @@ -62,22 +62,7 @@ namespace OpenRA.Mods.Common.Scripting public static void PlayFMVInRadar(string videoFileName, Action onComplete) { var player = Ui.Root.Get("PLAYER"); - - try - { - player.LoadAndPlay(videoFileName); - } - catch (FileNotFoundException) - { - onComplete(); - return; - } - - player.PlayThen(() => - { - onComplete(); - player.CloseVideo(); - }); + player.LoadAndPlayAsync(videoFileName, onComplete); } } } diff --git a/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs b/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs index 507caef7c2..f7d2d2ec8c 100644 --- a/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs @@ -10,6 +10,8 @@ #endregion using System; +using System.IO; +using System.Threading.Tasks; using OpenRA.Graphics; using OpenRA.Primitives; using OpenRA.Video; @@ -50,11 +52,56 @@ namespace OpenRA.Mods.Common.Widgets if (filename == cachedVideoFileName) return; + cachedVideoFileName = filename; var stream = Game.ModData.DefaultFileSystem.Open(filename); var video = VideoLoader.GetVideo(stream, true, Game.ModData.VideoLoaders); Play(video); + } + + /// + /// Tries to load a video from the specified file and play it. Does nothing if the file name matches the already loaded video. + /// + /// Name of the file, including the extension. + /// Action to perform after the video ends. + public void LoadAndPlayAsync(string filename, Action after) + { + if (filename == cachedVideoFileName) + return; cachedVideoFileName = filename; + + if (!stopped) + CloseVideo(); + + Task.Run(() => + { + try + { + var stream = Game.ModData.DefaultFileSystem.Open(filename); + var video = VideoLoader.GetVideo(stream, true, Game.ModData.VideoLoaders); + + // Safeguard against race conditions with two videos being loaded at the same time - prefer to play only the last one. + if (filename != cachedVideoFileName) + { + after(); + return; + } + + Game.RunAfterTick(() => + { + Play(video); + PlayThen(() => + { + after(); + CloseVideo(); + }); + }); + } + catch (FileNotFoundException) + { + after(); + } + }); } /// @@ -239,7 +286,14 @@ namespace OpenRA.Mods.Common.Widgets Game.Sound.StopVideo(); video.Reset(); videoSprite.Sheet.GetTexture().SetData(video.CurrentFrameData, textureSize, textureSize); - Game.RunAfterTick(onComplete); + Game.RunAfterTick(() => + { + if (onComplete != null) + { + onComplete(); + onComplete = null; + } + }); } public void CloseVideo()