Archived
Merge pull request '添加对 Core 的直接引用' (#2) from obsmain into master
Reviewed-on: obugs/RDTKEditor#2
This commit was merged in pull request #2.
This commit is contained in:
+1
-1
@@ -252,6 +252,6 @@ namespace RDTKEditor
|
||||
}
|
||||
public class MainViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -9,8 +9,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="RhythmBase" Version="1.1.0-beta" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SkiaSharp.Views.WPF" Version="3.118.0-preview.2.3" />
|
||||
<PackageReference Include="sly" Version="3.6.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.IO" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
using RhythmBase.Adofai.Utils;
|
||||
using RhythmBase.Exceptions;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a beat in the ADLevel.
|
||||
/// </summary>
|
||||
public struct ADBeat : IComparable<ADBeat>, IEquatable<ADBeat>
|
||||
{
|
||||
internal readonly ADLevel? baseLevel => _calculator?.Collection;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the beat only value.
|
||||
/// </summary>
|
||||
public readonly float BeatOnly
|
||||
{
|
||||
get => _beat + 1f;
|
||||
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time span.
|
||||
/// </summary>
|
||||
public readonly TimeSpan TimeSpan
|
||||
{
|
||||
get => _timeSpan;
|
||||
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ADBeat"/> struct with a specified beat.
|
||||
/// </summary>
|
||||
/// <param name="beat">The beat value.</param>
|
||||
public ADBeat(float beat)
|
||||
{
|
||||
this = default;
|
||||
_beat = beat;
|
||||
_isBeatLoaded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ADBeat"/> struct with a specified time span.
|
||||
/// </summary>
|
||||
/// <param name="timeSpan">The time span value.</param>
|
||||
public ADBeat(TimeSpan timeSpan)
|
||||
{
|
||||
this = default;
|
||||
_timeSpan = timeSpan;
|
||||
_isTimeSpanLoaded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ADBeat"/> struct with a specified calculator and beat.
|
||||
/// </summary>
|
||||
/// <param name="calculator">The beat calculator.</param>
|
||||
/// <param name="beat">The beat value.</param>
|
||||
public ADBeat(ADBeatCalculator calculator, float beat)
|
||||
{
|
||||
this = default;
|
||||
_calculator = calculator;
|
||||
_beat = beat;
|
||||
_isBeatLoaded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ADBeat"/> struct with a specified calculator and time span.
|
||||
/// </summary>
|
||||
/// <param name="calculator">The beat calculator.</param>
|
||||
/// <param name="timeSpan">The time span value.</param>
|
||||
/// <exception cref="OverflowException">Thrown when the time span is less than zero.</exception>
|
||||
public ADBeat(ADBeatCalculator calculator, TimeSpan timeSpan)
|
||||
{
|
||||
this = default;
|
||||
if (timeSpan < TimeSpan.Zero)
|
||||
{
|
||||
throw new OverflowException(string.Format("The time must not be less than zero, but {0} is given", timeSpan));
|
||||
}
|
||||
_calculator = calculator;
|
||||
_timeSpan = timeSpan;
|
||||
_isTimeSpanLoaded = true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Construct a beat of the 1st beat from the calculator
|
||||
/// </summary>
|
||||
/// <param name="calculator">Specified calculator.</param>
|
||||
/// <returns>The first beat tied to the level.</returns>
|
||||
public static ADBeat Default(ADBeatCalculator calculator)
|
||||
{
|
||||
ADBeat Default = new(calculator, 1f);
|
||||
return Default;
|
||||
}
|
||||
/// <summary>
|
||||
/// Determine if two beats come from the same level
|
||||
/// </summary>
|
||||
/// <param name="a">A beat.</param>
|
||||
/// <param name="b">Another beat.</param>
|
||||
/// <param name="throw">If true, an exception will be thrown when two beats do not come from the same level.</param>
|
||||
/// <returns></returns>
|
||||
public static bool FromSameLevel(ADBeat a, ADBeat b, bool @throw = false)
|
||||
{
|
||||
bool flag = a.baseLevel.Equals(b.baseLevel);
|
||||
bool FromSameLevel;
|
||||
if (flag)
|
||||
{
|
||||
FromSameLevel = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (@throw)
|
||||
{
|
||||
throw new RhythmBaseException("Beats must come from the same ADLevel.");
|
||||
}
|
||||
FromSameLevel = false;
|
||||
}
|
||||
return FromSameLevel;
|
||||
}
|
||||
/// <summary>
|
||||
/// Determine if two beats are from the same level.
|
||||
/// <br />
|
||||
/// If any of them does not come from any level, it will also return true.
|
||||
/// </summary>
|
||||
/// <param name="a">A beat.</param>
|
||||
/// <param name="b">Another beat.</param>
|
||||
/// <param name="throw">If true, an exception will be thrown when two beats do not come from the same level.</param>
|
||||
/// <returns></returns>
|
||||
public static bool FromSameLevelOrNull(ADBeat a, ADBeat b, bool @throw = false) => a.baseLevel == null || b.baseLevel == null || FromSameLevel(a, b, @throw);
|
||||
|
||||
public readonly bool FromSameLevel(ADBeat b, bool @throw = false) => FromSameLevel(this, b, @throw);
|
||||
/// <summary>
|
||||
/// Determine if two beats are from the same level.
|
||||
/// <br />
|
||||
/// If any of them does not come from any level, it will also return true.
|
||||
/// </summary>
|
||||
/// <param name="b">Another beat.</param>
|
||||
/// <param name="throw">If true, an exception will be thrown when two beats do not come from the same level.</param>
|
||||
/// <returns></returns>
|
||||
public readonly bool FromSameLevelOrNull(ADBeat b, bool @throw = false) => baseLevel == null || b.baseLevel == null || FromSameLevel(b, @throw);
|
||||
/// <summary>
|
||||
/// Returns a new instance of unbinding the level.
|
||||
/// </summary>
|
||||
/// <returns>A new instance of unbinding the level.</returns>
|
||||
public readonly ADBeat WithoutBinding()
|
||||
{
|
||||
ADBeat result = this;
|
||||
result._calculator = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
private readonly void IfNullThrowException()
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
throw new InvalidRDBeatException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Refresh the cache.
|
||||
/// </summary>
|
||||
public void ResetCache()
|
||||
{
|
||||
float i = BeatOnly;
|
||||
_isTimeSpanLoaded = false;
|
||||
}
|
||||
|
||||
internal void ResetBPM()
|
||||
{
|
||||
_isBeatLoaded = true;
|
||||
_isTimeSpanLoaded = false;
|
||||
_isBpmLoaded = false;
|
||||
}
|
||||
|
||||
internal void ResetCPB() => _isBeatLoaded = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is empty.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is empty; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public readonly bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return _calculator == null || (!_isBeatLoaded && !_isTimeSpanLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static ADBeat operator +(ADBeat a, float b)
|
||||
{
|
||||
ADBeat result = new(a._calculator, a.BeatOnly + b);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static ADBeat operator +(ADBeat a, TimeSpan b)
|
||||
{
|
||||
ADBeat result = new(a._calculator, a.TimeSpan + b);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static ADBeat operator -(ADBeat a, float b)
|
||||
{
|
||||
ADBeat result = new(a._calculator, a.BeatOnly - b);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static ADBeat operator -(ADBeat a, TimeSpan b)
|
||||
{
|
||||
ADBeat result = new(a._calculator, a.TimeSpan - b);
|
||||
return result;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public static bool operator >(ADBeat a, ADBeat b) => FromSameLevel(a, b, true) && a.BeatOnly > b.BeatOnly;
|
||||
/// <inheritdoc/>
|
||||
|
||||
public static bool operator <(ADBeat a, ADBeat b) => FromSameLevel(a, b, true) && a.BeatOnly < b.BeatOnly;
|
||||
/// <inheritdoc/>
|
||||
|
||||
public static bool operator >=(ADBeat a, ADBeat b) => FromSameLevel(a, b, true) && a.BeatOnly >= b.BeatOnly;
|
||||
/// <inheritdoc/>
|
||||
|
||||
public static bool operator <=(ADBeat a, ADBeat b) => FromSameLevel(a, b, true) && a.BeatOnly <= b.BeatOnly;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator ==(ADBeat a, ADBeat b) => (FromSameLevel(a, b, true) && a._beat == b._beat) || (a._isTimeSpanLoaded && b._isTimeSpanLoaded && a._timeSpan == b._timeSpan) || a.BeatOnly == b.BeatOnly;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator !=(ADBeat a, ADBeat b) => !(a == b);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public readonly int CompareTo(ADBeat other) => checked((int)Math.Round((double)unchecked(_beat - other._beat)));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override readonly string ToString() => string.Format("[{0}]", BeatOnly);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override readonly bool Equals([NotNull] object obj) => obj.GetType() == typeof(ADBeat) && Equals((obj != null) ? ((ADBeat)obj) : default);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public readonly bool Equals(ADBeat other) => this == other;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override readonly int GetHashCode() => HashCode.Combine(BeatOnly, baseLevel);
|
||||
|
||||
internal ADBeatCalculator? _calculator;
|
||||
|
||||
private bool _isBeatLoaded;
|
||||
|
||||
private bool _isTimeSpanLoaded;
|
||||
|
||||
private bool _isBpmLoaded;
|
||||
|
||||
private float _beat;
|
||||
|
||||
private TimeSpan _timeSpan;
|
||||
|
||||
private float _bpm;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Adofai.Converters;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Adofai.Utils;
|
||||
using RhythmBase.Exceptions;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Adofal level.
|
||||
/// </summary>
|
||||
public class ADLevel : ADTileCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// Level settings.
|
||||
/// </summary>
|
||||
public ADSettings Settings { get; set; }
|
||||
/// <summary>
|
||||
/// Level decoration collection.
|
||||
/// </summary>
|
||||
public List<ADBaseEvent> Decorations { get; set; }
|
||||
/// <summary>
|
||||
/// Level file path.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string Path => _path;
|
||||
/// <summary>
|
||||
/// Level directory path.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string Directory => System.IO.Path.GetDirectoryName(_path);
|
||||
/// <summary>
|
||||
/// Get all the events of the level.
|
||||
/// </summary>
|
||||
public override IEnumerable<ADBaseEvent> Events
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (ADBaseEvent tile in base.Events)
|
||||
yield return tile;
|
||||
foreach (ADBaseEvent tile2 in Decorations)
|
||||
yield return tile2;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The calculator that comes with the level.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public ADBeatCalculator Calculator { get; }
|
||||
public ADLevel()
|
||||
{
|
||||
Settings = new ADSettings();
|
||||
Decorations = [];
|
||||
Calculator = new ADBeatCalculator(this);
|
||||
}
|
||||
public ADLevel(IEnumerable<ADTile> items)
|
||||
{
|
||||
Settings = new ADSettings();
|
||||
Decorations = [];
|
||||
Calculator = new ADBeatCalculator(this);
|
||||
foreach (ADTile tile in items)
|
||||
Add(tile);
|
||||
}
|
||||
/// <summary>
|
||||
/// The default level within the game.
|
||||
/// </summary>
|
||||
public static ADLevel Default => [];
|
||||
/// <summary>
|
||||
/// Read from file as level.
|
||||
/// Use default input settings.
|
||||
/// Supports .rdlevel, .rdzip, .zip file extension.
|
||||
/// </summary>
|
||||
/// <param name="filepath">File path.</param>
|
||||
/// <returns>An instance of a level that reads from a file.</returns>
|
||||
public static ADLevel Read(string filepath) => Read(filepath, new LevelReadOrWriteSettings());
|
||||
/// <summary>
|
||||
/// Read from file as level.
|
||||
/// Supports .rdlevel, .rdzip, .zip file extension.
|
||||
/// </summary>
|
||||
/// <param name="filepath">File path.</param>
|
||||
/// <param name="settings">Input settings.</param>
|
||||
/// <returns>An instance of a level that reads from a file.</returns>
|
||||
public static ADLevel Read(string filepath, LevelReadOrWriteSettings settings)
|
||||
{
|
||||
JsonSerializer LevelSerializer = new();
|
||||
LevelSerializer.Converters.Add(new ADLevelConverter(filepath, settings));
|
||||
string extension = System.IO.Path.GetExtension(filepath);
|
||||
if (extension != ".adofai")
|
||||
{
|
||||
throw new RhythmBaseException("File not supported.");
|
||||
}
|
||||
return LevelSerializer.Deserialize<ADLevel>(new JsonTextReader(File.OpenText(filepath)))!;
|
||||
}
|
||||
internal string _path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
public class ADSettings
|
||||
{
|
||||
public ADSettings()
|
||||
{
|
||||
RequiredMods = [];
|
||||
}
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
public string Artist { get; set; }
|
||||
|
||||
public SpecialArtistTypes SpecialArtistType { get; set; }
|
||||
|
||||
public string ArtistPermission { get; set; }
|
||||
|
||||
public string Song { get; set; }
|
||||
|
||||
public string Author { get; set; }
|
||||
|
||||
public bool SeparateCountdownTime { get; set; }
|
||||
|
||||
public string PreviewImage { get; set; }
|
||||
|
||||
public string PreviewIcon { get; set; }
|
||||
|
||||
public RDColor PreviewIconColor { get; set; }
|
||||
|
||||
public float PreviewSongStart { get; set; }
|
||||
|
||||
public float PreviewSongDuration { get; set; }
|
||||
|
||||
public bool SeizureWarning { get; set; }
|
||||
|
||||
public string LevelDesc { get; set; }
|
||||
|
||||
public string LevelTags { get; set; }
|
||||
|
||||
public string ArtistLinks { get; set; }
|
||||
|
||||
public int Difficulty { get; set; }
|
||||
|
||||
public List<string> RequiredMods { get; set; }
|
||||
|
||||
public string SongFilename { get; set; }
|
||||
|
||||
public float Bpm { get; set; }
|
||||
|
||||
public float Volume { get; set; }
|
||||
|
||||
public float Offset { get; set; }
|
||||
|
||||
public float Pitch { get; set; }
|
||||
|
||||
public string Hitsound { get; set; }
|
||||
|
||||
public float HitsoundVolume { get; set; }
|
||||
|
||||
public float CountdownTicks { get; set; }
|
||||
|
||||
public ADTrackColorTypes TrackColorType { get; set; }
|
||||
|
||||
public RDColor TrackColor { get; set; }
|
||||
|
||||
public RDColor SecondaryTrackColor { get; set; }
|
||||
|
||||
public float TrackColorAnimDuration { get; set; }
|
||||
|
||||
public ADTrackColorPulses TrackColorPulse { get; set; }
|
||||
|
||||
public float TrackPulseLength { get; set; }
|
||||
|
||||
public ADTrackStyles TrackStyle { get; set; }
|
||||
|
||||
public ADTrackAnimationTypes TrackAnimation { get; set; }
|
||||
|
||||
public int BeatsAhead { get; set; }
|
||||
|
||||
public ADTrackDisappearAnimationTypes TrackDisappearAnimation { get; set; }
|
||||
|
||||
public int BeatsBehind { get; set; }
|
||||
|
||||
public RDColor BackgroundColor { get; set; }
|
||||
|
||||
public bool ShowDefaultBGIfNoImage { get; set; }
|
||||
|
||||
public string BgImage { get; set; }
|
||||
|
||||
public RDColor BgImageColor { get; set; }
|
||||
|
||||
public RDPointI Parallax { get; set; }
|
||||
|
||||
public BgDisplayModes BgDisplayMode { get; set; }
|
||||
|
||||
public bool LockRot { get; set; }
|
||||
|
||||
public bool LoopBG { get; set; }
|
||||
|
||||
public float ScalingRatio { get; set; }
|
||||
|
||||
public ADCameraRelativeTo RelativeTo { get; set; }
|
||||
|
||||
public RDPointI Position { get; set; }
|
||||
|
||||
public float Rotation { get; set; }
|
||||
|
||||
public float Zoom { get; set; }
|
||||
|
||||
public string BgVideo { get; set; }
|
||||
|
||||
public bool LoopVideo { get; set; }
|
||||
|
||||
public int VidOffset { get; set; }
|
||||
|
||||
public bool FloorIconOutlines { get; set; }
|
||||
|
||||
public bool StickToFloors { get; set; }
|
||||
|
||||
public EaseType PlanetEase { get; set; }
|
||||
|
||||
public int PlanetEaseParts { get; set; }
|
||||
|
||||
public ADEasePartBehaviors PlanetEasePartBehavior { get; set; }
|
||||
|
||||
public RDColor DefaultTextColor { get; set; }
|
||||
|
||||
public RDColor DefaultTextShadowColor { get; set; }
|
||||
|
||||
public string CongratsText { get; set; }
|
||||
|
||||
public string PerfectText { get; set; }
|
||||
|
||||
public bool LegacyFlash { get; set; }
|
||||
|
||||
public bool LegacyCamRelativeTo { get; set; }
|
||||
|
||||
public bool LegacySpriteTiles { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using RhythmBase.Adofai.Events;
|
||||
using System.Collections;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
public abstract class ADTileCollection : ICollection<ADTile>
|
||||
{
|
||||
protected ADTileCollection()
|
||||
{
|
||||
tileOrder = [];
|
||||
IsReadOnly = false;
|
||||
EndTile = [];
|
||||
}
|
||||
public int Count => tileOrder.Count;
|
||||
public bool IsReadOnly { get; }
|
||||
public ADTile EndTile { get; }
|
||||
public ADTile this[int index] => index == tileOrder.Count ? EndTile : tileOrder[index];
|
||||
public virtual IEnumerable<ADBaseEvent> Events
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (ADTile tile in tileOrder)
|
||||
foreach (ADBaseTileEvent action in tile)
|
||||
yield return action;
|
||||
foreach (ADBaseTileEvent action2 in EndTile)
|
||||
yield return action2;
|
||||
}
|
||||
}
|
||||
public void Add(ADTile item) => tileOrder.Add(item);
|
||||
public void Clear() => tileOrder.Clear();
|
||||
public void CopyTo(ADTile[] array, int arrayIndex) => tileOrder.CopyTo(array, arrayIndex);
|
||||
public bool Contains(ADTile item) => tileOrder.Contains(item);
|
||||
public bool Remove(ADTile item) => tileOrder.Remove(item);
|
||||
public IEnumerator<ADTile> GetEnumerator() => tileOrder.GetEnumerator();
|
||||
/// <summary>
|
||||
/// Get the index of tile.
|
||||
/// </summary>
|
||||
/// <param name="item">The index of tile.</param>
|
||||
/// <returns></returns>
|
||||
public int IndexOf(ADTile item) => item == EndTile ? Count : tileOrder.IndexOf(item);
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
internal List<ADTile> tileOrder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
public enum ADTrackAnimationTypes
|
||||
{
|
||||
None,
|
||||
Assemble,
|
||||
Assemble_Far,
|
||||
Extend,
|
||||
Grow,
|
||||
Grow_Spin,
|
||||
Fade,
|
||||
Drop,
|
||||
Rise
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
public enum ADTrackDisappearAnimationTypes
|
||||
{
|
||||
None,
|
||||
Scatter,
|
||||
Scatter_Far,
|
||||
Retract,
|
||||
Shrink,
|
||||
Shrink_Spin,
|
||||
Fade
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using RhythmBase.Adofai.Events;
|
||||
using System.Collections;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
public class ADTypedList<TEvent> : IEnumerable<TEvent> where TEvent : ADBaseEvent
|
||||
{
|
||||
public ADTypedList()
|
||||
{
|
||||
list = [];
|
||||
_types = [];
|
||||
}
|
||||
public void Add(TEvent item)
|
||||
{
|
||||
list.Add(item);
|
||||
_types.Add(item.Type);
|
||||
}
|
||||
public object Remove(TEvent item)
|
||||
{
|
||||
_types.Remove(item.Type);
|
||||
return list.Remove(item);
|
||||
}
|
||||
public override string ToString() => string.Format("Count = {0}", list.Count);
|
||||
public IEnumerator<TEvent> GetEnumerator() => list.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => list.GetEnumerator();
|
||||
private readonly List<TEvent> list;
|
||||
protected internal HashSet<ADEventType> _types;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Components
|
||||
{
|
||||
public enum BgDisplayModes
|
||||
{
|
||||
FitToScreen,
|
||||
Unscaled,
|
||||
Tiled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Adofai.Utils;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Adofai.Converters
|
||||
{
|
||||
internal class ADBaseEventConverter<TEvent>(ADLevel level, LevelReadOrWriteSettings inputSettings) : JsonConverter<TEvent> where TEvent : ADBaseEvent
|
||||
{
|
||||
public override bool CanRead
|
||||
{
|
||||
get
|
||||
{
|
||||
return _canread;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get
|
||||
{
|
||||
return _canwrite;
|
||||
}
|
||||
}
|
||||
public override void WriteJson(JsonWriter writer, TEvent? value, JsonSerializer serializer) => throw new NotImplementedException();
|
||||
|
||||
public override TEvent ReadJson(JsonReader reader, Type objectType, TEvent? existingValue, bool hasExistingValue, JsonSerializer serializer) => GetDeserializedObject((JObject)JToken.ReadFrom(reader), objectType, existingValue, hasExistingValue, serializer);
|
||||
|
||||
public virtual TEvent GetDeserializedObject(JObject jobj, Type objectType, TEvent existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
Type SubClassType = Utils.Utils.ADConvertToType(jobj["eventType"].ToObject<string>());
|
||||
_canread = false;
|
||||
existingValue = Conversions.ToGenericParameter<TEvent>((SubClassType != null) ? jobj.ToObject(SubClassType, serializer) : jobj.ToObject<ADCustomEvent>(serializer));
|
||||
_canread = true;
|
||||
return existingValue;
|
||||
}
|
||||
|
||||
public virtual JObject SetSerializedObject(TEvent value, JsonSerializer serializer)
|
||||
{
|
||||
_canwrite = false;
|
||||
JObject JObj = JObject.FromObject(value, serializer);
|
||||
_canwrite = true;
|
||||
JObj.Remove("type");
|
||||
JToken s = JObj.First;
|
||||
s.AddBeforeSelf(new JProperty("eventType", value.Type.ToString()));
|
||||
return JObj;
|
||||
}
|
||||
|
||||
protected readonly ADLevel level = level;
|
||||
|
||||
protected readonly LevelReadOrWriteSettings settings = inputSettings;
|
||||
|
||||
protected bool _canread = true;
|
||||
|
||||
protected bool _canwrite = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Adofai.Utils;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Adofai.Converters
|
||||
{
|
||||
internal class ADBaseTileEventConverter<TEvent>(ADLevel level, LevelReadOrWriteSettings inputSettings) : ADBaseEventConverter<TEvent>(level, inputSettings) where TEvent : ADBaseTileEvent
|
||||
{
|
||||
public override TEvent GetDeserializedObject(JObject jobj, Type objectType, TEvent existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
JToken jtoken = jobj["floor"];
|
||||
int? parentIndex = (jtoken != null) ? new int?(jtoken.ToObject<int>()) : null;
|
||||
_canread = false;
|
||||
if (Utils.Utils.ADConvertToType(jobj["eventType"].ToObject<string>()) == typeof(ADCustomEvent))
|
||||
{
|
||||
existingValue = (TEvent)(object)new ADCustomTileEventConverter(level, settings).GetDeserializedObject(jobj, objectType, null, hasExistingValue, serializer);
|
||||
}
|
||||
else
|
||||
{
|
||||
jobj.Remove("floor");
|
||||
existingValue = base.GetDeserializedObject(jobj, objectType, existingValue, hasExistingValue, serializer);
|
||||
}
|
||||
_canread = true;
|
||||
if (parentIndex != null)
|
||||
{
|
||||
existingValue.Parent = level[parentIndex.Value];
|
||||
existingValue.Parent.Add((ADBaseTileEvent)(object)existingValue);
|
||||
}
|
||||
return existingValue;
|
||||
}
|
||||
public override JObject SetSerializedObject(TEvent value, JsonSerializer serializer)
|
||||
{
|
||||
JObject jobj = base.SetSerializedObject(value, serializer);
|
||||
JToken s = jobj.First;
|
||||
s.AddBeforeSelf(new JProperty("floor", level.tileOrder.IndexOf(value.Parent)));
|
||||
return jobj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Adofai.Converters
|
||||
{
|
||||
internal class ADCustomEventConverter(ADLevel level, LevelReadOrWriteSettings settings) : ADBaseEventConverter<ADCustomEvent>(level, settings)
|
||||
{
|
||||
public override ADCustomEvent GetDeserializedObject(JObject jobj, Type objectType, ADCustomEvent existingValue, bool hasExistingValue, JsonSerializer serializer) => new()
|
||||
{
|
||||
Data = jobj
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Adofai.Converters
|
||||
{
|
||||
internal class ADCustomTileEventConverter(ADLevel level, LevelReadOrWriteSettings settings) : ADBaseTileEventConverter<ADCustomTileEvent>(level, settings)
|
||||
{
|
||||
public override ADCustomTileEvent GetDeserializedObject(JObject jobj, Type objectType, ADCustomTileEvent existingValue, bool hasExistingValue, JsonSerializer serializer) => new()
|
||||
{
|
||||
Parent = level[jobj["floor"].ToObject<int>()],
|
||||
Data = jobj
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Adofai.Utils;
|
||||
using RhythmBase.Extensions;
|
||||
using RhythmBase.Converters;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Adofai.Converters
|
||||
{
|
||||
internal class ADLevelConverter(string location, LevelReadOrWriteSettings settings) : JsonConverter<ADLevel>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, ADLevel? value, JsonSerializer serializer)
|
||||
{
|
||||
JsonSerializerSettings AllInOneSerializer = new()
|
||||
{
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||
Formatting = Formatting.None
|
||||
};
|
||||
IList<JsonConverter> converters = AllInOneSerializer.Converters;
|
||||
converters.Add(new StringEnumConverter());
|
||||
converters.Add(new ColorConverter());
|
||||
writer.Formatting = settings.Indented ? Formatting.Indented : Formatting.None;
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName("angleData");
|
||||
writer.WriteStartArray();
|
||||
foreach (ADTile item in value!)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item.Angle, Formatting.None));
|
||||
writer.WriteEndArray();
|
||||
writer.WritePropertyName("settings");
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(value.Settings, Formatting.Indented, AllInOneSerializer));
|
||||
writer.WritePropertyName("actions");
|
||||
writer.WriteStartArray();
|
||||
foreach (ADTile item2 in value)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item2, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WritePropertyName("decorations");
|
||||
writer.WriteStartArray();
|
||||
foreach (ADBaseEvent item3 in value.Decorations)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item3, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WriteEndObject();
|
||||
writer.Close();
|
||||
}
|
||||
public override ADLevel ReadJson(JsonReader reader, Type objectType, ADLevel? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
ADLevel outLevel = new()
|
||||
{
|
||||
_path = fileLocation
|
||||
};
|
||||
JsonSerializer AllInOneSerializer = outLevel.GetSerializer(settings);
|
||||
JArray JActions = [];
|
||||
JArray JDecorations = [];
|
||||
while (reader.Read())
|
||||
{
|
||||
string name = (string)reader.Value!;
|
||||
reader.Read();
|
||||
object left = name;
|
||||
switch (name)
|
||||
{
|
||||
case "settings":
|
||||
JObject jobj = JObject.Load(reader);
|
||||
outLevel.Settings = jobj.ToObject<ADSettings>(AllInOneSerializer)!;
|
||||
break;
|
||||
case "angleData":
|
||||
JArray jobj2 = JArray.Load(reader);
|
||||
//outLevel.AddRange(jobj2.ToObject<List<ADTile>>(AllInOneSerializer)!);
|
||||
break;
|
||||
case "actions":
|
||||
JActions = JArray.Load(reader);
|
||||
break;
|
||||
case "decorations":
|
||||
JDecorations = JArray.Load(reader);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reader.Close();
|
||||
JActions.ToObject<List<ADBaseTileEvent>>(AllInOneSerializer);
|
||||
outLevel.Decorations.AddRange(JDecorations.ToObject<List<ADBaseEvent>>(AllInOneSerializer)!);
|
||||
return outLevel;
|
||||
}
|
||||
private readonly string fileLocation = location;
|
||||
private readonly LevelReadOrWriteSettings settings = settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Events;
|
||||
namespace RhythmBase.Adofai.Converters
|
||||
{
|
||||
internal class ADTileConverter(ADLevel level) : JsonConverter<ADTile>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, ADTile value, JsonSerializer serializer) => throw new NotImplementedException();
|
||||
|
||||
public override ADTile ReadJson(JsonReader reader, Type objectType, ADTile existingValue, bool hasExistingValue, JsonSerializer serializer) => new()
|
||||
{
|
||||
Angle = JToken.Load(reader).ToObject<float>(),
|
||||
Parent = level
|
||||
};
|
||||
|
||||
private readonly ADLevel level = level;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADAddDecoration : ADBaseTileEvent
|
||||
{
|
||||
public ADAddDecoration()
|
||||
{
|
||||
Type = ADEventType.AddDecoration;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string DecorationImage { get; set; }
|
||||
|
||||
public RDPointN Position { get; set; }
|
||||
|
||||
public ADDecorationRelativeTo RelativeTo { get; set; }
|
||||
|
||||
public RDSizeN PivotOffset { get; set; }
|
||||
|
||||
public float Rotation { get; set; }
|
||||
|
||||
public bool LockRotation { get; set; }
|
||||
|
||||
public RDSizeN Scale { get; set; }
|
||||
|
||||
public bool LockScale { get; set; }
|
||||
|
||||
public RDSizeN Tile { get; set; }
|
||||
|
||||
public RDColor Color { get; set; }
|
||||
|
||||
public float Opacity { get; set; }
|
||||
|
||||
public int Depth { get; set; }
|
||||
|
||||
public RDSizeN Parallax { get; set; }
|
||||
|
||||
public RDSizeN ParallaxOffset { get; set; }
|
||||
|
||||
public string Tag { get; set; }
|
||||
|
||||
public bool ImageSmoothing { get; set; }
|
||||
|
||||
public BlendModes BlendMode { get; set; }
|
||||
|
||||
public MaskingTypes MaskingType { get; set; }
|
||||
|
||||
public bool UseMaskingDepth { get; set; }
|
||||
|
||||
public int MaskingFrontDepth { get; set; }
|
||||
|
||||
public int MaskingBackDepth { get; set; }
|
||||
|
||||
public HitboxTypes Hitbox { get; set; }
|
||||
|
||||
public string HitboxEventTag { get; set; }
|
||||
|
||||
public FailHitboxTypes FailHitboxType { get; set; }
|
||||
|
||||
public RDSizeN FailHitboxScale { get; set; }
|
||||
|
||||
public RDSizeN FailHitboxOffset { get; set; }
|
||||
|
||||
public int FailHitboxRotation { get; set; }
|
||||
|
||||
public string Components { get; set; }
|
||||
|
||||
public enum BlendModes
|
||||
{
|
||||
None,
|
||||
Darken,
|
||||
Multiply,
|
||||
ColorBurn,
|
||||
LinearBurn,
|
||||
DarkerColor,
|
||||
Lighten,
|
||||
Screen,
|
||||
ColorDodge,
|
||||
LinearDodge,
|
||||
LighterColor,
|
||||
Overlay,
|
||||
SoftLight,
|
||||
HardLight,
|
||||
VividLight,
|
||||
LinearLight,
|
||||
PinLight,
|
||||
HardMix,
|
||||
Difference,
|
||||
Exclusion,
|
||||
Subtract,
|
||||
Divide,
|
||||
Hue,
|
||||
Saturation,
|
||||
Color,
|
||||
Luminosity
|
||||
}
|
||||
|
||||
public enum MaskingTypes
|
||||
{
|
||||
None,
|
||||
Mask,
|
||||
VisibleInsideMask,
|
||||
VisibleOutsideMask
|
||||
}
|
||||
|
||||
public enum HitboxTypes
|
||||
{
|
||||
None,
|
||||
Kill,
|
||||
Event
|
||||
}
|
||||
|
||||
public enum FailHitboxTypes
|
||||
{
|
||||
Box,
|
||||
Circle,
|
||||
Capsule
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADAddObject : ADBaseEvent
|
||||
{
|
||||
public ADAddObject()
|
||||
{
|
||||
Type = ADEventType.AddObject;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public ObjectTypes ObjectType { get; set; }
|
||||
|
||||
public PlanetColorTypes PlanetColorType { get; set; }
|
||||
|
||||
public RDColor PlanetColor { get; set; }
|
||||
|
||||
public RDColor PlanetTailColor { get; set; }
|
||||
|
||||
public TrackTypes TrackType { get; set; }
|
||||
|
||||
public float TrackAngle { get; set; }
|
||||
|
||||
public ADTrackColorTypes TrackColorType { get; set; }
|
||||
|
||||
public RDColor TrackColor { get; set; }
|
||||
|
||||
public RDColor SecondaryTrackColor { get; set; }
|
||||
|
||||
public float TrackColorAnimDuration { get; set; }
|
||||
|
||||
public float TrackOpacity { get; set; }
|
||||
|
||||
public ADTrackStyles TrackStyle { get; set; }
|
||||
|
||||
public string TrackIcon { get; set; }
|
||||
|
||||
public float TrackIconAngle { get; set; }
|
||||
|
||||
public bool TrackRedSwirl { get; set; }
|
||||
|
||||
public bool TrackGraySetSpeedIcon { get; set; }
|
||||
|
||||
public float TrackSetSpeedIconBpm { get; set; }
|
||||
|
||||
public bool TrackGlowEnabled { get; set; }
|
||||
|
||||
public RDColor TrackGlowColor { get; set; }
|
||||
|
||||
public RDPointN Position { get; set; }
|
||||
|
||||
public ADCameraRelativeTo RelativeTo { get; set; }
|
||||
|
||||
public RDSizeN PivotOffset { get; set; }
|
||||
|
||||
public float Rotation { get; set; }
|
||||
|
||||
public bool LockRotation { get; set; }
|
||||
|
||||
public RDSizeN Scale { get; set; }
|
||||
|
||||
public bool LockScale { get; set; }
|
||||
|
||||
public int Depth { get; set; }
|
||||
|
||||
public RDSizeN Parallax { get; set; }
|
||||
|
||||
public RDSizeN ParallaxOffset { get; set; }
|
||||
|
||||
public string Tag { get; set; }
|
||||
|
||||
public enum ObjectTypes
|
||||
{
|
||||
Floor,
|
||||
Planet
|
||||
}
|
||||
|
||||
public enum PlanetColorTypes
|
||||
{
|
||||
DefaultRed,
|
||||
planetColorType,
|
||||
Gold,
|
||||
Overseer,
|
||||
Custom
|
||||
}
|
||||
|
||||
public enum TrackTypes
|
||||
{
|
||||
Normal,
|
||||
Midspin
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADAddText : ADBaseEvent
|
||||
{
|
||||
public ADAddText()
|
||||
{
|
||||
Type = ADEventType.AddText;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string DecText { get; set; }
|
||||
|
||||
public string Font { get; set; }
|
||||
|
||||
public RDPointN Position { get; set; }
|
||||
|
||||
public ADCameraRelativeTo RelativeTo { get; set; }
|
||||
|
||||
public RDSizeN PivotOffset { get; set; }
|
||||
|
||||
public float Rotation { get; set; }
|
||||
|
||||
public bool LockRotation { get; set; }
|
||||
|
||||
public RDSizeN Scale { get; set; }
|
||||
|
||||
public bool LockScale { get; set; }
|
||||
|
||||
public RDColor Color { get; set; }
|
||||
|
||||
public float Opacity { get; set; }
|
||||
|
||||
public int Depth { get; set; }
|
||||
|
||||
public RDSizeN Parallax { get; set; }
|
||||
|
||||
public RDSizeN ParallaxOffset { get; set; }
|
||||
|
||||
public string Tag { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
|
||||
public class ADAnimateTrack : ADBaseTileEvent
|
||||
{
|
||||
public ADAnimateTrack()
|
||||
{
|
||||
Type = ADEventType.AnimateTrack;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public TrackAnimations? TrackAnimation { get; set; }
|
||||
|
||||
public TrackDisappearAnimations? TrackDisappearAnimation { get; set; }
|
||||
|
||||
public int BeatsAhead { get; set; }
|
||||
|
||||
public int BeatsBehind { get; set; }
|
||||
|
||||
public enum TrackAnimations
|
||||
{
|
||||
None,
|
||||
Assemble,
|
||||
Assemble_Far,
|
||||
Extend,
|
||||
Grow,
|
||||
Grow_Spin,
|
||||
Fade,
|
||||
Drop,
|
||||
Rise
|
||||
}
|
||||
|
||||
public enum TrackDisappearAnimations
|
||||
{
|
||||
None,
|
||||
Scatter,
|
||||
Scatter_Far,
|
||||
Retract,
|
||||
Shrink,
|
||||
Shrink_Spin,
|
||||
Fade
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADAutoPlayTiles : ADBaseTileEvent
|
||||
{
|
||||
public ADAutoPlayTiles()
|
||||
{
|
||||
Type = ADEventType.AutoPlayTiles;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public bool ShowStatusText { get; set; }
|
||||
|
||||
public bool SafetyTiles { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public abstract class ADBaseEvent
|
||||
{
|
||||
public abstract ADEventType Type { get; }
|
||||
|
||||
public override string ToString() => Type.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public abstract class ADBaseTaggedTileAction : ADBaseTileEvent
|
||||
{
|
||||
public float AngleOffset { get; set; }
|
||||
|
||||
public string EventTag { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public abstract class ADBaseTileEvent : ADBaseEvent
|
||||
{
|
||||
[JsonIgnore]
|
||||
public ADTile Parent { get; set; }
|
||||
|
||||
public override string ToString() => string.Format("{0}", Type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADBloom : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADBloom()
|
||||
{
|
||||
Type = ADEventType.Bloom;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public int Threshold { get; set; }
|
||||
|
||||
public int Intensity { get; set; }
|
||||
|
||||
public RDColor Color { get; set; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADBookmark : ADBaseTileEvent
|
||||
{
|
||||
public ADBookmark()
|
||||
{
|
||||
Type = ADEventType.Bookmark;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADCameraRelativeTo
|
||||
{
|
||||
Player,
|
||||
Tile,
|
||||
Global,
|
||||
LastPosition,
|
||||
LastPositionNoRotation
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADCheckpoint : ADBaseTileEvent
|
||||
{
|
||||
public ADCheckpoint()
|
||||
{
|
||||
Type = ADEventType.Checkpoint;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public int TileOffset { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using RhythmBase.Components;
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADColorTrack : ADBaseTileEvent
|
||||
{
|
||||
public ADColorTrack()
|
||||
{
|
||||
Type = ADEventType.ColorTrack;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public ADTrackColorTypes TrackColorType { get; set; }
|
||||
|
||||
public RDColor TrackColor { get; set; }
|
||||
|
||||
public RDColor SecondaryTrackColor { get; set; }
|
||||
|
||||
public float TrackColorAnimDuration { get; set; }
|
||||
|
||||
public ADTrackColorPulses TrackColorPulse { get; set; }
|
||||
|
||||
public float TrackPulseLength { get; set; }
|
||||
|
||||
public ADTrackStyles TrackStyle { get; set; }
|
||||
|
||||
public string TrackTexture { get; set; }
|
||||
|
||||
public float TrackTextureScale { get; set; }
|
||||
|
||||
public float TrackGlowIntensity { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADCustomBackground : ADBaseTaggedTileAction
|
||||
{
|
||||
public ADCustomBackground()
|
||||
{
|
||||
Type = ADEventType.CustomBackground;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public RDColor Color { get; set; }
|
||||
|
||||
public string BgImage { get; set; }
|
||||
|
||||
public RDColor ImageColor { get; set; }
|
||||
|
||||
public RDPoint Parallax { get; set; }
|
||||
|
||||
public BgDisplayModes BgDisplayMode { get; set; }
|
||||
|
||||
public bool ImageSmoothing { get; set; }
|
||||
|
||||
public bool LockRot { get; set; }
|
||||
|
||||
public bool LoopBG { get; set; }
|
||||
|
||||
public float ScalingRatio { get; set; }
|
||||
|
||||
public enum BgDisplayModes
|
||||
{
|
||||
FitToScreen,
|
||||
Unscaled,
|
||||
Tiled
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADCustomEvent : ADBaseEvent
|
||||
{
|
||||
public ADCustomEvent()
|
||||
{
|
||||
Type = ADEventType.CustomEvent;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string ActureType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Data["eventType"].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public JObject Data { get; set; }
|
||||
|
||||
public override string ToString() => ActureType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADCustomTileEvent : ADBaseTileEvent
|
||||
{
|
||||
public ADCustomTileEvent()
|
||||
{
|
||||
Type = ADEventType.CustomTileEvent;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string ActureType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Data["eventType"].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public JObject Data { get; set; }
|
||||
|
||||
public override string ToString() => string.Format("{0}({1}): {2}", Parent.Index, Parent.Angle, ActureType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADDecorationRelativeTo
|
||||
{
|
||||
Tile,
|
||||
Global,
|
||||
RedPlanet,
|
||||
BluePlanet,
|
||||
GreenPlanet,
|
||||
Camera,
|
||||
CameraAspect,
|
||||
LastPosition
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADEasePartBehaviors
|
||||
{
|
||||
Repeat,
|
||||
Mirror
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADEditorComment : ADBaseTileEvent
|
||||
{
|
||||
public ADEditorComment()
|
||||
{
|
||||
Type = ADEventType.EditorComment;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADEventType
|
||||
{
|
||||
AddDecoration,
|
||||
AddObject,
|
||||
AddText,
|
||||
AnimateTrack,
|
||||
AutoPlayTiles,
|
||||
Bloom,
|
||||
Bookmark,
|
||||
Checkpoint,
|
||||
ColorTrack,
|
||||
CustomBackground,
|
||||
CustomEvent,
|
||||
CustomTileEvent,
|
||||
EditorComment,
|
||||
Flash,
|
||||
FreeRoam,
|
||||
FreeRoamRemove,
|
||||
FreeRoamTwirl,
|
||||
HallOfMirrors,
|
||||
Hide,
|
||||
Hold,
|
||||
MoveCamera,
|
||||
MoveDecorations,
|
||||
MoveTrack,
|
||||
MultiPlanet,
|
||||
Pause,
|
||||
PlaySound,
|
||||
PositionTrack,
|
||||
RecolorTrack,
|
||||
RepeatEvents,
|
||||
ScaleMargin,
|
||||
ScalePlanets,
|
||||
ScaleRadius,
|
||||
ScreenScroll,
|
||||
ScreenTile,
|
||||
SetConditionalEvents,
|
||||
SetDefaultText,
|
||||
SetFilter,
|
||||
SetHitsound,
|
||||
SetHoldSound,
|
||||
SetObject,
|
||||
SetPlanetRotation,
|
||||
SetSpeed,
|
||||
SetText,
|
||||
ShakeScreen,
|
||||
Twirl
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADFlash : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADFlash()
|
||||
{
|
||||
Type = ADEventType.Flash;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public string Plane { get; set; }
|
||||
|
||||
public RDColor StartColor { get; set; }
|
||||
|
||||
public float StartOpacity { get; set; }
|
||||
|
||||
public RDColor EndColor { get; set; }
|
||||
|
||||
public float EndOpacity { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADFreeRoam : ADBaseTileEvent, IEaseEvent
|
||||
{
|
||||
public ADFreeRoam()
|
||||
{
|
||||
Type = ADEventType.FreeRoam;
|
||||
}
|
||||
public override ADEventType Type { get; }
|
||||
public float Duration { get; set; }
|
||||
public int Size { get; set; }
|
||||
public int PositionOffset { get; set; }
|
||||
public int OutTime { get; set; }
|
||||
[JsonProperty("OutEase")]
|
||||
public EaseType Ease { get; set; }
|
||||
public string HitsoundOnBeats { get; set; }
|
||||
public string HitsoundOffBeats { get; set; }
|
||||
public int CountdownTicks { get; set; }
|
||||
public int AngleCorrectionDir { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADFreeRoamRemove : ADBaseTileEvent
|
||||
{
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public int Position { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADFreeRoamTwirl : ADBaseTileEvent
|
||||
{
|
||||
public ADFreeRoamTwirl()
|
||||
{
|
||||
Type = ADEventType.FreeRoamTwirl;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public int Position { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADHallOfMirrors : ADBaseTaggedTileAction
|
||||
{
|
||||
public ADHallOfMirrors()
|
||||
{
|
||||
Type = ADEventType.HallOfMirrors;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADHide : ADBaseTileEvent
|
||||
{
|
||||
public ADHide()
|
||||
{
|
||||
Type = ADEventType.Hide;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public bool HideJudgment { get; set; }
|
||||
|
||||
public bool HideTileIcon { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADHold : ADBaseTileEvent
|
||||
{
|
||||
public ADHold()
|
||||
{
|
||||
Type = ADEventType.Hold;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public int Duration { get; set; }
|
||||
|
||||
public int DistanceMultiplier { get; set; }
|
||||
|
||||
public bool LandingAnimation { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
|
||||
public class ADMoveCamera : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADMoveCamera()
|
||||
{
|
||||
Type = ADEventType.MoveCamera;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
|
||||
public bool DontDisable { get; set; }
|
||||
|
||||
public bool MinVfxOnly { get; set; }
|
||||
|
||||
public ADCameraRelativeTo RelativeTo { get; set; }
|
||||
|
||||
public RDPoint? Position { get; set; }
|
||||
|
||||
public float Rotation { get; set; }
|
||||
|
||||
public float Zoom { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
|
||||
public class ADMoveDecorations : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADMoveDecorations()
|
||||
{
|
||||
Type = ADEventType.MoveDecorations;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public string Tag { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
|
||||
public RDPoint? PositionOffset { get; set; }
|
||||
|
||||
public RDPoint? ParallaxOffset { get; set; }
|
||||
|
||||
public bool? Visible { get; set; }
|
||||
|
||||
public ADDecorationRelativeTo? RelativeTo { get; set; }
|
||||
|
||||
public string DecorationImage { get; set; }
|
||||
|
||||
public RDSize? PivotOffset { get; set; }
|
||||
|
||||
public float? RotationOffset { get; set; }
|
||||
|
||||
public RDSize? Scale { get; set; }
|
||||
|
||||
public RDColor? Color { get; set; }
|
||||
|
||||
public float? Opacity { get; set; }
|
||||
|
||||
public int? Depth { get; set; }
|
||||
|
||||
public RDPoint? Parallax { get; set; }
|
||||
|
||||
public MaskingTypes? MaskingType { get; set; }
|
||||
|
||||
public bool? UseMaskingDepth { get; set; }
|
||||
|
||||
public int? MaskingFrontDepth { get; set; }
|
||||
|
||||
public int? MaskingBackDepth { get; set; }
|
||||
|
||||
public enum MaskingTypes
|
||||
{
|
||||
None,
|
||||
Mask,
|
||||
VisibleInsideMask,
|
||||
VisibleOutsideMask
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADMoveTrack : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADMoveTrack()
|
||||
{
|
||||
Type = ADEventType.MoveTrack;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public object StartTile
|
||||
{
|
||||
[CompilerGenerated]
|
||||
get
|
||||
{
|
||||
return StartTile;
|
||||
}
|
||||
[CompilerGenerated]
|
||||
set
|
||||
{
|
||||
StartTile = RuntimeHelpers.GetObjectValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public object EndTile
|
||||
{
|
||||
[CompilerGenerated]
|
||||
get
|
||||
{
|
||||
return EndTile;
|
||||
}
|
||||
[CompilerGenerated]
|
||||
set
|
||||
{
|
||||
EndTile = RuntimeHelpers.GetObjectValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public int GapLength { get; set; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public RDPoint PositionOffset { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
|
||||
public bool MaxVfxOnly { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADMultiPlanet : ADBaseTileEvent
|
||||
{
|
||||
public ADMultiPlanet()
|
||||
{
|
||||
Type = ADEventType.MultiPlanet;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string Planets { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADPause : ADBaseTileEvent
|
||||
{
|
||||
public ADPause()
|
||||
{
|
||||
Type = ADEventType.Pause;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public int CountdownTicks { get; set; }
|
||||
|
||||
public int AngleCorrectionDir { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADPlaySound : ADBaseTaggedTileAction
|
||||
{
|
||||
public ADPlaySound()
|
||||
{
|
||||
Type = ADEventType.PlaySound;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string Hitsound { get; set; }
|
||||
|
||||
public int HitsoundVolume { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADPositionTrack : ADBaseTileEvent
|
||||
{
|
||||
public ADPositionTrack()
|
||||
{
|
||||
Type = ADEventType.PositionTrack;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public RDPoint PositionOffset { get; set; }
|
||||
|
||||
public object RelativeTo
|
||||
{
|
||||
[CompilerGenerated]
|
||||
get
|
||||
{
|
||||
return RelativeTo;
|
||||
}
|
||||
[CompilerGenerated]
|
||||
set
|
||||
{
|
||||
RelativeTo = RuntimeHelpers.GetObjectValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public float Rotation { get; set; }
|
||||
|
||||
public float Scale { get; set; }
|
||||
|
||||
public float Opacity { get; set; }
|
||||
|
||||
public bool JustThisTile { get; set; }
|
||||
|
||||
public bool SditorOnly { get; set; }
|
||||
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? StickToFloors { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADRecolorTrack : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADRecolorTrack()
|
||||
{
|
||||
Type = ADEventType.RecolorTrack;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public object StartTile
|
||||
{
|
||||
[CompilerGenerated]
|
||||
get
|
||||
{
|
||||
return StartTile;
|
||||
}
|
||||
[CompilerGenerated]
|
||||
set
|
||||
{
|
||||
StartTile = RuntimeHelpers.GetObjectValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public object EndTile
|
||||
{
|
||||
[CompilerGenerated]
|
||||
get
|
||||
{
|
||||
return EndTile;
|
||||
}
|
||||
[CompilerGenerated]
|
||||
set
|
||||
{
|
||||
EndTile = RuntimeHelpers.GetObjectValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public int GapLength { get; set; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public ADTrackColorTypes TrackColorType { get; set; }
|
||||
|
||||
public RDColor TrackColor { get; set; }
|
||||
|
||||
public RDColor SecondaryTrackColor { get; set; }
|
||||
|
||||
public float TrackColorAnimDuration { get; set; }
|
||||
|
||||
public ADTrackColorPulses TrackColorPulse { get; set; }
|
||||
|
||||
public float TrackPulseLength { get; set; }
|
||||
|
||||
public ADTrackStyles TrackStyle { get; set; }
|
||||
|
||||
public float TrackGlowIntensity { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADRepeatEvents : ADBaseTileEvent
|
||||
{
|
||||
public ADRepeatEvents()
|
||||
{
|
||||
Type = ADEventType.RepeatEvents;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public RepeatTypes RepeatType { get; set; }
|
||||
|
||||
public int Repetitions { get; set; }
|
||||
|
||||
public int FloorCount { get; set; }
|
||||
|
||||
public float Interval { get; set; }
|
||||
|
||||
public bool ExecuteOnCurrentFloor { get; set; }
|
||||
|
||||
public string Tag { get; set; }
|
||||
|
||||
public enum RepeatTypes
|
||||
{
|
||||
Beat,
|
||||
Floor
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADScaleMargin : ADBaseTileEvent
|
||||
{
|
||||
public ADScaleMargin()
|
||||
{
|
||||
Type = ADEventType.ScaleMargin;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public int Scale { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADScalePlanets : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADScalePlanets()
|
||||
{
|
||||
Type = ADEventType.ScalePlanets;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public TargetPlanets TargetPlanet { get; set; }
|
||||
|
||||
[EaseProperty]
|
||||
public int Scale { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
|
||||
public enum TargetPlanets
|
||||
{
|
||||
FirePlanet,
|
||||
IcePlanet,
|
||||
GreenPlanet,
|
||||
All
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADScaleRadius : ADBaseTileEvent
|
||||
{
|
||||
public ADScaleRadius()
|
||||
{
|
||||
Type = ADEventType.ScaleRadius;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public int Scale { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADScreenScroll : ADBaseTaggedTileAction
|
||||
{
|
||||
public ADScreenScroll()
|
||||
{
|
||||
Type = ADEventType.ScreenScroll;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public RDSizeN Scroll { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADScreenTile : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADScreenTile()
|
||||
{
|
||||
Type = ADEventType.ScreenTile;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public RDPoint Tile { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADSetConditionalEvents : ADBaseTileEvent
|
||||
{
|
||||
public ADSetConditionalEvents()
|
||||
{
|
||||
Type = ADEventType.SetConditionalEvents;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string PerfectTag { get; set; }
|
||||
|
||||
public string HitTag { get; set; }
|
||||
|
||||
public string EarlyPerfectTag { get; set; }
|
||||
|
||||
public string LatePerfectTag { get; set; }
|
||||
|
||||
public string BarelyTag { get; set; }
|
||||
|
||||
public string VeryEarlyTag { get; set; }
|
||||
|
||||
public string VeryLateTag { get; set; }
|
||||
|
||||
public string MissTag { get; set; }
|
||||
|
||||
public string TooEarlyTag { get; set; }
|
||||
|
||||
public string TooLateTag { get; set; }
|
||||
|
||||
public string LossTag { get; set; }
|
||||
|
||||
public string OnCheckpointTag { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
|
||||
public class ADSetDefaultText : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADSetDefaultText()
|
||||
{
|
||||
Type = ADEventType.SetDefaultText;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
|
||||
public RDColor? DefaultTextColor { get; set; }
|
||||
|
||||
public RDColor? DefaultTextShadowColor { get; set; }
|
||||
|
||||
public RDPoint? LevelTitlePosition { get; set; }
|
||||
|
||||
public string LevelTitleText { get; set; }
|
||||
|
||||
public string CongratsText { get; set; }
|
||||
|
||||
public string PerfectText { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADSetFilter : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADSetFilter()
|
||||
{
|
||||
Type = ADEventType.SetFilter;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public Filters Filter { get; set; }
|
||||
|
||||
public string Enabled { get; set; }
|
||||
|
||||
public int Intensity { get; set; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
|
||||
public string DisableOthers { get; set; }
|
||||
|
||||
public enum Filters
|
||||
{
|
||||
Grayscale,
|
||||
Sepia,
|
||||
Invert,
|
||||
VHS,
|
||||
EightiesTV,
|
||||
FiftiesTV,
|
||||
Arcade,
|
||||
LED,
|
||||
Rain,
|
||||
Blizzard,
|
||||
PixelSnow,
|
||||
Compression,
|
||||
Glitch,
|
||||
Pixelate,
|
||||
Waves,
|
||||
Static,
|
||||
Grain,
|
||||
MotionBlur,
|
||||
Fisheye,
|
||||
Aberration,
|
||||
Drawing,
|
||||
Neon,
|
||||
Handheld,
|
||||
NightVision,
|
||||
Funk,
|
||||
Tunnel,
|
||||
Weird3D,
|
||||
Blur,
|
||||
BlurFocus,
|
||||
GaussianBlur,
|
||||
HexagonBlack,
|
||||
Posterize,
|
||||
Sharpen,
|
||||
Contrast,
|
||||
EdgeBlackLine,
|
||||
OilPaint,
|
||||
SuperDot,
|
||||
WaterDrop,
|
||||
LightWater,
|
||||
Petals,
|
||||
PetalsInstant
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADSetHitsound : ADBaseTileEvent
|
||||
{
|
||||
public ADSetHitsound()
|
||||
{
|
||||
Type = ADEventType.SetHitsound;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string GameSound { get; set; }
|
||||
|
||||
public string Hitsound { get; set; }
|
||||
|
||||
public int HitsoundVolume { get; set; }
|
||||
|
||||
public enum GameSounds
|
||||
{
|
||||
Hitsound,
|
||||
Midspin
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADSetHoldSound : ADBaseTileEvent
|
||||
{
|
||||
public ADSetHoldSound()
|
||||
{
|
||||
Type = ADEventType.SetHoldSound;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string HoldStartSound { get; set; }
|
||||
|
||||
public string HoldLoopSound { get; set; }
|
||||
|
||||
public string HoldEndSound { get; set; }
|
||||
|
||||
public string HoldMidSound { get; set; }
|
||||
|
||||
public string HoldMidSoundType { get; set; }
|
||||
|
||||
public float HoldMidSoundDelay { get; set; }
|
||||
|
||||
public string HoldMidSoundTimingRelativeTo { get; set; }
|
||||
|
||||
public int HoldSoundVolume { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
|
||||
public class ADSetObject : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADSetObject()
|
||||
{
|
||||
Type = ADEventType.SetObject;
|
||||
}
|
||||
public override ADEventType Type { get; }
|
||||
public float Duration { get; set; }
|
||||
public string Tag { get; set; }
|
||||
public EaseType Ease { get; set; }
|
||||
public RDColor? PlanetColor { get; set; }
|
||||
public RDColor? PlanetTailColor { get; set; }
|
||||
public float? TrackAngle { get; set; }
|
||||
public ADTrackColorTypes? TrackColorType { get; set; }
|
||||
public RDColor? TrackColor { get; set; }
|
||||
public RDColor? SecondaryTrackColor { get; set; }
|
||||
public float? TrackColorAnimDuration { get; set; }
|
||||
public float? TrackOpacity { get; set; }
|
||||
public ADTrackStyles? TrackStyle { get; set; }
|
||||
public string TrackIcon { get; set; }
|
||||
public float? TrackIconAngle { get; set; }
|
||||
public bool? TrackRedSwirl { get; set; }
|
||||
public bool? TrackGraySetSpeedIcon { get; set; }
|
||||
public bool? TrackGlowEnabled { get; set; }
|
||||
public RDColor? TrackGlowColor { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADSetPlanetRotation : ADBaseTileEvent
|
||||
{
|
||||
public ADSetPlanetRotation()
|
||||
{
|
||||
Type = ADEventType.SetPlanetRotation;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string Ease { get; set; }
|
||||
|
||||
public int EaseParts { get; set; }
|
||||
|
||||
public ADEasePartBehaviors EasePartBehavior { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADSetSpeed : ADBaseTaggedTileAction
|
||||
{
|
||||
public ADSetSpeed()
|
||||
{
|
||||
Type = ADEventType.SetSpeed;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public SpeedTypes SpeedType { get; set; }
|
||||
|
||||
public float BeatsPerMinute { get; set; }
|
||||
|
||||
public float BpmMultiplier { get; set; }
|
||||
|
||||
public enum SpeedTypes
|
||||
{
|
||||
Bpm,
|
||||
Multiplier
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADSetText : ADBaseTaggedTileAction
|
||||
{
|
||||
public ADSetText()
|
||||
{
|
||||
Type = ADEventType.SetText;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public string DecText { get; set; }
|
||||
|
||||
public string Tag { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Components.Easing;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADShakeScreen : ADBaseTaggedTileAction, IEaseEvent
|
||||
{
|
||||
public ADShakeScreen()
|
||||
{
|
||||
Type = ADEventType.ShakeScreen;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
|
||||
public float Duration { get; set; }
|
||||
|
||||
public float Strength { get; set; }
|
||||
|
||||
public float Intensity { get; set; }
|
||||
|
||||
public EaseType Ease { get; set; }
|
||||
|
||||
public float FadeOut { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Adofai.Components;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADTile : ADTypedList<ADBaseTileEvent>
|
||||
{
|
||||
public float Angle
|
||||
{
|
||||
get => _angle;
|
||||
set => _angle = value is > (-360f) and < 360f ? ((value + 540f) % 360f) - 180f : -999f;
|
||||
}
|
||||
public bool IsMidSpin => _angle < -180f || _angle > 180f;
|
||||
public ADBeat Beat => new(Parent?.Calculator!, Index + (_angle / 180f));
|
||||
[JsonIgnore]
|
||||
public ADLevel? Parent { get; set; }
|
||||
public ADTile() { }
|
||||
public ADTile(IEnumerable<ADBaseTileEvent> actions)
|
||||
{
|
||||
foreach (ADBaseTileEvent i in actions)
|
||||
{
|
||||
i.Parent = this;
|
||||
Add(i);
|
||||
}
|
||||
}
|
||||
public int Index => Parent?.IndexOf(this) ?? -1;
|
||||
public override string ToString() => string.Format("[{0}]{1}<{2}>{3}",
|
||||
[
|
||||
Index,
|
||||
Beat,
|
||||
IsMidSpin ? "MS".PadRight(4) : _angle.ToString().PadLeft(4),
|
||||
((IEnumerable<ADBaseTileEvent>)this).Any<ADBaseTileEvent>() ? string.Format(", Count = {0}", ((IEnumerable<ADBaseTileEvent>)this).Count<ADBaseTileEvent>()) : string.Empty
|
||||
]);
|
||||
private float _angle = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADTileRelativeTo
|
||||
{
|
||||
ThisTile,
|
||||
Start,
|
||||
End
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADTrackColorPulses
|
||||
{
|
||||
None,
|
||||
Forward,
|
||||
Backward
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADTrackColorTypes
|
||||
{
|
||||
Single,
|
||||
Stripes,
|
||||
Glow,
|
||||
Blink,
|
||||
Switch,
|
||||
Rainbow,
|
||||
Volume
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public enum ADTrackStyles
|
||||
{
|
||||
Standard,
|
||||
Neon,
|
||||
NeonLight,
|
||||
Basic,
|
||||
Gems,
|
||||
Minimal
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
namespace RhythmBase.Adofai.Events
|
||||
{
|
||||
public class ADTwirl : ADBaseTileEvent
|
||||
{
|
||||
public ADTwirl()
|
||||
{
|
||||
Type = ADEventType.Twirl;
|
||||
}
|
||||
|
||||
public override ADEventType Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Extensions;
|
||||
namespace RhythmBase.Adofai.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Beat Calculator.
|
||||
/// </summary>
|
||||
public class ADBeatCalculator
|
||||
{
|
||||
internal ADBeatCalculator(ADLevel level)
|
||||
{
|
||||
Collection = level;
|
||||
Refresh();
|
||||
}
|
||||
private void Refresh()
|
||||
{
|
||||
_DefaultBpm = Collection.Settings.Bpm;
|
||||
_MidSpins = Collection.Where((i) => i.IsMidSpin).ToList();
|
||||
////this._SetSpeeds = this.Collection.EventsWhere<ADSetSpeed>().ToList<ADSetSpeed>();
|
||||
////this._Twirls = this.Collection.EventsWhere<ADTwirl>().ToList<ADTwirl>();
|
||||
////this._Pauses = this.Collection.EventsWhere<ADPause>().ToList<ADPause>();
|
||||
////this._Holds = this.Collection.EventsWhere<ADHold>().ToList<ADHold>();
|
||||
////this._Freeroams = this.Collection.EventsWhere<ADFreeRoam>().ToList<ADFreeRoam>();
|
||||
}
|
||||
#pragma warning disable IDE0052 // 删除未读的私有成员
|
||||
internal ADLevel Collection;
|
||||
private float _DefaultBpm = 100;
|
||||
private List<ADTile> _MidSpins = [];
|
||||
private readonly List<ADSetSpeed> _SetSpeeds = [];
|
||||
private readonly List<ADTwirl> _Twirls = [];
|
||||
private readonly List<ADPause> _Pauses = [];
|
||||
private readonly List<ADHold> _Holds = [];
|
||||
private readonly List<ADFreeRoam> _Freeroams = [];
|
||||
#pragma warning restore IDE0052 // 删除未读的私有成员
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using RhythmBase.Adofai.Components;
|
||||
using RhythmBase.Adofai.Converters;
|
||||
using RhythmBase.Adofai.Events;
|
||||
using RhythmBase.Converters;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Exceptions;
|
||||
using RhythmBase.Settings;
|
||||
using System.Collections.ObjectModel;
|
||||
namespace RhythmBase.Adofai.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Useful utils.
|
||||
/// </summary>
|
||||
[StandardModule]
|
||||
public static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a given type to an ADEventType enumeration.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to convert.</param>
|
||||
/// <returns>The corresponding ADEventType enumeration.</returns>
|
||||
/// <exception cref="IllegalEventTypeException">Thrown when no matching EventType is found or multiple matching EventTypes are found.</exception>
|
||||
public static ADEventType ADConvertToEnum(Type type)
|
||||
{
|
||||
if (ADETypesToEnum == null)
|
||||
{
|
||||
if (type.Name.StartsWith("AD"))
|
||||
{
|
||||
string name = type.Name[2..];
|
||||
if (Enum.TryParse(name, out ADEventType result))
|
||||
return result;
|
||||
}
|
||||
throw new IllegalEventTypeException(type, "Unable to find a matching EventType.");
|
||||
}
|
||||
ADEventType ADConvertToEnum;
|
||||
try
|
||||
{
|
||||
ADConvertToEnum = ADETypesToEnum![type].Single();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new IllegalEventTypeException(type, "Multiple matching EventTypes were found. Please check if the type is an abstract class type.", new ArgumentException("Multiple matching EventTypes were found. Please check if the type is an abstract class type.", nameof(type)));
|
||||
}
|
||||
return ADConvertToEnum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a generic type to an ADEventType enumeration.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to convert, which must inherit from ADBaseEvent and have a parameterless constructor.</typeparam>
|
||||
/// <returns>The corresponding ADEventType enumeration.</returns>
|
||||
public static ADEventType ConvertToADEnum<T>() where T : ADBaseEvent, new() => ADConvertToEnum(typeof(T));
|
||||
|
||||
/// <summary>
|
||||
/// Converts a generic type to an array of ADEventType enumerations.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to convert, which must inherit from BaseEvent.</typeparam>
|
||||
/// <returns>An array of corresponding ADEventType enumerations.</returns>
|
||||
/// <exception cref="IllegalEventTypeException">Thrown when no matching EventType is found.</exception>
|
||||
public static ADEventType[] ConvertToADEnums<T>() where T : BaseEvent
|
||||
{
|
||||
ADEventType[] ConvertToADEnums;
|
||||
try
|
||||
{
|
||||
ConvertToADEnums = ADETypesToEnum[typeof(T)];
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new IllegalEventTypeException(typeof(T), "This exception is not expected. Please contact the developer to handle this exception.");
|
||||
}
|
||||
return ConvertToADEnums;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string representation of an ADEventType to a Type.
|
||||
/// </summary>
|
||||
/// <param name="type">The string representation of the ADEventType.</param>
|
||||
/// <returns>The corresponding Type.</returns>
|
||||
public static Type ADConvertToType(string type)
|
||||
{
|
||||
bool flag = Enum.TryParse(type, out ADEventType result);
|
||||
Type ADConvertToType;
|
||||
if (flag)
|
||||
ADConvertToType = ConvertToType(result);
|
||||
else
|
||||
ADConvertToType = ConvertToType(ADEventType.CustomEvent);
|
||||
return ADConvertToType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an ADEventType enumeration to a Type.
|
||||
/// </summary>
|
||||
/// <param name="type">The ADEventType enumeration to convert.</param>
|
||||
/// <returns>The corresponding Type.</returns>
|
||||
/// <exception cref="RhythmBaseException">Thrown when the type is illegal.</exception>
|
||||
/// <exception cref="IllegalEventTypeException">Thrown when the value does not exist in the EventType enumeration.</exception>
|
||||
public static Type ConvertToType(this ADEventType type)
|
||||
{
|
||||
Type ConvertToType;
|
||||
if (ADEnumToEType == null)
|
||||
ConvertToType = Type.GetType(string.Format("{0}.AD{1}", typeof(ADBaseEvent).Namespace, type))
|
||||
?? throw new RhythmBaseException(string.Format("Illegal Type: {0}.", type));
|
||||
else
|
||||
try
|
||||
{
|
||||
ConvertToType = ADEnumToEType[type];
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new IllegalEventTypeException(Conversions.ToString((int)type), "This value does not exist in the EventType enumeration.");
|
||||
}
|
||||
return ConvertToType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a JsonSerializer configured with the necessary converters for the given ADLevel and settings.
|
||||
/// </summary>
|
||||
/// <param name="adlevel">The ADLevel instance.</param>
|
||||
/// <param name="settings">The LevelReadOrWriteSettings instance.</param>
|
||||
/// <returns>A configured JsonSerializer instance.</returns>
|
||||
public static JsonSerializer GetSerializer(this ADLevel adlevel, LevelReadOrWriteSettings settings)
|
||||
{
|
||||
JsonSerializer AllInOneSerializer = new();
|
||||
JsonConverterCollection converters = AllInOneSerializer.Converters;
|
||||
converters.Add(new StringEnumConverter());
|
||||
converters.Add(new ColorConverter());
|
||||
converters.Add(new ADTileConverter(adlevel));
|
||||
converters.Add(new ADCustomTileEventConverter(adlevel, settings));
|
||||
converters.Add(new ADCustomEventConverter(adlevel, settings));
|
||||
converters.Add(new ADBaseTileEventConverter<ADBaseTileEvent>(adlevel, settings));
|
||||
converters.Add(new ADBaseEventConverter<ADBaseEvent>(adlevel, settings));
|
||||
return AllInOneSerializer;
|
||||
}
|
||||
|
||||
private static readonly ReadOnlyCollection<Type> ADETypes = (from i in typeof(ADBaseEvent).Assembly.GetTypes()
|
||||
where i.IsAssignableTo(typeof(ADBaseEvent))
|
||||
select i).ToList().AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// A dictionary that records the correspondence of ADEventType to event types inheriting from ADBaseEvent.
|
||||
/// </summary>
|
||||
public static readonly ReadOnlyDictionary<Type, ADEventType[]> ADETypesToEnum = ADETypes.ToDictionary((Type i) => i, (Type i) => (from j in ADETypes
|
||||
where (j == i || j.IsAssignableTo(i)) && !j.IsAbstract
|
||||
select j).Select((Type j) => ADConvertToEnum(j)).ToArray()).AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// A dictionary that records the correspondence of event types inheriting from ADBaseEvent to ADEventType.
|
||||
/// </summary>
|
||||
public static readonly ReadOnlyDictionary<ADEventType, Type> ADEnumToEType = Enum.GetValues<ADEventType>().ToDictionary((ADEventType i) => i, ConvertToType).AsReadOnly();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using Newtonsoft.Json;
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a base class for different types of conditions.
|
||||
/// </summary>
|
||||
public abstract class BaseConditional
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of this condition.
|
||||
/// </summary>
|
||||
public abstract ConditionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the condition tag. Its role has not been clarified.
|
||||
/// </summary>
|
||||
public string Tag { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the condition name.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the 1-based serial number of this condition in the parent collection.
|
||||
/// </summary>
|
||||
public int Id => checked(ParentCollection.IndexOf(this) + 1);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the condition.
|
||||
/// </summary>
|
||||
/// <returns>The name of the condition.</returns>
|
||||
public override string ToString() => Name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parent collection of conditions.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
internal List<BaseConditional> ParentCollection = [];
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the type of condition.
|
||||
/// </summary>
|
||||
public enum ConditionType
|
||||
{
|
||||
/// <summary>
|
||||
/// Condition based on the last hit.
|
||||
/// </summary>
|
||||
LastHit,
|
||||
|
||||
/// <summary>
|
||||
/// Custom condition.
|
||||
/// </summary>
|
||||
Custom,
|
||||
|
||||
/// <summary>
|
||||
/// Condition based on the number of times executed.
|
||||
/// </summary>
|
||||
TimesExecuted,
|
||||
|
||||
/// <summary>
|
||||
/// Condition based on the language.
|
||||
/// </summary>
|
||||
Language,
|
||||
|
||||
/// <summary>
|
||||
/// Condition based on the player mode.
|
||||
/// </summary>
|
||||
PlayerMode
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a bookmark in the rhythm base.
|
||||
/// </summary>
|
||||
public class Bookmark
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the beat where the bookmark is located.
|
||||
/// </summary>
|
||||
public RDBeat Beat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color of the bookmark.
|
||||
/// </summary>
|
||||
public BookmarkColors Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current bookmark.
|
||||
/// </summary>
|
||||
/// <returns>A string that represents the current bookmark.</returns>
|
||||
public override string ToString() => string.Format("{0}, {1}", Beat, Color);
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the colors available for bookmarks.
|
||||
/// </summary>
|
||||
public enum BookmarkColors
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the color blue.
|
||||
/// </summary>
|
||||
Blue,
|
||||
/// <summary>
|
||||
/// Represents the color red.
|
||||
/// </summary>
|
||||
Red,
|
||||
/// <summary>
|
||||
/// Represents the color yellow.
|
||||
/// </summary>
|
||||
Yellow,
|
||||
/// <summary>
|
||||
/// Represents the color green.
|
||||
/// </summary>
|
||||
Green
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the status of a classic beat.
|
||||
/// </summary>
|
||||
public struct ClassicBeatStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the status type of the beat.
|
||||
/// </summary>
|
||||
public StatusType Status;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the beat count.
|
||||
/// </summary>
|
||||
public ushort BeatCount;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the various status types for a classic beat.
|
||||
/// </summary>
|
||||
public enum StatusType
|
||||
{
|
||||
#pragma warning disable CS1591
|
||||
Unset = -1,
|
||||
None,
|
||||
Synco,
|
||||
Beat_Open,
|
||||
Beat_Flash,
|
||||
Beat_Double_Flash,
|
||||
Beat_Triple_Flash,
|
||||
Beat_Close,
|
||||
X_Open,
|
||||
X_Flash,
|
||||
X_Close,
|
||||
X_Synco_Open,
|
||||
X_Synco_Flash,
|
||||
X_Synco_Close,
|
||||
Up_Open,
|
||||
Up_Close,
|
||||
Down_Open,
|
||||
Down_Close,
|
||||
Swing_Left,
|
||||
Swing_Right,
|
||||
Swing_Bounce,
|
||||
Held_Start,
|
||||
Held_End
|
||||
#pragma warning restore CS1591
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using RhythmBase.Exceptions;
|
||||
using System.Text.RegularExpressions;
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// The conditions of the event.
|
||||
/// </summary>
|
||||
public class Condition
|
||||
{
|
||||
/// <summary>
|
||||
/// Condition list.
|
||||
/// </summary>
|
||||
public List<(bool Enabled, BaseConditional Conditional)> ConditionLists;
|
||||
|
||||
/// <summary>
|
||||
/// The time of effectiveness of the condition.
|
||||
/// </summary>
|
||||
public float Duration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Condition"/> class.
|
||||
/// </summary>
|
||||
public Condition()
|
||||
{
|
||||
ConditionLists = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a condition from a string.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to load the condition from.</param>
|
||||
/// <returns>A new instance of the <see cref="Condition"/> class.</returns>
|
||||
/// <exception cref="RhythmBaseException">Thrown when the condition is illegal.</exception>
|
||||
internal static Condition Load(string text)
|
||||
{
|
||||
Condition @out = new();
|
||||
MatchCollection Matches = Regex.Matches(text, "(~?\\d+)(?=[&d])");
|
||||
if (Matches.Count > 0)
|
||||
{
|
||||
@out.Duration = float.Parse(Regex.Match(text, "[\\d\\.]").Value);
|
||||
return @out;
|
||||
}
|
||||
throw new RhythmBaseException(string.Format("Illegal condition: {0}.", text));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts conditions to a string.
|
||||
/// </summary>
|
||||
/// <returns>A string in the format supported by RDLevel.</returns>
|
||||
public string Serialize() => $"{string.Join("&", ConditionLists.Select((i) => (i.Enabled ? "" : "~") + i.Conditional.Id.ToString()))}d{Duration}";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => Serialize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace RhythmBase.Components.Conditions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a custom condition with an expression.
|
||||
/// </summary>
|
||||
public class CustomCondition : BaseConditional
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CustomCondition"/> class.
|
||||
/// </summary>
|
||||
public CustomCondition()
|
||||
{
|
||||
Type = ConditionType.Custom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the expression for the custom condition.
|
||||
/// </summary>
|
||||
/// <value>The expression as a string.</value>
|
||||
public string Expression { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the condition.
|
||||
/// </summary>
|
||||
/// <value>The type of the condition, which is <see cref="BaseConditional.ConditionType.Custom"/>.</value>
|
||||
public override ConditionType Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Newtonsoft.Json;
|
||||
namespace RhythmBase.Components.Conditions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a condition based on the game language.
|
||||
/// </summary>
|
||||
public class LanguageCondition : BaseConditional
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LanguageCondition"/> class.
|
||||
/// </summary>
|
||||
public LanguageCondition()
|
||||
{
|
||||
Type = ConditionType.Language;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the game language.
|
||||
/// </summary>
|
||||
[JsonProperty(nameof(Language))]
|
||||
public Languages Language
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the condition.
|
||||
/// </summary>
|
||||
public override ConditionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the supported game languages.
|
||||
/// </summary>
|
||||
public enum Languages
|
||||
{
|
||||
/// <summary>
|
||||
/// English language.
|
||||
/// </summary>
|
||||
English,
|
||||
|
||||
/// <summary>
|
||||
/// Spanish language.
|
||||
/// </summary>
|
||||
Spanish,
|
||||
|
||||
/// <summary>
|
||||
/// Portuguese language.
|
||||
/// </summary>
|
||||
Portuguese,
|
||||
|
||||
/// <summary>
|
||||
/// Simplified Chinese language.
|
||||
/// </summary>
|
||||
ChineseSimplified,
|
||||
|
||||
/// <summary>
|
||||
/// Traditional Chinese language.
|
||||
/// </summary>
|
||||
ChineseTraditional,
|
||||
|
||||
/// <summary>
|
||||
/// Korean language.
|
||||
/// </summary>
|
||||
Korean,
|
||||
|
||||
/// <summary>
|
||||
/// Polish language.
|
||||
/// </summary>
|
||||
Polish,
|
||||
|
||||
/// <summary>
|
||||
/// Japanese language.
|
||||
/// </summary>
|
||||
Japanese,
|
||||
|
||||
/// <summary>
|
||||
/// German language.
|
||||
/// </summary>
|
||||
German
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
namespace RhythmBase.Components.Conditions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a condition based on the last hit in a rhythm game.
|
||||
/// </summary>
|
||||
public class LastHitCondition : BaseConditional
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LastHitCondition"/> class.
|
||||
/// </summary>
|
||||
public LastHitCondition()
|
||||
{
|
||||
Type = ConditionType.LastHit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the condition.
|
||||
/// </summary>
|
||||
public override ConditionType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the row where the last hit occurred.
|
||||
/// </summary>
|
||||
public sbyte Row { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the result that determines under what condition the event will be executed.
|
||||
/// </summary>
|
||||
public HitResult Result { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines the possible results of a hit.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum HitResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The hit was perfect.
|
||||
/// </summary>
|
||||
Perfect = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The hit was slightly early.
|
||||
/// </summary>
|
||||
SlightlyEarly = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The hit was slightly late.
|
||||
/// </summary>
|
||||
SlightlyLate = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The hit was very early.
|
||||
/// </summary>
|
||||
VeryEarly = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The hit was very late.
|
||||
/// </summary>
|
||||
VeryLate = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The hit was either slightly early or slightly late.
|
||||
/// </summary>
|
||||
AnyEarlyOrLate = 7,
|
||||
|
||||
/// <summary>
|
||||
/// The hit was missed.
|
||||
/// </summary>
|
||||
Missed = 15
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
namespace RhythmBase.Components.Conditions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a condition based on the player mode.
|
||||
/// </summary>
|
||||
public class PlayerModeCondition : BaseConditional
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlayerModeCondition"/> class.
|
||||
/// </summary>
|
||||
public PlayerModeCondition()
|
||||
{
|
||||
Type = ConditionType.PlayerMode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether two-player mode is enabled.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if two-player mode is enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool TwoPlayerMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the condition.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the condition.
|
||||
/// </value>
|
||||
public override ConditionType Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace RhythmBase.Components.Conditions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a condition based on the number of times it has been executed.
|
||||
/// </summary>
|
||||
public class TimesExecutedCondition : BaseConditional
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TimesExecutedCondition"/> class.
|
||||
/// </summary>
|
||||
public TimesExecutedCondition()
|
||||
{
|
||||
Type = ConditionType.TimesExecuted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of executions allowed.
|
||||
/// </summary>
|
||||
public int MaxTimes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the condition.
|
||||
/// </summary>
|
||||
public override ConditionType Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Exceptions;
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A decoration.
|
||||
/// </summary>
|
||||
[JsonObject]
|
||||
public class DecorationEventCollection : OrderedEventCollection<BaseDecorationAction>
|
||||
{
|
||||
/// <summary>
|
||||
/// Decorated ID.
|
||||
/// </summary>
|
||||
[JsonProperty("id")]
|
||||
public string Id
|
||||
{
|
||||
get => _id;
|
||||
set => _id = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// Decoration index.
|
||||
/// </summary>
|
||||
[JsonProperty("row")]
|
||||
public int Index => Parent?.Decorations.ToList().IndexOf(this) ?? throw new RhythmBaseException();
|
||||
|
||||
/// <summary>
|
||||
/// Room.
|
||||
/// </summary>
|
||||
[JsonProperty("rooms")]
|
||||
public RDSingleRoom Room { get; set; }
|
||||
/// <summary>
|
||||
/// The file reference used by the decoration.
|
||||
/// </summary>
|
||||
[JsonProperty("filename")]
|
||||
public string Filename { get; set; } = "";
|
||||
/// <summary>
|
||||
/// Decoration depth.
|
||||
/// </summary>
|
||||
public int Depth { get; set; }
|
||||
/// <summary>
|
||||
/// The filter used for this decoration.
|
||||
/// </summary>
|
||||
public Filters Filter { get; set; }
|
||||
/// <summary>
|
||||
/// The initial visibility of this decoration.
|
||||
/// </summary>
|
||||
public bool Visible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DecorationEventCollection"/> class.
|
||||
/// </summary>
|
||||
public DecorationEventCollection()
|
||||
{
|
||||
Room = new RDSingleRoom(RDRoomIndex.Room1);
|
||||
}
|
||||
/// <param name="room">Decoration room.</param>
|
||||
internal DecorationEventCollection(RDSingleRoom room)
|
||||
{
|
||||
Room = room;
|
||||
_id = GetHashCode().ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// Add an event to decoration.
|
||||
/// </summary>
|
||||
/// <param name="item">Decoration event.</param>
|
||||
public override void Add(BaseDecorationAction item)
|
||||
{
|
||||
item._parent?.Remove(item);
|
||||
item._parent = this;
|
||||
Parent?.Add(item);
|
||||
}
|
||||
internal void AddSafely(BaseDecorationAction item) => base.Add(item);
|
||||
/// <summary>
|
||||
/// Remove an event from decoration.
|
||||
/// </summary>
|
||||
/// <param name="item">A decoration event.</param>
|
||||
public override bool Remove(BaseDecorationAction item) => Parent?.Remove(item) ?? throw new RhythmBaseException();
|
||||
internal bool RemoveSafely(BaseDecorationAction item) => base.Remove(item);
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => string.Format("{0}, {1}, {2}, {3}",
|
||||
[
|
||||
_id,
|
||||
Index,
|
||||
Room,
|
||||
Filename
|
||||
]);
|
||||
internal DecorationEventCollection Clone() => (DecorationEventCollection)MemberwiseClone();
|
||||
private string _id = "";
|
||||
[JsonIgnore]
|
||||
internal RDLevel? Parent = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
namespace RhythmBase.Components.Easing
|
||||
|
||||
{
|
||||
///<summary>
|
||||
/// The EaseType enumeration represents various types of easing functions.
|
||||
/// These functions are used to create smooth transitions in animations.
|
||||
///</summary>
|
||||
public enum EaseType
|
||||
{
|
||||
/// <summary>
|
||||
/// Unset.
|
||||
/// </summary>
|
||||
Unset = -1,
|
||||
///<summary>
|
||||
///Ease Linear.
|
||||
///</summary>
|
||||
Linear,
|
||||
///<summary>
|
||||
///Ease InSine.
|
||||
///</summary>
|
||||
InSine,
|
||||
///<summary>
|
||||
///Ease OutSine.
|
||||
///</summary>
|
||||
OutSine,
|
||||
///<summary>
|
||||
///Ease InOutSine.
|
||||
///</summary>
|
||||
InOutSine,
|
||||
///<summary>
|
||||
///Ease InQuad.
|
||||
///</summary>
|
||||
InQuad,
|
||||
///<summary>
|
||||
///Ease OutQuad.
|
||||
///</summary>
|
||||
OutQuad,
|
||||
///<summary>
|
||||
///Ease InOutQuad.
|
||||
///</summary>
|
||||
InOutQuad,
|
||||
///<summary>
|
||||
///Ease InCubic.
|
||||
///</summary>
|
||||
InCubic,
|
||||
///<summary>
|
||||
///Ease OutCubic.
|
||||
///</summary>
|
||||
OutCubic,
|
||||
///<summary>
|
||||
///Ease InOutCubic.
|
||||
///</summary>
|
||||
InOutCubic,
|
||||
///<summary>
|
||||
///Ease InQuart.
|
||||
///</summary>
|
||||
InQuart,
|
||||
///<summary>
|
||||
///Ease OutQuart.
|
||||
///</summary>
|
||||
OutQuart,
|
||||
///<summary>
|
||||
///Ease InOutQuart.
|
||||
///</summary>
|
||||
InOutQuart,
|
||||
///<summary>
|
||||
///Ease InQuint.
|
||||
///</summary>
|
||||
InQuint,
|
||||
///<summary>
|
||||
///Ease OutQuint.
|
||||
///</summary>
|
||||
OutQuint,
|
||||
///<summary>
|
||||
///Ease InOutQuint.
|
||||
///</summary>
|
||||
InOutQuint,
|
||||
///<summary>
|
||||
///Ease InExpo.
|
||||
///</summary>
|
||||
InExpo,
|
||||
///<summary>
|
||||
///Ease OutExpo.
|
||||
///</summary>
|
||||
OutExpo,
|
||||
///<summary>
|
||||
///Ease InOutExpo.
|
||||
///</summary>
|
||||
InOutExpo,
|
||||
///<summary>
|
||||
///Ease InCirc.
|
||||
///</summary>
|
||||
InCirc,
|
||||
///<summary>
|
||||
///Ease OutCirc.
|
||||
///</summary>
|
||||
OutCirc,
|
||||
///<summary>
|
||||
///Ease InOutCirc.
|
||||
///</summary>
|
||||
InOutCirc,
|
||||
///<summary>
|
||||
///Ease InElastic.
|
||||
///</summary>
|
||||
InElastic,
|
||||
///<summary>
|
||||
///Ease OutElastic.
|
||||
///</summary>
|
||||
OutElastic,
|
||||
///<summary>
|
||||
///Ease InOutElastic.
|
||||
///</summary>
|
||||
InOutElastic,
|
||||
///<summary>
|
||||
///Ease InBack.
|
||||
///</summary>
|
||||
InBack,
|
||||
///<summary>
|
||||
///Ease OutBack.
|
||||
///</summary>
|
||||
OutBack,
|
||||
///<summary>
|
||||
///Ease InOutBack.
|
||||
///</summary>
|
||||
InOutBack,
|
||||
///<summary>
|
||||
///Ease InBounce.
|
||||
///</summary>
|
||||
InBounce,
|
||||
///<summary>
|
||||
///Ease OutBounce.
|
||||
///</summary>
|
||||
OutBounce,
|
||||
///<summary>
|
||||
///Ease InOutBounce.
|
||||
///</summary>
|
||||
InOutBounce,
|
||||
///<summary>
|
||||
///Ease SmoothStep.
|
||||
///</summary>
|
||||
SmoothStep,
|
||||
}
|
||||
/// <summary>
|
||||
/// Ease Calculate module.
|
||||
/// </summary>
|
||||
public static class Ease
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates the value with the specified ease type.
|
||||
/// </summary>
|
||||
/// <param name="type">Ease type.</param>
|
||||
/// <param name="x">A doubleing-point number in the range of 0 to 1.</param>
|
||||
/// <returns>Easing result.</returns>
|
||||
public static double Calculate(this EaseType type, double x) => type switch
|
||||
{
|
||||
EaseType.Unset => EaseFunction.None(x),
|
||||
EaseType.Linear => EaseFunction.Linear(x),
|
||||
EaseType.InSine => EaseFunction.InSine(x),
|
||||
EaseType.OutSine => EaseFunction.OutSine(x),
|
||||
EaseType.InOutSine => EaseFunction.InOutSine(x),
|
||||
EaseType.InQuad => EaseFunction.InQuad(x),
|
||||
EaseType.OutQuad => EaseFunction.OutQuad(x),
|
||||
EaseType.InOutQuad => EaseFunction.InOutQuad(x),
|
||||
EaseType.InCubic => EaseFunction.InCubic(x),
|
||||
EaseType.OutCubic => EaseFunction.OutCubic(x),
|
||||
EaseType.InOutCubic => EaseFunction.InOutCubic(x),
|
||||
EaseType.InQuart => EaseFunction.InQuart(x),
|
||||
EaseType.OutQuart => EaseFunction.OutQuart(x),
|
||||
EaseType.InOutQuart => EaseFunction.InOutQuart(x),
|
||||
EaseType.InQuint => EaseFunction.InQuint(x),
|
||||
EaseType.OutQuint => EaseFunction.OutQuint(x),
|
||||
EaseType.InOutQuint => EaseFunction.InOutQuint(x),
|
||||
EaseType.InExpo => EaseFunction.InExpo(x),
|
||||
EaseType.OutExpo => EaseFunction.OutExpo(x),
|
||||
EaseType.InOutExpo => EaseFunction.InOutExpo(x),
|
||||
EaseType.InCirc => EaseFunction.InCirc(x),
|
||||
EaseType.OutCirc => EaseFunction.OutCirc(x),
|
||||
EaseType.InOutCirc => EaseFunction.InOutCirc(x),
|
||||
EaseType.InElastic => EaseFunction.InElastic(x),
|
||||
EaseType.OutElastic => EaseFunction.OutElastic(x),
|
||||
EaseType.InOutElastic => EaseFunction.InOutElastic(x),
|
||||
EaseType.InBack => EaseFunction.InBack(x),
|
||||
EaseType.OutBack => EaseFunction.OutBack(x),
|
||||
EaseType.InOutBack => EaseFunction.InOutBack(x),
|
||||
EaseType.InBounce => EaseFunction.InBounce(x),
|
||||
EaseType.OutBounce => EaseFunction.OutBounce(x),
|
||||
EaseType.InOutBounce => EaseFunction.InOutBounce(x),
|
||||
EaseType.SmoothStep => EaseFunction.SmoothStep(x),
|
||||
_ => 0,
|
||||
};
|
||||
/// <summary>
|
||||
/// Calculates the value with the specified ease type.
|
||||
/// </summary>
|
||||
/// <param name="Type">Ease type.</param>
|
||||
/// <param name="x">A doubleing-point number in the range of 0 to 1.</param>
|
||||
/// <param name="from">The starting value of the easing result.</param>
|
||||
/// <param name="to">The endding value of the easing result</param>
|
||||
/// <returns>Easing result.</returns>
|
||||
public static double Calculate(this EaseType Type, double x, double from, double to) => Type.Calculate(x) * (to - from) + from;
|
||||
/// <summary>
|
||||
/// Ease types.
|
||||
/// </summary>
|
||||
|
||||
private static class EaseFunction
|
||||
{
|
||||
private const double c1 = 1.525;
|
||||
private const double c2 = 1.70158;
|
||||
public static double None(double x) => 0;
|
||||
public static double Linear(double x) => x;
|
||||
public static double InSine(double x) => 1 - Math.Cos(x * double.Pi / 2);
|
||||
public static double OutSine(double x) => Math.Sin(x * double.Pi / 2);
|
||||
public static double InOutSine(double x) => -(Math.Cos(x * double.Pi) - 1) / 2;
|
||||
public static double InQuad(double x) => Math.Pow(x, 2);
|
||||
public static double OutQuad(double x) => 1 - Math.Pow(1 - x, 2);
|
||||
public static double InOutQuad(double x) => x < 0.5 ? 2 * Math.Pow(x, 2) : 1 - Math.Pow(-2 * x + 2, 2) / 2;
|
||||
public static double InCubic(double x) => Math.Pow(x, 3);
|
||||
public static double OutCubic(double x) => 1 - Math.Pow(1 - x, 3);
|
||||
public static double InOutCubic(double x) => x < 0.5 ? 4 * Math.Pow(x, 3) : 1 - Math.Pow(-2 * x + 2, 3) / 2;
|
||||
public static double InQuart(double x) => Math.Pow(x, 4);
|
||||
public static double OutQuart(double x) => 1 - Math.Pow(1 - x, 4);
|
||||
public static double InOutQuart(double x) => x < 0.5 ? 8 * Math.Pow(x, 4) : 1 - Math.Pow(-2 * x + 2, 4) / 2;
|
||||
public static double InQuint(double x) => Math.Pow(x, 5);
|
||||
public static double OutQuint(double x) => 1 - Math.Pow(1 - x, 5);
|
||||
public static double InOutQuint(double x) => x < 0.5 ? 16 * Math.Pow(x, 5) : 1 - Math.Pow(-2 * x + 2, 5) / 2;
|
||||
public static double InExpo(double x) => x == 0 ? 0 : Math.Pow(2, 10 * x - 10);
|
||||
public static double OutExpo(double x) => x == 1 ? 1 : 1 - Math.Pow(2, -10 * x);
|
||||
public static double InOutExpo(double x) => x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: x < 0.5 ? Math.Pow(2, 20 * x - 10) / 2
|
||||
: (2 - Math.Pow(2, -20 * x + 10)) / 2;
|
||||
public static double InCirc(double x) => 1 - Math.Sqrt(1 - Math.Pow(x, 2));
|
||||
public static double OutCirc(double x) => Math.Sqrt(1 - Math.Pow(x - 1, 2));
|
||||
public static double InOutCirc(double x) => x < 0.5
|
||||
? (1 - Math.Sqrt(1 - Math.Pow(2 * x, 2))) / 2
|
||||
: (Math.Sqrt(1 - Math.Pow(-2 * x + 2, 2)) + 1) / 2;
|
||||
public static double InElastic(double x) => x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: -Math.Pow(2, 10 * x - 10) * Math.Sin((x * 10 - 10.75) * (2 * double.Pi / 3));
|
||||
public static double OutElastic(double x) => x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: Math.Pow(2, -10 * x) * Math.Sin((x * 10 - 0.75) * (2 * double.Pi / 3)) + 1;
|
||||
public static double InOutElastic(double x) => x == 0
|
||||
? 0
|
||||
: x == 1
|
||||
? 1
|
||||
: x < 0.5
|
||||
? -(Math.Pow(2, 20 * x - 10) * Math.Sin((20 * x - 11.125) * (2 * double.Pi / 4.5))) / 2
|
||||
: Math.Pow(2, -20 * x + 10) * Math.Sin((20 * x - 11.125) * (2 * double.Pi / 4.5)) / 2 + 1;
|
||||
public static double InBack(double x) => (c2 + 1) * x * x * x - c2 * x * x;
|
||||
public static double OutBack(double x) => 1 + (c2 + 1) * Math.Pow(x - 1, 3) + c2 * Math.Pow(x - 1, 2);
|
||||
public static double InOutBack(double x) => x < 0.5
|
||||
? Math.Pow(2 * x, 2) * ((c2 * c1 + 1) * 2 * x - c2 * c1) / 2
|
||||
: (Math.Pow(2 * x - 2, 2) * ((c2 * c1 + 1) * (x * 2 - 2) + c2 * c1) + 2) / 2;
|
||||
public static double InBounce(double x) =>
|
||||
1 - OutBounce(1 - x);
|
||||
public static double OutBounce(double x)
|
||||
{
|
||||
const double n1 = 7.5625;
|
||||
const double d1 = 2.75;
|
||||
return x switch
|
||||
{
|
||||
< 1 / d1 => n1 * x * x,
|
||||
< 2 / d1 => n1 * (x -= 1.5 / d1) * x + 0.75,
|
||||
< 2.5 / d1 => n1 * (x -= 2.25 / d1) * x + 0.9375,
|
||||
_ => n1 * (x -= 2.625 / d1) * x + 0.984375,
|
||||
};
|
||||
}
|
||||
public static double InOutBounce(double x) =>
|
||||
x < 0.5
|
||||
? (1 - OutBounce(1 - 2 * x)) / 2
|
||||
: (1 + OutBounce(2 * x - 1)) / 2;
|
||||
public static double SmoothStep(double x) =>
|
||||
(3 - 2 * x) * Math.Pow(x, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a node in the easing process.
|
||||
/// </summary>
|
||||
/// <param name="target">The target value of the easing node.</param>
|
||||
public struct EaseNode(float target)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the time at which the easing node starts.
|
||||
/// </summary>
|
||||
public float Time { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target value of the easing node.
|
||||
/// </summary>
|
||||
public float Target { get; set; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the duration of the easing node.
|
||||
/// </summary>
|
||||
public float Duration { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of easing to be applied.
|
||||
/// </summary>
|
||||
public EaseType Type { get; set; } = EaseType.Linear;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute to mark properties for easing functions.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class EasePropertyAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using RhythmBase.Events;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an easing property with a color value.
|
||||
/// </summary>
|
||||
public class EasePropertyColor : IEaseProperty<RDColor>
|
||||
{
|
||||
private EaseValue _r;
|
||||
private EaseValue _g;
|
||||
private EaseValue _b;
|
||||
private EaseValue _a;
|
||||
/// <inheritdoc/>
|
||||
public RDColor GetValue(RDBeat beat) => RDColor.FromRgba(
|
||||
(byte)Math.Clamp(_r.GetValue(beat.BeatOnly), 0, 255),
|
||||
(byte)Math.Clamp(_g.GetValue(beat.BeatOnly), 0, 255),
|
||||
(byte)Math.Clamp(_b.GetValue(beat.BeatOnly), 0, 255),
|
||||
(byte)Math.Clamp(_a.GetValue(beat.BeatOnly), 0, 255));
|
||||
/// <inheritdoc/>
|
||||
public static bool CanConvert(object data) => data is RDColor;
|
||||
/// <inheritdoc/>
|
||||
public static EaseNode?[] Convert(IEaseEvent data, PropertyInfo property)
|
||||
{
|
||||
RDColor? value = (RDColor?)property.GetValue(data);
|
||||
return [
|
||||
value?.R is byte vr ? new(vr) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
value?.G is byte vg ? new(vg) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
value?.B is byte vb ? new(vb) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
value?.A is byte va ? new(va) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
];
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public static IEaseProperty<RDColor> CreateEaseProperty(RDColor originalValue, IEaseEvent[] data, PropertyInfo property)
|
||||
{
|
||||
EaseNode?[][] nodes = [.. data.Select(d => Convert(d, property))];
|
||||
return new EasePropertyColor()
|
||||
{
|
||||
_r = new(originalValue.R, [.. nodes.Select(i => i[0]).Where(i => i is not null).Cast<EaseNode>()]),
|
||||
_g = new(originalValue.G, [.. nodes.Select(i => i[1]).Where(i => i is not null).Cast<EaseNode>()]),
|
||||
_b = new(originalValue.B, [.. nodes.Select(i => i[2]).Where(i => i is not null).Cast<EaseNode>()]),
|
||||
_a = new(originalValue.A, [.. nodes.Select(i => i[3]).Where(i => i is not null).Cast<EaseNode>()])
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using RhythmBase.Events;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an easing property with a float value.
|
||||
/// </summary>
|
||||
public class EasePropertyFloat : IEaseProperty<float>
|
||||
{
|
||||
private EaseValue _value;
|
||||
/// <inheritdoc/>
|
||||
public float GetValue(RDBeat beat) => _value.GetValue(beat.BeatOnly);
|
||||
/// <inheritdoc/>
|
||||
public static bool CanConvert(object data) => data is float;
|
||||
/// <inheritdoc/>
|
||||
public static EaseNode?[] Convert(IEaseEvent data, PropertyInfo property)
|
||||
{
|
||||
RDExpression? value = (RDExpression?)property.GetValue(data);
|
||||
return [
|
||||
value is RDExpression v? new EaseNode(v.Value) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
];
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public static IEaseProperty<float> CreateEaseProperty(float originalValue, IEaseEvent[] data, PropertyInfo property)
|
||||
{
|
||||
EaseNode?[][] nodes = [.. data.Select(d => Convert(d, property))];
|
||||
return new EasePropertyFloat()
|
||||
{
|
||||
_value = new(originalValue, [.. nodes.Select(i => i[0]).Where(i => i is not null).Cast<EaseNode>()])
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using RhythmBase.Events;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an easing property with a point value.
|
||||
/// </summary>
|
||||
public class EasePropertyPoint : IEaseProperty<RDPointN>
|
||||
{
|
||||
private EaseValue _x;
|
||||
private EaseValue _y;
|
||||
/// <inheritdoc/>
|
||||
public RDPointN GetValue(RDBeat beat) => new(_x.GetValue(beat.BeatOnly), _y.GetValue(beat.BeatOnly));
|
||||
/// <inheritdoc/>
|
||||
public static bool CanConvert(object data) => data is RDPoint;
|
||||
/// <inheritdoc/>
|
||||
public static EaseNode?[] Convert(IEaseEvent data, PropertyInfo property)
|
||||
{
|
||||
RDPointE? value = (RDPointE?)property.GetValue(data);
|
||||
return [
|
||||
value?.X?.Value is float vx ? new(vx) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
value?.Y?.Value is float vy ? new(vy) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
];
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public static IEaseProperty<RDPointN> CreateEaseProperty(RDPointN originalValue, IEaseEvent[] data, PropertyInfo property)
|
||||
{
|
||||
EaseNode?[][] nodes = [.. data.Select(d => Convert(d, property))];
|
||||
return new EasePropertyPoint()
|
||||
{
|
||||
_x = new(originalValue.X, [.. nodes.Select(i => i[0]).Where(i => i is not null).Cast<EaseNode>()]),
|
||||
_y = new(originalValue.Y, [.. nodes.Select(i => i[1]).Where(i => i is not null).Cast<EaseNode>()])
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using RhythmBase.Events;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an easing property with a size value.
|
||||
/// </summary>
|
||||
public class EasePropertySize : IEaseProperty<RDSizeN>
|
||||
{
|
||||
private EaseValue _width;
|
||||
private EaseValue _height;
|
||||
/// <inheritdoc/>
|
||||
public RDSizeN GetValue(RDBeat beat) => new(_width.GetValue(beat.BeatOnly), _height.GetValue(beat.BeatOnly));
|
||||
/// <inheritdoc/>
|
||||
public static bool CanConvert(object data) => data is RDSize;
|
||||
/// <inheritdoc/>
|
||||
public static EaseNode?[] Convert(IEaseEvent data, PropertyInfo property)
|
||||
{
|
||||
RDSizeE? value = (RDSizeE?)property.GetValue(data);
|
||||
return [
|
||||
value?.Width?.Value is float vx ? new(vx) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
value?.Height?.Value is float vy ? new(vy) {
|
||||
Duration = data.Duration,
|
||||
Time = ((BaseEvent)data).Beat.BeatOnly,
|
||||
Type = data.Ease
|
||||
} : null,
|
||||
];
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public static IEaseProperty<RDSizeN> CreateEaseProperty(RDSizeN originalValue, IEaseEvent[] data, PropertyInfo property)
|
||||
{
|
||||
EaseNode?[][] nodes = [.. data.Select(d => Convert(d, property))];
|
||||
return new EasePropertySize()
|
||||
{
|
||||
_width = new(originalValue.Width, [.. nodes.Select(i => i[0]).Where(i => i is not null).Cast<EaseNode>()]),
|
||||
_height = new(originalValue.Height, [.. nodes.Select(i => i[1]).Where(i => i is not null).Cast<EaseNode>()])
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
using System.Data;
|
||||
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a value that changes over time according to a series of easing nodes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="EaseValue"/> class with the specified original value and easing nodes.
|
||||
/// </remarks>
|
||||
/// <param name="originalValue">The original value before any easing is applied.</param>
|
||||
/// <param name="nodes">The collection of easing nodes that define how the value changes over time.</param>
|
||||
public struct EaseValue(float originalValue, IEnumerable<EaseNode> nodes)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the collection of easing nodes, ordered by their start time.
|
||||
/// </summary>
|
||||
public EaseNode[] Nodes { get; set; } = [.. nodes.OrderBy(x => x.Time)];
|
||||
/// <summary>
|
||||
/// Gets or sets the original value before any easing is applied.
|
||||
/// </summary>
|
||||
public float OriginalValue { get; set; } = originalValue;
|
||||
/// <summary>
|
||||
/// Gets the value at the specified time, taking into account the easing nodes.
|
||||
/// </summary>
|
||||
/// <param name="time">The time at which to get the value.</param>
|
||||
/// <returns>The value at the specified time.</returns>
|
||||
public readonly float GetValue(float time)
|
||||
{
|
||||
if (Nodes.Length == 0 || time <= Nodes[0].Time)
|
||||
return OriginalValue;
|
||||
int i = Nodes.Length - 1;
|
||||
while (i >= 0 && time <= Nodes[i].Time)
|
||||
i--;
|
||||
if (Nodes[i].Time + Nodes[i].Duration <= time)
|
||||
return Nodes[i].Target;
|
||||
Stack<EaseNode> ns = new([Nodes[i]]);
|
||||
while (--i > -1)
|
||||
{
|
||||
if (IsInRange(Nodes[i], ns.Peek().Time))
|
||||
{
|
||||
ns.Push(Nodes[i]);
|
||||
}
|
||||
}
|
||||
float origin = i == -1 ? OriginalValue : Nodes[i + 1].Target;
|
||||
while (ns.Count > 1)
|
||||
{
|
||||
EaseNode node = ns.Pop();
|
||||
origin = GetValue(node, ns.Peek().Time, origin);
|
||||
}
|
||||
origin = GetValue(ns.Pop(), time, origin);
|
||||
return origin;
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether the specified time is within the range of the easing node.
|
||||
/// </summary>
|
||||
/// <param name="node">The easing node to check.</param>
|
||||
/// <param name="time">The time to check.</param>
|
||||
/// <returns><c>true</c> if the time is within the range of the easing node; otherwise, <c>false</c>.</returns>
|
||||
private static bool IsInRange(EaseNode node, float time) => node.Time <= time && time <= node.Time + node.Duration;
|
||||
/// <summary>
|
||||
/// Calculates the value of the easing node at the specified time.
|
||||
/// </summary>
|
||||
/// <param name="node">The easing node to calculate the value for.</param>
|
||||
/// <param name="time">The time at which to calculate the value.</param>
|
||||
/// <param name="origin">The original value before any easing is applied.</param>
|
||||
/// <returns>The calculated value at the specified time.</returns>
|
||||
private static float GetValue(EaseNode node, float time, float origin) => node.Duration == 0 ? node.Target : (float)node.Type.Calculate((time - node.Time) / node.Duration, origin, node.Target);
|
||||
/// <summary>
|
||||
/// Fits the data points to an easing function with the specified precision.
|
||||
/// </summary>
|
||||
/// <param name="originalValue">The original value before any easing is applied.</param>
|
||||
/// <param name="values">The array of time and value pairs to fit.</param>
|
||||
/// <param name="precision">The precision for fitting the data points.</param>
|
||||
/// <returns>An <see cref="EaseValue"/> instance that fits the data points.</returns>
|
||||
public static EaseValue Fit(float originalValue, (float time, float value)[] values, float precision = 3f) => Fit(originalValue, values, eases, precision);
|
||||
/// <summary>
|
||||
/// Fits the data points to an easing function with the specified precision.
|
||||
/// </summary>
|
||||
/// <param name="originalValue">The original value before any easing is applied.</param>
|
||||
/// <param name="values">The array of time and value pairs to fit.</param>
|
||||
/// <param name="precision">The precision for fitting the data points.</param>
|
||||
/// <param name="easeTypes">The array of easing types to consider.</param>
|
||||
/// <returns>An <see cref="EaseValue"/> instance that fits the data points.</returns>
|
||||
public static EaseValue Fit(float originalValue, (float time, float value)[] values, EaseType[] easeTypes, float precision = 3f)
|
||||
{
|
||||
values = [.. values.OrderBy(x => x.time)];
|
||||
if (values.Length == 0)
|
||||
return new EaseValue(originalValue, []);
|
||||
if (values.Length == 1)
|
||||
return new EaseValue(originalValue, [new EaseNode(values[0].value) { Duration = values[0].time, Type = EaseType.InOutSine }]);
|
||||
if (values.Length == 2)
|
||||
return new EaseValue(originalValue, [new EaseNode(values[0].value) { Time = values[0].time, Duration = values[1].time, Type = EaseType.InOutSine }]);
|
||||
return Fit([(0, originalValue), .. values], easeTypes, precision);
|
||||
}
|
||||
/// <summary>
|
||||
/// Fits the data points to an easing function with the specified precision.
|
||||
/// </summary>
|
||||
/// <param name="values">The array of time and value pairs to fit.</param>
|
||||
/// <param name="precision">The precision for fitting the data points.</param>
|
||||
/// <returns>An <see cref="EaseValue"/> instance that fits the data points.</returns>
|
||||
public static EaseValue Fit((float time, float value)[] values, float precision = 3f) => Fit(values, eases, precision);
|
||||
/// <summary>
|
||||
/// Fits the data points to an easing function with the specified precision and ease types.
|
||||
/// </summary>
|
||||
/// <param name="values">The array of time and value pairs to fit.</param>
|
||||
/// <param name="easeTypes">The array of easing types to consider.</param>
|
||||
/// <param name="precision">The precision for fitting the data points.</param>
|
||||
/// <remarks>Special thanks to <b>mfgujhgh</b> for the algorithm!</remarks>
|
||||
/// <returns>An <see cref="EaseValue"/> instance that fits the data points.</returns>
|
||||
public static EaseValue Fit((float time, float value)[] values, EaseType[] easeTypes, float precision = 3f)
|
||||
{
|
||||
if (easeTypes.Length == 0)
|
||||
throw new ArgumentException("At least one ease type must be specified.", nameof(easeTypes));
|
||||
values = [.. values.OrderBy(x => x.time)];
|
||||
int[] steps = new int[values.Length],
|
||||
p = new int[values.Length];
|
||||
EaseType[] pe = new EaseType[values.Length];
|
||||
steps[0] = 0;
|
||||
for (int i = 1; i < values.Length; i++)
|
||||
{
|
||||
steps[i] = steps[i - 1] + 1;
|
||||
p[i] = i - 1;
|
||||
pe[i] = easeTypes[0];
|
||||
for (int j = 0; j < i - 1; j++)
|
||||
{
|
||||
if (steps[j] + 1 >= steps[i])
|
||||
continue;
|
||||
EaseType besttype = easeTypes[0];
|
||||
float bests = float.MaxValue;
|
||||
foreach (var e in easeTypes)
|
||||
{
|
||||
float s = Check(values, j, i, e, precision);
|
||||
if (s < bests)
|
||||
{
|
||||
bests = s;
|
||||
besttype = e;
|
||||
}
|
||||
}
|
||||
if (bests < precision && steps[i] > steps[j] + 1)
|
||||
{
|
||||
steps[i] = steps[j] + 1;
|
||||
p[i] = j;
|
||||
pe[i] = besttype;
|
||||
}
|
||||
}
|
||||
}
|
||||
EaseNode[] ns = new EaseNode[steps[^1]];
|
||||
int k = values.Length - 1;
|
||||
while (k != 0)
|
||||
{
|
||||
ns[--steps[k]] = new EaseNode(values[k].value)
|
||||
{
|
||||
Time = values[p[k]].time,
|
||||
Duration = values[k].time - values[p[k]].time,
|
||||
Type = pe[k]
|
||||
};
|
||||
k = p[k];
|
||||
}
|
||||
return new EaseValue(values[0].value, ns);
|
||||
}
|
||||
private static float Check((float time, float value)[] data, int start, int end, EaseType type, float precision)
|
||||
{
|
||||
float s = 0;
|
||||
for (int i = start + 1; i <= end; i++)
|
||||
{
|
||||
float v = data[start].value
|
||||
+ (float)type.Calculate((data[i].time - data[start].time) / (data[end].time - data[start].time))
|
||||
* (data[end].value - data[start].value);
|
||||
s = Math.Max(s, Math.Abs(v - data[i].value));
|
||||
if (s > precision)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
private static readonly EaseType[] eases = Enum.GetValues<EaseType>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using RhythmBase.Events;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RhythmBase.Components.Easing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an easing property.
|
||||
/// </summary>
|
||||
public interface IEaseProperty
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Represents an easing property with a specific value type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
||||
public interface IEaseProperty<TValue> : IEaseProperty where TValue : new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of the value.
|
||||
/// </summary>
|
||||
static Type Type => typeof(TValue);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value at the specified beat.
|
||||
/// </summary>
|
||||
/// <param name="beat">The beat at which to get the value.</param>
|
||||
/// <returns>The value at the specified beat.</returns>
|
||||
abstract TValue GetValue(RDBeat beat);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified data can be converted to the value type.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to check.</param>
|
||||
/// <returns><c>true</c> if the data can be converted; otherwise, <c>false</c>.</returns>
|
||||
static abstract bool CanConvert(object data);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the specified easing event data to an array of easing nodes.
|
||||
/// </summary>
|
||||
/// <param name="data">The easing event data to convert.</param>
|
||||
/// <param name="property">The property information of the easing event.</param>
|
||||
/// <returns>An array of easing nodes.</returns>
|
||||
static abstract EaseNode?[] Convert(IEaseEvent data, PropertyInfo property);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an easing property with the specified original value and easing event data.
|
||||
/// </summary>
|
||||
/// <param name="originalValue">The original value before any easing is applied.</param>
|
||||
/// <param name="data">The array of easing event data.</param>
|
||||
/// <param name="property">The property information of the easing event.</param>
|
||||
/// <returns>An easing property instance.</returns>
|
||||
static abstract IEaseProperty<TValue> CreateEaseProperty(TValue originalValue, IEaseEvent[] data, PropertyInfo property);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the type of render filter to be used.
|
||||
/// </summary>
|
||||
public enum Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Nearest neighbor filtering.
|
||||
/// </summary>
|
||||
NearestNeighbor,
|
||||
|
||||
/// <summary>
|
||||
/// Bilinear filtering.
|
||||
/// </summary>
|
||||
BiliNear
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a vortex interface that supports various mathematical operations.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSelf">The type that implements this interface.</typeparam>
|
||||
/// <typeparam name="TRight">The type of the right operand in addition and subtraction operations.</typeparam>
|
||||
/// <typeparam name="TValue">The type of the value in multiplication and division operations.</typeparam>
|
||||
public interface IRDVortex<TSelf, TRight, TValue> :
|
||||
IEquatable<TSelf>,
|
||||
IAdditionOperators<TSelf, TRight, TSelf>,
|
||||
ISubtractionOperators<TSelf, TRight, TSelf>,
|
||||
IMultiplyOperators<TSelf, TValue, TSelf>,
|
||||
IDivisionOperators<TSelf, TValue, TSelf>,
|
||||
IEqualityOperators<TSelf, TSelf, bool>
|
||||
where TSelf :
|
||||
IEquatable<TSelf>,
|
||||
IAdditionOperators<TSelf, TRight, TSelf>,
|
||||
ISubtractionOperators<TSelf, TRight, TSelf>,
|
||||
IMultiplyOperators<TSelf, TValue, TSelf>,
|
||||
IDivisionOperators<TSelf, TValue, TSelf>,
|
||||
IEqualityOperators<TSelf, TSelf, bool>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of ordered events.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEvent">The type of event.</typeparam>
|
||||
public class OrderedEventCollection<TEvent> : OrderedEventCollection, ICollection<TEvent> where TEvent : IBaseEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrderedEventCollection{TEvent}"/> class.
|
||||
/// </summary>
|
||||
public OrderedEventCollection()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrderedEventCollection{TEvent}"/> class with the specified items.
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add to the collection.</param>
|
||||
public OrderedEventCollection(IEnumerable<TEvent> items)
|
||||
{
|
||||
foreach (TEvent item in items)
|
||||
Add(item);
|
||||
}
|
||||
/// <summary>
|
||||
/// Concatenates all events in the collection.
|
||||
/// </summary>
|
||||
/// <returns>An <see cref="IEnumerable{TEvent}"/> that contains all events in the collection.</returns>
|
||||
public new IEnumerable<TEvent> ConcatAll() => eventsBeatOrder.SelectMany(i => i.Value).Cast<TEvent>();
|
||||
/// <summary>
|
||||
/// Adds an event to the collection.
|
||||
/// </summary>
|
||||
/// <param name="item">The event to add.</param>
|
||||
public virtual void Add(TEvent item) => Add((IBaseEvent)(object)item);
|
||||
/// <inheritdoc/>
|
||||
public virtual bool Contains(TEvent item) => Contains((IBaseEvent)(object)item);
|
||||
/// <inheritdoc/>
|
||||
public void CopyTo(TEvent[] array, int arrayIndex) => CopyTo((IBaseEvent[])(object)array, arrayIndex);
|
||||
/// <inheritdoc/>
|
||||
public virtual bool Remove(TEvent item) => Remove((BaseEvent)(object)item);
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => string.Format("Count = {0}", Count);
|
||||
/// <inheritdoc/>
|
||||
IEnumerator<TEvent> IEnumerable<TEvent>.GetEnumerator()
|
||||
{
|
||||
foreach (KeyValuePair<RDBeat, TypedEventCollection<IBaseEvent>> pair in eventsBeatOrder)
|
||||
foreach (TEvent item in pair.Value.Select(v => (TEvent)v))
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Events;
|
||||
using System.Collections;
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of events that maintains the sequence of events.
|
||||
/// </summary>
|
||||
public abstract class OrderedEventCollection : ICollection<IBaseEvent>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the total count of events in the collection.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public virtual int Count => eventsBeatOrder.Sum((i) => i.Value.Count());
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the collection is read-only.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public bool IsReadOnly { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the beat of the last event.
|
||||
/// </summary>
|
||||
/// <returns>The beat of the last event.</returns>
|
||||
[JsonIgnore]
|
||||
public RDBeat Length => eventsBeatOrder.LastOrDefault().Value.FirstOrDefault()?.Beat??new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrderedEventCollection"/> class.
|
||||
/// </summary>
|
||||
public OrderedEventCollection()
|
||||
{
|
||||
eventsBeatOrder = [];
|
||||
IsReadOnly = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OrderedEventCollection"/> class with the specified items.
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add to the collection.</param>
|
||||
public OrderedEventCollection(IEnumerable<IBaseEvent> items)
|
||||
{
|
||||
eventsBeatOrder = [];
|
||||
IsReadOnly = false;
|
||||
foreach (IBaseEvent item in items)
|
||||
Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Concatenates all events in the collection.
|
||||
/// </summary>
|
||||
/// <returns>A list of all events in the collection.</returns>
|
||||
public IEnumerable<IBaseEvent> ConcatAll() => eventsBeatOrder.SelectMany(i => i.Value).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Adds an event to the collection.
|
||||
/// </summary>
|
||||
/// <param name="item">The event to add.</param>
|
||||
public void Add(IBaseEvent item)
|
||||
{
|
||||
TypedEventCollection<IBaseEvent> list = [];
|
||||
if (eventsBeatOrder.TryGetValue(item.Beat, out TypedEventCollection<IBaseEvent>? value))
|
||||
list = value;
|
||||
else
|
||||
eventsBeatOrder.Add(item.Beat, list);
|
||||
list.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all events from the collection.
|
||||
/// </summary>
|
||||
public void Clear() => eventsBeatOrder.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the collection contains a specific event.
|
||||
/// </summary>
|
||||
/// <param name="item">The event to locate in the collection.</param>
|
||||
/// <returns>true if the event is found in the collection; otherwise, false.</returns>
|
||||
public virtual bool Contains(IBaseEvent item) => eventsBeatOrder.ContainsKey(item.Beat) && eventsBeatOrder[item.Beat].Contains(item);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements of the collection to an array, starting at a particular array index.
|
||||
/// </summary>
|
||||
/// <param name="array">The array to copy the elements to.</param>
|
||||
/// <param name="arrayIndex">The zero-based index in the array at which copying begins.</param>
|
||||
public void CopyTo(IBaseEvent[] array, int arrayIndex)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
if (arrayIndex < 0 || arrayIndex > array.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
if (array.Length - arrayIndex < Count)
|
||||
throw new ArgumentException("The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array.");
|
||||
|
||||
foreach (var pair in eventsBeatOrder)
|
||||
{
|
||||
foreach (var item in pair.Value)
|
||||
{
|
||||
array[arrayIndex++] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of a specific event from the collection.
|
||||
/// </summary>
|
||||
/// <param name="item">The event to remove from the collection.</param>
|
||||
/// <returns>true if the event was successfully removed; otherwise, false.</returns>
|
||||
internal bool Remove(IBaseEvent item)
|
||||
{
|
||||
bool Remove;
|
||||
if (Contains(item))
|
||||
{
|
||||
bool result = eventsBeatOrder[item.Beat].Remove(item);
|
||||
if (!eventsBeatOrder[item.Beat].Any())
|
||||
eventsBeatOrder.Remove(item.Beat);
|
||||
Remove = result;
|
||||
}
|
||||
else
|
||||
Remove = false;
|
||||
return Remove;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the collection.
|
||||
/// </summary>
|
||||
/// <returns>An enumerator for the collection.</returns>
|
||||
public IEnumerator<IBaseEvent> GetEnumerator()
|
||||
{
|
||||
foreach (KeyValuePair<RDBeat, TypedEventCollection<IBaseEvent>> pair in eventsBeatOrder)
|
||||
foreach (IBaseEvent item in pair.Value)
|
||||
yield return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the collection.
|
||||
/// </summary>
|
||||
/// <returns>An enumerator for the collection.</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
foreach (KeyValuePair<RDBeat, TypedEventCollection<IBaseEvent>> pair in eventsBeatOrder)
|
||||
foreach (IBaseEvent item in pair.Value)
|
||||
yield return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current object.
|
||||
/// </summary>
|
||||
/// <returns>A string that represents the current object.</returns>
|
||||
public override string ToString() => string.Format("Count = {0}", Count);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of a specific event from the collection.
|
||||
/// </summary>
|
||||
/// <param name="item">The event to remove from the collection.</param>
|
||||
/// <returns>true if the event was successfully removed; otherwise, false.</returns>
|
||||
bool ICollection<IBaseEvent>.Remove(IBaseEvent item) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// The dictionary that maintains the order of events based on their beats.
|
||||
/// </summary>
|
||||
internal SortedDictionary<RDBeat, TypedEventCollection<IBaseEvent>> eventsBeatOrder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
namespace RhythmBase.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Palette color
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// </remarks>
|
||||
/// <param name="enableAlpha">Specifies whether this object supports alpha channel.</param>
|
||||
public class PaletteColor(bool enableAlpha)
|
||||
{
|
||||
/// <summary>
|
||||
/// Get or set a custom color.
|
||||
/// </summary>
|
||||
public RDColor? Color
|
||||
{
|
||||
get
|
||||
{
|
||||
RDColor? Color = new RDColor?(EnablePanel ? parent[_panel] : default);
|
||||
return Color;
|
||||
}
|
||||
set
|
||||
{
|
||||
_panel = -1;
|
||||
_color = EnableAlpha
|
||||
? value
|
||||
: value == null
|
||||
? null
|
||||
: new RDColor?(value.GetValueOrDefault().WithAlpha(byte.MaxValue));
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Go back to or set the palette color index.
|
||||
/// </summary>
|
||||
public int PaletteIndex
|
||||
{
|
||||
get => _panel;
|
||||
set
|
||||
{
|
||||
if (value >= 0)
|
||||
{
|
||||
_color = null;
|
||||
_panel = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Specifies whether this object supports alpha channel.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool EnableAlpha { get; } = enableAlpha;
|
||||
/// <summary>
|
||||
/// Specifies whether this object is used for this color.
|
||||
/// </summary>
|
||||
public bool EnablePanel
|
||||
{
|
||||
get
|
||||
{
|
||||
return PaletteIndex >= 0;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The actual color of this object.<br />
|
||||
/// If comes from a palette, it's a palette color.
|
||||
/// If not, it's a custom color.
|
||||
/// </summary>
|
||||
public RDColor Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EnablePanel ? (parent[_panel]) : _color ?? throw new RhythmBase.Exceptions.RhythmBaseException());
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => EnablePanel ? string.Format("{0}: {1}", _panel, Value) : Value.ToString();
|
||||
|
||||
private int _panel;
|
||||
|
||||
private RDColor? _color;
|
||||
|
||||
internal RDColor[] parent = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using Newtonsoft.Json;
|
||||
using RhythmBase.Converters;
|
||||
namespace RhythmBase.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an audio file with properties for volume, pitch, pan, and offset.
|
||||
/// </summary>
|
||||
public class RDAudio
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RDAudio"/> class with default values.
|
||||
/// </summary>
|
||||
public RDAudio() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file name of the audio.
|
||||
/// </summary>
|
||||
public string Filename { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the volume of the audio.
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
|
||||
public int Volume { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pitch of the audio.
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
|
||||
public int Pitch { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pan of the audio.
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
|
||||
public int Pan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the offset of the audio.
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
|
||||
[JsonConverter(typeof(MilliSecondConverter))]
|
||||
public TimeSpan Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the file is a valid audio file based on its extension.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public bool IsFile => sourceArray.Contains(Path.GetExtension(Filename));
|
||||
|
||||
private static readonly string[] sourceArray =
|
||||
[
|
||||
".mp3",
|
||||
".wav",
|
||||
".ogg",
|
||||
".aif",
|
||||
".aiff"
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current object.
|
||||
/// </summary>
|
||||
/// <returns>A string that represents the current object.</returns>
|
||||
public override string ToString() => Filename;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user