#region license
// This file is part of Vocaluxe.
//
// Vocaluxe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Vocaluxe is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vocaluxe. If not, see .
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
using VocaluxeLib.Menu.SingNotes;
using VocaluxeLib.Menu.SongMenu;
using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
public struct SScreenInformation
{
public string ScreenName;
public int ScreenVersion;
}
[XmlType("Screen")]
public struct SThemeScreen
{
public SScreenInformation Informations;
[XmlArray("Backgrounds")] public List Backgrounds;
[XmlArray("Statics")] public List Statics;
[XmlArray("Texts")] public List Texts;
[XmlArray("Buttons")] public List Buttons;
[XmlArray("SongMenus")] public List SongMenus;
[XmlArray("Lyrics")] public List Lyrics;
[XmlArray("SelectSlides")] public List SelectSlides;
[XmlArray("SingNotes")] public List SingNotes;
[XmlArray("NameSelections")] public List NameSelections;
[XmlArray("Equalizers")] public List Equalizers;
[XmlArray("Playlists")] public List Playlists;
[XmlArray("ParticleEffects")] public List ParticleEffects;
[XmlArray("ScreenSettings")] public List ScreenSettings;
}
struct SZSort
{
public int ID;
public float Z;
}
public abstract class CMenu : CObjectInteractions, IMenu
{
public string ThemePath { get; private set; }
protected abstract int _ScreenVersion { get; }
public int PartyModeID { get; protected set; }
public string ThemeName { get; private set; }
public SThemeScreen Theme;
// ReSharper disable MemberCanBePrivate.Global
protected string[] _ThemeBackgrounds;
protected string[] _ThemeStatics;
protected string[] _ThemeTexts;
protected string[] _ThemeButtons;
protected string[] _ThemeSongMenus;
protected string[] _ThemeLyrics;
protected string[] _ThemeSelectSlides;
protected string[] _ThemeSingNotes;
protected string[] _ThemeNameSelections;
protected string[] _ThemeEqualizers;
protected string[] _ThemePlaylists;
protected string[] _ThemeParticleEffects;
protected string[] _ThemeScreenSettings;
protected readonly Dictionary _ScreenSettings = new Dictionary();
// ReSharper restore MemberCanBePrivate.Global
protected CMenu()
{
PartyModeID = -1;
}
public override void Init()
{
base.Init();
ThemeName = GetType().Name;
if (ThemeName[0] == 'C' && Char.IsUpper(ThemeName[1]))
ThemeName = ThemeName.Remove(0, 1);
_ThemeBackgrounds = null;
_ThemeStatics = null;
_ThemeTexts = null;
_ThemeButtons = null;
_ThemeSongMenus = null;
_ThemeLyrics = null;
_ThemeSelectSlides = null;
_ThemeSingNotes = null;
_ThemeNameSelections = null;
_ThemeEqualizers = null;
_ThemePlaylists = null;
_ThemeParticleEffects = null;
_ThemeScreenSettings = null;
}
#region ThemeHandler
protected override void _ClearElements()
{
base._ClearElements();
_ScreenSettings.Clear();
}
private delegate void AddElementHandler(T element, String key);
private void _LoadThemeElement(IEnumerable elements, AddElementHandler addElementHandler, CXmlReader xmlReader) where T : IThemeable
{
if (elements != null)
{
foreach (string elName in elements)
{
var element = (T)Activator.CreateInstance(typeof(T), PartyModeID);
if (element.LoadTheme("//root/" + ThemeName, elName, xmlReader))
addElementHandler(element, elName);
else
CBase.Log.LogError("Can't load " + typeof(T).Name.Substring(1) + " \"" + elName + "\" in screen " + ThemeName);
}
}
}
public virtual void LoadTheme(string xmlPath)
{
if (CBase.Config.GetLoadOldThemeFiles())
{
LoadThemeOld(xmlPath);
return;
}
ThemePath = xmlPath;
string file = Path.Combine(xmlPath, ThemeName + ".xml");
Theme.Informations = new SScreenInformation();
Theme.Backgrounds = new List();
Theme.Statics = new List();
Theme.Texts = new List();
Theme.Buttons = new List();
Theme.SongMenus = new List();
Theme.Lyrics = new List();
Theme.SelectSlides = new List();
Theme.SingNotes = new List();
Theme.NameSelections = new List();
Theme.Equalizers = new List();
Theme.Playlists = new List();
Theme.ParticleEffects = new List();
Theme.ScreenSettings = new List();
try
{
TextReader textReader = new StreamReader(file);
XmlSerializer deserializer = new XmlSerializer(typeof(SThemeScreen));
Theme = (SThemeScreen)deserializer.Deserialize(textReader);
foreach (SThemeBackground bg in Theme.Backgrounds)
_AddBackground(new CBackground(bg, PartyModeID), bg.Name);
foreach (SThemeButton bt in Theme.Buttons)
_AddButton(new CButton(bt, PartyModeID), bt.Name);
foreach (SThemeEqualizer eq in Theme.Equalizers)
_AddEqualizer(new CEqualizer(eq, PartyModeID), eq.Name);
foreach (SThemeLyrics ly in Theme.Lyrics)
_AddLyric(new CLyric(ly, PartyModeID), ly.Name);
foreach (SThemeNameSelection ns in Theme.NameSelections)
_AddNameSelection(new CNameSelection(ns, PartyModeID), ns.Name);
foreach (SThemeParticleEffect pe in Theme.ParticleEffects)
_AddParticleEffect(new CParticleEffect(pe, PartyModeID), pe.Name);
foreach (SThemePlaylist pl in Theme.Playlists)
_AddPlaylist(new CPlaylist(pl, PartyModeID), pl.Name);
foreach (SThemeScreenSetting ss in Theme.ScreenSettings)
_AddScreenSetting(new CScreenSetting(ss, PartyModeID), ss.Name);
foreach (SThemeSelectSlide sl in Theme.SelectSlides)
_AddSelectSlide(new CSelectSlide(sl, PartyModeID), sl.Name);
foreach (SThemeSingBar sb in Theme.SingNotes)
_AddSingNote(new CSingNotes(sb, PartyModeID), sb.Name);
foreach (SThemeSongMenu sm in Theme.SongMenus)
_AddSongMenu(CSongMenuFactory.CreateSongMenu(sm, PartyModeID), sm.Name);
foreach (SThemeStatic st in Theme.Statics)
_AddStatic(new CStatic(st, PartyModeID), st.Name);
foreach (SThemeText te in Theme.Texts)
_AddText(new CText(te, PartyModeID), te.Name);
if (_ScreenVersion != Theme.Informations.ScreenVersion)
{
string msg = "Can't load screen file of screen \"" + ThemeName + "\", ";
if (Theme.Informations.ScreenVersion < _ScreenVersion)
msg += "the file ist outdated! ";
else
msg += "the file is for newer program versions! ";
msg += "Current screen version is " + _ScreenVersion;
CBase.Log.LogError(msg);
}
foreach (IThemeable el in _Elements.Select(_GetElement).OfType())
el.LoadSkin();
}
catch (InvalidOperationException)
{
CBase.Log.LogError("Error while reading " + ThemeName + ".xml", true, true);
}
catch (Exception e)
{
CBase.Log.LogError(e.Message + e.StackTrace, true, true);
}
}
private void _AddScreenSetting(CScreenSetting screenSetting, string name)
{
_ScreenSettings.Add(name, screenSetting);
}
public void LoadThemeOld(string xmlPath)
{
string file = Path.Combine(xmlPath, ThemeName + ".xml");
CXmlReader xmlReader = CXmlReader.OpenFile(file);
if (xmlReader == null)
return;
bool versionCheck = _CheckVersion(_ScreenVersion, xmlReader);
if (versionCheck)
{
ThemePath = xmlPath;
_LoadThemeBasics(xmlReader);
_LoadThemeElement(_ThemeBackgrounds, _AddBackground, xmlReader);
_LoadThemeElement(_ThemeStatics, _AddStatic, xmlReader);
_LoadThemeElement(_ThemeTexts, _AddText, xmlReader);
_LoadThemeElement(_ThemeButtons, _AddButton, xmlReader);
_LoadThemeElement(_ThemeSelectSlides, _AddSelectSlide, xmlReader);
foreach (string elName in _ThemeSongMenus)
{
ISongMenu element = CSongMenuFactory.CreateSongMenu(PartyModeID);
if (element.LoadTheme("//root/" + ThemeName, elName, xmlReader))
_AddSongMenu(element, elName);
else
CBase.Log.LogError("Can't load songmenu \"" + elName + "\" in screen " + ThemeName);
}
_LoadThemeElement(_ThemeSongMenus, _AddSongMenu, xmlReader);
_LoadThemeElement(_ThemeLyrics, _AddLyric, xmlReader);
_LoadThemeElement(_ThemeSingNotes, _AddSingNote, xmlReader);
_LoadThemeElement(_ThemeNameSelections, _AddNameSelection, xmlReader);
_LoadThemeElement(_ThemeEqualizers, _AddEqualizer, xmlReader);
_LoadThemeElement(_ThemePlaylists, _AddPlaylist, xmlReader);
_LoadThemeElement(_ThemeParticleEffects, _AddParticleEffect, xmlReader);
_LoadThemeElement(_ThemeScreenSettings, _AddScreenSetting, xmlReader);
}
Theme.Informations.ScreenName = ThemeName;
Theme.Informations.ScreenVersion = _ScreenVersion;
Theme.Backgrounds = new List();
Theme.Statics = new List();
Theme.Texts = new List();
Theme.Buttons = new List();
Theme.SongMenus = new List();
Theme.Lyrics = new List();
Theme.SelectSlides = new List();
Theme.SingNotes = new List();
Theme.NameSelections = new List();
Theme.Equalizers = new List();
Theme.Playlists = new List();
Theme.ParticleEffects = new List();
Theme.ScreenSettings = new List();
}
private static void _AddThemeablesToList(ICollection themeList, IEnumerable objects) where T : IThemeable
{
themeList.Clear();
foreach (T el in objects.Where(el => el.ThemeLoaded))
themeList.Add((TT)el.GetTheme());
}
public virtual void SaveTheme()
{
if (string.IsNullOrEmpty(ThemePath))
return;
_ReadThemeSubElements();
try
{
TextWriter textWriter = new StreamWriter(Path.Combine(ThemePath, ThemeName + ".xml"));
XmlSerializer serializer = new XmlSerializer(typeof(SThemeScreen));
serializer.Serialize(textWriter, Theme);
textWriter.Close();
}
catch (Exception e)
{
CBase.Log.LogError("Error while saving theme-file: " + ThemeName + " " + e.Message, true);
}
}
private void _ReadThemeSubElements()
{
// Load changed/added theme elements into theme struct
_AddThemeablesToList(Theme.Backgrounds, _Backgrounds);
_AddThemeablesToList(Theme.Buttons, _Buttons);
_AddThemeablesToList(Theme.Equalizers, _Equalizers);
_AddThemeablesToList(Theme.Lyrics, _Lyrics);
_AddThemeablesToList(Theme.NameSelections, _NameSelections);
_AddThemeablesToList(Theme.ParticleEffects, _ParticleEffects);
_AddThemeablesToList(Theme.Playlists, _Playlists);
_AddThemeablesToList(Theme.ScreenSettings, _ScreenSettings.Values);
_AddThemeablesToList(Theme.SelectSlides, _SelectSlides);
_AddThemeablesToList(Theme.Statics, _Statics);
_AddThemeablesToList(Theme.Texts, _Texts);
_AddThemeablesToList(Theme.SongMenus, _SongMenus);
_AddThemeablesToList(Theme.SingNotes, _SingNotes);
}
public virtual void ReloadSkin()
{
foreach (IThemeable el in _Elements.Select(_GetElement).OfType())
el.ReloadSkin();
}
public virtual void UnloadSkin()
{
foreach (IThemeable el in _Elements.Select(_GetElement).OfType())
el.UnloadSkin();
}
public virtual void ReloadTheme(string xmlPath)
{
if (ThemePath == "")
return;
_ReadThemeSubElements();
UnloadSkin();
_ClearElements();
LoadTheme(xmlPath);
}
#endregion ThemeHandler
#region Create Elements
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBeProtected.Global
public CButton GetNewButton()
{
return new CButton(PartyModeID);
}
public static CButton GetNewButton(CButton button)
{
return new CButton(button);
}
public CText GetNewText()
{
return new CText(PartyModeID);
}
public static CText GetNewText(CText text)
{
return new CText(text);
}
public static CText GetNewText(float x, float y, float z, float h, float mw, EAlignment align, EStyle style, string font, SColorF col, string text)
{
return new CText(x, y, z, h, mw, align, style, font, col, text);
}
public CBackground GetNewBackground()
{
return new CBackground(PartyModeID);
}
public CStatic GetNewStatic()
{
return new CStatic(PartyModeID);
}
public static CStatic GetNewStatic(CStatic oldStatic)
{
return new CStatic(oldStatic);
}
public CStatic GetNewStatic(CTextureRef texture, SColorF color, SRectF rect)
{
return new CStatic(PartyModeID, texture, color, rect);
}
public CSelectSlide GetNewSelectSlide()
{
return new CSelectSlide(PartyModeID);
}
public static CSelectSlide GetNewSelectSlide(CSelectSlide slide)
{
return new CSelectSlide(slide);
}
public CLyric GetNewLyric()
{
return new CLyric(PartyModeID);
}
public CSingNotes GetNewSingNotes()
{
return new CSingNotes(PartyModeID);
}
public CNameSelection GetNewNameSelection()
{
return new CNameSelection(PartyModeID);
}
public CEqualizer GetNewEqualizer()
{
return new CEqualizer(PartyModeID);
}
public CPlaylist GetNewPlaylist()
{
return new CPlaylist(PartyModeID);
}
public CParticleEffect GetNewParticleEffect(int maxNumber, SColorF color, SRectF area, CTextureRef texture, float size, EParticleType type)
{
return new CParticleEffect(PartyModeID, maxNumber, color, area, texture, size, type);
}
// ReSharper restore MemberCanBeProtected.Global
// ReSharper restore UnusedMember.Global
#endregion Create Elements
public override bool HandleInputThemeEditor(SKeyEvent keyEvent)
{
if (!keyEvent.KeyPressed)
{
switch (keyEvent.Key)
{
case Keys.S:
CBase.Graphics.SaveTheme();
return true;
case Keys.R:
_ReloadThemeEditMode();
return true;
}
}
return base.HandleInputThemeEditor(keyEvent);
}
public abstract bool UpdateGame();
public virtual void ApplyVolume() {}
public virtual void OnShow()
{
_ResumeBG();
_Active = true;
}
public virtual void OnShowFinish()
{
_ResumeBG();
}
public virtual void OnClose()
{
_PauseBG();
_Active = false;
}
public virtual SRectF ScreenArea
{
get { return CBase.Settings.GetRenderRect(); }
}
public virtual EMusicType CurrentMusicType
{
get { return EMusicType.Background; }
}
protected void _ResumeBG()
{
foreach (CBackground bg in _Backgrounds)
bg.Resume();
}
protected void _PauseBG()
{
foreach (CBackground bg in _Backgrounds)
bg.Pause();
}
#region Theme Handling
private bool _CheckVersion(int reqVersion, CXmlReader xmlReader)
{
int actualVersion = 0;
xmlReader.TryGetIntValue("//root/" + ThemeName + "/ScreenVersion", ref actualVersion);
if (actualVersion == reqVersion)
return true;
string msg = "Can't load screen file of screen \"" + ThemeName + "\", ";
if (actualVersion < reqVersion)
msg += "the file ist outdated! ";
else
msg += "the file is for newer program versions! ";
msg += "Current screen version is " + reqVersion;
CBase.Log.LogError(msg);
return false;
}
private void _LoadThemeBasics(CXmlReader xmlReader)
{
// Backgrounds
var background = new CBackground(PartyModeID);
int i = 1;
while (background.LoadTheme("//root/" + ThemeName, "Background" + i, xmlReader))
{
_AddBackground(background);
background = new CBackground(PartyModeID);
i++;
}
// Statics
var stat = new CStatic(PartyModeID);
i = 1;
while (stat.LoadTheme("//root/" + ThemeName, "Static" + i, xmlReader))
{
_AddStatic(stat);
stat = new CStatic(PartyModeID);
i++;
}
// Texts
var text = new CText(PartyModeID);
i = 1;
while (text.LoadTheme("//root/" + ThemeName, "Text" + i, xmlReader))
{
_AddText(text);
text = new CText(PartyModeID);
i++;
}
// ParticleEffects
var partef = new CParticleEffect(PartyModeID);
i = 1;
while (partef.LoadTheme("//root/" + ThemeName, "ParticleEffect" + i, xmlReader))
{
_AddParticleEffect(partef);
partef = new CParticleEffect(PartyModeID);
i++;
}
}
private void _ReloadThemeEditMode()
{
CBase.Themes.Reload();
CBase.Graphics.ReloadTheme();
OnShow();
OnShowFinish();
}
#endregion Theme Handling
}
}