diff --git a/Output/Cover/Blue.xml b/Output/Cover/Blue.xml
index 9befe7d3..8afbbb3b 100644
--- a/Output/Cover/Blue.xml
+++ b/Output/Cover/Blue.xml
@@ -5,4 +5,41 @@
Blue
flokuep
+
+
+
+ Default
+
+
+ %TEXT%
+
+ Normal
+
+
+
+ 500
+
+
+
+
+ 1110.8
+
+
+
+ 24
+ 24
+
+
+ 100
+
+
+ 1111
+
+
+ EmptyCover.png
+
+ true
+
+ 0.75
+
diff --git a/Output/Fonts/Fonts.xml b/Output/Fonts/Fonts.xml
index 2bbf61c3..70102ffa 100644
--- a/Output/Fonts/Fonts.xml
+++ b/Output/Fonts/Fonts.xml
@@ -4,10 +4,12 @@
Normal
0,00
- 0,00
- 0,00
- 0,00
- 1,00
+
+ 0,00
+ 0,00
+ 0,00
+ 1,00
+
FreeSans
FreeSans.ttf
FreeSansBold.ttf
@@ -17,10 +19,12 @@
Outline
0,10
- 0,00
- 0,00
- 0,00
- 1,00
+
+ 0,00
+ 0,00
+ 0,00
+ 1,00
+
FreeSans
FreeSans.ttf
FreeSansBold.ttf
diff --git a/Output/Languages/English.xml b/Output/Languages/English.xml
index c0ece78c..6231e96b 100644
--- a/Output/Languages/English.xml
+++ b/Output/Languages/English.xml
@@ -212,8 +212,8 @@
Webcams
Webcam-Resolution
Screen adjustments
- Press CTR + ALT + SHIFT + Arrows to adjust screen
- CTR + ALT + SHIFT + 0 to reset
+ Press CTR + ALT (+ SHIFT) + Arrows|"+" to adjust screen
+ CTR + ALT + 0 to reset
Top left
Top right
Bottom left
diff --git a/Output/Languages/German.xml b/Output/Languages/German.xml
index 4ded8f3f..751bf476 100644
--- a/Output/Languages/German.xml
+++ b/Output/Languages/German.xml
@@ -211,8 +211,8 @@
Webcams
Webcam-Auflösung
Anzeigeanpassungen
- STRG + ALT + SHIFT + Pfeiltasten drücken um den Bildschirm anzupassen
- STRG + ALT + SHIFT + 0 um die Anpassungen zurückzusetzen
+ STRG + ALT (+ SHIFT) + Pfeiltasten|"+" drücken um den Bildschirm anzupassen
+ STRG + ALT + 0 um die Anpassungen zurückzusetzen
Oben links
Oben rechts
Unten links
diff --git a/PartyModes/PartyModeChallenge/CPartyScreenChallengeMain.cs b/PartyModes/PartyModeChallenge/CPartyScreenChallengeMain.cs
index 22945876..ea025b8e 100644
--- a/PartyModes/PartyModeChallenge/CPartyScreenChallengeMain.cs
+++ b/PartyModes/PartyModeChallenge/CPartyScreenChallengeMain.cs
@@ -446,7 +446,7 @@ namespace VocaluxeLib.PartyModes.Challenge
_RoundsTableScrollArea.Y = numberY;
_RoundsTableScrollArea.W = CBase.Settings.GetRenderW() - _Texts[_TextRoundNumber].X - 20;
- float delta = _Texts[_TextRoundNumber].Height;
+ float delta = _Texts[_TextRoundNumber].Rect.H;
//Update statics and texts for rounds
foreach (CRoundsTableRow roundRow in _RoundsTable)
@@ -479,7 +479,7 @@ namespace VocaluxeLib.PartyModes.Challenge
roundRow.TextScores[column].Y = numberY + delta;
roundRow.TextScores[column].MaxWidth = maxw;
}
- numberY = numberY + delta + delta;
+ numberY = numberY + 2*delta;
}
numberY = numberY + delta / 2;
}
@@ -532,7 +532,7 @@ namespace VocaluxeLib.PartyModes.Challenge
_PlayerTableScrollArea = new SRectF {X = _Texts[_TextPosition].X, Y = _Texts[_TextPosition].Y, W = _Texts[_TextGamePoints].X - _Texts[_TextPosition].X};
_PlayerTable = new List();
- float delta = _Texts[_TextPosition].Height * 1.2f;
+ float delta = _Texts[_TextPosition].Rect.H * 1.2f;
float h = 0;
diff --git a/PartyModes/PartyModeChallengeMedley/CPartyScreenChallengeMedleyMain.cs b/PartyModes/PartyModeChallengeMedley/CPartyScreenChallengeMedleyMain.cs
index 47dcb43c..0a0240f1 100644
--- a/PartyModes/PartyModeChallengeMedley/CPartyScreenChallengeMedleyMain.cs
+++ b/PartyModes/PartyModeChallengeMedley/CPartyScreenChallengeMedleyMain.cs
@@ -446,7 +446,7 @@ namespace VocaluxeLib.PartyModes.ChallengeMedley
_RoundsTableScrollArea.Y = numberY;
_RoundsTableScrollArea.W = CBase.Settings.GetRenderW() - _Texts[_TextRoundNumber].X - 20;
- float delta = _Texts[_TextRoundNumber].Height;
+ float delta = _Texts[_TextRoundNumber].Rect.H;
//Update statics and texts for rounds
foreach (CRoundsTableRow roundRow in _RoundsTable)
@@ -532,7 +532,7 @@ namespace VocaluxeLib.PartyModes.ChallengeMedley
_PlayerTableScrollArea = new SRectF {X = _Texts[_TextPosition].X, Y = _Texts[_TextPosition].Y, W = _Texts[_TextGamePoints].X - _Texts[_TextPosition].X};
_PlayerTable = new List();
- float delta = _Texts[_TextPosition].Height * 1.2f;
+ float delta = _Texts[_TextPosition].Rect.H * 1.2f;
float h = 0;
diff --git a/Vocaluxe/Base/CBackgroundMusic.cs b/Vocaluxe/Base/CBackgroundMusic.cs
index 4006f4c9..f8685ff9 100644
--- a/Vocaluxe/Base/CBackgroundMusic.cs
+++ b/Vocaluxe/Base/CBackgroundMusic.cs
@@ -52,25 +52,26 @@ namespace Vocaluxe.Base
public static bool VideoEnabled
{
get { return _PlaysPreview ? _PreviewPlayer.VideoEnabled : _SongPlayer.VideoEnabled; }
- set {
- if(_PlaysPreview)
+ set
+ {
+ if (_PlaysPreview)
_PreviewPlayer.VideoEnabled = value;
- else
+ else
_SongPlayer.VideoEnabled = value;
}
}
- public static bool CanSing
- {
- get
+ public static bool CanSing
+ {
+ get
{
if (_PlaysPreview)
return false;
+ else if (_BGMusicFiles.Contains(_CurrentPlaylistElement))
+ return false;
else
- if (_BGMusicFiles.Contains(_CurrentPlaylistElement))
- return false;
- else return true;
- }
+ return true;
+ }
}
public static bool Disabled
@@ -85,7 +86,8 @@ namespace Vocaluxe.Base
}
}
- public static bool RepeatSong {
+ public static bool RepeatSong
+ {
get { return _SongPlayer.RepeatSong; }
set { _SongPlayer.RepeatSong = value; }
}
@@ -100,13 +102,20 @@ namespace Vocaluxe.Base
get { return _SongPlayer.SongHasVideo; }
}
- public static bool IsPlaying { get { return _PlaysPreview ? _PreviewPlayer.IsPlaying : _SongPlayer.IsPlaying; } }
+ public static bool IsPlaying
+ {
+ get { return _PlaysPreview ? _PreviewPlayer.IsPlaying : _SongPlayer.IsPlaying; }
+ }
- public static bool IsPlayingPreview { get { return _PlaysPreview; } }
+ public static bool IsPlayingPreview
+ {
+ get { return _PlaysPreview; }
+ }
public static string ArtistAndTitle
{
- get {
+ get
+ {
if (_PlaysPreview)
return _PreviewPlayer.ArtistAndTitle;
else
@@ -119,7 +128,7 @@ namespace Vocaluxe.Base
get { return _PlaysPreview ? _PreviewPlayer.Length : _SongPlayer.Length; }
}
- public static CTexture Cover
+ public static CTextureRef Cover
{
get { return _PlaysPreview ? _PreviewPlayer.Cover : _SongPlayer.Cover; }
}
@@ -185,11 +194,13 @@ namespace Vocaluxe.Base
if (_PlaysPreview)
_PreviewPlayer.Play();
else if(CConfig.BackgroundMusic == EBackgroundMusicOffOn.TR_CONFIG_ON)
+ {
if (_SongPlayer.SongLoaded)
//Resume
_SongPlayer.TogglePause();
else
Next();
+ }
}
public static void Stop()
@@ -278,7 +289,7 @@ namespace Vocaluxe.Base
public static void Update()
{
- if (!IsPlaying && (!_SongPlayer.SongLoaded || !_PreviewPlayer.SongLoaded) )
+ if (!IsPlaying && (!_SongPlayer.SongLoaded || !_PreviewPlayer.SongLoaded))
return;
if (_PlaysPreview)
@@ -291,7 +302,7 @@ namespace Vocaluxe.Base
}
}
- public static CTexture GetVideoTexture()
+ public static CTextureRef GetVideoTexture()
{
return _PlaysPreview ? _PreviewPlayer.GetVideoTexture() : _SongPlayer.GetVideoTexture();
}
@@ -439,6 +450,5 @@ namespace Vocaluxe.Base
{
return _BGMusicFiles.Contains(element);
}
-
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs
index ac4cf8b9..3e201c06 100644
--- a/Vocaluxe/Base/CConfig.cs
+++ b/Vocaluxe/Base/CConfig.cs
@@ -28,6 +28,7 @@ using Vocaluxe.Lib.Sound.Record;
using Vocaluxe.Lib.Webcam;
using VocaluxeLib;
using VocaluxeLib.Profile;
+using VocaluxeLib.Xml;
namespace Vocaluxe.Base
{
@@ -72,6 +73,8 @@ namespace Vocaluxe.Base
public static int BorderTop;
public static int BorderBottom;
+ public static EGeneralAlignment ScreenAlignment = EGeneralAlignment.Middle;
+
public static EAntiAliasingModes AAMode = EAntiAliasingModes.X0;
public static EOffOn VSync = EOffOn.TR_CONFIG_ON;
@@ -226,6 +229,8 @@ namespace Vocaluxe.Base
xmlReader.TryGetIntValue("//root/Graphics/ScreenW", ref ScreenW);
xmlReader.TryGetIntValue("//root/Graphics/ScreenH", ref ScreenH);
+ xmlReader.TryGetEnumValue("//root/Graphics/ScreenAlignment", ref ScreenAlignment);
+
xmlReader.TryGetIntValue("//root/Graphics/BorderLeft", ref BorderLeft);
xmlReader.TryGetIntValue("//root/Graphics/BorderRight", ref BorderRight);
xmlReader.TryGetIntValue("//root/Graphics/BorderTop", ref BorderTop);
@@ -404,6 +409,8 @@ namespace Vocaluxe.Base
writer.WriteElementString("ScreenW", ScreenW.ToString());
writer.WriteElementString("ScreenH", ScreenH.ToString());
+ writer.WriteElementString("ScreenAlignment", Enum.GetName(typeof(EGeneralAlignment), ScreenAlignment));
+
writer.WriteComment("Screen borders (pixels)");
writer.WriteElementString("BorderLeft", BorderLeft.ToString());
writer.WriteElementString("BorderRight", BorderRight.ToString());
@@ -834,7 +841,7 @@ namespace Vocaluxe.Base
break;
case "oldtheme":
- if(value == "yes")
+ if (value == "yes")
LoadOldThemeFiles = true;
break;
}
diff --git a/Vocaluxe/Base/CCover.cs b/Vocaluxe/Base/CCover.cs
index 61692ce7..096e988f 100644
--- a/Vocaluxe/Base/CCover.cs
+++ b/Vocaluxe/Base/CCover.cs
@@ -17,25 +17,31 @@
using System;
using System.Collections.Generic;
+using System.Drawing;
using System.IO;
+using System.Threading.Tasks;
using VocaluxeLib;
using VocaluxeLib.Draw;
+using VocaluxeLib.Songs;
+using VocaluxeLib.Xml;
namespace Vocaluxe.Base
{
- struct SCoverTheme
+ struct SThemeCover
{
- public string Name;
- public string Folder;
- public string File;
+ public string Name, Folder;
+ public string FilePath;
}
static class CCover
{
- private static readonly Dictionary _Covers = new Dictionary();
- private static readonly List _CoverThemes = new List();
+ private const string _NoCoverName = "No Cover";
+ private const string _NoCoverNameAlt = "NoCover";
+ private static readonly Dictionary _Covers = new Dictionary();
+ private static readonly Dictionary _NoCoverGenerators = new Dictionary();
+ private static readonly List _CoverThemes = new List();
- public static CTexture NoCover { get; private set; }
+ public static CTextureRef NoCover { get; private set; }
public static void Init()
{
@@ -81,7 +87,7 @@ namespace Vocaluxe.Base
///
/// Returns a STexture for a given cover name. Returns "NoCover" if the cover does not exist.
///
- public static CTexture Cover(string name)
+ public static CTextureRef Cover(string name)
{
lock (_Covers)
{
@@ -92,6 +98,26 @@ namespace Vocaluxe.Base
}
}
+ public static CTextureRef GenerateCover(string text, ESongSorting sorting, CCategory category)
+ {
+ CSong firstSong = category.GetSong(0);
+ CTextureRef texture = CDraw.CopyTexture(NoCover);
+ Task.Factory.StartNew(() =>
+ {
+ ECoverGeneratorType type = _SongSortingToType(sorting);
+ Bitmap coverBmp = !_NoCoverGenerators.ContainsKey(type)?null:_NoCoverGenerators[type].GetCover(text, firstSong != null ? Path.Combine(firstSong.Folder, firstSong.CoverFileName) : null);
+ if (coverBmp == null && _NoCoverGenerators.ContainsKey(ECoverGeneratorType.Default))
+ coverBmp = _NoCoverGenerators[ECoverGeneratorType.Default].GetCover(text, firstSong != null ? Path.Combine(firstSong.Folder, firstSong.CoverFileName) : null);
+ if (coverBmp != null)
+ CDraw.EnqueueTextureUpdate(texture, coverBmp);
+ });
+ lock (_Covers)
+ {
+ _Covers.Add(text, texture);
+ }
+ return texture;
+ }
+
///
/// Returns true if a cover with the given name exists.
/// MUST HOLD _Covers lock at this point
@@ -116,24 +142,28 @@ namespace Vocaluxe.Base
{
foreach (string key in _Covers.Keys)
{
- CTexture texture = _Covers[key];
+ CTextureRef texture = _Covers[key];
CDraw.RemoveTexture(ref texture);
}
_Covers.Clear();
}
+ lock (_NoCoverGenerators)
+ {
+ _NoCoverGenerators.Clear();
+ }
}
///
/// Returns a SCoverTheme by cover-theme-name
///
- private static SCoverTheme _CoverTheme(string coverThemeName)
+ private static SThemeCover _CoverTheme(string coverThemeName)
{
for (int i = 0; i < _CoverThemes.Count; i++)
{
if (_CoverThemes[i].Name == coverThemeName)
return _CoverThemes[i];
}
- return new SCoverTheme();
+ return new SThemeCover();
}
///
@@ -152,14 +182,14 @@ namespace Vocaluxe.Base
if (xmlReader != null)
{
- var coverTheme = new SCoverTheme();
+ var coverTheme = new SThemeCover();
xmlReader.GetValue("//root/Info/Name", out coverTheme.Name, String.Empty);
xmlReader.GetValue("//root/Info/Folder", out coverTheme.Folder, String.Empty);
if (coverTheme.Folder != "" && coverTheme.Name != "")
{
- coverTheme.File = file;
+ coverTheme.FilePath = xmlReader.FilePath;
_CoverThemes.Add(coverTheme);
}
@@ -168,11 +198,11 @@ namespace Vocaluxe.Base
}
///
- /// Loads all cover which are defined in the cover config file.
+ /// Loads all covers from the theme
///
private static void _LoadCovers(string coverThemeName)
{
- SCoverTheme coverTheme = _CoverTheme(coverThemeName);
+ SThemeCover coverTheme = _CoverTheme(coverThemeName);
if (String.IsNullOrEmpty(coverTheme.Name))
return;
@@ -184,8 +214,64 @@ namespace Vocaluxe.Base
{
foreach (string file in files)
_AddCover(Path.GetFileNameWithoutExtension(file), file);
- if (_CoverExists("No Cover"))
- NoCover = _Covers["No Cover"];
+ if (_CoverExists(_NoCoverName))
+ NoCover = _Covers[_NoCoverName];
+ else if (_CoverExists(_NoCoverNameAlt))
+ NoCover = _Covers[_NoCoverNameAlt];
+ else
+ CBase.Log.LogError("Covertheme \"" + coverThemeName + "\" does not include a cover file named \"" + _NoCoverName + "\" and cannot be used!", true, true);
+ }
+ _LoadNoCoverThemes(coverTheme);
+ }
+
+ private static ECoverGeneratorType _SongSortingToType(ESongSorting sorting)
+ {
+ switch (sorting)
+ {
+ case ESongSorting.TR_CONFIG_NONE:
+ return ECoverGeneratorType.Default;
+ case ESongSorting.TR_CONFIG_FOLDER:
+ return ECoverGeneratorType.Folder;
+ case ESongSorting.TR_CONFIG_ARTIST:
+ return ECoverGeneratorType.Artist;
+ case ESongSorting.TR_CONFIG_ARTIST_LETTER:
+ case ESongSorting.TR_CONFIG_TITLE_LETTER:
+ return ECoverGeneratorType.Letter;
+ case ESongSorting.TR_CONFIG_EDITION:
+ return ECoverGeneratorType.Edition;
+ case ESongSorting.TR_CONFIG_GENRE:
+ return ECoverGeneratorType.Genre;
+ case ESongSorting.TR_CONFIG_LANGUAGE:
+ return ECoverGeneratorType.Language;
+ case ESongSorting.TR_CONFIG_YEAR:
+ return ECoverGeneratorType.Year;
+ case ESongSorting.TR_CONFIG_DECADE:
+ return ECoverGeneratorType.Decade;
+ case ESongSorting.TR_CONFIG_DATEADDED:
+ return ECoverGeneratorType.Date;
+ default:
+ throw new ArgumentOutOfRangeException("sorting");
+ }
+ }
+
+ private static void _LoadNoCoverThemes(SThemeCover coverTheme)
+ {
+ CXMLReader xmlReader = CXMLReader.OpenFile(coverTheme.FilePath);
+ string coverPath = Path.Combine(CSettings.ProgramFolder, CSettings.FolderNameCover, coverTheme.Folder);
+ lock (_NoCoverGenerators)
+ {
+ int i = 1;
+ while(xmlReader.ItemExists("//root/CoverGenerator"+i)){
+ SThemeCoverGenerator theme;
+ if (xmlReader.Read("//root/CoverGenerator" + i, out theme))
+ {
+ if (_NoCoverGenerators.ContainsKey(theme.Type))
+ continue;
+ CNoCoverGenerator el = new CNoCoverGenerator(theme, coverPath);
+ _NoCoverGenerators.Add(theme.Type, el);
+ }
+ i++;
+ }
}
}
diff --git a/Vocaluxe/Base/CCursor.cs b/Vocaluxe/Base/CCursor.cs
index 46a6e2b1..01ede32b 100644
--- a/Vocaluxe/Base/CCursor.cs
+++ b/Vocaluxe/Base/CCursor.cs
@@ -27,7 +27,7 @@ namespace Vocaluxe.Base
{
private int _MouseMoveDiffMin = CSettings.MouseMoveDiffMinActive;
private CFading _Fading;
- private CTexture _Cursor;
+ private CTextureRef _Cursor;
private Point _LastDiffPos;
private readonly Stopwatch _Movetimer = new Stopwatch();
diff --git a/Vocaluxe/Base/CDataBase.cs b/Vocaluxe/Base/CDataBase.cs
index 6297433e..a3e6397d 100644
--- a/Vocaluxe/Base/CDataBase.cs
+++ b/Vocaluxe/Base/CDataBase.cs
@@ -93,7 +93,7 @@ namespace Vocaluxe.Base
_HighscoreDB.IncreaseSongCounter(dataBaseSongID);
}
- public static bool GetCover(string fileName, ref CTexture tex, int maxSize)
+ public static bool GetCover(string fileName, ref CTextureRef tex, int maxSize)
{
return _CoverDB.GetCover(fileName, ref tex, maxSize);
}
@@ -103,7 +103,7 @@ namespace Vocaluxe.Base
_CoverDB.CommitCovers();
}
- public static bool GetCreditsRessource(string fileName, ref CTexture tex)
+ public static bool GetCreditsRessource(string fileName, ref CTextureRef tex)
{
return _ResourceDB.GetCreditsRessource(fileName, ref tex);
}
diff --git a/Vocaluxe/Base/CDraw.cs b/Vocaluxe/Base/CDraw.cs
index f109645b..526d30cc 100644
--- a/Vocaluxe/Base/CDraw.cs
+++ b/Vocaluxe/Base/CDraw.cs
@@ -20,7 +20,6 @@ using System.Drawing;
using Vocaluxe.Lib.Draw;
using VocaluxeLib;
using VocaluxeLib.Draw;
-using VocaluxeLib.Menu;
namespace Vocaluxe.Base
{
@@ -28,6 +27,10 @@ namespace Vocaluxe.Base
{
private static IDraw _Draw;
+ ///
+ /// Initializes the Driver selected in the config
+ ///
+ ///
public static bool Init()
{
if (_Draw != null)
@@ -74,12 +77,20 @@ namespace Vocaluxe.Base
return _Draw.Init();
}
+ ///
+ /// Has to be called to start rendering
+ /// Will only return if program is closed
+ /// Also inits the first screen
+ ///
public static void MainLoop()
{
CGraphics.InitFirstScreen();
_Draw.MainLoop();
}
+ ///
+ /// Unloads the current driver, e.g. to switch to another one
+ ///
public static void Unload()
{
if (_Draw != null)
@@ -89,143 +100,303 @@ namespace Vocaluxe.Base
}
}
+ ///
+ /// Gets the width of the rendering area
+ ///
+ ///
public static int GetScreenWidth()
{
return _Draw.GetScreenWidth();
}
+ ///
+ /// Gets the height of the rendering area
+ ///
+ ///
public static int GetScreenHeight()
{
return _Draw.GetScreenHeight();
}
- public static void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2)
- {
- _Draw.DrawLine(a, r, g, b, w, x1, y1, x2, y2);
- }
-
- public static void DrawRect(SColorF color, SRectF rect, float thickness)
- {
- if (thickness <= 0f)
- return;
-
- _Draw.DrawColor(color, new SRectF(rect.X - thickness / 2, rect.Y - thickness / 2, rect.W + thickness, thickness, rect.Z));
- _Draw.DrawColor(color, new SRectF(rect.X - thickness / 2, rect.Y + rect.H - thickness / 2, rect.W + thickness, thickness, rect.Z));
- _Draw.DrawColor(color, new SRectF(rect.X - thickness / 2, rect.Y - thickness / 2, thickness, rect.H + thickness, rect.Z));
- _Draw.DrawColor(color, new SRectF(rect.X + rect.W - thickness / 2, rect.Y - thickness / 2, thickness, rect.H + thickness, rect.Z));
- }
-
- public static void DrawColor(SColorF color, SRectF rect)
- {
- _Draw.DrawColor(color, rect);
- }
-
- public static void DrawColorReflection(SColorF color, SRectF rect, float space, float height)
- {
- _Draw.DrawColorReflection(color, rect, space, height);
- }
-
- public static void ClearScreen()
- {
- _Draw.ClearScreen();
- }
-
- public static CTexture CopyScreen()
- {
- return _Draw.CopyScreen();
- }
-
- public static void CopyScreen(ref CTexture texture)
- {
- _Draw.CopyScreen(ref texture);
- }
-
+ ///
+ /// Takes a screenshot and saves it to the Screenshot folder
+ ///
public static void MakeScreenShot()
{
_Draw.MakeScreenShot();
}
- public static CTexture AddTexture(Bitmap bitmap)
+ ///
+ /// Gets the current screen content as a texture
+ ///
+ ///
+ public static CTextureRef CopyScreen()
+ {
+ return _Draw.CopyScreen();
+ }
+
+ ///
+ /// Gets the current screen content updating the given texture
+ ///
+ ///
+ public static void CopyScreen(ref CTextureRef texture)
+ {
+ _Draw.CopyScreen(ref texture);
+ }
+
+ ///
+ /// Adds a texture from a Bitmap and returns a reference to it
+ /// Must be called from main thread!
+ ///
+ ///
+ /// Reference to texture
+ public static CTextureRef AddTexture(Bitmap bitmap)
{
return _Draw.AddTexture(bitmap);
}
- public static CTexture AddTexture(string texturePath)
+ ///
+ /// Adds a texture from an image file given by its file path
+ /// Must be called from main thread!
+ ///
+ ///
+ /// Reference to texture or null on error
+ public static CTextureRef AddTexture(string texturePath)
{
return _Draw.AddTexture(texturePath);
}
- public static CTexture AddTexture(int w, int h, byte[] data)
+ ///
+ /// Adds a texture from a byte array
+ /// Must be called from main thread!
+ ///
+ /// Width of the image
+ /// Height of the image
+ /// Array of 4 byte values for each pixel
+ /// Reference to texture
+ public static CTextureRef AddTexture(int w, int h, byte[] data)
{
return _Draw.AddTexture(w, h, data);
}
- public static CTexture EnqueueTexture(int w, int h, byte[] data)
+ ///
+ /// Requests aadding a texture from a byte array
+ /// Use this if you add textures from another thread or don't need it immediatelly
+ ///
+ /// Width of the image
+ /// Height of the image
+ /// Array of 4 byte values for each pixel
+ /// Reference to texture
+ public static CTextureRef EnqueueTexture(int w, int h, byte[] data)
{
return _Draw.EnqueueTexture(w, h, data);
}
- public static bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
+ ///
+ /// Requests adding a texture from a bitmap
+ /// Use this if you add textures from another thread or don't need it immediatelly
+ ///
+ /// Bitmap to add, gets disposed after adding!
+ /// Reference to texture
+ public static CTextureRef EnqueueTexture(Bitmap bmp)
{
- return _Draw.UpdateTexture(texture, w, h, data);
+ return _Draw.EnqueueTexture(bmp);
}
- public static bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data)
+ ///
+ /// Requests adding a texture from a file
+ /// Use this if you add textures from another thread or don't need it immediatelly
+ ///
+ /// Full path to the image file
+ /// Reference to texture
+ public static CTextureRef EnqueueTexture(String texturePath)
{
- return _Draw.UpdateOrAddTexture(ref texture, w, h, data);
+ return _Draw.EnqueueTexture(texturePath);
}
- public static void RemoveTexture(ref CTexture texture)
+ ///
+ /// Requests updating a texture from a bitmap
+ /// Use this if you add textures from another thread or don't need it immediatelly
+ /// Bitmap is freed after use
+ ///
+ /// Reference to the texture to update
+ ///
+ public static void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp)
{
- _Draw.RemoveTexture(ref texture);
+ _Draw.EnqueueTextureUpdate(textureRef, bmp);
}
- public static void DrawTexture(CTexture texture)
+ ///
+ /// Creates a copy of the texture
+ /// Updates to the copy do not affect the original texture
+ ///
+ /// Original texture reference
+ /// New texture reference of the copy
+ public static CTextureRef CopyTexture(CTextureRef textureRef)
{
- _Draw.DrawTexture(texture);
+ return _Draw.CopyTexture(textureRef);
}
- public static void DrawTexture(CTexture texture, SRectF rect)
+ ///
+ /// Updates a texture, filling it with the new data
+ ///
+ ///
+ /// Width of the image
+ /// Height of the image
+ /// Array of 4 byte values for each pixel
+ public static void UpdateTexture(CTextureRef textureRef, int w, int h, byte[] data)
{
- _Draw.DrawTexture(texture, rect);
+ _Draw.UpdateTexture(textureRef, w, h, data);
}
- public static void DrawTexture(CTexture texture, SRectF rect, SColorF color, bool mirrored = false)
+ ///
+ /// Updates a texture, filling it with the new data from the bitmap
+ ///
+ ///
+ ///
+ public static void UpdateTexture(CTextureRef textureRef, Bitmap bmp)
{
- _Draw.DrawTexture(texture, rect, color, mirrored);
+ _Draw.UpdateTexture(textureRef, bmp);
}
- public static void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
+ ///
+ /// Removes a texture from the VRAM and sets it to null to avoid accidential usage
+ /// Note: You can also use its Dispose method to do the same as this gets automaticly called from the Dispose method and destructor of a texture reference
+ ///
+ ///
+ public static void RemoveTexture(ref CTextureRef texture)
{
- _Draw.DrawTexture(texture, rect, color, bounds, mirrored);
- }
-
- public static void DrawTexture(CTexture texture, SRectF rect, SColorF color, float begin, float end)
- {
- _Draw.DrawTexture(texture, rect, color, begin, end);
- }
-
- public static void DrawTexture(CStatic staticBounds, CTexture texture, EAspect aspect)
- {
- if (texture == null)
- return;
-
- var bounds = new RectangleF(staticBounds.Rect.X, staticBounds.Rect.Y, staticBounds.Rect.W, staticBounds.Rect.H);
- RectangleF rect;
-
- CHelper.SetRect(bounds, out rect, texture.OrigAspect, aspect);
- DrawTexture(texture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, staticBounds.Rect.Z),
- texture.Color, new SRectF(bounds.X, bounds.Y, bounds.Width, bounds.Height, 0f));
- }
-
- public static void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float space, float height)
- {
- _Draw.DrawTextureReflection(texture, rect, color, bounds, space, height);
+ // Disposed textures call this, possibly at program end!
+ if (_Draw != null)
+ _Draw.RemoveTexture(ref texture);
}
+ ///
+ /// Returns the number of textures in the VRAM (textures might get reused so this might not be the actual number of textures in use)
+ ///
+ ///
public static int TextureCount()
{
return _Draw.GetTextureCount();
}
+
+ ///
+ /// Draws a simple (filled) rectangle with the given color
+ ///
+ ///
+ ///
+ public static void DrawRect(SColorF color, SRectF rect)
+ {
+ _Draw.DrawRect(color, rect);
+ }
+
+ ///
+ /// Draws the reflection of a filled rectangle with the given color
+ ///
+ ///
+ /// (Original) rectangle to draw the reflection for
+ /// Spacing between the rect and the reflection
+ /// Height of the reflection
+ public static void DrawRectReflection(SColorF color, SRectF rect, float space, float height)
+ {
+ _Draw.DrawRectReflection(color, rect, space, height);
+ }
+
+ ///
+ /// Draws a texture at its position and with its color
+ ///
+ /// The texture to be drawn
+ public static void DrawTexture(CTextureRef texture)
+ {
+ DrawTexture(texture, texture.Rect);
+ }
+
+ ///
+ /// Draws a texture with its color at the given position
+ ///
+ /// The texture to be drawn
+ /// A rectangle with the destination coordinates
+ public static void DrawTexture(CTextureRef textureRef, SRectF rect)
+ {
+ DrawTexture(textureRef, rect, textureRef.Color);
+ }
+
+ ///
+ /// Draws a texture at the given position with the given color
+ ///
+ ///
+ ///
+ ///
+ /// True to mirror the texture on the y axis
+ public static void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false)
+ {
+ _Draw.DrawTexture(textureRef, rect, color, mirrored);
+ }
+
+ ///
+ /// Draws a texture at the given position with the given color
+ ///
+ ///
+ ///
+ ///
+ /// Bounds to draw the texture in (rest gets cropped off)
+ /// True to mirror the texture on the y axis
+ public static void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
+ {
+ _Draw.DrawTexture(textureRef, rect, color, bounds, mirrored);
+ }
+
+ ///
+ /// Draws a part of a texture at the given position with the given color
+ ///
+ ///
+ ///
+ ///
+ /// Normalized start x-coordinate (0..1)
+ /// Normalized end x-coordinate (0..1)
+ public static void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, float begin, float end)
+ {
+ _Draw.DrawTexture(textureRef, rect, color, begin, end);
+ }
+
+ ///
+ /// Draws a texture fitting it within the given bounds with the method specified by aspect
+ ///
+ ///
+ /// Where to draw the texture
+ /// How to fit a texture in the bounds if the size differs
+ public static void DrawTexture(CTextureRef textureRef, SRectF bounds, EAspect aspect)
+ {
+ DrawTexture(textureRef, bounds, aspect, textureRef.Color);
+ }
+
+ ///
+ /// Draws a texture fitting it within the given color and bounds with the method specified by aspect
+ ///
+ ///
+ /// Where to draw the texture
+ /// How to fit a texture in the bounds if the size differs
+ /// Color to use
+ public static void DrawTexture(CTextureRef textureRef, SRectF bounds, EAspect aspect, SColorF color)
+ {
+ if (textureRef == null)
+ return;
+
+ SRectF rect = CHelper.FitInBounds(bounds, textureRef.OrigAspect, aspect);
+ DrawTexture(textureRef, rect, color);
+ }
+
+ ///
+ /// Draws the reflection of a texture at the given position and with the given color
+ ///
+ ///
+ /// (Original) rectangle to draw the reflection for
+ ///
+ /// Spacing between the rect and the reflection
+ /// Height of the reflection
+ public static void DrawTextureReflection(CTextureRef textureRef, SRectF rect, SColorF color, float space, float height)
+ {
+ _Draw.DrawTextureReflection(textureRef, rect, color, space, height);
+ }
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Base/CGraphics.cs b/Vocaluxe/Base/CGraphics.cs
index fa427bef..6ec89672 100644
--- a/Vocaluxe/Base/CGraphics.cs
+++ b/Vocaluxe/Base/CGraphics.cs
@@ -196,9 +196,6 @@ namespace Vocaluxe.Base
CController.Update();
CProfiles.Update();
- if (CConfig.CoverLoading == ECoverLoading.TR_CONFIG_COVERLOADING_DYNAMIC && _CurrentScreen != EScreens.ScreenSing)
- CSongs.LoadCover();
-
if (CSettings.ProgramState != EProgramState.EditTheme)
{
run &= _HandleInputs(keys, mouse);
@@ -362,32 +359,55 @@ namespace Vocaluxe.Base
if (!eventsAvailable)
keyEvent = inputKeyEvent;
- if (keyEvent.IsArrowKey() || keyEvent.Key == Keys.NumPad0 || keyEvent.Key == Keys.D0)
+ if (keyEvent.IsArrowKey() || keyEvent.Key == Keys.NumPad0 || keyEvent.Key == Keys.D0 || keyEvent.Key == Keys.Add)
{
_Cursor.Deactivate();
- if (keyEvent.ModAlt && keyEvent.ModCtrl && keyEvent.ModShift)
+ if (keyEvent.ModAlt && keyEvent.ModCtrl)
{
switch (keyEvent.Key)
{
- case Keys.Left:
- CConfig.BorderLeft -= 1;
- CConfig.BorderRight -= 1;
- CConfig.BorderTop -= 1;
- CConfig.BorderBottom -= 1;
- break;
case Keys.Right:
- CConfig.BorderLeft += 1;
- CConfig.BorderRight += 1;
- CConfig.BorderTop += 1;
- CConfig.BorderBottom += 1;
+ if (keyEvent.ModShift)
+ CConfig.BorderLeft++;
+ else
+ CConfig.BorderRight--;
+ break;
+ case Keys.Left:
+ if (keyEvent.ModShift)
+ CConfig.BorderLeft--;
+ else
+ CConfig.BorderRight++;
+ break;
+ case Keys.Down:
+ if (keyEvent.ModShift)
+ CConfig.BorderTop++;
+ else
+ CConfig.BorderBottom--;
+ break;
+ case Keys.Up:
+ if (keyEvent.ModShift)
+ CConfig.BorderTop--;
+ else
+ CConfig.BorderBottom++;
break;
case Keys.D0:
case Keys.NumPad0:
- CConfig.BorderLeft = 0;
- CConfig.BorderRight = 0;
- CConfig.BorderTop = 0;
- CConfig.BorderBottom = 0;
+ CConfig.BorderLeft = CConfig.BorderRight = CConfig.BorderTop = CConfig.BorderBottom = 0;
+ break;
+ case Keys.Add:
+ switch (CConfig.ScreenAlignment)
+ {
+ case EGeneralAlignment.Middle:
+ CConfig.ScreenAlignment = EGeneralAlignment.End;
+ break;
+ case EGeneralAlignment.End:
+ CConfig.ScreenAlignment = EGeneralAlignment.Start;
+ break;
+ default:
+ CConfig.ScreenAlignment = EGeneralAlignment.Middle;
+ break;
+ }
break;
}
CConfig.SaveConfig();
@@ -638,16 +658,15 @@ namespace Vocaluxe.Base
}
}
}
- CFonts.Style = EStyle.Normal;
- CFonts.SetFont("Normal");
- CFonts.Height = 25;
+ CFont font=new CFont("Normal",EStyle.Normal, 25);
SColorF gray = new SColorF(1f, 1f, 1f, 0.5f);
float y = 0;
foreach (string txt in debugOutput)
{
- RectangleF rect = new RectangleF(CSettings.RenderW - CFonts.GetTextWidth(txt), y, CFonts.GetTextWidth(txt), CFonts.GetTextHeight(txt));
- CDraw.DrawColor(gray, new SRectF(rect.X, rect.Top, rect.Width, rect.Height, CSettings.ZNear));
- CFonts.DrawText(txt, rect.X, rect.Y, CSettings.ZNear);
+ float textWidth = CFonts.GetTextWidth(txt, font);
+ RectangleF rect = new RectangleF(CSettings.RenderW - textWidth, y, textWidth, CFonts.GetTextHeight(txt,font));
+ CDraw.DrawRect(gray, new SRectF(rect.X, rect.Top, rect.Width, rect.Height, CSettings.ZNear));
+ CFonts.DrawText(txt, font, rect.X, rect.Y, CSettings.ZNear);
y += rect.Height;
}
}
diff --git a/Vocaluxe/Base/CLanguage.cs b/Vocaluxe/Base/CLanguage.cs
index fb452747..9f529b4f 100644
--- a/Vocaluxe/Base/CLanguage.cs
+++ b/Vocaluxe/Base/CLanguage.cs
@@ -20,6 +20,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using VocaluxeLib;
+using VocaluxeLib.Xml;
namespace Vocaluxe.Base
{
diff --git a/Vocaluxe/Base/CMain.cs b/Vocaluxe/Base/CMain.cs
index 2af43f68..36fa3aa5 100644
--- a/Vocaluxe/Base/CMain.cs
+++ b/Vocaluxe/Base/CMain.cs
@@ -272,12 +272,12 @@ namespace Vocaluxe.Base
return CTheme.GetSkinIndex(partyModeID);
}
- public CTexture GetSkinTexture(string textureName, int partyModeID)
+ public CTextureRef GetSkinTexture(string textureName, int partyModeID)
{
return CTheme.GetSkinTexture(textureName, partyModeID);
}
- public CTexture GetSkinVideoTexture(string videoName, int partyModeID)
+ public CTextureRef GetSkinVideoTexture(string videoName, int partyModeID)
{
return CTheme.GetSkinVideoTexture(videoName, partyModeID);
}
@@ -405,7 +405,7 @@ namespace Vocaluxe.Base
CBackgroundMusic.StopPreview();
}
- public CTexture GetVideoTexture()
+ public CTextureRef GetVideoTexture()
{
return CBackgroundMusic.GetVideoTexture();
}
@@ -413,44 +413,54 @@ namespace Vocaluxe.Base
class CBdraw : IDrawing
{
- public void DrawTexture(CTexture texture, SRectF rect)
+ public void DrawTexture(CTextureRef texture, SRectF rect)
{
CDraw.DrawTexture(texture, rect);
}
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color)
+ public void DrawTexture(CTextureRef texture, SRectF rect, SColorF color)
{
CDraw.DrawTexture(texture, rect, color);
}
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
+ public void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
{
CDraw.DrawTexture(texture, rect, color, bounds, mirrored);
}
- public void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float reflectionSpace, float reflectionHeight)
+ public void DrawTexture(CTextureRef textureRef, SRectF bounds, EAspect aspect)
{
- CDraw.DrawTextureReflection(texture, rect, color, bounds, reflectionSpace, reflectionHeight);
+ CDraw.DrawTexture(textureRef, bounds, aspect);
}
- public CTexture AddTexture(string fileName)
+ public void DrawTexture(CTextureRef textureRef, SRectF bounds, EAspect aspect, SColorF color)
+ {
+ CDraw.DrawTexture(textureRef, bounds, aspect, color);
+ }
+
+ public void DrawTextureReflection(CTextureRef texture, SRectF rect, SColorF color, float reflectionSpace, float reflectionHeight)
+ {
+ CDraw.DrawTextureReflection(texture, rect, color, reflectionSpace, reflectionHeight);
+ }
+
+ public CTextureRef AddTexture(string fileName)
{
return CDraw.AddTexture(fileName);
}
- public void RemoveTexture(ref CTexture texture)
+ public void RemoveTexture(ref CTextureRef texture)
{
CDraw.RemoveTexture(ref texture);
}
- public void DrawColor(SColorF color, SRectF rect)
+ public void DrawRect(SColorF color, SRectF rect)
{
- CDraw.DrawColor(color, rect);
+ CDraw.DrawRect(color, rect);
}
- public void DrawColorReflection(SColorF color, SRectF rect, float space, float height)
+ public void DrawRectReflection(SColorF color, SRectF rect, float space, float height)
{
- CDraw.DrawColorReflection(color, rect, space, height);
+ CDraw.DrawRectReflection(color, rect, space, height);
}
}
@@ -502,39 +512,24 @@ namespace Vocaluxe.Base
class CBfonts : IFonts
{
- public void SetFont(string fontName)
- {
- CFonts.SetFont(fontName);
- }
-
- public void SetStyle(EStyle fontStyle)
- {
- CFonts.Style = fontStyle;
- }
-
public RectangleF GetTextBounds(CText text)
{
return CFonts.GetTextBounds(text);
}
- public RectangleF GetTextBounds(CText text, float textHeight)
+ public void DrawText(string text, CFont font, float x, float y, float z, SColorF color)
{
- return CFonts.GetTextBounds(text, textHeight);
+ CFonts.DrawText(text, font, x, y, z, color);
}
- public void DrawText(string text, float textHeight, float x, float y, float z, SColorF color)
+ public void DrawTextReflection(string text, CFont font, float x, float y, float z, SColorF color, float reflectionSpace, float reflectionHeight)
{
- CFonts.DrawText(text, textHeight, x, y, z, color);
+ CFonts.DrawTextReflection(text, font, x, y, z, color, reflectionSpace, reflectionHeight);
}
- public void DrawTextReflection(string text, float textHeight, float x, float y, float z, SColorF color, float reflectionSpace, float reflectionHeight)
+ public void DrawText(string text, CFont font, float x, float y, float z, SColorF color, float begin, float end)
{
- CFonts.DrawTextReflection(text, textHeight, x, y, z, color, reflectionSpace, reflectionHeight);
- }
-
- public void DrawText(string text, float textHeight, float x, float y, float z, SColorF color, float begin, float end)
- {
- CFonts.DrawText(text, textHeight, x, y, z, color, begin, end);
+ CFonts.DrawText(text, font, x, y, z, color, begin, end);
}
}
@@ -656,7 +651,7 @@ namespace Vocaluxe.Base
return CProfiles.GetPlayerName(profileID, playerNum);
}
- public CTexture GetAvatar(int profileID)
+ public CTextureRef GetAvatar(int profileID)
{
return CProfiles.GetAvatarTextureFromProfile(profileID);
}
@@ -815,7 +810,7 @@ namespace Vocaluxe.Base
return CVideo.Skip(videoStream, startPosition, videoGap);
}
- public bool GetFrame(int videoStream, ref CTexture videoTexture, float time, out float videoTime)
+ public bool GetFrame(int videoStream, ref CTextureRef videoTexture, float time, out float videoTime)
{
return CVideo.GetFrame(videoStream, ref videoTexture, time, out videoTime);
}
@@ -896,7 +891,7 @@ namespace Vocaluxe.Base
class CBcover : ICover
{
- public CTexture GetNoCover()
+ public CTextureRef GetNoCover()
{
return CCover.NoCover;
}
@@ -904,7 +899,7 @@ namespace Vocaluxe.Base
class CBdataBase : IDataBase
{
- public bool GetCover(string fileName, ref CTexture texture, int coverSize)
+ public bool GetCover(string fileName, ref CTextureRef texture, int coverSize)
{
return CDataBase.GetCover(fileName, ref texture, coverSize);
}
diff --git a/Vocaluxe/Base/CNoCoverGenerator.cs b/Vocaluxe/Base/CNoCoverGenerator.cs
new file mode 100644
index 00000000..d92177e0
--- /dev/null
+++ b/Vocaluxe/Base/CNoCoverGenerator.cs
@@ -0,0 +1,495 @@
+#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.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Drawing.Text;
+using System.IO;
+using Vocaluxe.Base.Fonts;
+using VocaluxeLib;
+using System.Linq;
+
+namespace Vocaluxe.Base
+{
+ ///
+ /// Class that generates Covers if the right Cover is missing
+ /// Themeable via the xml of the Cover theme
+ ///
+ class CNoCoverGenerator
+ {
+ private readonly bool _Valid;
+ private readonly SThemeCoverGenerator _Theme;
+ private readonly string _Image;
+ private readonly SColorF _TextColor;
+ private readonly SColorF _BGColor;
+ private const int _LineSpace = 5;
+
+ ///
+ /// Split lines after special chars, descending priority
+ ///
+ private static readonly char[] _SplitCharPreferences = {':', '/', '-'};
+ private static readonly char[] _SplitCharAfter = {':', '/', '-', ' ', ')', '.', '*', ','};
+ private static readonly char[] _SplitCharBefore = {'('};
+
+ public CNoCoverGenerator(SThemeCoverGenerator theme, string basePath)
+ {
+ _Theme = theme;
+ _Valid = true;
+ _Valid &= _Theme.Text.Color.Get(-1, out _TextColor);
+ _Valid &= _Theme.BackgroundColor.Get(-1, out _BGColor);
+ if (_Valid)
+ {
+ _Image = Path.Combine(basePath, _Theme.Image);
+ _Valid = File.Exists(_Image);
+ }
+ }
+
+ private class CTextElement
+ {
+ public readonly string Text;
+ public float Width, Height;
+ private readonly Graphics _Graphics;
+ private readonly Font _Font;
+ private float _WidthTrimmed = -1;
+ public float WidthTrimmed
+ {
+ get
+ {
+ if (_WidthTrimmed < 0f)
+ {
+ string text = Text.TrimEnd(null);
+ _WidthTrimmed = text.Length == Text.Length ? Width : _Graphics.MeasureString(text, _Font, -1, StringFormat.GenericTypographic).Width;
+ }
+ return _WidthTrimmed;
+ }
+ }
+ public int Line;
+
+ public CTextElement(string text, Graphics g, Font font)
+ {
+ Text = text;
+ SizeF dimensions = g.MeasureString(text, font, -1, StringFormat.GenericTypographic);
+ Width = dimensions.Width;
+ Height = (dimensions.Height + font.Height) / 2;
+ _Graphics = g;
+ _Font = font;
+ }
+
+ public void AdjustSize(float factor)
+ {
+ Width *= factor;
+ _WidthTrimmed *= factor;
+ Height *= factor;
+ }
+ }
+
+ private void _DrawBackground(Graphics g, Bitmap bmpBackground, String firstCoverPath)
+ {
+ g.Clear(_BGColor.AsColor());
+
+ ImageAttributes ia = null;
+ if (_Theme.ShowFirstCover && !String.IsNullOrEmpty(firstCoverPath) && File.Exists(firstCoverPath))
+ {
+ using (Bitmap bmp2 = new Bitmap(firstCoverPath))
+ g.DrawImage(bmp2, bmpBackground.GetRect(), 0, 0, bmp2.Width, bmp2.Height, GraphicsUnit.Pixel);
+ ColorMatrix cm = new ColorMatrix {Matrix33 = _Theme.ImageAlpha};
+ ia = new ImageAttributes();
+ ia.SetColorMatrix(cm);
+ }
+ g.DrawImage(bmpBackground, bmpBackground.GetRect(), 0, 0, bmpBackground.Width, bmpBackground.Height, GraphicsUnit.Pixel, ia);
+ }
+
+ private void _DrawText(Graphics g, Size bmpSize, CFont font, List elements)
+ {
+ Font fo = CFonts.GetSystemFont(font);
+
+ float maxHeight = elements.Select(el => el.Height).Max();
+ int lineCount = elements.Last().Line + 1;
+
+ //Have to use size in em not pixels!
+ float emSize = fo.Size * fo.FontFamily.GetCellAscent(fo.Style) / fo.FontFamily.GetEmHeight(fo.Style);
+ float outlineSize = CFonts.GetOutlineSize(font) * font.Height;
+ SColorF outlineColorF = CFonts.GetOutlineColor(font);
+ outlineColorF.A = outlineColorF.A * _TextColor.A;
+
+ using (var path = new GraphicsPath())
+ using (var pen = new Pen(outlineColorF.AsColor(), outlineSize / 2))
+ {
+ pen.LineJoin = LineJoin.Round;
+ pen.Alignment = PenAlignment.Outset;
+ float top = (bmpSize.Height - _Theme.Text.Margin.Bottom - _Theme.Text.Margin.Top - maxHeight * lineCount) / 2 + _Theme.Text.Margin.Top;
+ int nextLineEl = 0;
+ for (int i = 0; i < lineCount; i++)
+ {
+ int firstEl = nextLineEl;
+ for (; nextLineEl < elements.Count; nextLineEl++)
+ {
+ if (elements[nextLineEl].Line > i)
+ break;
+ }
+
+ string line = elements.GetRange(firstEl, nextLineEl - firstEl).Aggregate("", (current, element) => current + element.Text);
+ float left;
+ if (lineCount == 1 || (i == 1 && lineCount == 3))
+ {
+ //Center Text if this is the only line or the middle line
+ float width = _GetWidth(elements, firstEl, nextLineEl - 1);
+ left = (bmpSize.Width - _Theme.Text.Margin.Left - _Theme.Text.Margin.Right - width) / 2 + _Theme.Text.Margin.Left;
+ }
+ else if (i == lineCount - 1)
+ {
+ //Place last line at right
+ float width = _GetWidth(elements, firstEl, nextLineEl - 1);
+ left = bmpSize.Width - width - _Theme.Text.Margin.Right;
+ }
+ else
+ left = _Theme.Text.Margin.Left;
+ //g.DrawString(line, fo, new SolidBrush(_TextColor.AsColor()), left, top, StringFormat.GenericTypographic);
+ path.AddString(line, fo.FontFamily, (int)fo.Style, emSize, new PointF(left, top), StringFormat.GenericTypographic);
+ top += maxHeight + _LineSpace;
+ }
+ g.DrawPath(pen, path);
+ g.FillPath(new SolidBrush(_TextColor.AsColor()), path);
+ }
+ }
+
+ public Bitmap GetCover(string text, string firstCoverPath)
+ {
+ if (!_Valid)
+ return null;
+ text = CLanguage.Translate(_Theme.Text.Text.Replace("%TEXT%", text));
+ using (Bitmap bmpImage = new Bitmap(_Image))
+ {
+ Bitmap bmp = new Bitmap(bmpImage.Width, bmpImage.Height, PixelFormat.Format32bppArgb);
+ try
+ {
+ using (Graphics g = Graphics.FromImage(bmp))
+ {
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ g.TextRenderingHint = TextRenderingHint.AntiAlias;
+
+ _DrawBackground(g, bmpImage, firstCoverPath);
+
+ if (text != "")
+ {
+ CFont font = new CFont(_Theme.Text.Font);
+ Font fo = CFonts.GetSystemFont(font);
+ IEnumerable textParts = _SplitText(text);
+ List elements = textParts.Select(line => new CTextElement(line, g, fo)).ToList();
+ float factor = _DistributeText(elements, bmp.Width, bmp.Height);
+ foreach (CTextElement element in elements)
+ element.AdjustSize(factor);
+ font.Height *= factor / (1f + CFonts.GetOutlineSize(font)); //Adjust for outline size
+ _DrawText(g, bmp.GetSize(), font, elements);
+ }
+ }
+ return bmp;
+ }
+ catch (Exception)
+ {
+ bmp.Dispose();
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Distributes the text among max. 3 lines maximizing the height of the line
+ /// Sets the Line field in the elements
+ ///
+ /// Text with set Width and Height
+ /// Image Width
+ /// Image Height
+ /// Factor for resizing the text (Maximizing this factor means maximizing the height)
+ private float _DistributeText(List elements, int width, int height)
+ {
+ int availableWidth = width - _Theme.Text.Margin.Left - _Theme.Text.Margin.Right;
+ int availableHeight = height - _Theme.Text.Margin.Top - _Theme.Text.Margin.Bottom;
+
+ float textHeight = elements.Select(el => el.Height).Max();
+
+ //Try 1 line:
+ float textWidth = _GetWidth(elements, 0);
+ int maxHeight = Math.Min(availableHeight, (int)_Theme.Text.Font.Size);
+ float factorH = maxHeight / textHeight;
+ float factorW = availableWidth / textWidth;
+ if (factorH <= factorW)
+ return factorH; //Limited by Height
+ float factor1 = factorW;
+
+ //Try 2 lines
+ if (elements.Count == 1)
+ {
+ //Only 1 element -> 1 line
+ return factor1;
+ }
+ availableWidth -= _Theme.Text.Indent;
+ maxHeight = Math.Min(availableHeight / 2 - _LineSpace, (int)_Theme.Text.Font.Size);
+ factorH = maxHeight / textHeight;
+ if (factorH <= factor1)
+ return factor1; //Cannot get any bigger with more lines
+ int splitEl = _GetSplitElement(elements, textWidth / 2);
+ Debug.Assert(splitEl >= 0 && splitEl < elements.Count - 1);
+ float width1 = _GetWidth(elements, 0, splitEl);
+ float width2 = _GetWidth(elements, splitEl + 1);
+ factorW = availableWidth / Math.Max(width1, width2);
+ if (factorH <= factorW)
+ {
+ // Assertion: factorH>factor1 (check above) && factorH<=factorW --> Min(factorH,factorW)>factor 1
+ // but for 2 lines it is limited by height
+ // --> Use 2 lines
+ _SetLine(elements, splitEl + 1, elements.Count - 1, 1);
+ return factorH;
+ }
+ // factor2 < factorH && factorH>factor1
+ float factor2 = factorW;
+
+ //Try 3 lines
+ maxHeight = Math.Min(availableHeight / 3 - 2 * _LineSpace, (int)_Theme.Text.Font.Size);
+ factorH = maxHeight / textHeight;
+ if (elements.Count == 2 || factorH <= Math.Max(factor1, factor2))
+ {
+ //Only 2 elements or cannot get any bigger
+ if (factor2 <= factor1)
+ return factor1;
+ _SetLine(elements, splitEl + 1, elements.Count - 1, 1);
+ return factor2;
+ }
+ int splitEl21 = _GetSplitElement(elements, textWidth / 3, false);
+ int splitEl22 = _GetSplitElement(elements, textWidth / 3, true, splitEl21 + 1);
+ Debug.Assert(splitEl21 >= 0 && splitEl21 < splitEl22 && splitEl22 < elements.Count - 1);
+ float width21 = _GetWidth(elements, 0, splitEl21);
+ float width22 = _GetWidth(elements, splitEl21 + 1, splitEl22);
+ float width23 = _GetWidth(elements, splitEl22 + 1);
+ factorW = availableWidth / Math.Max(Math.Max(width21, width22), width23);
+ float factor3 = Math.Min(factorH, factorW);
+ if (factor3 > Math.Max(factor1, factor2))
+ {
+ _SetLine(elements, splitEl21 + 1, splitEl22, 1);
+ _SetLine(elements, splitEl22 + 1, elements.Count - 1, 2);
+ return factor3;
+ }
+ if (factor2 > factor1)
+ {
+ _SetLine(elements, splitEl + 1, elements.Count - 1, 1);
+ return factor2;
+ }
+ return factor1;
+ }
+
+ ///
+ /// Returns the width of the elements with index from start to end of the list (inclusive) if they are put on 1 line
+ ///
+ ///
+ ///
+ ///
+ private static float _GetWidth(List list, int start)
+ {
+ return _GetWidth(list, start, list.Count - 1);
+ }
+
+ ///
+ /// Returns the width of the elements with index from start to end (inclusive) if they are put on 1 line
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static float _GetWidth(List list, int start, int end)
+ {
+ if (start < 0)
+ start = 0;
+ if (end >= list.Count)
+ end = list.Count - 1;
+ if (start > end)
+ return 0f;
+ float width = list.GetRange(start, end - start).Select(el => el.Width).Sum();
+ return width + list[end].WidthTrimmed;
+ }
+
+ private static void _SetLine(List list, int start, int end, int line)
+ {
+ for (int i = start; i <= end; i++)
+ list[i].Line = line;
+ }
+
+ ///
+ /// Find the element after which to split the line
+ ///
+ /// List with elements, width must be set
+ /// The requested line width
+ /// Split on one point or two
+ /// First element on line
+ /// Index of element AFTER which to split
+ private static int _GetSplitElement(List elements, float requestedWidth, bool singleSplit = true, int startElement = 0)
+ {
+ //Assert we have enough elements
+ Debug.Assert(singleSplit && elements.Count - startElement >= 2 || !singleSplit && elements.Count - startElement >= 3);
+ float curWidth = 0f;
+ int splitEl;
+ for (splitEl = startElement; splitEl < elements.Count; splitEl++)
+ {
+ curWidth += elements[splitEl].Width;
+ if (curWidth >= requestedWidth)
+ break;
+ }
+
+ // At this point we can either keep splitEl on this line for move it to the next line
+ // ==> line with splitEl is to long, without it is to short. so find the best option
+ // Check if line starts or ends with a long word, than put that on a single line
+ if (splitEl == startElement)
+ return splitEl;
+ // These 2 conditions also cover if the text fits on 1 line
+ if (!singleSplit && splitEl >= elements.Count - 2)
+ return elements.Count - 3; // Make sure we have 2 elements left if in multi split mode!
+ if (splitEl >= elements.Count - 1)
+ return elements.Count - 2; // Make sure we have 1 element left!
+
+ float diffWith = curWidth - requestedWidth;
+ float diffWithout = requestedWidth - (curWidth - elements[splitEl].Width);
+ if (!singleSplit)
+ {
+ // If we split in 3 lines, add the error of the next 2 lines to the current error for both cases
+ int splitEl2 = _GetSplitElement(elements, requestedWidth, true, splitEl + 1);
+ int splitEl3 = _GetSplitElement(elements, requestedWidth, true, splitEl);
+ diffWith += Math.Abs(requestedWidth - _GetWidth(elements, splitEl + 1, splitEl2)) + Math.Abs(requestedWidth - _GetWidth(elements, splitEl2 + 1));
+ diffWithout += Math.Abs(requestedWidth - _GetWidth(elements, splitEl, splitEl3)) + Math.Abs(requestedWidth - _GetWidth(elements, splitEl3 + 1));
+ }
+ float diff = diffWith - diffWithout;
+ //Differences below this value are considered acceptable
+ float equalDist = requestedWidth * 0.025f;
+ if (diff > equalDist)
+ return splitEl - 1; // width error with element is much higher than without -> put element on next line
+ if (diff < -equalDist)
+ return splitEl; // width error with element is much less than without -> keep element on line
+
+ //The real split would be somewhere in the middle of the element so we can move it to either line
+ string tmp = elements[splitEl].Text.TrimEnd(null);
+ char lastCharWith = tmp[tmp.Length - 1];
+ tmp = elements[splitEl - 1].Text.TrimEnd(null);
+ char lastCharWithout = tmp[tmp.Length - 1];
+ //Check if last chars are special chars
+ if (Char.IsLetterOrDigit(lastCharWith))
+ {
+ if (Char.IsLetterOrDigit(lastCharWithout))
+ return startElement == 0 ? splitEl : splitEl - 1; //Both are alphanumeric, favor longer first lines but shorter middle lines
+ return splitEl - 1; //Split after non-alphanumeric char
+ }
+ if (Char.IsLetterOrDigit(lastCharWithout))
+ return splitEl; //Split after non-alphanumeric char
+
+ int indexWith = Array.IndexOf(_SplitCharPreferences, lastCharWith);
+ int indexWithout = Array.IndexOf(_SplitCharPreferences, lastCharWithout);
+ if (indexWith <= indexWithout)
+ return startElement == 0 ? splitEl : splitEl - 1; //favor longer first lines but shorter middle lines
+ return splitEl - 1;
+ }
+
+ ///
+ /// Split the text in parts that can then be distributet among the lines
+ ///
+ ///
+ ///
+ private static IEnumerable _SplitText(string text)
+ {
+ Debug.Assert(!String.IsNullOrWhiteSpace(text));
+
+ text = text.Trim().TrimMultipleWs();
+ List lines = new List();
+ if (text.Length == 1)
+ {
+ lines.Add(text);
+ return lines;
+ }
+ //Split the text on non-letter chars
+ int curStart = 0;
+ for (int i = 1; i < text.Length - 1; i++)
+ {
+ if ((Array.IndexOf(_SplitCharAfter, text[i]) >= 0 && (Char.IsLetterOrDigit(text, i + 1) || Array.IndexOf(_SplitCharBefore, text[i + 1]) >= 0)) ||
+ (Char.IsLetterOrDigit(text, i) && Array.IndexOf(_SplitCharBefore, text[i + 1]) >= 0))
+ {
+ lines.Add(text.Substring(curStart, i - curStart + 1));
+ curStart = ++i;
+ }
+ }
+ //Add the rest
+ lines.Add(text.Substring(curStart));
+
+ //Check for initials (like J. R.R. Tolkien) and join them
+ curStart = -1;
+ string curText = "";
+ for (int i = 0; i < lines.Count; i++)
+ {
+ string part = lines[i].Trim();
+ if (part.Length == 2 && part[1] == '.')
+ {
+ //Initials found, continue or start new
+ if (curStart < 0)
+ curStart = i;
+ curText += lines[i];
+ }
+ else if (curStart >= 0)
+ {
+ //Initials end
+ if (curStart < i - 1)
+ {
+ //More than 1 part
+ lines[curStart] = curText;
+ lines.RemoveRange(curStart + 1, i - curStart - 1);
+ i = curStart;
+ }
+ curText = "";
+ curStart = -1;
+ }
+ }
+ //Handle last part
+ if (curStart >= 0)
+ {
+ //Initials end
+ if (curStart < lines.Count - 1)
+ {
+ //More than 1 part
+ lines[curStart] = curText;
+ lines.RemoveRange(curStart + 1, lines.Count - curStart - 1);
+ }
+ }
+
+ // Remove single char lines
+ for (int i = 0; i < lines.Count; i++)
+ {
+ string part = lines[i];
+ if (part.Trim().Length == 1)
+ {
+ lines.RemoveAt(i);
+ if (i == 0)
+ lines[0] = part + lines[0];
+ else
+ {
+ lines[i - 1] += part;
+ i--;
+ }
+ }
+ }
+ return lines;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Vocaluxe/Base/CParty.cs b/Vocaluxe/Base/CParty.cs
index 469e8af9..87607df9 100644
--- a/Vocaluxe/Base/CParty.cs
+++ b/Vocaluxe/Base/CParty.cs
@@ -23,6 +23,7 @@ using System.Reflection;
using VocaluxeLib;
using VocaluxeLib.Menu;
using VocaluxeLib.PartyModes;
+using VocaluxeLib.Xml;
namespace Vocaluxe.Base
{
@@ -99,7 +100,6 @@ namespace Vocaluxe.Base
pair.Value.PartyMode.SaveScreens();
}
-
public static List GetPartyModeInfos()
{
var infos = new List();
diff --git a/Vocaluxe/Base/CPlaylistElement.cs b/Vocaluxe/Base/CPlaylistElement.cs
index 3b6588de..eec209c1 100644
--- a/Vocaluxe/Base/CPlaylistElement.cs
+++ b/Vocaluxe/Base/CPlaylistElement.cs
@@ -61,7 +61,7 @@ namespace Vocaluxe.Base
get { return _Song != null ? _Song.Finish : 0f; }
}
- public CTexture Cover
+ public CTextureRef Cover
{
get { return _Song != null ? _Song.CoverTextureSmall : CCover.NoCover; }
}
diff --git a/Vocaluxe/Base/CProfiles.cs b/Vocaluxe/Base/CProfiles.cs
index 5c05719f..8cc7d8b5 100644
--- a/Vocaluxe/Base/CProfiles.cs
+++ b/Vocaluxe/Base/CProfiles.cs
@@ -504,7 +504,7 @@ namespace Vocaluxe.Base
#endregion profile properties
#region avatar texture
- public static CTexture GetAvatarTexture(int avatarID)
+ public static CTextureRef GetAvatarTexture(int avatarID)
{
if (!IsAvatarIDValid(avatarID))
return null;
@@ -512,7 +512,7 @@ namespace Vocaluxe.Base
return _Avatars[avatarID].Texture;
}
- public static CTexture GetAvatarTextureFromProfile(int profileID)
+ public static CTextureRef GetAvatarTextureFromProfile(int profileID)
{
if (!IsProfileIDValid(profileID) || _Profiles[profileID].Avatar == null)
return null;
diff --git a/Vocaluxe/Base/CSongCategorizer.cs b/Vocaluxe/Base/CSongCategorizer.cs
index 4c16bf3a..7104c795 100644
--- a/Vocaluxe/Base/CSongCategorizer.cs
+++ b/Vocaluxe/Base/CSongCategorizer.cs
@@ -178,7 +178,11 @@ namespace Vocaluxe.Base
}
foreach (CCategory cat in _Categories)
+ {
cat.CoverTextureSmall = CCover.Cover(cat.Name);
+ if (cat.CoverTextureSmall == CCover.NoCover)
+ cat.CoverTextureSmall = CCover.GenerateCover(cat.Name, CSongs.Sorter.SongSorting, cat);
+ }
_Changed = false;
}
}
diff --git a/Vocaluxe/Base/CSongs.cs b/Vocaluxe/Base/CSongs.cs
index 2bf74681..2216f63b 100644
--- a/Vocaluxe/Base/CSongs.cs
+++ b/Vocaluxe/Base/CSongs.cs
@@ -21,6 +21,7 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.IO;
+using System.Threading.Tasks;
using VocaluxeLib;
using VocaluxeLib.Songs;
@@ -134,23 +135,13 @@ namespace Vocaluxe.Base
Category--;
}
- public static int GetNextSongWithoutCover(ref CSong song)
+ private static int _NumSongsWithCoverLoaded;
+ public static int NumSongsWithCoverLoaded
{
- if (!SongsLoaded)
- return -1;
-
- if (NumSongsWithCoverLoaded < _Songs.Count)
- {
- song = _Songs[NumSongsWithCoverLoaded];
- NumSongsWithCoverLoaded++;
- return NumSongsWithCoverLoaded;
- }
-
- return -2;
+ get { return _NumSongsWithCoverLoaded; }
+ private set { _NumSongsWithCoverLoaded = value; }
}
- public static int NumSongsWithCoverLoaded { get; private set; }
-
public static string GetCurrentCategoryName()
{
return _IsCatIndexValid(_CatIndex) ? Categories[_CatIndex].Name : "";
@@ -371,59 +362,50 @@ namespace Vocaluxe.Base
Category = -1;
SongsLoaded = true;
- if (CConfig.CoverLoading == ECoverLoading.TR_CONFIG_COVERLOADING_ATSTART)
+ switch (CConfig.CoverLoading)
{
- CLog.StartBenchmark("Load Covers/Notes");
- _LoadCover();
- CLog.StopBenchmark("Load Covers/Notes");
+ case ECoverLoading.TR_CONFIG_COVERLOADING_ATSTART:
+ _LoadCovers();
+ break;
+ case ECoverLoading.TR_CONFIG_COVERLOADING_DYNAMIC:
+ _LoadCoversAsync();
+ break;
}
- CLog.StopBenchmark("Load Songs ");
+ CLog.StopBenchmark("Load Songs");
}
- public static void LoadCover()
+ private static void _LoadCoversAsync()
{
- if (CConfig.Renderer == ERenderer.TR_CONFIG_SOFTWARE)
- return; //should be removed as soon as the other renderer are ready for queue
-
if (!SongsLoaded || CoverLoaded)
return;
if (_CoverLoaderThread != null)
return;
- _CoverLoaderThread = new Thread(_LoadCover) {Name = "CoverLoader", Priority = ThreadPriority.BelowNormal, IsBackground = true};
+ _CoverLoaderThread = new Thread(_LoadCovers) {Name = "CoverLoader", Priority = ThreadPriority.BelowNormal, IsBackground = true};
_CoverLoaderThread.Start();
-
- /*
- if (_CoverLoadTimer.ElapsedMilliseconds >= WaitTime)
- {
- for (int i = 0; i < NumLoads; i++)
- {
- CSong song = null;
- int n = GetNextSongWithoutCover(ref song);
-
- if (n < 0)
- return;
-
- song.LoadSmallCover();
-
- if (n == NumAllSongs)
- CDataBase.CommitCovers();
- }
- _CoverLoadTimer.Reset();
- _CoverLoadTimer.Start();
- }
- * */
}
- private static void _LoadCover()
+ private static void _LoadCovers()
{
+ CLog.StartBenchmark("Load Covers");
+ int songCount = _Songs.Count;
+ AutoResetEvent ev = new AutoResetEvent(songCount == 0);
+
+ NumSongsWithCoverLoaded = 0;
foreach (CSong song in _Songs)
{
- song.LoadSmallCover();
- NumSongsWithCoverLoaded++;
+ CSong tmp = song;
+ Task.Factory.StartNew(() =>
+ {
+ tmp.LoadSmallCover();
+ if (Interlocked.Increment(ref _NumSongsWithCoverLoaded) >= songCount)
+ ev.Set();
+ });
}
+ ev.WaitOne();
_CoverLoaded = true;
CDataBase.CommitCovers();
+ CLog.StopBenchmark("Load Covers");
}
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Base/CTheme.cs b/Vocaluxe/Base/CTheme.cs
index 520353a4..b66796f1 100644
--- a/Vocaluxe/Base/CTheme.cs
+++ b/Vocaluxe/Base/CTheme.cs
@@ -23,6 +23,7 @@ using System.Xml;
using Vocaluxe.Base.Fonts;
using VocaluxeLib;
using VocaluxeLib.Draw;
+using VocaluxeLib.Xml;
namespace Vocaluxe.Base
{
@@ -44,7 +45,7 @@ namespace Vocaluxe.Base
class CSkinElement
{
public string Value;
- public CTexture Texture;
+ public CTextureRef Texture;
}
class CVideoSkinElement : CSkinElement
@@ -266,7 +267,7 @@ namespace Vocaluxe.Base
{
CFonts.LoadThemeFonts(
_Themes[themeIndex].Name,
- Path.Combine(Path.Combine(_Themes[themeIndex].Path, _Themes[themeIndex].SkinFolder), CSettings.FolderNameThemeFonts),
+ Path.Combine(_Themes[themeIndex].Path, _Themes[themeIndex].SkinFolder, CSettings.FolderNameThemeFonts),
xmlReader);
}
else
@@ -554,7 +555,7 @@ namespace Vocaluxe.Base
return path;
}
- public static CTexture GetSkinTexture(string textureName, int partyModeID)
+ public static CTextureRef GetSkinTexture(string textureName, int partyModeID)
{
int skinIndex = GetSkinIndex(partyModeID);
CSkinElement sk;
@@ -597,7 +598,7 @@ namespace Vocaluxe.Base
return null;
}
- public static CTexture GetSkinVideoTexture(string videoName, int partyModeID)
+ public static CTextureRef GetSkinVideoTexture(string videoName, int partyModeID)
{
CVideoSkinElement sk = GetSkinVideo(videoName, partyModeID);
if (sk == null)
diff --git a/Vocaluxe/Base/CVideo.cs b/Vocaluxe/Base/CVideo.cs
index 3d57cbd3..9b127eae 100644
--- a/Vocaluxe/Base/CVideo.cs
+++ b/Vocaluxe/Base/CVideo.cs
@@ -75,7 +75,7 @@ namespace Vocaluxe.Base
return _VideoDecoder.GetLength(streamID);
}
- public static bool GetFrame(int streamID, ref CTexture frame, float time, out float videoTime)
+ public static bool GetFrame(int streamID, ref CTextureRef frame, float time, out float videoTime)
{
return _VideoDecoder.GetFrame(streamID, ref frame, time, out videoTime);
}
diff --git a/Vocaluxe/Base/CVideoPlayer.cs b/Vocaluxe/Base/CVideoPlayer.cs
index 8dd47d4b..0838ae7c 100644
--- a/Vocaluxe/Base/CVideoPlayer.cs
+++ b/Vocaluxe/Base/CVideoPlayer.cs
@@ -7,7 +7,7 @@ namespace Vocaluxe.Base
{
class CVideoPlayer
{
- private CTexture _VideoTexture;
+ private CTextureRef _VideoTexture;
private int _VideoStream;
private readonly Stopwatch _VideoTimer = new Stopwatch();
private bool _Finished;
@@ -62,11 +62,8 @@ namespace Vocaluxe.Base
}
if (_VideoTexture == null)
return;
- var bounds = new RectangleF(0f, 0f, CSettings.RenderW, CSettings.RenderH);
- RectangleF rect;
- CHelper.SetRect(bounds, out rect, _VideoTexture.OrigAspect, EAspect.Crop);
- CDraw.DrawTexture(_VideoTexture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, CSettings.ZFar / 4));
+ CDraw.DrawTexture(_VideoTexture, new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, CSettings.ZFar / 4), EAspect.Crop);
}
public void PreLoad()
diff --git a/Vocaluxe/Base/CWebcam.cs b/Vocaluxe/Base/CWebcam.cs
index af66025a..980c6f58 100644
--- a/Vocaluxe/Base/CWebcam.cs
+++ b/Vocaluxe/Base/CWebcam.cs
@@ -57,7 +57,7 @@ namespace Vocaluxe.Base
_Webcam = null;
}
- public static bool GetFrame(ref CTexture tex)
+ public static bool GetFrame(ref CTextureRef tex)
{
return _Webcam != null && _Webcam.GetFrame(ref tex);
}
diff --git a/Vocaluxe/Base/Fonts/CFont.cs b/Vocaluxe/Base/Fonts/CFontStyle.cs
similarity index 51%
rename from Vocaluxe/Base/Fonts/CFont.cs
rename to Vocaluxe/Base/Fonts/CFontStyle.cs
index e1408b72..a71c949f 100644
--- a/Vocaluxe/Base/Fonts/CFont.cs
+++ b/Vocaluxe/Base/Fonts/CFontStyle.cs
@@ -24,48 +24,64 @@ using VocaluxeLib.Draw;
namespace Vocaluxe.Base.Fonts
{
- class CFont : IDisposable
+ class CFontStyle : IDisposable
{
- private readonly Dictionary _Glyphs;
+ private readonly string _FilePath;
+ private readonly EStyle _Style;
+ public readonly float Outline; //0..1, 0=not outline 1=100% outline
+ public readonly SColorF OutlineColor;
+ private readonly float _MaxGlyphHeight;
+ private readonly Dictionary _Glyphs = new Dictionary();
private PrivateFontCollection _Fonts;
private FontFamily _Family;
- private readonly float _MaxGlyphHeight;
- private readonly string _FilePath;
-
- private bool _Disposed;
-
- public CFont(string file)
+ public CFontStyle(string file, EStyle style, float outline, SColorF outlineColor)
{
_FilePath = file;
-
- _Glyphs = new Dictionary();
+ _Style = style;
+ Outline = outline;
+ OutlineColor = outlineColor;
switch (CConfig.TextureQuality)
{
case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
- _MaxGlyphHeight = 25f;
+ _MaxGlyphHeight = 20f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
- _MaxGlyphHeight = 50f;
+ _MaxGlyphHeight = 40f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
- _MaxGlyphHeight = 100f;
+ _MaxGlyphHeight = 60f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
- _MaxGlyphHeight = 200f;
+ _MaxGlyphHeight = 80f;
break;
case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
- _MaxGlyphHeight = 400f;
- break;
- default:
_MaxGlyphHeight = 100f;
break;
+ default:
+ _MaxGlyphHeight = 60f;
+ break;
}
- _MaxGlyphHeight = 50;
}
- public Font GetFont()
+ private FontStyle _GetSystemFontStyle()
+ {
+ switch (_Style)
+ {
+ case EStyle.Normal:
+ return FontStyle.Regular;
+ case EStyle.Italic:
+ return FontStyle.Italic;
+ case EStyle.Bold:
+ return FontStyle.Bold;
+ case EStyle.BoldItalic:
+ return FontStyle.Bold | FontStyle.Italic;
+ }
+ throw new ArgumentException("Invalid style: " + _Style);
+ }
+
+ public Font GetSystemFont(float height)
{
if (_Fonts == null)
{
@@ -80,100 +96,83 @@ namespace Vocaluxe.Base.Fonts
CLog.LogError("Error opening font file " + _FilePath + ": " + e.Message);
}
}
- return new Font(_Family, CFonts.Height, CFonts.GetFontStyle(), GraphicsUnit.Pixel);
+ return new Font(_Family, height, _GetSystemFontStyle(), GraphicsUnit.Pixel);
}
- public void DrawGlyph(char chr, float x, float y, float z, SColorF color)
+ public void DrawGlyph(char chr, float fontHeight, float x, float y, float z, SColorF color)
{
- CTexture texture;
+ CTextureRef texture;
SRectF rect;
- GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect);
+ GetOrAddGlyph(chr, fontHeight).GetTextureAndRect(fontHeight, x, y, z, out texture, out rect);
CDraw.DrawTexture(texture, rect, color);
}
- public void DrawGlyph(char chr, float x, float y, float z, SColorF color, float begin, float end)
+ public void DrawGlyph(char chr, float fontHeight, float x, float y, float z, SColorF color, float begin, float end)
{
- CTexture texture;
+ CTextureRef texture;
SRectF rect;
- GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect);
+ GetOrAddGlyph(chr, fontHeight).GetTextureAndRect(fontHeight, x, y, z, out texture, out rect);
CDraw.DrawTexture(texture, rect, color, begin, end);
}
- public void DrawGlyphReflection(char chr, float x, float y, float z, SColorF color, float rspace, float rheight)
+ public void DrawGlyphReflection(char chr, float fontHeight, float x, float y, float z, SColorF color, float rspace, float rheight)
{
- CTexture texture;
+ CTextureRef texture;
SRectF rect;
- GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect);
- CDraw.DrawTextureReflection(texture, rect, color, rect, rspace, rheight);
+ GetOrAddGlyph(chr, fontHeight).GetTextureAndRect(fontHeight, x, y, z, out texture, out rect);
+ CDraw.DrawTextureReflection(texture, rect, color, rspace, rheight);
}
- public float GetWidth(char chr)
+ public float GetWidth(char chr, float height)
{
- return GetOrAddGlyph(chr).Width;
+ return GetOrAddGlyph(chr, height).GetWidth(height);
}
- public float GetHeight(char chr)
+ public float GetHeight(char chr, float height)
{
- return GetOrAddGlyph(chr).Height;
+ return GetOrAddGlyph(chr, height).GetHeight(height);
}
- public CGlyph GetOrAddGlyph(char chr)
+ public CGlyph GetOrAddGlyph(char chr, float height)
{
CGlyph glyph;
if (!_Glyphs.TryGetValue(chr, out glyph))
{
- glyph = new CGlyph(chr, _MaxGlyphHeight);
+ float maxHeight = (height < 0 || _MaxGlyphHeight + 50 >= height) ? _MaxGlyphHeight : (float)Math.Round(height / 50) * 50;
+ glyph = new CGlyph(chr, this, maxHeight);
_Glyphs.Add(chr, glyph);
}
- if (glyph.MaxHeight + 50 < CFonts.Height)
+ if (glyph.MaxHeight + 50 < height)
{
glyph.UnloadTexture();
- glyph = new CGlyph(chr, (float)Math.Round(CFonts.Height / 50) * 50);
+ glyph = new CGlyph(chr, this, (float)Math.Round(height / 50) * 50);
_Glyphs[chr] = glyph;
}
return glyph;
}
- public void UnloadGlyphs()
+ private void _UnloadGlyphs()
{
foreach (CGlyph glyph in _Glyphs.Values)
glyph.UnloadTexture();
_Glyphs.Clear();
}
+ private bool _Disposed;
+
public void Dispose()
{
if (!_Disposed)
{
if (_Fonts != null)
+ {
_Fonts.Dispose();
- UnloadGlyphs();
+ _Fonts = null;
+ }
+ _UnloadGlyphs();
_Disposed = true;
}
GC.SuppressFinalize(this);
}
}
-
- struct SFont
- {
- public string Name;
-
- public bool IsThemeFont;
- public int PartyModeID;
- public string ThemeName;
-
- public string Folder;
- public string FileNormal;
- public string FileItalic;
- public string FileBold;
- public string FileBoldItalic;
-
- public float Outline; //0..1, 0=not outline 1=100% outline
- public SColorF OutlineColor;
-
- public CFont Normal;
- public CFont Italic;
- public CFont Bold;
- public CFont BoldItalic;
- }
}
\ No newline at end of file
diff --git a/Vocaluxe/Base/Fonts/CFonts.cs b/Vocaluxe/Base/Fonts/CFonts.cs
index 1fa9ee31..bdcdefbe 100644
--- a/Vocaluxe/Base/Fonts/CFonts.cs
+++ b/Vocaluxe/Base/Fonts/CFonts.cs
@@ -15,216 +15,166 @@
// along with Vocaluxe. If not, see .
#endregion
+using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml;
using VocaluxeLib;
using VocaluxeLib.Menu;
+using VocaluxeLib.Xml;
namespace Vocaluxe.Base.Fonts
{
+ ///
+ /// Struct used for describing a font family (a type of text with 4 different styles)
+ ///
+ struct SFontFamily
+ {
+ public string Name;
+
+ public int PartyModeID;
+ public string ThemeName;
+ public string Folder;
+
+ public string FileNormal;
+ public string FileItalic;
+ public string FileBold;
+ public string FileBoldItalic;
+
+ public float Outline; //0..1, 0=not outline 1=100% outline
+ public SColorF OutlineColor;
+
+ public CFontStyle Normal;
+ public CFontStyle Italic;
+ public CFontStyle Bold;
+ public CFontStyle BoldItalic;
+
+ public void Dispose()
+ {
+ Normal.Dispose();
+ Italic.Dispose();
+ Bold.Dispose();
+ BoldItalic.Dispose();
+ }
+ }
+
static class CFonts
{
- private static readonly List _Fonts = new List();
- private static int _CurrentFont;
- private static float _Height = 1f;
+ private static bool _IsInitialized;
+ private static readonly List _FontFamilies = new List();
+ private static readonly List _LoggedMissingFonts = new List();
- // ReSharper disable MemberCanBePrivate.Global
public static int PartyModeID { get; set; }
- // ReSharper restore MemberCanBePrivate.Global
- public static EStyle Style = EStyle.Normal;
-
- public static float Height
+ public static bool Init()
{
- get { return _Height; }
- set { _Height = value < 0f ? 0f : value; }
- }
-
- public static float Outline
- {
- get { return _Fonts[_CurrentFont].Outline; }
- }
-
- public static SColorF OutlineColor
- {
- get { return _Fonts[_CurrentFont].OutlineColor; }
- }
-
- public static void Init()
- {
- _CurrentFont = 0;
+ if (_IsInitialized)
+ return false;
PartyModeID = -1;
- _BuildFonts();
+ return _LoadDefaultFonts();
}
- private static void _BuildFonts()
+ public static void Close()
{
- foreach (SFont font in _Fonts)
- {
- font.Normal.Dispose();
- font.Bold.Dispose();
- font.Italic.Dispose();
- font.BoldItalic.Dispose();
- }
- _Fonts.Clear();
- _CurrentFont = 0;
-
- _LoadFontList();
- }
-
- public static Font GetFont()
- {
- return _GetCurrentFont().GetFont();
- }
-
- private static CFont _GetCurrentFont()
- {
- switch (Style)
- {
- case EStyle.Normal:
- return _Fonts[_CurrentFont].Normal;
- case EStyle.Italic:
- return _Fonts[_CurrentFont].Italic;
- case EStyle.Bold:
- return _Fonts[_CurrentFont].Bold;
- case EStyle.BoldItalic:
- return _Fonts[_CurrentFont].BoldItalic;
- }
- //Just in case...
- return _Fonts[_CurrentFont].Normal;
+ foreach (SFontFamily font in _FontFamilies)
+ font.Dispose();
+ _FontFamilies.Clear();
+ _IsInitialized = false;
}
#region DrawText
- public static void DrawText(string text, int x, int y, int h)
+ ///
+ /// Draws a black text
+ ///
+ /// The text to be drawn
+ /// The texts font
+ /// The texts x-position
+ /// The texts y-position
+ /// The texts z-position
+ public static void DrawText(string text, CFont font, float x, float y, float z)
{
- DrawText(text, h, x, y, 0f, new SColorF(0f, 0f, 0f, 1f));
- }
-
- public static void DrawText(string text, float x, float y, float z)
- {
- DrawText(text, Height, x, y, z, new SColorF(0f, 0f, 0f, 1f));
+ DrawText(text, font, x, y, z, new SColorF(0f, 0f, 0f, 1f));
}
///
- /// Draws a text string
+ /// Draws a text
///
/// The text to be drawn
- /// The text's x-position
- /// The text's y-position
- /// The text's height
- /// The text's z-position
+ /// The texts font
+ /// The texts x-position
+ /// The texts y-position
+ /// The texts z-position
/// The text color
- public static void DrawText(string text, float h, float x, float y, float z, SColorF color)
+ public static void DrawText(string text, CFont font, float x, float y, float z, SColorF color)
{
- if (h <= 0f)
+ if (font.Height <= 0f || text == "")
return;
- if (text == "")
- return;
-
- Height = h;
- CFont font = _GetCurrentFont();
+ CFontStyle fontStyle = _GetFontStyle(font);
float dx = x;
foreach (char chr in text)
{
- font.DrawGlyph(chr, dx, y, z, color);
- dx += font.GetWidth(chr);
+ fontStyle.DrawGlyph(chr, font.Height, dx, y, z, color);
+ dx += fontStyle.GetWidth(chr, font.Height);
}
}
- public static void DrawTextReflection(string text, float h, float x, float y, float z, SColorF color, float rspace, float rheight)
+ public static void DrawTextReflection(string text, CFont font, float x, float y, float z, SColorF color, float rspace, float rheight)
{
- if (h <= 0f)
+ if (font.Height <= 0f || text == "")
return;
- if (text == "")
- return;
-
- Height = h;
- CFont font = _GetCurrentFont();
+ CFontStyle fontStyle = _GetFontStyle(font);
float dx = x;
foreach (char chr in text)
{
- font.DrawGlyphReflection(chr, dx, y, z, color, rspace, rheight);
- dx += font.GetWidth(chr);
+ fontStyle.DrawGlyphReflection(chr, font.Height, dx, y, z, color, rspace, rheight);
+ dx += fontStyle.GetWidth(chr, font.Height);
}
}
- public static void DrawText(string text, float h, float x, float y, float z, SColorF color, float begin, float end)
+ public static void DrawText(string text, CFont font, float x, float y, float z, SColorF color, float begin, float end)
{
- if (h <= 0f)
+ if (font.Height <= 0f || text == "")
return;
- if (text == "")
- return;
-
- Height = h;
-
- float dx = x;
- float w = GetTextWidth(text);
+ float w = GetTextWidth(text, font);
if (w <= 0f)
return;
- float x1 = x + w * begin;
- float x2 = x + w * end;
+ float xStart = x + w * begin;
+ float xEnd = x + w * end;
+ float xCur = x;
- CFont font = _GetCurrentFont();
+ CFontStyle fontStyle = _GetFontStyle(font);
foreach (char chr in text)
{
- float w2 = font.GetWidth(chr);
- float b = (x1 - dx) / w2;
+ float w2 = fontStyle.GetWidth(chr, font.Height);
+ float b = (xStart - xCur) / w2;
if (b < 1f)
{
if (b < 0f)
b = 0f;
- float e = (x2 - dx) / w2;
+ float e = (xEnd - xCur) / w2;
if (e > 0f)
{
if (e > 1f)
e = 1f;
- font.DrawGlyph(chr, dx, y, z, color, b, e);
+ fontStyle.DrawGlyph(chr, font.Height, xCur, y, z, color, b, e);
}
}
- dx += w2;
+ xCur += w2;
}
}
#endregion DrawText
- public static FontStyle GetFontStyle()
- {
- switch (Style)
- {
- case EStyle.Normal:
- return FontStyle.Regular;
- case EStyle.Italic:
- return FontStyle.Italic;
- case EStyle.Bold:
- return FontStyle.Bold;
- case EStyle.BoldItalic:
- return FontStyle.Bold | FontStyle.Italic;
- default:
- return FontStyle.Regular;
- }
- }
-
- public static void SetFont(string fontName)
- {
- int index = _GetPartyFontIndex(PartyModeID, fontName);
- if (index < 0)
- index = _GetThemeFontIndex(CConfig.Theme, fontName);
- if (index < 0)
- index = _GetFontIndex(fontName);
- if (index >= 0)
- _CurrentFont = index;
- }
-
///
/// Calculates the bounds for a CText object
///
@@ -232,94 +182,172 @@ namespace Vocaluxe.Base.Fonts
/// RectangleF object containing the bounds
public static RectangleF GetTextBounds(CText text)
{
- return GetTextBounds(text, text.Height);
+ return new RectangleF(text.X, text.Y, GetTextWidth(text.TranslatedText, text.Font), GetTextHeight(text.TranslatedText, text.Font));
+ }
+
+ public static Font GetSystemFont(CFont font)
+ {
+ return _GetFontStyle(font).GetSystemFont(font.Height);
+ }
+
+ public static float GetOutlineSize(CFont font)
+ {
+ return _FontFamilies[_GetFontIndex(font.Name)].Outline;
+ }
+
+ public static SColorF GetOutlineColor(CFont font)
+ {
+ return _FontFamilies[_GetFontIndex(font.Name)].OutlineColor;
+ }
+
+ private static CFontStyle _GetFontStyle(CFont font)
+ {
+ int index = _GetFontIndex(font.Name);
+
+ switch (font.Style)
+ {
+ case EStyle.Normal:
+ return _FontFamilies[index].Normal;
+ case EStyle.Italic:
+ return _FontFamilies[index].Italic;
+ case EStyle.Bold:
+ return _FontFamilies[index].Bold;
+ case EStyle.BoldItalic:
+ return _FontFamilies[index].BoldItalic;
+ }
+ throw new ArgumentException("Invalid Style: " + font.Style);
+ }
+
+ public static float GetTextWidth(string text, CFont font)
+ {
+ CFontStyle fontStyle = _GetFontStyle(font);
+ return text.Sum(chr => fontStyle.GetWidth(chr, font.Height));
+ }
+
+ public static float GetTextHeight(string text, CFont font)
+ {
+ CFontStyle fontStyle = _GetFontStyle(font);
+ return text == "" ? 0 : text.Select(chr => fontStyle.GetHeight(chr, font.Height)).Max();
+ }
+
+ private static int _GetFontIndex(string fontName)
+ {
+ if (fontName != "")
+ {
+ int index = _GetPartyFontIndex(fontName, PartyModeID);
+ if (index < 0)
+ index = _GetThemeFontIndex(fontName, CConfig.Theme);
+ if (index >= 0)
+ return index;
+ for (int i = 0; i < _FontFamilies.Count; i++)
+ {
+ if (_FontFamilies[i].Name == fontName)
+ return i;
+ }
+ if (!_LoggedMissingFonts.Contains(fontName))
+ {
+ _LoggedMissingFonts.Add(fontName);
+ CLog.LogError("Font \"" + fontName + "\" not found!");
+ }
+ }
+ else
+ CLog.LogError("Empty fontName requested", false, false, new Exception());
+
+ if (_FontFamilies.Count == 0)
+ CLog.LogError("No fonts found!", true, true);
+
+ return 0;
+ }
+
+ private static int _GetThemeFontIndex(string fontName, string themeName)
+ {
+ Debug.Assert(fontName != "" && themeName != "");
+
+ for (int i = 0; i < _FontFamilies.Count; i++)
+ {
+ if (_FontFamilies[i].Name == fontName && _FontFamilies[i].ThemeName == themeName)
+ return i;
+ }
+
+ return -1;
+ }
+
+ private static int _GetPartyFontIndex(string fontName, int partyModeID)
+ {
+ Debug.Assert(fontName != "");
+
+ for (int i = 0; i < _FontFamilies.Count; i++)
+ {
+ if (_FontFamilies[i].PartyModeID == partyModeID && _FontFamilies[i].Name == fontName)
+ return i;
+ }
+
+ return -1;
}
///
- /// Calculates the bounds for a CText object
+ /// Load default fonts
///
- /// The CText object of which the bounds should be calculated for
- /// The height of the CText object
- /// RectangleF object containing the bounds
- public static RectangleF GetTextBounds(CText text, float height)
+ ///
+ private static bool _LoadDefaultFonts()
{
- float oldHeight = Height;
- int oldFont = _CurrentFont;
- EStyle oldStyle = Style;
- Height = height;
- SetFont(text.Font);
- Style = text.Style;
- var result = new RectangleF(text.X, text.Y, GetTextWidth(CLanguage.Translate(text.Text, text.TranslationID)),
- GetTextHeight(CLanguage.Translate(text.Text, text.TranslationID)));
- //restore old values
- Height = oldHeight;
- _CurrentFont = oldFont;
- Style = oldStyle;
- return result;
+ CXMLReader xmlReader = CXMLReader.OpenFile(Path.Combine(CSettings.ProgramFolder, CSettings.FolderNameFonts, CSettings.FileNameFonts));
+ if (xmlReader == null)
+ return false;
+
+ return _LoadFontFile(xmlReader, Path.Combine(CSettings.ProgramFolder, CSettings.FolderNameFonts));
}
- public static float GetTextWidth(string text)
+ ///
+ /// Loads theme fonts from skin file
+ ///
+ public static bool LoadThemeFonts(string themeName, string fontFolder, CXMLReader xmlReader)
{
- CFont font = _GetCurrentFont();
- return text.Sum(chr => font.GetWidth(chr));
+ bool ok = _LoadFontFile(xmlReader, fontFolder, themeName);
+ CLog.StartBenchmark("BuildGlyphs");
+ _BuildGlyphs();
+ CLog.StopBenchmark("BuildGlyphs");
+ return ok;
}
- public static float GetTextHeight(string text)
+ ///
+ /// Loads party mode fonts from skin file
+ ///
+ public static bool LoadPartyModeFonts(int partyModeID, string fontFolder, CXMLReader xmlReader)
{
- //return TextRenderer.MeasureText(text, GetFont()).Height;
- CFont font = _GetCurrentFont();
- return text == "" ? 0 : text.Select(font.GetHeight).Max();
+ bool ok = _LoadFontFile(xmlReader, fontFolder, "", partyModeID);
+ CLog.StartBenchmark("BuildGlyphs");
+ _BuildGlyphs();
+ CLog.StopBenchmark("BuildGlyphs");
+ return ok;
}
- private static void _LoadFontFiles(CXMLReader xmlReader, string fontFolder, string themeName = "", int partyModeId = -1)
+ private static bool _LoadFontFile(CXMLReader xmlReader, string fontFolder, string themeName = "", int partyModeId = -1)
{
- string value = string.Empty;
+ string value;
int i = 1;
- while (xmlReader.GetValue("//root/Fonts/Font" + i + "/Folder", out value, value))
+ while (xmlReader.GetValue("//root/Fonts/Font" + i + "/Folder", out value))
{
- var sf = new SFont {Folder = value, IsThemeFont = themeName != "", ThemeName = themeName, PartyModeID = partyModeId};
+ var sf = new SFontFamily {Folder = value, ThemeName = themeName, PartyModeID = partyModeId};
bool ok = true;
- string name;
- ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/Name", out name, value);
- sf.Name = name;
-
- ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileNormal", out value, value);
- sf.FileNormal = value;
- value = Path.Combine(fontFolder, Path.Combine(sf.Folder, value));
- var f = new CFont(value);
- sf.Normal = f;
-
- ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileItalic", out value, value);
- sf.FileItalic = value;
- value = Path.Combine(fontFolder, Path.Combine(sf.Folder, value));
- f = new CFont(value);
- sf.Italic = f;
-
- ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileBold", out value, value);
- sf.FileBold = value;
- value = Path.Combine(fontFolder, Path.Combine(sf.Folder, value));
- f = new CFont(value);
- sf.Bold = f;
-
- ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileBoldItalic", out value, value);
- sf.FileBoldItalic = value;
- value = Path.Combine(fontFolder, Path.Combine(sf.Folder, value));
- f = new CFont(value);
- sf.BoldItalic = f;
-
- sf.Outline = 0f;
- ok &= xmlReader.TryGetFloatValue("//root/Fonts/Font" + i + "/Outline", ref sf.Outline);
-
- sf.OutlineColor = new SColorF(0f, 0f, 0f, 1f);
- ok &= xmlReader.TryGetFloatValue("//root/Fonts/Font" + i + "/OutlineColorR", ref sf.OutlineColor.R);
- ok &= xmlReader.TryGetFloatValue("//root/Fonts/Font" + i + "/OutlineColorG", ref sf.OutlineColor.G);
- ok &= xmlReader.TryGetFloatValue("//root/Fonts/Font" + i + "/OutlineColorB", ref sf.OutlineColor.B);
- ok &= xmlReader.TryGetFloatValue("//root/Fonts/Font" + i + "/OutlineColorA", ref sf.OutlineColor.A);
+ ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/Name", out sf.Name);
+ ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileNormal", out sf.FileNormal);
+ ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileItalic", out sf.FileItalic);
+ ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileBold", out sf.FileBold);
+ ok &= xmlReader.GetValue("//root/Fonts/Font" + i + "/FileBoldItalic", out sf.FileBoldItalic);
+ ok &= xmlReader.TryGetNormalizedFloatValue("//root/Fonts/Font" + i + "/Outline", ref sf.Outline);
+ ok &= xmlReader.TryGetColorFromRGBA("//root/Fonts/Font" + i + "/OutlineColor", ref sf.OutlineColor);
if (ok)
- _Fonts.Add(sf);
+ {
+ sf.Normal = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileNormal), EStyle.Normal, sf.Outline, sf.OutlineColor);
+ sf.Italic = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileItalic), EStyle.Italic, sf.Outline, sf.OutlineColor);
+ sf.Bold = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileBold), EStyle.Bold, sf.Outline, sf.OutlineColor);
+ sf.BoldItalic = new CFontStyle(Path.Combine(fontFolder, sf.Folder, sf.FileBoldItalic), EStyle.BoldItalic, sf.Outline, sf.OutlineColor);
+ _FontFamilies.Add(sf);
+ }
else
{
string fontTypes;
@@ -330,170 +358,80 @@ namespace Vocaluxe.Base.Fonts
else
fontTypes = "basic fonts";
CLog.LogError("Error loading " + fontTypes + ": Error in Font" + i);
+ return false;
}
i++;
}
- }
-
- ///
- /// Load default fonts
- ///
- ///
- private static void _LoadFontList()
- {
- CXMLReader xmlReader = CXMLReader.OpenFile(Path.Combine(CSettings.ProgramFolder, CSettings.FolderNameFonts, CSettings.FileNameFonts));
- if (xmlReader == null)
- return;
-
- _LoadFontFiles(xmlReader, Path.Combine(CSettings.ProgramFolder, CSettings.FolderNameFonts));
- }
-
- ///
- /// Loads theme fonts from skin file
- ///
- public static void LoadThemeFonts(string themeName, string fontFolder, CXMLReader xmlReader)
- {
- _LoadFontFiles(xmlReader, fontFolder, themeName);
- CLog.StartBenchmark("BuildGlyphs");
- _BuildGlyphs();
- CLog.StopBenchmark("BuildGlyphs");
- }
-
- ///
- /// Loads party mode fonts from skin file
- ///
- public static void LoadPartyModeFonts(int partyModeID, string fontFolder, CXMLReader xmlReader)
- {
- _LoadFontFiles(xmlReader, fontFolder, "", partyModeID);
- CLog.StartBenchmark("BuildGlyphs");
- _BuildGlyphs();
- CLog.StopBenchmark("BuildGlyphs");
+ return true;
}
public static void SaveThemeFonts(string themeName, XmlWriter writer)
{
- if (_Fonts.Count == 0)
+ if (_FontFamilies.Count == 0)
return;
- int index = 0;
+ writer.WriteStartElement("Fonts");
int fontNr = 1;
- bool setStart = false;
- while (index < _Fonts.Count)
+ foreach (SFontFamily font in _FontFamilies)
{
- if (_Fonts[index].IsThemeFont && _Fonts[index].ThemeName == themeName)
+ if (font.ThemeName == themeName)
{
- if (!setStart)
- {
- writer.WriteStartElement("Fonts");
- setStart = true;
- }
-
writer.WriteStartElement("Font" + fontNr);
- writer.WriteElementString("Name", _Fonts[index].Name);
- writer.WriteElementString("Folder", _Fonts[index].Folder);
+ writer.WriteElementString("Name", font.Name);
+ writer.WriteElementString("Folder", font.Folder);
- writer.WriteElementString("Outline", _Fonts[index].Outline.ToString("#0.00"));
- writer.WriteElementString("OutlineColorR", _Fonts[index].OutlineColor.R.ToString("#0.00"));
- writer.WriteElementString("OutlineColorG", _Fonts[index].OutlineColor.G.ToString("#0.00"));
- writer.WriteElementString("OutlineColorB", _Fonts[index].OutlineColor.B.ToString("#0.00"));
- writer.WriteElementString("OutlineColorA", _Fonts[index].OutlineColor.A.ToString("#0.00"));
+ writer.WriteElementString("Outline", font.Outline.ToString("#0.00"));
+ writer.WriteStartElement("OutlineColor");
+ writer.WriteElementString("R", font.OutlineColor.R.ToString("#0.00"));
+ writer.WriteElementString("G", font.OutlineColor.G.ToString("#0.00"));
+ writer.WriteElementString("B", font.OutlineColor.B.ToString("#0.00"));
+ writer.WriteElementString("A", font.OutlineColor.A.ToString("#0.00"));
+ writer.WriteEndElement();
- writer.WriteElementString("FileNormal", _Fonts[index].FileNormal);
- writer.WriteElementString("FileBold", _Fonts[index].FileBold);
- writer.WriteElementString("FileItalic", _Fonts[index].FileItalic);
- writer.WriteElementString("FileBoldItalic", _Fonts[index].FileBoldItalic);
+ writer.WriteElementString("FileNormal", font.FileNormal);
+ writer.WriteElementString("FileBold", font.FileBold);
+ writer.WriteElementString("FileItalic", font.FileItalic);
+ writer.WriteElementString("FileBoldItalic", font.FileBoldItalic);
writer.WriteEndElement();
fontNr++;
}
- index++;
}
- if (setStart)
- writer.WriteEndElement();
+ writer.WriteEndElement();
}
public static void UnloadThemeFonts(string themeName)
{
int index = 0;
- while (index < _Fonts.Count)
+ while (index < _FontFamilies.Count)
{
- if (_Fonts[index].IsThemeFont && _Fonts[index].ThemeName == themeName)
+ if (_FontFamilies[index].ThemeName == themeName)
{
- _Fonts[index].Normal.UnloadGlyphs();
- _Fonts[index].Italic.UnloadGlyphs();
- _Fonts[index].Bold.UnloadGlyphs();
- _Fonts[index].BoldItalic.UnloadGlyphs();
- _Fonts.RemoveAt(index);
+ _FontFamilies[index].Dispose();
+ _FontFamilies.RemoveAt(index);
}
else
index++;
}
}
- private static int _GetFontIndex(string fontName)
- {
- for (int i = 0; i < _Fonts.Count; i++)
- {
- if (!_Fonts[i].IsThemeFont && _Fonts[i].Name == fontName)
- return i;
- }
-
- return -1;
- }
-
- private static int _GetThemeFontIndex(string themeName, string fontName)
- {
- if (themeName == "" || fontName == "")
- return -1;
-
- for (int i = 0; i < _Fonts.Count; i++)
- {
- if (_Fonts[i].IsThemeFont && _Fonts[i].Name == fontName && _Fonts[i].ThemeName == themeName)
- return i;
- }
-
- return -1;
- }
-
- private static int _GetPartyFontIndex(int partyModeID, string fontName)
- {
- if (partyModeID == -1 || fontName == "")
- return -1;
-
- for (int i = 0; i < _Fonts.Count; i++)
- {
- if (!_Fonts[i].IsThemeFont && _Fonts[i].PartyModeID == partyModeID && _Fonts[i].Name == fontName)
- return i;
- }
-
- return -1;
- }
-
private static void _BuildGlyphs()
{
const string text = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
- for (int i = 0; i < _Fonts.Count; i++)
+ foreach (SFontFamily fontFamily in _FontFamilies)
{
- _CurrentFont = i;
-
foreach (char chr in text)
{
- Style = EStyle.Normal;
- _Fonts[_CurrentFont].Normal.GetOrAddGlyph(chr);
- Style = EStyle.Bold;
- _Fonts[_CurrentFont].Bold.GetOrAddGlyph(chr);
- Style = EStyle.Italic;
- _Fonts[_CurrentFont].Italic.GetOrAddGlyph(chr);
- Style = EStyle.BoldItalic;
- _Fonts[_CurrentFont].BoldItalic.GetOrAddGlyph(chr);
+ fontFamily.Normal.GetOrAddGlyph(chr, -1);
+ fontFamily.Bold.GetOrAddGlyph(chr, -1);
+ fontFamily.Italic.GetOrAddGlyph(chr, -1);
+ fontFamily.BoldItalic.GetOrAddGlyph(chr, -1);
}
}
- Style = EStyle.Normal;
- SetFont("Normal");
}
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Base/Fonts/CGlyph.cs b/Vocaluxe/Base/Fonts/CGlyph.cs
index c694c84d..6b949903 100644
--- a/Vocaluxe/Base/Fonts/CGlyph.cs
+++ b/Vocaluxe/Base/Fonts/CGlyph.cs
@@ -31,31 +31,18 @@ namespace Vocaluxe.Base.Fonts
{
class CGlyph
{
- private CTexture _Texture;
+ private CTextureRef _Texture;
private readonly SizeF _BoundingBox;
private readonly RectangleF _DrawBounding;
public readonly float MaxHeight;
- public float Width
- {
- get { return _BoundingBox.Width * _GetFactor(); }
- }
-
- public float Height
- {
- get { return _BoundingBox.Height * _GetFactor(); }
- }
-
- public CGlyph(char chr, float maxHeight)
+ public CGlyph(char chr, CFontStyle fontStyle, float maxHeight)
{
MaxHeight = maxHeight;
- float oldHeight = CFonts.Height;
- float outline = CFonts.Outline;
- float outlineSize = outline * maxHeight;
+ float outlineSize = fontStyle.Outline * maxHeight;
string chrString = chr.ToString();
- CFonts.Height = maxHeight;
- Font fo = CFonts.GetFont();
+ Font fo = fontStyle.GetSystemFont(maxHeight);
SizeF fullSize;
Size bmpSize;
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
@@ -64,7 +51,7 @@ namespace Vocaluxe.Base.Fonts
if (chr != ' ')
{
//Gets exact height and width for drawing more than 1 char. But width is to small to draw char on bitmap as e.g. italic chars will get cropped
- _BoundingBox = g.MeasureString(chrString, fo, -1, new StringFormat(StringFormat.GenericTypographic));
+ _BoundingBox = g.MeasureString(chrString, fo, -1, StringFormat.GenericTypographic);
// ReSharper disable CompareOfFloatsByEqualityOperator
if (_BoundingBox.Height == 0)
// ReSharper restore CompareOfFloatsByEqualityOperator
@@ -105,7 +92,7 @@ namespace Vocaluxe.Base.Fonts
float emSize = fo.Size * fo.FontFamily.GetCellAscent(fo.Style) / fo.FontFamily.GetEmHeight(fo.Style);
path.AddString(chrString, fo.FontFamily, (int)fo.Style, emSize, point, new StringFormat());
- using (var pen = new Pen(CFonts.OutlineColor.AsColor(), outlineSize))
+ using (var pen = new Pen(fontStyle.OutlineColor.AsColor(), outlineSize))
{
pen.LineJoin = LineJoin.Round;
g.DrawPath(pen, path);
@@ -134,7 +121,6 @@ namespace Vocaluxe.Base.Fonts
}
}
}
- CFonts.Height = oldHeight;
}
public void UnloadTexture()
@@ -142,15 +128,25 @@ namespace Vocaluxe.Base.Fonts
CDraw.RemoveTexture(ref _Texture);
}
- private float _GetFactor()
+ private float _GetFactor(float fontHeight)
{
- return CFonts.Height / _BoundingBox.Height;
+ return fontHeight / _BoundingBox.Height;
}
- public void GetTextureAndRect(float x, float y, float z, out CTexture texture, out SRectF rect)
+ public float GetWidth(float fontHeight)
+ {
+ return _BoundingBox.Width * _GetFactor(fontHeight);
+ }
+
+ public float GetHeight(float fontHeight)
+ {
+ return _BoundingBox.Height * _GetFactor(fontHeight);
+ }
+
+ public void GetTextureAndRect(float fontHeight, float x, float y, float z, out CTextureRef texture, out SRectF rect)
{
texture = _Texture;
- float factor = _GetFactor();
+ float factor = _GetFactor(fontHeight);
x += _DrawBounding.X * factor;
y += _DrawBounding.Y * factor;
float h = _DrawBounding.Height * factor;
@@ -161,7 +157,7 @@ namespace Vocaluxe.Base.Fonts
private static Rectangle _GetRealBounds(Bitmap bmp)
{
int minX = 0, maxX = bmp.Width - 1, minY = 0;
- BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ BitmapData bmpData = bmp.LockBits(bmp.GetRect(), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int values = bmpData.Width * bmp.Height;
var rgbValues = new Int32[values];
Marshal.Copy(bmpData.Scan0, rgbValues, 0, values);
diff --git a/Vocaluxe/COSFunctions.cs b/Vocaluxe/COSFunctions.cs
index f41d5bbe..33faab37 100644
--- a/Vocaluxe/COSFunctions.cs
+++ b/Vocaluxe/COSFunctions.cs
@@ -16,6 +16,7 @@
#endregion
using System;
+using System.Drawing;
using System.Runtime.InteropServices;
namespace Vocaluxe
diff --git a/Vocaluxe/Lib/Database/CCoverDB.cs b/Vocaluxe/Lib/Database/CCoverDB.cs
index 7723e2d4..efd33c13 100644
--- a/Vocaluxe/Lib/Database/CCoverDB.cs
+++ b/Vocaluxe/Lib/Database/CCoverDB.cs
@@ -22,6 +22,7 @@ using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using Vocaluxe.Base;
+using VocaluxeLib;
using VocaluxeLib.Draw;
#if WIN
using System.Data.SQLite;
@@ -34,28 +35,29 @@ namespace Vocaluxe.Lib.Database
{
public class CCoverDB : CDatabaseBase
{
- //You have to lock all actions using cover connection or transaction, otherwhise order is not guaranted
- private readonly object _CoverMutex = new object();
private SQLiteTransaction _TransactionCover;
public CCoverDB(string filePath) : base(filePath) {}
public override bool Init()
{
- if (!base.Init())
- return false;
+ lock (_Mutex)
+ {
+ if (!base.Init())
+ return false;
- if (_Version < 0)
- return _CreateCoverDB();
- if (_Version < CSettings.DatabaseCoverVersion)
- throw new NotImplementedException("Upgrading of cover DB not implemented");
+ if (_Version < 0)
+ return _CreateCoverDB();
+ if (_Version < CSettings.DatabaseCoverVersion)
+ throw new NotImplementedException("Upgrading of cover DB not implemented");
+ }
return true;
}
public override void Close()
{
//Do commit and close atomicly otherwhise we may loose changes
- lock (_CoverMutex)
+ lock (_Mutex)
{
_CommitCovers();
@@ -63,7 +65,7 @@ namespace Vocaluxe.Lib.Database
}
}
- public bool GetCover(string coverPath, ref CTexture tex, int maxSize)
+ public bool GetCover(string coverPath, ref CTextureRef tex, int maxSize)
{
if (_Connection == null)
return false;
@@ -73,7 +75,7 @@ namespace Vocaluxe.Lib.Database
return false;
}
- lock (_CoverMutex)
+ lock (_Mutex)
{
//Double check here because we may have just closed our connection
if (_Connection == null)
@@ -81,7 +83,7 @@ namespace Vocaluxe.Lib.Database
using (var command = new SQLiteCommand(_Connection))
{
command.CommandText = "SELECT id, width, height FROM Cover WHERE [Path] = @path";
- command.Parameters.Add("@path", DbType.String, 0).Value = coverPath;
+ command.Parameters.Add("@path", DbType.String).Value = coverPath;
SQLiteDataReader reader = command.ExecuteReader();
@@ -100,81 +102,81 @@ namespace Vocaluxe.Lib.Database
if (reader.HasRows)
{
reader.Read();
- byte[] data = _GetBytes(reader);
+ byte[] data2 = _GetBytes(reader);
reader.Dispose();
- tex = CDraw.EnqueueTexture(w, h, data);
+ tex = CDraw.EnqueueTexture(w, h, data2);
return true;
}
- }
- else
- {
- if (reader != null)
- reader.Close();
-
- if (_TransactionCover == null)
- _TransactionCover = _Connection.BeginTransaction();
-
- Bitmap origin;
- try
- {
- origin = new Bitmap(coverPath);
- }
- catch (Exception)
- {
- CLog.LogError("Error loading Texture: " + coverPath);
- return false;
- }
-
- int w = maxSize;
- int h = maxSize;
- byte[] data;
-
- try
- {
- if (origin.Width >= origin.Height && origin.Width > w)
- h = (int)Math.Round((float)w / origin.Width * origin.Height);
- else if (origin.Height > origin.Width && origin.Height > h)
- w = (int)Math.Round((float)h / origin.Height * origin.Width);
-
- using (var bmp = new Bitmap(w, h))
- {
- using (Graphics g = Graphics.FromImage(bmp))
- g.DrawImage(origin, new Rectangle(0, 0, w, h));
-
- data = new byte[w * h * 4];
- BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
- Marshal.Copy(bmpData.Scan0, data, 0, w * h * 4);
- bmp.UnlockBits(bmpData);
- }
- }
- finally
- {
- origin.Dispose();
- }
-
- tex = CDraw.EnqueueTexture(w, h, data);
-
- command.CommandText = "INSERT INTO Cover (Path, width, height) VALUES (@path, @w, @h)";
- command.Parameters.Add("@w", DbType.Int32).Value = w;
- command.Parameters.Add("@h", DbType.Int32).Value = h;
- command.Parameters.Add("@path", DbType.String, 0).Value = coverPath;
+ command.CommandText = "DELETE FROM Cover WHERE id = @id";
+ command.Parameters.Add("@id", DbType.Int32).Value = id;
command.ExecuteNonQuery();
+ }
+ if (reader != null)
+ reader.Close();
+ }
+ }
- command.CommandText = "SELECT id FROM Cover WHERE [Path] = @path";
- command.Parameters.Add("@path", DbType.String, 0).Value = coverPath;
- reader = command.ExecuteReader();
+ // At this point we do not have a mathing entry in the CoverDB (either no Data found and deleted or nothing at all)
+ // We break out of the lock to do the bitmap loading and resizing here to allow multithreaded loading
- if (reader != null)
- {
- reader.Read();
- int id = reader.GetInt32(0);
- reader.Dispose();
- command.CommandText = "INSERT INTO CoverData (CoverID, Data) VALUES (@id, @data)";
- command.Parameters.Add("@id", DbType.Int32).Value = id;
- command.Parameters.Add("@data", DbType.Binary, 20).Value = data;
- command.ExecuteReader();
- return true;
- }
+ Bitmap origin = CHelper.LoadBitmap(coverPath);
+ if (origin == null)
+ return false;
+
+ Size size = origin.GetSize();
+ if (size.Width > maxSize || size.Height > maxSize)
+ {
+ size = CHelper.FitInBounds(new SRectF(0, 0, maxSize, maxSize, 0), (float)size.Width / size.Height, EAspect.LetterBox).SizeI;
+ Bitmap tmp = origin.Resize(size);
+ origin.Dispose();
+ origin = tmp;
+ }
+
+ byte[] data;
+
+ try
+ {
+ data = new byte[size.Width * size.Height * 4];
+ BitmapData bmpData = origin.LockBits(origin.GetRect(), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ Marshal.Copy(bmpData.Scan0, data, 0, data.Length);
+ origin.UnlockBits(bmpData);
+ }
+ finally
+ {
+ origin.Dispose();
+ }
+
+ tex = CDraw.EnqueueTexture(size.Width, size.Height, data);
+
+ lock (_Mutex)
+ {
+ //Double check here because we may have just closed our connection
+ if (_Connection == null)
+ return false;
+ if (_TransactionCover == null)
+ _TransactionCover = _Connection.BeginTransaction();
+ using (var command = new SQLiteCommand(_Connection))
+ {
+ command.CommandText = "INSERT INTO Cover (Path, width, height) VALUES (@path, @w, @h)";
+ command.Parameters.Add("@w", DbType.Int32).Value = size.Width;
+ command.Parameters.Add("@h", DbType.Int32).Value = size.Height;
+ command.Parameters.Add("@path", DbType.String).Value = coverPath;
+ command.ExecuteNonQuery();
+
+ command.CommandText = "SELECT id FROM Cover WHERE [Path] = @path";
+ command.Parameters.Add("@path", DbType.String).Value = coverPath;
+ SQLiteDataReader reader = command.ExecuteReader();
+
+ if (reader != null)
+ {
+ reader.Read();
+ int id = reader.GetInt32(0);
+ reader.Dispose();
+ command.CommandText = "INSERT INTO CoverData (CoverID, Data) VALUES (@id, @data)";
+ command.Parameters.Add("@id", DbType.Int32).Value = id;
+ command.Parameters.Add("@data", DbType.Binary).Value = data;
+ command.ExecuteNonQuery();
+ return true;
}
}
}
@@ -183,7 +185,7 @@ namespace Vocaluxe.Lib.Database
public void CommitCovers()
{
- lock (_CoverMutex)
+ lock (_Mutex)
{
_CommitCovers();
}
diff --git a/Vocaluxe/Lib/Database/CDatabaseBase.cs b/Vocaluxe/Lib/Database/CDatabaseBase.cs
index 068530e5..bbe0f026 100644
--- a/Vocaluxe/Lib/Database/CDatabaseBase.cs
+++ b/Vocaluxe/Lib/Database/CDatabaseBase.cs
@@ -17,7 +17,6 @@
using System;
using System.IO;
-using Vocaluxe.Base;
#if WIN
using System.Data.SQLite;
@@ -27,61 +26,72 @@ using Mono.Data.Sqlite;
namespace Vocaluxe.Lib.Database
{
- public class CDatabaseBase
+ public abstract class CDatabaseBase
{
protected readonly string _FilePath;
protected SQLiteConnection _Connection;
+ //You have to lock all actions using connection or transaction, otherwhise order is not guaranted
+ protected readonly object _Mutex = new object();
+
protected int _Version; //Version of the database (value of row "Value" in table "Version") or -1 if none
- public CDatabaseBase(string filePath)
+ protected CDatabaseBase(string filePath)
{
_FilePath = filePath;
}
public virtual bool Init()
{
- _Connection = new SQLiteConnection("Data Source=" + _FilePath);
- try
+ lock (_Mutex)
{
- _Connection.Open();
- }
- catch (Exception)
- {
- _Connection.Dispose();
- _Connection = null;
- return false;
- }
-
- using (var command = new SQLiteCommand(_Connection))
- {
- command.CommandText = "SELECT Value FROM Version";
-
- SQLiteDataReader reader = null;
-
+ if (_Connection != null)
+ return false;
+ _Connection = new SQLiteConnection("Data Source=" + _FilePath);
try
{
- reader = command.ExecuteReader();
+ _Connection.Open();
+ }
+ catch (Exception)
+ {
+ _Connection.Dispose();
+ _Connection = null;
+ return false;
}
- catch (Exception) {}
- if (reader == null || !reader.Read() || reader.FieldCount == 0)
- _Version = -1;
- else
- _Version = reader.GetInt32(0);
+ using (var command = new SQLiteCommand(_Connection))
+ {
+ command.CommandText = "SELECT Value FROM Version";
- if (reader != null)
- reader.Dispose();
+ SQLiteDataReader reader = null;
+
+ try
+ {
+ reader = command.ExecuteReader();
+ }
+ catch (Exception) {}
+
+ if (reader == null || !reader.Read() || reader.FieldCount == 0)
+ _Version = -1;
+ else
+ _Version = reader.GetInt32(0);
+
+ if (reader != null)
+ reader.Dispose();
+ }
}
return true;
}
public virtual void Close()
{
- if (_Connection != null)
+ lock (_Mutex)
{
- _Connection.Dispose();
- _Connection = null;
+ if (_Connection != null)
+ {
+ _Connection.Dispose();
+ _Connection = null;
+ }
}
}
@@ -92,6 +102,13 @@ namespace Vocaluxe.Lib.Database
return t70.Ticks;
}
+ ///
+ /// Reads the contents of a field as a byte array
+ /// Assumes you did the locking!
+ ///
+ ///
+ /// Field number to read from (default=first)
+ ///
protected static byte[] _GetBytes(SQLiteDataReader reader, int field = 0)
{
const int chunkSize = 2 * 1024;
diff --git a/Vocaluxe/Lib/Database/CResourceDB.cs b/Vocaluxe/Lib/Database/CResourceDB.cs
index 4891a19e..77d9c455 100644
--- a/Vocaluxe/Lib/Database/CResourceDB.cs
+++ b/Vocaluxe/Lib/Database/CResourceDB.cs
@@ -66,7 +66,7 @@ namespace Vocaluxe.Lib.Database
return true;
}
- public bool GetCreditsRessource(string fileName, ref CTexture tex)
+ public bool GetCreditsRessource(string fileName, ref CTextureRef tex)
{
if (_Connection == null)
return false;
diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs
index 1c04f6fd..682905bc 100644
--- a/Vocaluxe/Lib/Draw/CDirect3D.cs
+++ b/Vocaluxe/Lib/Draw/CDirect3D.cs
@@ -15,13 +15,10 @@
// along with Vocaluxe. If not, see .
#endregion
-using System.Drawing.Drawing2D;
-using System.Threading;
using SlimDX;
using SlimDX.Direct3D9;
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
@@ -34,49 +31,56 @@ using VocaluxeLib.Draw;
namespace Vocaluxe.Lib.Draw
{
- class CDirect3D : RenderForm, IDraw
+ class CRenderFormHook : RenderForm, IFormHook
+ {
+ public MessageEventHandler OnMessage { private get; set; }
+
+ protected override void WndProc(ref Message m)
+ {
+ if (OnMessage == null || OnMessage(ref m))
+ base.WndProc(ref m);
+ }
+ }
+
+ class CD3DTexture : CTextureBase
+ {
+ public readonly Texture D3DTexture;
+
+ public CD3DTexture(Device device, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, texWidth, texHeight)
+ {
+ //Create a new texture in the managed pool, which does not need to be recreated on a lost device
+ //because a copy of the texture is hold in the Ram
+ D3DTexture = device == null ? null : new Texture(device, W2, H2, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
+ }
+
+ public override bool IsLoaded
+ {
+ get { return D3DTexture != null; }
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ if (D3DTexture != null)
+ D3DTexture.Dispose();
+ }
+ }
+
+ class CDirect3D : CDrawBaseWindows, IDraw
{
#region private vars
- private const int _MaxID = 100000;
-
- private readonly CKeys _Keys;
- private readonly CMouse _Mouse;
- private bool _Run;
-
private readonly Direct3D _D3D;
private readonly Device _Device;
private readonly PresentParameters _PresentParameters;
- private bool _Fullscreen;
- private Size _OldSize;
- private Size _SizeBeforeMinimize;
-
- private readonly Dictionary _D3DTextures = new Dictionary();
- private readonly Queue _TexturesToLoad = new Queue();
- private readonly Queue _IDs = new Queue(_MaxID);
-
- private readonly Object _MutexTexture = new Object();
-
private VertexBuffer _VertexBuffer;
private IndexBuffer _IndexBuffer;
- private int _H = 1;
- private int _W = 1;
- private int _Y;
- private int _X;
-
- private int _BorderLeft;
- private int _BorderRight;
- private int _BorderTop;
- private int _BorderBottom;
-
- private CTexture _BlankTexture;
+ private CTextureRef _BlankTexture;
private readonly Queue _Vertices = new Queue();
private readonly Queue _VerticesTextures = new Queue();
- private readonly Queue _VerticesRotationMatrices = new Queue();
-
- private readonly bool _NonPowerOf2TextureSupported;
+ private readonly Queue _VerticesRotationMatrices = new Queue();
#endregion private vars
///
@@ -84,13 +88,8 @@ namespace Vocaluxe.Lib.Draw
///
public CDirect3D()
{
- Icon = new Icon(Path.Combine(CSettings.ProgramFolder, CSettings.FileNameIcon));
+ _Form = new CRenderFormHook {ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH)};
- //Fill Queue with 100000 IDs
- for (int i = 0; i < _MaxID; i++)
- _IDs.Enqueue(i);
-
- _Keys = new CKeys();
try
{
_D3D = new Direct3D();
@@ -100,25 +99,17 @@ namespace Vocaluxe.Lib.Draw
CLog.LogError("No DirectX runtimes were found, please download and install them from http://www.microsoft.com/download/en/details.aspx?id=8109", true, true, e);
}
- Paint += _OnPaintEvent;
- Closing += _OnClosingEvent;
- Resize += _OnResizeEvent;
+ _Form.KeyDown += _OnKeyDown;
+ _Form.PreviewKeyDown += _OnPreviewKeyDown;
+ _Form.KeyPress += _OnKeyPress;
+ _Form.KeyUp += _OnKeyUp;
- KeyDown += _OnKeyDown;
- PreviewKeyDown += _OnPreviewKeyDown;
- KeyPress += _OnKeyPress;
- KeyUp += _OnKeyUp;
-
- _Mouse = new CMouse();
- MouseMove += _OnMouseMove;
- MouseWheel += _OnMouseWheel;
- MouseDown += _OnMouseDown;
- MouseUp += _OnMouseUp;
- MouseLeave += _OnMouseLeave;
- MouseEnter += _OnMouseEnter;
-
- ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH);
- _SizeBeforeMinimize = ClientSize;
+ _Form.MouseMove += _OnMouseMove;
+ _Form.MouseWheel += _OnMouseWheel;
+ _Form.MouseDown += _OnMouseDown;
+ _Form.MouseUp += _OnMouseUp;
+ _Form.MouseLeave += _OnMouseLeave;
+ _Form.MouseEnter += _OnMouseEnter;
_PresentParameters = new PresentParameters
{
@@ -184,7 +175,11 @@ namespace Vocaluxe.Lib.Draw
try
{
- _Device = new Device(_D3D, _D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware, Handle, flags, _PresentParameters);
+ _Device = new Device(_D3D, _D3D.Adapters.DefaultAdapter.Adapter, DeviceType.Hardware, _Form.Handle, flags, _PresentParameters);
+ }
+ catch (Exception e)
+ {
+ CLog.LogError("Error during D3D device creation.", false, false, e);
}
finally
{
@@ -195,213 +190,87 @@ namespace Vocaluxe.Lib.Draw
true, true);
}
}
-
- CenterToScreen();
}
- #region form events
- private void _OnPaintEvent(object sender, PaintEventArgs e) {}
-
- private void _OnResizeEvent(object sender, EventArgs e) {}
-
- private void _OnClosingEvent(object sender, CancelEventArgs e)
- {
- _Run = false;
- }
-
- protected override void OnLoad(EventArgs e)
- {
- _Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
- }
-
- protected override void OnResize(EventArgs e)
- {
- base.OnResize(e);
- _DoResize();
- }
-
- protected override void WndProc(ref Message m)
- {
- switch (m.Msg)
- {
- case 0x112: // WM_SYSCOMMAND
- switch ((int)m.WParam & 0xFFF0)
- {
- case 0xF100: // SC_KEYMENU
- m.Result = IntPtr.Zero;
- break;
- case 0xF140: // SC_SCREENSAVER
- case 0xF170: // SC_MONITORPOWER
- break;
- default:
- base.WndProc(ref m);
- break;
- }
- break;
- default:
- base.WndProc(ref m);
- break;
- }
- }
- #endregion form events
-
#region resize
///
/// Resizes the viewport
///
- private void _DoResize()
+ protected override void _DoResize()
{
// The window was minimized, so restore it to the last known size
- if (ClientSize.Width == 0 || ClientSize.Height == 0)
- ClientSize = _SizeBeforeMinimize;
- if (!_Run)
- return;
- _H = ClientSize.Height;
- _W = ClientSize.Width;
- _Y = 0;
- _X = 0;
+ if (_Form.ClientSize.Width == 0 || _Form.ClientSize.Height == 0)
+ _Form.ClientSize = _SizeBeforeMinimize;
- if (_W / (float)_H > CSettings.GetRenderAspect())
- {
- //The windows's width is too big
- _W = (int)Math.Round(_H * CSettings.GetRenderAspect());
- _X = (ClientSize.Width - _W) / 2;
- }
- else
- {
- //The windows's height is too big
- _H = (int)Math.Round(_W / CSettings.GetRenderAspect());
- _Y = (ClientSize.Height - _H) / 2;
- }
+ if (_H == _Form.ClientSize.Height && _W == _Form.ClientSize.Width && CConfig.ScreenAlignment == _CurrentAlignment)
+ return;
+
+ _CurrentAlignment = CConfig.ScreenAlignment;
+ _H = _Form.ClientSize.Height;
+ _W = _Form.ClientSize.Width;
+
+ _AdjustAspect(false);
//Apply the new sizes to the PresentParameters
- _PresentParameters.BackBufferWidth = ClientSize.Width;
- _PresentParameters.BackBufferHeight = ClientSize.Height;
- ClearScreen();
- //To set new PresentParameters the device has to be resetted
- _Reset();
- //All configurations got flushed due to Reset(), so apply them again
- Init();
+ _PresentParameters.BackBufferWidth = _Form.ClientSize.Width;
+ _PresentParameters.BackBufferHeight = _Form.ClientSize.Height;
+ if (_Run)
+ {
+ _ClearScreen();
+ //To set new PresentParameters the device has to be resetted
+ _Reset();
+ //All configurations got flushed due to Reset(), so apply them again
+ _InitDevice();
+ _Device.Viewport = new Viewport(_X, _Y, _W, _H);
+ }
- //Set the new Viewport
- _Device.Viewport = new Viewport(_X, _Y, _W, _H);
//Store size so it can get restored after the window gets minimized
- _SizeBeforeMinimize = ClientSize;
+ _SizeBeforeMinimize = _Form.ClientSize;
}
+ // ReSharper disable RedundantOverridenMember
///
/// Triggers the Fullscreen mode
///
- private void _EnterFullScreen()
+ protected override void _EnterFullScreen()
{
//This currently not using real fullscreen mode but a borderless window
//Real fullscreen could be gained setting _PresentParameters.Windowed = true
//And calling Reset() and Init() after
- _OldSize = ClientSize;
-
- int screenNr = 0;
- for (int i = 0; i < Screen.AllScreens.Length; i++)
- {
- Screen scr = Screen.AllScreens[i];
- if (scr.Bounds.Top <= Top && scr.Bounds.Left <= Left)
- screenNr = i;
- }
-
- ClientSize = new Size(Screen.AllScreens[screenNr].Bounds.Width, Screen.AllScreens[screenNr].Bounds.Height);
- FormBorderStyle = FormBorderStyle.None;
- CenterToScreen();
- _Fullscreen = true;
-
- if (WindowState == FormWindowState.Maximized)
- {
- WindowState = FormWindowState.Normal;
- _DoResize();
- WindowState = FormWindowState.Maximized;
- }
- else
- _DoResize();
+ base._EnterFullScreen();
}
- ///
- /// Triggers the windowed mode
- ///
- private void _LeaveFullScreen()
- {
- ClientSize = _OldSize;
- FormBorderStyle = FormBorderStyle.Sizable;
- CenterToScreen();
- _Fullscreen = false;
- }
+ // ReSharper restore RedundantOverridenMember
#endregion resize
- #region mouse event handlers
- private void _OnMouseMove(object sender, MouseEventArgs e)
- {
- _Mouse.MouseMove(e);
- }
-
- private void _OnMouseWheel(object sender, MouseEventArgs e)
- {
- _Mouse.MouseWheel(e);
- }
-
- private void _OnMouseDown(object sender, MouseEventArgs e)
- {
- _Mouse.MouseDown(e);
- }
-
- private void _OnMouseUp(object sender, MouseEventArgs e)
- {
- _Mouse.MouseUp(e);
- }
-
- private void _OnMouseLeave(object sender, EventArgs e)
- {
- _Mouse.Visible = false;
- Cursor.Show();
- }
-
- private void _OnMouseEnter(object sender, EventArgs e)
- {
- Cursor.Hide();
- _Mouse.Visible = true;
- }
- #endregion
-
- #region keyboard event handlers
- private void _OnPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
- {
- _OnKeyDown(sender, new KeyEventArgs(e.KeyData));
- }
-
- private void _OnKeyDown(object sender, KeyEventArgs e)
- {
- _Keys.KeyDown(e);
- }
-
- private void _OnKeyPress(object sender, KeyPressEventArgs e)
- {
- _Keys.KeyPress(e);
- }
-
- private void _OnKeyUp(object sender, KeyEventArgs e)
- {
- _Keys.KeyUp(e);
- }
- #endregion keyboard event handlers
-
- #region implementation
-
#region main stuff
///
/// Inits the Device
///
/// True if it succeeded else false
- public bool Init()
+ public override bool Init()
{
+ if (!base.Init())
+ return false;
+
if (_Device.Disposed)
return false;
- Text = CSettings.GetFullVersionText();
+
+ _InitDevice();
+
+ //This creates a new white texture and adds it to the texture pool
+ //This texture is used for the DrawRect method
+ using (var blankMap = new Bitmap(1, 1))
+ using (Graphics g = Graphics.FromImage(blankMap))
+ {
+ g.Clear(Color.White);
+ _BlankTexture = AddTexture(blankMap);
+ }
+ return true;
+ }
+
+ private void _InitDevice()
+ {
_AdjustNewBorders();
_VertexBuffer = new VertexBuffer(_Device, CSettings.VertexBufferElements * (4 * Marshal.SizeOf(typeof(STexturedColoredVertex))), Usage.WriteOnly | Usage.Dynamic,
@@ -417,9 +286,9 @@ namespace Vocaluxe.Lib.Draw
CLog.LogError("Failed to enable alpha blending");
if (_Device.SetRenderState(RenderState.Lighting, false).IsFailure)
CLog.LogError("Failed to disable lighting");
- if (_Device.SetRenderState(RenderState.DestinationBlend, SlimDX.Direct3D9.Blend.InverseSourceAlpha).IsFailure)
+ if (_Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha).IsFailure)
CLog.LogError("Failed to set destination blend");
- if (_Device.SetRenderState(RenderState.SourceBlend, SlimDX.Direct3D9.Blend.SourceAlpha).IsFailure)
+ if (_Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha).IsFailure)
CLog.LogError("Failed to set source blend");
if (_PresentParameters.Multisample != MultisampleType.None)
{
@@ -457,99 +326,37 @@ namespace Vocaluxe.Lib.Draw
stream.WriteRange(indices);
_IndexBuffer.Unlock();
_Device.Indices = _IndexBuffer;
-
- //This creates a new white texture and adds it to the texture pool
- //This texture is used for the DrawRect method
- using (var blankMap = new Bitmap(1, 1))
- {
- Graphics g = Graphics.FromImage(blankMap);
- g.Clear(Color.White);
- g.Dispose();
- _BlankTexture = AddTexture(blankMap);
- }
- return true;
}
- ///
- /// Starts the rendering
- ///
- public void MainLoop()
+ protected override void _OnBeforeDraw()
{
- _Run = true;
- int delay = 0;
- Show();
+ if (_Device.BeginScene().IsFailure)
+ CLog.LogError("Failed to begin scene");
+ }
- if (CConfig.FullScreen == EOffOn.TR_CONFIG_ON)
- _EnterFullScreen();
-
- //Resize window if aspect ratio is incorrect
- if (Math.Abs(_W / (float)_H - CSettings.GetRenderAspect()) > 0.01)
- _DoResize();
-
- while (_Run)
+ protected override void _OnAfterDraw()
+ {
+ _RenderVertexBuffer();
+ if (_Device.EndScene().IsFailure)
+ CLog.LogError("Failed to end scene");
+ try
{
- Application.DoEvents();
- //Clear the previous Frame
- ClearScreen();
- //We want to begin drawing
- if (_Device.BeginScene().IsFailure)
- CLog.LogError("Failed to begin scene");
- _CheckQueue();
- if (!CGraphics.Draw())
- _Run = false;
- _RenderVertexBuffer();
- //We finished drawing the frame
- if (_Device.EndScene().IsFailure)
- CLog.LogError("Failed to end scene");
- if (!CGraphics.UpdateGameLogic(_Keys, _Mouse))
- _Run = false;
- try
- {
- //Now push the frame to the Viewport
- _Device.Present();
- }
- catch (Direct3D9Exception)
- {
- //In Direct3D devices can get lost.
- //This happens for example when opening the Task Manager in Vista/Windows 7 or if a UAC message is opening
- //We need to reset the device to get it to workable state again
- //After a reset Init() needs to be called because all data in the Direct3D default pool are lost and need to be recreated
- if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset)
- {
- _Reset();
- Init();
- }
- }
- //Apply fullscreen mode
- if ((CConfig.FullScreen == EOffOn.TR_CONFIG_ON) != _Fullscreen)
- {
- if (!_Fullscreen)
- _EnterFullScreen();
- else
- _LeaveFullScreen();
- }
-
- //Apply border changes
- if (_BorderLeft != CConfig.BorderLeft || _BorderRight != CConfig.BorderRight || _BorderTop != CConfig.BorderTop || _BorderBottom != CConfig.BorderBottom)
- {
- _BorderLeft = CConfig.BorderLeft;
- _BorderRight = CConfig.BorderRight;
- _BorderTop = CConfig.BorderTop;
- _BorderBottom = CConfig.BorderBottom;
-
- _AdjustNewBorders();
- }
-
- if (CTime.IsRunning())
- delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds());
-
- if (delay >= 1 && CConfig.VSync == EOffOn.TR_CONFIG_OFF)
- Thread.Sleep(delay);
- //Calculate the FPS Rate and restart the timer after a frame
- CTime.CalculateFPS();
- CTime.Restart();
+ //Now push the frame to the Viewport
+ _Device.Present();
}
- Close();
+ catch (Direct3D9Exception)
+ {
+ //In Direct3D devices can get lost.
+ //This happens for example when opening the Task Manager in Vista/Windows 7 or if a UAC message is opening
+ //We need to reset the device to get it to workable state again
+ //After a reset Init() needs to be called because all data in the Direct3D default pool are lost and need to be recreated
+ if (_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset)
+ {
+ _Reset();
+ _InitDevice();
+ }
+ }
+ Application.DoEvents();
}
///
@@ -565,12 +372,14 @@ namespace Vocaluxe.Lib.Draw
CLog.LogError("Failed to reset the device");
}
- private void _AdjustNewBorders()
+ protected override void _AdjustNewBorders()
{
- SlimDX.Matrix translate = SlimDX.Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
- SlimDX.Matrix projection = SlimDX.Matrix.OrthoOffCenterLH(
- -(float)CSettings.RenderW / 2 - _BorderLeft, (float)CSettings.RenderW / 2 + _BorderRight,
- -(float)CSettings.RenderH / 2 - _BorderBottom, (float)CSettings.RenderH / 2 + _BorderTop,
+ const float dx = (float)CSettings.RenderW / 2;
+ const float dy = (float)CSettings.RenderH / 2;
+ Matrix translate = Matrix.Translation(new Vector3(-dx, dy, 0));
+ Matrix projection = Matrix.OrthoOffCenterLH(
+ -dx - _BorderLeft, dx + _BorderRight,
+ -dy - _BorderBottom, dy + _BorderTop,
CSettings.ZNear, CSettings.ZFar);
if (_Device.SetTransform(TransformState.Projection, projection).IsFailure)
@@ -583,21 +392,10 @@ namespace Vocaluxe.Lib.Draw
/// Unloads all Textures and other objects used by Direct3D for rendering
///
///
- public void Unload()
+ public override void Unload()
{
- try
- {
- Close();
- }
- catch {}
- //Dispose all textures
- foreach (Texture texture in _D3DTextures.Values)
- {
- if (texture != null)
- texture.Dispose();
- }
-
- STexturedColoredVertex.GetDeclaration(_Device).Dispose();
+ base.Unload();
+ STexturedColoredVertex.DisposeDeclaration();
_VertexBuffer.Dispose();
_IndexBuffer.Dispose();
_Device.Dispose();
@@ -628,7 +426,7 @@ namespace Vocaluxe.Lib.Draw
/// A TexturedColoredVertex array containg 4 vertices
/// The texture the vertex should be textured with
/// The vertices' rotation
- private void _AddToVertexBuffer(STexturedColoredVertex[] vertices, Texture tex, SlimDX.Matrix rotation)
+ private void _AddToVertexBuffer(STexturedColoredVertex[] vertices, Texture tex, Matrix rotation)
{
//The vertexbuffer is full, so we need to flush it before we can continue
if (_Vertices.Count >= CSettings.VertexBufferElements)
@@ -677,7 +475,7 @@ namespace Vocaluxe.Lib.Draw
///
/// Removes all textures from the screen
///
- public void ClearScreen()
+ protected override void _ClearScreen()
{
if (_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0).IsFailure)
CLog.LogError("Failed to clear the backbuffer");
@@ -687,41 +485,35 @@ namespace Vocaluxe.Lib.Draw
/// Copies the current frame into a texture
/// A texture holding the current frame
///
- public CTexture CopyScreen()
+ public CTextureRef CopyScreen()
{
- CTexture texture = _GetNewTexture(_W, _H);
-
+ CD3DTexture tex = _CreateTexture(new Size(_W, _H));
Surface backbufferSurface = _Device.GetBackBuffer(0, 0);
- var tex = new Texture(_Device, texture.W2, texture.H2, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
- Surface textureSurface = tex.GetSurfaceLevel(0);
+ Surface textureSurface = tex.D3DTexture.GetSurfaceLevel(0);
Surface.FromSurface(textureSurface, backbufferSurface, Filter.Default, 0, new Rectangle(0, 0, _W, _H), new Rectangle(0, 0, _W, _H));
backbufferSurface.Dispose();
- lock (_MutexTexture)
- {
- texture.ID = _IDs.Dequeue();
- _D3DTextures.Add(texture.ID, tex);
- return texture;
- }
+ return _GetTextureReference(_W, _H, tex);
}
///
/// Copies the current frame into a texture
///
- /// The texture in which the frame is copied to
- public void CopyScreen(ref CTexture texture)
+ /// The texture in which the frame is copied to
+ public void CopyScreen(ref CTextureRef textureRef)
{
- //Check for actual texture sizes! (W2/H2) as it may be up/downsized compared to OrigSize
- if (!_TextureExists(texture) || texture.W2 != GetScreenWidth() || texture.H2 != GetScreenHeight())
+ CD3DTexture texture;
+ if (!_GetTexture(textureRef, out texture) || texture.DataSize.Width != GetScreenWidth() || texture.DataSize.Height != GetScreenHeight())
{
- RemoveTexture(ref texture);
- texture = CopyScreen();
+ RemoveTexture(ref textureRef);
+ textureRef = CopyScreen();
}
else
{
Surface backbufferSurface = _Device.GetBackBuffer(0, 0);
- Surface textureSurface = _D3DTextures[texture.ID].GetSurfaceLevel(0);
+ Surface textureSurface = texture.D3DTexture.GetSurfaceLevel(0);
Surface.FromSurface(textureSurface, backbufferSurface, Filter.Default, 0);
+ backbufferSurface.Dispose();
}
}
@@ -741,36 +533,12 @@ namespace Vocaluxe.Lib.Draw
}
}
- ///
- /// Draws a line
- ///
- /// The alpha value from 0-255
- /// The red value from 0-255
- /// The red value from 0-255
- /// The red value from 0-255
- /// The width of the line
- /// The start x-value
- /// The start y-value
- /// The end x-value
- /// The end y-value
- public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2)
- {
- var lineVector = new Vector2[] {new Vector2(x1, y1), new Vector2(x2, y2)};
- using (var line = new Line(_Device))
- {
- line.Antialias = true;
- line.Begin();
- line.Draw(lineVector, new Color4((float)a / 255, (float)r / 255, (float)g / 255, (float)b / 255));
- line.End();
- }
- }
-
///
/// Draws a colored rectangle
///
/// The color in which the rectangle will be drawn in
/// The coordinates in a SRectF struct
- public void DrawColor(SColorF color, SRectF rect)
+ public void DrawRect(SColorF color, SRectF rect)
{
DrawTexture(_BlankTexture, rect, color);
}
@@ -782,154 +550,25 @@ namespace Vocaluxe.Lib.Draw
/// The coordinates in a SRectF struct
/// The space between the texture and the reflection
/// The height of the reflection
- public void DrawColorReflection(SColorF color, SRectF rect, float space, float height)
+ public void DrawRectReflection(SColorF color, SRectF rect, float space, float height)
{
- DrawTextureReflection(_BlankTexture, rect, color, rect, space, height);
+ DrawTextureReflection(_BlankTexture, rect, color, space, height);
}
#endregion Basic Draw Methods
#region Textures
-
- #region adding
- ///
- /// Adds a texture and stores it in the VRam
- ///
- /// The texture's filepath
- /// A STexture object containing the added texture
- public CTexture AddTexture(string texturePath)
+ protected override CD3DTexture _CreateTexture(Size dataSize)
{
- if (!File.Exists(texturePath))
- {
- CLog.LogError("Can't find File: " + texturePath);
- return null;
- }
- Bitmap bmp;
- try
- {
- bmp = new Bitmap(texturePath);
- }
- catch (Exception)
- {
- CLog.LogError("Error loading Texture: " + texturePath);
- return null;
- }
- CTexture s;
- try
- {
- s = AddTexture(bmp);
- }
- finally
- {
- bmp.Dispose();
- }
- return s;
+ if (dataSize.Width < 0)
+ return new CD3DTexture(null, dataSize);
+ return new CD3DTexture(_Device, dataSize, _CheckForNextPowerOf2(dataSize.Width), _CheckForNextPowerOf2(dataSize.Height));
}
- ///
- /// Adds a texture and stores it in the Vram
- ///
- /// The Bitmap of which the texure will be created from
- /// A STexture object containing the added texture
- public CTexture AddTexture(Bitmap bmp)
- {
- if (bmp.Height == 0 || bmp.Width == 0)
- return null;
- int maxSize;
- //Apply the right max size
- switch (CConfig.TextureQuality)
- {
- case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
- maxSize = 128;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
- maxSize = 256;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
- maxSize = 512;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
- maxSize = 1024;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
- maxSize = 2048;
- break;
- default:
- maxSize = 512;
- break;
- }
-
- int w = Math.Min(bmp.Width, maxSize);
- int h = Math.Min(bmp.Height, maxSize);
- w = _CheckForNextPowerOf2(w);
- h = _CheckForNextPowerOf2(h);
-
- var texture = new CTexture(bmp.Width, bmp.Height, w, h, true);
-
- Bitmap bmp2 = null;
- byte[] data;
- try
- {
- if (bmp.Width != w || bmp.Height != h)
- {
- //Create a new Bitmap with the new sizes
- bmp2 = new Bitmap(w, h);
- //Scale the texture
- using (Graphics g = Graphics.FromImage(bmp2))
- {
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.SmoothingMode = SmoothingMode.HighQuality;
- g.DrawImage(bmp, new Rectangle(0, 0, bmp2.Width, bmp2.Height));
- }
- bmp = bmp2;
- }
-
- //Fill the new Bitmap with the texture data
- BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
- data = new byte[4 * w * h];
- Marshal.Copy(bmpData.Scan0, data, 0, data.Length);
- bmp.UnlockBits(bmpData);
- }
- finally
- {
- if (bmp2 != null)
- bmp2.Dispose();
- }
-
- return _AddTexture(texture, w, data);
- }
-
- public CTexture AddTexture(int w, int h, byte[] data)
- {
- CTexture texture = _GetNewTexture(w, h);
- return _AddTexture(texture, w, data);
- }
-
- private CTexture _AddTexture(CTexture texture, int w, byte[] data)
- {
- Texture t = _CreateTexture(texture.W2, texture.H2, w, data);
-
- lock (_MutexTexture)
- {
- texture.ID = _IDs.Dequeue();
- _D3DTextures.Add(texture.ID, t);
- }
- return texture;
- }
-
- private Texture _CreateTexture(int textureW, int textureH, int w, byte[] data)
- {
- //Create a new texture in the managed pool, which does not need to be recreated on a lost device
- //because a copy of the texture is hold in the Ram
- var t = new Texture(_Device, textureW, textureH, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
- _WriteDataToTexture(t, w, data);
- return t;
- }
-
- private static void _WriteDataToTexture(Texture t, int w, byte[] data)
+ protected override void _WriteDataToTexture(CD3DTexture texture, byte[] data)
{
//Lock the texture and fill it with the data
- DataRectangle rect = t.LockRectangle(0, LockFlags.Discard);
- int rowWidth = 4 * w;
+ DataRectangle rect = texture.D3DTexture.LockRectangle(0, LockFlags.Discard);
+ int rowWidth = 4 * texture.DataSize.Width;
if (rowWidth == rect.Pitch)
rect.Data.Write(data, 0, data.Length);
else
@@ -941,141 +580,78 @@ namespace Vocaluxe.Lib.Draw
rect.Data.Position = rect.Data.Position - rowWidth + rect.Pitch;
}
}
- t.UnlockRectangle(0);
- }
-
- public CTexture EnqueueTexture(int w, int h, byte[] data)
- {
- CTexture texture = _GetNewTexture(w, h);
-
- lock (_MutexTexture)
- {
- texture.ID = _IDs.Dequeue();
- _D3DTextures.Add(texture.ID, null);
- var queue = new STextureQueue(texture.ID, texture.W2, texture.H2, w, h, data);
- _TexturesToLoad.Enqueue(queue);
- }
- return texture;
- }
-
- private CTexture _GetNewTexture(int w, int h)
- {
- return new CTexture(w, h, _CheckForNextPowerOf2(w), _CheckForNextPowerOf2(h));
- }
- #endregion adding
-
- #region updating
- ///
- /// Updates the data of a texture
- ///
- /// The texture to update
- ///
- ///
- /// A byte array containing the new texture's data
- /// True if succeeded
- public bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
- {
- //Check if texture exists and extend matches
- if (!_TextureExists(texture) || texture.UsedWidth != w || texture.UsedHeight != h)
- return false;
- lock (_MutexTexture)
- {
- _WriteDataToTexture(_D3DTextures[texture.ID], w, data);
- }
- return true;
- }
-
- public bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data)
- {
- if (!UpdateTexture(texture, w, h, data))
- {
- RemoveTexture(ref texture);
- texture = AddTexture(w, h, data);
- }
- return true;
- }
- #endregion updating
-
- ///
- /// Checks if a texture exists
- ///
- /// The texture to check
- /// True if the texture exists
- private bool _TextureExists(CTexture texture)
- {
- lock (_MutexTexture)
- {
- return texture != null && _D3DTextures.ContainsKey(texture.ID);
- }
- }
-
- ///
- /// Removes a texture from the Vram
- ///
- /// The texture to be removed
- public void RemoveTexture(ref CTexture texture)
- {
- if (_TextureExists(texture))
- {
- lock (_MutexTexture)
- {
- _D3DTextures[texture.ID].Dispose();
- _D3DTextures.Remove(texture.ID);
- _IDs.Enqueue(texture.ID);
- }
- }
- texture = null;
+ texture.D3DTexture.UnlockRectangle(0);
}
#region drawing
///
/// Draws a texture
///
- /// The texture to be drawn
- public void DrawTexture(CTexture texture)
- {
- if (texture == null)
- return;
- DrawTexture(texture, texture.Rect, texture.Color);
- }
-
- ///
- /// Draws a texture
- ///
- /// The texture to be drawn
- /// A SRectF struct containing the destination coordinates
- public void DrawTexture(CTexture texture, SRectF rect)
- {
- if (texture == null)
- return;
- DrawTexture(texture, rect, texture.Color);
- }
-
- ///
- /// Draws a texture
- ///
- /// The texture to be drawn
+ /// The texture to be drawn
/// A SRectF struct containing the destination coordinates
/// A SColorF struct containing a color which the texture will be colored in
/// True if the texture should be mirrored
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, bool mirrored = false)
+ public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false)
{
- DrawTexture(texture, rect, color, new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, rect.Z), mirrored);
+ if (rect.W < 1 || rect.H < 1)
+ return;
+
+ CD3DTexture texture;
+ if (!_GetTexture(textureRef, out texture))
+ return;
+
+ //Calculate the position
+ const float x1 = 0;
+ float x2 = texture.WidthRatio;
+ float y1 = 0;
+ float y2 = texture.HeightRatio;
+
+ //Calculate the size
+ float rx1 = rect.X;
+ float rx2 = rect.X + rect.W;
+ float ry1 = rect.Y;
+ float ry2 = rect.Y + rect.H;
+
+ color.A *= CGraphics.GlobalAlpha;
+
+ Color c = color.AsColor();
+
+ if (mirrored)
+ {
+ float tmp = y2;
+ y2 = y1;
+ y1 = tmp;
+ }
+ var vert = new STexturedColoredVertex[4];
+ vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb());
+ vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb());
+ vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
+ vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb());
+ _AddToVertexBuffer(vert, texture.D3DTexture, _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
///
/// Draws a texture
///
- /// The texture to be drawn
+ /// The texture to be drawn
/// A SRectF struct containing the destination coordinates
/// A SColorF struct containing a color which the texture will be colored in
/// A SRectF struct containing which part of the texture should be drawn
/// True if the texture should be mirrored
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
+ public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
{
- if (!_TextureExists(texture))
+ if (Math.Abs(rect.W) < 1 || Math.Abs(rect.H) < 1 || Math.Abs(bounds.H) < 1 || Math.Abs(bounds.W) < 1 ||
+ Math.Abs(color.A) < 0.01)
return;
- if (_D3DTextures[texture.ID] == null)
+
+ if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X)
+ return;
+
+ if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y)
+ return;
+
+ CD3DTexture texture;
+ if (!_GetTexture(textureRef, out texture))
return;
//Calculate the position
@@ -1114,58 +690,35 @@ namespace Vocaluxe.Lib.Draw
if (ry2 > bounds.Y + bounds.H)
ry2 = bounds.Y + bounds.H;
- //Align the pixels because Direct3D expects the pixels to be the left top corner
- rx1 -= 0.5f;
- ry1 -= 0.5f;
- rx2 -= 0.5f;
- ry2 -= 0.5f;
-
color.A *= CGraphics.GlobalAlpha;
- if (color.A > 1)
- color.A = 1;
- if (color.R > 1)
- color.R = 1;
- if (color.G > 1)
- color.G = 1;
- if (color.B > 1)
- color.B = 1;
-
Color c = color.AsColor();
- if (!mirrored)
+ if (mirrored)
{
- var vert = new STexturedColoredVertex[4];
- vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb());
- vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb());
- vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
- vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb());
- _AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
- }
- else
- {
- var vert = new STexturedColoredVertex[4];
- vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y1), c.ToArgb());
- vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, -y2), c.ToArgb());
- vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y2), c.ToArgb());
- vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, -y1), c.ToArgb());
- _AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
+ y1 = -y1;
+ y2 = -y2;
}
+ var vert = new STexturedColoredVertex[4];
+ vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb());
+ vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb());
+ vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
+ vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb());
+ _AddToVertexBuffer(vert, texture.D3DTexture, _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
///
/// Draws a texture
///
- /// The texture to be drawn
+ /// The texture to be drawn
/// A SRectF struct containing the destination coordinates
/// A SColorF struct containing a color which the texture will be colored in
/// A Value ranging from 0 to 1 containing the beginning of the texture
/// A Value ranging from 0 to 1 containing the ending of the texture
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, float begin, float end)
+ public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, float begin, float end)
{
- if (!_TextureExists(texture))
- return;
- if (_D3DTextures[texture.ID] == null)
+ CD3DTexture texture;
+ if (!_GetTexture(textureRef, out texture))
return;
float x1 = 0f + begin * texture.WidthRatio;
@@ -1193,73 +746,39 @@ namespace Vocaluxe.Lib.Draw
vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb());
vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), c.ToArgb());
- _AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
+ _AddToVertexBuffer(vert, texture.D3DTexture, _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
///
/// Draws a reflection of a texture
///
- /// The texture of which a reflection should be drawn
+ /// The texture of which a reflection should be drawn
/// A SRectF struct containing the destination coordinates
/// A SColorF struct containing a color which the texture will be colored in
- /// A SRectF struct containing which part of the texture should be drawn
/// The space between the texture and the reflection
/// The height of the reflection
- public void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float space, float height)
+ public void DrawTextureReflection(CTextureRef textureRef, SRectF rect, SColorF color, float space, float height)
{
- if (!_TextureExists(texture))
- return;
- if (_D3DTextures[texture.ID] == null)
+ CD3DTexture texture;
+ if (!_GetTexture(textureRef, out texture))
return;
- if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(bounds.H) < float.Epsilon || Math.Abs(bounds.W) < float.Epsilon ||
- Math.Abs(color.A) < float.Epsilon || height <= 0f)
+ if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(color.A) < float.Epsilon || height <= 0f)
return;
- if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X)
- return;
-
- if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y)
- return;
-
- if (height > bounds.H)
- height = bounds.H;
-
- float x1 = (bounds.X - rect.X) / rect.W * texture.WidthRatio;
- float x2 = (bounds.X + bounds.W - rect.X) / rect.W * texture.WidthRatio;
- float y1 = (bounds.Y - rect.Y + rect.H - height) / rect.H * texture.HeightRatio;
- float y2 = (bounds.Y + bounds.H - rect.Y) / rect.H * texture.HeightRatio;
-
- if (x1 < 0)
- x1 = 0f;
-
- if (x2 > texture.WidthRatio)
- x2 = texture.WidthRatio;
-
- if (y1 < 0)
- y1 = 0f;
-
- if (y2 > texture.HeightRatio)
- y2 = texture.HeightRatio;
+ if (height > rect.H)
+ height = rect.H;
+ const float x1 = 0;
+ float x2 = texture.WidthRatio;
+ float y1 = (rect.H - height) / rect.H * texture.HeightRatio;
+ float y2 = texture.HeightRatio;
float rx1 = rect.X;
float rx2 = rect.X + rect.W;
float ry1 = rect.Y + rect.H + space;
float ry2 = rect.Y + rect.H + space + height;
- if (rx1 < bounds.X)
- rx1 = bounds.X;
-
- if (rx2 > bounds.X + bounds.W)
- rx2 = bounds.X + bounds.W;
-
- if (ry1 < bounds.Y + space)
- ry1 = bounds.Y + space;
-
- if (ry2 > bounds.Y + bounds.H + space + height)
- ry2 = bounds.Y + bounds.H + space + height;
-
//Align the pixels because Direct3D expects the pixels to be the left top corner
rx1 -= 0.5f;
ry1 -= 0.5f;
@@ -1276,79 +795,35 @@ namespace Vocaluxe.Lib.Draw
vert[1] = new STexturedColoredVertex(new Vector3(rx1, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), transparent.ToArgb());
vert[2] = new STexturedColoredVertex(new Vector3(rx2, -ry2, rect.Z + CGraphics.ZOffset), new Vector2(x2, y1), transparent.ToArgb());
vert[3] = new STexturedColoredVertex(new Vector3(rx2, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x2, y2), c.ToArgb());
- _AddToVertexBuffer(vert, _D3DTextures[texture.ID], _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
+ _AddToVertexBuffer(vert, texture.D3DTexture, _CalculateRotationMatrix(rect.Rotation, rx1, rx2, ry1, ry2));
}
#endregion drawing
- private void _CheckQueue()
- {
- lock (_MutexTexture)
- {
- while (_TexturesToLoad.Count > 0)
- {
- STextureQueue q = _TexturesToLoad.Dequeue();
- Texture t;
- if (_D3DTextures.TryGetValue(q.ID, out t) && t != null)
- continue;
-
- t = _CreateTexture(q.TextureWidth, q.TextureHeight, q.DataWidth, q.Data);
- _D3DTextures[q.ID] = t;
- }
- }
- }
-
- ///
- /// Gets the count of current textures
- ///
- /// The amount of textures
- public int GetTextureCount()
- {
- return _D3DTextures.Count;
- }
#endregion Textures
- #endregion implementation
-
- #region utility
- ///
- /// Calculates the next power of two if the device has the POW2 flag set
- ///
- /// The value of which the next power of two will be calculated
- /// The next power of two
- private int _CheckForNextPowerOf2(int n)
+ private static Matrix _CalculateRotationMatrix(float rot, float rx1, float rx2, float ry1, float ry2)
{
- if (_NonPowerOf2TextureSupported)
- return n;
- if (n < 0)
- throw new ArgumentOutOfRangeException("n", "Must be positive.");
- return (int)Math.Pow(2, Math.Ceiling(Math.Log(n, 2)));
- }
-
- private SlimDX.Matrix _CalculateRotationMatrix(float rot, float rx1, float rx2, float ry1, float ry2)
- {
- SlimDX.Matrix originTranslation = SlimDX.Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
+ Matrix originTranslation = Matrix.Translation(new Vector3(-(float)CSettings.RenderW / 2, (float)CSettings.RenderH / 2, 0));
if (Math.Abs(rot) > float.Epsilon)
{
float rotation = rot * (float)Math.PI / 180;
float centerX = (rx1 + rx2) / 2f;
float centerY = -(ry1 + ry2) / 2f;
- SlimDX.Matrix translationA = SlimDX.Matrix.Translation(-centerX, -centerY, 0);
- SlimDX.Matrix rotationMat = SlimDX.Matrix.RotationZ(-rotation);
- SlimDX.Matrix translationB = SlimDX.Matrix.Translation(centerX, centerY, 0);
+ Matrix translationA = Matrix.Translation(-centerX, -centerY, 0);
+ Matrix rotationMat = Matrix.RotationZ(-rotation);
+ Matrix translationB = Matrix.Translation(centerX, centerY, 0);
//Multiplicate the matrices to get the real world matrix,
//First shift the texture into the center
//Rotate it and shift it back to the origin position
//Apply the originTranslation after
- SlimDX.Matrix result = translationA * rotationMat * translationB * originTranslation;
+ Matrix result = translationA * rotationMat * translationB * originTranslation;
return result;
}
return originTranslation;
}
- #endregion utility
- #region TexturedColoredVertex
private struct STexturedColoredVertex
{
private static VertexDeclaration _Declaration;
@@ -1380,7 +855,15 @@ namespace Vocaluxe.Lib.Draw
return _Declaration;
}
+
+ public static void DisposeDeclaration()
+ {
+ if (_Declaration != null && !_Declaration.Disposed)
+ {
+ _Declaration.Dispose();
+ _Declaration = null;
+ }
+ }
}
- #endregion TexturedColoredVertex
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Draw/CDrawBase.cs b/Vocaluxe/Lib/Draw/CDrawBase.cs
new file mode 100644
index 00000000..3a8eeed2
--- /dev/null
+++ b/Vocaluxe/Lib/Draw/CDrawBase.cs
@@ -0,0 +1,1004 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Vocaluxe.Base;
+using VocaluxeLib;
+using VocaluxeLib.Draw;
+using System.Diagnostics;
+
+namespace Vocaluxe.Lib.Draw
+{
+ ///
+ /// Base class for graphic drivers
+ /// A few notes:
+ /// Writes to textures (TTextureType) should only be done in the main thread
+ /// Writes to the RefCount of existing textures should only be done in the main thread and guarded by _Textures lock
+ ///
+ ///
+ abstract class CDrawBase where TTextureType : CTextureBase, IDisposable
+ {
+ private enum EQueueAction
+ {
+ Add,
+ Update,
+ Delete
+ }
+
+ private struct STextureQueue
+ {
+ public readonly object TextureOrRef;
+ ///
+ /// Only valid if Data is byte[]
+ ///
+ public readonly Size DataSize;
+ public readonly object Data;
+ public readonly EQueueAction Action;
+
+ ///
+ /// Creates a new Queue entry
+ ///
+ /// TTextureType or CTextureRef
+ ///
+ /// Texture data as a bitmap
+ public STextureQueue(object textureOrRef, EQueueAction action, Bitmap data)
+ {
+ TextureOrRef = textureOrRef;
+ Action = action;
+ Data = data;
+ DataSize = new Size();
+ }
+
+ ///
+ /// Creates a new Queue entry
+ ///
+ /// TTextureType or CTextureRef
+ ///
+ /// Size of data
+ /// Texture data
+ public STextureQueue(object textureOrRef, EQueueAction action, Size dataSize, byte[] data)
+ {
+ TextureOrRef = textureOrRef;
+ Action = action;
+ DataSize = dataSize;
+ Data = data;
+ }
+ }
+
+ private struct STextureCacheEntry
+ {
+ public TTextureType Texture;
+ ///
+ /// Size of original image (e.g. of bmp)
+ ///
+ public Size OrigSize;
+ }
+
+ protected bool _NonPowerOf2TextureSupported;
+ protected bool _Fullscreen;
+
+ protected bool _Run;
+
+ protected readonly CKeys _Keys = new CKeys();
+ protected readonly CMouse _Mouse = new CMouse();
+
+ private int _NextID;
+ private readonly Object _MutexID = new object();
+
+ // Maps texture IDs to textures. Multiple IDs can be mapped to one texture (-->texture.RefCount>1)
+ private readonly Dictionary _Textures = new Dictionary();
+ // Maps texturePaths to textures. Texture may have already been disposed (RefCount<=0)
+ private readonly Dictionary _TextureCache = new Dictionary();
+ private readonly Queue _TextureQueue = new Queue();
+ private readonly Dictionary> _BitmapsLoading = new Dictionary>();
+ private int _TextureCount;
+
+ protected int _H;
+ protected int _W;
+ protected int _Y;
+ protected int _X;
+
+ protected int _BorderLeft;
+ protected int _BorderRight;
+ protected int _BorderTop;
+ protected int _BorderBottom;
+ protected EGeneralAlignment _CurrentAlignment = EGeneralAlignment.Middle;
+
+ private int _MainThreadID;
+
+ protected abstract void _ClearScreen();
+ protected abstract void _AdjustNewBorders();
+ protected abstract void _LeaveFullScreen();
+
+ protected abstract void _OnAfterDraw();
+
+ protected abstract void _OnBeforeDraw();
+
+ protected abstract void _DoResize();
+
+ protected abstract void _EnterFullScreen();
+
+ public virtual bool Init()
+ {
+ _MainThreadID = Thread.CurrentThread.ManagedThreadId;
+ return true;
+ }
+
+ ///
+ /// This makes sure, the function is called from within the main thread
+ ///
+ private void _EnsureMainThread()
+ {
+ Debug.Assert(_MainThreadID == Thread.CurrentThread.ManagedThreadId);
+ }
+
+ public virtual void Unload()
+ {
+ _EnsureMainThread();
+ lock (_Textures)
+ {
+ //Dispose all textures
+ foreach (TTextureType texture in _Textures.Values)
+ {
+ if (texture != null && --texture.RefCount <= 0)
+ texture.Dispose();
+ }
+ _Textures.Clear();
+ _TextureCache.Clear();
+ }
+ }
+
+ protected void _AdjustAspect(bool reverse)
+ {
+ if (_W / (float)_H > CSettings.GetRenderAspect())
+ {
+ _Y = 0;
+ //The windows width is too big
+ int old = _W;
+ _W = (int)Math.Round(_H * CSettings.GetRenderAspect());
+ int diff = old - _W;
+ switch (_CurrentAlignment)
+ {
+ case EGeneralAlignment.Start:
+ _X = 0;
+ break;
+ case EGeneralAlignment.Middle:
+ _X = diff / 2;
+ break;
+ case EGeneralAlignment.End:
+ _X = diff;
+ break;
+ }
+ }
+ else
+ {
+ _X = 0;
+ //The windows height is too big
+ int old = _H;
+ _H = (int)Math.Round(_W / CSettings.GetRenderAspect());
+ int diff = old - _H;
+ switch (_CurrentAlignment)
+ {
+ case EGeneralAlignment.Start:
+ _Y = reverse ? diff : 0;
+ break;
+ case EGeneralAlignment.Middle:
+ _Y = diff / 2;
+ break;
+ case EGeneralAlignment.End:
+ _Y = reverse ? 0 : diff;
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Calculates the next power of two if the device has the POW2 flag set
+ ///
+ /// The value of which the next power of two will be calculated
+ /// The next power of two
+ protected int _CheckForNextPowerOf2(int n)
+ {
+ if (_NonPowerOf2TextureSupported)
+ return n;
+ if (n < 0)
+ throw new ArgumentOutOfRangeException("n", "Must be positive.");
+ return (int)Math.Pow(2, Math.Ceiling(Math.Log(n, 2)));
+ }
+
+ #region Textures
+
+ #region private/protected
+ ///
+ /// Returns the maximum area allowed for a texture based on the current quality
+ ///
+ ///
+ private static int _GetMaxTextureArea()
+ {
+ switch (CConfig.TextureQuality)
+ {
+ case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
+ return 128 * 128;
+ case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
+ return 256 * 128;
+ case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
+ return 512 * 256;
+ case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
+ return 1024 * 512;
+ case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
+ return CSettings.RenderW * CSettings.RenderH;
+ default:
+ throw new ArgumentException();
+ }
+ }
+
+ ///
+ /// Returns true if a texture with the given size needs to be resized
+ ///
+ ///
+ ///
+ private static bool _RequiresResize(Size size)
+ {
+ int maxArea = _GetMaxTextureArea();
+ int curArea = size.Width * size.Height;
+ return curArea > maxArea;
+ }
+
+ ///
+ /// Calculates the size for a new texture using the quality and smart values for rescaling
+ ///
+ /// New size for the texture
+ private Size _GetNewTextureSize(Size size)
+ {
+ Debug.Assert(size.Width > 0 && size.Height > 0);
+ int maxArea = _GetMaxTextureArea();
+ int curArea = size.Width * size.Height;
+ if (curArea <= maxArea)
+ return size;
+ Debug.Assert(_RequiresResize(size));
+ double factor = Math.Sqrt((double)maxArea / curArea);
+ Size newSize = new Size((int)(size.Width * factor), (int)(size.Height * factor));
+ if (!_NonPowerOf2TextureSupported)
+ {
+ if (size.Width < size.Height)
+ {
+ newSize.Width = _CheckForNextPowerOf2(newSize.Width);
+ newSize.Height = _CheckForNextPowerOf2(maxArea / newSize.Width);
+ if (newSize.Width * newSize.Height > maxArea)
+ newSize.Height /= 2;
+ }
+ else
+ {
+ newSize.Height = _CheckForNextPowerOf2(newSize.Height);
+ newSize.Width = _CheckForNextPowerOf2(maxArea / newSize.Height);
+ if (newSize.Width * newSize.Height > maxArea)
+ newSize.Width /= 2;
+ }
+ }
+ Debug.Assert(newSize.Width * newSize.Height <= maxArea);
+ return newSize;
+ }
+
+ protected abstract void _WriteDataToTexture(TTextureType texture, byte[] data);
+
+ protected virtual void _WriteDataToTexture(TTextureType texture, IntPtr data)
+ {
+ byte[] dataArray = new byte[4 * texture.DataSize.Width * texture.DataSize.Height];
+ Marshal.Copy(data, dataArray, 0, dataArray.Length);
+ _WriteDataToTexture(texture, dataArray);
+ }
+
+ ///
+ /// Factory method to create a texture of the actual type
+ /// The implementer has to create an invalid texture (IsLoaded=false) if dataSize=(-1,-1)
+ ///
+ ///
+ ///
+ protected abstract TTextureType _CreateTexture(Size dataSize);
+
+ ///
+ /// Creates the texture specified by the reference and fills it with the given data
+ ///
+ ///
+ ///
+ ///
+ private TTextureType _CreateAndFillTexture(Size dataSize, byte[] data)
+ {
+ TTextureType texture = _CreateTexture(dataSize);
+ _WriteDataToTexture(texture, data);
+ return texture;
+ }
+
+ ///
+ /// Writes the specified bitmap to the texture, creating it if null
+ /// Also does the resizing if required
+ ///
+ ///
+ ///
+ private void _WriteBitmapToTexture(ref TTextureType texture, Bitmap bmp)
+ {
+ Bitmap bmp2 = null;
+ try
+ {
+ Size size = _GetNewTextureSize(bmp.GetSize());
+ if (!size.Equals(bmp.GetSize()))
+ {
+ bmp2 = bmp.Resize(size);
+ bmp = bmp2;
+ }
+
+ //Fill the new Bitmap with the texture data
+ BitmapData bmpData = bmp.LockBits(bmp.GetRect(), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ if (texture == null)
+ texture = _CreateTexture(size);
+ else
+ texture.DataSize = size;
+ _WriteDataToTexture(texture, bmpData.Scan0);
+ bmp.UnlockBits(bmpData);
+ }
+ finally
+ {
+ if (bmp2 != null)
+ bmp2.Dispose();
+ }
+ }
+
+ ///
+ /// Adds the texture to the cache
+ /// Asserts that the cache entry does not exist yet. So make Get/Add cache atomic through use of _TextureCache lock!
+ /// Thread safe
+ ///
+ ///
+ ///
+ ///
+ private void _AddToCache(TTextureType texture, Size origSize, string texturePath)
+ {
+ if (String.IsNullOrEmpty(texturePath))
+ return;
+ Debug.Assert(texture != null);
+ lock (_Textures)
+ {
+ Debug.Assert(!_TextureCache.ContainsKey(texturePath));
+ texture.TexturePath = texturePath;
+ STextureCacheEntry cacheEntry = new STextureCacheEntry {OrigSize = origSize, Texture = texture};
+ _TextureCache.Add(texturePath, cacheEntry);
+ }
+ }
+
+ ///
+ /// Gets a new texture reference from the cache
+ /// Thread safe
+ ///
+ ///
+ /// Task that loads the texture or null if not loading
+ ///
+ private CTextureRef _GetFromCache(string texturePath, out Task loader)
+ {
+ loader = null;
+ if (String.IsNullOrEmpty(texturePath))
+ return null;
+ lock (_TextureCache)
+ lock (_Textures)
+ {
+ STextureCacheEntry cacheEntry;
+ if (_TextureCache.TryGetValue(texturePath, out cacheEntry))
+ {
+ if (cacheEntry.Texture.RefCount <= 0)
+ _TextureCache.Remove(texturePath);
+ else
+ {
+ if (cacheEntry.OrigSize.Width < 0)
+ {
+ lock (_BitmapsLoading)
+ {
+ loader = _BitmapsLoading[texturePath];
+ }
+ }
+ return _GetTextureReference(cacheEntry.OrigSize, cacheEntry.Texture);
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Method used to add a texture to the texture list and return a TextureRef to it
+ /// If you are using an already used texture, you have to hold the _Textures lock or call from the main thread!
+ /// Thread safe
+ ///
+ ///
+ ///
+ ///
+ protected CTextureRef _GetTextureReference(Size origSize, TTextureType texture)
+ {
+ Debug.Assert(origSize.Width > 0 && origSize.Height > 0);
+ Debug.Assert(texture != null);
+ int id;
+ lock (_MutexID)
+ {
+ id = _NextID++;
+ }
+ CTextureRef textureRef = new CTextureRef(id, origSize);
+ lock (_Textures)
+ {
+ if (texture.RefCount == 0)
+ _TextureCount++;
+ texture.RefCount++;
+ _Textures.Add(id, texture);
+ }
+ return textureRef;
+ }
+
+ ///
+ /// Method used to add a texture to the texture list and return a TextureRef to it
+ /// Thread safe
+ /// Convenience method
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected CTextureRef _GetTextureReference(int origWidth, int origHeight, TTextureType texture)
+ {
+ return _GetTextureReference(new Size(origWidth, origHeight), texture);
+ }
+
+ private static bool _IsTextureUsable(TTextureType texture, int dataWidth, int dataHeight)
+ {
+ if (texture == null)
+ return false;
+ if (texture.DataSize.Width != dataWidth || texture.DataSize.Height != dataHeight)
+ {
+ if (texture.W2 > dataWidth || texture.H2 > dataHeight)
+ return false; // Texture memory to small
+ if (texture.W2 * 0.9 < dataWidth || texture.H2 * 0.9 < dataHeight)
+ return false; // Texture memory to big
+ }
+ return true;
+ }
+
+ protected bool _GetTexture(CTextureRef textureRef, out TTextureType texture, bool checkDrawable = true)
+ {
+ if (textureRef == null)
+ {
+ texture = null;
+ return false;
+ }
+ lock (_Textures)
+ {
+ return _Textures.TryGetValue(textureRef.ID, out texture) && (!checkDrawable || texture.IsLoaded);
+ }
+ }
+
+ ///
+ /// Decreases the RefCount of a texture and disposes it if necessary
+ ///
+ ///
+ private void _DisposeTexture(TTextureType texture)
+ {
+ _EnsureMainThread();
+ lock (_Textures)
+ {
+ if (texture != null && --texture.RefCount <= 0)
+ {
+ if (texture.TexturePath != null)
+ _TextureCache.Remove(texture.TexturePath);
+ texture.Dispose();
+ _TextureCount--;
+ }
+ }
+ }
+
+ private void _CheckQueue()
+ {
+ _EnsureMainThread();
+ lock (_TextureQueue)
+ {
+ while (_TextureQueue.Count > 0)
+ {
+ STextureQueue q = _TextureQueue.Dequeue();
+
+ if (q.Action == EQueueAction.Add)
+ {
+ TTextureType oldTexture = q.TextureOrRef as TTextureType;
+ Debug.Assert(oldTexture != null, "Queued type is wrong");
+ Debug.Assert(!oldTexture.IsLoaded);
+ if (oldTexture.RefCount <= 0)
+ continue;
+ TTextureType texture = null;
+ // ReSharper disable CanBeReplacedWithTryCastAndCheckForNull
+ if (q.Data is Bitmap)
+ _WriteBitmapToTexture(ref texture, (Bitmap)q.Data);
+ else if (q.Data is byte[])
+ texture = _CreateAndFillTexture(q.DataSize, (byte[])q.Data);
+ else
+ throw new ArgumentException("q.Data is of invalid type");
+ // ReSharper restore CanBeReplacedWithTryCastAndCheckForNull
+ _MergeTextures(oldTexture, texture);
+ }
+ else
+ {
+ CTextureRef textureRef = q.TextureOrRef as CTextureRef;
+ Debug.Assert(textureRef != null, "Queued type is wrong");
+ if (!_Textures.ContainsKey(textureRef.ID))
+ continue;
+ if (q.Action == EQueueAction.Update)
+ {
+ // ReSharper disable CanBeReplacedWithTryCastAndCheckForNull
+ if (q.Data is Bitmap)
+ UpdateTexture(textureRef, (Bitmap)q.Data);
+ else if (q.Data is byte[])
+ UpdateTexture(textureRef, q.DataSize.Width, q.DataSize.Height, (byte[])q.Data);
+ else
+ throw new ArgumentException("q.Data is of invalid type");
+ // ReSharper restore CanBeReplacedWithTryCastAndCheckForNull
+ }
+ else if (q.Action == EQueueAction.Delete)
+ RemoveTexture(ref textureRef);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Replaces one oldTexture by newTexture summing the refCounts. Also disposes oldTexture
+ ///
+ ///
+ ///
+ private void _MergeTextures(TTextureType oldTexture, TTextureType newTexture)
+ {
+ _EnsureMainThread();
+ Debug.Assert(oldTexture.RefCount > 0);
+ lock (_Textures)
+ {
+ newTexture.RefCount += oldTexture.RefCount;
+ IEnumerable oldKeys = _Textures.Where(pair => pair.Value == oldTexture).Select(pair => pair.Key).ToArray();
+ foreach (int key in oldKeys)
+ _Textures[key] = newTexture;
+ if (!String.IsNullOrEmpty(oldTexture.TexturePath))
+ {
+ newTexture.TexturePath = oldTexture.TexturePath;
+ STextureCacheEntry cacheEntry;
+ if (_TextureCache.TryGetValue(newTexture.TexturePath, out cacheEntry))
+ {
+ cacheEntry.Texture = newTexture;
+ _TextureCache[newTexture.TexturePath] = cacheEntry;
+ }
+ }
+ oldTexture.Dispose();
+ }
+ }
+ #endregion private/protected
+
+ ///
+ /// Adds a texture and stores it in the VRam
+ ///
+ /// The texture's filepath
+ /// A STexture object containing the added texture
+ public CTextureRef AddTexture(string texturePath)
+ {
+ _EnsureMainThread();
+ CTextureRef textureRef;
+ Task loader;
+ lock (_TextureCache)
+ {
+ textureRef = _GetFromCache(texturePath, out loader);
+ }
+ if (textureRef != null)
+ {
+ if (loader != null)
+ textureRef.OrigSize = loader.Result;
+ Debug.Assert(textureRef.OrigSize.Width > 0);
+ return textureRef;
+ }
+
+ Bitmap bmp = CHelper.LoadBitmap(texturePath);
+ if (bmp == null)
+ return null;
+ try
+ {
+ textureRef = AddTexture(bmp, texturePath);
+ }
+ finally
+ {
+ bmp.Dispose();
+ }
+ return textureRef;
+ }
+
+ public CTextureRef AddTexture(Bitmap bmp)
+ {
+ _EnsureMainThread();
+ return AddTexture(bmp, null);
+ }
+
+ ///
+ /// Adds a texture and stores it in the Vram
+ ///
+ /// The Bitmap of which the texure will be created from
+ ///
+ /// A reference to the texture
+ public CTextureRef AddTexture(Bitmap bmp, string texturePath)
+ {
+ _EnsureMainThread();
+ if (bmp.Height == 0 || bmp.Width == 0)
+ return null;
+
+ CTextureRef textureRef;
+ Size origSize = bmp.GetSize();
+ TTextureType texture = null;
+ Task loader;
+ // Make the Get/Add Cache methods atomic
+ lock (_TextureCache)
+ {
+ textureRef = _GetFromCache(texturePath, out loader);
+ if (textureRef == null)
+ {
+ _WriteBitmapToTexture(ref texture, bmp);
+
+ _AddToCache(texture, origSize, texturePath);
+ }
+ }
+ if (textureRef == null)
+ textureRef = _GetTextureReference(origSize, texture);
+ else if (loader != null)
+ textureRef.OrigSize = loader.Result;
+ Debug.Assert(textureRef.OrigSize.Width > 0);
+ return textureRef;
+ }
+
+ public CTextureRef AddTexture(int w, int h, byte[] data)
+ {
+ _EnsureMainThread();
+ TTextureType texture = _CreateAndFillTexture(new Size(w, h), data);
+ return _GetTextureReference(w, h, texture);
+ }
+
+ public CTextureRef EnqueueTexture(int w, int h, byte[] data)
+ {
+ lock (_TextureQueue)
+ {
+ TTextureType texture = _CreateTexture(new Size(-1, -1));
+ CTextureRef textureRef = _GetTextureReference(w, h, texture);
+ _TextureQueue.Enqueue(new STextureQueue(texture, EQueueAction.Add, new Size(w, h), data));
+ return textureRef;
+ }
+ }
+
+ ///
+ /// Enqueues a bitmap to add or update the texture
+ ///
+ /// TTextureType (Add) or CTextureRef(Update)
+ ///
+ ///
+ /// True if resizing should be done in an extra thread
+ private void _EnqueueTextureAddOrUpdate(Object texture, Bitmap bmp, EQueueAction action, bool asyncResize)
+ {
+ Debug.Assert(action == EQueueAction.Add || action == EQueueAction.Update);
+ Debug.Assert(action != EQueueAction.Add || texture is TTextureType);
+ Debug.Assert(action != EQueueAction.Update || texture is CTextureRef);
+ if (_RequiresResize(bmp.GetSize()))
+ {
+ if (asyncResize)
+ Task.Factory.StartNew(() => _ResizeTextureAndEnqueue(texture, bmp, action));
+ else
+ _ResizeTextureAndEnqueue(texture, bmp, action);
+ }
+ else
+ {
+ lock (_TextureQueue)
+ {
+ _TextureQueue.Enqueue(new STextureQueue(texture, action, bmp));
+ }
+ }
+ }
+
+ ///
+ /// Helper function to resize a bitmap and enqueue it
+ ///
+ ///
+ ///
+ ///
+ private void _ResizeTextureAndEnqueue(object texture, Bitmap bmp, EQueueAction action)
+ {
+ Bitmap bmp2 = bmp.Resize(_GetNewTextureSize(bmp.Size));
+ bmp.Dispose();
+ lock (_TextureQueue)
+ {
+ _TextureQueue.Enqueue(new STextureQueue(texture, action, bmp2));
+ }
+ }
+
+ public CTextureRef EnqueueTexture(Bitmap bmp)
+ {
+ TTextureType texture = _CreateTexture(new Size(-1, -1));
+ CTextureRef textureRef = _GetTextureReference(bmp.GetSize(), texture);
+ _EnqueueTextureAddOrUpdate(texture, bmp, EQueueAction.Add, true);
+
+ return textureRef;
+ }
+
+ public CTextureRef EnqueueTexture(String filePath)
+ {
+ // 3 important scenarios: (+ means after, || means in parallel)
+ // 1) EnqueueTexture(fileA) (+ or ||) EnqueueTexture(fileA) --> No block on 2nd call and same texture returned
+ // 2) EnqueueTexture(fileA) + AddTexture(fileA) before texture is loaded --> Wait in AddTexture for this to finish
+ // 3) a) AddTexture(fileA) || b) EnqueueTexture(fileA) with a)getFromCache + b)getFromCache + a)addToCache + b)addToCache --> Only keep one copy
+ // All solved with atomic get/add cache and _WaitForTextureLoaded
+
+ CTextureRef textureRef;
+ TTextureType texture = null;
+ Task loader;
+ // Make Get/Add cache atomic
+ lock (_TextureCache)
+ {
+ textureRef = _GetFromCache(filePath, out loader);
+ if (textureRef == null)
+ {
+ Debug.Assert(loader == null);
+ Size invalidSize = new Size(-1, -1);
+ texture = _CreateTexture(invalidSize);
+ // This cache entry has to be updated once the real origSize is available
+ _AddToCache(texture, invalidSize, filePath);
+ textureRef = _GetTextureReference(invalidSize, texture);
+ // Add the loader to the dictionary in the same lock as the add cache call
+ // Avoids that we get a cache entry in AddTexture but no Task
+ loader = new Task(() => _LoadAndEnqueueBitmap(filePath, textureRef, texture));
+ lock (_BitmapsLoading)
+ {
+ _BitmapsLoading.Add(filePath, loader);
+ }
+ }
+ }
+
+ if (texture == null)
+ {
+ // Found in cache
+ CTextureRef tmp = textureRef; // Workaround for implicitly captured closure warning (false positive)
+ if (loader != null)
+ Task.Factory.StartNew(() => tmp.OrigSize = loader.Result);
+ return textureRef;
+ }
+
+ Debug.Assert(loader != null);
+ Debug.Assert(texture != null);
+ loader.Start();
+ return textureRef;
+ }
+
+ ///
+ /// Helper function for loading a bitmap in a task
+ ///
+ ///
+ ///
+ ///
+ ///
+ private Size _LoadAndEnqueueBitmap(string filePath, CTextureRef textureRef, TTextureType texture)
+ {
+ Bitmap bmp = CHelper.LoadBitmap(filePath);
+ if (bmp == null)
+ {
+ RemoveTexture(ref textureRef); // Done asynchonously in the function
+ lock (_Textures)
+ {
+ _TextureCache.Remove(filePath);
+ lock (_BitmapsLoading)
+ {
+ _BitmapsLoading.Remove(filePath);
+ }
+ }
+ return new Size(-1, -1);
+ }
+ Size origSize = bmp.GetSize();
+ textureRef.OrigSize = origSize;
+ // Update cache, use the same lock as in add/get cache methods
+ lock (_Textures)
+ {
+ STextureCacheEntry cacheEntry;
+ if (_TextureCache.TryGetValue(filePath, out cacheEntry))
+ {
+ cacheEntry.OrigSize = origSize;
+ _TextureCache[filePath] = cacheEntry;
+ }
+ lock (_BitmapsLoading)
+ {
+ _BitmapsLoading.Remove(filePath);
+ }
+ }
+ _EnqueueTextureAddOrUpdate(texture, bmp, EQueueAction.Add, false);
+ return origSize;
+ }
+
+ public void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp)
+ {
+ _EnqueueTextureAddOrUpdate(textureRef, bmp, EQueueAction.Update, true);
+ }
+
+ ///
+ /// Updates the data of a texture
+ ///
+ /// The texture to update
+ ///
+ ///
+ /// A byte array containing the new texture's data
+ /// True if succeeded
+ public void UpdateTexture(CTextureRef textureRef, int w, int h, byte[] data)
+ {
+ _EnsureMainThread();
+ TTextureType texture;
+ if (!_GetTexture(textureRef, out texture, false))
+ return;
+ bool reuseTexture = _IsTextureUsable(texture, w, h);
+ if (reuseTexture && texture.RefCount == 1)
+ {
+ texture.DataSize = new Size(w, h);
+ _WriteDataToTexture(texture, data);
+ }
+ else
+ {
+ _DisposeTexture(texture);
+ texture = _CreateAndFillTexture(new Size(w, h), data);
+ texture.RefCount = 1;
+ _Textures[textureRef.ID] = texture;
+ }
+ }
+
+ public void UpdateTexture(CTextureRef textureRef, Bitmap bmp)
+ {
+ _EnsureMainThread();
+ TTextureType texture;
+ if (!_GetTexture(textureRef, out texture, false))
+ return;
+ bool reuseTexture = _IsTextureUsable(texture, bmp.Width, bmp.Height);
+ if (reuseTexture && texture.RefCount == 1)
+ _WriteBitmapToTexture(ref texture, bmp);
+ else
+ {
+ _DisposeTexture(texture);
+ texture = null;
+ _WriteBitmapToTexture(ref texture, bmp);
+ texture.RefCount = 1;
+ _Textures[textureRef.ID] = texture;
+ }
+ }
+
+ public CTextureRef CopyTexture(CTextureRef textureRef)
+ {
+ _EnsureMainThread();
+ TTextureType texture;
+ if (!_GetTexture(textureRef, out texture, false))
+ return null;
+ // If bitmap is not yet loaded, wait for it
+ if (!String.IsNullOrEmpty(texture.TexturePath))
+ {
+ Task loader;
+ lock (_BitmapsLoading)
+ {
+ _BitmapsLoading.TryGetValue(texture.TexturePath, out loader);
+ }
+ if (loader != null)
+ textureRef.OrigSize = loader.Result;
+ }
+ Debug.Assert(textureRef.OrigSize.Width > 0);
+ return _GetTextureReference(textureRef.OrigSize, texture);
+ }
+
+ ///
+ /// Removes a texture from the Vram
+ ///
+ /// The texture to be removed
+ public void RemoveTexture(ref CTextureRef textureRef)
+ {
+ if (textureRef == null)
+ return;
+ if (textureRef.ID > 0)
+ {
+ if (_MainThreadID != Thread.CurrentThread.ManagedThreadId)
+ {
+ lock (_TextureQueue)
+ {
+ _TextureQueue.Enqueue(new STextureQueue(textureRef, EQueueAction.Delete, null));
+ }
+ textureRef = null;
+ return;
+ }
+ lock (_Textures)
+ {
+ TTextureType t;
+ if (_Textures.TryGetValue(textureRef.ID, out t))
+ {
+ _DisposeTexture(t);
+ _Textures.Remove(textureRef.ID);
+ }
+ textureRef.SetRemoved();
+ }
+ }
+ textureRef = null;
+ }
+
+ public int GetTextureCount()
+ {
+ return _TextureCount;
+ }
+ #endregion
+
+ // Resharper doesn't get that this is used -.-
+ // ReSharper disable UnusedMemberHiearchy.Global
+ ///
+ /// Starts the rendering
+ ///
+ public virtual void MainLoop()
+ {
+ // ReSharper restore UnusedMemberHiearchy.Global
+ _EnsureMainThread();
+ _Run = true;
+
+ _Fullscreen = false;
+ if (CConfig.FullScreen == EOffOn.TR_CONFIG_ON)
+ _EnterFullScreen();
+ else
+ _DoResize(); //Resize window if aspect ratio is incorrect
+
+ while (_Run)
+ {
+ _CheckQueue();
+
+ //We want to begin drawing
+ _OnBeforeDraw();
+
+ //Clear the previous Frame
+ _ClearScreen();
+ if (!CGraphics.Draw())
+ _Run = false;
+ _OnAfterDraw();
+
+ if (!CGraphics.UpdateGameLogic(_Keys, _Mouse))
+ _Run = false;
+
+ //Apply fullscreen mode
+ if ((CConfig.FullScreen == EOffOn.TR_CONFIG_ON) != _Fullscreen)
+ _ToggleFullScreen();
+
+ //Apply border changes
+ if (_BorderLeft != CConfig.BorderLeft || _BorderRight != CConfig.BorderRight || _BorderTop != CConfig.BorderTop || _BorderBottom != CConfig.BorderBottom)
+ {
+ _BorderLeft = CConfig.BorderLeft;
+ _BorderRight = CConfig.BorderRight;
+ _BorderTop = CConfig.BorderTop;
+ _BorderBottom = CConfig.BorderBottom;
+
+ _AdjustNewBorders();
+ }
+
+ if (_CurrentAlignment != CConfig.ScreenAlignment)
+ _DoResize();
+
+ if (CConfig.VSync == EOffOn.TR_CONFIG_OFF)
+ {
+ if (CTime.IsRunning())
+ {
+ int delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds());
+
+ if (delay >= 1 && delay < 500)
+ Thread.Sleep(delay);
+ }
+ }
+ //Calculate the FPS Rate and restart the timer after a frame
+ CTime.CalculateFPS();
+ CTime.Restart();
+ }
+ }
+
+ private void _ToggleFullScreen()
+ {
+ if (!_Fullscreen)
+ _EnterFullScreen();
+ else
+ _LeaveFullScreen();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs
new file mode 100644
index 00000000..8ac494e8
--- /dev/null
+++ b/Vocaluxe/Lib/Draw/CDrawBaseWindows.cs
@@ -0,0 +1,198 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using Vocaluxe.Base;
+
+namespace Vocaluxe.Lib.Draw
+{
+ public delegate bool MessageEventHandler(ref Message m);
+
+ public interface IFormHook
+ {
+ MessageEventHandler OnMessage { set; }
+ }
+
+ abstract class CDrawBaseWindows : CDrawBase where TTextureType : CTextureBase, IDisposable
+ {
+ private struct SClientRect
+ {
+ public Point Location;
+ public int Width;
+ public int Height;
+ }
+
+ protected Form _Form;
+ private SClientRect _Restore;
+ protected Size _SizeBeforeMinimize;
+
+ public override void Unload()
+ {
+ base.Unload();
+ try
+ {
+ _Form.Close();
+ }
+ catch {}
+ }
+
+ protected void _CenterToScreen()
+ {
+ Screen screen = Screen.FromControl(_Form);
+ _Form.Location = new Point((screen.WorkingArea.Width - _Form.Width) / 2,
+ (screen.WorkingArea.Height - _Form.Height) / 2);
+ }
+
+ private static bool _OnMessageAvoidScreenOff(ref Message m)
+ {
+ switch (m.Msg)
+ {
+ case 0x112: // WM_SYSCOMMAND
+ switch ((int)m.WParam & 0xFFF0)
+ {
+ case 0xF100: // SC_KEYMENU
+ m.Result = IntPtr.Zero;
+ return false;
+ case 0xF140: // SC_SCREENSAVER
+ case 0xF170: // SC_MONITORPOWER
+ return false;
+ }
+ break;
+ }
+ return true;
+ }
+
+ protected override void _EnterFullScreen()
+ {
+ Debug.Assert(!_Fullscreen);
+ _Fullscreen = true;
+
+ _Restore.Location = _Form.Location;
+ _Restore.Width = _Form.Width;
+ _Restore.Height = _Form.Height;
+
+ _Form.FormBorderStyle = FormBorderStyle.None;
+
+ Screen screen = Screen.FromControl(_Form);
+ _Form.DesktopBounds = new Rectangle(screen.Bounds.Location, new Size(screen.Bounds.Width, screen.Bounds.Height));
+
+ if (_Form.WindowState == FormWindowState.Maximized)
+ {
+ _Form.WindowState = FormWindowState.Normal;
+ _DoResize();
+ _Form.WindowState = FormWindowState.Maximized;
+ }
+ else
+ _DoResize();
+ }
+
+ protected override void _LeaveFullScreen()
+ {
+ Debug.Assert(_Fullscreen);
+ _Fullscreen = false;
+
+ _Form.FormBorderStyle = FormBorderStyle.Sizable;
+ _Form.DesktopBounds = new Rectangle(_Restore.Location, new Size(_Restore.Width, _Restore.Height));
+ }
+
+ #region form event handlers
+ private void _OnClose(object sender, CancelEventArgs e)
+ {
+ _Run = false;
+ }
+
+ private void _OnLoad(object sender, EventArgs e)
+ {
+ _ClearScreen();
+ }
+
+ protected virtual void _OnResize(object sender, EventArgs e)
+ {
+ _DoResize();
+ }
+
+ #region mouse event handlers
+ protected void _OnMouseMove(object sender, MouseEventArgs e)
+ {
+ _Mouse.MouseMove(e);
+ }
+
+ protected void _OnMouseWheel(object sender, MouseEventArgs e)
+ {
+ _Mouse.MouseWheel(e);
+ }
+
+ protected void _OnMouseDown(object sender, MouseEventArgs e)
+ {
+ _Mouse.MouseDown(e);
+ }
+
+ protected void _OnMouseUp(object sender, MouseEventArgs e)
+ {
+ _Mouse.MouseUp(e);
+ }
+
+ protected void _OnMouseLeave(object sender, EventArgs e)
+ {
+ _Mouse.Visible = false;
+ Cursor.Show();
+ }
+
+ protected void _OnMouseEnter(object sender, EventArgs e)
+ {
+ Cursor.Hide();
+ _Mouse.Visible = true;
+ }
+ #endregion
+
+ #region keyboard event handlers
+ protected void _OnPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
+ {
+ _OnKeyDown(sender, new KeyEventArgs(e.KeyData));
+ }
+
+ protected void _OnKeyDown(object sender, KeyEventArgs e)
+ {
+ _Keys.KeyDown(e);
+ }
+
+ protected void _OnKeyPress(object sender, KeyPressEventArgs e)
+ {
+ _Keys.KeyPress(e);
+ }
+
+ protected void _OnKeyUp(object sender, KeyEventArgs e)
+ {
+ _Keys.KeyUp(e);
+ }
+ #endregion keyboard event handlers
+
+ #endregion
+
+ public override bool Init()
+ {
+ if (!base.Init())
+ return false;
+ _Form.Icon = new Icon(Path.Combine(CSettings.ProgramFolder, CSettings.FileNameIcon));
+ _Form.Text = CSettings.GetFullVersionText();
+ ((IFormHook)_Form).OnMessage = _OnMessageAvoidScreenOff;
+ _Form.Closing += _OnClose;
+ _Form.Resize += _OnResize;
+ _Form.Load += _OnLoad;
+
+ _SizeBeforeMinimize = _Form.ClientSize;
+ _CenterToScreen();
+
+ return true;
+ }
+
+ public override void MainLoop()
+ {
+ _Form.Show();
+ base.MainLoop();
+ _Form.Hide();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Draw/CDrawWinForm.cs b/Vocaluxe/Lib/Draw/CDrawWinForm.cs
index 08720117..0c9cb5c4 100644
--- a/Vocaluxe/Lib/Draw/CDrawWinForm.cs
+++ b/Vocaluxe/Lib/Draw/CDrawWinForm.cs
@@ -44,7 +44,8 @@ namespace Vocaluxe.Lib.Draw
private bool _TopMost;
private Rectangle _Bounds;
- private readonly Dictionary _Textures = new Dictionary();
+ private readonly Dictionary _Textures = new Dictionary();
+ private readonly Dictionary _TextureCache = new Dictionary();
private readonly List _Bitmaps = new List();
private readonly Color _ClearColor = Color.DarkBlue;
@@ -64,7 +65,6 @@ namespace Vocaluxe.Lib.Draw
_G = Graphics.FromImage(_Backbuffer);
_G.Clear(Color.DarkBlue);
- Paint += _OnPaintEvent;
Closing += _OnClosingEvent;
KeyDown += _OnKeyDownEvent;
KeyPress += _OnKeyPressEvent;
@@ -107,8 +107,6 @@ namespace Vocaluxe.Lib.Draw
frontBuffer.DrawImage(_Backbuffer, new Rectangle(x, y, w, h), new Rectangle(0, 0, _Backbuffer.Width, _Backbuffer.Height), GraphicsUnit.Pixel);
}
- private void _OnPaintEvent(object sender, PaintEventArgs e) {}
-
#region FullScreenStuff
private void _ToggleFullScreen()
{
@@ -234,6 +232,7 @@ namespace Vocaluxe.Lib.Draw
if (_Run)
{
+ ClearScreen();
_Run = _Run && CGraphics.Draw();
_Run = CGraphics.UpdateGameLogic(_Keys, _Mouse);
_FlipBuffer();
@@ -279,11 +278,11 @@ namespace Vocaluxe.Lib.Draw
_G.Clear(_ClearColor);
}
- public CTexture CopyScreen()
+ public CTextureRef CopyScreen()
{
var bmp = new Bitmap(_Backbuffer);
_Bitmaps.Add(bmp);
- CTexture texture = _GetNewTexture(bmp.Width, bmp.Height);
+ CTextureRef texture = _GetNewTexture(bmp.GetSize());
// Add to Texture List
_Textures[texture.ID] = texture;
@@ -291,9 +290,9 @@ namespace Vocaluxe.Lib.Draw
return texture;
}
- public void CopyScreen(ref CTexture texture)
+ public void CopyScreen(ref CTextureRef texture)
{
- if (!_TextureExists(texture) || texture.W2 != GetScreenWidth() || texture.H2 != GetScreenHeight())
+ if (!_TextureExists(texture) || texture.OrigSize.Width != GetScreenWidth() || texture.OrigSize.Height != GetScreenHeight())
{
RemoveTexture(ref texture);
texture = CopyScreen();
@@ -309,20 +308,15 @@ namespace Vocaluxe.Lib.Draw
_Backbuffer.Save(file, ImageFormat.Png);
}
- public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2)
- {
- _G.DrawLine(new Pen(Color.FromArgb(a, r, g, b), w), new Point(x1, y1), new Point(x2, y2));
- }
+ public void DrawRect(SColorF color, SRectF rect) {}
- public void DrawColor(SColorF color, SRectF rect) {}
+ public void DrawRectReflection(SColorF color, SRectF rect, float space, float height) {}
- public void DrawColorReflection(SColorF color, SRectF rect, float space, float height) {}
-
- public CTexture AddTexture(Bitmap bmp)
+ public CTextureRef AddTexture(Bitmap bmp)
{
var bmp2 = new Bitmap(bmp);
_Bitmaps.Add(bmp2);
- CTexture texture = _GetNewTexture(bmp.Width, bmp.Height);
+ CTextureRef texture = _GetNewTexture(bmp.GetSize());
// Add to Texture List
_Textures[texture.ID] = texture;
@@ -330,62 +324,84 @@ namespace Vocaluxe.Lib.Draw
return texture;
}
- private CTexture _GetNewTexture(int w, int h)
+ private CTextureRef _GetNewTexture(Size size)
{
- return new CTexture(w, h) {ID = _Bitmaps.Count - 1};
+ return new CTextureRef(_Bitmaps.Count - 1, size);
}
- public CTexture AddTexture(string texturePath)
+ public CTextureRef AddTexture(string texturePath)
{
if (File.Exists(texturePath))
{
- foreach (CTexture tex in _Textures.Values)
- {
- if (tex.TexturePath == texturePath)
- return tex;
- }
+ CTextureRef texture;
+ if (_TextureCache.TryGetValue(texturePath, out texture))
+ return texture;
using (var bmp = new Bitmap(texturePath))
{
- CTexture texture = AddTexture(bmp);
- texture.TexturePath = texturePath;
+ texture = AddTexture(bmp);
+ _TextureCache.Add(texturePath, texture);
}
+ return texture;
}
return null;
}
- private bool _TextureExists(CTexture texture)
+ private bool _TextureExists(CTextureRef texture)
{
return texture != null && _Textures.ContainsKey(texture.ID);
}
- public void RemoveTexture(ref CTexture texture)
+ public CTextureRef CopyTexture(CTextureRef textureRef)
+ {
+ if (_TextureExists(textureRef))
+ return AddTexture(_Bitmaps[textureRef.ID]);
+ return null;
+ }
+
+ public void RemoveTexture(ref CTextureRef texture)
{
if (_TextureExists(texture))
{
_Bitmaps[texture.ID].Dispose();
_Textures.Remove(texture.ID);
+ texture.SetRemoved();
}
texture = null;
}
- public CTexture EnqueueTexture(int w, int h, byte[] data)
+ public CTextureRef EnqueueTexture(int w, int h, byte[] data)
{
return AddTexture(w, h, data);
}
- public CTexture AddTexture(int w, int h, byte[] data)
+ public CTextureRef EnqueueTexture(string texturePath)
+ {
+ return AddTexture(texturePath);
+ }
+
+ public CTextureRef EnqueueTexture(Bitmap bmp)
+ {
+ return AddTexture(bmp);
+ }
+
+ public void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp)
+ {
+ UpdateTexture(textureRef, bmp);
+ }
+
+ public CTextureRef AddTexture(int w, int h, byte[] data)
{
using (var bmp = new Bitmap(w, h))
{
- BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
+ BitmapData bmpData = bmp.LockBits(bmp.GetRect(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
bmp.UnlockBits(bmpData);
return AddTexture(bmp);
}
}
- public bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
+ public void UpdateTexture(CTextureRef texture, int w, int h, byte[] data)
{
if (_TextureExists(texture))
{
@@ -393,40 +409,22 @@ namespace Vocaluxe.Lib.Draw
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
_Bitmaps[texture.ID].UnlockBits(bmpData);
- return true;
}
- return false;
}
- public bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data)
+ public void UpdateTexture(CTextureRef textureRef, Bitmap bmp)
{
- if (!UpdateTexture(texture, w, h, data))
- {
- RemoveTexture(ref texture);
- texture = AddTexture(w, h, data);
- }
- return true;
+ if (_TextureExists(textureRef))
+ _Bitmaps[textureRef.ID] = bmp;
}
- public void DrawTexture(CTexture texture)
- {
- if (texture != null)
- DrawTexture(texture, texture.Rect, texture.Color);
- }
-
- public void DrawTexture(CTexture texture, SRectF rect)
- {
- if (texture != null)
- DrawTexture(texture, rect, texture.Color);
- }
-
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, bool mirrored = false)
+ public void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, bool mirrored = false)
{
if (texture != null)
DrawTexture(texture, rect, color, rect, mirrored);
}
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
+ public void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
{
if (!_TextureExists(texture))
return;
@@ -435,9 +433,9 @@ namespace Vocaluxe.Lib.Draw
coloredBitmap.Dispose();
}
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, float begin, float end) {}
+ public void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, float begin, float end) {}
- public void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float space, float height) {}
+ public void DrawTextureReflection(CTextureRef texture, SRectF rect, SColorF color, float space, float height) {}
public int GetTextureCount()
{
diff --git a/Vocaluxe/Lib/Draw/COpenGL.cs b/Vocaluxe/Lib/Draw/COpenGL.cs
index 43ba70c2..94f0b63d 100644
--- a/Vocaluxe/Lib/Draw/COpenGL.cs
+++ b/Vocaluxe/Lib/Draw/COpenGL.cs
@@ -15,17 +15,12 @@
// along with Vocaluxe. If not, see .
#endregion
-using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
-using System.Threading;
using OpenTK;
using OpenTK.Graphics;
using System;
-using System.Collections.Generic;
-using System.ComponentModel;
using System.Drawing;
using System.IO;
-using System.Runtime.InteropServices;
using System.Windows.Forms;
using Vocaluxe.Base;
using VocaluxeLib;
@@ -33,15 +28,11 @@ using VocaluxeLib.Draw;
using BeginMode = OpenTK.Graphics.OpenGL.BeginMode;
using BlendingFactorDest = OpenTK.Graphics.OpenGL.BlendingFactorDest;
using BlendingFactorSrc = OpenTK.Graphics.OpenGL.BlendingFactorSrc;
-using BufferAccess = OpenTK.Graphics.OpenGL.BufferAccess;
-using BufferTarget = OpenTK.Graphics.OpenGL.BufferTarget;
-using BufferUsageHint = OpenTK.Graphics.OpenGL.BufferUsageHint;
using ClearBufferMask = OpenTK.Graphics.OpenGL.ClearBufferMask;
using DepthFunction = OpenTK.Graphics.OpenGL.DepthFunction;
using EnableCap = OpenTK.Graphics.OpenGL.EnableCap;
using GL = OpenTK.Graphics.OpenGL.GL;
using GenerateMipmapTarget = OpenTK.Graphics.OpenGL.GenerateMipmapTarget;
-using KeyPressEventArgs = System.Windows.Forms.KeyPressEventArgs;
using MatrixMode = OpenTK.Graphics.OpenGL.MatrixMode;
using PixelFormat = OpenTK.Graphics.OpenGL.PixelFormat;
using PixelInternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat;
@@ -54,67 +45,61 @@ using TextureTarget = OpenTK.Graphics.OpenGL.TextureTarget;
namespace Vocaluxe.Lib.Draw
{
- struct SClientRect
+ class CFormHook : Form, IFormHook
{
- public Point Location;
- public int Width;
- public int Height;
- };
+ public MessageEventHandler OnMessage { private get; set; }
- struct STextureQueue
- {
- public readonly int ID;
- public readonly int TextureWidth;
- public readonly int TextureHeight;
- public readonly int DataWidth;
- public readonly int DataHeight;
- public readonly byte[] Data;
-
- public STextureQueue(int id, int textureWidth, int textureHeight, int dataWidth, int dataHeight, byte[] data)
+ protected override void WndProc(ref Message m)
{
- ID = id;
- TextureWidth = textureWidth;
- TextureHeight = textureHeight;
- DataWidth = dataWidth;
- DataHeight = dataHeight;
- Data = data;
+ if (OnMessage == null || OnMessage(ref m))
+ base.WndProc(ref m);
}
}
- class COpenGL : Form, IDraw
+ class COGLTexture : CTextureBase
+ {
+ //The texture "name" according to the specs
+ public readonly int Name;
+
+ public COGLTexture(int name, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, texWidth, texHeight)
+ {
+ Name = name;
+ if (name == 0)
+ return;
+ GL.BindTexture(TextureTarget.Texture2D, Name);
+
+ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, W2, H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
+
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+ }
+
+ public override bool IsLoaded
+ {
+ get { return Name != 0; }
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ if (Name != 0)
+ GL.DeleteTexture(Name);
+ }
+ }
+
+ class COpenGL : CDrawBaseWindows, IDraw
{
#region private vars
- private const int _MaxID = 100000;
-
- private readonly CKeys _Keys;
- private readonly CMouse _Mouse;
- private bool _Run;
-
private readonly GLControl _Control;
-
- private SClientRect _Restore;
- private bool _Fullscreen;
-
- private readonly Dictionary _Textures = new Dictionary();
- private readonly Queue _IDs = new Queue(_MaxID);
- private readonly Queue _TexturesToLoad = new Queue();
-
- private readonly Object _MutexTexture = new Object();
-
- private int _H = 1;
- private int _W = 1;
- private int _Y;
- private int _X;
-
- private bool _UsePBO;
#endregion private vars
public COpenGL()
{
- Icon = new Icon(Path.Combine(CSettings.ProgramFolder, CSettings.FileNameIcon));
-
- for (int i = 1; i < _MaxID; i++)
- _IDs.Enqueue(i);
+ _Form = new CFormHook();
//Check AA Mode
CConfig.AAMode = (EAntiAliasingModes)_CheckAntiAliasingMode((int)CConfig.AAMode);
@@ -138,20 +123,13 @@ namespace Vocaluxe.Lib.Draw
_Control.MakeCurrent();
_Control.VSync = CConfig.VSync == EOffOn.TR_CONFIG_ON;
- Controls.Add(_Control);
+ _Form.Controls.Add(_Control);
+ _Control.KeyDown += _OnKeyDown;
+ _Control.PreviewKeyDown += _OnPreviewKeyDown;
+ _Control.KeyPress += _OnKeyPress;
+ _Control.KeyUp += _OnKeyUp;
- _Keys = new CKeys();
- Paint += _OnPaintEvent;
- Closing += _OnClosingEvent;
- Resize += _OnResizeEvent;
-
- _Control.KeyDown += _OnKeyDownEvent;
- _Control.PreviewKeyDown += _OnPreviewKeyDownEvent;
- _Control.KeyPress += _OnKeyPressEvent;
- _Control.KeyUp += _OnKeyUpEvent;
-
- _Mouse = new CMouse();
_Control.MouseMove += _OnMouseMove;
_Control.MouseWheel += _OnMouseWheel;
_Control.MouseDown += _OnMouseDown;
@@ -159,12 +137,11 @@ namespace Vocaluxe.Lib.Draw
_Control.MouseLeave += _OnMouseLeave;
_Control.MouseEnter += _OnMouseEnter;
- ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH);
- CenterToScreen();
+ _NonPowerOf2TextureSupported = false;
}
#region Helpers
- private int _CheckAntiAliasingMode(int setValue)
+ private static int _CheckAntiAliasingMode(int setValue)
{
int samples = 0;
@@ -223,189 +200,37 @@ namespace Vocaluxe.Lib.Draw
return result - 8;
}
*/
-
- private void _ToggleFullScreen()
- {
- if (!_Fullscreen)
- _EnterFullScreen();
- else
- _LeaveFullScreen();
- }
-
- private void _EnterFullScreen()
- {
- _Fullscreen = true;
-
- _Restore.Location = Location;
- _Restore.Width = Width;
- _Restore.Height = Height;
-
- FormBorderStyle = FormBorderStyle.None;
-
- int screenNr = 0;
- for (int i = 0; i < Screen.AllScreens.Length; i++)
- {
- Screen scr = Screen.AllScreens[i];
- if (scr.Bounds.Top <= Top && scr.Bounds.Left <= Left)
- screenNr = i;
- }
-
- DesktopBounds = new Rectangle(Screen.AllScreens[screenNr].Bounds.Location, new Size(Screen.AllScreens[screenNr].Bounds.Width, Screen.AllScreens[screenNr].Bounds.Height));
-
- if (WindowState == FormWindowState.Maximized)
- {
- WindowState = FormWindowState.Normal;
- _DoResize();
- WindowState = FormWindowState.Maximized;
- }
- else
- _DoResize();
- }
-
- private void _LeaveFullScreen()
- {
- _Fullscreen = false;
-
- FormBorderStyle = FormBorderStyle.Sizable;
- DesktopBounds = new Rectangle(_Restore.Location, new Size(_Restore.Width, _Restore.Height));
- }
#endregion Helpers
#region form events
- private void _OnPaintEvent(object sender, PaintEventArgs e) {}
-
- private void _OnResizeEvent(object sender, EventArgs e) {}
-
- private void _OnClosingEvent(object sender, CancelEventArgs e)
+ protected override void _OnResize(object sender, EventArgs e)
{
- _Run = false;
- }
-
- protected override void OnLoad(EventArgs e)
- {
- GL.ClearColor(Color.Black);
- }
-
- protected override void OnResize(EventArgs e)
- {
- base.OnResize(e);
-
- _Control.ClientSize = ClientSize;
- _DoResize();
- }
-
- protected override void WndProc(ref Message m)
- {
- switch (m.Msg)
- {
- case 0x112: // WM_SYSCOMMAND
- switch ((int)m.WParam & 0xFFF0)
- {
- case 0xF100: // SC_KEYMENU
- m.Result = IntPtr.Zero;
- break;
- case 0xF140: // SC_SCREENSAVER
- case 0xF170: // SC_MONITORPOWER
- break;
- default:
- base.WndProc(ref m);
- break;
- }
- break;
- default:
- base.WndProc(ref m);
- break;
- }
+ _Control.ClientSize = _Form.ClientSize;
+ base._OnResize(sender, e);
}
#endregion form events
- #region mouse event handlers
- private void _OnMouseMove(object sender, MouseEventArgs e)
- {
- _Mouse.MouseMove(e);
- }
-
- private void _OnMouseWheel(object sender, MouseEventArgs e)
- {
- _Mouse.MouseWheel(e);
- }
-
- private void _OnMouseDown(object sender, MouseEventArgs e)
- {
- _Mouse.MouseDown(e);
- }
-
- private void _OnMouseUp(object sender, MouseEventArgs e)
- {
- _Mouse.MouseUp(e);
- }
-
- private void _OnMouseLeave(object sender, EventArgs e)
- {
- _Mouse.Visible = false;
- Cursor.Show();
- }
-
- private void _OnMouseEnter(object sender, EventArgs e)
- {
- Cursor.Hide();
- _Mouse.Visible = true;
- }
- #endregion
-
- #region keyboard event handlers
- private void _OnPreviewKeyDownEvent(object sender, PreviewKeyDownEventArgs e)
- {
- _OnKeyDownEvent(sender, new KeyEventArgs(e.KeyData));
- }
-
- private void _OnKeyDownEvent(object sender, KeyEventArgs e)
- {
- _Keys.KeyDown(e);
- }
-
- private void _OnKeyPressEvent(object sender, KeyPressEventArgs e)
- {
- _Keys.KeyPress(e);
- }
-
- private void _OnKeyUpEvent(object sender, KeyEventArgs e)
- {
- _Keys.KeyUp(e);
- }
- #endregion keyboard event handlers
-
- private void _DoResize()
+ protected override void _DoResize()
{
_H = _Control.Height;
_W = _Control.Width;
- _Y = 0;
- _X = 0;
+ _CurrentAlignment = CConfig.ScreenAlignment;
-
- if (_W / (float)_H > CSettings.GetRenderAspect())
- {
- _W = (int)Math.Round(_H * CSettings.GetRenderAspect());
- _X = (_Control.Width - _W) / 2;
- }
- else
- {
- _H = (int)Math.Round(_W / CSettings.GetRenderAspect());
- _Y = (_Control.Height - _H) / 2;
- }
-
- GL.MatrixMode(MatrixMode.Projection);
- GL.LoadIdentity();
- GL.Ortho(0, CSettings.RenderW, CSettings.RenderH, 0, CSettings.ZNear, CSettings.ZFar);
+ _AdjustAspect(true);
+ _AdjustNewBorders();
GL.Viewport(_X, _Y, _W, _H);
}
#region implementation
#region main stuff
- public bool Init()
+ public override bool Init()
{
- Text = CSettings.GetFullVersionText();
+ if (!base.Init())
+ return false;
+
+ //OpenGL needs that here but D3D needs it in the constructor, so do NOT unify!
+ _Form.ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH);
// Init Texturing
GL.Enable(EnableCap.Texture2D);
@@ -416,59 +241,20 @@ namespace Vocaluxe.Lib.Draw
GL.DepthRange(CSettings.ZFar, CSettings.ZNear);
GL.DepthFunc(DepthFunction.Lequal);
GL.Enable(EnableCap.DepthTest);
+ GL.ClearColor(Color.Black);
return true;
}
- public void MainLoop()
+ protected override void _OnBeforeDraw()
{
- _Run = true;
- int delay = 0;
- Show();
-
- if (CConfig.FullScreen == EOffOn.TR_CONFIG_ON)
- _EnterFullScreen();
-
- while (_Run)
- {
- ClearScreen();
- if (!CGraphics.Draw())
- _Run = false;
- if (!CGraphics.UpdateGameLogic(_Keys, _Mouse))
- _Run = false;
-
- _Control.SwapBuffers();
-
- if ((CConfig.FullScreen == EOffOn.TR_CONFIG_ON) != _Fullscreen)
- _ToggleFullScreen();
-
- _CheckQueue();
-
- if (CTime.IsRunning())
- delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds());
-
- if (delay >= 1 && CConfig.VSync == EOffOn.TR_CONFIG_OFF)
- Thread.Sleep(delay);
-
- CTime.CalculateFPS();
- CTime.Restart();
-
- Application.DoEvents();
- }
- Close();
+ //Nothing to do
}
- public void Unload()
+ protected override void _OnAfterDraw()
{
- try
- {
- Close();
- }
- catch {}
- var textures = new CTexture[_Textures.Count];
- _Textures.Values.CopyTo(textures, 0);
- for (int i = 0; i < _Textures.Count; i++)
- RemoveTexture(ref textures[i]);
+ _Control.SwapBuffers();
+ Application.DoEvents();
}
public int GetScreenWidth()
@@ -480,56 +266,17 @@ namespace Vocaluxe.Lib.Draw
{
return _Control.Height;
}
- #endregion main stuff
- #region Basic Draw Methods
- public void ClearScreen()
+ protected override void _ClearScreen()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
}
- public CTexture CopyScreen()
+ protected override void _AdjustNewBorders()
{
- CTexture texture = _GetNewTexture(_W, _H);
-
- texture.Name = GL.GenTexture();
- GL.BindTexture(TextureTarget.Texture2D, texture.Name);
-
- GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
- GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, _X, _Y, _W, _H);
-
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
-
- GL.BindTexture(TextureTarget.Texture2D, 0);
-
- // Add to Texture List
-
- lock (_MutexTexture)
- {
- texture.ID = _IDs.Dequeue();
- _Textures[texture.ID] = texture;
- }
-
- return texture;
- }
-
- public void CopyScreen(ref CTexture texture)
- {
- //Check for actual texture sizes as it may be downsized compared to OrigSize
- if (!_TextureExists(texture) || texture.UsedWidth != GetScreenWidth() || texture.UsedHeight != GetScreenHeight())
- {
- RemoveTexture(ref texture);
- texture = CopyScreen();
- }
- else
- {
- GL.BindTexture(TextureTarget.Texture2D, texture.Name);
-
- GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, 0, 0, GetScreenWidth(), GetScreenHeight());
-
- GL.BindTexture(TextureTarget.Texture2D, 0);
- }
+ GL.MatrixMode(MatrixMode.Projection);
+ GL.LoadIdentity();
+ GL.Ortho(-CConfig.BorderLeft, CConfig.BorderRight + CSettings.RenderW, CConfig.BorderBottom + CSettings.RenderH, -CConfig.BorderTop, CSettings.ZNear, CSettings.ZFar);
}
public void MakeScreenShot()
@@ -550,36 +297,63 @@ namespace Vocaluxe.Lib.Draw
screen.Save(file, ImageFormat.Bmp);
}
}
+ #endregion main stuff
- public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2)
+ #region Basic Draw Methods
+ public CTextureRef CopyScreen()
{
- GL.Enable(EnableCap.Blend);
- GL.Color4(r, g, b, a * CGraphics.GlobalAlpha);
+ //TODO: Check if _W,_H needs to be used or not
+ Size size = new Size(GetScreenWidth(), GetScreenHeight());
+ COGLTexture texture = _CreateTexture(size);
- GL.Begin(BeginMode.Lines);
- GL.Vertex3(x1, y1, CGraphics.ZOffset);
- GL.Vertex3(x2, y2, CGraphics.ZOffset);
- GL.End();
+ GL.BindTexture(TextureTarget.Texture2D, texture.Name);
+ GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, 0, 0, size.Width, size.Height); //TODO: Use _X,_Y and _W,_H?
+ GL.BindTexture(TextureTarget.Texture2D, 0);
- GL.Disable(EnableCap.Blend);
+ return _GetTextureReference(size, texture);
}
- public void DrawColor(SColorF color, SRectF rect)
+ public void CopyScreen(ref CTextureRef textureRef)
+ {
+ COGLTexture texture;
+ //Check for actual texture sizes as it may be downsized compared to OrigSize
+ if (!_GetTexture(textureRef, out texture) || texture.DataSize.Width != GetScreenWidth() || texture.DataSize.Height != GetScreenHeight())
+ {
+ RemoveTexture(ref textureRef);
+ textureRef = CopyScreen();
+ }
+ else
+ {
+ GL.BindTexture(TextureTarget.Texture2D, texture.Name);
+ GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, 0, 0, GetScreenWidth(), GetScreenHeight());
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+ }
+ }
+
+ public void DrawRect(SColorF color, SRectF rect)
{
GL.Enable(EnableCap.Blend);
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
GL.Begin(BeginMode.Quads);
+ GL.MatrixMode(MatrixMode.Color);
+ GL.PushMatrix();
+ if (Math.Abs(rect.Rotation) > 0.001)
+ {
+ GL.Translate(0.5f, 0.5f, 0);
+ GL.Rotate(-rect.Rotation, 0f, 0f, 1f);
+ GL.Translate(-0.5f, -0.5f, 0);
+ }
GL.Vertex3(rect.X, rect.Y, rect.Z + CGraphics.ZOffset);
GL.Vertex3(rect.X, rect.Y + rect.H, rect.Z + CGraphics.ZOffset);
GL.Vertex3(rect.X + rect.W, rect.Y + rect.H, rect.Z + CGraphics.ZOffset);
GL.Vertex3(rect.X + rect.W, rect.Y, rect.Z + CGraphics.ZOffset);
GL.End();
-
+ GL.PopMatrix();
GL.Disable(EnableCap.Blend);
}
- public void DrawColorReflection(SColorF color, SRectF rect, float space, float height)
+ public void DrawRectReflection(SColorF color, SRectF rect, float space, float height)
{
if (rect.H < height)
height = rect.H;
@@ -603,7 +377,8 @@ namespace Vocaluxe.Lib.Draw
GL.Enable(EnableCap.Blend);
-
+ GL.MatrixMode(MatrixMode.Texture);
+ GL.PushMatrix();
if (Math.Abs(rect.Rotation) > 0.001)
{
GL.Translate(0.5f, 0.5f, 0);
@@ -626,299 +401,113 @@ namespace Vocaluxe.Lib.Draw
GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
GL.End();
-
+ GL.PopMatrix();
GL.Disable(EnableCap.Blend);
}
#endregion Basic Draw Methods
#region Textures
-
- #region adding
- public CTexture AddTexture(string texturePath)
+ protected override COGLTexture _CreateTexture(Size dataSize)
{
- if (!File.Exists(texturePath))
- {
- CLog.LogError("Can't find File: " + texturePath);
- return null;
- }
- Bitmap bmp;
- try
- {
- bmp = new Bitmap(texturePath);
- }
- catch (Exception)
- {
- CLog.LogError("Error loading Texture: " + texturePath);
- return null;
- }
- try
- {
- return AddTexture(bmp);
- }
- finally
- {
- bmp.Dispose();
- }
- }
-
- public CTexture AddTexture(Bitmap bmp)
- {
- if (bmp.Height == 0 || bmp.Width == 0)
- return null;
-
- int maxSize;
- switch (CConfig.TextureQuality)
- {
- case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
- maxSize = 128;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
- maxSize = 256;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
- maxSize = 512;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
- maxSize = 1024;
- break;
- case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
- maxSize = 2048;
- break;
- default:
- maxSize = 512;
- break;
- }
-
- int w = Math.Min(bmp.Width, maxSize);
- int h = Math.Min(bmp.Height, maxSize);
- w = MathHelper.NextPowerOfTwo(w);
- h = MathHelper.NextPowerOfTwo(h);
-
- var texture = new CTexture(bmp.Width, bmp.Height, w, h, true) {Name = GL.GenTexture()};
-
- GL.BindTexture(TextureTarget.Texture2D, texture.Name);
- Bitmap bmp2 = null;
- try
- {
- if (bmp.Width != w || bmp.Height != h)
- {
- //Create a new Bitmap with the new sizes
- bmp2 = new Bitmap(w, h);
- //Scale the texture
- using (Graphics g = Graphics.FromImage(bmp2))
- {
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.SmoothingMode = SmoothingMode.HighQuality;
- g.DrawImage(bmp, new Rectangle(0, 0, bmp2.Width, bmp2.Height));
- }
- bmp = bmp2;
- }
-
- BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
- GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmpData.Width, bmpData.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
- bmp.UnlockBits(bmpData);
- }
- finally
- {
- if (bmp2 != null)
- bmp2.Dispose();
- }
-
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
-
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
- GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
-
- GL.BindTexture(TextureTarget.Texture2D, 0);
- // Add to Texture List
- texture.TexturePath = String.Empty;
-
- lock (_MutexTexture)
- {
- texture.ID = _IDs.Dequeue();
- _Textures[texture.ID] = texture;
- }
+ if (dataSize.Width < 0)
+ return new COGLTexture(0, dataSize);
+ COGLTexture texture = new COGLTexture(GL.GenTexture(), dataSize, _CheckForNextPowerOf2(dataSize.Width), _CheckForNextPowerOf2(dataSize.Height));
return texture;
}
- public CTexture AddTexture(int w, int h, byte[] data)
+ protected override void _WriteDataToTexture(COGLTexture texture, byte[] data)
{
- CTexture texture = _GetNewTexture(w, h);
-
- _CreateTexture(texture, w, h, data);
-
- lock (_MutexTexture)
- {
- texture.ID = _IDs.Dequeue();
- _Textures[texture.ID] = texture;
- }
-
- return texture;
- }
-
- private void _CreateTexture(CTexture texture, int w, int h, byte[] data)
- {
- if (_UsePBO)
- {
- try
- {
- GL.GenBuffers(1, out texture.PBO);
- GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
- GL.BufferData(BufferTarget.PixelUnpackBuffer, (IntPtr)data.Length, IntPtr.Zero, BufferUsageHint.StreamDraw);
- GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
- }
- catch (Exception)
- {
- //throw;
- _UsePBO = false;
- }
- }
-
- texture.Name = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
- GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
- GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);
-
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
+ GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
}
- public CTexture EnqueueTexture(int w, int h, byte[] data)
+ protected override void _WriteDataToTexture(COGLTexture texture, IntPtr data)
{
- CTexture texture = _GetNewTexture(w, h);
-
- lock (_MutexTexture)
- {
- texture.ID = _IDs.Dequeue();
- var queue = new STextureQueue(texture.ID, texture.W2, texture.H2, w, h, data);
- _TexturesToLoad.Enqueue(queue);
- _Textures[texture.ID] = texture;
- }
-
- return texture;
- }
-
- private static CTexture _GetNewTexture(int w, int h)
- {
- return new CTexture(w, h, MathHelper.NextPowerOfTwo(w), MathHelper.NextPowerOfTwo(h));
- }
- #endregion adding
-
- #region updating
- public bool UpdateTexture(CTexture texture, int w, int h, byte[] data)
- {
- //Check if texture exists and extend matches
- if (!_TextureExists(texture) || texture.UsedWidth != w || texture.UsedHeight != h)
- return false;
- if (_UsePBO)
- {
- GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
-
- IntPtr buffer = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
- Marshal.Copy(data, 0, buffer, data.Length);
-
- GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);
-
- GL.BindTexture(TextureTarget.Texture2D, texture.Name);
-
- GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
-
- GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
-
- GL.BindTexture(TextureTarget.Texture2D, 0);
- GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
-
- return true;
- }
-
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
- GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);
-
+ GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
-
- return true;
- }
-
- public bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data)
- {
- if (!UpdateTexture(texture, w, h, data))
- {
- RemoveTexture(ref texture);
- texture = AddTexture(w, h, data);
- }
- return true;
- }
- #endregion updating
-
- public void RemoveTexture(ref CTexture texture)
- {
- if (_TextureExists(texture, false))
- {
- lock (_MutexTexture)
- {
- _IDs.Enqueue(texture.ID);
- GL.DeleteTexture(texture.Name);
- if (texture.PBO > 0)
- GL.DeleteBuffers(1, ref texture.PBO);
- _Textures.Remove(texture.ID);
- }
- }
- texture = null;
- }
-
- private bool _TextureExists(CTexture texture, bool checkIfLoaded = true)
- {
- lock (_MutexTexture)
- {
- if (texture != null && _Textures.ContainsKey(texture.ID))
- {
- if (!checkIfLoaded || _Textures[texture.ID].Name > 0)
- return true;
- }
- }
- return false;
}
#region drawing
- public void DrawTexture(CTexture texture)
+ public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, bool mirrored = false)
{
- if (texture == null)
- return;
- DrawTexture(texture, texture.Rect, texture.Color);
- }
-
- public void DrawTexture(CTexture texture, SRectF rect)
- {
- if (texture == null)
- return;
- DrawTexture(texture, rect, texture.Color);
- }
-
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, bool mirrored = false)
- {
- DrawTexture(texture, rect, color, new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, rect.Z), mirrored);
- }
-
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
- {
- if (!_TextureExists(texture))
+ COGLTexture texture;
+ if (!_GetTexture(textureRef, out texture))
return;
- if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(bounds.H) < float.Epsilon || Math.Abs(bounds.W) < float.Epsilon ||
- Math.Abs(color.A) < float.Epsilon)
+ if (Math.Abs(rect.W) < 1 || Math.Abs(rect.H) < 1 || Math.Abs(color.A) < 0.01)
+ return;
+
+ GL.BindTexture(TextureTarget.Texture2D, texture.Name);
+
+ const float x1 = 0;
+ float x2 = texture.WidthRatio;
+ float y1 = 0;
+ float y2 = texture.HeightRatio;
+
+ float rx1 = rect.X;
+ float rx2 = rect.X + rect.W;
+ float ry1 = rect.Y;
+ float ry2 = rect.Y + rect.H;
+
+ GL.Enable(EnableCap.Blend);
+ GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
+
+ GL.MatrixMode(MatrixMode.Texture);
+ GL.PushMatrix();
+
+ if (Math.Abs(rect.Rotation) > float.Epsilon)
+ {
+ GL.Translate(0.5f, 0.5f, 0);
+ GL.Rotate(-rect.Rotation, 0f, 0f, 1f);
+ GL.Translate(-0.5f, -0.5f, 0);
+ }
+
+ if (mirrored)
+ {
+ float tmp = y2;
+ y2 = y1;
+ y1 = tmp;
+ }
+
+ GL.Begin(BeginMode.Quads);
+
+ GL.TexCoord2(x1, y1);
+ GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
+
+ GL.TexCoord2(x1, y2);
+ GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);
+
+ GL.TexCoord2(x2, y2);
+ GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);
+
+ GL.TexCoord2(x2, y1);
+ GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);
+
+ GL.End();
+
+ GL.PopMatrix();
+
+ GL.Disable(EnableCap.Blend);
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+ }
+
+ public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false)
+ {
+ COGLTexture texture;
+ if (!_GetTexture(textureRef, out texture))
+ return;
+
+ if (Math.Abs(rect.W) < 1 || Math.Abs(rect.H) < 1 || Math.Abs(bounds.H) < 1 || Math.Abs(bounds.W) < 1 ||
+ Math.Abs(color.A) < 0.01)
return;
if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X)
@@ -977,42 +566,28 @@ namespace Vocaluxe.Lib.Draw
GL.Translate(-0.5f, -0.5f, 0);
}
- if (!mirrored)
+ if (mirrored)
{
- GL.Begin(BeginMode.Quads);
-
- GL.TexCoord2(x1, y1);
- GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
-
- GL.TexCoord2(x1, y2);
- GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);
-
- GL.TexCoord2(x2, y2);
- GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);
-
- GL.TexCoord2(x2, y1);
- GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);
-
- GL.End();
+ float tmp = y2;
+ y2 = y1;
+ y1 = tmp;
}
- else
- {
- GL.Begin(BeginMode.Quads);
- GL.TexCoord2(x2, y2);
- GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);
+ GL.Begin(BeginMode.Quads);
- GL.TexCoord2(x2, y1);
- GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);
+ GL.TexCoord2(x1, y1);
+ GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
- GL.TexCoord2(x1, y1);
- GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);
+ GL.TexCoord2(x1, y2);
+ GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);
- GL.TexCoord2(x1, y2);
- GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
+ GL.TexCoord2(x2, y2);
+ GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);
- GL.End();
- }
+ GL.TexCoord2(x2, y1);
+ GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);
+
+ GL.End();
GL.PopMatrix();
@@ -1020,10 +595,12 @@ namespace Vocaluxe.Lib.Draw
GL.BindTexture(TextureTarget.Texture2D, 0);
}
- public void DrawTexture(CTexture texture, SRectF rect, SColorF color, float begin, float end)
+ public void DrawTexture(CTextureRef textureRef, SRectF rect, SColorF color, float begin, float end)
{
- if (!_TextureExists(texture))
+ COGLTexture texture;
+ if (!_GetTexture(textureRef, out texture))
return;
+
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
GL.Enable(EnableCap.Blend);
@@ -1046,47 +623,28 @@ namespace Vocaluxe.Lib.Draw
GL.End();
-
GL.Disable(EnableCap.Blend);
GL.BindTexture(TextureTarget.Texture2D, 0);
}
- public void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float space, float height)
+ public void DrawTextureReflection(CTextureRef textureRef, SRectF rect, SColorF color, float space, float height)
{
- if (!_TextureExists(texture))
+ COGLTexture texture;
+ if (!_GetTexture(textureRef, out texture))
return;
- if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(bounds.H) < float.Epsilon || Math.Abs(bounds.W) < float.Epsilon ||
- Math.Abs(color.A) < float.Epsilon || height <= float.Epsilon)
+ if (Math.Abs(rect.W) < float.Epsilon || Math.Abs(rect.H) < float.Epsilon || Math.Abs(color.A) < float.Epsilon || height <= float.Epsilon)
return;
- if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X)
- return;
-
- if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y)
- return;
-
- if (height > bounds.H)
- height = bounds.H;
+ if (height > rect.H)
+ height = rect.H;
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
- float x1 = (bounds.X - rect.X) / rect.W * texture.WidthRatio;
- float x2 = (bounds.X + bounds.W - rect.X) / rect.W * texture.WidthRatio;
- float y1 = (bounds.Y - rect.Y + rect.H - height) / rect.H * texture.HeightRatio;
- float y2 = (bounds.Y + bounds.H - rect.Y) / rect.H * texture.HeightRatio;
-
- if (x1 < 0)
- x1 = 0f;
-
- if (x2 > texture.WidthRatio)
- x2 = texture.WidthRatio;
-
- if (y1 < 0)
- y1 = 0f;
-
- if (y2 > texture.HeightRatio)
- y2 = texture.HeightRatio;
+ const float x1 = 0;
+ float x2 = texture.WidthRatio;
+ float y1 = (rect.H - height) / rect.H * texture.HeightRatio;
+ float y2 = texture.HeightRatio;
float rx1 = rect.X;
@@ -1094,18 +652,6 @@ namespace Vocaluxe.Lib.Draw
float ry1 = rect.Y + rect.H + space;
float ry2 = rect.Y + rect.H + space + height;
- if (rx1 < bounds.X)
- rx1 = bounds.X;
-
- if (rx2 > bounds.X + bounds.W)
- rx2 = bounds.X + bounds.W;
-
- if (ry1 < bounds.Y + space)
- ry1 = bounds.Y + space;
-
- if (ry2 > bounds.Y + bounds.H + space + height)
- ry2 = bounds.Y + bounds.H + space + height;
-
GL.Enable(EnableCap.Blend);
GL.MatrixMode(MatrixMode.Texture);
@@ -1118,7 +664,6 @@ namespace Vocaluxe.Lib.Draw
GL.Translate(-0.5f, -0.5f, 0);
}
-
GL.Begin(BeginMode.Quads);
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
@@ -1139,7 +684,6 @@ namespace Vocaluxe.Lib.Draw
GL.End();
-
GL.PopMatrix();
GL.Disable(EnableCap.Blend);
@@ -1147,26 +691,6 @@ namespace Vocaluxe.Lib.Draw
}
#endregion drawing
- public int GetTextureCount()
- {
- return _Textures.Count;
- }
-
- private void _CheckQueue()
- {
- lock (_MutexTexture)
- {
- while (_TexturesToLoad.Count > 0)
- {
- STextureQueue q = _TexturesToLoad.Dequeue();
- CTexture texture;
- if (!_Textures.TryGetValue(q.ID, out texture))
- continue;
-
- _CreateTexture(texture, q.DataWidth, q.DataHeight, q.Data);
- }
- }
- }
#endregion Textures
#endregion implementation
diff --git a/Vocaluxe/Lib/Draw/CTextureBase.cs b/Vocaluxe/Lib/Draw/CTextureBase.cs
new file mode 100644
index 00000000..eb9d11bf
--- /dev/null
+++ b/Vocaluxe/Lib/Draw/CTextureBase.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Drawing;
+
+namespace Vocaluxe.Lib.Draw
+{
+ abstract class CTextureBase : IDisposable
+ {
+ public int RefCount;
+ public string TexturePath;
+
+ private Size _DataSize;
+ ///
+ /// Size of data used (mostly equal to OrigSize but due to resizing this might change)
+ ///
+ public Size DataSize
+ {
+ get { return _DataSize; }
+ set
+ {
+ _DataSize = value;
+ _CalcRatios();
+ }
+ }
+
+ ///
+ /// texture width (on device), a power of 2 if necessary
+ ///
+ public int W2 { get; protected set; }
+ ///
+ /// texture height (on device), a power of 2 if necessary
+ ///
+ public int H2 { get; protected set; }
+
+ ///
+ /// Specifies which part of texture memory is actually used
+ ///
+ public float WidthRatio { get; private set; }
+ ///
+ /// Specifies which part of texture memory is actually used
+ ///
+ public float HeightRatio { get; private set; }
+
+ ///
+ /// True if the texture contains usefull data
+ ///
+ public abstract bool IsLoaded { get; }
+
+ ///
+ /// Creates a new texture
+ ///
+ /// Size of the data used
+ /// Width in video memory
+ /// Height in video memory
+ protected CTextureBase(Size dataSize, int texWidth = 0, int texHeight = 0)
+ {
+ _DataSize = dataSize;
+ W2 = (texWidth > 0) ? texWidth : dataSize.Width;
+ H2 = (texHeight > 0) ? texHeight : dataSize.Height;
+
+ _CalcRatios();
+ }
+
+ private void _CalcRatios()
+ {
+ // OpenGL has a problem with partial (NPOT) textures, so we remove 1 pixel
+ if (_DataSize.Width == W2)
+ WidthRatio = 1f;
+ else
+ {
+ int mod = 0;
+ if (_DataSize.Width > 1)
+ mod = -1;
+ WidthRatio = (float)(_DataSize.Width + mod) / W2;
+ }
+ if (_DataSize.Height == H2)
+ HeightRatio = 1f;
+ else
+ {
+ int mod = 0;
+ if (_DataSize.Height > 1)
+ mod = -1;
+ HeightRatio = (float)(_DataSize.Height + mod) / H2;
+ }
+ }
+
+ private bool _IsDisposed;
+
+ public virtual void Dispose()
+ {
+ if (_IsDisposed)
+ throw new ObjectDisposedException(GetType().Name);
+ RefCount = 0;
+ _IsDisposed = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Draw/IDraw.cs b/Vocaluxe/Lib/Draw/IDraw.cs
index f5e3fad3..0b2421ff 100644
--- a/Vocaluxe/Lib/Draw/IDraw.cs
+++ b/Vocaluxe/Lib/Draw/IDraw.cs
@@ -32,30 +32,30 @@ namespace Vocaluxe.Lib.Draw
int GetTextureCount();
- void ClearScreen();
- CTexture CopyScreen();
- void CopyScreen(ref CTexture texture);
+ CTextureRef CopyScreen();
+ void CopyScreen(ref CTextureRef texture);
void MakeScreenShot();
- CTexture AddTexture(string texturePath);
- CTexture AddTexture(Bitmap bitmap);
- CTexture AddTexture(int w, int h, byte[] data);
- CTexture EnqueueTexture(int w, int h, byte[] data);
- bool UpdateTexture(CTexture texture, int w, int h, byte[] data);
- bool UpdateOrAddTexture(ref CTexture texture, int w, int h, byte[] data);
- void RemoveTexture(ref CTexture texture);
+ CTextureRef AddTexture(string texturePath);
+ CTextureRef AddTexture(Bitmap bitmap);
+ CTextureRef AddTexture(int w, int h, byte[] data);
+ void UpdateTexture(CTextureRef texture, Bitmap bmp);
+ void UpdateTexture(CTextureRef texture, int w, int h, byte[] data);
+ CTextureRef EnqueueTexture(string texturePath);
+ CTextureRef EnqueueTexture(Bitmap bmp);
+ CTextureRef EnqueueTexture(int w, int h, byte[] data);
+ void EnqueueTextureUpdate(CTextureRef textureRef, Bitmap bmp);
+ CTextureRef CopyTexture(CTextureRef textureRef);
+ void RemoveTexture(ref CTextureRef texture);
// Basic Draw Methods
- void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2);
- void DrawColor(SColorF color, SRectF rect);
- void DrawColorReflection(SColorF color, SRectF rect, float space, float height);
+ void DrawRect(SColorF color, SRectF rect);
+ void DrawRectReflection(SColorF color, SRectF rect, float space, float height);
- void DrawTexture(CTexture texture);
- void DrawTexture(CTexture texture, SRectF rect);
- void DrawTexture(CTexture texture, SRectF rect, SColorF color, bool mirrored = false);
- void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false);
- void DrawTexture(CTexture texture, SRectF rect, SColorF color, float begin, float end);
+ void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, bool mirrored = false);
+ void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false);
+ void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, float begin, float end);
- void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float space, float height);
+ void DrawTextureReflection(CTextureRef texture, SRectF rect, SColorF color, float space, float height);
}
}
\ No newline at end of file
diff --git a/Vocaluxe/Lib/Playlist/CPlaylistFile.cs b/Vocaluxe/Lib/Playlist/CPlaylistFile.cs
index ff86215f..d09c9b95 100644
--- a/Vocaluxe/Lib/Playlist/CPlaylistFile.cs
+++ b/Vocaluxe/Lib/Playlist/CPlaylistFile.cs
@@ -24,6 +24,7 @@ using Vocaluxe.Base;
using VocaluxeLib;
using VocaluxeLib.Menu;
using VocaluxeLib.Songs;
+using VocaluxeLib.Xml;
namespace Vocaluxe.Lib.Playlist
{
diff --git a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs
index 7d35df67..e32d3795 100644
--- a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs
+++ b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs
@@ -17,6 +17,7 @@
using Gst;
using System;
+using Vocaluxe.Base;
namespace Vocaluxe.Lib.Sound.Playback.GstreamerSharp
{
@@ -26,13 +27,20 @@ namespace Vocaluxe.Lib.Sound.Playback.GstreamerSharp
{
if (_Initialized)
return false;
+
#if ARCH_X86
- var gstreamerEnvVar = Environment.GetEnvironmentVariable("GSTREAMER_1_0_ROOT_X86", EnvironmentVariableTarget.User);
+ const string varName = "GSTREAMER_1_0_ROOT_X86";
#endif
#if ARCH_X64
- var gstreamerEnvVar = Environment.GetEnvironmentVariable("GSTREAMER_1_0_ROOT_X86_64", EnvironmentVariableTarget.User);
+ const string varName = "GSTREAMER_1_0_ROOT_X86_64";
#endif
- var dllDirectory = gstreamerEnvVar + "bin\\";
+ string gstreamerEnvVar = Environment.GetEnvironmentVariable(varName, EnvironmentVariableTarget.User);
+ if (gstreamerEnvVar == null)
+ {
+ CLog.LogError("Gstreamer not found! Make sure you installed it correctly and if it set the environment variable '" + varName + "'!", true);
+ return false;
+ }
+ string dllDirectory = gstreamerEnvVar + "bin\\";
COSFunctions.AddEnvironmentPath(dllDirectory);
Application.Init();
diff --git a/Vocaluxe/Lib/Video/Acinerella/CDecoder.cs b/Vocaluxe/Lib/Video/Acinerella/CDecoder.cs
index 9203b118..823c5290 100644
--- a/Vocaluxe/Lib/Video/Acinerella/CDecoder.cs
+++ b/Vocaluxe/Lib/Video/Acinerella/CDecoder.cs
@@ -102,7 +102,7 @@ namespace Vocaluxe.Lib.Video.Acinerella
Finished = true;
}
- public bool GetFrame(ref CTexture frame, float time, out float videoTime)
+ public bool GetFrame(ref CTextureRef frame, float time, out float videoTime)
{
if (Finished)
{
diff --git a/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs b/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs
index 0ff06799..78707644 100644
--- a/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs
+++ b/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs
@@ -193,7 +193,7 @@ namespace Vocaluxe.Lib.Video.Acinerella
/// Maximum start time for frame
/// Set to whether there are no more frames (stream finished, no loop, future calls will always return false)
/// True if a new frame was gotten
- public bool GetFrame(ref CTexture frame, ref float time, out bool finished)
+ public bool GetFrame(ref CTextureRef frame, ref float time, out bool finished)
{
bool result;
if (Math.Abs(_LastShownTime - time) < _FrameDuration && frame != null) //Check 1 frame difference
@@ -206,7 +206,10 @@ namespace Vocaluxe.Lib.Video.Acinerella
CFramebuffer.CFrame curFrame = _FindFrame(time);
if (curFrame != null)
{
- CDraw.UpdateOrAddTexture(ref frame, _Width, _Height, curFrame.Data);
+ if (frame == null)
+ frame = CDraw.AddTexture(_Width, _Height, curFrame.Data);
+ else
+ CDraw.UpdateTexture(frame, _Width, _Height, curFrame.Data);
if (!_Paused)
curFrame.SetRead();
time = curFrame.Time;
diff --git a/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs b/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs
index 27f2baeb..045a6344 100644
--- a/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs
+++ b/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs
@@ -69,7 +69,7 @@ namespace Vocaluxe.Lib.Video
return _Decoder.Count;
}
- public bool GetFrame(int streamID, ref CTexture frame, float time, out float videoTime)
+ public bool GetFrame(int streamID, ref CTextureRef frame, float time, out float videoTime)
{
CDecoder decoder;
if (_Decoder.TryGetValue(streamID, out decoder))
diff --git a/Vocaluxe/Lib/Video/IVideoDecoder.cs b/Vocaluxe/Lib/Video/IVideoDecoder.cs
index b1da1feb..ebf5e575 100644
--- a/Vocaluxe/Lib/Video/IVideoDecoder.cs
+++ b/Vocaluxe/Lib/Video/IVideoDecoder.cs
@@ -73,7 +73,7 @@ namespace Vocaluxe.Lib.Video
///
/// The actual position in s of the returned frame. Should be ~ time+VideoGap
/// True if frame is valid, false: frame and videoTime might be unchanged or invalid
- bool GetFrame(int streamID, ref CTexture frame, float time, out float videoTime);
+ bool GetFrame(int streamID, ref CTextureRef frame, float time, out float videoTime);
///
/// Seeks to given position
diff --git a/Vocaluxe/Lib/Webcam/CAForgeNet.cs b/Vocaluxe/Lib/Webcam/CAForgeNet.cs
index 13bc4d20..0d6e9918 100644
--- a/Vocaluxe/Lib/Webcam/CAForgeNet.cs
+++ b/Vocaluxe/Lib/Webcam/CAForgeNet.cs
@@ -201,13 +201,16 @@ namespace Vocaluxe.Lib.Webcam
}
}
- public bool GetFrame(ref CTexture frame)
+ public bool GetFrame(ref CTextureRef frame)
{
lock (_MutexData)
{
if (_Data != null && _Data.Length == _Width * _Height * 4 && _NewFrameAvailable)
{
- CDraw.UpdateOrAddTexture(ref frame, _Width, _Height, _Data);
+ if (frame == null)
+ frame = CDraw.AddTexture(_Width, _Height, _Data);
+ else
+ CDraw.UpdateTexture(frame, _Width, _Height, _Data);
_NewFrameAvailable = false;
return true;
}
diff --git a/Vocaluxe/Lib/Webcam/IWebcam.cs b/Vocaluxe/Lib/Webcam/IWebcam.cs
index 98ae1804..9960b979 100644
--- a/Vocaluxe/Lib/Webcam/IWebcam.cs
+++ b/Vocaluxe/Lib/Webcam/IWebcam.cs
@@ -58,7 +58,7 @@ namespace Vocaluxe.Lib.Webcam
///
///
///
- bool GetFrame(ref CTexture frame);
+ bool GetFrame(ref CTextureRef frame);
///
/// Gets the last captured frame as a bitma
diff --git a/Vocaluxe/Program.cs b/Vocaluxe/Program.cs
index b4720e87..65e9a06d 100644
--- a/Vocaluxe/Program.cs
+++ b/Vocaluxe/Program.cs
@@ -81,7 +81,7 @@ namespace Vocaluxe
{
// Init Log
CLog.Init();
-
+ CLog.StartBenchmark("Init Program");
if (!CProgrammHelper.CheckRequirements())
return;
CProgrammHelper.Init();
@@ -173,17 +173,11 @@ namespace Vocaluxe
Application.DoEvents();
- // Init Font
- CLog.StartBenchmark("Init Font");
- CFonts.Init();
- CLog.StopBenchmark("Init Font");
-
- Application.DoEvents();
-
- // Load Cover
- CLog.StartBenchmark("Init Cover");
- CCover.Init();
- CLog.StopBenchmark("Init Cover");
+ // Init Fonts
+ CLog.StartBenchmark("Init Fonts");
+ if (!CFonts.Init())
+ throw new CLoadingException("fonts");
+ CLog.StopBenchmark("Init Fonts");
Application.DoEvents();
@@ -195,6 +189,13 @@ namespace Vocaluxe
Application.DoEvents();
+ // Load Cover
+ CLog.StartBenchmark("Init Cover");
+ CCover.Init();
+ CLog.StopBenchmark("Init Cover");
+
+ Application.DoEvents();
+
// Init Screens
CLog.StartBenchmark("Init Screens");
CGraphics.Init();
@@ -235,6 +236,7 @@ namespace Vocaluxe
//Only reasonable point to call GC.Collect() because initialization may cause lots of garbage
//Rely on GC doing its job afterwards and call Dispose methods where appropriate
GC.Collect();
+ CLog.StopBenchmark("Init Program");
}
catch (Exception e)
{
@@ -250,7 +252,6 @@ namespace Vocaluxe
// Start Main Loop
if (_SplashScreen != null)
_SplashScreen.Close();
- CVocaluxeServer.Start();
CDraw.MainLoop();
}
@@ -264,6 +265,7 @@ namespace Vocaluxe
CVocaluxeServer.Close();
CGraphics.Close();
CCover.Close();
+ CFonts.Close();
CBackgroundMusic.Close();
CWebcam.Close();
CDataBase.Close();
diff --git a/Vocaluxe/Screens/CPopupScreenPlayerControl.cs b/Vocaluxe/Screens/CPopupScreenPlayerControl.cs
index e0c1cdf2..4475e1da 100644
--- a/Vocaluxe/Screens/CPopupScreenPlayerControl.cs
+++ b/Vocaluxe/Screens/CPopupScreenPlayerControl.cs
@@ -195,7 +195,7 @@ namespace Vocaluxe.Screens
return false;
_Statics[_StaticCover].Texture = CBackgroundMusic.Cover;
if (CBackgroundMusic.VideoEnabled && _VideoPreview && CBackgroundMusic.SongHasVideo)
- CDraw.DrawTexture(_Statics[_StaticCover], CBackgroundMusic.GetVideoTexture(), EAspect.Crop);
+ CDraw.DrawTexture(CBackgroundMusic.GetVideoTexture(), _Statics[_StaticCover].Rect, EAspect.Crop);
_Buttons[_ButtonPause].Visible = CBackgroundMusic.IsPlaying;
_Buttons[_ButtonPlay].Visible = !CBackgroundMusic.IsPlaying;
_Texts[_TextCurrentSong].Text = CBackgroundMusic.ArtistAndTitle;
diff --git a/Vocaluxe/Screens/CPopupScreenServerQR.cs b/Vocaluxe/Screens/CPopupScreenServerQR.cs
index febb08a2..e6d4beeb 100644
--- a/Vocaluxe/Screens/CPopupScreenServerQR.cs
+++ b/Vocaluxe/Screens/CPopupScreenServerQR.cs
@@ -33,11 +33,11 @@ namespace Vocaluxe.Screens
get { return 1; }
}
- private CTexture _QRServerAddress;
- private CTexture _QRAndroidLink;
- private CTexture _QRSymbianLink;
- private CTexture _QRWebOSLink;
- private CTexture _QRWindowsPhoneLink;
+ private CTextureRef _QRServerAddress;
+ private CTextureRef _QRAndroidLink;
+ private CTextureRef _QRSymbianLink;
+ private CTextureRef _QRWebOSLink;
+ private CTextureRef _QRWindowsPhoneLink;
private const string _StaticQRServer = "StaticQRServer";
private const string _StaticQRAndroid = "StaticQRAndroid";
diff --git a/Vocaluxe/Screens/CScreenCredits.cs b/Vocaluxe/Screens/CScreenCredits.cs
index 67dcfdf8..dc9904fc 100644
--- a/Vocaluxe/Screens/CScreenCredits.cs
+++ b/Vocaluxe/Screens/CScreenCredits.cs
@@ -126,21 +126,21 @@ namespace Vocaluxe.Screens
private List _Paragraphs;
private List _ParagraphTexts;
- private CTexture _TexLogo;
- private CTexture _TexPerfectNoteStar;
+ private CTextureRef _TexLogo;
+ private CTextureRef _TexPerfectNoteStar;
- private CTexture _TexRedDot;
- private CTexture _TexBlueDot;
+ private CTextureRef _TexRedDot;
+ private CTextureRef _TexBlueDot;
- private CTexture _TexNameBrunzel;
- private CTexture _TexNameDarkice;
- private CTexture _TexNameFlokuep;
- private CTexture _TexNameFlamefire;
- private CTexture _TexNameMesand;
- private CTexture _TexNameBohning;
- private CTexture _TexNameBabene03;
- private CTexture _TexNamePantero;
- private CTexture _TexNamePinky007;
+ private CTextureRef _TexNameBrunzel;
+ private CTextureRef _TexNameDarkice;
+ private CTextureRef _TexNameFlokuep;
+ private CTextureRef _TexNameFlamefire;
+ private CTextureRef _TexNameMesand;
+ private CTextureRef _TexNameBohning;
+ private CTextureRef _TexNameBabene03;
+ private CTextureRef _TexNamePantero;
+ private CTextureRef _TexNamePinky007;
public override void Init()
{
@@ -286,12 +286,12 @@ namespace Vocaluxe.Screens
return GetNewParticleEffect(numStars, partColor, rect, _TexPerfectNoteStar, partSize, EParticleType.Star);
}
- private void _AddNewCreditName(CTexture texture, int particleOffsetX, int particleOffsetY, bool bigParticles)
+ private void _AddNewCreditName(CTextureRef texture, int particleOffsetX, int particleOffsetY, bool bigParticles)
{
bool isRight = _CreditNames.Count % 2 == 0;
int partRectSize = bigParticles ? 25 : 20;
int partCount = bigParticles ? 8 : 6;
- CTexture texDot = isRight ? _TexRedDot : _TexBlueDot;
+ CTextureRef texDot = isRight ? _TexRedDot : _TexBlueDot;
CStatic image = GetNewStatic(texture, new SColorF(1, 1, 1, 1), new SRectF(-1, -1, 400, 120, -4));
@@ -360,7 +360,7 @@ namespace Vocaluxe.Screens
base.Draw();
//Draw background
- CDraw.DrawColor(new SColorF(0, 0.18f, 0.474f, 1), new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, 0));
+ CDraw.DrawRect(new SColorF(0, 0.18f, 0.474f, 1), new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, 0));
//Draw stars
_StarsBlue.Draw();
diff --git a/Vocaluxe/Screens/CScreenNames.cs b/Vocaluxe/Screens/CScreenNames.cs
index 3a566060..4e9b3b06 100644
--- a/Vocaluxe/Screens/CScreenNames.cs
+++ b/Vocaluxe/Screens/CScreenNames.cs
@@ -55,7 +55,7 @@ namespace Vocaluxe.Screens
{"EqualizerPlayer1", "EqualizerPlayer2", "EqualizerPlayer3", "EqualizerPlayer4", "EqualizerPlayer5", "EqualizerPlayer6"};
private readonly string[] _SelectSlideDuetPlayer = new string[]
{"SelectSlideDuetPlayer1", "SelectSlideDuetPlayer2", "SelectSlideDuetPlayer3", "SelectSlideDuetPlayer4", "SelectSlideDuetPlayer5", "SelectSlideDuetPlayer6"};
- private readonly CTexture[] _OriginalPlayerAvatarTextures = new CTexture[CSettings.MaxNumPlayer];
+ private readonly CTextureRef[] _OriginalPlayerAvatarTextures = new CTextureRef[CSettings.MaxNumPlayer];
private bool _SelectingKeyboardActive;
private bool _SelectingFast;
diff --git a/Vocaluxe/Screens/CScreenOptionsVideo.cs b/Vocaluxe/Screens/CScreenOptionsVideo.cs
index 9a6e6a57..81fdb4eb 100644
--- a/Vocaluxe/Screens/CScreenOptionsVideo.cs
+++ b/Vocaluxe/Screens/CScreenOptionsVideo.cs
@@ -49,7 +49,7 @@ namespace Vocaluxe.Screens
private const string _TextWebcamResolution = "TextWebcamResolution";
private SWebcamConfig _Config;
- private CTexture _WebcamTexture;
+ private CTextureRef _WebcamTexture;
private int _DeviceNr;
private int _CapabilityNr;
diff --git a/Vocaluxe/Screens/CScreenProfiles.cs b/Vocaluxe/Screens/CScreenProfiles.cs
index 0835e451..532f3a8a 100644
--- a/Vocaluxe/Screens/CScreenProfiles.cs
+++ b/Vocaluxe/Screens/CScreenProfiles.cs
@@ -64,7 +64,7 @@ namespace Vocaluxe.Screens
private EEditMode _EditMode;
- private CTexture _WebcamTexture;
+ private CTextureRef _WebcamTexture;
private Bitmap _Snapshot;
public override void Init()
diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs
index 077afca4..5e3183d6 100644
--- a/Vocaluxe/Screens/CScreenSing.cs
+++ b/Vocaluxe/Screens/CScreenSing.cs
@@ -99,9 +99,9 @@ namespace Vocaluxe.Screens
private const float _Volume = 100f;
private int _CurrentVideo = -1;
private EAspect _VideoAspect = EAspect.Crop;
- private CTexture _CurrentVideoTexture;
- private CTexture _CurrentWebcamFrameTexture;
- private CTexture _Background;
+ private CTextureRef _CurrentVideoTexture;
+ private CTextureRef _CurrentWebcamFrameTexture;
+ private CTextureRef _Background;
private float _CurrentTime;
private float _FinishTime;
@@ -274,7 +274,7 @@ namespace Vocaluxe.Screens
case Keys.V:
if (_VideoAspect == EAspect.Zoom2)
- _VideoAspect = 0;
+ _VideoAspect = EAspect.Crop;
else
_VideoAspect++;
@@ -463,7 +463,7 @@ namespace Vocaluxe.Screens
{
if (_Active)
{
- CTexture background;
+ CTextureRef background;
var aspect = EAspect.Crop;
if (_CurrentVideo != -1 && CConfig.VideosInSongs == EOffOn.TR_CONFIG_ON && !_Webcam)
{
@@ -479,11 +479,8 @@ namespace Vocaluxe.Screens
background = _Background;
if (background != null)
{
- var bounds = new RectangleF(0, 0, CSettings.RenderW, CSettings.RenderH);
- RectangleF rect;
- CHelper.SetRect(bounds, out rect, background.OrigAspect, aspect);
- CDraw.DrawTexture(background, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, 0f),
- background.Color, new SRectF(bounds.X, bounds.Y, bounds.Width, bounds.Height, 0f));
+ var bounds = new SRectF(0, 0, CSettings.RenderW, CSettings.RenderH, 0);
+ CDraw.DrawTexture(background, bounds, aspect, background.Color);
}
else if (_SlideShow != null)
_SlideShow.Draw();
@@ -1004,13 +1001,13 @@ namespace Vocaluxe.Screens
float partSeconds = timeDiff - fullSeconds;
_Texts[_TextMedleyCountdown].Visible = true;
_Texts[_TextMedleyCountdown].Text = fullSeconds.ToString();
- float h = partSeconds * CSettings.RenderH;
- float w = CFonts.GetTextBounds(_Texts[_TextMedleyCountdown], h).Width;
- float x = CSettings.RenderW / 2 - w / 2;
- float y = CSettings.RenderH / 2 - h / 2;
+ _Texts[_TextMedleyCountdown].Font.Height = partSeconds * CSettings.RenderH;
+
+ RectangleF textBounds = CFonts.GetTextBounds(_Texts[_TextMedleyCountdown]);
+ float x = CSettings.RenderW / 2 - textBounds.Width / 2;
+ float y = CSettings.RenderH / 2 - textBounds.Height / 2;
_Texts[_TextMedleyCountdown].X = x;
_Texts[_TextMedleyCountdown].Y = y;
- _Texts[_TextMedleyCountdown].Height = h;
}
else
_Texts[_TextMedleyCountdown].Visible = false;
@@ -1216,8 +1213,8 @@ namespace Vocaluxe.Screens
}
else
{
- _Statics[_StaticSongText].Color.A = 10f - t / 3f;
- _Texts[_TextSongName].Color.A = 10f - t / 3f;
+ _Statics[_StaticSongText].Color.A = (10f - t) / 3f;
+ _Texts[_TextSongName].Color.A = (10f - t) / 3f;
}
}
else
diff --git a/Vocaluxe/Screens/CScreenSong.cs b/Vocaluxe/Screens/CScreenSong.cs
index 89e6d1ef..57a5ed16 100644
--- a/Vocaluxe/Screens/CScreenSong.cs
+++ b/Vocaluxe/Screens/CScreenSong.cs
@@ -413,7 +413,7 @@ namespace Vocaluxe.Screens
_SongMenu.Active = !_PlaylistActive;
_ToggleSongOptions(ESongOptionsView.None);
}
- else if (CHelper.IsInBounds(_SongMenu.Rect, mouseEvent.X, mouseEvent.Y))
+ else if (CHelper.IsInBounds(_SongMenu.Rect, mouseEvent))
{
_PlaylistActive = false;
_Playlist.Selected = _PlaylistActive;
diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj
index b8276467..48110d1e 100644
--- a/Vocaluxe/Vocaluxe.csproj
+++ b/Vocaluxe/Vocaluxe.csproj
@@ -216,6 +216,7 @@
+
@@ -224,6 +225,9 @@
+
+
+
@@ -241,7 +245,7 @@
-
+
diff --git a/VocaluxeLib/CEncoding.cs b/VocaluxeLib/CEncoding.cs
new file mode 100644
index 00000000..7b763d5b
--- /dev/null
+++ b/VocaluxeLib/CEncoding.cs
@@ -0,0 +1,39 @@
+using System.Text;
+
+namespace VocaluxeLib
+{
+ static class CEncoding
+ {
+ public static Encoding GetEncoding(this string encodingName)
+ {
+ switch (encodingName)
+ {
+ case "AUTO":
+ return Encoding.Default;
+ case "CP1250":
+ return Encoding.GetEncoding(1250);
+ case "CP1252":
+ return Encoding.GetEncoding(1252);
+ case "LOCALE":
+ return Encoding.Default;
+ case "UTF8":
+ return Encoding.UTF8;
+ default:
+ return Encoding.Default;
+ }
+ }
+
+ public static string GetEncodingName(this Encoding enc)
+ {
+ string result = "UTF8";
+
+ if (enc.CodePage == 1250)
+ result = "CP1250";
+
+ if (enc.CodePage == 1252)
+ result = "CP1252";
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/VocaluxeLib/CFont.cs b/VocaluxeLib/CFont.cs
new file mode 100644
index 00000000..bb8fed4e
--- /dev/null
+++ b/VocaluxeLib/CFont.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Xml.Serialization;
+
+namespace VocaluxeLib
+{
+ public interface IFontObserver
+ {
+ void FontChanged();
+ }
+
+ public struct SThemeFont
+ {
+ public string Name;
+ public EStyle Style;
+ public float Size;
+ }
+
+ public class CFont
+ {
+ private string _Name;
+ private EStyle _Style;
+ private float _Height;
+ private readonly List _Observers = new List();
+
+ public string Name
+ {
+ get { return _Name; }
+ set
+ {
+ if (_Name == value)
+ return;
+ _Name = value;
+ foreach (IFontObserver observer in _Observers)
+ observer.FontChanged();
+ }
+ }
+ public EStyle Style
+ {
+ get { return _Style; }
+ set
+ {
+ if (_Style == value)
+ return;
+ _Style = value;
+ foreach (IFontObserver observer in _Observers)
+ observer.FontChanged();
+ }
+ }
+ public float Height
+ {
+ get { return _Height; }
+ set
+ {
+ if (Math.Abs(_Height - value) < 0.001)
+ return;
+ _Height = value;
+ foreach (IFontObserver observer in _Observers)
+ observer.FontChanged();
+ }
+ }
+
+ public CFont()
+ {
+ _Name = "Normal";
+ _Style = EStyle.Normal;
+ _Height = 25f;
+ }
+
+ public CFont(SThemeFont font)
+ {
+ _Name = font.Name;
+ _Style = font.Style;
+ _Height = font.Size;
+ }
+
+ public CFont(string fontFamily, EStyle style, float h)
+ {
+ _Name = fontFamily;
+ _Style = style;
+ _Height = h;
+ }
+
+ public void AddObserver(IFontObserver observer)
+ {
+ if (!_Observers.Contains(observer))
+ _Observers.Add(observer);
+ }
+
+ public void RemoveObserver(IFontObserver observer)
+ {
+ _Observers.Remove(observer);
+ }
+ }
+}
\ No newline at end of file
diff --git a/VocaluxeLib/CHelper.cs b/VocaluxeLib/CHelper.cs
index 7eb1cd7a..d54a2d00 100644
--- a/VocaluxeLib/CHelper.cs
+++ b/VocaluxeLib/CHelper.cs
@@ -17,11 +17,9 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
-using System.Text;
namespace VocaluxeLib
{
@@ -64,46 +62,6 @@ namespace VocaluxeLib
return (int)result;
}
- ///
- /// Makes sure val is between min and max
- /// Asserts that min<=max
- ///
- ///
- ///
- ///
- ///
- /// Clamped value
- public static T Clamp(this T val, T min, T max) where T : IComparable
- {
- Debug.Assert(min.CompareTo(max) <= 0);
- if (val.CompareTo(min) < 0)
- return min;
- if (val.CompareTo(max) > 0)
- return max;
- return val;
- }
-
- ///
- /// Makes sure val is between min and max but also handles the case where min>max
- ///
- ///
- ///
- ///
- ///
- ///
- /// Clamped value
- public static T Clamp(this T val, T min, T max, bool preferMin) where T : IComparable
- {
- if (min.CompareTo(max) > 0)
- {
- if (preferMin)
- max = min;
- else
- min = max;
- }
- return Clamp(val, min, max);
- }
-
///
/// Concat strings into one string with ", " as separator.
///
@@ -120,90 +78,88 @@ namespace VocaluxeLib
return result;
}
- public static void SetRect(SRectF bounds, out SRectF rect, float rectAspect, EAspect aspect)
+ ///
+ /// Places a rect within the bounds maintaining the aspectRatio and using the given aspect
+ ///
+ /// Bounds to fit the rect in
+ /// The original aspectRatio of the rect/image/...
+ ///
+ /// Crop: Fit fully in bounds cutting off overhanging parts (same on both sides)
+ /// LetterBox: Fit the long side possibly leaving some space on the other (rect will be centered)
+ /// StretcH: Just fit the rect in the bounds (rect=bounds)
+ ///
+ public static SRectF FitInBounds(SRectF bounds, float aspectRatio, EAspect aspect)
{
- var bounds2 = new RectangleF(bounds.X, bounds.Y, bounds.W, bounds.H);
- RectangleF rect2;
- SetRect(bounds2, out rect2, rectAspect, aspect);
+ if (aspect == EAspect.Stretch)
+ return bounds;
- rect = new SRectF(rect2.X, rect2.Y, rect2.Width, rect2.Height, bounds.Z);
- }
+ float boundsAspectRatio = bounds.W / bounds.H;
- public static void SetRect(RectangleF bounds, out RectangleF rect, float rectAspect, EAspect aspect)
- {
- float boundsW = bounds.Width;
- float boundsH = bounds.Height;
- float boundsAspect = boundsW / boundsH;
-
- float scaledWidth;
- float scaledHeight;
+ float scaledWidth, scaledHeight;
switch (aspect)
{
case EAspect.Crop:
- if (boundsAspect >= rectAspect)
+ if (boundsAspectRatio >= aspectRatio)
{
- scaledWidth = boundsW;
- scaledHeight = boundsW / rectAspect;
+ scaledWidth = bounds.W;
+ scaledHeight = bounds.W / aspectRatio;
}
else
{
- scaledHeight = boundsH;
- scaledWidth = boundsH * rectAspect;
+ scaledHeight = bounds.H;
+ scaledWidth = bounds.H * aspectRatio;
}
break;
case EAspect.Zoom1:
- if (boundsAspect >= rectAspect)
+ if (boundsAspectRatio >= aspectRatio)
{
- scaledWidth = boundsW * 1.33f;
- scaledHeight = boundsW * 1.33f / rectAspect;
+ scaledWidth = bounds.W * 1.33f;
+ scaledHeight = bounds.W * 1.33f / aspectRatio;
}
else
{
- scaledHeight = boundsH / 1.33f;
- scaledWidth = boundsH / 1.33f * rectAspect;
+ scaledHeight = bounds.H / 1.33f;
+ scaledWidth = bounds.H / 1.33f * aspectRatio;
}
break;
case EAspect.Zoom2:
- if (boundsAspect >= rectAspect)
+ if (boundsAspectRatio >= aspectRatio)
{
- scaledWidth = boundsW * 1.17f;
- scaledHeight = boundsW * 1.17f / rectAspect;
+ scaledWidth = bounds.W * 1.17f;
+ scaledHeight = bounds.W * 1.17f / aspectRatio;
}
else
{
- scaledHeight = boundsH / 1.17f;
- scaledWidth = boundsH / 1.17f * rectAspect;
+ scaledHeight = bounds.H / 1.17f;
+ scaledWidth = bounds.H / 1.17f * aspectRatio;
}
break;
case EAspect.LetterBox:
- if (boundsAspect <= rectAspect)
+ if (boundsAspectRatio <= aspectRatio)
{
- scaledWidth = boundsW;
- scaledHeight = boundsW / rectAspect;
+ scaledWidth = bounds.W;
+ scaledHeight = bounds.W / aspectRatio;
}
else
{
- scaledHeight = boundsH;
- scaledWidth = boundsH * rectAspect;
+ scaledHeight = bounds.H;
+ scaledWidth = bounds.H * aspectRatio;
}
break;
default:
- scaledWidth = boundsW;
- scaledHeight = boundsH;
- break;
+ return bounds;
}
+ float left = (bounds.W - scaledWidth) / 2 + bounds.X;
+ float top = (bounds.H - scaledHeight) / 2 + bounds.Y;
- float left = (boundsW - scaledWidth) / 2 + bounds.Left;
- float upper = (boundsH - scaledHeight) / 2 + bounds.Top;
-
- rect = new RectangleF(left, upper, scaledWidth, scaledHeight);
+ return new SRectF(left, top, scaledWidth, scaledHeight, bounds.Z);
}
///
/// Returns a list with all files in the given path that match a given pattern
///
- /// Path to search for
+ /// Path to search
/// Pattern to match (e.g. "*.jpg")
/// Search directories recursively
/// False for just file names, True for full path
@@ -301,7 +257,7 @@ namespace VocaluxeLib
public static bool IsInBounds(SRectF bounds, int x, int y)
{
- return (bounds.X <= x) && (bounds.X + bounds.W >= x) && (bounds.Y <= y) && (bounds.Y + bounds.H >= y);
+ return ((float)x).IsInRange(bounds.X, bounds.X + bounds.W) && ((float)y).IsInRange(bounds.Y, bounds.Y + bounds.H);
}
///
@@ -331,40 +287,30 @@ namespace VocaluxeLib
{
return (n * n + n) / 2;
}
- }
- static class CEncoding
- {
- public static Encoding GetEncoding(this string encodingName)
+ ///
+ /// Loads a bitmap from a file logging errors
+ ///
+ /// Full path to image file
+ /// Bitmap or null on error
+ public static Bitmap LoadBitmap(string filePath)
{
- switch (encodingName)
+ if (!File.Exists(filePath))
{
- case "AUTO":
- return Encoding.Default;
- case "CP1250":
- return Encoding.GetEncoding(1250);
- case "CP1252":
- return Encoding.GetEncoding(1252);
- case "LOCALE":
- return Encoding.Default;
- case "UTF8":
- return Encoding.UTF8;
- default:
- return Encoding.Default;
+ CBase.Log.LogError("Can't find File: " + filePath);
+ return null;
}
- }
-
- public static string GetEncodingName(this Encoding enc)
- {
- string result = "UTF8";
-
- if (enc.CodePage == 1250)
- result = "CP1250";
-
- if (enc.CodePage == 1252)
- result = "CP1252";
-
- return result;
+ Bitmap bmp;
+ try
+ {
+ bmp = new Bitmap(filePath);
+ }
+ catch (Exception)
+ {
+ CBase.Log.LogError("Error loading bitmap: " + filePath);
+ return null;
+ }
+ return bmp;
}
}
}
\ No newline at end of file
diff --git a/VocaluxeLib/Draw/CTexture.cs b/VocaluxeLib/Draw/CTexture.cs
deleted file mode 100644
index 76a03818..00000000
--- a/VocaluxeLib/Draw/CTexture.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-#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.Drawing;
-
-namespace VocaluxeLib.Draw
-{
- public class CTexture
- {
- public int ID = -1;
- public int PBO;
- //Only used by OpenGL (the texture "name" according to the specs)
- public int Name = -1;
-
- public string TexturePath = "";
-
- ///
- /// Original size (e.g. of bmp)
- ///
- public readonly Size OrigSize;
- public float OrigAspect
- {
- get { return (float)OrigSize.Width / OrigSize.Height; }
- }
-
- ///
- /// Current size when drawn
- ///
- public SRectF Rect;
-
- public SColorF Color = new SColorF(1f, 1f, 1f, 1f);
-
- private int _W2, _H2;
- private readonly bool _UseFullTexture;
- ///
- /// Internal texture width (on device), a power of 2 if necessary
- ///
- public int W2
- {
- get { return _W2; }
- set
- {
- _W2 = value;
- if (_UseFullTexture)
- WidthRatio = 1;
- else
- WidthRatio = (float)OrigSize.Width / _W2;
- }
- }
- ///
- /// Internal texture height (on device), a power of 2 if necessary
- ///
- public int H2
- {
- get { return _H2; }
- set
- {
- _H2 = value;
- if (_UseFullTexture)
- HeightRatio = 1;
- else
- HeightRatio = (float)OrigSize.Height / _H2;
- }
- }
-
- ///
- /// Internal use. Specifies which part of texture memory is actually used
- ///
- public float WidthRatio { get; private set; }
- ///
- /// Internal use. Specifies which part of texture memory is actually used
- ///
- public float HeightRatio { get; private set; }
-
- ///
- /// Actual texture space used in x direction
- ///
- public int UsedWidth
- {
- get { return (int)(_W2 * WidthRatio); }
- }
-
- ///
- /// Actual texture space used in y direction
- ///
- public int UsedHeight
- {
- get { return (int)(_H2 * HeightRatio); }
- }
-
- /*
- ///
- /// Internal use. Specifies if full texture memory should be used
- /// Set to true if you resized the original image to the maximum
- ///
- public bool UseFullTexture
- {
- get { return _UseFullTexture; }
- set
- {
- _UseFullTexture = value;
- if (value)
- {
- WidthRatio = 1;
- HeightRatio = 1;
- }
- else
- {
- WidthRatio = (float)OrigSize.Width / _W2;
- HeightRatio = (float)OrigSize.Height / _H2;
- }
- }
- }
-*/
-
- ///
- /// Creates a new texture reference
- ///
- /// Original width (Bitmap size)
- /// Original height (Bitmap size)
- /// Width in video memory
- /// Height in video memory
- /// True if it is using the full size of the video memory (no blank parts due to Pow-2-Issue)
- public CTexture(int origWidth, int origHeight, int texWidth = 0, int texHeight = 0, bool useFullTexture = false)
- {
- OrigSize = new Size(origWidth, origHeight);
- Rect = new SRectF(0f, 0f, origWidth, origHeight, 0f);
- _UseFullTexture = useFullTexture;
-
- //IMPORTANT: Use setter here to calculate ratios!
- W2 = (texWidth > 0) ? texWidth : origWidth;
- H2 = (texHeight > 0) ? texHeight : origHeight;
- }
- }
-}
\ No newline at end of file
diff --git a/VocaluxeLib/Draw/CTextureRef.cs b/VocaluxeLib/Draw/CTextureRef.cs
new file mode 100644
index 00000000..d593cb12
--- /dev/null
+++ b/VocaluxeLib/Draw/CTextureRef.cs
@@ -0,0 +1,87 @@
+#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.Drawing;
+
+namespace VocaluxeLib.Draw
+{
+ ///
+ /// Reference to a texture in the drawing driver
+ ///
+ public class CTextureRef : IDisposable
+ {
+ public int ID { get; private set; }
+ ///
+ /// Size of original image (e.g. of bmp)
+ ///
+ public Size OrigSize;
+
+ public float OrigAspect
+ {
+ get { return (float)OrigSize.Width / OrigSize.Height; }
+ }
+
+ ///
+ /// Current size when drawn
+ ///
+ public SRectF Rect;
+
+ public SColorF Color = new SColorF(1f, 1f, 1f, 1f);
+
+ ///
+ /// Creates a new texture reference
+ ///
+ /// ID of the texture
+ /// Original size (Bitmap size)
+ public CTextureRef(int id, Size origSize)
+ {
+ ID = id;
+ OrigSize = origSize;
+
+ Rect = new SRectF(0f, 0f, origSize.Width, origSize.Height, 0f);
+ }
+
+ ~CTextureRef()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ if (ID >= 0)
+ {
+ //Free textures that are no longer referenced
+ CTextureRef tmp = this;
+ CBase.Drawing.RemoveTexture(ref tmp);
+ }
+ SetRemoved();
+ }
+
+ ///
+ /// Call this from the graphics driver to denote that this reference is remove and no longer valid
+ /// This avoids the finalizer
+ ///
+ public void SetRemoved()
+ {
+ if (ID < 0)
+ throw new ObjectDisposedException(GetType().Name);
+ ID = -1;
+ GC.SuppressFinalize(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/VocaluxeLib/Enums.cs b/VocaluxeLib/Enums.cs
index 13a57b6b..5a7b4005 100644
--- a/VocaluxeLib/Enums.cs
+++ b/VocaluxeLib/Enums.cs
@@ -48,6 +48,13 @@ namespace VocaluxeLib
Zoom2
}
+ public enum EGeneralAlignment
+ {
+ Middle,
+ Start,
+ End
+ }
+
public enum EAlignment
{
Left,
diff --git a/VocaluxeLib/Extensions.cs b/VocaluxeLib/Extensions.cs
index f04d5f40..12f06137 100644
--- a/VocaluxeLib/Extensions.cs
+++ b/VocaluxeLib/Extensions.cs
@@ -17,13 +17,71 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
+using System.Text.RegularExpressions;
namespace VocaluxeLib
{
public static class CExtensions
{
+ ///
+ /// Makes sure val is between min and max
+ /// Asserts that min<=max
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Clamped value
+ public static T Clamp(this T val, T min, T max) where T : IComparable
+ {
+ Debug.Assert(min.CompareTo(max) <= 0);
+ if (val.CompareTo(min) < 0)
+ return min;
+ if (val.CompareTo(max) > 0)
+ return max;
+ return val;
+ }
+
+ ///
+ /// Makes sure val is between min and max but also handles the case where min>max
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Clamped value
+ public static T Clamp(this T val, T min, T max, bool preferMin) where T : IComparable
+ {
+ if (min.CompareTo(max) > 0)
+ {
+ if (preferMin)
+ max = min;
+ else
+ min = max;
+ }
+ return Clamp(val, min, max);
+ }
+
+ ///
+ /// Checks if the value is in the specified range
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool IsInRange(this T val, T min, T max) where T : IComparable
+ {
+ Debug.Assert(min.CompareTo(max) <= 0);
+ return min.CompareTo(val) <= 0 && max.CompareTo(val) >= 0;
+ }
+
///
/// Resizes the given list to the given size. Removes elements or adds default values
///
@@ -91,28 +149,13 @@ namespace VocaluxeLib
return value.IndexOf(other, StringComparison.CurrentCultureIgnoreCase) >= 0;
}
+ private static Regex _MultipleWhiteSpaceRegEx = new Regex(@" {2,}");
+
public static string TrimMultipleWs(this string value)
{
if (string.IsNullOrEmpty(value))
return "";
- int start = 0;
- int len = value.Length;
- while (value[start] == ' ')
- {
- start++;
- if (start >= len)
- return "";
- }
- if (start > 0)
- start--;
- int end = --len;
- while (value[end] == ' ')
- end--;
- if (end < len)
- end++;
- if (end - start < len)
- value = value.Substring(start, end - start + 1);
- return value;
+ return _MultipleWhiteSpaceRegEx.Replace(value, " ");
}
///
@@ -134,5 +177,47 @@ namespace VocaluxeLib
rect.H + 2 * rect.H * (scale - 1f),
rect.Z);
}
+
+ public static Size GetSize(this Bitmap bmp)
+ {
+ return new Size(bmp.Width, bmp.Height);
+ }
+
+ public static Rectangle GetRect(this Bitmap bmp)
+ {
+ return Rectangle.Round(new Rectangle(0, 0, bmp.Width, bmp.Height));
+ }
+
+ ///
+ /// Resizes the bitmap to the given size creating a copy of it
+ ///
+ ///
+ ///
+ /// Resized bitmap or null on error
+ public static Bitmap Resize(this Bitmap bmp, Size newSize)
+ {
+ Bitmap result = null;
+ try
+ {
+ //Create a new Bitmap with the new sizes
+ result = new Bitmap(newSize.Width, newSize.Height);
+ //Scale the texture
+ using (Graphics g = Graphics.FromImage(result))
+ {
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ g.SmoothingMode = SmoothingMode.HighQuality;
+ g.DrawImage(bmp, result.GetRect());
+ }
+ }
+ catch (Exception)
+ {
+ if (result != null)
+ {
+ result.Dispose();
+ result = null;
+ }
+ }
+ return result;
+ }
}
}
\ No newline at end of file
diff --git a/VocaluxeLib/IBasic.cs b/VocaluxeLib/IBasic.cs
index e461c22b..f58ec27b 100644
--- a/VocaluxeLib/IBasic.cs
+++ b/VocaluxeLib/IBasic.cs
@@ -101,8 +101,8 @@ namespace VocaluxeLib
{
string GetThemeScreensPath(int partyModeID);
int GetSkinIndex(int partyModeID);
- CTexture GetSkinTexture(string textureName, int partyModeID);
- CTexture GetSkinVideoTexture(string videoName, int partyModeID);
+ CTextureRef GetSkinTexture(string textureName, int partyModeID);
+ CTextureRef GetSkinVideoTexture(string videoName, int partyModeID);
void SkinVideoResume(string videoName, int partyModeID);
void SkinVideoPause(string videoName, int partyModeID);
@@ -133,26 +133,27 @@ namespace VocaluxeLib
void Play();
void Stop();
- CTexture GetVideoTexture();
+ CTextureRef GetVideoTexture();
void LoadPreview(CSong song, float start = 0f);
void PlayPreview(float start = -1f);
void StopPreview();
-
}
public interface IDrawing
{
- void DrawTexture(CTexture texture, SRectF rect);
- void DrawTexture(CTexture texture, SRectF rect, SColorF color);
- void DrawTexture(CTexture texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false);
- void DrawTextureReflection(CTexture texture, SRectF rect, SColorF color, SRectF bounds, float reflectionSpace, float reflectionHeight);
+ void DrawTexture(CTextureRef texture, SRectF rect);
+ void DrawTexture(CTextureRef texture, SRectF rect, SColorF color);
+ void DrawTexture(CTextureRef texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored = false);
+ void DrawTexture(CTextureRef textureRef, SRectF bounds, EAspect aspect);
+ void DrawTexture(CTextureRef textureRef, SRectF bounds, EAspect aspect, SColorF color);
+ void DrawTextureReflection(CTextureRef texture, SRectF rect, SColorF color, float reflectionSpace, float reflectionHeight);
- CTexture AddTexture(string fileName);
- void RemoveTexture(ref CTexture texture);
+ CTextureRef AddTexture(string fileName);
+ void RemoveTexture(ref CTextureRef texture);
- void DrawColor(SColorF color, SRectF rect);
- void DrawColorReflection(SColorF color, SRectF rect, float space, float height);
+ void DrawRect(SColorF color, SRectF rect);
+ void DrawRectReflection(SColorF color, SRectF rect, float space, float height);
}
public interface IGraphics
@@ -175,15 +176,11 @@ namespace VocaluxeLib
public interface IFonts
{
- void SetFont(string fontName);
- void SetStyle(EStyle fontStyle);
-
RectangleF GetTextBounds(CText text);
- RectangleF GetTextBounds(CText text, float textHeight);
- void DrawText(string text, float textHeight, float x, float y, float z, SColorF color);
- void DrawTextReflection(string text, float textHeight, float x, float y, float z, SColorF color, float reflectionSpace, float reflectionHeight);
- void DrawText(string text, float textHeight, float x, float y, float z, SColorF color, float begin, float end);
+ void DrawText(string text, CFont font, float x, float y, float z, SColorF color);
+ void DrawTextReflection(string text, CFont font, float x, float y, float z, SColorF color, float reflectionSpace, float reflectionHeight);
+ void DrawText(string text, CFont font, float x, float y, float z, SColorF color, float begin, float end);
}
public interface ILanguage
@@ -226,7 +223,7 @@ namespace VocaluxeLib
CProfile[] GetProfiles();
EGameDifficulty GetDifficulty(int profileID);
string GetPlayerName(int profileID, int playerNum = 0);
- CTexture GetAvatar(int profileID);
+ CTextureRef GetAvatar(int profileID);
CAvatar GetAvatarByFilename(string fileName);
bool IsProfileIDValid(int profileID);
bool IsGuest(int profileID);
@@ -267,7 +264,7 @@ namespace VocaluxeLib
{
int Load(string videoFileName);
bool Skip(int streamID, float startPosition, float videoGap);
- bool GetFrame(int streamID, ref CTexture videoTexture, float time, out float videoTime);
+ bool GetFrame(int streamID, ref CTextureRef videoTexture, float time, out float videoTime);
bool IsFinished(int streamID);
bool Close(int streamID);
void SetLoop(int streamID, bool loop = true);
@@ -292,12 +289,12 @@ namespace VocaluxeLib
public interface ICover
{
- CTexture GetNoCover();
+ CTextureRef GetNoCover();
}
public interface IDataBase
{
- bool GetCover(string fileName, ref CTexture texture, int coverSize);
+ bool GetCover(string fileName, ref CTextureRef texture, int coverSize);
bool GetDataBaseSongInfos(string artist, string title, out int numPlayed, out DateTime dateAdded, out int highscoreID);
}
@@ -336,10 +333,9 @@ namespace VocaluxeLib
void Load(CSong song, float start = 0f);
void Stop();
void TogglePause();
- CTexture GetCover();
- CTexture GetVideoTexture();
+ CTextureRef GetCover();
+ CTextureRef GetVideoTexture();
bool IsPlaying();
float GetLength();
-
}
}
\ No newline at end of file
diff --git a/VocaluxeLib/Menu/CBackground.cs b/VocaluxeLib/Menu/CBackground.cs
index 9e9c8317..46a64c3d 100644
--- a/VocaluxeLib/Menu/CBackground.cs
+++ b/VocaluxeLib/Menu/CBackground.cs
@@ -16,12 +16,12 @@
#endregion
using System;
-using System.Drawing;
using System.Xml;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Collections.Generic;
using VocaluxeLib.Draw;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
@@ -37,16 +37,11 @@ namespace VocaluxeLib.Menu
[XmlType("Background")]
public struct SThemeBackground
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
- [XmlElement("Type")]
- public EBackgroundTypes Type;
- [XmlArray]
- public List SlideShowTextures;
- [XmlElement("Video")]
- public string VideoName;
- [XmlElement("Skin")]
- public string TextureName;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
+ [XmlElement("Type")] public EBackgroundTypes Type;
+ [XmlArray] public List SlideShowTextures;
+ [XmlElement("Video")] public string VideoName;
+ [XmlElement("Skin")] public string TextureName;
public SThemeColor Color;
}
@@ -58,7 +53,7 @@ namespace VocaluxeLib.Menu
private int _SlideShowCurrent;
private readonly Stopwatch _SlideShowTimer = new Stopwatch();
- private readonly List _SlideShowTextures = new List();
+ private readonly List _SlideShowTextures = new List();
public SColorF Color;
public bool ThemeLoaded
@@ -149,36 +144,31 @@ namespace VocaluxeLib.Menu
CBase.Theme.SkinVideoPause(_Theme.VideoName, _PartyModeID);
}
- public bool Draw()
+ public void Draw()
{
bool ok = false;
- if (_Theme.Type == EBackgroundTypes.Video && CBase.Config.GetVideoBackgrounds() == EOffOn.TR_CONFIG_ON &&
- CBase.Config.GetVideosToBackground() == EOffOn.TR_CONFIG_ON && CBase.BackgroundMusic.IsPlaying() && CBase.BackgroundMusic.SongHasVideo() &&
- CBase.BackgroundMusic.VideoEnabled() && !CBase.BackgroundMusic.IsDisabled())
+ if (_Theme.Type == EBackgroundTypes.Video && CBase.Config.GetVideoBackgrounds() == EOffOn.TR_CONFIG_ON)
{
- Pause();
- ok = _DrawBackgroundMusicVideo();
+ if (CBase.Config.GetVideosToBackground() == EOffOn.TR_CONFIG_ON && CBase.BackgroundMusic.IsPlaying() && CBase.BackgroundMusic.SongHasVideo() &&
+ CBase.BackgroundMusic.VideoEnabled())
+ {
+ Pause();
+ ok = _DrawBackgroundMusicVideo();
+ }
+ else
+ {
+ Resume();
+ ok = _DrawVideo();
+ }
}
- else if (_Theme.Type == EBackgroundTypes.Video && CBase.Config.GetVideoBackgrounds() == EOffOn.TR_CONFIG_ON)
- {
- Resume();
- ok = _DrawVideo();
- }
-
-
- if (_Theme.Type == EBackgroundTypes.SlideShow && _Theme.SlideShowTextures.Count > 0)
+ else if (_Theme.Type == EBackgroundTypes.SlideShow && _Theme.SlideShowTextures.Count > 0)
ok = _DrawSlideShow();
- if (!String.IsNullOrEmpty(_Theme.TextureName) &&
- (_Theme.Type == EBackgroundTypes.Texture ||
- (_Theme.Type == EBackgroundTypes.Video && CBase.Config.GetVideoBackgrounds() == EOffOn.TR_CONFIG_OFF)))
+ if (!String.IsNullOrEmpty(_Theme.TextureName) && (_Theme.Type == EBackgroundTypes.Texture || !ok))
ok = _DrawTexture();
- if (_Theme.Type == EBackgroundTypes.Color || _Theme.Type == EBackgroundTypes.Texture && !ok ||
- (_Theme.Type == EBackgroundTypes.Video && CBase.Config.GetVideoBackgrounds() == EOffOn.TR_CONFIG_OFF && !ok))
+ if (_Theme.Type == EBackgroundTypes.Color || !ok)
_DrawColor();
-
- return true;
}
public void UnloadTextures()
@@ -200,7 +190,7 @@ namespace VocaluxeLib.Menu
_Theme.Type = EBackgroundTypes.SlideShow;
if (!String.IsNullOrEmpty(image))
{
- CTexture texture = CBase.Drawing.AddTexture(image);
+ CTextureRef texture = CBase.Drawing.AddTexture(image);
if (texture != null)
_SlideShowTextures.Add(texture);
}
@@ -208,9 +198,9 @@ namespace VocaluxeLib.Menu
public void RemoveSlideShowTextures()
{
- foreach (CTexture tex in _SlideShowTextures)
+ foreach (CTextureRef tex in _SlideShowTextures)
{
- CTexture texture = tex;
+ CTextureRef texture = tex;
CBase.Drawing.RemoveTexture(ref texture);
}
_SlideShowTextures.Clear();
@@ -229,23 +219,22 @@ namespace VocaluxeLib.Menu
#endregion public
#region internal
+ private static SRectF _GetDrawRect()
+ {
+ return new SRectF(0f, 0f, CBase.Settings.GetRenderW(), CBase.Settings.GetRenderH(), CBase.Settings.GetZFar() / 4);
+ }
+
private void _DrawColor()
{
- var bounds = new SRectF(0f, 0f, CBase.Settings.GetRenderW(), CBase.Settings.GetRenderH(), CBase.Settings.GetZFar() / 4);
-
- CBase.Drawing.DrawColor(Color, bounds);
+ CBase.Drawing.DrawRect(Color, _GetDrawRect());
}
private bool _DrawTexture()
{
- CTexture texture = CBase.Theme.GetSkinTexture(_Theme.TextureName, _PartyModeID);
+ CTextureRef texture = CBase.Theme.GetSkinTexture(_Theme.TextureName, _PartyModeID);
if (texture != null)
{
- var bounds = new RectangleF(0f, 0f, CBase.Settings.GetRenderW(), CBase.Settings.GetRenderH());
- RectangleF rect;
- CHelper.SetRect(bounds, out rect, texture.OrigAspect, EAspect.Crop);
-
- CBase.Drawing.DrawTexture(texture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, CBase.Settings.GetZFar() / 4));
+ CBase.Drawing.DrawTexture(texture, _GetDrawRect(), EAspect.Crop);
return true;
}
return false;
@@ -266,20 +255,16 @@ namespace VocaluxeLib.Menu
_SlideShowTimer.Restart();
if (_SlideShowCurrent + 1 < _SlideShowTextures.Count)
_SlideShowCurrent++;
- else if (_SlideShowCurrent != 0)
+ else
_SlideShowCurrent = 0;
}
- CTexture texture = _SlideShowTextures[_SlideShowCurrent];
+ CTextureRef texture = _SlideShowTextures[_SlideShowCurrent];
if (texture == null)
return false;
- var bounds = new RectangleF(0f, 0f, CBase.Settings.GetRenderW(), CBase.Settings.GetRenderH());
- RectangleF rect;
- CHelper.SetRect(bounds, out rect, texture.OrigAspect, EAspect.Crop);
-
- CBase.Drawing.DrawTexture(texture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, CBase.Settings.GetZFar() / 4));
+ CBase.Drawing.DrawTexture(texture, _GetDrawRect(), EAspect.Crop);
if (_SlideShowTimer.ElapsedMilliseconds >= CBase.Settings.GetSlideShowImageTime())
{
@@ -292,9 +277,9 @@ namespace VocaluxeLib.Menu
if (texture != null)
{
- float alpha = (_SlideShowTimer.ElapsedMilliseconds - CBase.Settings.GetSlideShowImageTime()) / CBase.Settings.GetSlideShowFadeTime();
- CHelper.SetRect(bounds, out rect, texture.OrigAspect, EAspect.Crop);
- CBase.Drawing.DrawTexture(texture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, (CBase.Settings.GetZFar() / 4) - 1), new SColorF(1, 1, 1, alpha));
+ SColorF color = texture.Color;
+ color.A = (_SlideShowTimer.ElapsedMilliseconds - CBase.Settings.GetSlideShowImageTime()) / CBase.Settings.GetSlideShowFadeTime();
+ CBase.Drawing.DrawTexture(texture, _GetDrawRect(), EAspect.Crop, color);
}
}
@@ -305,14 +290,10 @@ namespace VocaluxeLib.Menu
private bool _DrawVideo()
{
- CTexture videoTexture = CBase.Theme.GetSkinVideoTexture(_Theme.VideoName, _PartyModeID);
+ CTextureRef videoTexture = CBase.Theme.GetSkinVideoTexture(_Theme.VideoName, _PartyModeID);
if (videoTexture != null)
{
- var bounds = new RectangleF(0f, 0f, CBase.Settings.GetRenderW(), CBase.Settings.GetRenderH());
- RectangleF rect;
- CHelper.SetRect(bounds, out rect, videoTexture.OrigAspect, EAspect.Crop);
-
- CBase.Drawing.DrawTexture(videoTexture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, CBase.Settings.GetZFar() / 4));
+ CBase.Drawing.DrawTexture(videoTexture, _GetDrawRect(), EAspect.Crop);
return true;
}
return false;
@@ -320,14 +301,10 @@ namespace VocaluxeLib.Menu
private bool _DrawBackgroundMusicVideo()
{
- CTexture videoTexture = CBase.BackgroundMusic.GetVideoTexture();
+ CTextureRef videoTexture = CBase.BackgroundMusic.GetVideoTexture();
if (videoTexture != null)
{
- var bounds = new RectangleF(0f, 0f, CBase.Settings.GetRenderW(), CBase.Settings.GetRenderH());
- RectangleF rect;
- CHelper.SetRect(bounds, out rect, videoTexture.OrigAspect, EAspect.Crop);
-
- CBase.Drawing.DrawTexture(videoTexture, new SRectF(rect.X, rect.Y, rect.Width, rect.Height, CBase.Settings.GetZFar() / 4));
+ CBase.Drawing.DrawTexture(videoTexture, _GetDrawRect(), EAspect.Crop);
return true;
}
return false;
diff --git a/VocaluxeLib/Menu/CButton.cs b/VocaluxeLib/Menu/CButton.cs
index f2830195..d2652ba4 100644
--- a/VocaluxeLib/Menu/CButton.cs
+++ b/VocaluxeLib/Menu/CButton.cs
@@ -19,33 +19,25 @@ using System;
using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
[XmlType("Button")]
public struct SThemeButton
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("Skin")]
- public string TextureName;
- [XmlElement("SkinSelected")]
- public string SelTextureName;
+ [XmlElement("Skin")] public string TextureName;
+ [XmlElement("SkinSelected")] public string SelTextureName;
public SRectF Rect;
- [XmlElement("Color")]
- public SThemeColor Color;
- [XmlElement("SelColor")]
- public SThemeColor SelColor;
- [XmlElement("Text")]
- public SThemeText Text;
- [XmlElement("SText")]
- public SThemeText SText;
+ [XmlElement("Color")] public SThemeColor Color;
+ [XmlElement("SelColor")] public SThemeColor SelColor;
+ [XmlElement("Text")] public SThemeText Text;
+ [XmlElement("SText")] public SThemeText SText;
public bool STextSpecified;
- [XmlElement("Reflection")]
- public SReflection Reflection;
- [XmlElement("SelReflection")]
- public SReflection SelReflection;
+ [XmlElement("Reflection")] public SReflection Reflection;
+ [XmlElement("SelReflection")] public SReflection SelReflection;
}
public class CButton : IMenuElement
@@ -54,8 +46,8 @@ namespace VocaluxeLib.Menu
private bool _ThemeLoaded;
private readonly int _PartyModeID;
- public CTexture Texture;
- public CTexture SelTexture;
+ public CTextureRef Texture;
+ public CTextureRef SelTexture;
public SRectF Rect;
public SColorF Color;
public SColorF SelColor;
@@ -257,13 +249,12 @@ namespace VocaluxeLib.Menu
return _ThemeLoaded;
}
-
public void Draw(bool forceDraw = false)
{
if (!Visible && CBase.Settings.GetProgramState() != EProgramState.EditTheme && !forceDraw)
return;
- CTexture texture;
+ CTextureRef texture;
if (!Selected && !Pressed || !_Enabled)
{
@@ -273,7 +264,7 @@ namespace VocaluxeLib.Menu
if (_Reflection)
{
- CBase.Drawing.DrawTextureReflection(texture, Rect, Color, Rect, _ReflectionSpace, _ReflectionHeight);
+ CBase.Drawing.DrawTextureReflection(texture, Rect, Color, _ReflectionSpace, _ReflectionHeight);
Text.DrawRelative(Rect.X, Rect.Y, _ReflectionHeight, _ReflectionSpace, Rect.H);
}
else
@@ -287,7 +278,7 @@ namespace VocaluxeLib.Menu
if (_Reflection)
{
- CBase.Drawing.DrawTextureReflection(texture, Rect, SelColor, Rect, _ReflectionSpace, _ReflectionHeight);
+ CBase.Drawing.DrawTextureReflection(texture, Rect, SelColor, _ReflectionSpace, _ReflectionHeight);
Text.DrawRelative(Rect.X, Rect.Y, _ReflectionHeight, _ReflectionSpace, Rect.H);
}
else
@@ -301,7 +292,7 @@ namespace VocaluxeLib.Menu
if (_Reflection)
{
- CBase.Drawing.DrawTextureReflection(texture, Rect, SelColor, Rect, _ReflectionSpace, _ReflectionHeight);
+ CBase.Drawing.DrawTextureReflection(texture, Rect, SelColor, _ReflectionSpace, _ReflectionHeight);
_SelText.DrawRelative(Rect.X, Rect.Y, _ReflectionHeight, _ReflectionSpace, Rect.H);
}
else
diff --git a/VocaluxeLib/Menu/CEqualizer.cs b/VocaluxeLib/Menu/CEqualizer.cs
index 6cce6455..3faf40a1 100644
--- a/VocaluxeLib/Menu/CEqualizer.cs
+++ b/VocaluxeLib/Menu/CEqualizer.cs
@@ -18,6 +18,7 @@
using System;
using System.Xml;
using System.Xml.Serialization;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
@@ -29,30 +30,20 @@ namespace VocaluxeLib.Menu
[XmlType("Equalizer")]
public struct SThemeEqualizer
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("Skin")]
- public string TextureName;
+ [XmlElement("Skin")] public string TextureName;
- [XmlElement("Rect")]
- public SRectF Rect;
+ [XmlElement("Rect")] public SRectF Rect;
- [XmlElement("NumBars")]
- public int NumBars;
- [XmlElement("Space")]
- public float Space;
- [XmlElement("Style")]
- public EEqualizerStyle Style;
- [XmlElement("DrawNegative")]
- public EOffOn DrawNegative;
+ [XmlElement("NumBars")] public int NumBars;
+ [XmlElement("Space")] public float Space;
+ [XmlElement("Style")] public EEqualizerStyle Style;
+ [XmlElement("DrawNegative")] public EOffOn DrawNegative;
- [XmlElement("Color")]
- public SThemeColor Color;
- [XmlElement("MaxColor")]
- public SThemeColor MaxColor;
- [XmlElement("Reflection")]
- public SReflection Reflection;
+ [XmlElement("Color")] public SThemeColor Color;
+ [XmlElement("MaxColor")] public SThemeColor MaxColor;
+ [XmlElement("Reflection")] public SReflection Reflection;
}
public class CEqualizer : IMenuElement
@@ -249,10 +240,10 @@ namespace VocaluxeLib.Menu
if (i == _MaxBar)
color = MaxColor;
- CBase.Drawing.DrawColor(color, bar);
+ CBase.Drawing.DrawRect(color, bar);
if (Reflection)
- CBase.Drawing.DrawColorReflection(color, bar, ReflectionSpace, ReflectionHeight);
+ CBase.Drawing.DrawRectReflection(color, bar, ReflectionSpace, ReflectionHeight);
}
}
@@ -273,7 +264,7 @@ namespace VocaluxeLib.Menu
Rect = _Theme.Rect;
Space = _Theme.Space;
Reflection = _Theme.Reflection.Enabled;
- if(Reflection)
+ if (Reflection)
{
ReflectionHeight = _Theme.Reflection.Height;
ReflectionSpace = _Theme.Reflection.Space;
diff --git a/VocaluxeLib/Menu/CLyric.cs b/VocaluxeLib/Menu/CLyric.cs
index deddd67c..eb057bbd 100644
--- a/VocaluxeLib/Menu/CLyric.cs
+++ b/VocaluxeLib/Menu/CLyric.cs
@@ -19,22 +19,19 @@ using System;
using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Songs;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
[XmlType("Lyric")]
public struct SThemeLyrics
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("Rect")]
- public SRectF Rect;
+ [XmlElement("Rect")] public SRectF Rect;
- [XmlElement("Color")]
- public SThemeColor Color;
- [XmlElement("SColor")]
- public SThemeColor SColor;
+ [XmlElement("Color")] public SThemeColor Color;
+ [XmlElement("SColor")] public SThemeColor SColor;
}
public class CLyric : IMenuElement
@@ -192,10 +189,7 @@ namespace VocaluxeLib.Menu
private void _SetText(CSongNote note)
{
_Text.Text = note.Text;
- _Text.Style = EStyle.Bold;
-
- if (note.Type == ENoteType.Freestyle)
- _Text.Style = EStyle.BoldItalic;
+ _Text.Font.Style = (note.Type == ENoteType.Freestyle) ? EStyle.BoldItalic : EStyle.Bold;
}
public void Clear()
@@ -337,11 +331,11 @@ namespace VocaluxeLib.Menu
p = 1f - p;
float ty = _Text.Y;
- float th = _Text.Height;
+ float th = _Text.Font.Height;
float tz = _Text.Z;
SRectF normalRect = _Text.Rect;
- _Text.Height += _Text.Height * p * 0.4f;
+ _Text.Font.Height *= 1f + p * 0.4f;
_Text.X -= (_Text.Rect.W - normalRect.W) / 2f;
_Text.Y -= (_Text.Rect.H - normalRect.H) / 2f;
_Text.Z -= 0.1f;
@@ -351,7 +345,7 @@ namespace VocaluxeLib.Menu
_Text.Draw();
_Text.Y = ty;
- _Text.Height = th;
+ _Text.Font.Height = th;
_Text.Z = tz;
}
}
@@ -443,7 +437,7 @@ namespace VocaluxeLib.Menu
else
{
float y = _Text.Y;
- _Text.Y -= _Text.Height * 0.1f * p;
+ _Text.Y -= _Text.Font.Height * 0.1f * p;
_Text.Draw();
_Text.Y = y;
}
diff --git a/VocaluxeLib/Menu/CMenu.cs b/VocaluxeLib/Menu/CMenu.cs
index 2eea7aa4..500c1d82 100644
--- a/VocaluxeLib/Menu/CMenu.cs
+++ b/VocaluxeLib/Menu/CMenu.cs
@@ -25,6 +25,7 @@ using System.Xml.Serialization;
using VocaluxeLib.Draw;
using VocaluxeLib.Menu.SingNotes;
using VocaluxeLib.Menu.SongMenu;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
@@ -587,7 +588,7 @@ namespace VocaluxeLib.Menu
return new CStatic(oldStatic);
}
- public CStatic GetNewStatic(CTexture texture, SColorF color, SRectF rect)
+ public CStatic GetNewStatic(CTextureRef texture, SColorF color, SRectF rect)
{
return new CStatic(_PartyModeID, texture, color, rect);
}
@@ -632,7 +633,7 @@ namespace VocaluxeLib.Menu
return new CPlaylist(_PartyModeID);
}
- public CParticleEffect GetNewParticleEffect(int maxNumber, SColorF color, SRectF area, CTexture texture, float size, EParticleType type)
+ 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);
}
diff --git a/VocaluxeLib/Menu/CMenuPartyNameSelection.cs b/VocaluxeLib/Menu/CMenuPartyNameSelection.cs
index 76015829..f5a39dee 100644
--- a/VocaluxeLib/Menu/CMenuPartyNameSelection.cs
+++ b/VocaluxeLib/Menu/CMenuPartyNameSelection.cs
@@ -683,7 +683,7 @@ namespace VocaluxeLib.Menu
for (int i = 0; i < _TeamList[_CurrentTeam].Count; i++)
{
string name = CBase.Profiles.GetPlayerName(_TeamList[_CurrentTeam][i]);
- CTexture avatar = CBase.Profiles.GetAvatar(_TeamList[_CurrentTeam][i]);
+ CTextureRef avatar = CBase.Profiles.GetAvatar(_TeamList[_CurrentTeam][i]);
_SelectSlides[_SelectSlidePlayer].AddValue(name, avatar);
}
for (int i = _TeamList[_CurrentTeam].Count; i < _NumPlayerTeams[_CurrentTeam]; i++)
diff --git a/VocaluxeLib/Menu/CNameSelection.cs b/VocaluxeLib/Menu/CNameSelection.cs
index 3787d386..99a39a5d 100644
--- a/VocaluxeLib/Menu/CNameSelection.cs
+++ b/VocaluxeLib/Menu/CNameSelection.cs
@@ -22,56 +22,39 @@ using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
using VocaluxeLib.Profile;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
[XmlType("NameSelection")]
public struct SThemeNameSelection
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
- [XmlElement("Rect")]
- public SRectF Rect;
- [XmlElement("SkinEmptyTile")]
- public string TextureEmptyTileName;
- [XmlElement("ColorEmptyTile")]
- public SThemeColor ColorEmptyTile;
- [XmlElement("SkinTileSelected")]
- public string TextureTileSelectedName;
- [XmlElement("Tiles")]
- public SThemeNameSelectionTiles Tiles;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
+ [XmlElement("Rect")] public SRectF Rect;
+ [XmlElement("SkinEmptyTile")] public string TextureEmptyTileName;
+ [XmlElement("ColorEmptyTile")] public SThemeColor ColorEmptyTile;
+ [XmlElement("SkinTileSelected")] public string TextureTileSelectedName;
+ [XmlElement("Tiles")] public SThemeNameSelectionTiles Tiles;
}
public struct SThemeNameSelectionTiles
{
- [XmlElement("W")]
- public int W;
- [XmlElement("H")]
- public int H;
- [XmlElement("NumW")]
- public int NumW;
- [XmlElement("NumH")]
- public int NumH;
- [XmlElement("SpaceW")]
- public float SpaceW;
- [XmlElement("SpaceH")]
- public float SpaceH;
- [XmlElement("Name")]
- public SThemeNameSelectionName Name;
+ [XmlElement("W")] public int W;
+ [XmlElement("H")] public int H;
+ [XmlElement("NumW")] public int NumW;
+ [XmlElement("NumH")] public int NumH;
+ [XmlElement("SpaceW")] public float SpaceW;
+ [XmlElement("SpaceH")] public float SpaceH;
+ [XmlElement("Name")] public SThemeNameSelectionName Name;
}
public struct SThemeNameSelectionName
{
- [XmlElement("Space")]
- public float Space;
- [XmlElement("H")]
- public float Height;
- [XmlElement("Font")]
- public string Font;
- [XmlElement("Style")]
- public EStyle Style;
- [XmlElement("Color")]
- public SThemeColor Color;
+ [XmlElement("Space")] public float Space;
+ [XmlElement("H")] public float Height;
+ [XmlElement("Font")] public string Font;
+ [XmlElement("Style")] public EStyle Style;
+ [XmlElement("Color")] public SThemeColor Color;
}
public class CNameSelection : IMenuElement
@@ -110,16 +93,15 @@ namespace VocaluxeLib.Menu
public SRectF Rect;
private readonly List _Tiles;
- private CTexture _TextureEmptyTile;
- private CTexture _TextureTileSelected;
- public CTexture TextureEmptyTile
+ private CTextureRef _TextureEmptyTile;
+ private CTextureRef _TextureTileSelected;
+ public CTextureRef TextureEmptyTile
{
get { return _TextureEmptyTile; }
}
public SColorF ColorEmptyTile;
-
public int Offset;
private int _ActualSelection = -1;
public int Selection = -1;
@@ -517,9 +499,11 @@ namespace VocaluxeLib.Menu
{
for (int j = 0; j < _Theme.Tiles.NumW; j++)
{
- var rect = new SRectF(Rect.X + j * (_Theme.Tiles.W + _Theme.Tiles.SpaceW), Rect.Y + i * (_Theme.Tiles.H + _Theme.Tiles.SpaceH), _Theme.Tiles.W, _Theme.Tiles.H, Rect.Z);
+ var rect = new SRectF(Rect.X + j * (_Theme.Tiles.W + _Theme.Tiles.SpaceW), Rect.Y + i * (_Theme.Tiles.H + _Theme.Tiles.SpaceH), _Theme.Tiles.W, _Theme.Tiles.H,
+ Rect.Z);
var tileStatic = new CStatic(_PartyModeID, _TextureEmptyTile, ColorEmptyTile, rect) {Aspect = EAspect.Crop};
- var tileText = new CText(rect.X + rect.W / 2, rect.Y + rect.H + _Theme.Tiles.Name.Space, rect.Z, _Theme.Tiles.Name.Height, rect.W, EAlignment.Center, _Theme.Tiles.Name.Style,
+ var tileText = new CText(rect.X + rect.W / 2, rect.Y + rect.H + _Theme.Tiles.Name.Space, rect.Z, _Theme.Tiles.Name.Height, rect.W, EAlignment.Center,
+ _Theme.Tiles.Name.Style,
_Theme.Tiles.Name.Font, _Theme.Tiles.Name.Color.Color, "");
_Tiles.Add(new CTile(tileStatic, tileText, -1));
}
diff --git a/VocaluxeLib/Menu/CParticle.cs b/VocaluxeLib/Menu/CParticle.cs
index f0ba52a5..b21d52f6 100644
--- a/VocaluxeLib/Menu/CParticle.cs
+++ b/VocaluxeLib/Menu/CParticle.cs
@@ -21,27 +21,21 @@ using System.Diagnostics;
using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
[XmlType("ParticleEffect")]
public struct SThemeParticleEffect
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("Skin")]
- public string TextureName;
- [XmlElement("Rect")]
- public SRectF Rect;
- [XmlElement("Color")]
- public SThemeColor Color;
- [XmlElement("Type")]
- public EParticleType Type;
- [XmlElement("Size")]
- public float Size;
- [XmlElement("MaxNumber")]
- public int MaxNumber;
+ [XmlElement("Skin")] public string TextureName;
+ [XmlElement("Rect")] public SRectF Rect;
+ [XmlElement("Color")] public SThemeColor Color;
+ [XmlElement("Type")] public EParticleType Type;
+ [XmlElement("Size")] public float Size;
+ [XmlElement("MaxNumber")] public int MaxNumber;
}
public enum EParticleType
@@ -58,7 +52,7 @@ namespace VocaluxeLib.Menu
#region private vars
private readonly int _PartyModeID;
private readonly string _TextureName;
- private readonly CTexture _Texture;
+ private readonly CTextureRef _Texture;
private SRectF _Rect;
private float _Size;
private SColorF _Color;
@@ -141,7 +135,7 @@ namespace VocaluxeLib.Menu
_Rotation = (float)(CBase.Game.GetRandomDouble() * 360.0);
}
- public CParticle(int partyModeID, CTexture texture, SColorF color, float x, float y, float size, float maxage, float z, float vx, float vy, float vr, float vsize,
+ public CParticle(int partyModeID, CTextureRef texture, SColorF color, float x, float y, float size, float maxage, float z, float vx, float vy, float vr, float vsize,
EParticleType type)
{
_PartyModeID = partyModeID;
@@ -159,8 +153,6 @@ namespace VocaluxeLib.Menu
_MaxAge = maxage;
_Rotation = (float)(CBase.Game.GetRandomDouble() * 360.0);
}
-
-
#endregion Constructors
public void Update()
@@ -316,7 +308,7 @@ namespace VocaluxeLib.Menu
private SThemeParticleEffect _Theme;
private bool _ThemeLoaded;
- public CTexture Texture;
+ public CTextureRef Texture;
public SColorF Color;
public SRectF Rect;
@@ -370,7 +362,7 @@ namespace VocaluxeLib.Menu
Visible = true;
}
- public CParticleEffect(int partyModeID, int maxNumber, SColorF color, SRectF rect, CTexture texture, float size, EParticleType type)
+ public CParticleEffect(int partyModeID, int maxNumber, SColorF color, SRectF rect, CTextureRef texture, float size, EParticleType type)
{
_PartyModeID = partyModeID;
_Theme = new SThemeParticleEffect();
diff --git a/VocaluxeLib/Menu/CPlaylist.cs b/VocaluxeLib/Menu/CPlaylist.cs
index e1f283c6..57381f9a 100644
--- a/VocaluxeLib/Menu/CPlaylist.cs
+++ b/VocaluxeLib/Menu/CPlaylist.cs
@@ -21,6 +21,7 @@ using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Songs;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
@@ -57,48 +58,31 @@ namespace VocaluxeLib.Menu
[XmlType("Playlist")]
public struct SThemePlaylist
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("Rect")]
- public SRectF Rect;
+ [XmlElement("Rect")] public SRectF Rect;
- [XmlElement("EntryHeight")]
- public float EntryHeight;
+ [XmlElement("EntryHeight")] public float EntryHeight;
- [XmlElement("SkinBackground")]
- public string TextureBackgroundName;
- [XmlElement("SkinBackgroundSelected")]
- public string SelTextureBackgroundName;
+ [XmlElement("SkinBackground")] public string TextureBackgroundName;
+ [XmlElement("SkinBackgroundSelected")] public string SelTextureBackgroundName;
- [XmlElement("ColorBackground")]
- public SThemeColor ColorBackground;
- [XmlElement("SColorBackground")]
- public SThemeColor SelColorBackground;
+ [XmlElement("ColorBackground")] public SThemeColor ColorBackground;
+ [XmlElement("SColorBackground")] public SThemeColor SelColorBackground;
- [XmlElement("Text1")]
- public SThemeText SText1;
+ [XmlElement("Text1")] public SThemeText SText1;
- [XmlElement("StaticCover")]
- public SThemeStatic SStaticCover;
- [XmlElement("StaticPlaylistHeader")]
- public SThemeStatic SStaticPlaylistHeader;
- [XmlElement("StaticPlaylistFooter")]
- public SThemeStatic SStaticPlaylistFooter;
+ [XmlElement("StaticCover")] public SThemeStatic SStaticCover;
+ [XmlElement("StaticPlaylistHeader")] public SThemeStatic SStaticPlaylistHeader;
+ [XmlElement("StaticPlaylistFooter")] public SThemeStatic SStaticPlaylistFooter;
- [XmlElement("ButtonPlaylistName")]
- public SThemeButton SButtonPlaylistName;
- [XmlElement("ButtonPlaylistClose")]
- public SThemeButton SButtonPlaylistClose;
- [XmlElement("ButtonPlaylistSave")]
- public SThemeButton SButtonPlaylistSave;
- [XmlElement("ButtonPlaylistDelete")]
- public SThemeButton SButtonPlaylistDelete;
- [XmlElement("ButtonPlaylistSing")]
- public SThemeButton SButtonPlaylistSing;
+ [XmlElement("ButtonPlaylistName")] public SThemeButton SButtonPlaylistName;
+ [XmlElement("ButtonPlaylistClose")] public SThemeButton SButtonPlaylistClose;
+ [XmlElement("ButtonPlaylistSave")] public SThemeButton SButtonPlaylistSave;
+ [XmlElement("ButtonPlaylistDelete")] public SThemeButton SButtonPlaylistDelete;
+ [XmlElement("ButtonPlaylistSing")] public SThemeButton SButtonPlaylistSing;
- [XmlElement("SelectSlideGameMode")]
- public SThemeSelectSlide SSelectSlideGameMode;
+ [XmlElement("SelectSlideGameMode")] public SThemeSelectSlide SSelectSlideGameMode;
}
public class CPlaylist : IMenuElement
@@ -187,7 +171,7 @@ namespace VocaluxeLib.Menu
public SColorF BackgroundSelColor;
public CButton ButtonPlaylistName;
- public CButton ButtonPlaylistClose;
+ public CButton ButtonPlaylistClose;
public CButton ButtonPlaylistSave;
public CButton ButtonPlaylistDelete;
public CButton ButtonPlaylistSing;
@@ -353,7 +337,7 @@ namespace VocaluxeLib.Menu
_ThemeLoaded &= ButtonPlaylistSave.LoadTheme(item, "ButtonPlaylistSave", xmlReader, skinIndex);
_ThemeLoaded &= ButtonPlaylistDelete.LoadTheme(item, "ButtonPlaylistDelete", xmlReader, skinIndex);
- _ThemeLoaded &=SelectSlideGameMode.LoadTheme(item, "SelectSlideGameMode", xmlReader, skinIndex);
+ _ThemeLoaded &= SelectSlideGameMode.LoadTheme(item, "SelectSlideGameMode", xmlReader, skinIndex);
_ThemeLoaded &= xmlReader.TryGetFloatValue(item + "/EntryHeight", ref _Theme.EntryHeight);
if (_ThemeLoaded)
@@ -366,11 +350,11 @@ namespace VocaluxeLib.Menu
_Theme.SStaticCover = StaticCover.GetTheme();
_Theme.SStaticPlaylistFooter = StaticPlaylistFooter.GetTheme();
_Theme.SStaticPlaylistHeader = StaticPlaylistHeader.GetTheme();
- _Theme.SButtonPlaylistName =ButtonPlaylistName.GetTheme();
- _Theme.SButtonPlaylistSing =ButtonPlaylistSing.GetTheme();
- _Theme.SButtonPlaylistClose =ButtonPlaylistClose.GetTheme();
- _Theme.SButtonPlaylistSave =ButtonPlaylistSave.GetTheme();
- _Theme.SButtonPlaylistDelete =ButtonPlaylistDelete.GetTheme();
+ _Theme.SButtonPlaylistName = ButtonPlaylistName.GetTheme();
+ _Theme.SButtonPlaylistSing = ButtonPlaylistSing.GetTheme();
+ _Theme.SButtonPlaylistClose = ButtonPlaylistClose.GetTheme();
+ _Theme.SButtonPlaylistSave = ButtonPlaylistSave.GetTheme();
+ _Theme.SButtonPlaylistDelete = ButtonPlaylistDelete.GetTheme();
LoadTextures();
}
@@ -405,7 +389,7 @@ namespace VocaluxeLib.Menu
public bool IsMouseOver(SMouseEvent mouseEvent)
{
- return CHelper.IsInBounds(CompleteRect, mouseEvent.X, mouseEvent.Y) || _Interactions.IsMouseOver(mouseEvent);
+ return CHelper.IsInBounds(CompleteRect, mouseEvent) || _Interactions.IsMouseOver(mouseEvent);
}
public void UnloadTextures()
diff --git a/VocaluxeLib/Menu/CScreenSetting.cs b/VocaluxeLib/Menu/CScreenSetting.cs
index 7c003865..2bbc887c 100644
--- a/VocaluxeLib/Menu/CScreenSetting.cs
+++ b/VocaluxeLib/Menu/CScreenSetting.cs
@@ -19,6 +19,7 @@ using System;
using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
@@ -33,12 +34,9 @@ namespace VocaluxeLib.Menu
[XmlType("ScreenSetting")]
public struct SScreenSetting
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
- [XmlElement("Value")]
- public string Value;
- [XmlElement("Type")]
- public ESettingType Type;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
+ [XmlElement("Value")] public string Value;
+ [XmlElement("Type")] public ESettingType Type;
}
// ReSharper disable ClassNeverInstantiated.Global
@@ -131,7 +129,7 @@ namespace VocaluxeLib.Menu
}
}
- private CTexture _GetTextureValue(string value)
+ private CTextureRef _GetTextureValue(string value)
{
return CBase.Theme.GetSkinTexture(value, _PartyModeID);
}
diff --git a/VocaluxeLib/Menu/CSelectSlide.cs b/VocaluxeLib/Menu/CSelectSlide.cs
index 3167b238..05289057 100644
--- a/VocaluxeLib/Menu/CSelectSlide.cs
+++ b/VocaluxeLib/Menu/CSelectSlide.cs
@@ -18,75 +18,50 @@
using System;
using System.Collections.Generic;
using System.Drawing;
-using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
[XmlType("SelectSlide")]
public struct SThemeSelectSlide
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("Skin")]
- public string TextureName;
- [XmlElement("SkinArrowLeft")]
- public string TextureArrowLeftName;
- [XmlElement("SkinArrowRight")]
- public string TextureArrowRightName;
+ [XmlElement("Skin")] public string TextureName;
+ [XmlElement("SkinArrowLeft")] public string TextureArrowLeftName;
+ [XmlElement("SkinArrowRight")] public string TextureArrowRightName;
- [XmlElement("SkinSelected")]
- public string SelTextureName;
- [XmlElement("SkinArrowLeftSelected")]
- public string SelTextureArrowLeftName;
- [XmlElement("SkinArrowRightSelected")]
- public string SelTextureArrowRightName;
+ [XmlElement("SkinSelected")] public string SelTextureName;
+ [XmlElement("SkinArrowLeftSelected")] public string SelTextureArrowLeftName;
+ [XmlElement("SkinArrowRightSelected")] public string SelTextureArrowRightName;
- [XmlElement("SkinHighlighted")]
- public string HighlightTextureName;
+ [XmlElement("SkinHighlighted")] public string HighlightTextureName;
- [XmlElement("Rect")]
- public SRectF Rect;
- [XmlElement("RectArrowLeft")]
- public SRectF RectArrowLeft;
- [XmlElement("RectArrowRight")]
- public SRectF RectArrowRight;
+ [XmlElement("Rect")] public SRectF Rect;
+ [XmlElement("RectArrowLeft")] public SRectF RectArrowLeft;
+ [XmlElement("RectArrowRight")] public SRectF RectArrowRight;
- [XmlElement("Color")]
- public SThemeColor Color;
- [XmlElement("SColor")]
- public SThemeColor SColor;
- [XmlElement("HColor")]
- public SThemeColor HColor;
+ [XmlElement("Color")] public SThemeColor Color;
+ [XmlElement("SColor")] public SThemeColor SColor;
+ [XmlElement("HColor")] public SThemeColor HColor;
- [XmlElement("ArrowColor")]
- public SThemeColor ArrowColor;
- [XmlElement("ArrowSColor")]
- public SThemeColor ArrowSColor;
+ [XmlElement("ArrowColor")] public SThemeColor ArrowColor;
+ [XmlElement("ArrowSColor")] public SThemeColor ArrowSColor;
- [XmlElement("TextColor")]
- public SThemeColor TextColor;
- [XmlElement("TextSColor")]
- public SThemeColor TextSColor;
+ [XmlElement("TextColor")] public SThemeColor TextColor;
+ [XmlElement("TextSColor")] public SThemeColor TextSColor;
- [XmlElement("TextH")]
- public float TextH;
- [XmlElement("TextRelativeX")]
- public float TextRelativeX;
- [XmlElement("TextRelativeY")]
- public float TextRelativeY;
- [XmlElement("TextMaxW")]
- public float TextMaxW;
+ [XmlElement("TextH")] public float TextH;
+ [XmlElement("TextRelativeX")] public float TextRelativeX;
+ [XmlElement("TextRelativeY")] public float TextRelativeY;
+ [XmlElement("TextMaxW")] public float TextMaxW;
- [XmlElement("TextFont")]
- public string TextFont;
- [XmlElement("TextStyle")]
- public EStyle TextStyle;
+ [XmlElement("TextFont")] public string TextFont;
+ [XmlElement("TextStyle")] public EStyle TextStyle;
- [XmlElement("NumVisible")]
- public int NumVisible;
+ [XmlElement("NumVisible")] public int NumVisible;
}
public class CSelectSlide : IMenuElement, ICloneable
@@ -154,7 +129,7 @@ namespace VocaluxeLib.Menu
private readonly List _ValueNames;
private readonly List _ValuePartyModeIDs;
- private readonly List _Textures;
+ private readonly List _Textures;
private readonly List _ValueIndexes;
private readonly List _ValueBounds = new List();
@@ -222,7 +197,7 @@ namespace VocaluxeLib.Menu
MaxW = 0f;
_Selected = false;
- _Textures = new List();
+ _Textures = new List();
_ValueIndexes = new List();
_ValueNames = new List();
_ValuePartyModeIDs = new List();
@@ -270,7 +245,7 @@ namespace VocaluxeLib.Menu
MaxW = slide.MaxW;
_Selected = slide._Selected;
- _Textures = new List(slide._Textures);
+ _Textures = new List(slide._Textures);
_ValueIndexes = new List(slide._ValueIndexes);
_ValueNames = new List(slide._ValueNames);
_ValueBounds = new List(slide._ValueBounds);
@@ -288,7 +263,7 @@ namespace VocaluxeLib.Menu
_Theme = theme;
_Selected = false;
- _Textures = new List();
+ _Textures = new List();
_ValueIndexes = new List();
_ValueNames = new List();
_ValuePartyModeIDs = new List();
@@ -444,17 +419,17 @@ namespace VocaluxeLib.Menu
AddValue(value, null, _ValueIndexes.Count, partyModeID);
}
- public void AddValue(string value, CTexture texture)
+ public void AddValue(string value, CTextureRef texture)
{
AddValue(value, texture, _ValueIndexes.Count, _PartyModeID);
}
- private void _AddValue(string value, CTexture texture, int valueIndex)
+ private void _AddValue(string value, CTextureRef texture, int valueIndex)
{
AddValue(value, texture, valueIndex, _PartyModeID);
}
- public void AddValue(string value, CTexture texture, int valueIndex, int partyModeID)
+ public void AddValue(string value, CTextureRef texture, int valueIndex, int partyModeID)
{
_ValueNames.Add(value);
_Textures.Add(texture);
@@ -475,7 +450,7 @@ namespace VocaluxeLib.Menu
_ValueBounds.Clear();
}
- public void AddValues(string[] values, CTexture[] textures)
+ public void AddValues(string[] values, CTextureRef[] textures)
{
if (values.Length != textures.Length)
return;
@@ -499,7 +474,7 @@ namespace VocaluxeLib.Menu
RenameValue(Selection, newName);
}
- public void RenameValue(int selection, string newName, CTexture newTexture = null)
+ public void RenameValue(int selection, string newName, CTextureRef newTexture = null)
{
if (selection < 0 && selection >= _ValueNames.Count)
return;
@@ -623,15 +598,15 @@ namespace VocaluxeLib.Menu
if (!Visible && CBase.Settings.GetProgramState() != EProgramState.EditTheme)
return;
- CTexture texture = CBase.Theme.GetSkinTexture(_Theme.TextureName, _PartyModeID);
- CTexture textureArrowLeft = CBase.Theme.GetSkinTexture(_Theme.TextureArrowLeftName, _PartyModeID);
- CTexture textureArrowRight = CBase.Theme.GetSkinTexture(_Theme.TextureArrowRightName, _PartyModeID);
+ CTextureRef texture = CBase.Theme.GetSkinTexture(_Theme.TextureName, _PartyModeID);
+ CTextureRef textureArrowLeft = CBase.Theme.GetSkinTexture(_Theme.TextureArrowLeftName, _PartyModeID);
+ CTextureRef textureArrowRight = CBase.Theme.GetSkinTexture(_Theme.TextureArrowRightName, _PartyModeID);
- CTexture selTexture = CBase.Theme.GetSkinTexture(_Theme.SelTextureName, _PartyModeID);
- CTexture selTextureArrowLeft = CBase.Theme.GetSkinTexture(_Theme.SelTextureArrowLeftName, _PartyModeID);
- CTexture selTextureArrowRight = CBase.Theme.GetSkinTexture(_Theme.SelTextureArrowRightName, _PartyModeID);
+ CTextureRef selTexture = CBase.Theme.GetSkinTexture(_Theme.SelTextureName, _PartyModeID);
+ CTextureRef selTextureArrowLeft = CBase.Theme.GetSkinTexture(_Theme.SelTextureArrowLeftName, _PartyModeID);
+ CTextureRef selTextureArrowRight = CBase.Theme.GetSkinTexture(_Theme.SelTextureArrowRightName, _PartyModeID);
- CTexture highlightTexture = CBase.Theme.GetSkinTexture(_Theme.HighlightTextureName, _PartyModeID);
+ CTextureRef highlightTexture = CBase.Theme.GetSkinTexture(_Theme.HighlightTextureName, _PartyModeID);
if (Selected)
{
@@ -773,7 +748,6 @@ namespace VocaluxeLib.Menu
TextRelativeX = _Theme.TextRelativeX;
TextRelativeY = _Theme.TextRelativeY;
MaxW = _Theme.TextMaxW;
-
}
public void ReloadTextures()
diff --git a/VocaluxeLib/Menu/CStatic.cs b/VocaluxeLib/Menu/CStatic.cs
index b8012f4b..a223dc05 100644
--- a/VocaluxeLib/Menu/CStatic.cs
+++ b/VocaluxeLib/Menu/CStatic.cs
@@ -19,16 +19,15 @@ using System;
using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
[XmlType("Static")]
public struct SThemeStatic
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
- [XmlElement("Skin")]
- public string TextureName;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
+ [XmlElement("Skin")] public string TextureName;
public SThemeColor Color;
public SRectF Rect;
public SReflection Reflection;
@@ -51,8 +50,8 @@ namespace VocaluxeLib.Menu
get { return _ThemeLoaded; }
}
- private CTexture _Texture;
- public CTexture Texture
+ private CTextureRef _Texture;
+ public CTextureRef Texture
{
get { return _Texture ?? CBase.Theme.GetSkinTexture(_Theme.TextureName, _PartyModeID); }
@@ -73,10 +72,7 @@ namespace VocaluxeLib.Menu
public EAspect Aspect = EAspect.Stretch;
- public CStatic()
- {
-
- }
+ public CStatic() {}
public CStatic(int partyModeID)
{
@@ -99,7 +95,7 @@ namespace VocaluxeLib.Menu
Visible = s.Visible;
}
- public CStatic(int partyModeID, CTexture texture, SColorF color, SRectF rect)
+ public CStatic(int partyModeID, CTextureRef texture, SColorF color, SRectF rect)
{
_PartyModeID = partyModeID;
@@ -179,26 +175,27 @@ namespace VocaluxeLib.Menu
public void Draw(EAspect aspect, float scale = 1f, float zModify = 0f, bool forceDraw = false)
{
- CTexture texture = Texture ?? new CTexture((int)Rect.W, (int)Rect.H);
-
- SRectF bounds = Rect.Scale(scale);
- SRectF rect;
- if (aspect != EAspect.Stretch)
- CHelper.SetRect(bounds, out rect, texture.OrigAspect, aspect);
- else
- rect = bounds;
- rect.Z = Rect.Z + zModify;
+ CTextureRef texture = Texture;
+ SRectF rect = Rect.Scale(scale);
+ rect.Z += zModify;
+ if (texture != null)
+ rect = CHelper.FitInBounds(rect, texture.OrigAspect, aspect);
var color = new SColorF(Color.R, Color.G, Color.B, Color.A * Alpha);
if (Visible || forceDraw || (CBase.Settings.GetProgramState() == EProgramState.EditTheme))
{
- CBase.Drawing.DrawTexture(texture, rect, color, bounds);
- if (Reflection)
- CBase.Drawing.DrawTextureReflection(texture, rect, color, bounds, ReflectionSpace, ReflectionHeight);
+ if (texture != null)
+ {
+ CBase.Drawing.DrawTexture(texture, rect, color);
+ if (Reflection)
+ CBase.Drawing.DrawTextureReflection(texture, rect, color, ReflectionSpace, ReflectionHeight);
+ }
+ else
+ CBase.Drawing.DrawRect(color, rect);
}
if (Selected && (CBase.Settings.GetProgramState() == EProgramState.EditTheme))
- CBase.Drawing.DrawColor(new SColorF(1f, 1f, 1f, 0.5f), rect);
+ CBase.Drawing.DrawRect(new SColorF(1f, 1f, 1f, 0.5f), rect);
}
public void UnloadTextures() {}
diff --git a/VocaluxeLib/Menu/CText.cs b/VocaluxeLib/Menu/CText.cs
index bb6d567e..9f8c164f 100644
--- a/VocaluxeLib/Menu/CText.cs
+++ b/VocaluxeLib/Menu/CText.cs
@@ -17,43 +17,32 @@
using System;
using System.Drawing;
-using System.Xml;
using System.Xml.Serialization;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
[XmlType("Text")]
public struct SThemeText
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("X")]
- public float X;
- [XmlElement("Y")]
- public float Y;
- [XmlElement("Z")]
- public float Z;
- [XmlElement("H")]
- public float Height;
- [XmlElement("MaxW")]
- public float MaxWidth;
+ [XmlElement("X")] public float X;
+ [XmlElement("Y")] public float Y;
+ [XmlElement("Z")] public float Z;
+ [XmlElement("H")] public float FontHeight;
+ [XmlElement("MaxW")] public float MaxWidth;
public SThemeColor Color;
public SThemeColor SColor; //for Buttons
- [XmlElement("Align")]
- public EAlignment Align;
- [XmlElement("ResizeAlign")]
- public EHAlignment ResizeAlign;
- [XmlElement("Style")]
- public EStyle Style;
- [XmlElement("Font")]
- public string Font;
- [XmlElement("Text")]
- public string Text;
+ [XmlElement("Align")] public EAlignment Align;
+ [XmlElement("ResizeAlign")] public EHAlignment ResizeAlign;
+ [XmlElement("Style")] public EStyle FontStyle;
+ [XmlElement("Font")] public string FontFamily;
+ [XmlElement("Text")] public string Text;
public SReflection Reflection;
}
- public class CText : IMenuElement
+ public class CText : IMenuElement, IFontObserver
{
private SThemeText _Theme;
private bool _ThemeLoaded;
@@ -110,20 +99,6 @@ namespace VocaluxeLib.Menu
set { _Z = value; }
}
- private float _Height;
- public float Height
- {
- get { return _Height; }
- set
- {
- if (Math.Abs(_Height - value) > 0.01)
- {
- _Height = value;
- _PositionNeedsUpdate = true;
- }
- }
- }
-
private float _MaxWidth;
public float MaxWidth
{
@@ -166,29 +141,17 @@ namespace VocaluxeLib.Menu
}
}
- private EStyle _Style = EStyle.Normal;
- public EStyle Style
- {
- get { return _Style; }
- set
- {
- if (_Style != value)
- {
- _Style = value;
- _PositionNeedsUpdate = true;
- }
- }
- }
-
- private string _Font = String.Empty;
- public string Font
+ private CFont _Font = new CFont();
+ public CFont Font
{
get { return _Font; }
set
{
- if (_Font != value)
+ if (!_Font.Equals(value))
{
+ _Font.RemoveObserver(this);
_Font = value;
+ _Font.AddObserver(this);
_PositionNeedsUpdate = true;
}
}
@@ -227,10 +190,16 @@ namespace VocaluxeLib.Menu
_Text = translation;
if (_EditMode)
_Text += "|";
+ //Reset height, it might have been reduced in _UpdatePosition
+ Font.Height = _Theme.FontHeight;
_PositionNeedsUpdate = true;
}
}
}
+ public string TranslatedText
+ {
+ get { return _Text; }
+ }
public int PartyModeID
{
@@ -274,7 +243,7 @@ namespace VocaluxeLib.Menu
{
_PartyModeID = partyModeID;
_TranslationID = _PartyModeID;
- _Font = "Normal";
+ _Font.AddObserver(this);
}
public CText(CText text)
@@ -285,12 +254,10 @@ namespace VocaluxeLib.Menu
_X = text._X;
_Y = text._Y;
_Z = text._Z;
- _Height = text._Height;
_MaxWidth = text._MaxWidth;
_Align = text._Align;
_ResizeAlign = text._ResizeAlign;
- _Style = text._Style;
- _Font = text._Font;
+ Font = text.Font; //Use setter to set observer
Color = new SColorF(text.Color);
SelColor = new SColorF(text.SelColor);
@@ -305,24 +272,23 @@ namespace VocaluxeLib.Menu
_EditMode = text._EditMode;
}
- public CText(float x, float y, float z, float h, float mw, EAlignment align, EStyle style, string font, SColorF col, string text, int partyModeID = -1, float rheight = 0,
- float rspace = 0)
+ public CText(float x, float y, float z, float h, float mw, EAlignment align, EStyle style, string fontFamily, SColorF col, string text, int partyModeID = -1,
+ float rheight = 0,
+ float rspace = 0) : this(partyModeID)
{
- _Theme = new SThemeText();
+ _Theme = new SThemeText {FontFamily = fontFamily, FontStyle = style, FontHeight = h, Text = text};
_ThemeLoaded = false;
_ButtonText = false;
- _PartyModeID = partyModeID;
- _TranslationID = _PartyModeID;
X = x;
Y = y;
Z = z;
- Height = h;
MaxWidth = mw;
Align = align;
ResizeAlign = EHAlignment.Center;
- Style = style;
- Font = font;
+ _Font.Name = fontFamily;
+ _Font.Style = style;
+ _Font.Height = h;
Color = col;
SelColor = new SColorF(col);
@@ -362,7 +328,6 @@ namespace VocaluxeLib.Menu
if (!buttonText)
_ThemeLoaded &= xmlReader.TryGetFloatValue(item + "/Z", ref _Z);
- _ThemeLoaded &= xmlReader.TryGetFloatValue(item + "/H", ref _Height);
xmlReader.TryGetFloatValue(item + "/MaxW", ref _MaxWidth);
if (xmlReader.GetValue(item + "/Color", out _Theme.Color.Name, String.Empty))
@@ -389,8 +354,9 @@ namespace VocaluxeLib.Menu
_ThemeLoaded &= xmlReader.TryGetEnumValue(item + "/Align", ref _Align);
xmlReader.TryGetEnumValue(item + "/ResizeAlign", ref _ResizeAlign);
- _ThemeLoaded &= xmlReader.TryGetEnumValue(item + "/Style", ref _Style);
- _ThemeLoaded &= xmlReader.GetValue(item + "/Font", out _Font, "Normal");
+ _ThemeLoaded &= xmlReader.TryGetFloatValue(item + "/H", ref _Theme.FontHeight);
+ _ThemeLoaded &= xmlReader.TryGetEnumValue(item + "/Style", ref _Theme.FontStyle);
+ _ThemeLoaded &= xmlReader.GetValue(item + "/Font", out _Theme.FontFamily);
_ThemeLoaded &= xmlReader.GetValue(item + "/Text", out _Theme.Text, String.Empty);
@@ -407,15 +373,12 @@ namespace VocaluxeLib.Menu
_Theme.Name = elementName;
_Theme.Align = _Align;
_Theme.Color.Color = Color;
- _Theme.Font = _Font;
_Theme.ResizeAlign = _ResizeAlign;
_Theme.SColor.Color = SelColor;
- _Theme.Style = _Style;
_Theme.MaxWidth = _MaxWidth;
_Theme.X = _X;
_Theme.Y = _Y;
_Theme.Z = _Z;
- _Theme.Height = _Height;
_ButtonText = buttonText;
_PositionNeedsUpdate = true;
@@ -425,7 +388,6 @@ namespace VocaluxeLib.Menu
return _ThemeLoaded;
}
-
public void Draw(bool forceDraw = false)
{
if (!forceDraw && !Visible && CBase.Settings.GetProgramState() != EProgramState.EditTheme)
@@ -434,30 +396,24 @@ namespace VocaluxeLib.Menu
// Update Text
Text = Text;
- CBase.Fonts.SetFont(Font);
- CBase.Fonts.SetStyle(Style);
-
SColorF currentColor = (Selected) ? SelColor : Color;
var color = new SColorF(currentColor.R, currentColor.G, currentColor.B, currentColor.A * Alpha);
- CBase.Fonts.DrawText(_Text, Rect.H, Rect.X, Rect.Y, Z, color);
+ CBase.Fonts.DrawText(_Text, Font, Rect.X, Rect.Y, Z, color);
if (ReflectionHeight > 0)
- CBase.Fonts.DrawTextReflection(_Text, Rect.H, Rect.X, Rect.Y, Z, color, ReflectionSpace, ReflectionHeight);
+ CBase.Fonts.DrawTextReflection(_Text, Font, Rect.X, Rect.Y, Z, color, ReflectionSpace, ReflectionHeight);
if (Selected && (CBase.Settings.GetProgramState() == EProgramState.EditTheme))
- CBase.Drawing.DrawColor(new SColorF(0.5f, 1f, 0.5f, 0.5f), new SRectF(Rect.X, Rect.Y, Rect.W, Rect.H, Z));
+ CBase.Drawing.DrawRect(new SColorF(0.5f, 1f, 0.5f, 0.5f), new SRectF(Rect.X, Rect.Y, Rect.W, Rect.H, Z));
}
public void Draw(float begin, float end)
{
- CBase.Fonts.SetFont(Font);
- CBase.Fonts.SetStyle(Style);
-
SColorF currentColor = (Selected) ? SelColor : Color;
var color = new SColorF(currentColor.R, currentColor.G, currentColor.B, currentColor.A * Alpha);
- CBase.Fonts.DrawText(Text, Rect.H, Rect.X, Rect.Y, Z, color, begin, end);
+ CBase.Fonts.DrawText(Text, Font, Rect.X, Rect.Y, Z, color, begin, end);
if (ReflectionHeight > 0)
{
@@ -465,7 +421,7 @@ namespace VocaluxeLib.Menu
}
if (Selected && (CBase.Settings.GetProgramState() == EProgramState.EditTheme))
- CBase.Drawing.DrawColor(new SColorF(0.5f, 1f, 0.5f, 0.5f), new SRectF(X, Y, Rect.W, Rect.H, Z));
+ CBase.Drawing.DrawRect(new SColorF(0.5f, 1f, 0.5f, 0.5f), new SRectF(X, Y, Rect.W, Rect.H, Z));
}
public void DrawRelative(float rx, float ry, float reflectionHeight = 0f, float reflectionSpace = 0f, float rectHeight = 0f)
@@ -505,12 +461,10 @@ namespace VocaluxeLib.Menu
_X = _Theme.X;
_Y = _Theme.Y;
_Z = _Theme.Z;
- _Height = _Theme.Height;
_MaxWidth = _Theme.MaxWidth;
_Align = _Theme.Align;
_ResizeAlign = _Theme.ResizeAlign;
- _Style = _Theme.Style;
- _Font = _Theme.Font;
+ Font = new CFont(_Theme.FontFamily, _Theme.FontStyle, _Theme.FontHeight);
if (_Theme.Reflection.Enabled)
{
@@ -541,17 +495,16 @@ namespace VocaluxeLib.Menu
X += stepX;
Y += stepY;
- _Theme.X += stepX;
- _Theme.Y += stepY;
+ _Theme.X = X;
+ _Theme.Y = Y;
}
public void ResizeElement(int stepW, int stepH)
{
- Height += stepH;
- if (Height <= 0)
- Height = 1;
-
- _Theme.Height = _Height;
+ _Theme.FontHeight += stepH;
+ if (_Theme.FontHeight <= 0)
+ _Theme.FontHeight = 1;
+ _Font.Height = _Theme.FontHeight;
}
#endregion ThemeEdit
@@ -560,10 +513,7 @@ namespace VocaluxeLib.Menu
if (_Text == "")
return;
- CBase.Fonts.SetFont(Font);
- CBase.Fonts.SetStyle(Style);
-
- float h = Height;
+ float h = Font.Height;
float y = Y;
RectangleF bounds = CBase.Fonts.GetTextBounds(this);
@@ -584,8 +534,8 @@ namespace VocaluxeLib.Menu
y += step * 0.75f;
break;
}
-
- bounds = CBase.Fonts.GetTextBounds(this, h);
+ Font.Height = h;
+ bounds = CBase.Fonts.GetTextBounds(this);
}
float x = X;
@@ -606,5 +556,10 @@ namespace VocaluxeLib.Menu
_PositionNeedsUpdate = false;
}
+
+ public void FontChanged()
+ {
+ _PositionNeedsUpdate = true;
+ }
}
}
\ No newline at end of file
diff --git a/VocaluxeLib/Menu/IMenuElement.cs b/VocaluxeLib/Menu/IMenuElement.cs
index dc805d70..391dd1ad 100644
--- a/VocaluxeLib/Menu/IMenuElement.cs
+++ b/VocaluxeLib/Menu/IMenuElement.cs
@@ -16,6 +16,7 @@
#endregion
using System.Xml;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu
{
diff --git a/VocaluxeLib/Menu/SingNotes/CSingNotes.cs b/VocaluxeLib/Menu/SingNotes/CSingNotes.cs
index 41b87e8a..276f586b 100644
--- a/VocaluxeLib/Menu/SingNotes/CSingNotes.cs
+++ b/VocaluxeLib/Menu/SingNotes/CSingNotes.cs
@@ -18,10 +18,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Xml;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
using VocaluxeLib.Songs;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu.SingNotes
{
@@ -42,42 +42,30 @@ namespace VocaluxeLib.Menu.SingNotes
}
[XmlType("Position")]
- public struct SBarPosition
+ public struct SBarPosition
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
public SRectF Rect;
}
[XmlType("SingBar")]
public struct SThemeSingBar
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("SkinLeft")]
- public string SkinLeftName;
- [XmlElement("SkinMiddle")]
- public string SkinMiddleName;
- [XmlElement("SkinRight")]
- public string SkinRightName;
+ [XmlElement("SkinLeft")] public string SkinLeftName;
+ [XmlElement("SkinMiddle")] public string SkinMiddleName;
+ [XmlElement("SkinRight")] public string SkinRightName;
- [XmlElement("SkinBackgroundLeft")]
- public string SkinBackgroundLeftName;
- [XmlElement("SkinBackgroundMiddle")]
- public string SkinBackgroundMiddleName;
- [XmlElement("SkinBackgroundRight")]
- public string SkinBackgroundRightName;
+ [XmlElement("SkinBackgroundLeft")] public string SkinBackgroundLeftName;
+ [XmlElement("SkinBackgroundMiddle")] public string SkinBackgroundMiddleName;
+ [XmlElement("SkinBackgroundRight")] public string SkinBackgroundRightName;
- [XmlElement("SkinGoldenStar")]
- public string SkinGoldenStarName;
- [XmlElement("SkinToneHelper")]
- public string SkinToneHelperName;
- [XmlElement("SkinPerfectNoteStart")]
- public string SkinPerfectNoteStarName;
+ [XmlElement("SkinGoldenStar")] public string SkinGoldenStarName;
+ [XmlElement("SkinToneHelper")] public string SkinToneHelperName;
+ [XmlElement("SkinPerfectNoteStart")] public string SkinPerfectNoteStarName;
- [XmlArray("BarPositions")]
- public SBarPosition[] BarPos;
+ [XmlArray("BarPositions")] public SBarPosition[] BarPos;
}
public abstract class CSingNotes : IMenuElement
@@ -116,7 +104,7 @@ namespace VocaluxeLib.Menu.SingNotes
_PlayerNotes = new List();
_ActID = 0;
- BarPos = new SRectF[CBase.Settings.GetMaxNumPlayer(), CBase.Settings.GetMaxNumPlayer()];
+ BarPos = new SRectF[CBase.Settings.GetMaxNumPlayer(),CBase.Settings.GetMaxNumPlayer()];
LoadTextures();
}
@@ -152,21 +140,18 @@ namespace VocaluxeLib.Menu.SingNotes
BarPos = new SRectF[CBase.Settings.GetMaxNumPlayer(),CBase.Settings.GetMaxNumPlayer()];
for (int numplayer = 0; numplayer < CBase.Settings.GetMaxNumPlayer(); numplayer++)
{
- for (int player = 0; player < CBase.Settings.GetMaxNumPlayer(); player++)
+ for (int player = 0; player <= numplayer; player++)
{
- if (player <= numplayer)
- {
- BarPos[player, numplayer] = new SRectF();
- string target = "/BarPositions/P" + (player + 1) + "N" + (numplayer + 1);
- _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "X", ref BarPos[player, numplayer].X);
- _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "Y", ref BarPos[player, numplayer].Y);
- _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "Z", ref BarPos[player, numplayer].Z);
- _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "W", ref BarPos[player, numplayer].W);
- _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "H", ref BarPos[player, numplayer].H);
- _Theme.BarPos[i].Name = "P" + (player + 1) + "N" + (numplayer + 1);
- _Theme.BarPos[i].Rect = new SRectF(BarPos[player, numplayer]);
- i++;
- }
+ BarPos[player, numplayer] = new SRectF();
+ string target = "/BarPositions/P" + (player + 1) + "N" + (numplayer + 1);
+ _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "X", ref BarPos[player, numplayer].X);
+ _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "Y", ref BarPos[player, numplayer].Y);
+ _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "Z", ref BarPos[player, numplayer].Z);
+ _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "W", ref BarPos[player, numplayer].W);
+ _ThemeLoaded &= xmlReader.TryGetFloatValue(item + target + "H", ref BarPos[player, numplayer].H);
+ _Theme.BarPos[i].Name = "P" + (player + 1) + "N" + (numplayer + 1);
+ _Theme.BarPos[i].Rect = new SRectF(BarPos[player, numplayer]);
+ i++;
}
}
@@ -179,7 +164,6 @@ namespace VocaluxeLib.Menu.SingNotes
return _ThemeLoaded;
}
-
public void Reset()
{
_PlayerNotes.Clear();
@@ -317,7 +301,7 @@ namespace VocaluxeLib.Menu.SingNotes
);
_DrawNoteBG(rect, color, 1f, _PlayerNotes[n].Timer);
- _DrawNote(rect, new SColorF(5f, 5f, 5f, 0.7f * _PlayerNotes[n].Alpha), 0.7f);
+ _DrawNote(rect, new SColorF(1f, 1f, 1f, 0.7f * _PlayerNotes[n].Alpha), 0.7f);
if (note.Type == ENoteType.Golden)
{
@@ -428,7 +412,7 @@ namespace VocaluxeLib.Menu.SingNotes
public void UnloadTextures() {}
- public void LoadTextures()
+ public void LoadTextures()
{
foreach (SBarPosition bp in _Theme.BarPos)
{
@@ -471,9 +455,9 @@ namespace VocaluxeLib.Menu.SingNotes
var noteRect = new SRectF(rect.X + dw, rect.Y + dh, rect.W - 2 * dw, rect.H - 2 * dh, rect.Z);
- CTexture noteBegin = CBase.Theme.GetSkinTexture(_Theme.SkinLeftName, _PartyModeID);
- CTexture noteMiddle = CBase.Theme.GetSkinTexture(_Theme.SkinMiddleName, _PartyModeID);
- CTexture noteEnd = CBase.Theme.GetSkinTexture(_Theme.SkinRightName, _PartyModeID);
+ CTextureRef noteBegin = CBase.Theme.GetSkinTexture(_Theme.SkinLeftName, _PartyModeID);
+ CTextureRef noteMiddle = CBase.Theme.GetSkinTexture(_Theme.SkinMiddleName, _PartyModeID);
+ CTextureRef noteEnd = CBase.Theme.GetSkinTexture(_Theme.SkinRightName, _PartyModeID);
//Width of each of the ends (round parts)
//Need 2 of them so use minimum
@@ -518,9 +502,9 @@ namespace VocaluxeLib.Menu.SingNotes
rect.Z
);
- CTexture noteBackgroundBegin = CBase.Theme.GetSkinTexture(_Theme.SkinBackgroundLeftName, _PartyModeID);
- CTexture noteBackgroundMiddle = CBase.Theme.GetSkinTexture(_Theme.SkinBackgroundMiddleName, _PartyModeID);
- CTexture noteBackgroundEnd = CBase.Theme.GetSkinTexture(_Theme.SkinBackgroundRightName, _PartyModeID);
+ CTextureRef noteBackgroundBegin = CBase.Theme.GetSkinTexture(_Theme.SkinBackgroundLeftName, _PartyModeID);
+ CTextureRef noteBackgroundMiddle = CBase.Theme.GetSkinTexture(_Theme.SkinBackgroundMiddleName, _PartyModeID);
+ CTextureRef noteBackgroundEnd = CBase.Theme.GetSkinTexture(_Theme.SkinBackgroundRightName, _PartyModeID);
float dx = r.H * noteBackgroundBegin.OrigAspect;
if (2 * dx > r.W)
@@ -538,12 +522,13 @@ namespace VocaluxeLib.Menu.SingNotes
CBase.Drawing.DrawTexture(noteBackgroundEnd, new SRectF(r.X + r.W - dx, r.Y, dx, r.H, r.Z), col);
}
- protected void _DrawNoteLines(SRectF rect, SColorF color)
+ private static void _DrawNoteLines(SRectF rect, SColorF color)
{
- for (int i = 0; i < CBase.Settings.GetNumNoteLines() - 1; i++)
+ SRectF lineRect = new SRectF(rect) {H = 1.5f};
+ for (int i = 0; i < CBase.Settings.GetNumNoteLines(); i++)
{
- float y = rect.Y + rect.H / CBase.Settings.GetNumNoteLines() * (i + 1);
- CBase.Drawing.DrawColor(color, new SRectF(rect.X, y, rect.W, 1, -1.0f));
+ lineRect.Y = rect.Y + rect.H / CBase.Settings.GetNumNoteLines() * (i + 1);
+ CBase.Drawing.DrawRect(color, lineRect);
}
}
@@ -613,7 +598,7 @@ namespace VocaluxeLib.Menu.SingNotes
rect.Z
);
- CTexture noteBegin = CBase.Theme.GetSkinTexture(_Theme.SkinLeftName, _PartyModeID);
+ CTextureRef noteBegin = CBase.Theme.GetSkinTexture(_Theme.SkinLeftName, _PartyModeID);
float dx = r.H * noteBegin.OrigAspect;
if (2 * dx > r.W)
dx = r.W / 2;
@@ -670,7 +655,7 @@ namespace VocaluxeLib.Menu.SingNotes
_PlayerNotes[n].Color.B,
_PlayerNotes[n].Color.A * _PlayerNotes[n].Alpha);
- CTexture toneHelper = CBase.Theme.GetSkinTexture(_Theme.SkinToneHelperName, _PartyModeID);
+ CTextureRef toneHelper = CBase.Theme.GetSkinTexture(_Theme.SkinToneHelperName, _PartyModeID);
CBase.Drawing.DrawTexture(toneHelper, drawRect, color);
diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenu.cs b/VocaluxeLib/Menu/SongMenu/CSongMenu.cs
index 529ec03b..1fcb9619 100644
--- a/VocaluxeLib/Menu/SongMenu/CSongMenu.cs
+++ b/VocaluxeLib/Menu/SongMenu/CSongMenu.cs
@@ -17,6 +17,7 @@
using System.Xml;
using VocaluxeLib.PartyModes;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu.SongMenu
{
diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs b/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs
index f7a27cc6..73e53075 100644
--- a/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs
+++ b/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs
@@ -23,34 +23,26 @@ using System.Xml.Serialization;
using VocaluxeLib.Draw;
using VocaluxeLib.PartyModes;
using VocaluxeLib.Songs;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu.SongMenu
{
[XmlType("SongMenu")]
public struct SThemeSongMenu
{
- [XmlAttributeAttribute(AttributeName = "Name")]
- public string Name;
+ [XmlAttribute(AttributeName = "Name")] public string Name;
- [XmlElement("CoverBackground")]
- public string CoverBackgroundName;
- [XmlElement("CoverBigBackground")]
- public string CoverBigBackgroundName;
- [XmlElement("DuetIcon")]
- public string DuetIconName;
- [XmlElement("VideoIcon")]
- public string VideoIconName;
- [XmlElement("MedleyCalcIcon")]
- public string MedleyCalcIcon;
- [XmlElement("MedleyTagIcon")]
- public string MedleyTagIcon;
- [XmlElement("Color")]
- public SThemeColor Color;
+ [XmlElement("CoverBackground")] public string CoverBackgroundName;
+ [XmlElement("CoverBigBackground")] public string CoverBigBackgroundName;
+ [XmlElement("DuetIcon")] public string DuetIconName;
+ [XmlElement("VideoIcon")] public string VideoIconName;
+ [XmlElement("MedleyCalcIcon")] public string MedleyCalcIcon;
+ [XmlElement("MedleyTagIcon")] public string MedleyTagIcon;
+ [XmlElement("Color")] public SThemeColor Color;
//public SThemeSongMenuBook songMenuBook;
//public SThemeSongMenuDreidel songMenuDreidel;
//public SThemeSongMenuList songMenuList;
- [XmlElement("SongMenuTileBoard")]
public SThemeSongMenuTileBoard SongMenuTileBoard;
public SThemeSongMenu(SThemeSongMenu theme)
@@ -69,65 +61,48 @@ namespace VocaluxeLib.Menu.SongMenu
public struct SThemeSongMenuTileBoard
{
- [XmlElement("NumW")]
///
/// Number of tiles horizontal
///
public int NumW;
- [XmlElement("NumH")]
///
/// Number of tiles vertical
///
public int NumH;
- [XmlElement("NumWsmall")]
///
/// Number of tiles horizontal in small-modus
///
public int NumWsmall;
-
- [XmlElement("NumHsmall")]
+
///
/// Number of tiles vertical in small-modus
///
public int NumHsmall;
- [XmlElement("SpaceW")]
///
/// Space between tiles horizontal
///
public float SpaceW;
- [XmlElement("SpaceH")]
///
/// Space between tiles vertical
///
public float SpaceH;
- [XmlElement("TileRect")]
public SRectF TileRect;
- [XmlElement("TileRectSmall")]
public SRectF TileRectSmall;
- [XmlElement("TextArtist")]
public SThemeText TextArtist;
- [XmlElement("TextTitle")]
public SThemeText TextTitle;
- [XmlElement("TextSongLength")]
public SThemeText TextSongLength;
- [XmlElement("StaticCoverBig")]
public SThemeStatic StaticCoverBig;
- [XmlElement("StaticTextBG")]
public SThemeStatic StaticTextBG;
- [XmlElement("StaticDuetIcon")]
public SThemeStatic StaticDuetIcon;
- [XmlElement("StaticVideoIcon")]
public SThemeStatic StaticVideoIcon;
- [XmlElement("StaticMedleyCalcIcon")]
public SThemeStatic StaticMedleyCalcIcon;
- [XmlElement("StaticMedleyTagIcon")]
public SThemeStatic StaticMedleyTagIcon;
}
@@ -278,7 +253,6 @@ namespace VocaluxeLib.Menu.SongMenu
return _ThemeLoaded;
}
-
#endregion Theme
public virtual void Init()
@@ -294,7 +268,7 @@ namespace VocaluxeLib.Menu.SongMenu
}
public virtual void OnShow() {}
-
+
public virtual void OnHide()
{
if(CBase.Graphics.GetNextScreen() != EScreens.ScreenNames || CBase.Config.GetBackgroundMusicStatus() == EBackgroundMusicOffOn.TR_CONFIG_OFF)
@@ -373,7 +347,6 @@ namespace VocaluxeLib.Menu.SongMenu
_ColorInternal = CBase.Theme.GetColor(_Theme.Color.Name, _PartyModeID);
else
_ColorInternal = _Theme.Color.Color;
-
}
public void ReloadTextures()
diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs b/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs
index 759a9585..8a3c8190 100644
--- a/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs
+++ b/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs
@@ -17,13 +17,13 @@
using System;
using System.Collections.Generic;
-using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Xml;
using VocaluxeLib.Draw;
using VocaluxeLib.PartyModes;
using VocaluxeLib.Songs;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Menu.SongMenu
{
@@ -38,8 +38,8 @@ namespace VocaluxeLib.Menu.SongMenu
private CStatic _MedleyCalcIcon;
private CStatic _MedleyTagIcon;
- private CTexture _CoverBigBGTexture;
- private CTexture _CoverBGTexture;
+ private CTextureRef _CoverBigBGTexture;
+ private CTextureRef _CoverBGTexture;
private CText _Artist;
private CText _Title;
@@ -494,20 +494,16 @@ namespace VocaluxeLib.Menu.SongMenu
_TextBG.Draw();
- CTexture vidtex = CBase.BackgroundMusic.IsPlayingPreview() ? CBase.BackgroundMusic.GetVideoTexture() : null;
+ CTextureRef vidtex = CBase.BackgroundMusic.IsPlayingPreview() ? CBase.BackgroundMusic.GetVideoTexture() : null;
if (vidtex != null)
{
if (vidtex.Color.A < 1)
_CoverBig.Draw(EAspect.Crop);
- var bounds = new RectangleF(_CoverBig.Rect.X, _CoverBig.Rect.Y, _CoverBig.Rect.W, _CoverBig.Rect.H);
- RectangleF rect;
- CHelper.SetRect(bounds, out rect, vidtex.OrigAspect, EAspect.Crop);
- var vidRect = new SRectF(rect.X, rect.Y, rect.Width, rect.Height, _CoverBig.Rect.Z);
- var vidRectBounds = new SRectF(bounds.X, bounds.Y, bounds.Width, bounds.Height, 0f);
+ SRectF rect = CHelper.FitInBounds(_CoverBig.Rect, vidtex.OrigAspect, EAspect.Crop);
- CBase.Drawing.DrawTexture(vidtex, vidRect, vidtex.Color, vidRectBounds);
- CBase.Drawing.DrawTextureReflection(vidtex, vidRect, vidtex.Color, vidRectBounds, _CoverBig.ReflectionSpace, _CoverBig.ReflectionHeight);
+ CBase.Drawing.DrawTexture(vidtex, rect);
+ CBase.Drawing.DrawTextureReflection(vidtex, rect, vidtex.Color, _CoverBig.ReflectionSpace, _CoverBig.ReflectionHeight);
}
else
_CoverBig.Draw(EAspect.Crop);
diff --git a/VocaluxeLib/PartyModes/CScreenPartyDummy.cs b/VocaluxeLib/PartyModes/CScreenPartyDummy.cs
index 4ac0d76d..26574458 100644
--- a/VocaluxeLib/PartyModes/CScreenPartyDummy.cs
+++ b/VocaluxeLib/PartyModes/CScreenPartyDummy.cs
@@ -32,11 +32,9 @@ namespace VocaluxeLib.PartyModes
public override void LoadTheme(string xmlPath)
{
_Warning = GetNewText();
- _Warning.Height = 100f;
+ _Warning.Font.Height = 100f;
_Warning.X = 150;
_Warning.Y = 300;
- _Warning.Font = "Normal";
- _Warning.Style = EStyle.Normal;
_Warning.Color = new SColorF(1f, 0f, 0f, 1f);
_Warning.SelColor = new SColorF(1f, 0f, 0f, 1f);
_Warning.Text = "SOMETHING WENT WRONG!";
diff --git a/VocaluxeLib/Profile/CAvatar.cs b/VocaluxeLib/Profile/CAvatar.cs
index 1daba02e..dc0325e9 100644
--- a/VocaluxeLib/Profile/CAvatar.cs
+++ b/VocaluxeLib/Profile/CAvatar.cs
@@ -25,10 +25,10 @@ namespace VocaluxeLib.Profile
{
public int ID;
private readonly string _FileName = "";
- private CTexture _Texture;
+ private CTextureRef _Texture;
private const int _MaxNameLen = 12;
- public CTexture Texture
+ public CTextureRef Texture
{
get { return _Texture; }
}
@@ -39,11 +39,11 @@ namespace VocaluxeLib.Profile
public static CAvatar GetAvatar(string fileName)
{
- CTexture texture = CBase.Drawing.AddTexture(fileName);
+ CTextureRef texture = CBase.Drawing.AddTexture(fileName);
return texture == null ? null : new CAvatar(texture, fileName);
}
- private CAvatar(CTexture texture, string fileName, int id = -1)
+ private CAvatar(CTextureRef texture, string fileName, int id = -1)
{
_Texture = texture;
_FileName = fileName;
diff --git a/VocaluxeLib/Profile/CProfile.cs b/VocaluxeLib/Profile/CProfile.cs
index cf03f5b0..95ad5d4f 100644
--- a/VocaluxeLib/Profile/CProfile.cs
+++ b/VocaluxeLib/Profile/CProfile.cs
@@ -18,6 +18,7 @@
using System;
using System.IO;
using System.Xml;
+using VocaluxeLib.Xml;
namespace VocaluxeLib.Profile
{
diff --git a/VocaluxeLib/Songs/CCategory.cs b/VocaluxeLib/Songs/CCategory.cs
index 79f5087c..1fec7346 100644
--- a/VocaluxeLib/Songs/CCategory.cs
+++ b/VocaluxeLib/Songs/CCategory.cs
@@ -24,8 +24,8 @@ namespace VocaluxeLib.Songs
public class CCategory
{
public readonly string Name;
- private CTexture _CoverTextureSmall;
- private CTexture _CoverTextureBig;
+ private CTextureRef _CoverTextureSmall;
+ private CTextureRef _CoverTextureBig;
public readonly List Songs = new List();
public CCategory(string name)
@@ -33,14 +33,14 @@ namespace VocaluxeLib.Songs
Name = name;
}
- public CTexture CoverTextureSmall
+ public CTextureRef CoverTextureSmall
{
get { return _CoverTextureSmall; }
set { _CoverTextureSmall = value; }
}
- public CTexture CoverTextureBig
+ public CTextureRef CoverTextureBig
{
get { return _CoverTextureBig ?? _CoverTextureSmall; }
set
diff --git a/VocaluxeLib/Songs/CSong.cs b/VocaluxeLib/Songs/CSong.cs
index a3752341..a5baf8e5 100644
--- a/VocaluxeLib/Songs/CSong.cs
+++ b/VocaluxeLib/Songs/CSong.cs
@@ -78,8 +78,8 @@ namespace VocaluxeLib.Songs
public partial class CSong
{
- private CTexture _CoverTextureSmall;
- private CTexture _CoverTextureBig;
+ private CTextureRef _CoverTextureSmall;
+ private CTextureRef _CoverTextureBig;
public SMedley Medley;
@@ -104,7 +104,7 @@ namespace VocaluxeLib.Songs
public bool NotesLoaded { get; private set; }
- public CTexture CoverTextureSmall
+ public CTextureRef CoverTextureSmall
{
get
{
@@ -116,7 +116,7 @@ namespace VocaluxeLib.Songs
set { _CoverTextureSmall = value; }
}
- public CTexture CoverTextureBig
+ public CTextureRef CoverTextureBig
{
get { return _CoverTextureBig ?? _CoverTextureSmall; }
set { _CoverTextureBig = value; }
diff --git a/VocaluxeLib/Structs.cs b/VocaluxeLib/Structs.cs
index aeb49246..743585d5 100644
--- a/VocaluxeLib/Structs.cs
+++ b/VocaluxeLib/Structs.cs
@@ -17,6 +17,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Drawing;
using System.Windows.Forms;
@@ -25,21 +26,57 @@ using VocaluxeLib.Songs;
namespace VocaluxeLib
{
+ public enum ECoverGeneratorType
+ {
+ Default,
+ Folder,
+ Artist,
+ Letter,
+ Edition,
+ Genre,
+ Language,
+ Year,
+ Decade,
+ Date
+ }
+
+ public struct SMargin
+ {
+ public int Default;
+ public int Left, Right, Top, Bottom;
+ }
+
+ public struct SThemeCoverGeneratorText
+ {
+ public string Text;
+ public SThemeFont Font;
+ public SThemeColor Color;
+ public SMargin Margin;
+ public int Indent;
+ }
+
+ public struct SThemeCoverGenerator
+ {
+ public ECoverGeneratorType Type;
+ public SThemeCoverGeneratorText Text;
+ public SThemeColor BackgroundColor;
+ public string Image;
+ public float ImageAlpha;
+ public bool ShowFirstCover;
+ }
#region Drawing
public struct SColorF
{
- [XmlElement("R")]
- public float R;
- [XmlElement("G")]
- public float G;
- [XmlElement("B")]
- public float B;
- [XmlElement("A")]
- public float A;
+ [XmlElement("R")] public float R;
+ [XmlElement("G")] public float G;
+ [XmlElement("B")] public float B;
+ [XmlElement("A")] public float A;
public SColorF(float r, float g, float b, float a)
{
+ Debug.Assert(r.IsInRange(0, 1) && g.IsInRange(0, 1) && b.IsInRange(0, 1));
+ Debug.Assert(a.IsInRange(0, 1));
R = r;
G = g;
B = b;
@@ -69,14 +106,30 @@ namespace VocaluxeLib
public string Name;
//Needed for serialization
- public bool ColorSpecified { get { return String.IsNullOrEmpty(Name); } }
- public bool NameSpecified { get { return !String.IsNullOrEmpty(Name); } }
+ public bool ColorSpecified
+ {
+ get { return String.IsNullOrEmpty(Name); }
+ }
+ public bool NameSpecified
+ {
+ get { return !String.IsNullOrEmpty(Name); }
+ }
public SThemeColor(SThemeColor theme)
{
Color = new SColorF(theme.Color);
Name = theme.Name;
}
+
+ public bool Get(int partyModeId, out SColorF color)
+ {
+ if (String.IsNullOrEmpty(Name))
+ {
+ color = Color;
+ return true;
+ }
+ return CBase.Theme.GetColor(Name, CBase.Theme.GetSkinIndex(partyModeId), out color);
+ }
}
public struct SRectF
@@ -86,8 +139,24 @@ namespace VocaluxeLib
public float W;
public float H;
public float Z;
- [XmlIgnore]
- public float Rotation; //0..360°
+ [XmlIgnore] public float Rotation; //0..360°
+
+ public float Right
+ {
+ get { return X + W; }
+ }
+ public float Bottom
+ {
+ get { return Y + H; }
+ }
+ public Size SizeI
+ {
+ get { return new Size((int)W, (int)H); }
+ }
+ public SizeF Size
+ {
+ get { return new SizeF(W, H); }
+ }
public SRectF(float x, float y, float w, float h, float z)
{
@@ -108,19 +177,34 @@ namespace VocaluxeLib
Z = rect.Z;
Rotation = 0f;
}
+
+ public SRectF(Rectangle rect)
+ {
+ X = rect.X;
+ Y = rect.Y;
+ W = rect.Width;
+ H = rect.Height;
+ Z = 0;
+ Rotation = 0;
+ }
}
[XmlRoot("Reflection")]
public struct SReflection
{
- [XmlAttributeAttribute(AttributeName = "Enabled")]
- public bool Enabled;
+ [XmlAttribute(AttributeName = "Enabled")] public bool Enabled;
public float Height;
public float Space;
//Needed for serialization
- public bool HeightSpecified { get { return Enabled; } }
- public bool SpaceSpecified { get { return Enabled; } }
+ public bool HeightSpecified
+ {
+ get { return Enabled; }
+ }
+ public bool SpaceSpecified
+ {
+ get { return Enabled; }
+ }
public SReflection(bool enabled, float height, float space)
{
diff --git a/VocaluxeLib/Utils/Player/CSongPlayer.cs b/VocaluxeLib/Utils/Player/CSongPlayer.cs
index 078be067..d90eb1b6 100644
--- a/VocaluxeLib/Utils/Player/CSongPlayer.cs
+++ b/VocaluxeLib/Utils/Player/CSongPlayer.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
-
using VocaluxeLib.Draw;
using VocaluxeLib.Songs;
@@ -14,7 +13,7 @@ namespace VocaluxeLib.Utils.Player
private CSong _Song;
private bool _VideoEnabled;
private int _Video = -1;
- private CTexture _CurrentVideoTexture;
+ private CTextureRef _CurrentVideoTexture;
private CFading _VideoFading;
public bool VideoEnabled
@@ -41,7 +40,7 @@ namespace VocaluxeLib.Utils.Player
}
public bool SongHasVideo
{
- get { return _Song != null && File.Exists(Path.Combine(_Song.Folder,_Song.VideoFileName)); }
+ get { return _Song != null && File.Exists(Path.Combine(_Song.Folder, _Song.VideoFileName)); }
}
public string ArtistAndTitle
@@ -56,7 +55,7 @@ namespace VocaluxeLib.Utils.Player
}
}
- public CTexture Cover
+ public CTextureRef Cover
{
get { return _Song == null ? CBase.Cover.GetNoCover() : _Song.CoverTextureBig; }
}
@@ -66,11 +65,10 @@ namespace VocaluxeLib.Utils.Player
get { return _StreamID != -1; }
}
-
- public CSongPlayer(bool loop = false) : base(loop) { }
+ public CSongPlayer(bool loop = false) : base(loop) {}
public CSongPlayer(CSong song, bool loop = false, float position = 0f, bool autoplay = false)
- : base(Path.Combine(song.Folder,song.MP3FileName), loop, position, autoplay)
+ : base(Path.Combine(song.Folder, song.MP3FileName), loop, position, autoplay)
{
_Song = song;
_LoadVideo();
@@ -82,7 +80,7 @@ namespace VocaluxeLib.Utils.Player
_Song = null;
}
- public CTexture GetVideoTexture()
+ public CTextureRef GetVideoTexture()
{
if (_Video == -1 || _Song == null)
return null;
@@ -101,7 +99,7 @@ namespace VocaluxeLib.Utils.Player
return null;
}
- public void Load(CSong song, float position = 0f, bool autoplay = false)
+ public void Load(CSong song, float position = 0f, bool autoplay = false)
{
if (song == null)
return;
@@ -109,7 +107,7 @@ namespace VocaluxeLib.Utils.Player
Stop();
_Song = song;
-
+
base.Load(Path.Combine(song.Folder, song.MP3FileName), position, false);
_LoadVideo();
@@ -155,13 +153,10 @@ namespace VocaluxeLib.Utils.Player
CBase.Video.Pause(_Video);
CBase.Video.Skip(_Video, CBase.Sound.GetPosition(_StreamID) + _FadeTime, _Song.VideoGap);
}
- else if(_Video != -1)
- {
+ else if (_Video != -1)
CBase.Video.Resume(_Video);
- }
base.TogglePause();
}
-
private void _LoadVideo()
{
@@ -182,4 +177,4 @@ namespace VocaluxeLib.Utils.Player
}
}
}
-}
+}
\ No newline at end of file
diff --git a/VocaluxeLib/VocaluxeLib.csproj b/VocaluxeLib/VocaluxeLib.csproj
index a367e8e1..fb1e0737 100644
--- a/VocaluxeLib/VocaluxeLib.csproj
+++ b/VocaluxeLib/VocaluxeLib.csproj
@@ -76,7 +76,9 @@
+
+
@@ -100,8 +102,9 @@
-
-
+
+
+
@@ -137,6 +140,7 @@
+
diff --git a/VocaluxeLib/CXMLReader.cs b/VocaluxeLib/Xml/CXMLReader.cs
similarity index 69%
rename from VocaluxeLib/CXMLReader.cs
rename to VocaluxeLib/Xml/CXMLReader.cs
index 4b06b922..2f266ba6 100644
--- a/VocaluxeLib/CXMLReader.cs
+++ b/VocaluxeLib/Xml/CXMLReader.cs
@@ -19,9 +19,9 @@ using System;
using System.Collections.Generic;
using System.Xml.XPath;
-namespace VocaluxeLib
+namespace VocaluxeLib.Xml
{
- public class CXMLReader
+ public class CXMLReader : CXmlDeserializer
{
private readonly XPathNavigator _Navigator;
private readonly String _FilePath;
@@ -57,55 +57,17 @@ namespace VocaluxeLib
}
}
- public bool TryGetEnumValue(string xPath, ref T value)
- where T : struct
- {
- string val;
- if (GetValue(xPath, out val, Enum.GetName(typeof(T), value)))
- return CHelper.TryParse(val, out value, true);
- return false;
- }
-
- public bool TryGetIntValue(string xPath, ref int value)
- {
- string val;
- if (GetValue(xPath, out val, value.ToString()))
- return int.TryParse(val, out value);
- return false;
- }
-
- public bool TryGetIntValueRange(string xPath, ref int value, int min = 0, int max = 100)
- {
- bool result = TryGetIntValue(xPath, ref value);
- if (result)
- value = value.Clamp(min, max);
- return result;
- }
-
- public bool TryGetFloatValue(string xPath, ref float value)
- {
- string val;
- return GetValue(xPath, out val, value.ToString()) && CHelper.TryParse(val, out value);
- }
-
public bool TryGetColorFromRGBA(string xPath, ref SColorF value)
{
bool result = true;
- result &= TryGetFloatValue(xPath + "/R", ref value.R);
- result &= TryGetFloatValue(xPath + "/G", ref value.G);
- result &= TryGetFloatValue(xPath + "/B", ref value.B);
- result &= TryGetFloatValue(xPath + "/A", ref value.A);
- if (result)
- {
- value.R = value.R.Clamp(0f, 1f);
- value.G = value.G.Clamp(0f, 1f);
- value.B = value.B.Clamp(0f, 1f);
- value.A = value.A.Clamp(0f, 1f);
- }
+ result &= TryGetNormalizedFloatValue(xPath + "/R", ref value.R);
+ result &= TryGetNormalizedFloatValue(xPath + "/G", ref value.G);
+ result &= TryGetNormalizedFloatValue(xPath + "/B", ref value.B);
+ result &= TryGetNormalizedFloatValue(xPath + "/A", ref value.A);
return result;
}
- public bool GetValue(string xPath, out string value, string defaultValue = "")
+ public override bool GetValue(string xPath, out string value, string defaultValue = "")
{
int resultCt = 0;
string val = string.Empty;
@@ -128,6 +90,19 @@ namespace VocaluxeLib
return true;
}
+ public override bool GetAttribute(string xPath, string attribute, out string value)
+ {
+ _Navigator.MoveToRoot();
+ XPathNodeIterator iterator = _Navigator.Select(xPath);
+ if (iterator.MoveNext())
+ {
+ value = iterator.Current.GetAttribute(attribute, "");
+ return true;
+ }
+ value = "";
+ return false;
+ }
+
public List GetNames(string xPath)
{
var values = new List();
diff --git a/VocaluxeLib/Xml/CXmlDeserializer.cs b/VocaluxeLib/Xml/CXmlDeserializer.cs
new file mode 100644
index 00000000..0b202c6b
--- /dev/null
+++ b/VocaluxeLib/Xml/CXmlDeserializer.cs
@@ -0,0 +1,68 @@
+using System.Linq;
+
+namespace VocaluxeLib.Xml
+{
+ public abstract class CXmlDeserializer : CXmlReaderBase
+ {
+ public bool Read(string xPath, out SThemeFont el)
+ {
+ el = new SThemeFont();
+ bool ok = true;
+ ok &= GetValue(xPath + "/Name", out el.Name);
+ ok &= TryGetFloatValue(xPath + "/Size", ref el.Size);
+ ok &= TryGetEnumValue(xPath + "/Style", ref el.Style);
+ return ok;
+ }
+
+ public bool Read(string xPath, out SMargin el)
+ {
+ el = new SMargin();
+ bool ok = true;
+ bool defOk = TryGetIntValue(xPath + "/Default", ref el.Default);
+ ok &= TryGetIntValue(xPath + "/Left", ref el.Left, el.Default);
+ ok &= TryGetIntValue(xPath + "/Right", ref el.Right, el.Default);
+ ok &= TryGetIntValue(xPath + "/Top", ref el.Top, el.Default);
+ ok &= TryGetIntValue(xPath + "/Bottom", ref el.Bottom, el.Default);
+ return ok || defOk;
+ }
+
+ public bool Read(string xPath, out SThemeCoverGeneratorText el)
+ {
+ el = new SThemeCoverGeneratorText();
+ bool ok = true;
+ ok &= GetValue(xPath + "/Text", out el.Text);
+ ok &= Read(xPath + "/Font", out el.Font);
+ ok &= Read(xPath + "/Color", out el.Color);
+ ok &= Read(xPath + "/Margin", out el.Margin);
+ if (ok)
+ TryGetIntValue(xPath + "/Indent", ref el.Indent, 6 * (el.Margin.Left + el.Margin.Right) / 2);
+ return ok;
+ }
+
+ public bool Read(string xPath, out SThemeColor el)
+ {
+ el = new SThemeColor();
+ bool ok = true;
+ ok &= TryGetNormalizedFloatValue(xPath + "/R", ref el.Color.R);
+ ok &= TryGetNormalizedFloatValue(xPath + "/G", ref el.Color.G);
+ ok &= TryGetNormalizedFloatValue(xPath + "/B", ref el.Color.B);
+ ok &= TryGetNormalizedFloatValue(xPath + "/A", ref el.Color.A);
+ if (!ok)
+ ok = GetValue(xPath, out el.Name) && !el.Name.Contains('<');
+ return ok;
+ }
+
+ public bool Read(string xPath, out SThemeCoverGenerator el)
+ {
+ el = new SThemeCoverGenerator();
+ bool ok = true;
+ ok &= TryGetEnumValue(xPath + "/Type", ref el.Type);
+ ok &= Read(xPath + "/Text", out el.Text);
+ ok &= Read(xPath + "/BackgroundColor", out el.BackgroundColor);
+ ok &= GetValue(xPath + "/Image", out el.Image);
+ TryGetNormalizedFloatValue(xPath + "/ImageAlpha", ref el.ImageAlpha, 0.5f);
+ TryGetBoolValue(xPath + "/ShowFirstCover", out el.ShowFirstCover);
+ return ok;
+ }
+ }
+}
\ No newline at end of file
diff --git a/VocaluxeLib/Xml/CXmlReaderBase.cs b/VocaluxeLib/Xml/CXmlReaderBase.cs
new file mode 100644
index 00000000..152ecfad
--- /dev/null
+++ b/VocaluxeLib/Xml/CXmlReaderBase.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace VocaluxeLib.Xml
+{
+ ///
+ /// Base class that provides basic methods for reading xml, while the actual XML implementation is still abstract to allow different implementations
+ ///
+ public abstract class CXmlReaderBase
+ {
+ public abstract bool GetValue(string xPath, out string value, string defaultValue = "");
+ public abstract bool GetAttribute(string xPath, string attribute, out string value);
+
+ public bool TryGetBoolValue(string xPath, out bool value, bool defaultValue = false)
+ {
+ value = defaultValue;
+ string val;
+ return GetValue(xPath, out val) && bool.TryParse(val, out value);
+ }
+
+ public bool TryGetIntValue(string xPath, ref int value, int? defaultValue = null)
+ {
+ string val;
+ bool ok = GetValue(xPath, out val) && int.TryParse(val, out value);
+ if (!ok && defaultValue.HasValue)
+ value = defaultValue.Value;
+ return ok;
+ }
+
+ public bool TryGetFloatValue(string xPath, ref float value)
+ {
+ string val;
+ return GetValue(xPath, out val, value.ToString()) && CHelper.TryParse(val, out value);
+ }
+
+ public bool TryGetEnumValue(string xPath, ref T value) where T : struct
+ {
+ string val;
+ return GetValue(xPath, out val, Enum.GetName(typeof(T), value)) && CHelper.TryParse(val, out value, true);
+ }
+
+ public bool TryGetIntValueRange(string xPath, ref int value, int min = 0, int max = 100)
+ {
+ return TryGetIntValue(xPath, ref value) && value.IsInRange(min, max);
+ }
+
+ ///
+ /// Gets a normalized (0<=x<=1) float value
+ ///
+ ///
+ ///
+ ///
+ /// True if exists and is normalized
+ public bool TryGetNormalizedFloatValue(string xPath, ref float value, float defaultValue = 0)
+ {
+ bool ok = TryGetFloatValue(xPath, ref value) && value.IsInRange(0f, 1f);
+ if (!ok)
+ value = defaultValue;
+ return ok;
+ }
+ }
+}
\ No newline at end of file