Split Notes, Lines and Voices into separate files/classes

This commit is contained in:
Flamefire committed 2013-08-22 00:05:01 +02:00
1 parent 84fc0fcb91
commit 44c78fad19
32 files changed
+889 -926

No files matched your search

+2 -2
View File
@@ -51,7 +51,7 @@ namespace VocaluxeLib.Game
for (int player = 0; player < players.Length; player++)
{
_Rounds[round, player].SongID = songID;
_Rounds[round, player].LineNr = players[player].LineNr;
_Rounds[round, player].VoiceNr = players[player].VoiceNr;
_Rounds[round, player].Points = players[player].Points;
_Rounds[round, player].PointsGoldenNotes = players[player].PointsGoldenNotes;
_Rounds[round, player].PointsLineBonus = players[player].PointsLineBonus;
@@ -88,7 +88,7 @@ namespace VocaluxeLib.Game
players[p].PointsGoldenNotes = _Rounds[round, p].PointsGoldenNotes;
players[p].PointsLineBonus = _Rounds[round, p].PointsLineBonus;
players[p].SongID = _Rounds[round, p].SongID;
players[p].LineNr = _Rounds[round, p].LineNr;
players[p].VoiceNr = _Rounds[round, p].VoiceNr;
players[p].Medley = _Rounds[round, p].Medley;
players[p].Duet = _Rounds[round, p].Duet;
players[p].ShortSong = _Rounds[round, p].ShortSong;
+2 -2
View File
@@ -201,12 +201,12 @@ namespace VocaluxeLib.Menu
return false;
}
public void SetLine(CLine line)
public void SetLine(CSongLine line)
{
_Notes.Clear();
_Width = 0f;
foreach (CNote note in line.Notes)
foreach (CSongNote note in line.Notes)
{
SNote n = new SNote {Text = note.Text, StartBeat = note.StartBeat, EndBeat = note.EndBeat, Duration = note.Duration, Type = note.NoteType};
+8 -8
View File
@@ -487,10 +487,10 @@ namespace VocaluxeLib.Menu
{
for (int j = 0; j < _NumW; j++)
{
SRectF rect = new SRectF(Rect.X + j * (_TileW + _SpaceW), Rect.Y + i * (_TileH + _SpaceH), _TileW, _TileH, Rect.Z);
CStatic tileStatic = new CStatic(_PartyModeID, _TextureEmptyTile, ColorEmptyTile, rect) {Aspect = EAspect.Crop};
CText tileText = new CText(rect.X + rect.W / 2, rect.Y + rect.H + _Theme.NameSpace, rect.Z, _Theme.NameHeight, rect.W, EAlignment.Center, _Theme.NameStyle,
_Theme.NameFont, _Theme.NameColor, "");
var rect = new SRectF(Rect.X + j * (_TileW + _SpaceW), Rect.Y + i * (_TileH + _SpaceH), _TileW, _TileH, 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.NameSpace, rect.Z, _Theme.NameHeight, rect.W, EAlignment.Center, _Theme.NameStyle,
_Theme.NameFont, _Theme.NameColor, "");
_Tiles.Add(new CTile(tileStatic, tileText, -1));
}
}
@@ -501,21 +501,21 @@ namespace VocaluxeLib.Menu
_VisibleProfiles.Clear();
CProfile[] profiles = CBase.Profiles.GetProfiles();
for (int i = 0; i < profiles.Length; i++)
foreach (CProfile profile in profiles)
{
bool visible = profiles[i].Active == EOffOn.TR_CONFIG_ON;
bool visible = profile.Active == EOffOn.TR_CONFIG_ON;
if (visible)
{
//Show profile only if active
for (int p = 0; p < CBase.Game.GetNumPlayer(); p++)
{
//Don't show profile if is selected, but if selected and guest
if (CBase.Game.GetPlayers()[p].ProfileID == profiles[i].ID && profiles[i].GuestProfile == EOffOn.TR_CONFIG_OFF)
if (CBase.Game.GetPlayers()[p].ProfileID == profile.ID && profile.GuestProfile == EOffOn.TR_CONFIG_OFF)
visible = false;
}
}
if (visible)
_VisibleProfiles.Add(profiles[i].ID);
_VisibleProfiles.Add(profile.ID);
}
}
+4 -6
View File
@@ -205,11 +205,9 @@ namespace VocaluxeLib.Menu
public void Draw(float scale, float z, EAspect aspect, bool forceDraw = false)
{
CTexture texture = Texture;
if (texture == null)
texture = new CTexture((int)Rect.W, (int)Rect.H);
CTexture texture = Texture ?? new CTexture((int)Rect.W, (int)Rect.H);
SRectF bounds = new SRectF(
var bounds = new SRectF(
Rect.X - Rect.W * (scale - 1f),
Rect.Y - Rect.H * (scale - 1f),
Rect.W + 2 * Rect.W * (scale - 1f),
@@ -220,7 +218,7 @@ namespace VocaluxeLib.Menu
if (aspect != EAspect.Stretch)
{
RectangleF bounds2 = new RectangleF(bounds.X, bounds.Y, bounds.W, bounds.H);
var bounds2 = new RectangleF(bounds.X, bounds.Y, bounds.W, bounds.H);
RectangleF rect2;
CHelper.SetRect(bounds2, out rect2, texture.OrigAspect, aspect);
@@ -230,7 +228,7 @@ namespace VocaluxeLib.Menu
rect.H = rect2.Height;
}
SColorF color = new SColorF(Color.R, Color.G, Color.B, Color.A * Alpha);
var color = new SColorF(Color.R, Color.G, Color.B, Color.A * Alpha);
if (Visible || forceDraw || (CBase.Settings.GetGameState() == EGameState.EditTheme))
{
CBase.Drawing.DrawTexture(texture, rect, color, bounds);
+53 -56
View File
@@ -33,7 +33,7 @@ namespace VocaluxeLib.Menu.SingNotes
public SRectF Rect;
public SColorF Color;
public float Alpha;
public CLine[] Lines;
public CSongLine[] Lines;
public int LineNr;
public Stopwatch Timer;
public List<CParticleEffect> GoldenStars;
@@ -205,7 +205,7 @@ namespace VocaluxeLib.Menu.SingNotes
public int AddPlayer(SRectF rect, SColorF color, int playerNr)
{
SPlayerNotes notes = new SPlayerNotes
var notes = new SPlayerNotes
{
Rect = rect,
Color = color,
@@ -226,7 +226,7 @@ namespace VocaluxeLib.Menu.SingNotes
return notes.ID;
}
public void SetLines(int id, CLine[] lines, int lineNr)
public void SetLines(int id, CSongLine[] lines, int lineNr)
{
if (lines == null)
return;
@@ -278,7 +278,7 @@ namespace VocaluxeLib.Menu.SingNotes
Draw(id, null, player);
}
public void Draw(int id, List<CLine> singLines, int player)
public void Draw(int id, List<CSungLine> sungLines, int player)
{
int n = _FindPlayerNotes(id);
if (n == -1)
@@ -293,7 +293,7 @@ namespace VocaluxeLib.Menu.SingNotes
if (_PlayerNotes[n].Lines.Length <= _PlayerNotes[n].LineNr)
return;
CLine line = _PlayerNotes[n].Lines[_PlayerNotes[n].LineNr];
CSongLine line = _PlayerNotes[n].Lines[_PlayerNotes[n].LineNr];
if (CBase.Config.GetDrawNoteLines() == EOffOn.TR_CONFIG_ON)
_DrawNoteLines(_PlayerNotes[n].Rect, new SColorF(0.5f, 0.5f, 0.5f, 0.5f * _PlayerNotes[n].Alpha));
@@ -311,7 +311,7 @@ namespace VocaluxeLib.Menu.SingNotes
if (beats < 1)
return;
SColorF color = new SColorF(
var color = new SColorF(
_PlayerNotes[n].Color.R,
_PlayerNotes[n].Color.G,
_PlayerNotes[n].Color.B,
@@ -319,13 +319,13 @@ namespace VocaluxeLib.Menu.SingNotes
float baseLine = line.BaseLine;
int nr = 1;
foreach (CNote note in line.Notes)
foreach (CSongNote note in line.Notes)
{
if (note.NoteType != ENoteType.Freestyle)
{
float width = note.Duration / beats * w;
SRectF rect = new SRectF(
var rect = new SRectF(
_PlayerNotes[n].Rect.X + (note.StartBeat - line.FirstNoteBeat) / beats * w,
_PlayerNotes[n].Rect.Y + (CBase.Settings.GetNumNoteLines() - 1 - (note.Tone - baseLine) / 2) / CBase.Settings.GetNumNoteLines() * h - dh,
width,
@@ -359,7 +359,7 @@ namespace VocaluxeLib.Menu.SingNotes
foreach (CParticleEffect perfline in _PlayerNotes[n].PerfectLineTwinkle)
perfline.Draw();
if (singLines == null || singLines.Count == 0 || CBase.Game.GetPlayers()[player].CurrentLine == -1 || singLines.Count <= CBase.Game.GetPlayers()[player].CurrentLine)
if (sungLines == null || sungLines.Count == 0 || CBase.Game.GetPlayers()[player].CurrentLine == -1 || sungLines.Count <= CBase.Game.GetPlayers()[player].CurrentLine)
{
foreach (CParticleEffect stars in _PlayerNotes[n].GoldenStars)
{
@@ -369,48 +369,45 @@ namespace VocaluxeLib.Menu.SingNotes
return;
}
foreach (CNote note in singLines[CBase.Game.GetPlayers()[player].CurrentLine].Notes)
foreach (CSungNote note in sungLines[CBase.Game.GetPlayers()[player].CurrentLine].Notes)
{
if (note.StartBeat >= line.FirstNoteBeat && note.EndBeat <= line.LastNoteBeat)
float width = note.Duration / beats * w;
if (note.EndBeat == CBase.Game.GetCurrentBeatD())
width -= (1 - (CBase.Game.GetMidBeatD() - CBase.Game.GetCurrentBeatD())) / beats * w;
var rect = new SRectF(
_PlayerNotes[n].Rect.X + (note.StartBeat - line.FirstNoteBeat) / beats * w,
_PlayerNotes[n].Rect.Y + (CBase.Settings.GetNumNoteLines() - 1 - (note.Tone - baseLine) / 2) / CBase.Settings.GetNumNoteLines() * h - dh,
width,
h / CBase.Settings.GetNumNoteLines() + 2 * dh,
_PlayerNotes[n].Rect.Z
);
float f = (note.Hit) ? 0.7f : 0.4f;
_DrawNote(rect, color, f);
if (note.EndBeat >= CBase.Game.GetCurrentBeatD() && note.Hit && note.HitNote.NoteType == ENoteType.Golden)
{
float width = note.Duration / beats * w;
var re = new SRectF(rect) {W = (CBase.Game.GetMidBeatD() - note.StartBeat) / beats * w};
_AddFlare(re, n);
}
if (note.EndBeat == CBase.Game.GetCurrentBeatD())
width -= (1 - (CBase.Game.GetMidBeatD() - CBase.Game.GetCurrentBeatD())) / beats * w;
SRectF rect = new SRectF(
_PlayerNotes[n].Rect.X + (note.StartBeat - line.FirstNoteBeat) / beats * w,
_PlayerNotes[n].Rect.Y + (CBase.Settings.GetNumNoteLines() - 1 - (note.Tone - baseLine) / 2) / CBase.Settings.GetNumNoteLines() * h - dh,
width,
h / CBase.Settings.GetNumNoteLines() + 2 * dh,
_PlayerNotes[n].Rect.Z
);
float f = (note.Hit) ? 0.7f : 0.4f;
_DrawNote(rect, color, f);
if (note.EndBeat >= CBase.Game.GetCurrentBeatD() && note.Hit && note.NoteType == ENoteType.Golden)
{
SRectF re = new SRectF(rect) {W = (CBase.Game.GetMidBeatD() - note.StartBeat) / beats * w};
_AddFlare(re, n);
}
if (note.Perfect && note.EndBeat < CBase.Game.GetCurrentBeatD())
{
_AddPerfectNote(rect, n);
note.Perfect = false;
}
if (note.Perfect && note.EndBeat < CBase.Game.GetCurrentBeatD())
{
_AddPerfectNote(rect, n);
note.Perfect = false;
}
}
int currentLine = CBase.Game.GetPlayers()[player].SingLine.Count - 1;
int currentLine = CBase.Game.GetPlayers()[player].SungLines.Count - 1;
if (currentLine > 0)
{
if (CBase.Game.GetPlayers()[player].SingLine[currentLine - 1].PerfectLine)
if (CBase.Game.GetPlayers()[player].SungLines[currentLine - 1].PerfectLine)
{
_AddPerfectLine(n);
CBase.Game.GetPlayers()[player].SingLine[currentLine - 1].PerfectLine = false;
CBase.Game.GetPlayers()[player].SungLines[currentLine - 1].PerfectLine = false;
}
}
@@ -475,7 +472,7 @@ namespace VocaluxeLib.Menu.SingNotes
float dh = (1f - factor) * rect.H / 2;
float dw = Math.Min(dh, rect.W / 2);
SRectF noteRect = new SRectF(rect.X + dw, rect.Y + dh, rect.W - 2 * dw, rect.H - 2 * dh, rect.Z);
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);
@@ -487,7 +484,7 @@ namespace VocaluxeLib.Menu.SingNotes
CBase.Drawing.DrawTexture(noteBegin, new SRectF(noteRect.X, noteRect.Y, endsW, noteRect.H, noteRect.Z), color);
SRectF middleRect = new SRectF(noteRect.X + endsW, noteRect.Y, noteRect.W - 2 * endsW, noteRect.H, noteRect.Z);
var middleRect = new SRectF(noteRect.X + endsW, noteRect.Y, noteRect.W - 2 * endsW, noteRect.H, noteRect.Z);
if (noteRect.W >= 4 * endsW)
CBase.Drawing.DrawTexture(noteMiddle, middleRect, color);
else
@@ -516,7 +513,7 @@ namespace VocaluxeLib.Menu.SingNotes
if (2 * dw > rect.W)
dw = rect.W / 2;
SRectF r = new SRectF(
var r = new SRectF(
rect.X + dw + spacing,
rect.Y + d + spacing,
rect.W - 2 * dw - 2 * spacing,
@@ -532,7 +529,7 @@ namespace VocaluxeLib.Menu.SingNotes
if (2 * dx > r.W)
dx = r.W / 2;
SColorF col = new SColorF(color.R, color.G, color.B, color.A * alpha);
var col = new SColorF(color.R, color.G, color.B, color.A * alpha);
CBase.Drawing.DrawTexture(noteBackgroundBegin, new SRectF(r.X, r.Y, dx, r.H, r.Z), col);
@@ -565,7 +562,7 @@ namespace VocaluxeLib.Menu.SingNotes
if (2 * dw > rect.W)
dw = rect.W / 2;
SRectF r = new SRectF(
var r = new SRectF(
rect.X + dw + spacing,
rect.Y + d + spacing,
rect.W - 2 * dw - 2 * spacing,
@@ -573,8 +570,8 @@ namespace VocaluxeLib.Menu.SingNotes
rect.Z
);
int numstars = (int)(r.W * 0.25f);
CParticleEffect stars = new CParticleEffect(_PartyModeID, numstars, new SColorF(1f, 1f, 0f, 1f), r, _Theme.SkinGoldenStarName, 20, EParticleType.Star);
var numstars = (int)(r.W * 0.25f);
var stars = new CParticleEffect(_PartyModeID, numstars, new SColorF(1f, 1f, 0f, 1f), r, _Theme.SkinGoldenStarName, 20, EParticleType.Star);
_PlayerNotes[n].GoldenStars.Add(stars);
}
}
@@ -589,7 +586,7 @@ namespace VocaluxeLib.Menu.SingNotes
if (2 * dw > rect.W)
dw = rect.W / 2;
SRectF r = new SRectF(
var r = new SRectF(
rect.X + dw + spacing + rect.W - 2 * dw - 2 * spacing,
rect.Y + d + spacing,
0f,
@@ -597,7 +594,7 @@ namespace VocaluxeLib.Menu.SingNotes
rect.Z
);
CParticleEffect flares = new CParticleEffect(_PartyModeID, 15, new SColorF(1f, 1f, 1f, 1f), r, _Theme.SkinGoldenStarName, 20, EParticleType.Flare);
var flares = new CParticleEffect(_PartyModeID, 15, new SColorF(1f, 1f, 1f, 1f), r, _Theme.SkinGoldenStarName, 20, EParticleType.Flare);
_PlayerNotes[n].Flares.Add(flares);
}
@@ -611,7 +608,7 @@ namespace VocaluxeLib.Menu.SingNotes
if (2 * dw > rect.W)
dw = rect.W / 2;
SRectF r = new SRectF(
var r = new SRectF(
rect.X + dw + spacing,
rect.Y + d + spacing,
rect.W - 2 * dw - 2 * spacing,
@@ -632,14 +629,14 @@ namespace VocaluxeLib.Menu.SingNotes
rect.Z
);
CParticleEffect stars = new CParticleEffect(_PartyModeID, CBase.Game.GetRandom(2) + 1, new SColorF(1f, 1f, 1f, 1f), r, _Theme.SkinPerfectNoteStarName, 35,
EParticleType.PerfNoteStar);
var stars = new CParticleEffect(_PartyModeID, CBase.Game.GetRandom(2) + 1, new SColorF(1f, 1f, 1f, 1f), r, _Theme.SkinPerfectNoteStarName, 35,
EParticleType.PerfNoteStar);
_PlayerNotes[n].PerfectNoteEffect.Add(stars);
}
private void _AddPerfectLine(int n)
{
CParticleEffect twinkle = new CParticleEffect(_PartyModeID, 200, _PlayerNotes[n].Color, _PlayerNotes[n].Rect, _Theme.SkinGoldenStarName, 25, EParticleType.Twinkle);
var twinkle = new CParticleEffect(_PartyModeID, 200, _PlayerNotes[n].Color, _PlayerNotes[n].Rect, _Theme.SkinGoldenStarName, 25, EParticleType.Twinkle);
_PlayerNotes[n].PerfectLineTwinkle.Add(twinkle);
}
@@ -662,7 +659,7 @@ namespace VocaluxeLib.Menu.SingNotes
offsetX = noteBounds.W;
float dy = noteBounds.H / CBase.Settings.GetNumNoteLines();
SRectF drawRect = new SRectF(
var drawRect = new SRectF(
noteBounds.X - dy + offsetX,
noteBounds.Y + dy * (CBase.Settings.GetNumNoteLines() - 1 - (tonePlayer - baseLine) / 2f),
dy,
@@ -670,7 +667,7 @@ namespace VocaluxeLib.Menu.SingNotes
noteBounds.Z
);
SColorF color = new SColorF(
var color = new SColorF(
_PlayerNotes[n].Color.R,
_PlayerNotes[n].Color.G,
_PlayerNotes[n].Color.B,
+63
View File
@@ -0,0 +1,63 @@
namespace VocaluxeLib.Songs
{
/// <summary>
/// Base class for all note types
/// </summary>
public abstract class CBaseNote
{
private int _Duration = 1;
private int _Tone;
#region Contructors
protected CBaseNote(CBaseNote note)
{
StartBeat = note.StartBeat;
_Duration = note._Duration;
_Tone = note._Tone;
}
protected CBaseNote(int startBeat, int duration, int tone)
{
StartBeat = startBeat;
Duration = duration;
Tone = tone;
}
#endregion Constructors
#region Properties
public int StartBeat { get; set; }
public int EndBeat
{
get { return StartBeat + _Duration - 1; }
}
public int Duration
{
get { return _Duration; }
set
{
if (value > 0)
_Duration = value;
}
}
public int Tone
{
get { return _Tone; }
set
{
if ((value >= CBase.Settings.GetToneMin()) && (value <= CBase.Settings.GetToneMax()))
_Tone = value;
}
}
public int Points
{
get { return PointsForBeat * Duration; }
}
public abstract int PointsForBeat { get; }
#endregion Properties
}
}
+135
View File
@@ -0,0 +1,135 @@
using System.Collections.Generic;
using System.Linq;
namespace VocaluxeLib.Songs
{
public class CLineBase<T> where T : CBaseNote
{
protected readonly List<T> _Notes = new List<T>();
#region Properties
public int FirstNoteBeat
{
get { return (_Notes.Count == 0) ? int.MaxValue : _Notes[0].StartBeat; }
}
public int LastNoteBeat
{
get { return (_Notes.Count == 0) ? int.MinValue : _Notes[_Notes.Count - 1].EndBeat; }
}
public int NoteCount
{
get { return _Notes.Count; }
}
public T[] Notes
{
get { return _Notes.ToArray(); }
}
public T FirstNote
{
get { return _Notes.Count > 0 ? _Notes[0] : null; }
}
public T LastNote
{
get { return _Notes.Count > 0 ? _Notes[_Notes.Count - 1] : null; }
}
public int Points
{
get { return _Notes.Sum(note => note.Points); }
}
public int BaseLine
{
get
{
int min = int.MaxValue;
int max = int.MinValue;
foreach (T note in _Notes)
{
if (note.Tone < min)
min = note.Tone;
if (note.Tone > max)
max = note.Tone;
}
return min - (max - min) / 4;
}
}
#endregion Properties
#region Methods
//Find last note with StartBeat<=Beat
public int FindPreviousNote(int beat)
{
//If no notes -> No previous note
if (_Notes.Count == 0)
return -1;
int start = 0;
int end = _Notes.Count - 1;
//Ensure that start.StartBeat<=Beat && end.StartBeat>Beat
if (_Notes[0].StartBeat > beat)
return -1;
if (_Notes[end].StartBeat <= beat)
return end;
//Binary search
while (end - start > 1)
{
int mid = (start + end) / 2;
if (_Notes[mid].StartBeat <= beat)
start = mid;
else
end = mid;
}
return start;
}
public virtual bool AddNote(T note)
{
if (_Notes.Count == 0)
_Notes.Add(note);
else
{
int insPos = FindPreviousNote(note.StartBeat);
_Notes.Insert(insPos + 1, note);
}
return true;
}
public bool DeleteNote(int index)
{
if (_Notes.Count > index)
{
_Notes.RemoveAt(index);
return true;
}
return false;
}
public bool ReplaceNote(int index, T note)
{
if (_Notes.Count > index)
{
_Notes.RemoveAt(index);
return AddNote(note);
}
return false;
}
public bool IncLastNoteLength()
{
if (_Notes.Count > 0)
_Notes[_Notes.Count - 1].Duration++;
return false;
}
public void DeleteAllNotes()
{
_Notes.Clear();
}
#endregion Methods
}
}
-627
View File
@@ -17,9 +17,7 @@
// */
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
namespace VocaluxeLib.Songs
{
@@ -94,629 +92,4 @@ namespace VocaluxeLib.Songs
voice.SetMedley(startBeat, endBeat);
}
}
public class CNote
{
private int _StartBeat;
private int _Duration;
private int _Tone;
private ENoteType _NoteType;
private string _Text;
private bool _Hit; // for drawing player notes
private bool _Perfect; // for drawing perfect note effect
#region Contructors
public CNote()
{
StartBeat = 0;
Duration = 1;
Tone = 0;
NoteType = ENoteType.Normal;
Text = String.Empty;
_Hit = false;
_Perfect = false;
}
public CNote(CNote note)
{
_StartBeat = note._StartBeat;
_Duration = note._Duration;
_Tone = note._Tone;
_NoteType = note._NoteType;
_Text = note._Text;
_Hit = note._Hit;
_Perfect = note._Perfect;
}
public CNote(int startBeat, int duration, int tone, string text)
: this()
{
StartBeat = startBeat;
Duration = duration;
Tone = tone;
NoteType = ENoteType.Normal;
Text = text;
}
public CNote(int startBeat, int duration, int tone, string text, bool hit)
: this()
{
StartBeat = startBeat;
Duration = duration;
Tone = tone;
NoteType = ENoteType.Normal;
Text = text;
Hit = hit;
}
public CNote(int startBeat, int duration, int tone, string text, ENoteType noteType)
: this(startBeat, duration, tone, text)
{
NoteType = noteType;
}
public CNote(int startBeat, int duration, int tone, string text, bool hit, ENoteType noteType)
: this(startBeat, duration, tone, text)
{
NoteType = noteType;
Hit = hit;
}
#endregion Constructors
#region Properties
public bool Hit
{
get { return _Hit; }
set { _Hit = value; }
}
public bool Perfect
{
get { return _Perfect; }
set { _Perfect = value; }
}
public int StartBeat
{
get { return _StartBeat; }
set { _StartBeat = value; }
}
public int EndBeat
{
get { return _StartBeat + _Duration - 1; }
}
public int Duration
{
get { return _Duration; }
set
{
if (value > 0)
_Duration = value;
}
}
public int Tone
{
get { return _Tone; }
set
{
if ((value >= CBase.Settings.GetToneMin()) && (value <= CBase.Settings.GetToneMax()))
_Tone = value;
}
}
public ENoteType NoteType
{
get { return _NoteType; }
set { _NoteType = value; }
}
public string Text
{
get { return _Text; }
set { _Text = value; }
}
public int Points
{
get
{
switch (_NoteType)
{
case ENoteType.Normal:
return _Duration;
case ENoteType.Golden:
return _Duration * 2;
case ENoteType.Freestyle:
return 0;
default:
return 0;
}
}
}
public int PointsForBeat
{
get
{
switch (_NoteType)
{
case ENoteType.Normal:
return 1;
case ENoteType.Golden:
return 2;
case ENoteType.Freestyle:
return 0;
default:
return 0;
}
}
}
#endregion Properties
#region Methods
public bool IsPerfect(CNote compareNote)
{
bool result = Hit;
if (StartBeat != compareNote.StartBeat)
result = false;
if (EndBeat != compareNote.EndBeat)
result = false;
if (Tone != compareNote.Tone)
result = false;
Perfect = result;
return result;
}
#endregion Methods
}
public class CLine
{
private int _StartBeat = int.MinValue;
private int _EndBeat = int.MinValue;
private bool _PerfectLine; // for drawing perfect line effect
private bool _VisibleInTimeLine = true;
private int _MinBeat = int.MaxValue;
private int _MaxBeat = int.MinValue;
private readonly List<CNote> _Notes = new List<CNote>();
#region Constructors
public CLine() {}
public CLine(CLine line)
{
foreach (CNote note in line._Notes)
_Notes.Add(new CNote(note));
_StartBeat = line._StartBeat;
_EndBeat = line._EndBeat;
_PerfectLine = line._PerfectLine;
_MinBeat = line._MinBeat;
_MaxBeat = line._MaxBeat;
_VisibleInTimeLine = line._VisibleInTimeLine;
}
#endregion Constructors
#region Properties
public bool VisibleInTimeLine
{
get { return _VisibleInTimeLine; }
set { _VisibleInTimeLine = value; }
}
public int StartBeat
{
get { return _StartBeat; }
set
{
if (value <= _MinBeat)
_StartBeat = value;
}
}
public int EndBeat
{
get { return _EndBeat; }
set
{
if (value >= _MaxBeat)
_EndBeat = value;
}
}
public bool PerfectLine
{
get { return _PerfectLine; }
set { _PerfectLine = value; }
}
public int FirstNoteBeat
{
get { return _MinBeat; }
}
public int LastNoteBeat
{
get { return _MaxBeat; }
}
public string Lyrics
{
get { return _Notes.Aggregate(String.Empty, (current, note) => current + note.Text); }
}
public int NoteCount
{
get { return _Notes.Count; }
}
public int Points
{
get { return _Notes.Sum(note => note.Points); }
}
public CNote[] Notes
{
get { return _Notes.ToArray(); }
}
public CNote FirstNote
{
get { return _Notes.Count > 0 ? _Notes[0] : null; }
}
public CNote LastNote
{
get { return _Notes.Count > 0 ? _Notes[_Notes.Count - 1] : null; }
}
public int BaseLine
{
get
{
int min = int.MaxValue;
int max = int.MinValue;
foreach (CNote note in _Notes)
{
if (note.Tone < min)
min = note.Tone;
if (note.Tone > max)
max = note.Tone;
}
return min - (max - min) / 4;
}
}
#endregion Properties
#region Methods
public bool IsPerfect(CLine compareLine)
{
if (_Notes.Count == 0)
return false;
if (_Notes.Count != compareLine.NoteCount)
return false;
if (compareLine.Points == 0)
return false;
_PerfectLine = Points == compareLine.Points;
return _PerfectLine;
}
//Find last note with StartBeat<=Beat
public int FindPreviousNote(int beat)
{
//If no notes -> No previous note
if (_Notes.Count == 0)
return -1;
int start = 0;
int end = _Notes.Count - 1;
//Ensure that start.StartBeat<=Beat && end.StartBeat>Beat
if (_Notes[0].StartBeat > beat)
return -1;
if (_Notes[end].StartBeat <= beat)
return end;
//Binary search
while (end - start > 1)
{
int mid = (start + end) / 2;
if (_Notes[mid].StartBeat <= beat)
start = mid;
else
end = mid;
}
return start;
}
public bool AddNote(CNote note)
{
if (_Notes.Count == 0)
_Notes.Add(note);
else
{
int insPos = FindPreviousNote(note.StartBeat);
//Flamefire: May be a performance hit as notes are also used for sung notes
//But for song loading this might be very helpful!
//Check for overlapping notes
/*if (insPos >= 0 && _Notes[insPos].EndBeat > Note.StartBeat)
return false;
if (insPos < _Notes.Count - 1 && _Notes[insPos+1].StartBeat > Note.EndBeat)
return false;
* */
_Notes.Insert(insPos + 1, note);
}
_UpdateMinMaxBeat(note);
return true;
}
public bool DeleteNote(int index)
{
if (_Notes.Count > index)
{
_Notes.RemoveAt(index);
if (index == 0 || index == _Notes.Count - 1)
_UpdateMinMaxBeat();
return true;
}
return false;
}
public bool ReplaceNote(int index, CNote note)
{
if (_Notes.Count > index)
{
_Notes.RemoveAt(index);
return AddNote(note);
}
return false;
}
public bool IncLastNoteLength()
{
if (_Notes.Count > 0)
{
_Notes[_Notes.Count - 1].Duration++;
_MaxBeat++;
}
return false;
}
public void DeleteAllNotes()
{
_Notes.Clear();
_UpdateMinMaxBeat();
}
public void SetMedley(int startBeat, int endBeat)
{
foreach (CNote note in _Notes)
{
if (note.StartBeat < startBeat || note.EndBeat > endBeat)
note.NoteType = ENoteType.Freestyle;
}
_VisibleInTimeLine = _MinBeat >= startBeat && _MaxBeat <= endBeat;
}
private void _UpdateMinMaxBeat(CNote note)
{
if (note.StartBeat < _MinBeat)
_MinBeat = note.StartBeat;
if (note.EndBeat > _MaxBeat)
_MaxBeat = note.EndBeat;
}
private void _UpdateMinMaxBeat()
{
if (_Notes.Count > 0)
{
_MinBeat = _Notes[0].StartBeat;
_MaxBeat = _Notes[_Notes.Count - 1].EndBeat;
}
else
{
_MinBeat = int.MaxValue;
_MaxBeat = int.MinValue;
}
}
#endregion Methods
}
public class CVoice
{
private readonly List<CLine> _Lines = new List<CLine>();
public CVoice() {}
public CVoice(CVoice voice)
{
foreach (CLine line in voice._Lines)
_Lines.Add(new CLine(line));
}
public CLine[] Lines
{
get { return _Lines.ToArray(); }
}
public int NumLines
{
get { return _Lines.Count; }
}
/// <summary>
/// Total song length in beats
/// </summary>
public int Length
{
get
{
if (_Lines.Count == 0)
return 0;
int startbeat = _Lines.Max(line => line.FirstNoteBeat);
int endbeat = _Lines.Min(line => line.LastNoteBeat);
int result = endbeat - startbeat;
return result > 0 ? result : 0;
}
}
public int Points
{
get { return _Lines.Sum(line => line.Points); }
}
public int NumLinesWithPoints
{
get { return _Lines.Count(line => line.Points > 0f); }
}
#region Methods
//Find last line with StartBeat<=Beat
public int FindPreviousLine(int beat)
{
//If no line -> No previous line
if (_Lines.Count == 0)
return -1;
int start = 0;
int end = _Lines.Count - 1;
//Ensure that start.StartBeat<=Beat && end.StartBeat>Beat
if (_Lines[0].StartBeat > beat)
return -1;
if (_Lines[end].StartBeat <= beat)
return end;
//Binary search
while (end - start > 1)
{
int mid = (start + end) / 2;
if (_Lines[mid].StartBeat <= beat)
start = mid;
else
end = mid;
}
return start;
}
public void AddLine(CLine line)
{
if (_Lines.Count == 0)
_Lines.Add(line);
else
{
int insPos = FindPreviousLine(line.StartBeat);
_Lines.Insert(insPos + 1, line);
}
}
public bool DeleteLine(int index)
{
if (_Lines.Count > index)
{
_Lines.RemoveAt(index);
UpdateTimings();
return true;
}
return false;
}
public void DeleteAllLines()
{
_Lines.Clear();
}
public bool AddNote(CNote note, bool updateTimings = false)
{
int lineIndex = FindPreviousLine(note.StartBeat);
if (lineIndex < 0)
{
//Note is before ALL lines
CLine line = new CLine {StartBeat = note.StartBeat};
line.AddNote(note);
_Lines.Insert(0, line);
}
else
{
if (!_Lines[lineIndex].AddNote(note))
return false;
}
if (updateTimings)
UpdateTimings();
return true;
}
public bool InsertNote(CNote note, int lineIndex, bool updateTimings = false)
{
if (_Lines.Count > lineIndex && _Lines[lineIndex].StartBeat <= note.StartBeat)
{
_Lines[lineIndex].AddNote(note);
if (updateTimings)
UpdateTimings();
return true;
}
return false;
}
public void UpdateTimings()
{
CNote lastNote;
if (_Lines.Count > 0)
_Lines[0].StartBeat = -10000;
for (int i = 1; i < _Lines.Count; i++)
{
lastNote = _Lines[i - 1].LastNote;
CNote firstNote = _Lines[i].FirstNote;
if ((lastNote != null) && (firstNote != null))
{
int min = lastNote.EndBeat;
int max = firstNote.StartBeat;
int s;
switch (max - min)
{
case 0:
s = max;
break;
case 1:
s = max;
break;
case 2:
s = max - 1;
break;
case 3:
s = max - 2;
break;
default:
s = min + 2;
break;
}
_Lines[i].StartBeat = s;
_Lines[i - 1].EndBeat = min;
}
}
lastNote = _Lines[_Lines.Count - 1].LastNote;
if (lastNote != null)
_Lines[_Lines.Count - 1].EndBeat = lastNote.EndBeat;
}
public void SetMedley(int startBeat, int endBeat)
{
foreach (CLine line in _Lines)
line.SetMedley(startBeat, endBeat);
}
#endregion Methods
}
}
+3 -3
View File
@@ -725,7 +725,7 @@ namespace VocaluxeLib.Songs
private bool _ParseNote(int player, ENoteType noteType, int start, int length, int tone, string text)
{
CNote note = new CNote(start, length, tone, text, noteType);
CSongNote note = new CSongNote(start, length, tone, text, noteType);
CVoice voice = Notes.GetVoice(player);
return voice.AddNote(note);
}
@@ -733,7 +733,7 @@ namespace VocaluxeLib.Songs
private void _NewSentence(int player, int start)
{
CVoice voice = Notes.GetVoice(player);
CLine line = new CLine {StartBeat = start};
CSongLine line = new CSongLine {StartBeat = start};
voice.AddLine(line);
}
@@ -933,7 +933,7 @@ namespace VocaluxeLib.Songs
}
//Check if stop is in line
foreach (CLine line in voice.Lines)
foreach (CSongLine line in voice.Lines)
{
if (line.FirstNoteBeat < stop && line.LastNoteBeat > stop)
{
+86
View File
@@ -0,0 +1,86 @@
using System;
using System.Linq;
namespace VocaluxeLib.Songs
{
public class CSongLine : CLineBase<CSongNote>
{
private int _StartBeat = int.MinValue;
private int _EndBeat = int.MinValue;
#region Constructors
public CSongLine()
{
VisibleInTimeLine = true;
}
public CSongLine(CSongLine line)
{
foreach (CSongNote note in line._Notes)
_Notes.Add(new CSongNote(note));
_StartBeat = line._StartBeat;
_EndBeat = line._EndBeat;
VisibleInTimeLine = line.VisibleInTimeLine;
}
#endregion Constructors
#region Properties
public bool VisibleInTimeLine { get; set; }
public int StartBeat
{
get { return _StartBeat; }
set
{
if (value <= FirstNoteBeat)
_StartBeat = value;
}
}
public int EndBeat
{
get { return _EndBeat; }
set
{
if (value >= LastNoteBeat)
_EndBeat = value;
}
}
public string Lyrics
{
get { return _Notes.Aggregate(String.Empty, (current, note) => current + note.Text); }
}
#endregion Properties
#region Methods
public override bool AddNote(CSongNote note)
{
if (_Notes.Count == 0)
_Notes.Add(note);
else
{
int insPos = FindPreviousNote(note.StartBeat);
//Check for overlapping notes
if (insPos >= 0 && _Notes[insPos].EndBeat > note.StartBeat)
return false;
if (insPos < _Notes.Count - 1 && _Notes[insPos + 1].StartBeat > note.EndBeat)
return false;
_Notes.Insert(insPos + 1, note);
}
return true;
}
public void SetMedley(int startBeat, int endBeat)
{
foreach (CSongNote note in _Notes)
{
if (note.StartBeat < startBeat || note.EndBeat > endBeat)
note.NoteType = ENoteType.Freestyle;
}
VisibleInTimeLine = FirstNoteBeat >= startBeat && LastNoteBeat <= endBeat;
}
#endregion Methods
}
}
+52
View File
@@ -0,0 +1,52 @@
namespace VocaluxeLib.Songs
{
/// <summary>
/// Class to represent a note in a song
/// </summary>
public class CSongNote : CBaseNote
{
#region Contructors
public CSongNote(CSongNote note) : base(note)
{
NoteType = note.NoteType;
Text = note.Text;
}
public CSongNote(int startBeat, int duration, int tone, string text) : base(startBeat, duration, tone)
{
NoteType = ENoteType.Normal;
Text = text;
}
public CSongNote(int startBeat, int duration, int tone, string text, ENoteType noteType)
: this(startBeat, duration, tone, text)
{
NoteType = noteType;
}
#endregion Constructors
#region Properties
public ENoteType NoteType { get; set; }
public string Text { get; set; }
public override int PointsForBeat
{
get
{
switch (NoteType)
{
case ENoteType.Normal:
return 1;
case ENoteType.Golden:
return 2;
case ENoteType.Freestyle:
return 0;
default:
return 0;
}
}
}
#endregion Properties
}
}
+18
View File
@@ -0,0 +1,18 @@
using System.Linq;
namespace VocaluxeLib.Songs
{
public class CSungLine : CLineBase<CSungNote>
{
// for drawing perfect line effect
public bool PerfectLine { get; set; }
public bool IsPerfect(CSongLine compareLine)
{
PerfectLine = _Notes.Count > 0;
PerfectLine &= _Notes.Count == compareLine.NoteCount;
PerfectLine &= _Notes.All(note => note.Perfect);
return PerfectLine;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
namespace VocaluxeLib.Songs
{
/// <summary>
/// Note that was sung by a player
/// </summary>
public class CSungNote : CBaseNote
{
/// <summary>
/// Constructor for a sung note that was not hit
/// </summary>
/// <param name="startBeat"></param>
/// <param name="duration"></param>
/// <param name="tone"></param>
public CSungNote(int startBeat, int duration, int tone) : base(startBeat, duration, tone)
{
Perfect = false;
HitNote = null;
}
/// <summary>
/// Constructor for a sung note that hit the given note
/// </summary>
/// <param name="startBeat"></param>
/// <param name="duration"></param>
/// <param name="tone"></param>
/// <param name="hitNote"></param>
public CSungNote(int startBeat, int duration, int tone, CSongNote hitNote) : this(startBeat, duration, tone)
{
HitNote = hitNote;
}
#region Properties
// for drawing player notes
public bool Hit
{
get { return HitNote != null; }
}
public CSongNote HitNote { get; set; }
// for drawing perfect note effect
public bool Perfect { get; set; }
#endregion
#region Methods
public void CheckPerfect()
{
bool result = HitNote != null;
if (result)
{
result = (StartBeat == HitNote.StartBeat);
result &= (EndBeat == HitNote.EndBeat);
result &= (Tone == HitNote.Tone);
}
Perfect = result;
}
#endregion Methods
public override int PointsForBeat
{
get { return (HitNote == null) ? 0 : HitNote.PointsForBeat; }
}
}
}
+194
View File
@@ -0,0 +1,194 @@
using System.Collections.Generic;
using System.Linq;
namespace VocaluxeLib.Songs
{
public class CVoice
{
private readonly List<CSongLine> _Lines = new List<CSongLine>();
public CVoice() {}
public CVoice(CVoice voice)
{
foreach (CSongLine line in voice._Lines)
_Lines.Add(new CSongLine(line));
}
public CSongLine[] Lines
{
get { return _Lines.ToArray(); }
}
public int NumLines
{
get { return _Lines.Count; }
}
/// <summary>
/// Total song length in beats
/// </summary>
public int Length
{
get
{
if (_Lines.Count == 0)
return 0;
int startbeat = _Lines.Max(line => line.FirstNoteBeat);
int endbeat = _Lines.Min(line => line.LastNoteBeat);
int result = endbeat - startbeat;
return result > 0 ? result : 0;
}
}
public int Points
{
get { return _Lines.Sum(line => line.Points); }
}
public int NumLinesWithPoints
{
get { return _Lines.Count(line => line.Points > 0f); }
}
#region Methods
//Find last line with StartBeat<=Beat
public int FindPreviousLine(int beat)
{
//If no line -> No previous line
if (_Lines.Count == 0)
return -1;
int start = 0;
int end = _Lines.Count - 1;
//Ensure that start.StartBeat<=Beat && end.StartBeat>Beat
if (_Lines[0].StartBeat > beat)
return -1;
if (_Lines[end].StartBeat <= beat)
return end;
//Binary search
while (end - start > 1)
{
int mid = (start + end) / 2;
if (_Lines[mid].StartBeat <= beat)
start = mid;
else
end = mid;
}
return start;
}
public void AddLine(CSongLine line)
{
if (_Lines.Count == 0)
_Lines.Add(line);
else
{
int insPos = FindPreviousLine(line.StartBeat);
_Lines.Insert(insPos + 1, line);
}
}
public bool DeleteLine(int index)
{
if (_Lines.Count > index)
{
_Lines.RemoveAt(index);
UpdateTimings();
return true;
}
return false;
}
public void DeleteAllLines()
{
_Lines.Clear();
}
public bool AddNote(CSongNote note, bool updateTimings = false)
{
int lineIndex = FindPreviousLine(note.StartBeat);
if (lineIndex < 0)
{
//Note is before ALL lines
CSongLine line = new CSongLine {StartBeat = note.StartBeat};
line.AddNote(note);
_Lines.Insert(0, line);
}
else
{
if (!_Lines[lineIndex].AddNote(note))
return false;
}
if (updateTimings)
UpdateTimings();
return true;
}
public bool InsertNote(CSongNote note, int lineIndex, bool updateTimings = false)
{
if (_Lines.Count > lineIndex && _Lines[lineIndex].StartBeat <= note.StartBeat)
{
_Lines[lineIndex].AddNote(note);
if (updateTimings)
UpdateTimings();
return true;
}
return false;
}
public void UpdateTimings()
{
CSongNote lastNote;
if (_Lines.Count > 0)
_Lines[0].StartBeat = -10000;
for (int i = 1; i < _Lines.Count; i++)
{
lastNote = _Lines[i - 1].LastNote;
CSongNote firstNote = _Lines[i].FirstNote;
if ((lastNote != null) && (firstNote != null))
{
int min = lastNote.EndBeat;
int max = firstNote.StartBeat;
int s;
switch (max - min)
{
case 0:
s = max;
break;
case 1:
s = max;
break;
case 2:
s = max - 1;
break;
case 3:
s = max - 2;
break;
default:
s = min + 2;
break;
}
_Lines[i].StartBeat = s;
_Lines[i - 1].EndBeat = min;
}
}
lastNote = _Lines[_Lines.Count - 1].LastNote;
if (lastNote != null)
_Lines[_Lines.Count - 1].EndBeat = lastNote.EndBeat;
}
public void SetMedley(int startBeat, int endBeat)
{
foreach (CSongLine line in _Lines)
line.SetMedley(startBeat, endBeat);
}
#endregion Methods
}
}
+2 -2
View File
@@ -186,8 +186,8 @@ namespace VocaluxeLib
public double PointsLineBonus;
public double PointsGoldenNotes;
public int NoteDiff;
public int LineNr;
public List<CLine> SingLine;
public int VoiceNr;
public List<CSungLine> SungLines;
public int CurrentLine;
public int CurrentNote;
+7
View File
@@ -138,6 +138,10 @@
<Compile Include="Menu\IMenuElement.cs" />
<Compile Include="Profile\CAvatar.cs" />
<Compile Include="Profile\CProfile.cs" />
<Compile Include="Songs\CLineBase.cs" />
<Compile Include="Songs\CBaseNote.cs" />
<Compile Include="Songs\CSongLine.cs" />
<Compile Include="Songs\CSongNote.cs" />
<Compile Include="Songs\CNotes.cs" />
<Compile Include="Menu\SingNotes\CSingNotes.cs" />
<Compile Include="Menu\SingNotes\CSingNotesClassic.cs" />
@@ -150,6 +154,9 @@
<Compile Include="Menu\SongMenu\CSongMenuList.cs" />
<Compile Include="Menu\SongMenu\CSongMenuTileBoard.cs" />
<Compile Include="Menu\SongMenu\ISongMenu.cs" />
<Compile Include="Songs\CSungLine.cs" />
<Compile Include="Songs\CSungNote.cs" />
<Compile Include="Songs\CVoice.cs" />
<Compile Include="Structs.cs" />
<Compile Include="PartyModes\CPartyMode.cs" />
<Compile Include="PartyModes\CPartyModeNone.cs" />