1
0
mirror of synced 2024-11-23 20:10:57 +01:00

added dynamic types

This commit is contained in:
NotImplementedLife 2023-10-01 19:40:41 +03:00
parent c8fbf86afe
commit be0f4c1c4e
70 changed files with 1822 additions and 974 deletions

26
App.config Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

37
Collections/Collection.cs Normal file
View File

@ -0,0 +1,37 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.Json.Serialization;
using TaikoSoundEditor.Commons.IO;
namespace TaikoSoundEditor.Collections
{
public static class Collections
{
public static Collection<T> FromJson<T>(string json, Type expectedItemType)
{
var colType = MakeGeneric(expectedItemType);
Debug.WriteLine(json);
var col = Json.Deserialize(colType, json);
var items = colType.GetProperty("Items").GetValue(col) as IEnumerable;
var result = new Collection<T>();
foreach (var item in items)
{
if (item is T tItem) result.Items.Add(tItem);
else throw new InvalidOperationException("Json parse error");
}
return result;
}
public static Type MakeGeneric(Type type) => typeof(Collection<>).MakeGenericType(type);
}
public class Collection<T>
{
[JsonPropertyName("items")]
public List<T> Items { get; set; } = new List<T>();
}
}

View File

@ -1,13 +1,11 @@
using System.Text.Json.Serialization;
using System.Linq;
using TaikoSoundEditor.Data;
namespace TaikoSoundEditor.Data
namespace TaikoSoundEditor.Collections
{
public class MusicAttributes
public class MusicAttributes : Collection<IMusicAttribute>
{
[JsonPropertyName("items")]
public List<MusicAttribute> Items { get; set; } = new List<MusicAttribute>();
public MusicAttribute GetByUniqueId(int id)
public IMusicAttribute GetByUniqueId(int id)
{
return Items.Find(x => x.UniqueId == id);
}

View File

@ -3,11 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaikoSoundEditor.Data;
namespace TaikoSoundEditor.Utils
namespace TaikoSoundEditor.Collections
{
internal static class Emit
internal class MusicInfos : Collection<IMusicInfo>
{
//public
}
}

View File

@ -0,0 +1,9 @@
using TaikoSoundEditor.Data;
namespace TaikoSoundEditor.Collections
{
internal class MusicOrders : Collection<IMusicOrder>
{
public IMusicOrder GetByUniqueId(int id) => Items.Find(i => i.UniqueId == id);
}
}

11
Collections/WordList.cs Normal file
View File

@ -0,0 +1,11 @@
using TaikoSoundEditor.Data;
namespace TaikoSoundEditor.Collections
{
public class WordList : Collection<IWord>
{
public IWord GetBySong(string song) => Items.Find(i => i.Key == $"song_{song}");
public IWord GetBySongSub(string song) => Items.Find(i => i.Key == $"song_sub_{song}");
public IWord GetBySongDetail(string song) => Items.Find(i => i.Key == $"song_detail_{song}");
}
}

View File

@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons
{
public class FolderPicker
{

View File

@ -1,4 +1,6 @@
namespace TaikoSoundEditor.Controls
using System.Windows.Forms;
namespace TaikoSoundEditor.Commons.Controls
{
partial class MusicOrderViewer
{

View File

@ -1,11 +1,17 @@
using System.Diagnostics;
using System.Drawing.Drawing2D;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Extensions;
using TaikoSoundEditor.Commons.Extensions;
using TaikoSoundEditor.Properties;
using TaikoSoundEditor.Utils;
using TaikoSoundEditor.Commons.Utils;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Linq;
using System;
using TaikoSoundEditor.Collections;
namespace TaikoSoundEditor.Controls
namespace TaikoSoundEditor.Commons.Controls
{
public partial class MusicOrderViewer : UserControl
{
@ -20,9 +26,9 @@ namespace TaikoSoundEditor.Controls
internal WordList WordList { get; set; }
public List<SongCard> SongCards { get; } = new();
public List<SongCard> SongCards { get; } = new List<SongCard>();
public void AddSong(MusicOrder mo)
public void AddSong(IMusicOrder mo)
{
var songCard = new SongCard(WordList, mo);
@ -65,7 +71,7 @@ namespace TaikoSoundEditor.Controls
}
public void RemoveSong(MusicOrder mo)
public void RemoveSong(IMusicOrder mo)
{
SongCards.RemoveAll(c => c.MusicOrder == mo);
Selection.RemoveWhere(c => c.MusicOrder == mo);
@ -218,8 +224,8 @@ namespace TaikoSoundEditor.Controls
Invalidate();
});
public HashSet<SongCard> Selection = new();
public HashSet<SongCard> CutSelection = new();
public HashSet<SongCard> Selection = new HashSet<SongCard>();
public HashSet<SongCard> CutSelection = new HashSet<SongCard>();
private void MusicOrdersPanel_MouseDown(object sender, MouseEventArgs e) => ExceptionGuard.Run(() =>
@ -465,7 +471,7 @@ namespace TaikoSoundEditor.Controls
MusicOrdersPanel.Invalidate();
});
public delegate void OnSongRemoved(MusicOrderViewer sender, MusicOrder mo);
public delegate void OnSongRemoved(MusicOrderViewer sender, IMusicOrder mo);
public event OnSongRemoved SongRemoved;
private void ListStartButton_Click(object sender, EventArgs e)
@ -492,7 +498,7 @@ namespace TaikoSoundEditor.Controls
MusicOrdersPanel.Invalidate();
}
public bool Locate(MusicOrder mo)
public bool Locate(IMusicOrder mo)
{
var card = SongCards.Where(c => c.MusicOrder == mo).FirstOrDefault();
if (card == null) return false;
@ -512,7 +518,7 @@ namespace TaikoSoundEditor.Controls
MusicOrdersPanel.Invalidate();
}
public delegate void OnSongDoubleClick(MusicOrderViewer sender, MusicOrder mo);
public delegate void OnSongDoubleClick(MusicOrderViewer sender, IMusicOrder mo);
public event OnSongDoubleClick SongDoubleClick;
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
@ -568,7 +574,7 @@ namespace TaikoSoundEditor.Controls
var genre = (Genre)Enum.Parse(typeof(Genre), (sender as ToolStripMenuItem).Text);
//MessageBox.Show(genre.ToString());
var newMO = new MusicOrder(CardToClone.MusicOrder);
var newMO = DatatableTypes.Clone(CardToClone.MusicOrder);
newMO.Genre = genre;
AddSong(newMO);
}

View File

@ -1,4 +1,4 @@
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.Controls
{
partial class PathSelector
{

View File

@ -8,7 +8,8 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.Controls
{
[DefaultEvent("PathChanged")]
public partial class PathSelector : UserControl

View File

@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Extensions;
using TaikoSoundEditor.Utils;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Commons.Extensions;
using TaikoSoundEditor.Commons.Utils;
using System.Drawing;
using TaikoSoundEditor.Collections;
namespace TaikoSoundEditor.Controls
namespace TaikoSoundEditor.Commons.Controls
{
public class SongCard
{
internal WordList WordList { get; }
public MusicOrder MusicOrder { get; }
public IMusicOrder MusicOrder { get; }
public string Id => $"{MusicOrder.UniqueId}.{MusicOrder.Id}";
public string Title => WordList.GetBySong(MusicOrder.Id).JapaneseText;
@ -17,7 +17,7 @@ namespace TaikoSoundEditor.Controls
public string Genre => MusicOrder.Genre.ToString();
public Color Color => Constants.GenreColors[MusicOrder.GenreNo.Clamp(0, Constants.GenreColors.Length - 1)];
public SongCard(WordList wordList, MusicOrder musicOrder)
public SongCard(WordList wordList, IMusicOrder musicOrder)
{
WordList = wordList;
MusicOrder = musicOrder;

View File

@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Text.Json.Serialization;
using TaikoSoundEditor.Commons.Extensions;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor.Commons.Emit
{
internal class DatatableEntityTypeBuilder
{
private readonly ModuleBuilder mb;
public DatatableEntityTypeBuilder()
{
var aName = new AssemblyName(DynamicAssemblyName);
AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run);
mb = ab.DefineDynamicModule(aName.Name ?? DynamicAssemblyName);
}
public static Dictionary<string, Type> LoadTypes(DynamicTypeCollection dTypes)
{
var builder = new DatatableEntityTypeBuilder();
var result = new Dictionary<string, Type>();
foreach (var dtype in dTypes.Types)
{
var @interface = Types.GetTypeByName(dtype.Interface);
result[dtype.Name] = builder.BuildType(dtype.Name, @interface, dtype.Properties.Select(_ => _.CreatePropertyInfo()));
}
return result;
}
public Type BuildType(string name, Type @interface, IEnumerable<EntityPropertyInfo> properties)
{
TypeBuilder tb = @interface == null
? mb.DefineType(name, TypeAttributes.Public)
//: mb.DefineType(name, TypeAttributes.Public);
: mb.DefineType(name, TypeAttributes.Public, null, new Type[] { @interface });
ConstructorBuilder ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
ILGenerator ctorIL = ctor.GetILGenerator();
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
properties.ForEach(GeneratePropertyAction(tb, ctorIL));
ctorIL.Emit(OpCodes.Ret);
if(@interface!=null)
{
Debug.WriteLine("ERE??");
var recastedProps = @interface.GetProperties()
.Where(p => p.GetCustomAttribute<RecastAttribute>() != null)
.ToArray();
Debug.WriteLine(recastedProps.Length);
foreach(var prop in recastedProps)
{
Debug.WriteLine($"Recasted : {prop} ");
GenerateRecastedProperty(tb, prop, prop.GetCustomAttribute<RecastAttribute>().PropertyName);
}
}
var type = tb.CreateType();
/*var methods = tb.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.GetProperty);
foreach (var m in methods)
Debug.WriteLine(m);*/
return type;
}
private Action<EntityPropertyInfo> GeneratePropertyAction(TypeBuilder tb, ILGenerator ilg) => _ => GenerateProperty(tb, ilg, _);
private static Expression GetProperty(Expression instance, Type classType, string name)
{
var getProperty = typeof(Type).GetMethods().Where(m => m.Name == "GetProperty" && m.GetParameters().Length == 1).First();
var getValueMethod = typeof(PropertyInfo).GetMethods().Where(m => m.Name == "GetValue" && m.GetParameters().Length == 1).First();
var propInfo = Expression.Call(Expression.Constant(classType), getProperty, Expression.Constant(name));
Debug.WriteLine(propInfo);
var call = Expression.Call(propInfo, getValueMethod, instance);
Debug.WriteLine(call);
return call;
}
public static LambdaExpression ConvertGetExpr<T>(string castSourceName)
{
var param = Expression.Parameter(typeof(object));
var getType = typeof(object).GetMethods().Where(m => m.Name == "GetType" && m.GetParameters().Length == 0).First();
var getProperty = typeof(Type).GetMethods().Where(m => m.Name == "GetProperty" && m.GetParameters().Length == 1).First();
var getValue = typeof(PropertyInfo).GetMethods().Where(m => m.Name == "GetValue" && m.GetParameters().Length == 1).First();
var getTypeExpr = Expression.Call(param, getType);
var getPropertyExpr = Expression.Call(getTypeExpr, getProperty, Expression.Constant(castSourceName));
var getValueExpr = Expression.Call(getPropertyExpr, getValue, param);
return Expression.Lambda(Expression.Convert(getValueExpr, typeof(T)), param);
}
public static LambdaExpression ConvertSetExpr<T>(string castSourceName, PropertyInfo prop)
{
Debug.WriteLine("HERE?");
Debug.WriteLine(prop);
var param0 = Expression.Parameter(typeof(object));
var param1 = Expression.Parameter(typeof(T));
var getType = typeof(object).GetMethods().Where(m => m.Name == "GetType" && m.GetParameters().Length == 0).First();
var getProperty = typeof(Type).GetMethods().Where(m => m.Name == "GetProperty" && m.GetParameters().Length == 1).First();
var setValue = typeof(PropertyInfo).GetMethods().Where(m => m.Name == "SetValue" && m.GetParameters().Length == 2).First();
var changeType = typeof(Convert).GetMethods().Where(m => m.Name == "ChangeType" && m.GetParameters().Length == 2
&& m.GetParameters()[1].ParameterType == typeof(Type)).First();
var getTypeExpr = Expression.Call(param0, getType);
var getPropertyExpr = Expression.Call(getTypeExpr, getProperty, Expression.Constant(castSourceName));
var propertyTypeExpr = Expression.Property(getPropertyExpr, "PropertyType");
var converted = Expression.Convert(param1, typeof(object));
var changeTypeExpr = Expression.Call(changeType, converted, propertyTypeExpr);
Debug.WriteLine(getPropertyExpr);
Debug.WriteLine(changeTypeExpr);
var setValueExpr = Expression.Call(getPropertyExpr, setValue, param0, changeTypeExpr);
Debug.WriteLine(setValueExpr);
var returnLabel = Expression.Label(typeof(void));
return Expression.Lambda(Expression
.Block(setValueExpr, Expression.Return(returnLabel), Expression.Label(returnLabel)), param0, param1);
}
static MethodInfo ConvertGetExprMethod(Type t) =>
typeof(DatatableEntityTypeBuilder).GetMethod("ConvertGetExpr", BindingFlags.Static | BindingFlags.Public)
.MakeGenericMethod(t);
static MethodInfo ConvertSetExprMethod(Type t) =>
typeof(DatatableEntityTypeBuilder).GetMethod("ConvertSetExpr", BindingFlags.Static | BindingFlags.Public)
.MakeGenericMethod(t);
private void GenerateRecastedProperty(TypeBuilder tb, PropertyInfo prop, string castSourceName)
{
PropertyBuilder pb = tb.DefineProperty(prop.Name, PropertyAttributes.HasDefault, prop.PropertyType, null);
if (prop.GetCustomAttribute<JsonIgnoreAttribute>() != null)
pb.SetCustomAttribute(new CustomAttributeBuilder(typeof(JsonIgnoreAttribute).GetConstructor(new Type[0]), new object[0]));
MethodBuilder mbGetAccessor = tb.DefineMethod($"get_{prop.Name}", GetSetAttr, prop.PropertyType, Type.EmptyTypes);
var cvGetExpr = ConvertGetExprMethod(prop.PropertyType).Invoke(null, new object[] { castSourceName }) as LambdaExpression;
var m = tb.DefineMethod($"RecastGet{prop.Name}", MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard,
prop.PropertyType, new Type[] { typeof(object) });
Debug.WriteLine(cvGetExpr);
cvGetExpr.CompileToMethod(m);
var il = mbGetAccessor.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, m);
il.Emit(OpCodes.Ret);
pb.SetGetMethod(mbGetAccessor);
MethodBuilder mbSetAccessor = tb.DefineMethod($"set_{prop.Name}", GetSetAttr, null, new Type[] { prop.PropertyType });
var cvSetExpr = ConvertSetExprMethod(prop.PropertyType).Invoke(null, new object[] { castSourceName, prop }) as LambdaExpression;
m = tb.DefineMethod($"RecastSet{prop.Name}", MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard,
typeof(void), new Type[] { typeof(object), prop.PropertyType });
cvSetExpr.CompileToMethod(m);
il = mbSetAccessor.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, m);
il.Emit(OpCodes.Ret);
pb.SetSetMethod(mbSetAccessor);
}
private void GenerateProperty(TypeBuilder tb, ILGenerator ilg, EntityPropertyInfo property)
{
FieldBuilder fb = tb.DefineField($"m_{property.Name}", property.Type, FieldAttributes.Private);
if (property.DefaultValue != null)
{
var vType = property.DefaultValue.GetType();
var returnLabel = Expression.Label(vType);
var expr = Expression.Lambda(
Expression.Block(
Expression.Return(returnLabel, Expression.Constant(property.DefaultValue)),
Expression.Label(returnLabel, Expression.Constant(property.DefaultValue))
)
);
var m = tb.DefineMethod($"Initialize{property.Name}", MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard,
vType, Type.EmptyTypes);
expr.CompileToMethod(m);
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Call, m);
ilg.Emit(OpCodes.Stfld, fb);
}
PropertyBuilder pb = tb.DefineProperty(property.Name, PropertyAttributes.HasDefault, property.Type, null);
MethodBuilder mbGetAccessor = tb.DefineMethod($"get_{property.Name}", GetSetAttr, property.Type, Type.EmptyTypes);
ILGenerator getIL = mbGetAccessor.GetILGenerator();
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, fb);
getIL.Emit(OpCodes.Ret);
MethodBuilder mbSetAccessor = tb.DefineMethod($"set_{property.Name}", GetSetAttr, null, new Type[] { property.Type });
ILGenerator mbSetIL = mbSetAccessor.GetILGenerator();
mbSetIL.Emit(OpCodes.Ldarg_0);
mbSetIL.Emit(OpCodes.Ldarg_1);
mbSetIL.Emit(OpCodes.Stfld, fb);
mbSetIL.Emit(OpCodes.Ret);
pb.SetGetMethod(mbGetAccessor);
pb.SetSetMethod(mbSetAccessor);
if (property.JsonPropertyName != null)
AddAttribute(pb, typeof(JsonPropertyNameAttribute), property.JsonPropertyName);
if (property.IsReadOnly)
AddAttribute(pb, typeof(ReadOnlyAttribute), true);
}
private static void AddAttribute(PropertyBuilder pb, Type attributeType, params object[] args)
{
var ctor = (from c in attributeType.GetConstructors()
let pms = c.GetParameters()
where pms.Length == args.Length
where pms.Select(_ => _.ParameterType).Zip(args, (p, a) =>
a == null ? p.IsClass : p.IsAssignableFrom(a.GetType())).All(_ => _)
select c).FirstOrDefault();
Debug.WriteLine(ctor?.ToString() ?? "ctor null");
pb.SetCustomAttribute(new CustomAttributeBuilder(ctor, args));
}
private static readonly MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Virtual;
private static readonly string DynamicAssemblyName = "TSEDynEntities";
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Commons.Emit
{
internal class DynamicType
{
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("properties")] public EntityPropertyInfoDTO[] Properties { get; set; }
[JsonPropertyName("interface")] public string Interface { get; set; } = null;
public DynamicType() { }
public DynamicType(string name, Type @interface, IEnumerable<EntityPropertyInfoDTO> properties)
{
Name = name;
Interface = @interface.FullName;
Properties = properties.ToArray();
}
}
internal class DynamicTypeCollection
{
[JsonPropertyName("types")]
public DynamicType[] Types { get; set; }
public DynamicTypeCollection() { }
public DynamicTypeCollection(params DynamicType[] types)
{
Types = types;
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Text.Json.Serialization;
namespace TaikoSoundEditor.Commons.Emit
{
internal class EntityPropertyInfo
{
public string Name { get; }
public Type Type { get; }
public string JsonPropertyName { get; }
public bool IsReadOnly { get; }
public object DefaultValue { get; }
public EntityPropertyInfo(string name, Type type, string jsonPropertyName = null, bool isReadOnly = false, object defaultValue = null)
{
Name = name;
Type = type;
JsonPropertyName = jsonPropertyName ?? char.ToLower(Name[0]) + Name.Substring(1);
IsReadOnly = isReadOnly;
DefaultValue = defaultValue;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Linq;
using System.Reflection;
using System.Text.Json.Serialization;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor.Commons.Emit
{
internal class EntityPropertyInfoDTO
{
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("type")] public string Type { get; set; }
[JsonPropertyName("jsonName")] public string JsonName { get; set; }
[JsonPropertyName("isReadOnly")] public bool IsReadOnly { get; set; } = false;
[JsonPropertyName("defaultValue")] public string DefaultValue { get; set; } = null;
public static EntityPropertyInfoDTO FromPropertyInfo(EntityPropertyInfo p)
=> new EntityPropertyInfoDTO
{
Name = p.Name,
Type = p.Type.Name,
JsonName = p.JsonPropertyName,
IsReadOnly = p.IsReadOnly,
DefaultValue = p.DefaultValue?.ToString() ?? null
};
public EntityPropertyInfo CreatePropertyInfo()
{
var type = Types.GetTypeByName(Type);
if (type == null)
throw new InvalidOperationException($"Cannot find type `{Type}`");
return new EntityPropertyInfo(Name, type, JsonName, IsReadOnly, GetDefaultValue(type, DefaultValue));
}
private static object GetDefaultValue(Type type, string valStr)
{
if (valStr == null) return type.IsValueType ? Activator.CreateInstance(type) : null;
if (type == typeof(int)) return int.Parse(valStr);
if (type == typeof(uint)) return uint.Parse(valStr);
if (type == typeof(short)) return short.Parse(valStr);
if (type == typeof(ushort)) return ushort.Parse(valStr);
if (type == typeof(string)) return valStr;
if (type == typeof(bool)) return (valStr.ToLower() == "true" || valStr == "1") ? true : false;
if (type == typeof(double)) return double.Parse(valStr);
throw new InvalidOperationException($"Cannot decode default value of type {type}");
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace TaikoSoundEditor.Commons.Extensions
{
internal static class EnumerableExtensions
{
/*public static IEnumerable<T> Prepend<T>(this IEnumerable<T> items, T item)
{
yield return item;
foreach (var i in items) yield return i;
}*/
public static void ForEach<T>(this IEnumerable<T> items, Action<T> a)
{
foreach (var item in items) a(item);
}
}
}

View File

@ -1,4 +1,4 @@
namespace TaikoSoundEditor.Extensions
namespace TaikoSoundEditor.Commons.Extensions
{
internal static class IntExtensions
{

View File

@ -0,0 +1,13 @@
using System.Linq;
namespace TaikoSoundEditor.Commons.Extensions
{
internal static class ObjectExtensions
{
public static string ToStringProperties(this object obj)
{
return "{" + string.Join("; ", obj.GetType().GetProperties().Select(p => $"{p.Name}=`{p?.GetValue(obj) ?? "(null)"}`")) + "}";
}
}
}

View File

@ -1,18 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace TaikoSoundEditor.Extensions
namespace TaikoSoundEditor.Commons.Extensions
{
internal static class StringExtensions
{
public static Match Match(this string s, string regex, string options="")
{
var opts = RegexOptions.None;
if (options.Contains('i')) opts |= RegexOptions.IgnoreCase;
if (options.Contains("i")) opts |= RegexOptions.IgnoreCase;
var r = new Regex(regex);

58
Commons/IO/GZ.cs Normal file
View File

@ -0,0 +1,58 @@
using ICSharpCode.SharpZipLib.GZip;
using System.IO;
using System.IO.Compression;
using System.Text;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor.Commons.IO
{
internal class GZ
{
public static string DecompressBytes(byte[] bytes)
{
Logger.Info("GZ Decompressing bytes");
using (MemoryStream ms = new MemoryStream(bytes))
using (GZipStream decompressionStream = new GZipStream(ms, CompressionMode.Decompress))
using (StreamReader reader = new StreamReader(decompressionStream))
return reader.ReadToEnd();
}
public static string DecompressString(string gzPath)
{
Logger.Info("GZ Decompressing string");
using (FileStream originalFileStream = File.OpenRead(gzPath))
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
using (StreamReader reader = new StreamReader(decompressionStream))
return reader.ReadToEnd();
}
public static byte[] DecompressBytes(string gzPath)
{
Logger.Info("GZ Decompressing bytes");
using (FileStream originalFileStream = File.OpenRead(gzPath))
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
using (MemoryStream ms = new MemoryStream())
{
decompressionStream.CopyTo(ms);
return ms.ToArray();
}
}
public static byte[] CompressToBytes(string content)
{
Logger.Info("GZ Compressing bytes");
var uncompressed = Encoding.UTF8.GetBytes(content);
using (MemoryStream outStream = new MemoryStream())
{
using (GZipOutputStream gzoStream = new GZipOutputStream(outStream))
{
gzoStream.SetLevel(5);
gzoStream.Write(uncompressed, 0, uncompressed.Length);
}
return outStream.ToArray();
}
}
}
}

View File

@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.IO
{
internal static class IDSP
{
@ -21,8 +19,7 @@ namespace TaikoSoundEditor
var p = new Process();
p.StartInfo.FileName = Path.GetFullPath(@"Tools\VGAudio\VGAudioCli.exe");
p.StartInfo.ArgumentList.Add(source);
p.StartInfo.ArgumentList.Add(dest);
p.StartInfo.Arguments = ProcessArgs.GetString(source, dest);
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = false;

View File

@ -1,12 +1,22 @@
using System.Diagnostics;
using System.Linq;
using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.IO
{
internal static class Json
{
public static object Deserialize(Type type, string json)
{
var method = typeof(Json).GetMethods().Where(_ => _.Name == "Deserialize" && _.GetParameters().Length == 1)
.First().MakeGenericMethod(type);
return method.Invoke(null, new object[] { json });
}
public static T Deserialize<T>(string json)
{
Logger.Info($"Deserializing {typeof(T)} ({json.Length})");

View File

@ -1,9 +1,11 @@
using System.Diagnostics;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using TaikoSoundEditor.Utils;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.IO
{
internal static class SSL
{

View File

@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using TaikoSoundEditor.Extensions;
using TaikoSoundEditor.Utils;
using static TaikoSoundEditor.TJA;
using TaikoSoundEditor.Commons.Extensions;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.IO
{
internal class TJA
{
@ -448,7 +446,7 @@ namespace TaikoSoundEditor
var p = new Process();
p.StartInfo.FileName = Path.GetFullPath(@"Tools\tja2fumen.exe");
p.StartInfo.ArgumentList.Add(sourcePath);
p.StartInfo.Arguments = sourcePath;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;

View File

@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.IO
{
internal static class WAV
{
@ -16,12 +16,9 @@ namespace TaikoSoundEditor
destPath = Path.GetFullPath(destPath);
var p = new Process();
p.StartInfo.FileName = Path.GetFullPath(@"Tools\sox\sox.exe");
p.StartInfo.ArgumentList.Add(sourcePath);
p.StartInfo.ArgumentList.Add(destPath);
p.StartInfo.ArgumentList.Add("pad");
p.StartInfo.ArgumentList.Add(seconds_before.ToString());
p.StartInfo.ArgumentList.Add("0");
p.StartInfo.Arguments = ProcessArgs.GetString(sourcePath, destPath, "pad", seconds_before.ToString(), "0");
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Utils
namespace TaikoSoundEditor.Commons.Utils
{
public static class Config
{
@ -26,12 +20,19 @@ namespace TaikoSoundEditor.Utils
public static void SetMusicOrderNoSort() => IniFile.Write(MusicOrderSortProperty, MusicOrderSortValueNone);
public static void SetMusicOrderSortByGenre() => IniFile.Write(MusicOrderSortProperty, MusicOrderSortValueGenre);
public static string DatatableDefPath
{
get => IniFile.Read(DatatableDefPathProperty);
set => IniFile.Write(DatatableDefPathProperty, value);
}
public static string MusicOrderSort => IniFile.Read(MusicOrderSortProperty);
public static string MusicOrderSortProperty = "MusicOrderSort";
public static string DatatableDefPathProperty = "DatatableDef";
public static string MusicOrderSortValueNone = "None";
public static string MusicOrderSortValueId = "Id";
public static string MusicOrderSortValueGenre = "Genre";
public static string MusicOrderSortValueGenre = "Genre";
}
}

View File

@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
namespace TaikoSoundEditor.Utils
namespace TaikoSoundEditor.Commons.Utils
{
internal static class Constants
{

View File

@ -1,8 +1,40 @@
namespace TaikoSoundEditor.Utils
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TaikoSoundEditor.Collections;
using TaikoSoundEditor.Commons.IO;
using TaikoSoundEditor.Data;
namespace TaikoSoundEditor.Commons.Utils
{
public class DatatableIO
{
public bool IsEncrypted { get; set; }
public bool IsEncrypted { get; set; }
public T DeserializeCollection<T, I>(string path, Type itemType) where T: new()
{
if (!itemType.GetInterfaces().Any(_ => _ == typeof(I)))
throw new ArgumentException($"Type {itemType} does not implement {typeof(I)}");
var json = IsEncrypted
? GZ.DecompressBytes(SSL.DecryptDatatable(File.ReadAllBytes(path)))
: GZ.DecompressString(path);
var col = new T();
var itemsProp = typeof(T).GetProperty("Items");
var items = itemsProp.GetValue(col);
var addRange = itemsProp.PropertyType.GetMethod("AddRange");
addRange.Invoke(items, new object[] { Collections.Collections.FromJson<I>(json, itemType).Items });
return col;
}
public WordList DeserializeWordList(string path)
{
return DeserializeCollection<WordList, IWord>(path, DatatableTypes.Word);
}
public T Deserialize<T>(string path)
{

View File

@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TaikoSoundEditor.Utils
namespace TaikoSoundEditor.Commons.Utils
{
internal static class ExceptionGuard
{

View File

@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Utils
namespace TaikoSoundEditor.Commons.Utils
{
// https://stackoverflow.com/questions/217902/reading-writing-an-ini-file
public class IniFile // revision 11

View File

@ -1,6 +1,9 @@
using System.Collections;
using System;
using System.Collections;
using System.IO;
using System.Windows.Forms;
namespace TaikoSoundEditor
namespace TaikoSoundEditor.Commons.Utils
{
internal static class Logger
{

View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Utils
namespace TaikoSoundEditor.Commons.Utils
{
internal static class Number
{

View File

@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Linq;
namespace TaikoSoundEditor.Commons.Utils
{
public static class ProcessArgs
{
public static string GetString(params string[] args)
{
return string.Join(" ", args.Select(_ => _.Contains(" ") ? $"\"{_}\"" : _)); // does NOT support "something \" like this"
}
}
}

View File

@ -0,0 +1,14 @@
using System;
namespace TaikoSoundEditor.Commons.Utils
{
[AttributeUsage(AttributeTargets.Property)]
internal class RecastAttribute : Attribute
{
public string PropertyName { get; set; }
public RecastAttribute(string property)
{
PropertyName = property;
}
}
}

18
Commons/Utils/Types.cs Normal file
View File

@ -0,0 +1,18 @@
using System;
using System.Linq;
namespace TaikoSoundEditor.Commons.Utils
{
internal static class Types
{
public static object GetDefaultValue(this Type type)
=> type.IsValueType ? Activator.CreateInstance(type) : null;
public static Type GetTypeByName(string name)
{
return AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic)
.SelectMany(a => a.GetTypes())
.FirstOrDefault(t => t.Name == name || t.FullName == name);
}
}
}

37
Data/IMusicAttribute.cs Normal file
View File

@ -0,0 +1,37 @@
namespace TaikoSoundEditor.Data
{
public interface IMusicAttribute
{
string Id { get; set; }
int UniqueId { get; set; }
bool New { get; set; }
bool CanPlayUra { get; set; }
bool DoublePlay { get; set; }
string Tag1 { get; set; }
string Tag2 { get; set; }
string Tag3 { get; set; }
string Tag4 { get; set; }
string Tag5 { get; set; }
string Tag6 { get; set; }
string Tag7 { get; set; }
string Tag8 { get; set; }
string Tag9 { get; set; }
string Tag10 { get; set; }
string DonBg1p { get; set; }
string DonBg2p { get; set; }
string DancerDai { get; set; }
string Dancer { get; set; }
string DanceNormalBg { get; set; }
string DanceFeverBg { get; set; }
string RendaEffect { get; set; }
string Fever { get; set; }
string DonBg1p1 { get; set; }
string DonBg2p1 { get; set; }
string DancerDai1 { get; set; }
string Dancer1 { get; set; }
string DanceNormalBg1 { get; set; }
string DanceFeverBg1 { get; set; }
string RendaEffect1 { get; set; }
string Fever1 { get; set; }
}
}

64
Data/IMusicInfo.cs Normal file
View File

@ -0,0 +1,64 @@
using System.Text.Json.Serialization;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor.Data
{
public interface IMusicInfo
{
string Id { get; set; }
int UniqueId { get; set; }
int GenreNo { get; set; }
string SongFileName { get; set; }
bool Papamama { get; set; }
bool BranchEasy { get; set; }
bool BranchNormal { get; set; }
bool BranchHard { get; set; }
bool BranchMania { get; set; }
bool BranchUra { get; set; }
int StarEasy { get; set; }
int StarNormal { get; set; }
int StarHard { get; set; }
int StarMania { get; set; }
int StarUra { get; set; }
int ShinutiEasy { get; set; }
int ShinutiNormal { get; set; }
int ShinutiHard { get; set; }
int ShinutiMania { get; set; }
int ShinutiUra { get; set; }
int ShinutiEasyDuet { get; set; }
int ShinutiNormalDuet { get; set; }
int ShinutiHardDuet { get; set; }
int ShinutiManiaDuet { get; set; }
int ShinutiUraDuet { get; set; }
int ShinutiScoreEasy { get; set; }
int ShinutiScoreNormal { get; set; }
int ShinutiScoreHard { get; set; }
int ShinutiScoreMania { get; set; }
int ShinutiScoreUra { get; set; }
int ShinutiScoreEasyDuet { get; set; }
int ShinutiScoreNormalDuet { get; set; }
int ShinutiScoreHardDuet { get; set; }
int ShinutiScoreManiaDuet { get; set; }
int ShinutiScoreUraDuet { get; set; }
int EasyOnpuNum { get; set; }
int NormalOnpuNum { get; set; }
int HardOnpuNum { get; set; }
int ManiaOnpuNum { get; set; }
int UraOnpuNum { get; set; }
double RendaTimeEasy { get; set; }
double RendaTimeNormal { get; set; }
double RendaTimeHard { get; set; }
double RendaTimeMania { get; set; }
double RendaTimeUra { get; set; }
int FuusenTotalEasy { get; set; }
int FuusenTotalNormal { get; set; }
int FuusenTotalHard { get; set; }
int FuusenTotalMania { get; set; }
int FuusenTotalUra { get; set; }
[Recast("GenreNo")]
[JsonIgnore]
Genre Genre { get; set; }
}
}

17
Data/IMusicOrder.cs Normal file
View File

@ -0,0 +1,17 @@
using System.Text.Json.Serialization;
using TaikoSoundEditor.Commons.Utils;
namespace TaikoSoundEditor.Data
{
public interface IMusicOrder
{
int GenreNo { get; set; }
string Id { get; set; }
int UniqueId { get; set; }
int CloseDispType { get; set; }
[JsonIgnore]
[Recast("GenreNo")]
Genre Genre { get; set; }
}
}

9
Data/IWord.cs Normal file
View File

@ -0,0 +1,9 @@
namespace TaikoSoundEditor.Data
{
public interface IWord
{
string Key { get; set; }
string JapaneseText { get; set; }
int JapaneseFontType { get; set; }
}
}

View File

@ -1,52 +0,0 @@
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace TaikoSoundEditor.Data
{
public class MusicAttribute
{
[ReadOnly(true)]
[JsonPropertyName("id")] public string Id { get; set; } = "ABCDEF";
[ReadOnly(true)]
[JsonPropertyName("uniqueId")] public int UniqueId { get; set; }
[JsonPropertyName("new")] public bool New { get; set; } = false;
[JsonPropertyName("canPlayUra")] public bool CanPlayUra { get; set; } = false;
[JsonPropertyName("doublePlay")] public bool DoublePlay { get; set; } = false;
[JsonPropertyName("tag1")] public string Tag1 { get; set; } = "";
[JsonPropertyName("tag2")] public string Tag2 { get; set; } = "";
[JsonPropertyName("tag3")] public string Tag3 { get; set; } = "";
[JsonPropertyName("tag4")] public string Tag4 { get; set; } = "";
[JsonPropertyName("tag5")] public string Tag5 { get; set; } = "";
[JsonPropertyName("tag6")] public string Tag6 { get; set; } = "";
[JsonPropertyName("tag7")] public string Tag7 { get; set; } = "";
[JsonPropertyName("tag8")] public string Tag8 { get; set; } = "";
[JsonPropertyName("tag9")] public string Tag9 { get; set; } = "";
[JsonPropertyName("tag10")] public string Tag10 { get; set; } = "";
[JsonPropertyName("donBg1p")] public string DonBg1p { get; set; } = "";
[JsonPropertyName("donBg2p")] public string DonBg2p { get; set; } = "";
[JsonPropertyName("dancerDai")] public string DancerDai { get; set; } = "";
[JsonPropertyName("dancer")] public string Dancer { get; set; } = "";
[JsonPropertyName("danceNormalBg")] public string DanceNormalBg { get; set; } = "";
[JsonPropertyName("danceFeverBg")] public string DanceFeverBg { get; set; } = "";
[JsonPropertyName("rendaEffect")] public string RendaEffect { get; set; } = "";
[JsonPropertyName("fever")] public string Fever { get; set; } = "";
[JsonPropertyName("donBg1p1")] public string DonBg1p1 { get; set; } = "";
[JsonPropertyName("donBg2p1")] public string DonBg2p1 { get; set; } = "";
[JsonPropertyName("dancerDai1")] public string DancerDai1 { get; set; } = "";
[JsonPropertyName("dancer1")] public string Dancer1 { get; set; } = "";
[JsonPropertyName("danceNormalBg1")] public string DanceNormalBg1 { get; set; } = "";
[JsonPropertyName("danceFeverBg1")] public string DanceFeverBg1 { get; set; } = "";
[JsonPropertyName("rendaEffect1")] public string RendaEffect1 { get; set; } = "";
[JsonPropertyName("fever1")] public string Fever1 { get; set; } = "";
public MusicAttribute Clone()
{
var props = GetType().GetProperties();
var clone = new MusicAttribute();
foreach(var p in props)
p.SetValue(clone, p.GetValue(this));
return clone;
}
}
}

View File

@ -1,86 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Data
{
internal class MusicInfo
{
[ReadOnly(true)]
[JsonPropertyName("id")] public string Id { get; set; } = "ABCDEF";
[ReadOnly(true)]
[JsonPropertyName("uniqueId")] public int UniqueId { get; set; } =0;
[JsonPropertyName("genreNo")] public int GenreNo { get; set; } =0;
[JsonPropertyName("songFileName")] public string SongFileName { get; set; } = "";
[JsonPropertyName("papamama")] public bool Papamama { get; set; } = false;
[JsonPropertyName("branchEasy")] public bool BranchEasy { get; set; } = false;
[JsonPropertyName("branchNormal")] public bool BranchNormal { get; set; } = false;
[JsonPropertyName("branchHard")] public bool BranchHard { get; set; } = false;
[JsonPropertyName("branchMania")] public bool BranchMania { get; set; } = false;
[JsonPropertyName("branchUra")] public bool BranchUra { get; set; } = false;
[JsonPropertyName("starEasy")] public int StarEasy { get; set; } = 0;
[JsonPropertyName("starNormal")] public int StarNormal { get; set; } = 0;
[JsonPropertyName("starHard")] public int StarHard { get; set; } = 0;
[JsonPropertyName("starMania")] public int StarMania { get; set; } = 0;
[JsonPropertyName("starUra")] public int StarUra { get; set; } = 0;
[JsonPropertyName("shinutiEasy")] public int ShinutiEasy { get; set; } = 0;
[JsonPropertyName("shinutiNormal")] public int ShinutiNormal { get; set; } = 0;
[JsonPropertyName("shinutiHard")] public int ShinutiHard { get; set; } = 0;
[JsonPropertyName("shinutiMania")] public int ShinutiMania { get; set; } = 0;
[JsonPropertyName("shinutiUra")] public int ShinutiUra { get; set; } = 0;
[JsonPropertyName("shinutiEasyDuet")] public int ShinutiEasyDuet { get; set; } = 0;
[JsonPropertyName("shinutiNormalDuet")] public int ShinutiNormalDuet { get; set; } = 0;
[JsonPropertyName("shinutiHardDuet")] public int ShinutiHardDuet { get; set; } = 0;
[JsonPropertyName("shinutiManiaDuet")] public int ShinutiManiaDuet { get; set; } = 0;
[JsonPropertyName("shinutiUraDuet")] public int ShinutiUraDuet { get; set; } = 0;
[JsonPropertyName("shinutiScoreEasy")] public int ShinutiScoreEasy { get; set; } = 0;
[JsonPropertyName("shinutiScoreNormal")] public int ShinutiScoreNormal { get; set; } = 0;
[JsonPropertyName("shinutiScoreHard")] public int ShinutiScoreHard { get; set; } = 0;
[JsonPropertyName("shinutiScoreMania")] public int ShinutiScoreMania { get; set; } = 0;
[JsonPropertyName("shinutiScoreUra")] public int ShinutiScoreUra { get; set; } = 0;
[JsonPropertyName("shinutiScoreEasyDuet")] public int ShinutiScoreEasyDuet { get; set; } = 0;
[JsonPropertyName("shinutiScoreNormalDuet")] public int ShinutiScoreNormalDuet { get; set; } = 0;
[JsonPropertyName("shinutiScoreHardDuet")] public int ShinutiScoreHardDuet { get; set; } = 0;
[JsonPropertyName("shinutiScoreManiaDuet")] public int ShinutiScoreManiaDuet { get; set; } = 0;
[JsonPropertyName("shinutiScoreUraDuet")] public int ShinutiScoreUraDuet { get; set; } = 0;
[JsonPropertyName("easyOnpuNum")] public int EasyOnpuNum { get; set; } = 0;
[JsonPropertyName("normalOnpuNum")] public int NormalOnpuNum { get; set; } = 0;
[JsonPropertyName("hardOnpuNum")] public int HardOnpuNum { get; set; } = 0;
[JsonPropertyName("maniaOnpuNum")] public int ManiaOnpuNum { get; set; } = 0;
[JsonPropertyName("uraOnpuNum")] public int UraOnpuNum { get; set; } = 0;
[JsonPropertyName("rendaTimeEasy")] public double RendaTimeEasy { get; set; } = 0;
[JsonPropertyName("rendaTimeNormal")] public double RendaTimeNormal { get; set; } = 0;
[JsonPropertyName("rendaTimeHard")] public double RendaTimeHard { get; set; } = 0;
[JsonPropertyName("rendaTimeMania")] public double RendaTimeMania { get; set; } = 0;
[JsonPropertyName("rendaTimeUra")] public double RendaTimeUra { get; set; } = 0;
[JsonPropertyName("fuusenTotalEasy")] public int FuusenTotalEasy { get; set; } = 0;
[JsonPropertyName("fuusenTotalNormal")] public int FuusenTotalNormal { get; set; } = 0;
[JsonPropertyName("fuusenTotalHard")] public int FuusenTotalHard { get; set; } = 0;
[JsonPropertyName("fuusenTotalMania")] public int FuusenTotalMania { get; set; } = 0;
[JsonPropertyName("fuusenTotalUra")] public int FuusenTotalUra { get; set; } = 0;
public override string ToString() => $"{UniqueId}. {Id}";
[DefaultValue(Genre.Pop)]
[JsonIgnore]
public Genre Genre
{
get => (Genre)GenreNo;
set => GenreNo = (int)value;
}
public MusicInfo Clone()
{
var props = GetType().GetProperties();
var clone = new MusicInfo();
foreach (var p in props)
p.SetValue(clone, p.GetValue(this));
return clone;
}
}
}

View File

@ -1,10 +0,0 @@
using System.Text.Json.Serialization;
namespace TaikoSoundEditor.Data
{
internal class MusicInfos
{
[JsonPropertyName("items")]
public List<MusicInfo> Items { get; set; } = new List<MusicInfo>();
}
}

View File

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Data
{
public class MusicOrder
{
[JsonPropertyName("genreNo")] public int GenreNo { get; set; } = 0;
[ReadOnly(true)]
[JsonPropertyName("id")] public string Id { get; set; } = "ABCDEF";
[ReadOnly(true)]
[JsonPropertyName("uniqueId")] public int UniqueId { get; set; } = 0;
[JsonPropertyName("closeDispType")] public int CloseDispType { get; set; } = 0;
[DefaultValue(Genre.Pop)]
[JsonIgnore] public Genre Genre
{
get => (Genre)GenreNo;
set => GenreNo = (int)value;
}
public MusicOrder() { }
public MusicOrder(MusicOrder source)
{
Genre = source.Genre;
Id = source.Id;
UniqueId = source.UniqueId;
CloseDispType = source.CloseDispType;
}
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Data
{
public class MusicOrders
{
[JsonPropertyName("items")]
public List<MusicOrder> Items { get; set; } = new List<MusicOrder>();
public MusicOrder GetByUniqueId(int id) => Items.Find(i => i.UniqueId == id);
}
}

View File

@ -30,13 +30,13 @@ namespace TaikoSoundEditor.Data
public byte[] Nus3Bank { get; set; }
public MusicAttribute MusicAttribute { get; set; }
public MusicInfo MusicInfo { get; set; }
public MusicOrder MusicOrder { get; set; }
public IMusicAttribute MusicAttribute { get; set; }
public IMusicInfo MusicInfo { get; set; }
public IMusicOrder MusicOrder { get; set; }
public Word Word { get; set; }
public Word WordSub { get; set; }
public Word WordDetail { get; set; }
public IWord Word { get; set; }
public IWord WordSub { get; set; }
public IWord WordDetail { get; set; }
public override string ToString() => $"{UniqueId}. {Id}";

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Data
{
public class Word
{
[ReadOnly(true)]
[JsonPropertyName("key")] public string Key { get; set; } = "song_...";
[JsonPropertyName("japaneseText")] public string JapaneseText { get; set; } = "text...";
[JsonPropertyName("japaneseFontType")] public int JapaneseFontType { get; set; } = 0;
}
}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Data
{
public class WordList
{
[JsonPropertyName("items")]
public List<Word> Items { get; set; } = new List<Word>();
public Word GetBySong(string song) => Items.Find(i => i.Key == $"song_{song}");
public Word GetBySongSub(string song) => Items.Find(i => i.Key == $"song_sub_{song}");
public Word GetBySongDetail(string song) => Items.Find(i => i.Key == $"song_detail_{song}");
}
}

73
DatatableTypes.cs Normal file
View File

@ -0,0 +1,73 @@
using System;
using TaikoSoundEditor.Commons.Emit;
using TaikoSoundEditor.Commons.IO;
using TaikoSoundEditor.Data;
namespace TaikoSoundEditor
{
internal static class DatatableTypes
{
public static Type Word { get; private set; }
public static Type MusicOrder { get; private set; }
public static Type MusicAttribute { get; private set; }
public static Type MusicInfo { get; private set; }
public static IWord CreateWord(string key, string japaneseText = "")
{
var w = Activator.CreateInstance(Word) as IWord;
w.JapaneseText = japaneseText;
w.Key = key;
return w;
}
public static IMusicOrder CreateMusicOrder(Genre genre, string id, int uniqId, int closeDispType = 0)
{
var nmo = Activator.CreateInstance(MusicOrder) as IMusicOrder;
nmo.Genre = genre;
nmo.Id = id;
nmo.UniqueId = uniqId;
nmo.CloseDispType = closeDispType;
return nmo;
}
public static IMusicAttribute CreateMusicAttribute(string id, int uniqId, bool isNew = true)
{
var ma = Activator.CreateInstance(MusicAttribute) as IMusicAttribute;
ma.Id = id;
ma.UniqueId = uniqId;
ma.New = isNew;
return ma;
}
public static IMusicInfo CreateMusicInfo(string id="abcdef", int uniqId=0)
{
var mi = Activator.CreateInstance(MusicInfo) as IMusicInfo;
mi.Id = id;
mi.UniqueId = uniqId;
return mi;
}
public static T Clone<T>(this T item)
{
var type = item.GetType();
var props = type.GetProperties();
var clone = (T)Activator.CreateInstance(type);
foreach (var p in props)
p.SetValue(clone, p.GetValue(item));
return clone;
}
public static void LoadFromJson(string json)
{
var types = DatatableEntityTypeBuilder.LoadTypes(Json.Deserialize<DynamicTypeCollection>(json));
Word = types["Word"];
MusicOrder = types["MusicOrder"];
MusicAttribute = types["MusicAttribute"];
MusicInfo = types["MusicInfo"];
}
public static string ToString(this IMusicInfo mi) => $"{mi.UniqueId}. {mi.Id}";
}
}

76
GZ.cs
View File

@ -1,76 +0,0 @@
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using System.Diagnostics;
using System.IO.Compression;
using System.Text;
using static System.Net.Mime.MediaTypeNames;
namespace TaikoSoundEditor
{
internal class GZ
{
public static string DecompressBytes(byte[] bytes)
{
Logger.Info("GZ Decompressing bytes");
using MemoryStream ms = new MemoryStream(bytes);
using GZipStream decompressionStream = new GZipStream(ms, CompressionMode.Decompress);
using StreamReader reader = new StreamReader(decompressionStream);
return reader.ReadToEnd();
}
public static string DecompressString(string gzPath)
{
Logger.Info("GZ Decompressing string");
using FileStream originalFileStream = File.OpenRead(gzPath);
using GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress);
using StreamReader reader = new StreamReader(decompressionStream);
return reader.ReadToEnd();
}
public static byte[] DecompressBytes(string gzPath)
{
Logger.Info("GZ Decompressing bytes");
using FileStream originalFileStream = File.OpenRead(gzPath);
using GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress);
using MemoryStream ms = new MemoryStream();
decompressionStream.CopyTo(ms);
return ms.ToArray();
}
public static byte[] CompressToBytes(string content)
{
Logger.Info("GZ Compressing bytes");
var uncompressed = Encoding.UTF8.GetBytes(content);
using (MemoryStream outStream = new MemoryStream())
{
using (GZipOutputStream gzoStream = new GZipOutputStream(outStream))
{
gzoStream.SetLevel(5);
gzoStream.Write(uncompressed, 0, uncompressed.Length);
}
return outStream.ToArray();
}
}
public static string CompressToFile(string fileName, string content)
{
Logger.Info("GZ Compressing file");
var uncompressed = Encoding.UTF8.GetBytes(content);
using (MemoryStream outStream = new MemoryStream())
{
using (GZipOutputStream gzoStream = new GZipOutputStream(outStream))
{
gzoStream.SetLevel(5);
gzoStream.Write(uncompressed, 0, uncompressed.Length);
}
File.WriteAllBytes(fileName, outStream.ToArray());
}
return "";
}
}
}

441
MainForm.Designer.cs generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,12 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using TaikoSoundEditor.Collections;
using TaikoSoundEditor.Commons;
using TaikoSoundEditor.Commons.Utils;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Utils;
namespace TaikoSoundEditor
{
@ -118,7 +124,7 @@ namespace TaikoSoundEditor
Process.Start($"explorer.exe", path);
});
private string PickPath()
private static string PickPath()
{
Logger.Info($"Picking path dialog");
var picker = new FolderPicker();

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TaikoSoundEditor.Collections;
using TaikoSoundEditor.Data;
namespace TaikoSoundEditor

View File

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TaikoSoundEditor.Collections;
using TaikoSoundEditor.Commons.Controls;
using TaikoSoundEditor.Commons.Utils;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Utils;
namespace TaikoSoundEditor
{
@ -70,8 +72,8 @@ namespace TaikoSoundEditor
Config.DatatableIO.IsEncrypted = UseEncryptionBox.Checked;
try
{
MusicAttributes = Config.DatatableIO.Deserialize<MusicAttributes>(MusicAttributePath);
{
MusicAttributes = Config.DatatableIO.DeserializeCollection<MusicAttributes, IMusicAttribute>(MusicAttributePath, DatatableTypes.MusicAttribute);
}
catch (Exception ex)
{
@ -79,26 +81,28 @@ namespace TaikoSoundEditor
}
try
{
MusicOrders = Config.DatatableIO.Deserialize<MusicOrders>(MusicOrderPath);
MusicOrders = Config.DatatableIO.DeserializeCollection<MusicOrders, IMusicOrder>(MusicOrderPath, DatatableTypes.MusicOrder);
}
catch (Exception ex)
{
throw;
throw new Exception($"Failed to parse\n{MusicOrderPath}\nReason:\n{ex.InnerException}");
}
try
{
MusicInfos = Config.DatatableIO.Deserialize<MusicInfos>(MusicInfoPath);
{
MusicInfos = Config.DatatableIO.DeserializeCollection<MusicInfos, IMusicInfo>(MusicInfoPath, DatatableTypes.MusicInfo);
}
catch (Exception ex)
{
throw new Exception($"Failed to parse\n{MusicInfoPath}\nReason:\n{ex.InnerException}");
}
try
{
WordList = Config.DatatableIO.Deserialize<WordList>(WordListPath);
{
WordList = Config.DatatableIO.DeserializeCollection<WordList, IWord>(WordListPath, DatatableTypes.Word);
}
catch (Exception ex)
{
throw;
throw new Exception($"Failed to parse\n{WordListPath}\nReason:\n{ex.InnerException}");
}
@ -113,39 +117,29 @@ namespace TaikoSoundEditor
{
Logger.Info($"Added missing music_attribute entry for {mi.UniqueId}.{songId}");
MusicAttributes.Items.Add(new MusicAttribute
{
Id = songId,
UniqueId = mi.UniqueId,
New = false
});
MusicAttributes.Items.Add(DatatableTypes.CreateMusicAttribute(songId, mi.UniqueId, false));
}
if(MusicOrders.GetByUniqueId(mi.UniqueId)==null)
{
Logger.Info($"Added missing music_order entry for {mi.UniqueId}.{songId}");
MusicOrders.Items.Add(new MusicOrder
{
Genre = mi.Genre,
Id = songId,
UniqueId = mi.UniqueId
});
MusicOrders.Items.Add(DatatableTypes.CreateMusicOrder(mi.Genre, songId, mi.UniqueId));
}
if (WordList.GetBySong(songId) == null)
{
Logger.Info($"Added missing word title entry for {mi.UniqueId}.{songId}");
WordList.Items.Add(new Word { Key = $"song_{songId}", JapaneseText = "" });
WordList.Items.Add(DatatableTypes.CreateWord($"song_{songId}", ""));
}
if (WordList.GetBySongSub(songId) == null)
{
Logger.Info($"Added missing word subtitle entry for {mi.UniqueId}.{songId}");
WordList.Items.Add(new Word { Key = $"song_sub_{songId}", JapaneseText = "" });
WordList.Items.Add(DatatableTypes.CreateWord($"song_sub_{songId}", ""));
}
if (WordList.GetBySongDetail(songId) == null)
{
Logger.Info($"Added missing word detail entry for {mi.UniqueId}.{songId}");
WordList.Items.Add(new Word { Key = $"song_detail_{songId}", JapaneseText = "" });
WordList.Items.Add(DatatableTypes.CreateWord($"song_detail_{songId}", ""));
}
}

View File

@ -1,10 +1,16 @@
using System.Data;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using TaikoSoundEditor.Commons.IO;
using TaikoSoundEditor.Commons.Utils;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Utils;
namespace TaikoSoundEditor
{
partial class MainForm
partial class MainForm
{
private void CreateButton_Click(object sender, EventArgs e)
{
@ -136,7 +142,7 @@ namespace TaikoSoundEditor
Logger.Info("Creating temporary tja");
var newTja = @$".-tmp\{Path.GetFileName(tjaPath)}";
var newTja = $@".-tmp\{Path.GetFileName(tjaPath)}";
File.WriteAllLines(newTja, text);
@ -170,29 +176,27 @@ namespace TaikoSoundEditor
ns.NBin2 = tja_binaries[13];
var selectedMusicInfo = LoadedMusicBox.SelectedItem as MusicInfo;
var selectedMusicInfo = LoadedMusicBox.SelectedItem as IMusicInfo;
var mi = (selectedMusicInfo ?? (NewSoundsBox.SelectedItem as NewSongData)?.MusicInfo ?? new MusicInfo()).Clone();
var mi = (selectedMusicInfo ?? (NewSoundsBox.SelectedItem as NewSongData)?.MusicInfo ?? DatatableTypes.CreateMusicInfo()).Clone();
mi.Id = songName;
mi.UniqueId = id;
ns.MusicInfo = mi;
var mo = new MusicOrder();
mo.Id = songName;
mo.UniqueId = id;
var mo = DatatableTypes.CreateMusicOrder(Genre.Pop, songName, id);
ns.MusicOrder = mo;
var ma = selectedMusicInfo != null ? MusicAttributes.GetByUniqueId(selectedMusicInfo.UniqueId).Clone() : new MusicAttribute();
var ma = selectedMusicInfo != null ? MusicAttributes.GetByUniqueId(selectedMusicInfo.UniqueId).Clone() : DatatableTypes.CreateMusicAttribute("", 0);
ma.Id = songName;
ma.UniqueId = id;
ma.New = true;
ns.MusicAttribute = ma;
ns.Word = WordList.GetBySong(songName) ?? new Word { Key = $"song_{songName}" };
ns.Word = WordList.GetBySong(songName) ?? DatatableTypes.CreateWord($"song_{songName}");
ns.Word.JapaneseText = tja.Headers.Title;
ns.WordSub = WordList.GetBySongSub(songName) ?? new Word { Key = $"song_sub_{songName}" };
ns.WordSub = WordList.GetBySongSub(songName) ?? DatatableTypes.CreateWord($"song_{songName}");
ns.WordSub.JapaneseText = tja.Headers.Subtitle;
ns.WordDetail = WordList.GetBySongDetail(songName) ?? new Word { Key = $"song_detail_{songName}", JapaneseText = tja.Headers.TitleJa };
ns.WordDetail = WordList.GetBySongDetail(songName) ?? DatatableTypes.CreateWord($"song_{songName}", tja.Headers.TitleJa);
ns.WordDetail.JapaneseText = tja.Headers.TitleJa;
mi.EasyOnpuNum = tja.Courses[0].NotesCount;

View File

@ -1,5 +1,10 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using TaikoSoundEditor.Commons.Controls;
using TaikoSoundEditor.Commons.Utils;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Utils;
namespace TaikoSoundEditor
{
@ -21,21 +26,20 @@ namespace TaikoSoundEditor
SimpleGenreBox.DataSource = Enum.GetValues(typeof(Genre));
DatatableKeyBox.Text = Config.IniFile.Read("DatatableKey");
FumenKeyBox.Text = Config.IniFile.Read("FumenKey");
FumenKeyBox.Text = Config.IniFile.Read("FumenKey");
LoadPreferences();
LoadPreferences();
//SortByGenreToolStripMenuItem.RadioCheck = true;
}
private void TabControl_SelectedIndexChanged(object sender, EventArgs e)
{
Logger.Info($"Commuted to tab {TabControl.SelectedIndex}.{TabControl.Name}");
}
}
#region Editor
private void LoadMusicInfo(MusicInfo item)
private void LoadMusicInfo(IMusicInfo item)
{
Logger.Info($"Showing properties for MusicInfo: {item}");
@ -108,7 +112,7 @@ namespace TaikoSoundEditor
if (indexChanging) return;
indexChanging = true;
NewSoundsBox.SelectedItem = null;
var item = LoadedMusicBox.SelectedItem as MusicInfo;
var item = LoadedMusicBox.SelectedItem as IMusicInfo;
Logger.Info($"Selection Changed MusicItem: {item}");
LoadMusicInfo(item);
indexChanging = false;
@ -146,7 +150,7 @@ namespace TaikoSoundEditor
MusicAttributes.Items.Remove(ns.MusicAttribute);
}
private void RemoveExistingSong(MusicInfo mi)
private void RemoveExistingSong(IMusicInfo mi)
{
var ma = MusicAttributes.GetByUniqueId(mi.UniqueId);
var mo = MusicOrders.GetByUniqueId(mi.UniqueId);
@ -196,7 +200,7 @@ namespace TaikoSoundEditor
if (LoadedMusicBox.SelectedItem != null)
{
Logger.Info("Removing existing song");
var mi = LoadedMusicBox.SelectedItem as MusicInfo;
var mi = LoadedMusicBox.SelectedItem as IMusicInfo;
RemoveExistingSong(mi);
return;
}
@ -215,7 +219,7 @@ namespace TaikoSoundEditor
if (LoadedMusicBox.SelectedItem != null)
{
var item = LoadedMusicBox.SelectedItem as MusicInfo;
var item = LoadedMusicBox.SelectedItem as IMusicInfo;
Logger.Info($"Tab switched, reloading MusicItem: {item}");
LoadMusicInfo(item);
return;
@ -237,7 +241,7 @@ namespace TaikoSoundEditor
if (LoadedMusicBox.SelectedItem != null)
{
var item = LoadedMusicBox.SelectedItem as MusicInfo;
var item = LoadedMusicBox.SelectedItem as IMusicInfo;
Logger.Info($"Simple Box changed : {(sender as Control).Name} to value {(sender as Control).Text}");
@ -272,7 +276,7 @@ namespace TaikoSoundEditor
}
});
private void MusicOrderViewer_SongRemoved(Controls.MusicOrderViewer sender, MusicOrder mo) => ExceptionGuard.Run(() =>
private void MusicOrderViewer_SongRemoved(MusicOrderViewer sender, IMusicOrder mo) => ExceptionGuard.Run(() =>
{
var uniqId = mo.UniqueId;
if (MusicOrderViewer.SongExists(uniqId))
@ -299,7 +303,7 @@ namespace TaikoSoundEditor
{
if (LoadedMusicBox.SelectedItem != null)
{
var item = LoadedMusicBox.SelectedItem as MusicInfo;
var item = LoadedMusicBox.SelectedItem as IMusicInfo;
var mo = MusicOrders.GetByUniqueId(item.UniqueId);
if (MusicOrderViewer.Locate(mo))
{
@ -318,10 +322,10 @@ namespace TaikoSoundEditor
}
});
private void MusicOrderViewer_SongDoubleClick(Controls.MusicOrderViewer sender, MusicOrder mo)
private void MusicOrderViewer_SongDoubleClick(MusicOrderViewer sender, IMusicOrder mo)
{
var uid = mo.UniqueId;
var mi = LoadedMusicBox.Items.Cast<MusicInfo>().Where(_ => _.UniqueId == uid).FirstOrDefault();
var mi = LoadedMusicBox.Items.Cast<IMusicInfo>().Where(_ => _.UniqueId == uid).FirstOrDefault();
if(mi!=null)
{
LoadedMusicBox.SelectedItem = mi;
@ -399,10 +403,9 @@ namespace TaikoSoundEditor
}
}
private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e) => ExceptionGuard.Run(async () =>
private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e) => ExceptionGuard.Run(() =>
{
//var rel = await Updates.GetLatestTja2Fumen();
});
private void DatatableKeyBox_TextChanged(object sender, EventArgs e)
@ -414,5 +417,16 @@ namespace TaikoSoundEditor
{
Config.IniFile.Write("FumenKey", FumenKeyBox.Text);
}
private void LoadedMusicBox_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
if (e.Index<0 || e.Index >= LoadedMusicBox.Items.Count)
return;
var selItem = LoadedMusicBox.Items[e.Index] as IMusicInfo;
TextRenderer.DrawText(e.Graphics, $"{selItem.UniqueId}. {selItem.Id}", Font, e.Bounds, e.ForeColor, e.BackColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
e.DrawFocusRectangle();
}
}
}

View File

@ -1,4 +1,64 @@
<root>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@ -60,9 +120,6 @@
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>25</value>
</metadata>

View File

@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaikoSoundEditor.Commons.Utils;
using TaikoSoundEditor.Properties;
using static TaikoSoundEditor.TJA;
namespace TaikoSoundEditor
{
@ -25,40 +23,43 @@ namespace TaikoSoundEditor
Logger.Info($"uniqId = {uniqueId}");
Logger.Info($"idsp.len = {idsp.Length}");
Logger.Info($"demostart = {demostart}");
using var ms = new MemoryStream();
var header = Resources.song_ABCDEF_nus3bank.ToArray();
Write32(header, 0x4, (uint)idsp.Length);
for(int i=0;i<songId.Length;i++)
using (var ms = new MemoryStream())
{
header[0xAA + i] = (byte)songId[i];
header[0x612 + i] = (byte)songId[i];
}
for (int i = songId.Length; i < 6; i++)
{
header[0xAA + i] = 0;
header[0x612 + i] = 0;
}
var header = Resources.song_ABCDEF_nus3bank.ToArray();
header[0xB4] = (byte)(uniqueId & 0xFF);
header[0xB5] = (byte)((uniqueId >> 8) & 0xFF);
Write32(header, 0x4, (uint)idsp.Length);
for (int i = 0; i < songId.Length; i++)
{
header[0xAA + i] = (byte)songId[i];
header[0x612 + i] = (byte)songId[i];
}
Write32(header, 0x4C, (uint)idsp.Length);
Write32(header, 0x628, (uint)idsp.Length);
Write32(header, 0x74C, (uint)idsp.Length);
Write32(header, 0x4, (uint)idsp.Length);
for (int i = songId.Length; i < 6; i++)
{
header[0xAA + i] = 0;
header[0x612 + i] = 0;
}
uint bb = (uint)(demostart * 1000);
Write32(header, 0x6C4, bb);
header[0xB4] = (byte)(uniqueId & 0xFF);
header[0xB5] = (byte)((uniqueId >> 8) & 0xFF);
ms.Write(header);
ms.Write(idsp);
return ms.ToArray();
}
Write32(header, 0x4C, (uint)idsp.Length);
Write32(header, 0x628, (uint)idsp.Length);
Write32(header, 0x74C, (uint)idsp.Length);
Write32(header, 0x4, (uint)idsp.Length);
uint bb = (uint)(demostart * 1000);
Write32(header, 0x6C4, bb);
ms.Write(header);
ms.Write(idsp);
return ms.ToArray();
}
}
private static void Write(this MemoryStream ms, byte[] bytes) => ms.Write(bytes, 0, bytes.Length);
}
}

View File

@ -1,26 +1,66 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows.Forms;
using TaikoSoundEditor.Commons.Emit;
using TaikoSoundEditor.Commons.Extensions;
using TaikoSoundEditor.Commons.IO;
using TaikoSoundEditor.Commons.Utils;
using TaikoSoundEditor.Data;
using TaikoSoundEditor.Utils;
using TaikoSoundEditor.Properties;
namespace TaikoSoundEditor
{
internal static class Program
{
private static void InitTypesJson()
{
var wordProps = new List<EntityPropertyInfo>
{
new EntityPropertyInfo("Key", typeof(string), defaultValue:"song_...", isReadOnly:true),
new EntityPropertyInfo("JapaneseText", typeof(string), defaultValue:"text.."),
new EntityPropertyInfo("JapaneseFontType", typeof(int), defaultValue:0),
}.Select(EntityPropertyInfoDTO.FromPropertyInfo).ToArray();
var col = new DynamicTypeCollection(
new DynamicType("Word", typeof(IWord), wordProps)
);
File.WriteAllText("adef.json", JsonSerializer.Serialize(col, new JsonSerializerOptions() { WriteIndented = true }));
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
SSL.LoadKeys();
SSL.LoadKeys();
ApplicationConfiguration.Initialize();
string json = Resources.datatable_def_08_18;
try
{
json = File.ReadAllText(Config.DatatableDefPath);
}
catch { }
finally
{
DatatableTypes.LoadFromJson(json);
Config.DatatableDefPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "datatable_def.json");
File.WriteAllText(Config.DatatableDefPath, json);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TaikoSoundEditor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TaikoSoundEditor")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1528de8c-b28f-4c97-9404-13e4af27d989")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -60,6 +60,30 @@ namespace TaikoSoundEditor.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to {
/// &quot;types&quot;: [
/// {
/// &quot;name&quot;: &quot;Word&quot;,
/// &quot;properties&quot;: [
/// { &quot;name&quot;: &quot;Key&quot;, &quot;type&quot;: &quot;String&quot;, &quot;isReadOnly&quot;: true, &quot;defaultValue&quot;: &quot;song_...&quot; },
/// { &quot;name&quot;: &quot;JapaneseText&quot;, &quot;type&quot;: &quot;String&quot;, &quot;defaultValue&quot;: &quot;text..&quot; },
/// { &quot;name&quot;: &quot;JapaneseFontType&quot;, &quot;type&quot;: &quot;Int32&quot;, &quot;defaultValue&quot;: &quot;0&quot; }
/// ],
/// &quot;interface&quot;: &quot;TaikoSoundEditor.Data.IWord&quot;
/// },
///
/// {
/// &quot;name&quot;: &quot;MusicOrder&quot;,
/// &quot;properties&quot;: [
/// { &quot;name&quot;: &quot;GenreNo&quot;, &quot;type&quot;: &quot;Int32&quot;, &quot;defaultValue&quot;: [rest of string was truncated]&quot;;.
/// </summary>
internal static string datatable_def_08_18 {
get {
return ResourceManager.GetString("datatable_def_08_18", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@ -118,6 +118,9 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="datatable_def_08_18" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\datatable_def_08_18.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="ic_cut" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_cut.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>

26
Properties/Settings.Designer.cs generated Normal file
View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace TaikoSoundEditor.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,119 @@
{
"types": [
{
"name": "Word",
"properties": [
{ "name": "Key", "type": "String", "isReadOnly": true, "defaultValue": "song_..." },
{ "name": "JapaneseText", "type": "String", "defaultValue": "text.." },
{ "name": "JapaneseFontType", "type": "Int32", "defaultValue": "0" }
],
"interface": "TaikoSoundEditor.Data.IWord"
},
{
"name": "MusicOrder",
"properties": [
{ "name": "GenreNo", "type": "Int32", "defaultValue": "0" },
{ "name": "Id", "type": "String", "defaultValue": "ABCDEF", "isReadOnly":true },
{ "name": "UniqueId", "type": "Int32", "defaultValue": "0", "isReadOnly":true},
{ "name": "CloseDispType", "type": "Int32", "defaultValue": "0" }
],
"interface": "TaikoSoundEditor.Data.IMusicOrder"
},
{
"name": "MusicAttribute",
"properties": [
{ "name": "Id", "type": "String", "defaultValue": "ABCDEF", "isReadOnly":true },
{ "name": "UniqueId", "type": "Int32", "defaultValue": "0", "isReadOnly":true},
{ "name": "New", "type": "Boolean", "defaultValue": "false"},
{ "name": "CanPlayUra", "type": "Boolean", "defaultValue": "false"},
{ "name": "DoublePlay", "type": "Boolean", "defaultValue": "false"},
{ "name": "Tag1", "type": "String", "defaultValue": ""},
{ "name": "Tag2", "type": "String", "defaultValue": ""},
{ "name": "Tag3", "type": "String", "defaultValue": ""},
{ "name": "Tag4", "type": "String", "defaultValue": ""},
{ "name": "Tag5", "type": "String", "defaultValue": ""},
{ "name": "Tag6", "type": "String", "defaultValue": ""},
{ "name": "Tag7", "type": "String", "defaultValue": ""},
{ "name": "Tag8", "type": "String", "defaultValue": ""},
{ "name": "Tag9", "type": "String", "defaultValue": ""},
{ "name": "Tag10", "type": "String", "defaultValue": ""},
{ "name": "DonBg1p", "type": "String", "defaultValue": ""},
{ "name": "DonBg2p", "type": "String", "defaultValue": ""},
{ "name": "DancerDai", "type": "String", "defaultValue": ""},
{ "name": "Dancer", "type": "String", "defaultValue": ""},
{ "name": "DanceNormalBg", "type": "String", "defaultValue": ""},
{ "name": "DanceFeverBg", "type": "String", "defaultValue": ""},
{ "name": "RendaEffect", "type": "String", "defaultValue": ""},
{ "name": "Fever", "type": "String", "defaultValue": ""},
{ "name": "DonBg1p1", "type": "String", "defaultValue": ""},
{ "name": "DonBg2p1", "type": "String", "defaultValue": ""},
{ "name": "DancerDai1", "type": "String", "defaultValue": ""},
{ "name": "Dancer1", "type": "String", "defaultValue": ""},
{ "name": "DanceNormalBg1", "type": "String", "defaultValue": ""},
{ "name": "DanceFeverBg1", "type": "String", "defaultValue": ""},
{ "name": "RendaEffect1", "type": "String", "defaultValue": ""},
{ "name": "Fever1", "type": "String", "defaultValue": ""}
],
"interface": "TaikoSoundEditor.Data.IMusicAttribute"
},
{
"name": "MusicInfo",
"properties": [
{ "name": "Id", "type": "String", "defaultValue": "ABCDEF", "isReadOnly":true },
{ "name": "UniqueId", "type": "Int32", "defaultValue": "0", "isReadOnly":true},
{ "name": "GenreNo", "type": "Int32", "defaultValue": "0"},
{ "name": "SongFileName", "type": "String", "defaultValue": ""},
{ "name": "Papamama", "type": "Boolean", "defaultValue": "false"},
{ "name": "BranchEasy", "type": "Boolean", "defaultValue": "false"},
{ "name": "BranchNormal", "type": "Boolean", "defaultValue": "false"},
{ "name": "BranchHard", "type": "Boolean", "defaultValue": "false"},
{ "name": "BranchMania", "type": "Boolean", "defaultValue": "false"},
{ "name": "BranchUra", "type": "Boolean", "defaultValue": "false"},
{ "name": "StarEasy", "type": "Int32", "defaultValue": "0"},
{ "name": "StarNormal", "type": "Int32", "defaultValue": "0"},
{ "name": "StarHard", "type": "Int32", "defaultValue": "0"},
{ "name": "StarMania", "type": "Int32", "defaultValue": "0"},
{ "name": "StarUra", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiEasy", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiNormal", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiHard", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiMania", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiUra", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiEasyDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiNormalDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiHardDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiManiaDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiUraDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreEasy", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreNormal", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreHard", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreMania", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreUra", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreEasyDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreNormalDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreHardDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreManiaDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "ShinutiScoreUraDuet", "type": "Int32", "defaultValue": "0"},
{ "name": "EasyOnpuNum", "type": "Int32", "defaultValue": "0"},
{ "name": "NormalOnpuNum", "type": "Int32", "defaultValue": "0"},
{ "name": "HardOnpuNum", "type": "Int32", "defaultValue": "0"},
{ "name": "ManiaOnpuNum", "type": "Int32", "defaultValue": "0"},
{ "name": "UraOnpuNum", "type": "Int32", "defaultValue": "0"},
{ "name": "RendaTimeEasy", "type": "Double", "defaultValue": "0"},
{ "name": "RendaTimeNormal", "type": "Double", "defaultValue": "0"},
{ "name": "RendaTimeHard", "type": "Double", "defaultValue": "0"},
{ "name": "RendaTimeMania", "type": "Double", "defaultValue": "0"},
{ "name": "RendaTimeUra", "type": "Double", "defaultValue": "0"},
{ "name": "RendaTimeUra", "type": "Double", "defaultValue": "0"},
{ "name": "FuusenTotalEasy", "type": "Int32", "defaultValue": "0"},
{ "name": "FuusenTotalNormal", "type": "Int32", "defaultValue": "0"},
{ "name": "FuusenTotalHard", "type": "Int32", "defaultValue": "0"},
{ "name": "FuusenTotalMania", "type": "Int32", "defaultValue": "0"},
{ "name": "FuusenTotalUra", "type": "Int32", "defaultValue": "0"}
],
"interface": "TaikoSoundEditor.Data.IMusicInfo"
}
]
}

View File

@ -1,199 +1,267 @@
<Project Sdk="Microsoft.NET.Sdk">
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1528DE8C-B28F-4C97-9404-13E4AF27D989}</ProjectGuid>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>disable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Authors>NotImplementedLife</Authors>
<AssemblyVersion>0.5</AssemblyVersion>
<Version>0.5</Version>
<RootNamespace>TaikoSoundEditor</RootNamespace>
<AssemblyName>TaikoSoundEditor</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<Reference Include="ICSharpCode.SharpZipLib, Version=1.4.2.13, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.4.2\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encoding.CodePages.7.0.0\lib\net462\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encodings.Web, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
</Reference>
<Reference Include="System.Text.Json, Version=7.0.0.3, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Json.7.0.3\lib\net462\System.Text.Json.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<Compile Include="Collections\Collection.cs" />
<Compile Include="Collections\MusicAttributes.cs" />
<Compile Include="Collections\MusicInfos.cs" />
<Compile Include="Collections\MusicOrders.cs" />
<Compile Include="Collections\WordList.cs" />
<Compile Include="Commons\Controls\FolderPicker.cs" />
<Compile Include="Commons\Controls\MusicOrderViewer.cs">
<SubType>UserControl</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Compile Include="Commons\Controls\MusicOrderViewer.Designer.cs">
<DependentUpon>MusicOrderViewer.cs</DependentUpon>
</Compile>
<Compile Include="Commons\Controls\PathSelector.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Commons\Controls\PathSelector.Designer.cs">
<DependentUpon>PathSelector.cs</DependentUpon>
</Compile>
<Compile Include="Commons\Controls\SongCard.cs" />
<Compile Include="Commons\Emit\DatatableEntityTypeBuilder.cs" />
<Compile Include="Commons\Emit\DynamicTypeCollection.cs" />
<Compile Include="Commons\Emit\EntityPropertyInfo.cs" />
<Compile Include="Commons\Emit\EntityPropertyInfoDTO.cs" />
<Compile Include="Commons\Extensions\EnumerableExtensions.cs" />
<Compile Include="Commons\Extensions\IntExtensions.cs" />
<Compile Include="Commons\Extensions\ObjectExtensions.cs" />
<Compile Include="Commons\Extensions\StringExtensions.cs" />
<Compile Include="Commons\IO\GZ.cs" />
<Compile Include="Commons\IO\IDSP.cs" />
<Compile Include="Commons\IO\Json.cs" />
<Compile Include="Commons\IO\SSL.cs" />
<Compile Include="Commons\IO\TJA.cs" />
<Compile Include="Commons\IO\WAV.cs" />
<Compile Include="Commons\Utils\Config.cs" />
<Compile Include="Commons\Utils\Constants.cs" />
<Compile Include="Commons\Utils\DatatableIO.cs" />
<Compile Include="Commons\Utils\ExceptionGuard.cs" />
<Compile Include="Commons\Utils\IniFile.cs" />
<Compile Include="Commons\Utils\Logger.cs" />
<Compile Include="Commons\Utils\Number.cs" />
<Compile Include="Commons\Utils\ProcessArgs.cs" />
<Compile Include="Commons\Utils\RecastAttribute.cs" />
<Compile Include="Commons\Utils\Types.cs" />
<Compile Include="DatatableTypes.cs" />
<Compile Include="Data\IMusicAttribute.cs" />
<Compile Include="Data\IMusicInfo.cs" />
<Compile Include="Data\IMusicOrder.cs" />
<Compile Include="Data\IWord.cs" />
<Compile Include="Data\NewSongData.cs" />
<Compile Include="Genre.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="MainForm.Exports.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Properties.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.RequestFiles.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.SoundCreate.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="NUS3Bank.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Commons\Controls\MusicOrderViewer.resx">
<DependentUpon>MusicOrderViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Commons\Controls\PathSelector.resx">
<DependentUpon>PathSelector.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="LICENSE" />
<None Include="packages.config" />
<None Include="Properties\PublishProfiles\FolderProfile.pubxml" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<None Include="README.md" />
<None Include="Resources\song_ABCDEF_nus3bank.bin" />
<None Include="Tools\7z\Far\7-ZipEng.hlf" />
<None Include="Tools\7z\Far\7-ZipEng.lng" />
<None Include="Tools\7z\Far\7-ZipRus.hlf" />
<None Include="Tools\7z\Far\7-ZipRus.lng" />
<None Include="Tools\7z\Far\7zToFar.ini" />
<None Include="Tools\7z\Far\far7z.reg" />
<None Include="Tools\sox\batch-example.bat" />
<None Include="Tools\sox\sox.pdf" />
<None Include="Tools\sox\soxformat.pdf" />
<None Include="Tools\sox\soxi.pdf" />
<None Include="Tools\sox\wget.ini" />
<None Include="Tools\VGAudio\wav2idsp.bat" />
</ItemGroup>
<ItemGroup>
<None Update="Tools\7z\7za.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\7za.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\7zxa.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\7-ZipEng.hlf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\7-ZipEng.lng">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\7-ZipFar.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\7-ZipFar64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\7-ZipRus.hlf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\7-ZipRus.lng">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\7zToFar.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\far7z.reg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\Far\far7z.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\history.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\License.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\readme.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\x64\7za.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\x64\7za.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\7z\x64\7zxa.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\batch-example.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\ChangeLog.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libflac-8.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libgcc_s_sjlj-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libgomp-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libid3tag-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libogg-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libpng16-16.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libsox-3.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libssp-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libvorbis-0.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libvorbisenc-2.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libvorbisfile-3.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libwavpack-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\libwinpthread-1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\LICENSE.GPL.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\README.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\README.win32.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\sox.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\sox.pdf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\soxformat.pdf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\soxi.pdf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\wget.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\wget.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\sox\zlib1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\tja2fumen.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\idsp\empty.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\VGAudio.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\VGAudio.pdb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\VGAudio.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\VGAudioCli.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\VGAudioCli.pdb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\VGAudioTools.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\VGAudioTools.pdb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\wav2idsp.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tools\VGAudio\wav\empty.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Content Include=".gitignore" />
<Content Include="Properties\PublishProfiles\FolderProfile.pubxml.user" />
<None Include="Resources\datatable_def_08_18.txt" />
<Content Include="Resources\ic_cut.png" />
<Content Include="Resources\ic_cut_gs.png" />
<Content Include="Resources\ic_left_10.png" />
<Content Include="Resources\ic_list_end.png" />
<Content Include="Resources\ic_list_start.png" />
<Content Include="Resources\ic_paste.png" />
<Content Include="Resources\ic_paste_gs.png" />
<Content Include="Resources\ic_remove.png" />
<Content Include="Resources\ic_remove_gs.png" />
<Content Include="Resources\ic_right_10.png" />
<Content Include="Resources\ic_search.png" />
<Content Include="Tools\7z\7za.dll" />
<Content Include="Tools\7z\7za.exe" />
<Content Include="Tools\7z\7zxa.dll" />
<Content Include="Tools\7z\Far\7-ZipFar.dll" />
<Content Include="Tools\7z\Far\7-ZipFar64.dll" />
<Content Include="Tools\7z\Far\far7z.txt" />
<Content Include="Tools\7z\history.txt" />
<Content Include="Tools\7z\License.txt" />
<Content Include="Tools\7z\readme.txt" />
<Content Include="Tools\7z\x64\7za.dll" />
<Content Include="Tools\7z\x64\7za.exe" />
<Content Include="Tools\7z\x64\7zxa.dll" />
<Content Include="Tools\sox\ChangeLog.txt" />
<Content Include="Tools\sox\libflac-8.dll" />
<Content Include="Tools\sox\libgcc_s_sjlj-1.dll" />
<Content Include="Tools\sox\libgomp-1.dll" />
<Content Include="Tools\sox\libid3tag-0.dll" />
<Content Include="Tools\sox\libogg-0.dll" />
<Content Include="Tools\sox\libpng16-16.dll" />
<Content Include="Tools\sox\libsox-3.dll" />
<Content Include="Tools\sox\libssp-0.dll" />
<Content Include="Tools\sox\libvorbis-0.dll" />
<Content Include="Tools\sox\libvorbisenc-2.dll" />
<Content Include="Tools\sox\libvorbisfile-3.dll" />
<Content Include="Tools\sox\libwavpack-1.dll" />
<Content Include="Tools\sox\libwinpthread-1.dll" />
<Content Include="Tools\sox\LICENSE.GPL.txt" />
<Content Include="Tools\sox\Lycoris.ogg" />
<Content Include="Tools\sox\README.txt" />
<Content Include="Tools\sox\README.win32.txt" />
<Content Include="Tools\sox\sox.exe" />
<Content Include="Tools\sox\wav.wav" />
<Content Include="Tools\sox\wav2.wav" />
<Content Include="Tools\sox\wget.exe" />
<Content Include="Tools\sox\zlib1.dll" />
<Content Include="Tools\tja2fumen.exe" />
<Content Include="Tools\VGAudio\idsp\empty.txt" />
<Content Include="Tools\VGAudio\VGAudio.dll" />
<Content Include="Tools\VGAudio\VGAudio.pdb" />
<Content Include="Tools\VGAudio\VGAudio.xml" />
<Content Include="Tools\VGAudio\VGAudioCli.exe" />
<Content Include="Tools\VGAudio\VGAudioCli.pdb" />
<Content Include="Tools\VGAudio\VGAudioTools.exe" />
<Content Include="Tools\VGAudio\VGAudioTools.pdb" />
<Content Include="Tools\VGAudio\wav\empty.txt" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace TaikoSoundEditor.Utils
{
public static class Updates
{
public static async Task<GithubRelease> GetGithubLatestRelease(string owner, string repo)
{
var url = $"https://api.github.com/repos/{owner}/{repo}/releases/latest";
using HttpClient client = new HttpClient();
string json = await client.GetStringAsync(url);
var t = Task.Run(() => MessageBox.Show(json));
t.Wait();
return Json.Deserialize<GithubRelease>(json);
}
public static async Task<GithubRelease> GetLatestTja2Fumen()
{
return await GetGithubLatestRelease("vivaria", "tja2fumen");
}
public class GithubRelease
{
[JsonPropertyName("url")] public string Url { get; set; }
[JsonPropertyName("tag_name")] public string TagName { get; set; }
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("prerelease")] public bool Prerelease { get; set; }
[JsonPropertyName("assets")] public GithubAsset[] Assets { get; set; }
}
public class GithubAsset
{
[JsonPropertyName("name")] public string Name { get; set; }
[JsonPropertyName("browser_download_url")] public string DownloadUrl { get; set; }
}
}
}

14
packages.config Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl.AsyncInterfaces" version="7.0.0" targetFramework="net48" />
<package id="SharpZipLib" version="1.4.2" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
<package id="System.Text.Encoding.CodePages" version="7.0.0" targetFramework="net48" />
<package id="System.Text.Encodings.Web" version="7.0.0" targetFramework="net48" />
<package id="System.Text.Json" version="7.0.3" targetFramework="net48" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
</packages>