diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj
index 70872d0c8b..0072033ca7 100644
--- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj
+++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj
@@ -80,6 +80,7 @@
+
diff --git a/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs
index c6a6748d64..7ee6de97a6 100755
--- a/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs
+++ b/OpenRA.Mods.Cnc/Widgets/CncIngameChromeLogic.cs
@@ -89,7 +89,10 @@ namespace OpenRA.Mods.Cnc.Widgets
{
menu = widget.GetWidget("INGAME_MENU");
world.WorldActor.Trait().Active = true;
-
+
+ bool hideButtons = false;
+ menu.GetWidget("MENU_BUTTONS").IsVisible = () => !hideButtons;
+
var onQuit = (Action)(() =>
{
Game.DisconnectOnly();
@@ -108,7 +111,15 @@ namespace OpenRA.Mods.Cnc.Widgets
surrenderButton.OnClick = () =>
PromptConfirmAction("Surrender", "Are you sure you want to surrender?", onSurrender, doNothing);
- menu.GetWidget("MUSIC_BUTTON").IsDisabled = () => true;
+ menu.GetWidget("MUSIC_BUTTON").OnClick = () =>
+ {
+ hideButtons = true;
+ Widget.OpenWindow("MUSIC_PANEL", new Dictionary()
+ {
+ { "onExit", new Action(() => { hideButtons = false; Widget.CloseWindow(); }) },
+ });
+ };
+
menu.GetWidget("PREFERENCES_BUTTON").IsDisabled = () => true;
menu.GetWidget("RESUME_BUTTON").OnClick = () =>
diff --git a/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs
index 5113b4a898..4be5310c24 100755
--- a/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs
+++ b/OpenRA.Mods.Cnc/Widgets/CncMenuLogic.cs
@@ -99,7 +99,15 @@ namespace OpenRA.Mods.Cnc.Widgets
settingsMenu.IsVisible = () => Menu == MenuType.Settings;
settingsMenu.GetWidget("MODS_BUTTON").IsDisabled = () => true;
- settingsMenu.GetWidget("MUSIC_BUTTON").IsDisabled = () => true;
+ settingsMenu.GetWidget("MUSIC_BUTTON").OnClick = () =>
+ {
+ Menu = MenuType.None;
+ Widget.OpenWindow("MUSIC_PANEL", new Dictionary()
+ {
+ { "onExit", new Action(() => ReturnToMenu(MenuType.Main)) },
+ });
+ };
+
settingsMenu.GetWidget("PREFERENCES_BUTTON").IsDisabled = () => true;
settingsMenu.GetWidget("BACK_BUTTON").OnClick = () => Menu = MenuType.Main;
}
diff --git a/OpenRA.Mods.Cnc/Widgets/CncMusicPlayerLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncMusicPlayerLogic.cs
new file mode 100644
index 0000000000..1f661ce170
--- /dev/null
+++ b/OpenRA.Mods.Cnc/Widgets/CncMusicPlayerLogic.cs
@@ -0,0 +1,167 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2011 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.Drawing;
+using System.Linq;
+using OpenRA.FileFormats;
+using OpenRA.Support;
+using OpenRA.Widgets;
+using OpenRA.Traits;
+using OpenRA.Graphics;
+
+namespace OpenRA.Mods.Cnc.Widgets
+{
+ public class CncMusicPlayerLogic : IWidgetDelegate
+ {
+ bool installed;
+ string currentSong = null;
+ Widget panel;
+ string[] music;
+ string[] random;
+
+ [ObjectCreator.UseCtor]
+ public CncMusicPlayerLogic([ObjectCreator.Param] Widget widget,
+ [ObjectCreator.Param] Action onExit)
+ {
+ panel = widget.GetWidget("MUSIC_PANEL");
+ BuildMusicTable(panel);
+
+ currentSong = GetNextSong();
+ installed = Rules.Music.Where(m => m.Value.Exists).Any();
+ Func noMusic = () => !installed;
+
+ panel.GetWidget("BACK_BUTTON").OnClick = onExit;
+ panel.GetWidget("INSTALL_BUTTON").IsDisabled = () => true;
+ panel.GetWidget("NO_MUSIC_LABEL").IsVisible = noMusic;
+
+ var playButton = panel.GetWidget("BUTTON_PLAY");
+ playButton.OnClick = Play;
+ playButton.IsDisabled = noMusic;
+
+ var pauseButton = panel.GetWidget("BUTTON_PAUSE");
+ pauseButton.OnClick = Pause;
+ pauseButton.IsDisabled = noMusic;
+
+ var stopButton = panel.GetWidget("BUTTON_STOP");
+ stopButton.OnClick = Stop;
+ stopButton.IsDisabled = noMusic;
+
+ var nextButton = panel.GetWidget("BUTTON_NEXT");
+ nextButton.OnClick = () => { currentSong = GetNextSong(); Play(); };
+ nextButton.IsDisabled = noMusic;
+
+ var prevButton = panel.GetWidget("BUTTON_PREV");
+ prevButton.OnClick = () => { currentSong = GetPrevSong(); Play(); };
+ prevButton.IsDisabled = noMusic;
+
+ var shuffleCheckbox = panel.GetWidget("SHUFFLE");
+ shuffleCheckbox.IsChecked = () => Game.Settings.Sound.Shuffle;
+ shuffleCheckbox.OnClick = () => Game.Settings.Sound.Shuffle ^= true;
+
+ var repeatCheckbox = panel.GetWidget("REPEAT");
+ repeatCheckbox.IsChecked = () => Game.Settings.Sound.Repeat;
+ repeatCheckbox.OnClick = () => Game.Settings.Sound.Repeat ^= true;
+
+ panel.GetWidget("TIME_LABEL").GetText = () => (currentSong == null) ? "" :
+ "{0:D2}:{1:D2} / {2:D2}:{3:D2}".F((int)Sound.MusicSeekPosition / 60, (int)Sound.MusicSeekPosition % 60,
+ Rules.Music[currentSong].Length / 60, Rules.Music[currentSong].Length % 60);
+ }
+
+ void BuildMusicTable(Widget panel)
+ {
+ music = Rules.Music.Where(a => a.Value.Exists)
+ .Select(a => a.Key).ToArray();
+ random = music.Shuffle(Game.CosmeticRandom).ToArray();
+
+ var ml = panel.GetWidget("MUSIC_LIST");
+ var itemTemplate = ml.GetWidget("MUSIC_TEMPLATE");
+
+ foreach (var s in music)
+ {
+ var song = s;
+ if (currentSong == null)
+ currentSong = song;
+
+ var template = itemTemplate.Clone() as ContainerWidget;
+ template.GetBackground = () => (template.RenderBounds.Contains(Viewport.LastMousePos) ? "button-hover" : (song == currentSong) ? "button-pressed" : null);
+ template.OnMouseDown = mi =>
+ {
+ if (mi.Button != MouseButton.Left) return false;
+ currentSong = song;
+ Play();
+ return true;
+ };
+
+ template.IsVisible = () => true;
+ template.GetWidget("TITLE").GetText = () => Rules.Music[song].Title;
+ template.GetWidget("LENGTH").GetText = () => SongLengthLabel(song);
+ ml.AddChild(template);
+ }
+ }
+
+
+ void Play()
+ {
+ if (currentSong == null)
+ return;
+
+ Sound.PlayMusicThen(Rules.Music[currentSong].Filename, () =>
+ {
+ if (!Game.Settings.Sound.Repeat)
+ currentSong = GetNextSong();
+ Play();
+ });
+
+ panel.GetWidget("BUTTON_PLAY").Visible = false;
+ panel.GetWidget("BUTTON_PAUSE").Visible = true;
+ }
+
+ void Pause()
+ {
+ Sound.PauseMusic();
+ panel.GetWidget("BUTTON_PAUSE").Visible = false;
+ panel.GetWidget("BUTTON_PLAY").Visible = true;
+ }
+
+ void Stop()
+ {
+ Sound.StopMusic();
+ panel.GetWidget("BUTTON_PAUSE").Visible = false;
+ panel.GetWidget("BUTTON_PLAY").Visible = true;
+ }
+
+ string SongLengthLabel(string song)
+ {
+ return "{0:D1}:{1:D2}".F(Rules.Music[song].Length / 60,
+ Rules.Music[song].Length % 60);
+ }
+
+ string GetNextSong()
+ {
+ if (!music.Any())
+ return null;
+
+ var songs = Game.Settings.Sound.Shuffle ? random : music;
+ return songs.SkipWhile(m => m != currentSong)
+ .Skip(1).FirstOrDefault() ?? songs.FirstOrDefault();
+ }
+
+ string GetPrevSong()
+ {
+ if (!music.Any())
+ return null;
+
+ var songs = Game.Settings.Sound.Shuffle ? random : music;
+ return songs.Reverse().SkipWhile(m => m != currentSong)
+ .Skip(1).FirstOrDefault() ?? songs.FirstOrDefault();
+ }
+ }
+}
diff --git a/mods/cnc/chrome/ingamemenu.yaml b/mods/cnc/chrome/ingamemenu.yaml
index 26b83b16f2..9f70a84c83 100644
--- a/mods/cnc/chrome/ingamemenu.yaml
+++ b/mods/cnc/chrome/ingamemenu.yaml
@@ -19,7 +19,8 @@ Container@INGAME_MENU:
Width:WINDOW_RIGHT
Height:WINDOW_BOTTOM
Background:shellmapborder
- Container@MENUS:
+ Container@MENU_BUTTONS:
+ Id:MENU_BUTTONS
X:(WINDOW_RIGHT-WIDTH)/2
Y:WINDOW_BOTTOM-33-HEIGHT-10
Width:740
diff --git a/mods/cnc/chrome/music.yaml b/mods/cnc/chrome/music.yaml
new file mode 100644
index 0000000000..d12102ad4d
--- /dev/null
+++ b/mods/cnc/chrome/music.yaml
@@ -0,0 +1,185 @@
+Container@MUSIC_PANEL:
+ Id:MUSIC_PANEL
+ Delegate:CncMusicPlayerLogic
+ X:(WINDOW_RIGHT - WIDTH)/2
+ Y:(WINDOW_BOTTOM - 400)/2
+ Width:360
+ Height:435
+ Children:
+ Label@TITLE:
+ Width:360
+ Y:0-25
+ Font:BigBold
+ Contrast:true
+ Align:Center
+ Text:Music Player
+ Background@bg:
+ Width:360
+ Height:400
+ Background:panel-black
+ Children:
+ CncScrollPanel@MUSIC_LIST:
+ Id:MUSIC_LIST
+ X:15
+ Y:30
+ Width:330
+ Height:275
+ Children:
+ Container@MUSIC_TEMPLATE:
+ Id:MUSIC_TEMPLATE
+ Width:PARENT_RIGHT-27
+ Height:25
+ X:2
+ Y:0
+ Visible:false
+ Children:
+ Label@TITLE:
+ X:10
+ Id:TITLE
+ Width:PARENT_RIGHT-50
+ Height:25
+ Label@LENGTH:
+ Id:LENGTH
+ Width:50
+ X:PARENT_RIGHT-60
+ Align:Right
+ Height:25
+ Label@NO_MUSIC_LABEL:
+ Id:NO_MUSIC_LABEL
+ X:15
+ Y:147
+ Width:330
+ Height:25
+ Font:Bold
+ Align:Center
+ Visible:false
+ Text:No Music Installed
+ Container@LABEL_CONTAINER:
+ X:25
+ Y:5
+ Width:330
+ Children:
+ Label@TITLE:
+ Width:100
+ Height:25
+ Text:Track
+ Align:Center
+ Bold:True
+ Label@TYPE:
+ X:PARENT_RIGHT-85
+ Height:25
+ Width:50
+ Text:Length
+ Align:Right
+ Bold:True
+ Container@BUTTONS:
+ X:(PARENT_RIGHT-WIDTH)/2
+ Y:320
+ Width:170
+ Children:
+ CncMenuButton@BUTTON_PREV:
+ Id:BUTTON_PREV
+ Width:35
+ Height:35
+ Children:
+ Image@IMAGE_PREV:
+ Id:IMAGE_PREV
+ X:5
+ Y:5
+ Width:25
+ Height:25
+ ImageCollection:music
+ ImageName:prev
+ CncMenuButton@BUTTON_PLAY:
+ Id:BUTTON_PLAY
+ X:45
+ Width:35
+ Height:35
+ Children:
+ Image@IMAGE_PLAY:
+ Id:IMAGE_PLAY
+ X:5
+ Y:5
+ Width:25
+ Height:25
+ ImageCollection:music
+ ImageName:play
+ CncMenuButton@BUTTON_PAUSE:
+ Id:BUTTON_PAUSE
+ Visible:false
+ X:45
+ Width:35
+ Height:35
+ Children:
+ Image@IMAGE_PAUSE:
+ Id:IMAGE_PAUSE
+ X:5
+ Y:5
+ Width:25
+ Height:25
+ ImageCollection:music
+ ImageName:pause
+ CncMenuButton@BUTTON_STOP:
+ Id:BUTTON_STOP
+ X:90
+ Width:35
+ Height:35
+ Children:
+ Image@IMAGE_STOP:
+ Id:IMAGE_STOP
+ X:5
+ Y:5
+ Width:25
+ Height:25
+ ImageCollection:music
+ ImageName:stop
+ CncMenuButton@BUTTON_NEXT:
+ Id:BUTTON_NEXT
+ X:135
+ Width:35
+ Height:35
+ Children:
+ Image@IMAGE_NEXT:
+ Id:IMAGE_NEXT
+ X:5
+ Y:5
+ Width:25
+ Height:25
+ ImageCollection:music
+ ImageName:next
+ Label@TIME_LABEL:
+ Id:TIME_LABEL
+ X:(PARENT_RIGHT-WIDTH)/2
+ Y:PARENT_BOTTOM-13-HEIGHT
+ Width:140
+ Height:25
+ Align:Center
+ Font:Bold
+ CncCheckbox@SHUFFLE:
+ Id:SHUFFLE
+ X:15
+ Y:PARENT_BOTTOM-15-HEIGHT
+ Width:85
+ Height:20
+ Text:Shuffle
+ CncCheckbox@REPEAT:
+ Id:REPEAT
+ X:PARENT_RIGHT-15-WIDTH
+ Y:PARENT_BOTTOM-15-HEIGHT
+ Width:70
+ Height:20
+ Text:Loop
+ CncMenuButton@BACK_BUTTON:
+ Id:BACK_BUTTON
+ X:0
+ Y:399
+ Width:140
+ Height:35
+ Text:Back
+ CncMenuButton@INSTALL_BUTTON:
+ Id:INSTALL_BUTTON
+ X:220
+ Y:399
+ Width:140
+ Height:35
+ Text:Install Music
\ No newline at end of file
diff --git a/mods/cnc/chrome/unused/music.yaml b/mods/cnc/chrome/unused/music.yaml
deleted file mode 100644
index 8cead0b75c..0000000000
--- a/mods/cnc/chrome/unused/music.yaml
+++ /dev/null
@@ -1,161 +0,0 @@
-Background@MUSIC_MENU:
- Id:MUSIC_MENU
- Delegate:MusicPlayerDelegate
- X:(WINDOW_RIGHT - WIDTH)/2
- Y:(WINDOW_BOTTOM - HEIGHT)/2
- Width: 450
- Height: 250
- Children:
- Label@SETTINGS_LABEL_TITLE:
- Id:SETTINGS_LABEL_TITLE
- X:0
- Y:20
- Width:450
- Height:25
- Text:Music
- Align:Center
- Font:Bold
- Button@BUTTON_INSTALL:
- Id:BUTTON_INSTALL
- X:20
- Y:PARENT_BOTTOM - 45
- Width:160
- Height:25
- Text:Install Music
- Font:Bold
- Button@BUTTON_CLOSE:
- Id:BUTTON_CLOSE
- X:PARENT_RIGHT - 180
- Y:PARENT_BOTTOM - 45
- Width:160
- Height:25
- Text:Close
- Font:Bold
- Container@BUTTONS:
- X:PARENT_RIGHT - 150
- Y:50
- Children:
- Button@BUTTON_PLAY:
- Id:BUTTON_PLAY
- X:35
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_PLAY:
- Id:IMAGE_PLAY
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:play
- Button@BUTTON_PAUSE:
- Id:BUTTON_PAUSE
- Visible:false
- X:35
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_PAUSE:
- Id:IMAGE_PAUSE
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:pause
- Button@BUTTON_STOP:
- Id:BUTTON_STOP
- X:70
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_STOP:
- Id:IMAGE_STOP
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:stop
- Button@BUTTON_NEXT:
- Id:BUTTON_NEXT
- X:105
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_NEXT:
- Id:IMAGE_NEXT
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:next
- Button@BUTTON_PREV:
- Id:BUTTON_PREV
- X:0
- Y:0
- Width:25
- Height:25
- Children:
- Image@IMAGE_PREV:
- Id:IMAGE_PREV
- X:0
- Y:0
- Width:25
- Height:25
- ImageCollection:music
- ImageName:prev
- Label@TIME:
- Id:TIME
- X:PARENT_RIGHT - 150
- Y:75
- Width:140
- Height:25
- Align: Center
- ScrollPanel@MUSIC_LIST:
- Id:MUSIC_LIST
- X:10
- Y:50
- Width:280
- Height:140
- Children:
- Label@MUSIC_TEMPLATE:
- Id:MUSIC_TEMPLATE
- Width:PARENT_RIGHT-28
- Height:25
- X:2
- Y:0
- Visible:false
- Children:
- Label@TITLE:
- Id:TITLE
- X:5
- Width:PARENT_RIGHT - 10
- Height:PARENT_BOTTOM
- Align: Left
- Label@LENGTH:
- Id:LENGTH
- X:5
- Width:PARENT_RIGHT - 10
- Height:PARENT_BOTTOM
- Align: Right
- Checkbox@SHUFFLE:
- Id:SHUFFLE
- X:PARENT_RIGHT - 150
- Y:110
- Width:100
- Height:20
- Text:Shuffle
- Checkbox@REPEAT:
- Id:REPEAT
- X:PARENT_RIGHT - 150
- Y:140
- Width:100
- Height:20
- Text:Loop
\ No newline at end of file
diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml
index c773aa5c16..5174895fd1 100644
--- a/mods/cnc/mod.yaml
+++ b/mods/cnc/mod.yaml
@@ -72,6 +72,7 @@ ChromeLayout:
mods/cnc/chrome/replaybrowser.yaml
mods/cnc/chrome/ingame.yaml
mods/cnc/chrome/ingamemenu.yaml
+ mods/cnc/chrome/music.yaml
Weapons:
mods/cnc/weapons.yaml