Archived
forked from RDTKEditor/RDTKEditor
添加对 Core 的直接引用
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Events;
|
||||
using System.Text.RegularExpressions;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal partial class AnchorStyleConverter : JsonConverter<FloatingText.AnchorStyle>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, FloatingText.AnchorStyle value, JsonSerializer serializer)
|
||||
{
|
||||
var horizontal = value & (FloatingText.AnchorStyle.Left | FloatingText.AnchorStyle.Right);
|
||||
var vertical = value & (FloatingText.AnchorStyle.Upper | FloatingText.AnchorStyle.Lower);
|
||||
writer.WriteValue(
|
||||
(vertical == 0 ?
|
||||
"Middle"
|
||||
: vertical.ToString())
|
||||
+ horizontal.ToString()
|
||||
);
|
||||
}
|
||||
|
||||
public override FloatingText.AnchorStyle ReadJson(JsonReader reader, Type objectType, FloatingText.AnchorStyle existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
JToken token = JToken.ReadFrom(reader);
|
||||
string JString = token.ToObject<string>() ?? throw new Exceptions.ConvertingException("Cannot read the anchor.");
|
||||
Match match = AnchorStyleRegex().Match(JString);
|
||||
if (!match.Success)
|
||||
throw new Exceptions.ConvertingException(token, $"Illegal Anchor: {JString}");
|
||||
FloatingText.AnchorStyle result = FloatingText.AnchorStyle.Center;
|
||||
|
||||
result |= match.Groups[1].Value switch
|
||||
{
|
||||
"Upper" => FloatingText.AnchorStyle.Upper,
|
||||
"Lower" => FloatingText.AnchorStyle.Lower,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
result |= match.Groups[2].Value switch
|
||||
{
|
||||
"Left" => FloatingText.AnchorStyle.Left,
|
||||
"Right" => FloatingText.AnchorStyle.Right,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[GeneratedRegex("(Upper|Middle|Lower)(Left|Center|Right)")]
|
||||
private static partial Regex AnchorStyleRegex();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Settings;
|
||||
using System.Diagnostics;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class BaseDecorationActionConverter<TEvent>(RDLevel level, LevelReadOrWriteSettings inputSettings) : BaseEventConverter<TEvent>(level, inputSettings) where TEvent : BaseDecorationAction
|
||||
{
|
||||
public override TEvent? GetDeserializedObject(JObject jobj, Type objectType, TEvent? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
TEvent? obj = base.GetDeserializedObject(jobj, objectType, existingValue, hasExistingValue, serializer);
|
||||
if (obj is null) return obj;
|
||||
string decoId = jobj["target"]?.ToObject<string>()!;
|
||||
DecorationEventCollection? Parent = level.ModifiableDecorations.FirstOrDefault(i => i.Id == decoId);
|
||||
if (Parent == null && obj.Type != EventType.Comment)
|
||||
switch (settings.UnreadableEventsHandling)
|
||||
{
|
||||
case UnreadableEventHandling.Store:
|
||||
settings.UnreadableEvents.Add((jobj,$"Cannot find the decoration with id {decoId}."));
|
||||
return default;
|
||||
case UnreadableEventHandling.ThrowException:
|
||||
#if DEBUG
|
||||
Debugger.Log(2, "cate", "");
|
||||
return default;
|
||||
#else
|
||||
throw new ConvertingException(string.Format("Cannot find the decoration \"{0}\" at {1}", jobj["target"], obj));
|
||||
#endif
|
||||
}
|
||||
obj._parent = Parent!;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Exceptions;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class BaseEventConverter<TEvent>(RDLevel level, LevelReadOrWriteSettings inputSettings) : JsonConverter<TEvent> where TEvent : IBaseEvent
|
||||
{
|
||||
public override bool CanRead => _canread;
|
||||
public override bool CanWrite => _canwrite;
|
||||
public override void WriteJson(JsonWriter writer, TEvent? value, JsonSerializer serializer)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ConvertingException(($"Event is null"));
|
||||
serializer.Formatting = Formatting.None;
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(SetSerializedObject(value, serializer)));
|
||||
serializer.Formatting = Formatting.Indented;
|
||||
}
|
||||
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)
|
||||
{
|
||||
JToken? typeToken = (jobj["type"])
|
||||
?? throw new Exceptions.ConvertingException(jobj, new Exception($"Missing property \"{jobj["type"]}\". path \"{jobj.Path}\""));
|
||||
Type SubClassType = Utils.EventTypeUtils.ToType(typeToken.ToObject<string>()
|
||||
?? throw new Exceptions.ConvertingException(jobj, new Exception($"Missing property \"{typeToken}\". path \"{jobj.Path}\"")));
|
||||
if (SubClassType == null)
|
||||
if (jobj["target"] != null)
|
||||
SubClassType = typeof(CustomDecorationEvent);
|
||||
else if (jobj["row"] != null)
|
||||
SubClassType = typeof(CustomRowEvent);
|
||||
else
|
||||
SubClassType = typeof(CustomEvent);
|
||||
_canread = false;
|
||||
existingValue = (TEvent?)jobj.ToObject(SubClassType, serializer)
|
||||
?? throw new ConvertingException(jobj, new Exception($"Cannot convert this event: \"{jobj}\". path \"{jobj.Path}\""));
|
||||
_canread = true;
|
||||
((BaseEvent)(object)existingValue)._beat = level.Calculator.BeatOf(
|
||||
uint.Parse(((string?)jobj["bar"])
|
||||
?? throw new Exception($"Missing property \"{jobj["bar"]}\".path \"{jobj.Path}\"")),
|
||||
float.Parse((string?)jobj["beat"] ?? 1.ToString()));
|
||||
return existingValue;
|
||||
}
|
||||
public virtual JObject SetSerializedObject(TEvent value, JsonSerializer serializer)
|
||||
{
|
||||
_canwrite = false;
|
||||
JObject JObj = JObject.FromObject(value, serializer);
|
||||
_canwrite = true;
|
||||
JObj.Remove("type");
|
||||
ValueTuple<uint, float> b = value.Beat.BarBeat;
|
||||
JToken s = JObj.First ?? throw new ConvertingException($"Internal error: Missing properties. path \"{JObj.Path}\"");
|
||||
s.AddBeforeSelf(new JProperty("bar", b.Item1));
|
||||
if (value is not IBarBeginningEvent)
|
||||
s.AddBeforeSelf(new JProperty("beat", b.Item2));
|
||||
s.AddBeforeSelf(new JProperty("type", value.Type.ToString()));
|
||||
if (JObj.Value<string>("tag") is string str && string.IsNullOrEmpty(str))
|
||||
JObj.Property("tag")?.Remove();
|
||||
return JObj;
|
||||
}
|
||||
protected readonly RDLevel level = level;
|
||||
protected readonly LevelReadOrWriteSettings settings = inputSettings;
|
||||
private bool _canread = true;
|
||||
private bool _canwrite = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Exceptions;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class BaseRowActionConverter<TEvent>(RDLevel level, LevelReadOrWriteSettings inputSettings) : BaseEventConverter<TEvent>(level, inputSettings) where TEvent : BaseRowAction
|
||||
{
|
||||
public override TEvent? GetDeserializedObject(JObject jobj, Type objectType, TEvent? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
TEvent? obj = base.GetDeserializedObject(jobj, objectType, existingValue, hasExistingValue, serializer);
|
||||
if (obj is null) return obj;
|
||||
short rowId = jobj["row"]?.ToObject<short>() ?? throw new ConvertingException("Cannot read the property row.");
|
||||
if (rowId == -1)
|
||||
{
|
||||
if (obj.Type != EventType.TintRows)
|
||||
{
|
||||
switch (settings.UnreadableEventsHandling)
|
||||
{
|
||||
case UnreadableEventHandling.Store:
|
||||
settings.UnreadableEvents.Add((jobj, $"Cannot find the row with id {rowId}."));
|
||||
return default;
|
||||
case UnreadableEventHandling.ThrowException:
|
||||
throw new ConvertingException($"Cannot find the row \"{jobj["target"]}\" at {obj}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rowId >= level.Rows.Count)
|
||||
{
|
||||
switch (settings.UnreadableEventsHandling)
|
||||
{
|
||||
case UnreadableEventHandling.Store:
|
||||
settings.UnreadableEvents.Add((jobj, $"The row id {rowId} out of range."));
|
||||
return default;
|
||||
case UnreadableEventHandling.ThrowException:
|
||||
throw new ConvertingException($"The row id {rowId} out of range.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RowEventCollection Parent = level.ModifiableRows[(int)rowId];
|
||||
obj._parent = Parent;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Utils;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class BookmarkConverter(BeatCalculator calculator) : JsonConverter<Bookmark>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, Bookmark? value, JsonSerializer serializer)
|
||||
{
|
||||
var beat = value?.Beat.BarBeat ??throw new RhythmBase.Exceptions.ConvertingException("Cannot write the bookmark.");
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName("bar");
|
||||
writer.WriteValue(beat.bar);
|
||||
writer.WritePropertyName("beat");
|
||||
writer.WriteValue(beat.beat);
|
||||
writer.WritePropertyName("color");
|
||||
writer.WriteValue((int)value.Color);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
public override Bookmark ReadJson(JsonReader reader, Type objectType, Bookmark? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
JToken jobj = JToken.ReadFrom(reader);
|
||||
return new Bookmark
|
||||
{
|
||||
Beat = calculator.BeatOf(jobj["bar"]!.ToObject<uint>(), jobj["beat"]!.ToObject<float>()),
|
||||
Color = Enum.Parse<Bookmark.BookmarkColors>((string)jobj["color"]!)
|
||||
};
|
||||
}
|
||||
|
||||
private readonly BeatCalculator calculator = calculator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class CharacterConverter : JsonConverter<RDCharacter>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, RDCharacter value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue(
|
||||
value.IsCustom
|
||||
? value.CustomCharacter == null
|
||||
? ""
|
||||
: $"custom:{value.CustomCharacter}"
|
||||
: value.Character.ToString());
|
||||
}
|
||||
|
||||
public override RDCharacter ReadJson(JsonReader reader, Type objectType, RDCharacter existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
string value = JToken.ReadFrom(reader).ToObject<string>()!;
|
||||
RDCharacter ReadJson;
|
||||
if (value.StartsWith("custom:"))
|
||||
{
|
||||
string name = value[7..];
|
||||
ReadJson = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadJson = Enum.Parse<RDCharacters>(value);
|
||||
}
|
||||
return ReadJson;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class ColorConverter : JsonConverter<RDColor>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, RDColor value, JsonSerializer serializer) => writer.WriteValue(value.ToString("rrggbbaa"));
|
||||
|
||||
public override RDColor ReadJson(JsonReader reader, Type objectType, RDColor existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
string JString = JToken.Load(reader).Value<string>() ?? throw new RhythmBase.Exceptions.ConvertingException("Cannot read the color.");
|
||||
return RDColor.FromRgba(JString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using System.Text.RegularExpressions;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal partial class ConditionConverter(List<BaseConditional> Conditionals) : JsonConverter<Condition>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, Condition? value, JsonSerializer serializer) => writer.WriteValue(value!.Serialize());
|
||||
public override Condition ReadJson(JsonReader reader, Type objectType, Condition? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
string s = JToken.Load(reader).ToObject<string>()!;
|
||||
Condition Value = new();
|
||||
//MatchCollection ConditionIds = ConditionsRegex().Matches(J);
|
||||
//foreach (Match match in ConditionIds)
|
||||
//{
|
||||
// BaseConditional Parent = (from i in conditionals
|
||||
// where i.Id == int.Parse(ConditionIndexRegex().Match(match.Value).Value)
|
||||
// select i).First();
|
||||
// Value.ConditionLists.Add(new ValueTuple<bool, BaseConditional>(match.Value[0] != '~', Parent));
|
||||
//}
|
||||
//Value.Duration = float.Parse (ConditionDurationRegex().Match(J).Value);
|
||||
int p = 0;
|
||||
do
|
||||
{
|
||||
bool active = ReadActive(s, ref p);
|
||||
int index = ReadInt(s, ref p) - 1;
|
||||
if (index < conditionals.Count)
|
||||
{
|
||||
Value.ConditionLists.Add((active, conditionals[index]));
|
||||
}
|
||||
}
|
||||
while (!ReadIsEndList(s, ref p));
|
||||
Value.Duration = ReadFloat(s, ref p);
|
||||
|
||||
return Value;
|
||||
}
|
||||
private static int ReadInt(string s, ref int p)
|
||||
{
|
||||
int r = 0;
|
||||
while (p < s.Length && char.IsAsciiDigit(s[p]))
|
||||
{
|
||||
r *= 10;
|
||||
r += s[p] - '0';
|
||||
p++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
private static float ReadFloat(string s, ref int p)
|
||||
{
|
||||
float r = ReadInt(s, ref p);
|
||||
if (p < s.Length && s[p] == '.')
|
||||
{
|
||||
p++;
|
||||
float f = 0.1f;
|
||||
while (p < s.Length && char.IsAsciiDigit(s[p]))
|
||||
{
|
||||
r += f * (s[p] - '0');
|
||||
f *= 0.1f;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
private static bool ReadActive(string s, ref int p)
|
||||
{
|
||||
if (p >= s.Length || s[p] == '~')
|
||||
{
|
||||
p++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool ReadIsEndList(string s, ref int p) => p < s.Length && s[p++] == 'd';
|
||||
|
||||
private readonly List<BaseConditional> conditionals = Conditionals;
|
||||
[GeneratedRegex("~?\\d+(?=[&d])")]
|
||||
private static partial Regex ConditionsRegex();
|
||||
[GeneratedRegex("\\d+")]
|
||||
private static partial Regex ConditionIndexRegex();
|
||||
[GeneratedRegex("(?<=d)[\\d\\.]+")]
|
||||
private static partial Regex ConditionDurationRegex();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class ConditionalConverter : JsonConverter<BaseConditional>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, BaseConditional? value, JsonSerializer serializer) => writer.WriteRawValue(JsonConvert.SerializeObject(value, new JsonSerializerSettings
|
||||
{
|
||||
Converters = { new StringEnumConverter() },
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
}));
|
||||
|
||||
public override BaseConditional ReadJson(JsonReader reader, Type objectType, BaseConditional? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
JObject J = JObject.Load(reader);
|
||||
Type? SubClassType = Type.GetType($"{typeof(BaseConditional).Namespace}.Conditions.{J["type"]}Condition");
|
||||
return SubClassType == null
|
||||
? throw new Exceptions.ConvertingException(J, new Exception($"Unreadable condition: \"{J["type"]}\". path \"{reader.Path}\""))
|
||||
: (BaseConditional)J.ToObject(SubClassType)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class CustomDecorationEventConverter(RDLevel level, LevelReadOrWriteSettings inputSettings) : BaseDecorationActionConverter<CustomDecorationEvent>(level, inputSettings)
|
||||
{
|
||||
public override CustomDecorationEvent? GetDeserializedObject(JObject jobj, Type objectType, CustomDecorationEvent? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
CustomDecorationEvent? result = base.GetDeserializedObject(jobj, objectType, existingValue, hasExistingValue, serializer);
|
||||
if (result != null)
|
||||
result.Data = jobj;
|
||||
return result;
|
||||
}
|
||||
|
||||
public override JObject SetSerializedObject(CustomDecorationEvent value, JsonSerializer serializer)
|
||||
{
|
||||
JObject jobj = base.SetSerializedObject(value, serializer);
|
||||
JToken data = value.Data.DeepClone();
|
||||
foreach (KeyValuePair<string, JToken?> item in jobj)
|
||||
{
|
||||
data[item.Key] = item.Value;
|
||||
}
|
||||
return (JObject)data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class CustomEventConverter(RDLevel level, LevelReadOrWriteSettings inputSettings) : BaseEventConverter<CustomEvent>(level, inputSettings)
|
||||
{
|
||||
public override CustomEvent? GetDeserializedObject(JObject jobj, Type objectType, CustomEvent? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
CustomEvent? result = base.GetDeserializedObject(jobj, objectType, existingValue, hasExistingValue, serializer);
|
||||
if(result == null) return null;
|
||||
result.Data = jobj;
|
||||
return result;
|
||||
}
|
||||
|
||||
public override JObject SetSerializedObject(CustomEvent value, JsonSerializer serializer)
|
||||
{
|
||||
JObject jobj = base.SetSerializedObject(value, serializer);
|
||||
JObject data = (JObject)value.Data.DeepClone();
|
||||
foreach (KeyValuePair<string, JToken?> item in data)
|
||||
{
|
||||
jobj[item.Key] = item.Value;
|
||||
}
|
||||
return jobj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class CustomRowEventConverter(RDLevel level, LevelReadOrWriteSettings inputSettings) : BaseRowActionConverter<CustomRowEvent>(level, inputSettings)
|
||||
{
|
||||
public override CustomRowEvent? GetDeserializedObject(JObject jobj, Type objectType, CustomRowEvent? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
CustomRowEvent? result = base.GetDeserializedObject(jobj, objectType, existingValue, hasExistingValue, serializer);
|
||||
if (result == null) return null;
|
||||
result.Data = jobj;
|
||||
return result;
|
||||
}
|
||||
|
||||
public override JObject SetSerializedObject(CustomRowEvent value, JsonSerializer serializer)
|
||||
{
|
||||
JObject jobj = base.SetSerializedObject(value, serializer);
|
||||
JToken data = value.Data.DeepClone();
|
||||
foreach (KeyValuePair<string, JToken?> item in jobj)
|
||||
{
|
||||
data[item.Key] = item.Value;
|
||||
}
|
||||
return (JObject)data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using RhythmBase.Components.RichText;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class DialogueListConverter : JsonConverter<RDDialogueExchange>
|
||||
{
|
||||
public override RDDialogueExchange? ReadJson(JsonReader reader, Type objectType, RDDialogueExchange? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, RDDialogueExchange? value, JsonSerializer serializer) => writer.WriteRawValue(value?.Serialize());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Extensions;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class ExpressionConverter : JsonConverter<RDExpression>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, RDExpression value, JsonSerializer serializer)
|
||||
{
|
||||
if (value.IsNumeric)
|
||||
{
|
||||
writer.WriteRawValue(value.NumericValue.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value.ExpressionValue.IsNullOrEmpty())
|
||||
{
|
||||
writer.WriteNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteValue(string.Format("{{{0}}}", value.ExpressionValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override RDExpression ReadJson(JsonReader reader, Type objectType, RDExpression existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
string js = JToken.ReadFrom(reader).ToObject<string>() ?? throw new RhythmBase.Exceptions.ConvertingException("Cannot read the expression.");
|
||||
RDExpression ReadJson = new(js.TrimStart('{').TrimEnd('}'));
|
||||
return ReadJson;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class MilliSecondConverter : TimeConverter
|
||||
{
|
||||
public MilliSecondConverter() : base(TimeType.MiliSecond)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Extensions;
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal partial class PanelColorConverter : JsonConverter<PaletteColor>
|
||||
{
|
||||
internal PanelColorConverter(RDColor[] list)
|
||||
{
|
||||
parent = list;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, PaletteColor? value, JsonSerializer serializer)
|
||||
{
|
||||
if (value?.EnablePanel ?? throw new NotImplementedException())
|
||||
{
|
||||
writer.WriteValue(string.Format("pal{0}", value.PaletteIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
string s = value.Value.ToString().Replace("#", "");
|
||||
string alpha = s[..2];
|
||||
string rgb = s[2..];
|
||||
if (value.EnableAlpha)
|
||||
{
|
||||
writer.WriteValue(rgb + alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteValue(rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override PaletteColor ReadJson(JsonReader reader, Type objectType, PaletteColor? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
JToken token = JToken.Load(reader);
|
||||
string? JString = token.Value<string>();
|
||||
if (JString.IsNullOrEmpty())
|
||||
{
|
||||
throw new Exceptions.ConvertingException(token, new Exception($"Unreadable color: \"{token}\". path \"{reader.Path}\""));
|
||||
}
|
||||
Match reg = PaletteColorRegex().Match(JString);
|
||||
existingValue!.parent = parent;
|
||||
if (reg.Success)
|
||||
{
|
||||
existingValue.PaletteIndex = int.Parse(reg.Groups[1].Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
string s = JString.Replace("#", "");
|
||||
string alpha = "";
|
||||
if (s.Length > 6)
|
||||
{
|
||||
alpha = s[6..];
|
||||
}
|
||||
string rgb = s[..6];
|
||||
if (s.Length > 6)
|
||||
{
|
||||
existingValue.Color = new RDColor?(RDColor.FromArgb(alpha + rgb));
|
||||
}
|
||||
else
|
||||
{
|
||||
existingValue.Color = new RDColor?(RDColor.FromRgba(rgb));
|
||||
}
|
||||
}
|
||||
return existingValue;
|
||||
}
|
||||
|
||||
private readonly RDColor[] parent;
|
||||
|
||||
[GeneratedRegex("pal(\\d+)")]
|
||||
private static partial Regex PaletteColorRegex();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class PatternConverter : JsonConverter<Patterns[]>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, Patterns[]? value, JsonSerializer serializer) => writer.WriteValue(Utils.Utils.GetPatternString(value ?? throw new RhythmBase.Exceptions.ConvertingException($"Pattern cannot be null.")));
|
||||
|
||||
public override Patterns[] ReadJson(JsonReader reader, Type objectType, Patterns[]? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
string? pattern = JToken.ReadFrom(reader).ToObject<string>();
|
||||
if (pattern == null || pattern.Length != 6)
|
||||
throw new Exceptions.ConvertingException($"Invalid pattern: {pattern}");
|
||||
existingValue ??= new Patterns[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
existingValue[i] = pattern[i] switch
|
||||
{
|
||||
'x' => Patterns.X,
|
||||
'u' => Patterns.Up,
|
||||
'd' => Patterns.Down,
|
||||
'b' => Patterns.Banana,
|
||||
'r' => Patterns.Return,
|
||||
'-' => Patterns.None,
|
||||
_ => throw new Exceptions.ConvertingException($"Invalid pattern character: {pattern[i]}")
|
||||
};
|
||||
}
|
||||
return existingValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Extensions;
|
||||
using System.Reflection;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class RDContractResolver : DefaultContractResolver
|
||||
{
|
||||
public static RDContractResolver Instance { get; } = new RDContractResolver();
|
||||
public RDContractResolver() : base()
|
||||
{
|
||||
NamingStrategy = new CamelCaseNamingStrategy();
|
||||
}
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
|
||||
{
|
||||
JsonProperty p = base.CreateProperty(member, memberSerialization);
|
||||
Predicate<object>? f = null;
|
||||
if (p.DeclaringType == typeof(RowEventCollection))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(RowEventCollection.RowToMimic) => i => ((RowEventCollection)i).RowToMimic >= 0,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType?.IsAssignableTo(typeof(BaseEvent)) == true)
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(BaseEvent.Active) => i => !((BaseEvent)i).Active,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(MoveRow))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(MoveRow.CustomPosition) => i => ((MoveRow)i).Target == MoveRow.Targets.WholeRow,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(SetVFXPreset))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(SetVFXPreset.Enable) => i => (i is SetVFXPreset e) && e.Preset is not SetVFXPreset.Presets.DisableAll,
|
||||
nameof(SetVFXPreset.Threshold) => i => (i is SetVFXPreset e) && e.Enable && e.Preset == SetVFXPreset.Presets.Bloom,
|
||||
nameof(SetVFXPreset.Intensity) => i => (i is SetVFXPreset e) && e.Enable && durationPresets.Contains(e.Preset) && e.Preset is not (SetVFXPreset.Presets.TileN or SetVFXPreset.Presets.CustomScreenScroll),
|
||||
nameof(SetVFXPreset.Color) => i => (i is SetVFXPreset e) && e.Enable && (e.Preset is SetVFXPreset.Presets.Bloom or SetVFXPreset.Presets.Tutorial),
|
||||
nameof(SetVFXPreset.FloatX) or
|
||||
nameof(SetVFXPreset.FloatY) => i => (i is SetVFXPreset e) && e.Enable && (e.Preset is SetVFXPreset.Presets.TileN or SetVFXPreset.Presets.CustomScreenScroll),
|
||||
nameof(SetVFXPreset.Ease) => i => (i is SetVFXPreset e) && e.Enable && durationPresets.Contains(e.Preset),
|
||||
nameof(SetVFXPreset.Duration) => i => (i is SetVFXPreset e) && e.Enable && durationPresets.Contains(e.Preset),
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(TintRows))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(TintRows.Ease) or nameof(TintRows.Duration) => i => (i is TintRows e) && e.Duration != 0f,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(Tint))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(Tint.Ease) or nameof(Tint.Duration) => i => (i is Tint e) && e.Duration != 0f,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(Tile))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(Tile.TilingType) => i => (i is Tile e) && e.Speed is not null,
|
||||
nameof(Tile.Interval) => i => (i is Tile e) && e.TilingType == Tile.TilingTypes.Pulse,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(SoundSubType))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(SoundSubType.Filename) or
|
||||
nameof(SoundSubType.Pan) or
|
||||
nameof(SoundSubType.Offset) => i => (i is SoundSubType e) && e.Used,
|
||||
nameof(SoundSubType.Volume) => i => (i is SoundSubType e) && e.Used && e.Volume != 100,
|
||||
nameof(SoundSubType.Pitch) => i => (i is SoundSubType e) && e.Used && e.Pitch != 100,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(SetGameSound))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(SetGameSound.Filename) or
|
||||
nameof(SetGameSound.Pan) or
|
||||
nameof(SetGameSound.Offset) => i => (i is SetGameSound e) &&
|
||||
e.SoundType is not (
|
||||
SoundTypes.ClapSoundHold or
|
||||
SoundTypes.FreezeshotSound or
|
||||
SoundTypes.BurnshotSound),
|
||||
nameof(SetGameSound.Volume) => i => (i is SetGameSound e) &&
|
||||
e.SoundType is not (
|
||||
SoundTypes.ClapSoundHold or
|
||||
SoundTypes.FreezeshotSound or
|
||||
SoundTypes.BurnshotSound) && e.Volume != 100,
|
||||
nameof(SetGameSound.Pitch) => i => (i is SetGameSound e) &&
|
||||
e.SoundType is not (
|
||||
SoundTypes.ClapSoundHold or
|
||||
SoundTypes.FreezeshotSound or
|
||||
SoundTypes.BurnshotSound) && e.Pitch != 100,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(SetCountingSound))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(SetCountingSound.VoiceSource) => i => (i is SetCountingSound e) && e.VoiceSource == SetCountingSound.VoiceSources.Custom,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(AddOneshotBeat))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(AddOneshotBeat.Skipshot) => i => (i is AddOneshotBeat e) && e.Skipshot,
|
||||
nameof(AddOneshotBeat.FreezeBurnMode) => i => (i is AddOneshotBeat e) && e.FreezeBurnMode != null,
|
||||
_ => null
|
||||
};
|
||||
if (p.DeclaringType == typeof(Comment))
|
||||
f = p.PropertyName!.ToUpperCamelCase() switch
|
||||
{
|
||||
nameof(Comment.Target) => i => (i is Comment e) && e.Tab == Tabs.Decorations,
|
||||
_ => null
|
||||
};
|
||||
if (f != null)
|
||||
p.ShouldSerialize = f;
|
||||
return p;
|
||||
}
|
||||
private static readonly SetVFXPreset.Presets[] durationPresets =
|
||||
[
|
||||
SetVFXPreset.Presets.HueShift,
|
||||
SetVFXPreset.Presets.Brightness,
|
||||
SetVFXPreset.Presets.Contrast,
|
||||
SetVFXPreset.Presets.Saturation,
|
||||
SetVFXPreset.Presets.Rain,
|
||||
SetVFXPreset.Presets.Bloom,
|
||||
SetVFXPreset.Presets.TileN,
|
||||
SetVFXPreset.Presets.CustomScreenScroll,
|
||||
SetVFXPreset.Presets.JPEG,
|
||||
SetVFXPreset.Presets.Mosaic,
|
||||
SetVFXPreset.Presets.ScreenWaves,
|
||||
SetVFXPreset.Presets.Grain,
|
||||
SetVFXPreset.Presets.Blizzard,
|
||||
SetVFXPreset.Presets.Drawing,
|
||||
SetVFXPreset.Presets.Aberration,
|
||||
SetVFXPreset.Presets.Blur,
|
||||
SetVFXPreset.Presets.RadialBlur,
|
||||
SetVFXPreset.Presets.Dots,
|
||||
SetVFXPreset.Presets.Tutorial,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Exceptions;
|
||||
using RhythmBase.Extensions;
|
||||
using RhythmBase.Settings;
|
||||
using RhythmBase.Utils;
|
||||
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class RDLevelConverter : JsonConverter<RDLevel>
|
||||
{
|
||||
public RDLevelConverter(string location, LevelReadOrWriteSettings settings)
|
||||
{
|
||||
fileLocation = location;
|
||||
this.settings = settings;
|
||||
}
|
||||
public RDLevelConverter(LevelReadOrWriteSettings settings)
|
||||
{
|
||||
this.settings = settings;
|
||||
this.settings.PreloadAssets = false;
|
||||
}
|
||||
public override void WriteJson(JsonWriter writer, RDLevel? value, JsonSerializer serializer)
|
||||
{
|
||||
JsonSerializerSettings AllInOneSerializer = value!.GetSerializer(settings);
|
||||
writer.Formatting = settings.Indented ? Formatting.Indented : Formatting.None;
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName("settings");
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(value!.Settings, Formatting.Indented, AllInOneSerializer));
|
||||
writer.WritePropertyName("rows");
|
||||
writer.WriteStartArray();
|
||||
foreach (RowEventCollection item in value.Rows)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WritePropertyName("decorations");
|
||||
writer.WriteStartArray();
|
||||
foreach (DecorationEventCollection item2 in value.Decorations)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item2, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WritePropertyName("events");
|
||||
writer.WriteStartArray();
|
||||
foreach (IBaseEvent item3 in ((settings.InactiveEventsHandling == InactiveEventsHandling.Retain) ? value.Where(i => i.Active) : value.AsEnumerable()))
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item3, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WritePropertyName("conditionals");
|
||||
writer.WriteStartArray();
|
||||
foreach (BaseConditional item4 in value.Conditionals)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item4, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WritePropertyName("bookmarks");
|
||||
writer.WriteStartArray();
|
||||
foreach (Bookmark item5 in value.Bookmarks)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item5, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WritePropertyName("colorPalette");
|
||||
writer.WriteStartArray();
|
||||
foreach (RDColor item6 in value.ColorPalette)
|
||||
writer.WriteRawValue(JsonConvert.SerializeObject(item6, Formatting.None, AllInOneSerializer));
|
||||
writer.WriteEndArray();
|
||||
writer.WriteEndObject();
|
||||
writer.Close();
|
||||
}
|
||||
public override RDLevel ReadJson(JsonReader reader, Type objectType, RDLevel? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
RDLevel outLevel = new()
|
||||
{
|
||||
_path = fileLocation
|
||||
};
|
||||
JsonSerializer AllInOneSerializer = JsonSerializer.Create(outLevel.GetSerializer(settings));
|
||||
JArray JEvents = [];
|
||||
JArray JBookmarks = [];
|
||||
while (reader.Read())
|
||||
{
|
||||
string name = (string)reader.Value!;
|
||||
reader.Read();
|
||||
switch (name)
|
||||
{
|
||||
case "settings":
|
||||
JObject jobj = JObject.Load(reader);
|
||||
JToken? Mods = jobj["mods"];
|
||||
if (Mods?.Type == JTokenType.String)
|
||||
jobj["mods"] = new JArray(Mods);
|
||||
outLevel.Settings = jobj.ToObject<Components.Settings>(AllInOneSerializer)!;
|
||||
break;
|
||||
case "rows":
|
||||
JArray jarr1 = JArray.Load(reader);
|
||||
outLevel.ModifiableRows.AddRange(jarr1.ToObject<List<RowEventCollection>>(AllInOneSerializer)!);
|
||||
foreach (RowEventCollection row in outLevel.ModifiableRows)
|
||||
{
|
||||
row.Parent = outLevel;
|
||||
}
|
||||
break;
|
||||
case "decorations":
|
||||
JArray jarr2 = JArray.Load(reader);
|
||||
outLevel.ModifiableDecorations.AddRange(jarr2.ToObject<List<DecorationEventCollection>>(AllInOneSerializer)!);
|
||||
foreach (DecorationEventCollection deco in outLevel.ModifiableDecorations)
|
||||
{
|
||||
deco.Parent = outLevel;
|
||||
}
|
||||
break;
|
||||
case "conditionals":
|
||||
JArray jarr3 = JArray.Load(reader);
|
||||
outLevel.Conditionals.AddRange(jarr3.ToObject<List<BaseConditional>>(AllInOneSerializer)!);
|
||||
foreach (BaseConditional condi in outLevel.Conditionals)
|
||||
condi.ParentCollection = outLevel.Conditionals;
|
||||
break;
|
||||
case "colorPalette":
|
||||
JArray jarr4 = JArray.Load(reader);
|
||||
RDColor[] array = jarr4.ToObject<RDColor[]>(AllInOneSerializer) ?? throw new ConvertingException("Cannot read the color palette.");
|
||||
if (array.Length == 21)
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
outLevel.ColorPalette[i] = array[i];
|
||||
break;
|
||||
case "events":
|
||||
JEvents = JArray.Load(reader);
|
||||
break;
|
||||
case "bookmarks":
|
||||
JBookmarks = JArray.Load(reader);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
reader.Close();
|
||||
RDLevel ReadJson;
|
||||
try
|
||||
{
|
||||
List<(FloatingText @event, int id)> FloatingTextCollection = [];
|
||||
List<(AdvanceText @event, int id)> AdvanceTextCollection = [];
|
||||
foreach (JToken item in JEvents)
|
||||
{
|
||||
if (!(settings.InactiveEventsHandling > InactiveEventsHandling.Retain && (item["active"]?.Value<bool>() ?? false)))
|
||||
{
|
||||
Type eventType = Utils.EventTypeUtils.ToType((string)item["type"]!);
|
||||
if (eventType == null)
|
||||
{
|
||||
BaseEvent TempEvent;
|
||||
if (item["target"] != null)
|
||||
TempEvent = item.ToObject<CustomDecorationEvent>(AllInOneSerializer)!;
|
||||
else if (item["row"] != null)
|
||||
TempEvent = item.ToObject<CustomRowEvent>(AllInOneSerializer)!;
|
||||
else
|
||||
TempEvent = item.ToObject<CustomEvent>(AllInOneSerializer)!;
|
||||
if (settings.InactiveEventsHandling == InactiveEventsHandling.Store && !TempEvent.Active)
|
||||
settings.InactiveEvents.Add(TempEvent);
|
||||
else
|
||||
outLevel.Add(TempEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseEvent TempEvent2 = (BaseEvent)item.ToObject(eventType, AllInOneSerializer)!;
|
||||
if (TempEvent2 != null)
|
||||
{
|
||||
if (TempEvent2.Type != EventType.CustomEvent)
|
||||
{
|
||||
EventType type = TempEvent2.Type;
|
||||
switch (type)
|
||||
{
|
||||
case EventType.FloatingText:
|
||||
FloatingTextCollection.Add(((FloatingText)TempEvent2, (int)item["id"]!));
|
||||
break;
|
||||
case EventType.AdvanceText:
|
||||
AdvanceTextCollection.Add(((AdvanceText)TempEvent2, (int)item["id"]!));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (settings.InactiveEventsHandling == InactiveEventsHandling.Store && !TempEvent2.Active)
|
||||
settings.InactiveEvents.Add(TempEvent2);
|
||||
else
|
||||
outLevel.Add(TempEvent2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var (@event, id) in AdvanceTextCollection)
|
||||
{
|
||||
FloatingText Parent = FloatingTextCollection.First(((FloatingText @event, int id) i) => i.id == id).@event;
|
||||
Parent.Children.Add(@event);
|
||||
@event.Parent = Parent;
|
||||
}
|
||||
outLevel.Bookmarks.AddRange(JBookmarks.ToObject<List<Bookmark>>(AllInOneSerializer)!);
|
||||
ReadJson = outLevel;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (outLevel.Settings.Version < 55)
|
||||
throw new VersionTooLowException(outLevel.Settings.Version, ex);
|
||||
throw new ConvertingException(ex);
|
||||
}
|
||||
return ReadJson;
|
||||
}
|
||||
private readonly string fileLocation = "";
|
||||
private readonly LevelReadOrWriteSettings settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Extensions;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class RDPointsConverter : JsonConverter
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
if (value is RDPointNI v1)
|
||||
{
|
||||
writer.WriteValue(v1.X);
|
||||
writer.WriteValue(v1.Y);
|
||||
}
|
||||
else if (value is RDPointN v2)
|
||||
{
|
||||
writer.WriteValue(v2.X);
|
||||
writer.WriteValue(v2.Y);
|
||||
}
|
||||
else if (value is RDPointI v3)
|
||||
{
|
||||
writer.WriteValue(v3.X);
|
||||
writer.WriteValue(v3.Y);
|
||||
}
|
||||
else if (value is RDPoint v4)
|
||||
{
|
||||
writer.WriteValue(v4.X);
|
||||
writer.WriteValue(v4.Y);
|
||||
}
|
||||
else if (value is RDPointE v5)
|
||||
{
|
||||
if (v5.X != null)
|
||||
writer.WriteValue(v5.X.Value.IsNumeric ? v5.X.Value.NumericValue : v5.X.Value.ExpressionValue);
|
||||
else
|
||||
writer.WriteNull();
|
||||
if (v5.Y != null)
|
||||
writer.WriteValue(v5.Y.Value.IsNumeric ? v5.Y.Value.NumericValue : v5.Y.Value.ExpressionValue);
|
||||
else
|
||||
writer.WriteNull();
|
||||
}
|
||||
else if (value is RDSizeNI v6)
|
||||
{
|
||||
writer.WriteValue(v6.Width);
|
||||
writer.WriteValue(v6.Height);
|
||||
}
|
||||
else if (value is RDSizeN v7)
|
||||
{
|
||||
writer.WriteValue(v7.Width);
|
||||
writer.WriteValue(v7.Height);
|
||||
}
|
||||
else if (value is RDSizeI v8)
|
||||
{
|
||||
writer.WriteValue(v8.Width);
|
||||
writer.WriteValue(v8.Height);
|
||||
}
|
||||
else if (value is RDSize v9)
|
||||
{
|
||||
writer.WriteValue(v9.Width);
|
||||
writer.WriteValue(v9.Height);
|
||||
}
|
||||
else if (value is RDSizeE v10)
|
||||
{
|
||||
RDSizeE temp2 = (value != null) ? v10 : default;
|
||||
if (temp2.Width != null)
|
||||
writer.WriteValue(temp2.Width.Value.IsNumeric ? temp2.Width.Value.NumericValue : temp2.Width.Value.ExpressionValue);
|
||||
else
|
||||
writer.WriteNull();
|
||||
if (temp2.Height != null)
|
||||
writer.WriteValue(temp2.Height.Value.IsNumeric ? temp2.Height.Value.NumericValue : temp2.Height.Value.ExpressionValue);
|
||||
else
|
||||
writer.WriteNull();
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
JToken ja = JToken.ReadFrom(reader);
|
||||
object ReadJson;
|
||||
if (objectType == typeof(RDPointNI) || objectType == typeof(RDPointNI?))
|
||||
ReadJson = new RDPointNI(ja[0]!.ToObject<int>(), ja[1]!.ToObject<int>());
|
||||
else if (objectType == typeof(RDPointN) || objectType == typeof(RDPointN?))
|
||||
ReadJson = new RDPointN(ja[0]!.ToObject<float>(), ja[1]!.ToObject<float>());
|
||||
else if (objectType == typeof(RDPointI) || objectType == typeof(RDPointI?))
|
||||
ReadJson = new RDPointI(ja[0]?.ToObject<int?>(), ja[1]?.ToObject<int?>());
|
||||
else if (objectType == typeof(RDPoint) || objectType == typeof(RDPoint?))
|
||||
ReadJson = new RDPoint(ja[0]?.ToObject<float?>(), ja[1]?.ToObject<float?>());
|
||||
else if (objectType == typeof(RDPointE) || objectType == typeof(RDPointE?))
|
||||
ReadJson = new RDPointE(new RDExpression?(ja[0]!.ToString().IsNullOrEmpty()
|
||||
? default
|
||||
: ja[0]!.ToObject<RDExpression>()), new RDExpression?(ja[1]!.ToString().IsNullOrEmpty()
|
||||
? default
|
||||
: ja[1]!.ToObject<RDExpression>()));
|
||||
else if (objectType == typeof(RDSizeNI) || objectType == typeof(RDSizeNI?))
|
||||
ReadJson = new RDSizeNI(ja[0]!.ToObject<int>(), ja[1]!.ToObject<int>());
|
||||
else if (objectType == typeof(RDSizeN) || objectType == typeof(RDSizeN?))
|
||||
ReadJson = new RDSizeN(ja[0]!.ToObject<float>(), ja[1]!.ToObject<float>());
|
||||
else if (objectType == typeof(RDSizeI) || objectType == typeof(RDSizeI?))
|
||||
ReadJson = new RDSizeI(ja[0]?.ToObject<int?>(), ja[1]?.ToObject<int?>());
|
||||
else if (objectType == typeof(RDSize) || objectType == typeof(RDSize?))
|
||||
ReadJson = new RDSize(ja[0]?.ToObject<float?>(), ja[1]?.ToObject<float?>());
|
||||
else if (objectType == typeof(RDSizeE) || objectType == typeof(RDSizeE?))
|
||||
ReadJson = new RDSizeE(new RDExpression?(ja[0]!.ToString().IsNullOrEmpty()
|
||||
? default
|
||||
: ja[0]!.ToObject<RDExpression>()), new RDExpression?(ja[1]!.ToString().IsNullOrEmpty()
|
||||
? default
|
||||
: ja[1]!.ToObject<RDExpression>()));
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
return ReadJson;
|
||||
}
|
||||
public override bool CanConvert(Type objectType) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using Microsoft.VisualBasic.CompilerServices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class RoomConverter : JsonConverter
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||||
{
|
||||
Type type = value!.GetType();
|
||||
if (type == typeof(RDRoom))
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
foreach (int item in (((RDRoom?)value) ?? default).Rooms)
|
||||
writer.WriteValue(item);
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
else if (type == typeof(RDSingleRoom))
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
writer.WriteValue((((RDSingleRoom?)value) ?? default).Value);
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
JToken token = JArray.Load(reader);
|
||||
byte[]? J = token.ToObject<byte[]>();
|
||||
if (J == null)
|
||||
throw new Exceptions.ConvertingException(token, new Exception($"Unreadable room: \"{J}\". path \"{reader.Path}\""));
|
||||
|
||||
bool flag = objectType == typeof(RDRoom);
|
||||
object ReadJson;
|
||||
if (flag)
|
||||
{
|
||||
bool enableTop;
|
||||
if (existingValue != null)
|
||||
{
|
||||
object obj = existingValue;
|
||||
enableTop = ((obj != null) ? ((RDRoom)obj) : default).EnableTop;
|
||||
}
|
||||
else
|
||||
{
|
||||
enableTop = true;
|
||||
}
|
||||
existingValue = new RDRoom(enableTop);
|
||||
foreach (byte item in J)
|
||||
{
|
||||
NewLateBinding.LateIndexSet(existingValue,
|
||||
[
|
||||
item,
|
||||
true
|
||||
], null);
|
||||
}
|
||||
ReadJson = existingValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = objectType == typeof(RDSingleRoom);
|
||||
if (!flag)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
ReadJson = new RDSingleRoom(J.Single());
|
||||
}
|
||||
return ReadJson;
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type objectType) => objectType == typeof(RDRoom) || objectType == typeof(RDSingleRoom);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class SecondConverter : TimeConverter
|
||||
{
|
||||
public SecondConverter() : base(TimeType.Second)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Events;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class TabsConverter : JsonConverter<Tabs>
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, Tabs value, JsonSerializer serializer) => writer.WriteValue(TabNames[(int)value]);
|
||||
|
||||
public override Tabs ReadJson(JsonReader reader, Type objectType, Tabs existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
string value = JToken.Load(reader).ToObject<string>()??throw new RhythmBase.Exceptions.ConvertingException("Cannot read the tab.");
|
||||
int t = TabNames.ToList().IndexOf(value);
|
||||
bool flag = t >= 0;
|
||||
Tabs ReadJson;
|
||||
if (flag)
|
||||
{
|
||||
ReadJson = (Tabs)t;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadJson = Tabs.Unknown;
|
||||
}
|
||||
return ReadJson;
|
||||
}
|
||||
|
||||
private static readonly string[] TabNames =
|
||||
[
|
||||
"Song",
|
||||
"Rows",
|
||||
"Actions",
|
||||
"Sprites",
|
||||
"Rooms"
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using RhythmBase.Components;
|
||||
using RhythmBase.Events;
|
||||
using RhythmBase.Settings;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal class TagActionConverter(RDLevel level, LevelReadOrWriteSettings inputSettings) : BaseEventConverter<TagAction>(level, inputSettings)
|
||||
{
|
||||
public override JObject SetSerializedObject(TagAction value, JsonSerializer serializer)
|
||||
{
|
||||
JObject jobj = base.SetSerializedObject(value, serializer);
|
||||
if (value.Tag == null)
|
||||
{
|
||||
jobj.Remove("tag");
|
||||
}
|
||||
else
|
||||
{
|
||||
jobj["tag"] = value.Tag;
|
||||
}
|
||||
jobj["Tag"] = value.ActionTag;
|
||||
return jobj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
namespace RhythmBase.Converters
|
||||
{
|
||||
internal abstract class TimeConverter : JsonConverter<TimeSpan>
|
||||
{
|
||||
public TimeConverter()
|
||||
{
|
||||
_timeType = TimeType.MiliSecond;
|
||||
}
|
||||
|
||||
public TimeConverter(TimeType type)
|
||||
{
|
||||
_timeType = type;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, TimeSpan value, JsonSerializer serializer)
|
||||
{
|
||||
switch (_timeType)
|
||||
{
|
||||
case TimeType.Hour:
|
||||
writer.WriteValue(value.TotalHours);
|
||||
break;
|
||||
case TimeType.Minute:
|
||||
writer.WriteValue(value.TotalMinutes);
|
||||
break;
|
||||
case TimeType.Second:
|
||||
writer.WriteValue(value.TotalSeconds);
|
||||
break;
|
||||
case TimeType.MiliSecond:
|
||||
writer.WriteValue((int)value.TotalMilliseconds);
|
||||
break;
|
||||
case TimeType.Microsecond:
|
||||
writer.WriteValue((int)value.TotalMicroseconds);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override TimeSpan ReadJson(JsonReader reader, Type objectType, TimeSpan existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
float value = JToken.ReadFrom(reader).ToObject<float>();
|
||||
return _timeType switch
|
||||
{
|
||||
TimeType.Hour => TimeSpan.FromHours((double)value),
|
||||
TimeType.Minute => TimeSpan.FromMinutes((double)value),
|
||||
TimeType.Second => TimeSpan.FromSeconds((double)value),
|
||||
TimeType.MiliSecond => TimeSpan.FromMilliseconds((int)value),
|
||||
TimeType.Microsecond => TimeSpan.FromMicroseconds((int)value),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
|
||||
private readonly TimeType _timeType;
|
||||
|
||||
public enum TimeType
|
||||
{
|
||||
Hour,
|
||||
Minute,
|
||||
Second,
|
||||
MiliSecond,
|
||||
Microsecond
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user