Files
OpenRA/OpenRA.Game/Traits/World/MusicPlaylist.cs
2015-07-12 17:27:12 +02:00

150 lines
3.2 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.GameRules;
namespace OpenRA.Traits
{
[Desc("Trait for music handling. Attach this to the world actor.")]
public class MusicPlaylistInfo : ITraitInfo
{
public readonly string StartingMusic = null;
public readonly bool LoopStartingMusic = false;
public object Create(ActorInitializer init) { return new MusicPlaylist(init.World, this); }
}
public class MusicPlaylist : INotifyActorDisposing
{
readonly MusicInfo[] random;
readonly MusicInfo[] playlist;
public readonly bool IsMusicAvailable;
MusicInfo currentSong;
bool repeat;
public MusicPlaylist(World world, MusicPlaylistInfo info)
{
IsMusicAvailable = world.Map.Rules.InstalledMusic.Any();
playlist = world.Map.Rules.InstalledMusic.Select(a => a.Value).ToArray();
if (!IsMusicAvailable)
return;
random = playlist.Shuffle(Game.CosmeticRandom).ToArray();
if (!string.IsNullOrEmpty(info.StartingMusic)
&& world.Map.Rules.Music.ContainsKey(info.StartingMusic)
&& world.Map.Rules.Music[info.StartingMusic].Exists)
{
currentSong = world.Map.Rules.Music[info.StartingMusic];
repeat = info.LoopStartingMusic;
}
else
{
currentSong = Game.Settings.Sound.Shuffle ? random.First() : playlist.First();
repeat = Game.Settings.Sound.Repeat;
}
Play();
}
public MusicInfo CurrentSong()
{
return currentSong;
}
public MusicInfo[] AvailablePlaylist()
{
// TO-DO: add filter options for Race-specific music
return playlist;
}
void Play()
{
if (currentSong == null || !IsMusicAvailable)
return;
Sound.PlayMusicThen(currentSong, () =>
{
if (!repeat)
currentSong = GetNextSong();
Play();
});
}
public void Play(MusicInfo music)
{
if (music == null || !IsMusicAvailable)
return;
currentSong = music;
repeat = Game.Settings.Sound.Repeat;
Sound.PlayMusicThen(music, () =>
{
if (!repeat)
currentSong = GetNextSong();
Play();
});
}
public void Play(MusicInfo music, Action onComplete)
{
if (music == null || !IsMusicAvailable)
return;
currentSong = music;
Sound.PlayMusicThen(music, onComplete);
}
public MusicInfo GetNextSong()
{
return GetSong(false);
}
public MusicInfo GetPrevSong()
{
return GetSong(true);
}
MusicInfo GetSong(bool reverse)
{
if (!IsMusicAvailable)
return null;
var songs = Game.Settings.Sound.Shuffle ? random : playlist;
return reverse ? songs.SkipWhile(m => m != currentSong)
.Skip(1).FirstOrDefault() ?? songs.FirstOrDefault() :
songs.Reverse().SkipWhile(m => m != currentSong)
.Skip(1).FirstOrDefault() ?? songs.Reverse().FirstOrDefault();
}
public void Stop()
{
currentSong = null;
Sound.StopMusic();
}
public void Disposing(Actor self)
{
if (currentSong != null)
Stop();
}
}
}