Add yaml-defined FMV playback to GUI elements
This commit is contained in:
@@ -88,6 +88,15 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public class MapVideos
|
||||
{
|
||||
public string BackgroundInfo;
|
||||
public string Briefing;
|
||||
public string GameStart;
|
||||
public string GameWon;
|
||||
public string GameLost;
|
||||
}
|
||||
|
||||
public class Map
|
||||
{
|
||||
[FieldLoader.Ignore] public IFolder Container;
|
||||
@@ -102,7 +111,6 @@ namespace OpenRA
|
||||
|
||||
public string Title;
|
||||
public string Type = "Conquest";
|
||||
public string PreviewVideo;
|
||||
public string Description;
|
||||
public string Author;
|
||||
public string Tileset;
|
||||
@@ -131,6 +139,19 @@ namespace OpenRA
|
||||
return options;
|
||||
}
|
||||
|
||||
[FieldLoader.LoadUsing("LoadVideos")]
|
||||
public MapVideos Videos;
|
||||
|
||||
static object LoadVideos(MiniYaml y)
|
||||
{
|
||||
var videos = new MapVideos();
|
||||
var nodesDict = y.ToDictionary();
|
||||
if (nodesDict.ContainsKey("Videos"))
|
||||
FieldLoader.Load(videos, nodesDict["Videos"]);
|
||||
|
||||
return videos;
|
||||
}
|
||||
|
||||
[FieldLoader.Ignore] public Lazy<Dictionary<string, ActorReference>> Actors;
|
||||
|
||||
public int PlayerCount { get { return Players.Count(p => p.Value.Playable); } }
|
||||
@@ -372,7 +393,6 @@ namespace OpenRA
|
||||
"Title",
|
||||
"Description",
|
||||
"Author",
|
||||
"PreviewVideo",
|
||||
"Tileset",
|
||||
"MapSize",
|
||||
"Bounds",
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
{
|
||||
class LeaveMapLogic
|
||||
{
|
||||
enum Tab { Objectives, Chat };
|
||||
enum Tab { Objectives, Chat }
|
||||
Tab currentTab;
|
||||
|
||||
OrderManager orderManager;
|
||||
@@ -125,6 +125,13 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
var objectivesContainer = dialog.Get<ContainerWidget>("OBJECTIVES_PANEL");
|
||||
Game.LoadWidget(world, panel, objectivesContainer, new WidgetArgs());
|
||||
objectivesContainer.IsVisible = () => currentTab == Tab.Objectives;
|
||||
|
||||
string video = null;
|
||||
if (world.LocalPlayer.WinState != WinState.Undefined)
|
||||
video = world.LocalPlayer.WinState == WinState.Won ? world.Map.Videos.GameWon : world.Map.Videos.GameLost;
|
||||
|
||||
if (!string.IsNullOrEmpty(video))
|
||||
Media.PlayFMVFullscreen(world, video, () => { });
|
||||
}
|
||||
|
||||
if (isMultiplayer)
|
||||
|
||||
@@ -23,14 +23,19 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
public class MissionBrowserLogic
|
||||
{
|
||||
enum PlayingVideo { None, Info, Briefing, GameStart }
|
||||
|
||||
readonly Action onStart;
|
||||
readonly ScrollPanelWidget descriptionPanel;
|
||||
readonly LabelWidget description;
|
||||
readonly SpriteFont descriptionFont;
|
||||
readonly DropDownButtonWidget difficultyButton;
|
||||
readonly ButtonWidget startVideoButton;
|
||||
readonly ButtonWidget stopVideoButton;
|
||||
readonly ButtonWidget startBriefingVideoButton;
|
||||
readonly ButtonWidget stopBriefingVideoButton;
|
||||
readonly ButtonWidget startInfoVideoButton;
|
||||
readonly ButtonWidget stopInfoVideoButton;
|
||||
readonly VqaPlayerWidget videoPlayer;
|
||||
readonly BackgroundWidget fullscreenVideoPlayer;
|
||||
|
||||
readonly ScrollPanelWidget missionList;
|
||||
readonly ScrollItemWidget headerTemplate;
|
||||
@@ -38,12 +43,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
MapPreview selectedMapPreview;
|
||||
|
||||
bool showVideoPlayer;
|
||||
PlayingVideo playingVideo;
|
||||
|
||||
string difficulty;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public MissionBrowserLogic(Widget widget, Action onStart, Action onExit)
|
||||
public MissionBrowserLogic(Widget widget, World world, Action onStart, Action onExit)
|
||||
{
|
||||
this.onStart = onStart;
|
||||
|
||||
@@ -54,16 +59,17 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
var title = widget.GetOrNull<LabelWidget>("MISSIONBROWSER_TITLE");
|
||||
if (title != null)
|
||||
title.GetText = () => showVideoPlayer ? selectedMapPreview.Title : title.Text;
|
||||
title.GetText = () => playingVideo != PlayingVideo.None ? selectedMapPreview.Title : title.Text;
|
||||
|
||||
widget.Get("MISSION_INFO").IsVisible = () => selectedMapPreview != null;
|
||||
|
||||
var previewWidget = widget.Get<MapPreviewWidget>("MISSION_PREVIEW");
|
||||
previewWidget.Preview = () => selectedMapPreview;
|
||||
previewWidget.IsVisible = () => !showVideoPlayer;
|
||||
previewWidget.IsVisible = () => playingVideo == PlayingVideo.None;
|
||||
|
||||
videoPlayer = widget.Get<VqaPlayerWidget>("MISSION_VIDEO");
|
||||
widget.Get("MISSION_BIN").IsVisible = () => showVideoPlayer;
|
||||
widget.Get("MISSION_BIN").IsVisible = () => playingVideo != PlayingVideo.None;
|
||||
fullscreenVideoPlayer = Ui.LoadWidget<BackgroundWidget>("FULLSCREEN_PLAYER", Ui.Root, new WidgetArgs { { "world", world } });
|
||||
|
||||
descriptionPanel = widget.Get<ScrollPanelWidget>("MISSION_DESCRIPTION_PANEL");
|
||||
|
||||
@@ -72,10 +78,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
difficultyButton = widget.Get<DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");
|
||||
|
||||
startVideoButton = widget.Get<ButtonWidget>("START_VIDEO_BUTTON");
|
||||
stopVideoButton = widget.Get<ButtonWidget>("STOP_VIDEO_BUTTON");
|
||||
stopVideoButton.IsVisible = () => showVideoPlayer;
|
||||
stopVideoButton.OnClick = StopVideo;
|
||||
startBriefingVideoButton = widget.Get<ButtonWidget>("START_BRIEFING_VIDEO_BUTTON");
|
||||
stopBriefingVideoButton = widget.Get<ButtonWidget>("STOP_BRIEFING_VIDEO_BUTTON");
|
||||
stopBriefingVideoButton.IsVisible = () => playingVideo == PlayingVideo.Briefing;
|
||||
stopBriefingVideoButton.OnClick = () => StopVideo(videoPlayer);
|
||||
|
||||
startInfoVideoButton = widget.Get<ButtonWidget>("START_INFO_VIDEO_BUTTON");
|
||||
stopInfoVideoButton = widget.Get<ButtonWidget>("STOP_INFO_VIDEO_BUTTON");
|
||||
stopInfoVideoButton.IsVisible = () => playingVideo == PlayingVideo.Info;
|
||||
stopInfoVideoButton.OnClick = () => StopVideo(videoPlayer);
|
||||
|
||||
var allMaps = new List<Map>();
|
||||
missionList.RemoveChildren();
|
||||
@@ -114,12 +125,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
SelectMap(allMaps.First());
|
||||
|
||||
var startButton = widget.Get<ButtonWidget>("STARTGAME_BUTTON");
|
||||
startButton.OnClick = StartMission;
|
||||
startButton.OnClick = StartMissionClicked;
|
||||
startButton.IsDisabled = () => selectedMapPreview.RuleStatus != MapRuleStatus.Cached;
|
||||
|
||||
widget.Get<ButtonWidget>("BACK_BUTTON").OnClick = () =>
|
||||
{
|
||||
StopVideo();
|
||||
StopVideo(videoPlayer);
|
||||
Game.Disconnect();
|
||||
Ui.CloseWindow();
|
||||
onExit();
|
||||
@@ -128,7 +139,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
|
||||
void CreateMissionGroup(string title, IEnumerable<Map> maps)
|
||||
{
|
||||
var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => {});
|
||||
var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });
|
||||
header.Get<LabelWidget>("LABEL").GetText = () => title;
|
||||
missionList.AddChild(header);
|
||||
|
||||
@@ -139,41 +150,35 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
var item = ScrollItemWidget.Setup(template,
|
||||
() => selectedMapPreview != null && selectedMapPreview.Uid == map.Uid,
|
||||
() => SelectMap(map),
|
||||
StartMission);
|
||||
StartMissionClicked);
|
||||
|
||||
item.Get<LabelWidget>("TITLE").GetText = () => map.Title;
|
||||
missionList.AddChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
float cachedSoundVolume;
|
||||
float cachedMusicVolume;
|
||||
void SelectMap(Map map)
|
||||
{
|
||||
StopVideo();
|
||||
|
||||
selectedMapPreview = Game.modData.MapCache[map.Uid];
|
||||
|
||||
// Cache the rules on a background thread to avoid jank
|
||||
new Thread(selectedMapPreview.CacheRules).Start();
|
||||
|
||||
var video = selectedMapPreview.Map.PreviewVideo;
|
||||
var videoVisible = video != null;
|
||||
var videoDisabled = !(videoVisible && GlobalFileSystem.Exists(video));
|
||||
var briefingVideo = selectedMapPreview.Map.Videos.Briefing;
|
||||
var briefingVideoVisible = briefingVideo != null;
|
||||
var briefingVideoDisabled = !(briefingVideoVisible && GlobalFileSystem.Exists(briefingVideo));
|
||||
|
||||
startVideoButton.IsVisible = () => videoVisible && !showVideoPlayer;
|
||||
startVideoButton.IsDisabled = () => videoDisabled;
|
||||
startVideoButton.OnClick = () =>
|
||||
{
|
||||
showVideoPlayer = true;
|
||||
videoPlayer.Load(video);
|
||||
videoPlayer.PlayThen(StopVideo);
|
||||
var infoVideo = selectedMapPreview.Map.Videos.BackgroundInfo;
|
||||
var infoVideoVisible = infoVideo != null;
|
||||
var infoVideoDisabled = !(infoVideoVisible && GlobalFileSystem.Exists(infoVideo));
|
||||
|
||||
// Mute other distracting sounds
|
||||
cachedSoundVolume = Sound.SoundVolume;
|
||||
cachedMusicVolume = Sound.MusicVolume;
|
||||
Sound.SoundVolume = Sound.MusicVolume = 0;
|
||||
};
|
||||
startBriefingVideoButton.IsVisible = () => briefingVideoVisible && playingVideo != PlayingVideo.Briefing;
|
||||
startBriefingVideoButton.IsDisabled = () => briefingVideoDisabled || playingVideo != PlayingVideo.None;
|
||||
startBriefingVideoButton.OnClick = () => PlayVideo(videoPlayer, briefingVideo, PlayingVideo.Briefing, () => StopVideo(videoPlayer));
|
||||
|
||||
startInfoVideoButton.IsVisible = () => infoVideoVisible && playingVideo != PlayingVideo.Info;
|
||||
startInfoVideoButton.IsDisabled = () => infoVideoDisabled || playingVideo != PlayingVideo.None;
|
||||
startInfoVideoButton.OnClick = () => PlayVideo(videoPlayer, infoVideo, PlayingVideo.Info, () => StopVideo(videoPlayer));
|
||||
|
||||
var text = map.Description != null ? map.Description.Replace("\\n", "\n") : "";
|
||||
text = WidgetUtils.WrapText(text, description.Bounds.Width, descriptionFont);
|
||||
@@ -205,25 +210,72 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
};
|
||||
}
|
||||
|
||||
void StopVideo()
|
||||
float cachedSoundVolume;
|
||||
float cachedMusicVolume;
|
||||
void MuteSounds()
|
||||
{
|
||||
if (!showVideoPlayer)
|
||||
return;
|
||||
|
||||
Sound.SoundVolume = cachedSoundVolume;
|
||||
Sound.MusicVolume = cachedMusicVolume;
|
||||
|
||||
videoPlayer.Stop();
|
||||
showVideoPlayer = false;
|
||||
cachedSoundVolume = Sound.SoundVolume;
|
||||
cachedMusicVolume = Sound.MusicVolume;
|
||||
Sound.SoundVolume = Sound.MusicVolume = 0;
|
||||
}
|
||||
|
||||
void StartMission()
|
||||
void UnMuteSounds()
|
||||
{
|
||||
StopVideo();
|
||||
if (cachedSoundVolume > 0)
|
||||
Sound.SoundVolume = cachedSoundVolume;
|
||||
|
||||
if (cachedMusicVolume > 0)
|
||||
Sound.MusicVolume = cachedMusicVolume;
|
||||
}
|
||||
|
||||
void PlayVideo(VqaPlayerWidget player, string video, PlayingVideo pv, Action onComplete)
|
||||
{
|
||||
StopVideo(player);
|
||||
|
||||
playingVideo = pv;
|
||||
player.Load(video);
|
||||
|
||||
// video playback runs asynchronously
|
||||
player.PlayThen(onComplete);
|
||||
|
||||
// Mute other distracting sounds
|
||||
MuteSounds();
|
||||
}
|
||||
|
||||
void StopVideo(VqaPlayerWidget player)
|
||||
{
|
||||
if (playingVideo == PlayingVideo.None)
|
||||
return;
|
||||
|
||||
UnMuteSounds();
|
||||
player.Stop();
|
||||
playingVideo = PlayingVideo.None;
|
||||
}
|
||||
|
||||
void StartMissionClicked()
|
||||
{
|
||||
StopVideo(videoPlayer);
|
||||
|
||||
if (selectedMapPreview.RuleStatus != MapRuleStatus.Cached)
|
||||
return;
|
||||
|
||||
var gameStartVideo = selectedMapPreview.Map.Videos.GameStart;
|
||||
if (gameStartVideo != null && GlobalFileSystem.Exists(gameStartVideo))
|
||||
{
|
||||
var fsPlayer = fullscreenVideoPlayer.Get<VqaPlayerWidget>("PLAYER");
|
||||
fullscreenVideoPlayer.Visible = true;
|
||||
PlayVideo(fsPlayer, gameStartVideo, PlayingVideo.GameStart, () =>
|
||||
{
|
||||
StopVideo(fsPlayer);
|
||||
StartMission();
|
||||
});
|
||||
}
|
||||
else
|
||||
StartMission();
|
||||
}
|
||||
|
||||
void StartMission()
|
||||
{
|
||||
OrderManager om = null;
|
||||
|
||||
Action lobbyReady = null;
|
||||
|
||||
@@ -21,7 +21,7 @@ Container@MISSIONBROWSER_PANEL:
|
||||
X: 15
|
||||
Y: 15
|
||||
Width: 239
|
||||
Height: 347
|
||||
Height: 307
|
||||
Children:
|
||||
ScrollItem@HEADER:
|
||||
Width: PARENT_RIGHT-27
|
||||
@@ -74,6 +74,13 @@ Container@MISSIONBROWSER_PANEL:
|
||||
Width: PARENT_RIGHT - 32
|
||||
VAlign: Top
|
||||
Font: Small
|
||||
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
|
||||
X: 15
|
||||
Y: 337
|
||||
Width: 239
|
||||
Height: 25
|
||||
Text: Difficulty
|
||||
Font: Regular
|
||||
Button@BACK_BUTTON:
|
||||
Y: 376
|
||||
Width: 140
|
||||
@@ -81,20 +88,34 @@ Container@MISSIONBROWSER_PANEL:
|
||||
Text: Back
|
||||
Font: Bold
|
||||
Key: escape
|
||||
Button@START_VIDEO_BUTTON:
|
||||
Button@START_BRIEFING_VIDEO_BUTTON:
|
||||
X: PARENT_RIGHT - 290
|
||||
Y: 376
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: View Briefing
|
||||
Text: Watch Briefing
|
||||
Font: Bold
|
||||
Button@STOP_VIDEO_BUTTON:
|
||||
Button@STOP_BRIEFING_VIDEO_BUTTON:
|
||||
X: PARENT_RIGHT - 290
|
||||
Y: 376
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: Stop Briefing
|
||||
Font: Bold
|
||||
Button@START_INFO_VIDEO_BUTTON:
|
||||
X: PARENT_RIGHT - 440
|
||||
Y: 376
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: Watch Info Video
|
||||
Font: Bold
|
||||
Button@STOP_INFO_VIDEO_BUTTON:
|
||||
X: PARENT_RIGHT - 440
|
||||
Y: 376
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: Stop Info Video
|
||||
Font: Bold
|
||||
Button@STARTGAME_BUTTON:
|
||||
X: PARENT_RIGHT - 140
|
||||
Y: 376
|
||||
@@ -102,13 +123,6 @@ Container@MISSIONBROWSER_PANEL:
|
||||
Height: 35
|
||||
Text: Play
|
||||
Font: Bold
|
||||
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
|
||||
X: PARENT_RIGHT - 290 - 150
|
||||
Y: 376
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: Difficulty
|
||||
Font: Bold
|
||||
Container@MISSION_BIN:
|
||||
Children:
|
||||
VqaPlayer@MISSION_VIDEO:
|
||||
@@ -116,3 +130,14 @@ Container@MISSIONBROWSER_PANEL:
|
||||
Y: 1
|
||||
Width: 640
|
||||
Height: 375
|
||||
Background@FULLSCREEN_PLAYER:
|
||||
Width: WINDOW_RIGHT
|
||||
Height: WINDOW_BOTTOM
|
||||
Background: panel-allblack
|
||||
Visible: False
|
||||
Children:
|
||||
VqaPlayer@PLAYER:
|
||||
X: 0
|
||||
Y: 0
|
||||
Width: WINDOW_RIGHT
|
||||
Height: WINDOW_BOTTOM
|
||||
|
||||
@@ -16,7 +16,7 @@ Background@MISSIONBROWSER_PANEL:
|
||||
X: 20
|
||||
Y: 50
|
||||
Width: 270
|
||||
Height: 377
|
||||
Height: 332
|
||||
Children:
|
||||
ScrollItem@HEADER:
|
||||
BaseName: scrollheader
|
||||
@@ -69,20 +69,34 @@ Background@MISSIONBROWSER_PANEL:
|
||||
Width: PARENT_RIGHT - 32
|
||||
VAlign: Top
|
||||
Font: Small
|
||||
Button@START_VIDEO_BUTTON:
|
||||
Button@START_BRIEFING_VIDEO_BUTTON:
|
||||
X: 20
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 120
|
||||
Width: 130
|
||||
Height: 25
|
||||
Text: Play Briefing
|
||||
Text: Watch Briefing
|
||||
Font: Bold
|
||||
Button@STOP_VIDEO_BUTTON:
|
||||
Button@STOP_BRIEFING_VIDEO_BUTTON:
|
||||
X: 20
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 120
|
||||
Width: 130
|
||||
Height: 25
|
||||
Text: Stop Briefing
|
||||
Font: Bold
|
||||
Button@START_INFO_VIDEO_BUTTON:
|
||||
X: 160
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 130
|
||||
Height: 25
|
||||
Text: Watch Info Video
|
||||
Font: Bold
|
||||
Button@STOP_INFO_VIDEO_BUTTON:
|
||||
X: 160
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 130
|
||||
Height: 25
|
||||
Text: Stop Info Video
|
||||
Font: Bold
|
||||
Button@STARTGAME_BUTTON:
|
||||
X: PARENT_RIGHT - 140 - 130
|
||||
Y: PARENT_BOTTOM - 45
|
||||
@@ -99,9 +113,9 @@ Background@MISSIONBROWSER_PANEL:
|
||||
Font: Bold
|
||||
Key: escape
|
||||
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
|
||||
X: PARENT_RIGHT - 140 - 130 - 150
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 140
|
||||
X: 20
|
||||
Y: 427 - HEIGHT
|
||||
Width: 270
|
||||
Height: 25
|
||||
Text: Difficulty
|
||||
Font: Bold
|
||||
@@ -117,3 +131,14 @@ Background@MISSIONBROWSER_PANEL:
|
||||
Y: 1
|
||||
Width: 640
|
||||
Height: 375
|
||||
Background@FULLSCREEN_PLAYER:
|
||||
Width: WINDOW_RIGHT
|
||||
Height: WINDOW_BOTTOM
|
||||
Background: dialog5
|
||||
Visible: False
|
||||
Children:
|
||||
VqaPlayer@PLAYER:
|
||||
X: 0
|
||||
Y: 0
|
||||
Width: WINDOW_RIGHT
|
||||
Height: WINDOW_BOTTOM
|
||||
|
||||
Reference in New Issue
Block a user