Merge pull request #8876 from pchote/music
Refine the music playlist code.
This commit is contained in:
@@ -15,8 +15,10 @@ namespace OpenRA.GameRules
|
|||||||
{
|
{
|
||||||
public class MusicInfo
|
public class MusicInfo
|
||||||
{
|
{
|
||||||
public readonly string Filename = null;
|
public readonly string Filename;
|
||||||
public readonly string Title = null;
|
public readonly string Title;
|
||||||
|
public readonly bool Hidden;
|
||||||
|
|
||||||
public int Length { get; private set; } // seconds
|
public int Length { get; private set; } // seconds
|
||||||
public bool Exists { get; private set; }
|
public bool Exists { get; private set; }
|
||||||
|
|
||||||
@@ -25,18 +27,24 @@ namespace OpenRA.GameRules
|
|||||||
Title = value.Value;
|
Title = value.Value;
|
||||||
|
|
||||||
var nd = value.ToDictionary();
|
var nd = value.ToDictionary();
|
||||||
|
if (nd.ContainsKey("Hidden"))
|
||||||
|
bool.TryParse(nd["Hidden"].Value, out Hidden);
|
||||||
|
|
||||||
var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud";
|
var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud";
|
||||||
Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext;
|
Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext;
|
||||||
|
|
||||||
if (!GlobalFileSystem.Exists(Filename))
|
if (!GlobalFileSystem.Exists(Filename))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Exists = true;
|
Exists = true;
|
||||||
using (var s = GlobalFileSystem.Open(Filename))
|
using (var s = GlobalFileSystem.Open(Filename))
|
||||||
|
{
|
||||||
if (Filename.ToLowerInvariant().EndsWith("wav"))
|
if (Filename.ToLowerInvariant().EndsWith("wav"))
|
||||||
Length = (int)WavLoader.WaveLength(s);
|
Length = (int)WavLoader.WaveLength(s);
|
||||||
else
|
else
|
||||||
Length = (int)AudLoader.SoundLength(s);
|
Length = (int)AudLoader.SoundLength(s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Reload()
|
public void Reload()
|
||||||
{
|
{
|
||||||
@@ -45,6 +53,7 @@ namespace OpenRA.GameRules
|
|||||||
|
|
||||||
Exists = true;
|
Exists = true;
|
||||||
using (var s = GlobalFileSystem.Open(Filename))
|
using (var s = GlobalFileSystem.Open(Filename))
|
||||||
|
{
|
||||||
if (Filename.ToLowerInvariant().EndsWith("wav"))
|
if (Filename.ToLowerInvariant().EndsWith("wav"))
|
||||||
Length = (int)WavLoader.WaveLength(s);
|
Length = (int)WavLoader.WaveLength(s);
|
||||||
else
|
else
|
||||||
@@ -52,3 +61,4 @@ namespace OpenRA.GameRules
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -181,7 +181,6 @@
|
|||||||
<Compile Include="Traits\TraitsInterfaces.cs" />
|
<Compile Include="Traits\TraitsInterfaces.cs" />
|
||||||
<Compile Include="Traits\Util.cs" />
|
<Compile Include="Traits\Util.cs" />
|
||||||
<Compile Include="Traits\ValidateOrder.cs" />
|
<Compile Include="Traits\ValidateOrder.cs" />
|
||||||
<Compile Include="Traits\World\MusicPlaylist.cs" />
|
|
||||||
<Compile Include="Traits\World\Faction.cs" />
|
<Compile Include="Traits\World\Faction.cs" />
|
||||||
<Compile Include="Traits\World\ResourceType.cs" />
|
<Compile Include="Traits\World\ResourceType.cs" />
|
||||||
<Compile Include="Traits\World\ScreenShaker.cs" />
|
<Compile Include="Traits\World\ScreenShaker.cs" />
|
||||||
|
|||||||
@@ -702,6 +702,7 @@
|
|||||||
<Compile Include="Traits\RevealsShroud.cs" />
|
<Compile Include="Traits\RevealsShroud.cs" />
|
||||||
<Compile Include="Lint\CheckRevealFootprint.cs" />
|
<Compile Include="Lint\CheckRevealFootprint.cs" />
|
||||||
<Compile Include="Traits\ThrowsShrapnel.cs" />
|
<Compile Include="Traits\ThrowsShrapnel.cs" />
|
||||||
|
<Compile Include="Traits\World\MusicPlaylist.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using OpenRA.FileFormats;
|
|||||||
using OpenRA.FileSystem;
|
using OpenRA.FileSystem;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Effects;
|
using OpenRA.Mods.Common.Effects;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Scripting;
|
using OpenRA.Scripting;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.GameRules;
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
[Desc("Trait for music handling. Attach this to the world actor.")]
|
[Desc("Trait for music handling. Attach this to the world actor.")]
|
||||||
public class MusicPlaylistInfo : ITraitInfo
|
public class MusicPlaylistInfo : ITraitInfo
|
||||||
@@ -20,20 +21,15 @@ namespace OpenRA.Traits
|
|||||||
[Desc("Music to play when the map starts.", "Plays the first song on the playlist when undefined.")]
|
[Desc("Music to play when the map starts.", "Plays the first song on the playlist when undefined.")]
|
||||||
public readonly string StartingMusic = null;
|
public readonly string StartingMusic = null;
|
||||||
|
|
||||||
[Desc("Should the starting music loop?")]
|
|
||||||
public readonly bool LoopStartingMusic = false;
|
|
||||||
|
|
||||||
[Desc("Music to play when the game has been won.")]
|
[Desc("Music to play when the game has been won.")]
|
||||||
public readonly string VictoryMusic = null;
|
public readonly string VictoryMusic = null;
|
||||||
|
|
||||||
[Desc("Should the victory music loop?")]
|
|
||||||
public readonly bool LoopVictoryMusic = false;
|
|
||||||
|
|
||||||
[Desc("Music to play when the game has been lost.")]
|
[Desc("Music to play when the game has been lost.")]
|
||||||
public readonly string DefeatMusic = null;
|
public readonly string DefeatMusic = null;
|
||||||
|
|
||||||
[Desc("Should the defeat music loop?")]
|
[Desc("This track is played when no other music is playing.",
|
||||||
public readonly bool LoopDefeatMusic = false;
|
"It cannot be paused, but can be overridden by selecting a new track.")]
|
||||||
|
public readonly string BackgroundMusic = null;
|
||||||
|
|
||||||
public object Create(ActorInitializer init) { return new MusicPlaylist(init.World, this); }
|
public object Create(ActorInitializer init) { return new MusicPlaylist(init.World, this); }
|
||||||
}
|
}
|
||||||
@@ -41,44 +37,65 @@ namespace OpenRA.Traits
|
|||||||
public class MusicPlaylist : INotifyActorDisposing, IGameOver
|
public class MusicPlaylist : INotifyActorDisposing, IGameOver
|
||||||
{
|
{
|
||||||
readonly MusicPlaylistInfo info;
|
readonly MusicPlaylistInfo info;
|
||||||
|
readonly World world;
|
||||||
|
|
||||||
readonly MusicInfo[] random;
|
readonly MusicInfo[] random;
|
||||||
readonly MusicInfo[] playlist;
|
readonly MusicInfo[] playlist;
|
||||||
|
|
||||||
|
public readonly bool IsMusicInstalled;
|
||||||
public readonly bool IsMusicAvailable;
|
public readonly bool IsMusicAvailable;
|
||||||
|
public bool CurrentSongIsBackground { get; private set; }
|
||||||
|
|
||||||
MusicInfo currentSong;
|
MusicInfo currentSong;
|
||||||
bool repeat;
|
MusicInfo currentBackgroundSong;
|
||||||
|
|
||||||
public MusicPlaylist(World world, MusicPlaylistInfo info)
|
public MusicPlaylist(World world, MusicPlaylistInfo info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
|
this.world = world;
|
||||||
|
|
||||||
IsMusicAvailable = world.Map.Rules.InstalledMusic.Any();
|
IsMusicInstalled = world.Map.Rules.InstalledMusic.Any();
|
||||||
|
if (!IsMusicInstalled)
|
||||||
playlist = world.Map.Rules.InstalledMusic.Select(a => a.Value).ToArray();
|
|
||||||
|
|
||||||
if (!IsMusicAvailable)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
random = playlist.Shuffle(Game.CosmeticRandom).ToArray();
|
playlist = world.Map.Rules.InstalledMusic
|
||||||
|
.Where(a => !a.Value.Hidden)
|
||||||
|
.Select(a => a.Value)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(info.StartingMusic)
|
random = playlist.Shuffle(Game.CosmeticRandom).ToArray();
|
||||||
&& world.Map.Rules.Music.ContainsKey(info.StartingMusic)
|
IsMusicAvailable = playlist.Any();
|
||||||
&& world.Map.Rules.Music[info.StartingMusic].Exists)
|
|
||||||
{
|
if (SongExists(info.StartingMusic))
|
||||||
currentSong = world.Map.Rules.Music[info.StartingMusic];
|
currentSong = world.Map.Rules.Music[info.StartingMusic];
|
||||||
repeat = info.LoopStartingMusic;
|
else if (SongExists(info.BackgroundMusic))
|
||||||
|
{
|
||||||
|
currentSong = currentBackgroundSong = world.Map.Rules.Music[info.BackgroundMusic];
|
||||||
|
CurrentSongIsBackground = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentSong = Game.Settings.Sound.Shuffle ? random.First() : playlist.First();
|
// Start playback with a random song, but only if the player has installed more music
|
||||||
repeat = Game.Settings.Sound.Repeat;
|
var installData = Game.ModData.Manifest.Get<ContentInstaller>();
|
||||||
|
if (playlist.Length > installData.ShippedSoundtracks)
|
||||||
|
currentSong = random.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
Play();
|
Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SongExists(string song)
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(song)
|
||||||
|
&& world.Map.Rules.Music.ContainsKey(song)
|
||||||
|
&& world.Map.Rules.Music[song].Exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SongExists(MusicInfo song)
|
||||||
|
{
|
||||||
|
return song != null && song.Exists;
|
||||||
|
}
|
||||||
|
|
||||||
public MusicInfo CurrentSong()
|
public MusicInfo CurrentSong()
|
||||||
{
|
{
|
||||||
return currentSong;
|
return currentSong;
|
||||||
@@ -92,46 +109,34 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public void GameOver(World world)
|
public void GameOver(World world)
|
||||||
{
|
{
|
||||||
if (!IsMusicAvailable)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var playedSong = currentSong;
|
|
||||||
|
|
||||||
if (world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Won)
|
if (world.LocalPlayer != null && world.LocalPlayer.WinState == WinState.Won)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(info.VictoryMusic)
|
if (SongExists(info.VictoryMusic))
|
||||||
&& world.Map.Rules.Music.ContainsKey(info.VictoryMusic)
|
|
||||||
&& world.Map.Rules.Music[info.VictoryMusic].Exists)
|
|
||||||
{
|
{
|
||||||
currentSong = world.Map.Rules.Music[info.VictoryMusic];
|
currentBackgroundSong = world.Map.Rules.Music[info.VictoryMusic];
|
||||||
repeat = info.LoopVictoryMusic;
|
Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Most RTS treats observers losing the game,
|
// Most RTS treats observers losing the game,
|
||||||
// no need for a special handling involving them here.
|
// no need for a special handling involving them here.
|
||||||
if (!string.IsNullOrEmpty(info.DefeatMusic)
|
if (SongExists(info.DefeatMusic))
|
||||||
&& world.Map.Rules.Music.ContainsKey(info.DefeatMusic)
|
|
||||||
&& world.Map.Rules.Music[info.DefeatMusic].Exists)
|
|
||||||
{
|
{
|
||||||
currentSong = world.Map.Rules.Music[info.DefeatMusic];
|
currentBackgroundSong = world.Map.Rules.Music[info.DefeatMusic];
|
||||||
repeat = info.LoopDefeatMusic;
|
Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playedSong != currentSong)
|
|
||||||
Play();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Play()
|
void Play()
|
||||||
{
|
{
|
||||||
if (currentSong == null || !IsMusicAvailable)
|
if (!SongExists(currentSong))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Sound.PlayMusicThen(currentSong, () =>
|
Sound.PlayMusicThen(currentSong, () =>
|
||||||
{
|
{
|
||||||
if (!repeat)
|
if (!CurrentSongIsBackground && !Game.Settings.Sound.Repeat)
|
||||||
currentSong = GetNextSong();
|
currentSong = GetNextSong();
|
||||||
|
|
||||||
Play();
|
Play();
|
||||||
@@ -140,27 +145,22 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public void Play(MusicInfo music)
|
public void Play(MusicInfo music)
|
||||||
{
|
{
|
||||||
if (music == null || !IsMusicAvailable)
|
if (music == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currentSong = music;
|
currentSong = music;
|
||||||
repeat = Game.Settings.Sound.Repeat;
|
CurrentSongIsBackground = false;
|
||||||
|
|
||||||
Sound.PlayMusicThen(music, () =>
|
|
||||||
{
|
|
||||||
if (!repeat)
|
|
||||||
currentSong = GetNextSong();
|
|
||||||
|
|
||||||
Play();
|
Play();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Play(MusicInfo music, Action onComplete)
|
public void Play(MusicInfo music, Action onComplete)
|
||||||
{
|
{
|
||||||
if (music == null || !IsMusicAvailable)
|
if (music == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currentSong = music;
|
currentSong = music;
|
||||||
|
CurrentSongIsBackground = false;
|
||||||
Sound.PlayMusicThen(music, onComplete);
|
Sound.PlayMusicThen(music, onComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,22 +181,34 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
var songs = Game.Settings.Sound.Shuffle ? random : playlist;
|
var songs = Game.Settings.Sound.Shuffle ? random : playlist;
|
||||||
|
|
||||||
return reverse ? songs.SkipWhile(m => m != currentSong)
|
var next = reverse ? songs.Reverse().SkipWhile(m => m != currentSong)
|
||||||
.Skip(1).FirstOrDefault() ?? songs.FirstOrDefault() :
|
.Skip(1).FirstOrDefault() ?? songs.Reverse().FirstOrDefault() :
|
||||||
songs.Reverse().SkipWhile(m => m != currentSong)
|
songs.SkipWhile(m => m != currentSong)
|
||||||
.Skip(1).FirstOrDefault() ?? songs.Reverse().FirstOrDefault();
|
.Skip(1).FirstOrDefault() ?? songs.FirstOrDefault();
|
||||||
|
|
||||||
|
if (SongExists(next))
|
||||||
|
return next;
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
currentSong = null;
|
currentSong = null;
|
||||||
Sound.StopMusic();
|
Sound.StopMusic();
|
||||||
|
|
||||||
|
if (currentBackgroundSong != null)
|
||||||
|
{
|
||||||
|
currentSong = currentBackgroundSong;
|
||||||
|
CurrentSongIsBackground = true;
|
||||||
|
Play();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disposing(Actor self)
|
public void Disposing(Actor self)
|
||||||
{
|
{
|
||||||
if (currentSong != null)
|
if (currentSong != null)
|
||||||
Stop();
|
Sound.StopMusic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -560,7 +560,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
|
musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
|
||||||
{
|
{
|
||||||
{ "onExit", DoNothing },
|
{ "onExit", DoNothing },
|
||||||
{ "world", orderManager.World }
|
{ "world", worldRenderer.World }
|
||||||
});
|
});
|
||||||
|
|
||||||
var settingsButton = lobby.GetOrNull<ButtonWidget>("SETTINGS_BUTTON");
|
var settingsButton = lobby.GetOrNull<ButtonWidget>("SETTINGS_BUTTON");
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.GameRules;
|
using OpenRA.GameRules;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
@@ -35,8 +35,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
BuildMusicTable();
|
BuildMusicTable();
|
||||||
|
|
||||||
Func<bool> noMusic = () => !musicPlaylist.IsMusicAvailable;
|
Func<bool> noMusic = () => !musicPlaylist.IsMusicAvailable || musicPlaylist.CurrentSongIsBackground || currentSong == null;
|
||||||
panel.Get("NO_MUSIC_LABEL").IsVisible = noMusic;
|
panel.Get("NO_MUSIC_LABEL").IsVisible = () => !musicPlaylist.IsMusicAvailable;
|
||||||
|
|
||||||
var playButton = panel.Get<ButtonWidget>("BUTTON_PLAY");
|
var playButton = panel.Get<ButtonWidget>("BUTTON_PLAY");
|
||||||
playButton.OnClick = Play;
|
playButton.OnClick = Play;
|
||||||
@@ -63,14 +63,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var shuffleCheckbox = panel.Get<CheckboxWidget>("SHUFFLE");
|
var shuffleCheckbox = panel.Get<CheckboxWidget>("SHUFFLE");
|
||||||
shuffleCheckbox.IsChecked = () => Game.Settings.Sound.Shuffle;
|
shuffleCheckbox.IsChecked = () => Game.Settings.Sound.Shuffle;
|
||||||
shuffleCheckbox.OnClick = () => Game.Settings.Sound.Shuffle ^= true;
|
shuffleCheckbox.OnClick = () => Game.Settings.Sound.Shuffle ^= true;
|
||||||
|
shuffleCheckbox.IsDisabled = () => musicPlaylist.CurrentSongIsBackground;
|
||||||
|
|
||||||
var repeatCheckbox = panel.Get<CheckboxWidget>("REPEAT");
|
var repeatCheckbox = panel.Get<CheckboxWidget>("REPEAT");
|
||||||
repeatCheckbox.IsChecked = () => Game.Settings.Sound.Repeat;
|
repeatCheckbox.IsChecked = () => Game.Settings.Sound.Repeat;
|
||||||
repeatCheckbox.OnClick = () => Game.Settings.Sound.Repeat ^= true;
|
repeatCheckbox.OnClick = () => Game.Settings.Sound.Repeat ^= true;
|
||||||
|
repeatCheckbox.IsDisabled = () => musicPlaylist.CurrentSongIsBackground;
|
||||||
|
|
||||||
panel.Get<LabelWidget>("TIME_LABEL").GetText = () => (currentSong == null) ? "" :
|
panel.Get<LabelWidget>("TIME_LABEL").GetText = () =>
|
||||||
"{0:D2}:{1:D2} / {2:D2}:{3:D2}".F((int)Sound.MusicSeekPosition / 60, (int)Sound.MusicSeekPosition % 60,
|
{
|
||||||
currentSong.Length / 60, currentSong.Length % 60);
|
if (currentSong == null || musicPlaylist.CurrentSongIsBackground)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
var minutes = (int)Sound.MusicSeekPosition / 60;
|
||||||
|
var seconds = (int)Sound.MusicSeekPosition % 60;
|
||||||
|
var totalMinutes = currentSong.Length / 60;
|
||||||
|
var totalSeconds = currentSong.Length % 60;
|
||||||
|
|
||||||
|
return "{0:D2}:{1:D2} / {2:D2}:{3:D2}".F(minutes, seconds, totalMinutes, totalSeconds);
|
||||||
|
};
|
||||||
|
|
||||||
var musicSlider = panel.Get<SliderWidget>("MUSIC_SLIDER");
|
var musicSlider = panel.Get<SliderWidget>("MUSIC_SLIDER");
|
||||||
musicSlider.OnChange += x => Sound.MusicVolume = x;
|
musicSlider.OnChange += x => Sound.MusicVolume = x;
|
||||||
@@ -94,7 +105,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
songWatcher.OnTick = () =>
|
songWatcher.OnTick = () =>
|
||||||
{
|
{
|
||||||
if (Sound.CurrentMusic == null || currentSong == Sound.CurrentMusic)
|
if (musicPlaylist.CurrentSongIsBackground && currentSong != null)
|
||||||
|
currentSong = null;
|
||||||
|
|
||||||
|
if (Sound.CurrentMusic == null || currentSong == Sound.CurrentMusic || musicPlaylist.CurrentSongIsBackground)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currentSong = Sound.CurrentMusic;
|
currentSong = Sound.CurrentMusic;
|
||||||
@@ -111,23 +125,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
var music = musicPlaylist.AvailablePlaylist();
|
var music = musicPlaylist.AvailablePlaylist();
|
||||||
currentSong = musicPlaylist.CurrentSong();
|
currentSong = musicPlaylist.CurrentSong();
|
||||||
if (currentSong == null && music.Any())
|
|
||||||
currentSong = musicPlaylist.GetNextSong();
|
|
||||||
|
|
||||||
musicList.RemoveChildren();
|
musicList.RemoveChildren();
|
||||||
foreach (var s in music)
|
foreach (var s in music)
|
||||||
{
|
{
|
||||||
var song = s;
|
var song = s;
|
||||||
if (currentSong == null)
|
|
||||||
currentSong = song;
|
|
||||||
|
|
||||||
var item = ScrollItemWidget.Setup(song.Filename, itemTemplate, () => currentSong == song, () => { currentSong = song; Play(); }, () => { });
|
var item = ScrollItemWidget.Setup(song.Filename, itemTemplate, () => currentSong == song, () => { currentSong = song; Play(); }, () => { });
|
||||||
item.Get<LabelWidget>("TITLE").GetText = () => song.Title;
|
item.Get<LabelWidget>("TITLE").GetText = () => song.Title;
|
||||||
item.Get<LabelWidget>("LENGTH").GetText = () => SongLengthLabel(song);
|
item.Get<LabelWidget>("LENGTH").GetText = () => SongLengthLabel(song);
|
||||||
musicList.AddChild(item);
|
musicList.AddChild(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentSong != null)
|
if (currentSong != null && !musicPlaylist.CurrentSongIsBackground)
|
||||||
musicList.ScrollToItem(currentSong.Filename);
|
musicList.ScrollToItem(currentSong.Filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ fwp: Fight Win Prevail
|
|||||||
fist226m: Iron Fist
|
fist226m: Iron Fist
|
||||||
warfare: Warfare (Full Stop)
|
warfare: Warfare (Full Stop)
|
||||||
win1: Great Shot!
|
win1: Great Shot!
|
||||||
|
Hidden: true
|
||||||
win2: Great Shot! (Voiced)
|
win2: Great Shot! (Voiced)
|
||||||
Filename: win2
|
Filename: win2
|
||||||
Extension: var
|
Extension: var
|
||||||
@@ -41,6 +42,7 @@ justdoit2: Just Do it Up (Voiced)
|
|||||||
Filename: justdoit
|
Filename: justdoit
|
||||||
Extension: var
|
Extension: var
|
||||||
map1: Map Theme
|
map1: Map Theme
|
||||||
|
Hidden: true
|
||||||
march: March to Doom
|
march: March to Doom
|
||||||
nomercy: No Mercy
|
nomercy: No Mercy
|
||||||
nomercy2: No Mercy (Voiced)
|
nomercy2: No Mercy (Voiced)
|
||||||
@@ -58,5 +60,9 @@ target: Target (Mechanical Man)
|
|||||||
j1: Untamed Land
|
j1: Untamed Land
|
||||||
valkyrie: Ride of the Valkyries
|
valkyrie: Ride of the Valkyries
|
||||||
voic226m: Voice Rhythm
|
voic226m: Voice Rhythm
|
||||||
|
outtakes: Outtakes
|
||||||
|
Hidden: true
|
||||||
nod_map1: Nod Map Theme
|
nod_map1: Nod Map Theme
|
||||||
|
Hidden: true
|
||||||
nod_win1: Nod Win Theme
|
nod_win1: Nod Win Theme
|
||||||
|
Hidden: true
|
||||||
|
|||||||
@@ -995,8 +995,7 @@ Rules:
|
|||||||
LuaScript:
|
LuaScript:
|
||||||
Scripts: shellmap.lua
|
Scripts: shellmap.lua
|
||||||
MusicPlaylist:
|
MusicPlaylist:
|
||||||
StartingMusic: map1
|
BackgroundMusic: map1
|
||||||
LoopStartingMusic: True
|
|
||||||
LST:
|
LST:
|
||||||
Mobile:
|
Mobile:
|
||||||
Speed: 42
|
Speed: 42
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ LANDSAND: Land of Sand
|
|||||||
Extension: AUD
|
Extension: AUD
|
||||||
OPTIONS: Options
|
OPTIONS: Options
|
||||||
Extension: AUD
|
Extension: AUD
|
||||||
|
Hidden: true
|
||||||
PLOTTING: Plotting
|
PLOTTING: Plotting
|
||||||
Extension: AUD
|
Extension: AUD
|
||||||
RISEHARK: Rise of Harkonnen
|
RISEHARK: Rise of Harkonnen
|
||||||
@@ -25,6 +26,7 @@ ROBOTIX: Robotix
|
|||||||
Extension: AUD
|
Extension: AUD
|
||||||
SCORE: Score
|
SCORE: Score
|
||||||
Extension: AUD
|
Extension: AUD
|
||||||
|
Hidden: true
|
||||||
SOLDAPPR: The Soldiers Approach
|
SOLDAPPR: The Soldiers Approach
|
||||||
Extension: AUD
|
Extension: AUD
|
||||||
SPICESCT: Spice Scouting
|
SPICESCT: Spice Scouting
|
||||||
|
|||||||
@@ -124,8 +124,7 @@ Rules:
|
|||||||
Minimum: 1
|
Minimum: 1
|
||||||
Maximum: 1
|
Maximum: 1
|
||||||
MusicPlaylist:
|
MusicPlaylist:
|
||||||
StartingMusic: options
|
BackgroundMusic: options
|
||||||
LoopStartingMusic: True
|
|
||||||
rockettower:
|
rockettower:
|
||||||
Power:
|
Power:
|
||||||
Amount: 100
|
Amount: 100
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
intro: Intro
|
intro: Intro
|
||||||
|
Hidden: true
|
||||||
map: Map
|
map: Map
|
||||||
|
Hidden: true
|
||||||
score: Militant Force
|
score: Militant Force
|
||||||
|
Hidden: true
|
||||||
await_r: Await
|
await_r: Await
|
||||||
bigf226m: Bigfoot
|
bigf226m: Bigfoot
|
||||||
credits: End Credits
|
credits: Reload Fire
|
||||||
crus226m: Crush
|
crus226m: Crush
|
||||||
dense_r: Dense
|
dense_r: Dense
|
||||||
fac1226m: Face to the Enemy 1
|
fac1226m: Face to the Enemy 1
|
||||||
|
|||||||
@@ -1255,6 +1255,8 @@ Rules:
|
|||||||
-CrateSpawner:
|
-CrateSpawner:
|
||||||
-SpawnMPUnits:
|
-SpawnMPUnits:
|
||||||
-MPStartLocations:
|
-MPStartLocations:
|
||||||
|
MusicPlaylist:
|
||||||
|
BackgroundMusic: intro
|
||||||
ResourceType@ore:
|
ResourceType@ore:
|
||||||
ValuePerUnit: 0
|
ValuePerUnit: 0
|
||||||
LuaScript:
|
LuaScript:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#Tiberian Sun
|
#Tiberian Sun
|
||||||
intro: Intro
|
intro: Intro
|
||||||
|
Hidden: true
|
||||||
approach: Approach
|
approach: Approach
|
||||||
defense: The Defense
|
defense: The Defense
|
||||||
duskhour: Dusk Hour
|
duskhour: Dusk Hour
|
||||||
@@ -14,12 +15,14 @@ nodcrush: Nod Crush
|
|||||||
pharotek: Pharotek
|
pharotek: Pharotek
|
||||||
redsky: Red Sky
|
redsky: Red Sky
|
||||||
score: Score
|
score: Score
|
||||||
|
Hidden: true
|
||||||
scout: Scouting
|
scout: Scouting
|
||||||
storm: Storm
|
storm: Storm
|
||||||
timebomb: Timebomb
|
timebomb: Timebomb
|
||||||
valves1b: Valves
|
valves1b: Valves
|
||||||
whatlurk: What Lurks
|
whatlurk: What Lurks
|
||||||
maps: Map Selection
|
maps: Map Selection
|
||||||
|
Hidden: true
|
||||||
#Firestorm
|
#Firestorm
|
||||||
dmachine: Deploy Machines
|
dmachine: Deploy Machines
|
||||||
elusive: Elusive
|
elusive: Elusive
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ Rules:
|
|||||||
-SpawnMPUnits:
|
-SpawnMPUnits:
|
||||||
-MPStartLocations:
|
-MPStartLocations:
|
||||||
MusicPlaylist:
|
MusicPlaylist:
|
||||||
StartingMusic: intro
|
BackgroundMusic: intro
|
||||||
LoopStartingMusic: True
|
|
||||||
|
|
||||||
Sequences:
|
Sequences:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user