126 Commits

603 changed files with 3129 additions and 30455 deletions

1
.gitignore vendored
View File

@@ -68,3 +68,4 @@ crashlytics-build.properties
/UserSettings
/*.zip
*.lnk
/HybridCLRData

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5335612e48e4c3947808c99fb99411d5
guid: c4ef48e4a4983de4e9c31483df2a918e
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6823ead66b33bc048bbad48719feb25d
guid: 9ec674235c0dd6744af2dab2b58dd53c
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Cryville.Common.Collections.Generic {
public interface IPairList<TKey, TValue> : IList<KeyValuePair<TKey, TValue>> {
void Add(TKey key, TValue value);
void Insert(int index, TKey key, TValue value);
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f5b3f3294f679f14f8ec1195b0def630
guid: 73fb17b484b343242bcce27c15ed7d44
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections.Generic {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView<,>))]
public struct PairCollection<TKey, TValue> : IDisposable {
public void Dispose() { }
readonly IPairList<TKey, TValue> _pairList;
readonly IDictionary<TKey, TValue> _dictionary;
public PairCollection(object collection) : this() {
var type = collection.GetType();
if (typeof(IPairList<TKey, TValue>).IsAssignableFrom(type)) _pairList = (IPairList<TKey, TValue>)collection;
else if (typeof(IDictionary<TKey, TValue>).IsAssignableFrom(type)) _dictionary = (IDictionary<TKey, TValue>)collection;
else throw new ArgumentException("Parameter is not a pair collection");
}
public int Count {
get {
if (_pairList != null) return _pairList.Count;
else return _dictionary.Count;
}
}
public void Add(TKey key, TValue value) {
if (_pairList != null) _pairList.Add(key, value);
else _dictionary.Add(key, value);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) {
if (_pairList != null) _pairList.CopyTo(array, index);
else _dictionary.CopyTo(array, index);
}
}
internal class PairCollectionDebugView<TKey, TValue> {
readonly PairCollection<TKey, TValue> _self;
public PairCollectionDebugView(PairCollection<TKey, TValue> self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<TKey, TValue>[] Items {
get {
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 23377bf2926d93a4b8e3f3ab6040c7f2
guid: 2517e8f040bd36f46948e5fafaf5335c
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections.Generic {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView<,>))]
public class PairList<TKey, TValue> : List<KeyValuePair<TKey, TValue>>, IPairList<TKey, TValue>, IPairList {
public void Add(TKey key, TValue value) {
Add(new KeyValuePair<TKey, TValue>(key, value));
}
public void Add(object key, object value) {
try {
Add((TKey)key, (TValue)value);
}
catch (InvalidCastException) {
throw new ArgumentException("Wrong key type or value type");
}
}
public void Insert(int index, TKey key, TValue value) {
Insert(index, new KeyValuePair<TKey, TValue>(key, value));
}
public void Insert(int index, object key, object value) {
try {
Insert(index, (TKey)key, (TValue)value);
}
catch (InvalidCastException) {
throw new ArgumentException("Wrong key type or value type");
}
}
}
internal class PairListDebugView<TKey, TValue> {
readonly PairList<TKey, TValue> _self;
public PairListDebugView(PairList<TKey, TValue> self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<TKey, TValue>[] Items {
get {
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 4ffe72fef6ebb9e4da3571b4117f0d6d
guid: d9ed5ea8b7b1a934287e7ec5971166c0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,8 @@
using System.Collections;
namespace Cryville.Common.Collections {
public interface IPairList : IList {
void Add(object key, object value);
void Insert(int index, object key, object value);
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: e3c5a8bf05d5e284ba498e91cb0dd35e
guid: 046617672d437de4ab7e644a55defd3b
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView))]
public struct PairCollection : IDisposable {
public void Dispose() { }
readonly IPairList _pairList;
readonly IDictionary _dictionary;
public PairCollection(object collection) : this() {
var type = collection.GetType();
if (typeof(IPairList).IsAssignableFrom(type)) _pairList = (IPairList)collection;
else if (typeof(IDictionary).IsAssignableFrom(type)) _dictionary = (IDictionary)collection;
else throw new ArgumentException("Parameter is not a pair collection");
}
public int Count {
get {
if (_pairList != null) return _pairList.Count;
else return _dictionary.Count;
}
}
public void Add(object key, object value) {
if (_pairList != null) _pairList.Add(key, value);
else _dictionary.Add(key, value);
}
public void CopyTo(KeyValuePair<object, object>[] array, int index) {
if (_pairList != null) _pairList.CopyTo(array, index);
else _dictionary.CopyTo(array, index);
}
}
internal class PairCollectionDebugView {
readonly PairCollection _self;
public PairCollectionDebugView(PairCollection self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<object, object>[] Items {
get {
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f87dfb8f6a1f5640b6deae741cd715c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common.Collections {
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView))]
public class PairList : List<KeyValuePair<object, object>>, IPairList {
public void Add(object key, object value) {
Add(new KeyValuePair<object, object>(key, value));
}
public void Insert(int index, object key, object value) {
Insert(index, new KeyValuePair<object, object>(key, value));
}
}
internal class PairListDebugView {
readonly PairList _self;
public PairListDebugView(PairList self) {
_self = self;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<object, object>[] Items {
get {
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
_self.CopyTo(array, 0);
return array;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 57fc9f037c1fda5449e2a365a835c82c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -45,7 +45,7 @@ namespace Cryville.Common.Font {
return tableDirectoryOffsets;
}
public override TableDirectory GetSubTable(UInt32 item) {
var i = (UInt32)item;
var i = item;
return new TableDirectory(Reader, i);
}
}

View File

@@ -2,6 +2,7 @@
namespace Cryville.Common {
public struct Identifier : IEquatable<Identifier> {
public static Identifier Empty = new Identifier(0);
public int Key { get; private set; }
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
public Identifier(int key) {
@@ -24,11 +25,11 @@ namespace Cryville.Common {
if (Key == 0) return "";
return Name.ToString();
}
public static implicit operator Identifier(string identifier) {
return new Identifier(identifier);
public static bool operator ==(Identifier lhs, Identifier rhs) {
return lhs.Equals(rhs);
}
public static implicit operator string(Identifier identifier) {
return identifier.ToString();
public static bool operator !=(Identifier lhs, Identifier rhs) {
return !lhs.Equals(rhs);
}
}
}

View File

@@ -0,0 +1,44 @@
using SMath = System.Math;
namespace Cryville.Common.Math {
// Ported from https://github.com/arian/cubic-bezier/blob/master/index.js
public static class CubicBezier {
public static float Evaluate(float t, float x1, float y1, float x2, float y2, float epsilon) {
float x = t, t0, t1, t2, tx, d2, i;
for (t2 = x, i = 0; i < 8; i++) {
tx = CurveX(t2, x1, x2) - x;
if (SMath.Abs(tx) < epsilon) return CurveY(t2, y1, y2);
d2 = DerivativeCurveX(t2, x1, x2);
if (SMath.Abs(d2) < 1e-6) break;
t2 -= tx / d2;
}
t0 = 0; t1 = 1; t2 = x;
if (t2 < t0) return CurveY(t0, y1, y2);
if (t2 > t1) return CurveY(t1, y1, y2);
while (t0 < t1) {
tx = CurveX(t2, x1, x2);
if (SMath.Abs(tx - x) < epsilon) return CurveY(t2, y1, y2);
if (x > tx) t0 = t2;
else t1 = t2;
t2 = (t1 - t0) * .5f + t0;
}
return CurveY(t2, y1, y2);
}
static float CurveX(float t, float x1, float x2) {
float v = 1 - t;
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t;
}
static float CurveY(float t, float y1, float y2) {
float v = 1 - t;
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t;
}
static float DerivativeCurveX(float t, float x1, float x2) {
float v = 1 - t;
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (-t * t * t + 2 * v * t) * x2;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17dd6f775fc965f43960da7166b55b87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,12 +12,12 @@ namespace Cryville.Common.Math {
/// <param name="error">The error.</param>
/// <param name="n">The numerator.</param>
/// <param name="d">The denominator.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="value" /> is less than 0 or <paramref name="error" /> is not greater than 0 or not less than 1.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="value" /> is less than 0 or <paramref name="error" /> is not greater than 0 or greater than 1.</exception>
public static void ToFraction(double value, double error, out int n, out int d) {
if (value < 0.0)
throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
if (error <= 0.0 || error >= 1.0)
throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
if (error <= 0.0 || error > 1.0)
throw new ArgumentOutOfRangeException("error", "Must be > 0 and <= 1.");
int num = (int)System.Math.Floor(value);
value -= num;

View File

@@ -5,7 +5,7 @@ namespace Cryville.Common.Pdt {
/// Indicates that the attributed member is an element list.
/// </summary>
/// <remarks>
/// <para>An element list is a <see cref="System.Collections.IDictionary" /> that represents a collection of PDT elements. There must be at most one element list in a class.</para>
/// <para>An element list is a <see cref="System.Collections.IDictionary" /> or <see cref="Cryville.Common.Collections.Generic.IPairList" /> that represents a collection of PDT elements. There must be at most one element list in a class.</para>
/// </remarks>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ElementListAttribute : Attribute { }
@@ -14,7 +14,7 @@ namespace Cryville.Common.Pdt {
/// Indicates that the attributed member is a property list.
/// </summary>
/// <remarks>
/// <para>A property list is a <see cref="System.Collections.IDictionary" /> that represents a collection of PDT properties. There must be at most one property list in a class.</para>
/// <para>A property list is a <see cref="System.Collections.IDictionary" /> or <see cref="Cryville.Common.Collections.Generic.IPairList" /> that represents a collection of PDT properties. There must be at most one property list in a class.</para>
/// </remarks>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class PropertyListAttribute : Attribute { }

View File

@@ -186,7 +186,7 @@ namespace Cryville.Common.Pdt {
protected abstract PdtOperator GetOperator(PdtOperatorSignature sig);
unsafe void Operate(PdtOperator op, int pc, bool noset = false) {
fixed (byte* pmem = _mem) {
op.Begin(this);
op.Begin(this, pc);
for (int i = 0; i < pc; i++) {
var frame = _stack[--_framecount];
op.LoadOperand(new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length));

View File

@@ -92,7 +92,7 @@ namespace Cryville.Common.Pdt {
}
}
public partial class PdtInterpreter {
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
static readonly Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
{ '@', 7 },
{ '*', 6 }, { '/', 6 }, { '%', 6 },
{ '+', 5 }, { '-', 5 },
@@ -103,7 +103,7 @@ namespace Cryville.Common.Pdt {
{ ',', 0 },
{ '$', -1 },
};
readonly static Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
static readonly Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
{ '@', 0 },
{ '*', 0 }, { '/', 0 }, { '%', 0 },
{ '+', 0 }, { '-', 0 },
@@ -115,7 +115,7 @@ namespace Cryville.Common.Pdt {
{ '$', -1 },
};
readonly static PdtExpression _emptyexp;
static readonly PdtExpression _emptyexp;
static PdtInterpreter() {
var ins = new LinkedList<PdtInstruction>();
ins.AddLast(new PdtInstruction.PushConstant(
@@ -143,7 +143,7 @@ namespace Cryville.Common.Pdt {
public override string ToString() {
return string.Format("0x{0:x4}: {1}", Type, Value);
}
public readonly static PdtExpToken EmptyOperator = new PdtExpToken {
public static readonly PdtExpToken EmptyOperator = new PdtExpToken {
Type = 0x0080,
Value = "$",
};

View File

@@ -6,30 +6,30 @@
/// <summary>
/// Error type.
/// </summary>
public readonly static int Error = 0x00525245;
public const int Error = 0x00525245;
/// <summary>
/// Array of a same variable-length type, with a suffix indicating the element count and the element type.
/// </summary>
public readonly static int Array = 0x00525241;
public const int Array = 0x00525241;
/// <summary>
/// Null type.
/// </summary>
public readonly static int Null = 0x4c4c554e;
public const int Null = 0x4c4c554e;
/// <summary>
/// IEEE 754 32-bit floating-point number.
/// </summary>
public readonly static int Number = 0x004d554e;
public const int Number = 0x004d554e;
/// <summary>
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units.
/// </summary>
public readonly static int String = 0x00525453;
public const int String = 0x00525453;
/// <summary>
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units, representing the name of an undefined variable.
/// </summary>
public readonly static int Undefined = 0x00444e55;
public const int Undefined = 0x00444e55;
/// <summary>
/// Vector of a same constant-length type, with a suffix indicating the element type.
/// </summary>
public readonly static int Vector = 0x00434556;
public const int Vector = 0x00434556;
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Cryville.Common.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -27,7 +28,7 @@ namespace Cryville.Common.Pdt {
/// <item><term><c>0x1000</c></term><description>End of Key</description></item>
/// </list>
/// </remarks>
readonly static int[] cm = new int[] {
static readonly int[] cm = new int[] {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -54,15 +55,14 @@ namespace Cryville.Common.Pdt {
/// <param name="binder">The binder.</param>
/// <returns>The interpreted object.</returns>
public static T Interpret<T>(string src, Binder binder) {
return (T)new PdtInterpreter(src, typeof(T), binder).Interpret();
return (T)new PdtInterpreter(src, binder).Interpret(typeof(T));
}
/// <summary>
/// The source string.
/// </summary>
public string Source { get; private set; }
readonly Type _type;
readonly Binder _binder;
Binder _binder;
/// <summary>
/// The current position in the string being parsed by the interpreter.
/// </summary>
@@ -167,23 +167,27 @@ namespace Cryville.Common.Pdt {
/// Creates an instance of the <see cref="PdtInterpreter" /> class.
/// </summary>
/// <param name="src">The source string.</param>
/// <param name="type">The destination type.</param>
/// <param name="binder">The binder. May be <c>null</c>.</param>
public PdtInterpreter(string src, Type type, Binder binder) {
public PdtInterpreter(string src, Binder binder) {
Source = src;
_type = type;
_binder = binder;
if (_binder == null)
_binder = BinderAttribute.CreateBinderOfType(_type);
}
int[] m_formatVersion;
public int[] GetFormatVersion() {
if (m_formatVersion == null) InterpretDirectives();
return m_formatVersion;
}
/// <summary>
/// Interprets the source to an object.
/// </summary>
/// <param name="type">The output type.</param>
/// <returns>The interpreted object.</returns>
public object Interpret() {
public object Interpret(Type type) {
try {
InterpretDirectives();
return InterpretObject(_type);
if (m_formatVersion == null) InterpretDirectives();
if (_binder == null)
_binder = BinderAttribute.CreateBinderOfType(type);
return InterpretObject(type);
}
catch (Exception ex) {
throw new PdtParsingException(this, ex);
@@ -201,7 +205,10 @@ namespace Cryville.Common.Pdt {
break;
case "format":
ws();
if (GetNumber() != "1")
m_formatVersion = (from i in GetNumber().Split('.') select int.Parse(i)).ToArray();
if (m_formatVersion.Length == 0)
throw new FormatException("Invalid format version");
if (m_formatVersion[0] != 1)
throw new NotSupportedException("Format not supported");
flag = true;
break;
@@ -226,6 +233,10 @@ namespace Cryville.Common.Pdt {
while (true) {
try { ws(); }
catch (IndexOutOfRangeException) { return result; }
if (cc == '}') {
GetChar();
return result;
}
object pkey = InterpretKey(type);
char c = GetChar();
switch (c) {
@@ -245,13 +256,13 @@ namespace Cryville.Common.Pdt {
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
Type ptype = ReflectionHelper.GetMemberType(prop);
if (flag) {
if (!typeof(IDictionary).IsAssignableFrom(ptype))
throw new InvalidOperationException("Internal error: Element list is not a dictionary");
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = InterpretObject(vtype);
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
collection.Add(key, value);
}
}
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
}
@@ -274,13 +285,13 @@ namespace Cryville.Common.Pdt {
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
var ptype = ReflectionHelper.GetMemberType(prop);
if (flag) {
if (!typeof(IDictionary).IsAssignableFrom(ptype))
throw new InvalidOperationException("Internal error: Property list is not a dictionary");
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = _binder.ChangeType(exp, vtype, null);
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
collection.Add(key, value);
}
}
else {
object value = _binder.ChangeType(exp, ptype, null);
@@ -288,8 +299,6 @@ namespace Cryville.Common.Pdt {
}
}
break;
case '}':
return result;
default:
throw new InvalidOperationException("Internal error: Invalid key interpretation");
}

View File

@@ -4,14 +4,14 @@ namespace Cryville.Common.Pdt {
/// <summary>
/// PDT operator.
/// </summary>
public unsafe abstract class PdtOperator {
public abstract unsafe class PdtOperator {
byte* _prmem;
int _loadindex;
readonly PdtVariableMemory[] _operands;
/// <summary>
/// The count of the operands loaded.
/// </summary>
protected int LoadedOperandCount { get { return _pc - _loadindex; } }
protected int LoadedOperandCount { get; private set; }
/// <summary>
/// Gets the operand at the specified index.
/// </summary>
@@ -35,13 +35,13 @@ namespace Cryville.Common.Pdt {
}
PdtEvaluatorBase _etor;
bool _rfreq = true;
internal void Begin(PdtEvaluatorBase etor) {
internal void Begin(PdtEvaluatorBase etor, int pc) {
_etor = etor;
_loadindex = _pc;
_loadindex = LoadedOperandCount = pc;
}
internal void LoadOperand(PdtVariableMemory mem) {
if (_loadindex == 0) return;
_operands[--_loadindex] = mem;
if (--_loadindex >= _pc) return;
_operands[_loadindex] = mem;
}
internal void Call(byte* prmem, bool noset) {
_prmem = prmem;

View File

@@ -28,8 +28,8 @@ namespace Cryville.Common.Unity {
set { m_filter = value; }
}
public Dictionary<string, string> m_presetPaths = new Dictionary<string, string>();
public Dictionary<string, string> PresetPaths {
public IReadOnlyDictionary<string, string> m_presetPaths = new Dictionary<string, string>();
public IReadOnlyDictionary<string, string> PresetPaths {
get { return m_presetPaths; }
set { m_presetPaths = value; }
}

View File

@@ -3,6 +3,6 @@ using UnityEngine;
namespace Cryville.Common.Unity.UI {
public abstract class SetParameterBehaviour : StateMachineBehaviour {
[SerializeField] protected string m_name;
public override abstract void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex);
public abstract override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex);
}
}

View File

@@ -1,8 +0,0 @@
using System.Collections.Generic;
namespace Cryville.Crtr.Browsing {
public abstract class ExtensionInterface {
public abstract IEnumerable<ResourceConverter> GetResourceConverters();
public abstract IEnumerable<LocalResourceFinder> GetResourceFinders();
}
}

View File

@@ -0,0 +1,138 @@
using Cryville.Common;
using Cryville.Crtr.Extension;
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Cryville.Crtr.Browsing {
internal static class ExtensionManager {
static readonly Dictionary<string, List<ResourceConverter>> _converters
= new Dictionary<string, List<ResourceConverter>>();
public static IEnumerable<string> GetSupportedFormats() {
return _converters.Keys;
}
public static bool TryGetConverters(string extension, out IEnumerable<ResourceConverter> converters) {
List<ResourceConverter> outResult;
bool result = _converters.TryGetValue(extension, out outResult);
converters = outResult;
return result;
}
static readonly Dictionary<string, string> _localRes
= new Dictionary<string, string>();
public static IReadOnlyDictionary<string, string> GetLocalResourcePaths() {
return _localRes;
}
public static void Init(string rootPath) {
LoadExtension(typeof(Extensions.Umg.Extension));
var asms = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToHashSet();
var modules = new Queue<ModuleItem>();
var extensionDir = new DirectoryInfo(Path.Combine(rootPath, "extensions"));
if (extensionDir.Exists) {
foreach (var extension in extensionDir.EnumerateFiles("*.dll")) {
try {
modules.Enqueue(new ModuleItem(extension.OpenRead()));
}
catch (Exception ex) {
Logger.Log("main", 4, "Extension", "Failed to load DLL {0}: {1}", extension, ex);
}
}
}
int refCounter = 0;
while (modules.Count > 0 && refCounter < modules.Count) {
var module = modules.Dequeue();
bool flag = false;
foreach (var reference in module.Definition.AssemblyReferences) {
if (!asms.Contains(reference.Name)) {
flag = true;
break;
}
}
if (flag) {
modules.Enqueue(module);
refCounter++;
}
else {
try {
var stream = module.Stream;
stream.Seek(0, SeekOrigin.Begin);
var buf = new byte[stream.Length];
stream.Read(buf, 0, buf.Length);
var asm = Assembly.Load(buf);
if (asm == null) throw new TypeLoadException("Failed to load the module");
asms.Add(asm.GetName().Name);
foreach (var type in asm.GetTypes()) {
if (typeof(ExtensionInterface).IsAssignableFrom(type)) {
LoadExtension(type);
}
}
Logger.Log("main", 1, "Extension", "Loaded module {0}", module.Definition.Name);
}
catch (Exception ex) {
Logger.Log("main", 4, "Extension", "An error occured while trying to load module {0}: {1}", module.Definition.Name, ex);
}
finally {
module.Definition.Dispose();
module.Stream.Dispose();
refCounter = 0;
}
}
}
var missingList = new List<string>();
while (modules.Count > 0) {
missingList.Clear();
var module = modules.Dequeue();
foreach (var reference in module.Definition.AssemblyReferences) {
if (!asms.Contains(reference.Name)) {
missingList.Add(reference.Name);
}
}
Logger.Log("main", 4, "Extension", "Could not load the module {0} because the following dependencies were missing: {1}", module.Definition.Name, missingList.Aggregate((current, next) => current + ", " + next));
module.Definition.Dispose();
module.Stream.Dispose();
}
}
struct ModuleItem {
public ModuleDefinition Definition { get; set; }
public FileStream Stream { get; set; }
public ModuleItem(FileStream stream) {
Stream = stream;
Definition = ModuleDefinition.ReadModule(stream);
}
}
static void LoadExtension(Type type) {
try {
var extension = (ExtensionInterface)Activator.CreateInstance(type);
var l1 = extension.GetResourceConverters();
if (l1 != null) {
foreach (var c in l1) {
var fs = c.GetSupportedFormats();
if (fs == null) continue;
foreach (var f in fs) {
if (f == null) continue;
if (!_converters.ContainsKey(f))
_converters.Add(f, new List<ResourceConverter> { c });
else _converters[f].Add(c);
}
}
}
var l2 = extension.GetResourceFinders();
if (l2 != null) {
foreach (var f in l2) {
var name = f.Name;
var path = f.GetRootPath();
if (name != null && path != null) _localRes.Add(name, path);
}
}
Logger.Log("main", 1, "Extension", "Loaded extension {0}", type);
}
catch (Exception ex) {
Logger.Log("main", 4, "Extension", "Failed to load extension {0}: {1}", type, ex);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a9ea11165e6269b488f916982507a2af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,6 +12,6 @@ namespace Cryville.Crtr.Browsing {
bool ImportItemFrom(string path);
string[] GetSupportedFormats();
Dictionary<string, string> GetPresetPaths();
IReadOnlyDictionary<string, string> GetPresetPaths();
}
}

View File

@@ -1,5 +1,7 @@
using Cryville.Common;
using Cryville.Common.Unity;
using Cryville.Crtr.Extension;
using Cryville.Crtr.Extensions.Umg;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -15,49 +17,13 @@ namespace Cryville.Crtr.Browsing {
private DirectoryInfo[] items = new DirectoryInfo[0];
public string[] CurrentDirectory { get; private set; }
static readonly Dictionary<string, List<ResourceConverter>> converters
= new Dictionary<string, List<ResourceConverter>>();
static readonly Dictionary<string, string> localRes
= new Dictionary<string, string>();
static bool _init;
public LegacyResourceManager(string rootPath) {
_rootPath = rootPath;
}
static LegacyResourceManager() {
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) {
foreach (var type in asm.GetTypes()) {
if (!type.IsSubclassOf(typeof(ExtensionInterface))) continue;
var ext = (ExtensionInterface)Activator.CreateInstance(type);
try {
var cs = ext.GetResourceConverters();
if (cs != null) {
foreach (var c in cs) {
var fs = c.GetSupportedFormats();
if (fs == null) continue;
foreach (var f in fs) {
if (f == null) continue;
if (!converters.ContainsKey(f))
converters.Add(f, new List<ResourceConverter> { c });
else converters[f].Add(c);
}
}
}
var fs2 = ext.GetResourceFinders();
if (fs2 != null) {
foreach (var f in fs2) {
var name = f.Name;
var path = f.GetRootPath();
if (name != null && path != null)
localRes.Add(name, path);
}
}
Logger.Log("main", 1, "Resource", "Loaded extension {0}", ReflectionHelper.GetNamespaceQualifiedName(type));
}
catch (Exception ex) {
Logger.Log("main", 4, "Resource", "Failed to initialize extension {0}: {1}", ReflectionHelper.GetNamespaceQualifiedName(type), ex);
}
}
if (!_init) {
_init = true;
ExtensionManager.Init(rootPath);
}
}
@@ -149,14 +115,15 @@ namespace Cryville.Crtr.Browsing {
public bool ImportItemFrom(string path) {
var file = new FileInfo(path);
if (!converters.ContainsKey(file.Extension)) return false;
foreach (var converter in converters[file.Extension]) {
IEnumerable<ResourceConverter> converters;
if (!ExtensionManager.TryGetConverters(file.Extension, out converters)) return false;
foreach (var converter in converters) {
IEnumerable<Resource> resources = null;
try {
resources = converter.ConvertFrom(file);
}
catch (Exception ex) {
LogAndPopup(4, ex.Message);
LogAndPopupExtra(4, ex, "Failed to import resource: {0}", ex.Message);
return false;
}
foreach (var res in resources) {
@@ -168,7 +135,7 @@ namespace Cryville.Crtr.Browsing {
var dir = new DirectoryInfo(_rootPath + "/charts/" + res.Name);
if (!dir.Exists) dir.Create();
using (var writer = new StreamWriter(dir.FullName + "/.json")) {
writer.Write(JsonConvert.SerializeObject(tres.Main, Game.GlobalJsonSerializerSettings));
writer.Write(JsonConvert.SerializeObject(ConvertChartData(tres.Main), Game.GlobalJsonSerializerSettings));
}
using (var writer = new StreamWriter(dir.FullName + "/.umgc")) {
tres.Meta.data = "";
@@ -219,12 +186,89 @@ namespace Cryville.Crtr.Browsing {
Popup.Create(msg);
}
public string[] GetSupportedFormats() {
return converters.Keys.ToArray();
void LogAndPopupExtra(int level, object extraLog, string format, params object[] args) {
var msg = string.Format(format, args);
Logger.Log("main", level, "Resource", "{0}\n{1}", msg, extraLog);
Popup.Create(msg);
}
public Dictionary<string, string> GetPresetPaths() {
return localRes;
public string[] GetSupportedFormats() {
return ExtensionManager.GetSupportedFormats().ToArray();
}
public IReadOnlyDictionary<string, string> GetPresetPaths() {
return ExtensionManager.GetLocalResourcePaths();
}
static Chart ConvertChartData(ChartData i) {
return new Chart {
endtime = ConvertBeatTime(i.endtime),
format = i.format,
groups = ConvertGroups(i.groups),
motions = ConvertMotions(i.motions),
ruleset = i.ruleset,
sigs = ConvertSignatures(i.sigs),
sounds = ConvertSounds(i.sounds),
time = ConvertBeatTime(i.time),
};
}
static BeatTime? ConvertBeatTime(Extension.BeatTime? value) {
if (value == null) return null;
return new BeatTime(value.Value.b, value.Value.n, value.Value.d);
}
static List<Chart.Group> ConvertGroups(List<ChartData.Group> l) {
return l.Select(i => new Chart.Group {
endtime = ConvertBeatTime(i.endtime),
motions = ConvertMotions(i.motions),
notes = ConvertNotes(i.notes),
time = ConvertBeatTime(i.time),
tracks = ConvertTracks(i.tracks),
}).ToList();
}
static List<Chart.Judge> ConvertJudges(List<ChartData.Judge> l) {
return l.Select(i => new Chart.Judge {
endtime = ConvertBeatTime(i.endtime),
name = i.name,
time = ConvertBeatTime(i.time),
}).ToList();
}
static List<Chart.Motion> ConvertMotions(List<ChartData.Motion> l) {
return l.Select(i => new Chart.Motion {
endtime = ConvertBeatTime(i.endtime),
motion = i.motion,
sumfix = i.sumfix,
time = ConvertBeatTime(i.time),
}).ToList();
}
static List<Chart.Note> ConvertNotes(List<ChartData.Note> l) {
return l.Select(i => new Chart.Note {
endtime = ConvertBeatTime(i.endtime),
judges = ConvertJudges(i.judges),
motions = ConvertMotions(i.motions),
time = ConvertBeatTime(i.time),
}).ToList();
}
static List<Chart.Signature> ConvertSignatures(List<ChartData.Signature> l) {
return l.Select(i => new Chart.Signature {
endtime = ConvertBeatTime(i.endtime),
tempo = i.tempo,
time = ConvertBeatTime(i.time),
}).ToList();
}
static List<Chart.Sound> ConvertSounds(List<ChartData.Sound> l) {
return l.Select(i => new Chart.Sound {
endtime = ConvertBeatTime(i.endtime),
id = i.id,
offset = i.offset,
time = ConvertBeatTime(i.time),
}).ToList();
}
static List<Chart.Track> ConvertTracks(List<ChartData.Track> l) {
return l.Select(i => new Chart.Track {
endtime = ConvertBeatTime(i.endtime),
motions = ConvertMotions(i.motions),
time = ConvertBeatTime(i.time),
}).ToList();
}
}
}

View File

@@ -1,6 +0,0 @@
namespace Cryville.Crtr.Browsing {
public abstract class LocalResourceFinder {
public abstract string Name { get; }
public abstract string GetRootPath();
}
}

View File

@@ -9,11 +9,11 @@ namespace Cryville.Crtr.Browsing {
public override object Value {
get {
float s_value = GetDisplayValue();
return IntegerMode ? (object)(int)s_value : (object)s_value;
return IntegerMode ? (int)s_value : (object)s_value;
}
set {
if (value is double) m_value = (double)value;
else m_value = IntegerMode ? (double)(int)value : (double)(float)value;
else m_value = IntegerMode ? (int)value : (double)(float)value;
float s_value = GetDisplayValue();
m_text.text = s_value.ToString();
if (Range != null && MaxStep == 0) {

View File

@@ -1,7 +1,7 @@
using Cryville.Common;
using Cryville.Common.Unity.UI;
using Cryville.Crtr.Config;
using Newtonsoft.Json;
using Cryville.Crtr.Extension;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
@@ -94,24 +94,4 @@ namespace Cryville.Crtr.Browsing {
public AsyncDelivery<Texture2D> Cover { get; set; }
public ChartMeta Meta { get; set; }
}
#pragma warning disable IDE1006
public class MetaInfo {
public string name { get; set; }
public string author { get; set; }
[JsonRequired]
public string data { get; set; }
}
public class SongMetaInfo {
public string name { get; set; }
public string author { get; set; }
}
public class ChartMeta : MetaInfo {
public SongMetaInfo song { get; set; }
public float length { get; set; }
public string ruleset { get; set; }
public int note_count { get; set; }
public string cover { get; set; }
}
#pragma warning restore IDE1006
}

View File

@@ -1,79 +0,0 @@
using Cryville.Common;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
namespace Cryville.Crtr.Browsing {
public abstract class ResourceConverter {
public abstract string[] GetSupportedFormats();
public abstract IEnumerable<Resource> ConvertFrom(FileInfo file);
}
public abstract class Resource {
protected Resource(string name) {
Name = StringUtils.EscapeFileName(name);
}
public string Name { get; private set; }
public abstract bool Valid { get; }
public override string ToString() {
return string.Format("{0} ({1})", Name, ReflectionHelper.GetSimpleName(GetType()));
}
}
public class RawChartResource : Resource {
public RawChartResource(string name, Chart main, ChartMeta meta) : base(name) {
Main = main; Meta = meta;
}
public Chart Main { get; private set; }
public ChartMeta Meta { get; private set; }
public override bool Valid { get { return true; } }
}
public abstract class FileResource : Resource {
public FileResource(string name, FileInfo master) : base(name) {
Master = master;
Attachments = new List<FileInfo>();
}
public FileInfo Master { get; private set; }
public List<FileInfo> Attachments { get; private set; }
public override bool Valid {
get {
if (!Master.Exists) return false;
foreach (var file in Attachments) {
if (!file.Exists) return false;
}
return true;
}
}
}
public class ChartResource : FileResource {
public ChartResource(string name, FileInfo master) : base(name, master) {
using (var reader = new StreamReader(master.FullName)) {
var meta = JsonConvert.DeserializeObject<ChartMeta>(reader.ReadToEnd());
Attachments.Add(new FileInfo(Path.Combine(master.Directory.FullName, meta.data + ".json")));
if (meta.cover != null) Attachments.Add(new FileInfo(Path.Combine(master.Directory.FullName, meta.cover)));
}
}
}
public class SongResource : FileResource {
public SongResource(string name, FileInfo master) : base(name, master) { }
}
public class RulesetResource : FileResource {
public RulesetResource(string name, FileInfo master) : base(name, master) {
using (var reader = new StreamReader(master.FullName)) {
var meta = JsonConvert.DeserializeObject<Ruleset>(reader.ReadToEnd());
Attachments.Add(new FileInfo(Path.Combine(master.Directory.FullName, meta.data + ".pdt")));
}
}
}
public class SkinResource : FileResource {
public string RulesetName { get; private set; }
public SkinResource(string name, FileInfo master) : base(name, master) {
using (var reader = new StreamReader(master.FullName)) {
var meta = JsonConvert.DeserializeObject<Skin>(reader.ReadToEnd());
RulesetName = meta.ruleset;
Attachments.Add(new FileInfo(Path.Combine(master.Directory.FullName, meta.data + ".pdt")));
foreach (var frame in meta.frames) {
Attachments.Add(new FileInfo(Path.Combine(master.Directory.FullName, frame)));
}
}
}
}
}

View File

@@ -1,12 +0,0 @@
fileFormatVersion: 2
guid: 2546fb1d514348842a14a03531be192d
timeCreated: 1637982768
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,20 +0,0 @@
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Cryville.Crtr.Browsing {
public class SkinResourceImporter : ResourceConverter {
static readonly string[] SUPPORTED_FORMATS = { ".umgs" };
public override string[] GetSupportedFormats() {
return SUPPORTED_FORMATS;
}
public override IEnumerable<Resource> ConvertFrom(FileInfo file) {
using (StreamReader reader = new StreamReader(file.FullName, Encoding.UTF8)) {
var data = JsonConvert.DeserializeObject<Skin>(reader.ReadToEnd());
return new Resource[] { new SkinResource(data.name, file) };
}
}
}
}

View File

@@ -6,6 +6,7 @@ using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using UnsafeIL;
namespace Cryville.Crtr {
[JsonConverter(typeof(BeatTimeConverter))]
@@ -154,6 +155,10 @@ namespace Cryville.Crtr {
protected ChartEvent() {
PropSrcs = new Dictionary<int, PropSrc>();
PropOps = new Dictionary<int, PropOp>();
SubmitPropSrc("event", new PropSrc.Float(() => {
int hash = GetHashCode();
return Unsafe.As<int, float>(ref hash);
}));
SubmitPropSrc("long", new PropSrc.Boolean(() => IsLong));
SubmitPropSrc("time", new PropSrc.BeatTime(() => time.Value));
SubmitPropSrc("endtime", new PropSrc.BeatTime(() => endtime.Value));
@@ -320,7 +325,7 @@ namespace Cryville.Crtr {
else {
AbsoluteValue = Vector.Construct(registry.Type, m.Groups[11].Value);
}
SubmitPropSrc("value", VectorSrc.Construct(() => {
SubmitPropSrc("value", new VectorSrc(() => {
if (RelativeNode != null) return RelativeNode.Value;
else return AbsoluteValue;
}));

View File

@@ -16,7 +16,6 @@ using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.Scripting;
using UnityEngine.UI;
using diag = System.Diagnostics;
using Logger = Cryville.Common.Logger;
@@ -25,7 +24,7 @@ namespace Cryville.Crtr {
#region Fields
Chart chart;
Skin skin;
PdtSkin pskin;
public static PdtSkin pskin;
Ruleset ruleset;
PdtRuleset pruleset;
Dictionary<string, Texture2D> texs;
@@ -43,14 +42,14 @@ namespace Cryville.Crtr {
EventBus bbus;
EventBus tbus;
EventBus nbus;
InputProxy inputProxy;
Judge judge;
public static EffectManager effectManager;
bool started = false;
static bool initialized;
static Text logs;
TextMeshProUGUI logs;
TextMeshProUGUI status;
readonly TargetString statusstr = new TargetString();
readonly StringBuffer statusbuf = new StringBuffer();
static Vector2 screenSize;
public static Rect hitRect;
@@ -71,15 +70,15 @@ namespace Cryville.Crtr {
public static Dictionary<Identifier, MotionRegistry> motionRegistry = new Dictionary<Identifier, MotionRegistry>();
public static PdtEvaluator etor;
InputProxy inputProxy;
#endregion
#region MonoBehaviour
void Start() {
d_addLogEntry = new Action<int, string, string>(AddLogEntry);
var logobj = GameObject.Find("Logs");
if (logobj != null)
logs = logobj.GetComponent<Text>();
logs = logobj.GetComponent<TextMeshProUGUI>();
if (!initialized) {
Game.Init();
GenericResources.LoadDefault();
@@ -162,6 +161,8 @@ namespace Cryville.Crtr {
tbus.ForwardStepByTime(renderDist, step);
tbus.EndGraphicalUpdate();
UnityEngine.Profiling.Profiler.EndSample();
effectManager.Tick(cbus.Time);
}
catch (Exception ex) {
Game.LogException("Game", "An error occured while playing", ex);
@@ -174,10 +175,21 @@ namespace Cryville.Crtr {
string url = texLoader.url;
string name = StringUtils.TrimExt(url.Substring(url.LastIndexOfAny(new char[] {'/', '\\'}) + 1));
#if UNITY_5_4_OR_NEWER
if (texLoader.isDone) {
if (texHandler.isDone) {
var tex = texHandler.texture;
tex.wrapMode = TextureWrapMode.Clamp;
if (frames.ContainsKey(name)) {
Logger.Log("main", 3, "Load/Prehandle", "Duplicated texture name: {0}", name);
}
else {
frames.Add(name, new SpriteFrame(tex));
}
texs.Add(name, tex);
}
else {
Logger.Log("main", 4, "Load/Prehandle", "Unable to load texture: {0}", name);
}
texLoader.Dispose();
texHandler.Dispose();
texLoader = null;
@@ -192,7 +204,7 @@ namespace Cryville.Crtr {
}
#endif
}
if (texLoader == null)
if (texLoader == null) {
if (texLoadQueue.Count > 0) {
#if UNITY_5_4_OR_NEWER
texHandler = new DownloadHandlerTexture();
@@ -207,6 +219,7 @@ namespace Cryville.Crtr {
texloadtimer.Stop();
Logger.Log("main", 1, "Load/MainThread", "Main thread done ({0}ms)", texloadtimer.Elapsed.TotalMilliseconds);
}
}
if (!loadThread.IsAlive) {
if (threadException != null) {
Logger.Log("main", 4, "Load/MainThread", "Load failed");
@@ -222,9 +235,14 @@ namespace Cryville.Crtr {
}
}
}
void LogUpdate() {
string _logs = logs.text;
Game.MainLogger.Enumerate((level, module, msg) => {
readonly TargetString statusstr = new TargetString();
readonly StringBuffer statusbuf = new StringBuffer();
readonly TargetString logsstr = new TargetString();
readonly StringBuffer logsbuf = new StringBuffer();
readonly List<string> logEntries = new List<string>();
int logsLength = 0;
Action<int, string, string> d_addLogEntry;
void AddLogEntry(int level, string module, string msg) {
string color;
switch (level) {
case 0: color = "#888888"; break;
@@ -235,12 +253,28 @@ namespace Cryville.Crtr {
case 5: color = "#bb0000"; break;
default: color = "#ff00ff"; break;
}
_logs += string.Format(
"\r\n<color={1}bb><{2}> {3}</color>",
var l = string.Format(
"\n<color={1}bb><{2}> {3}</color>",
DateTime.UtcNow.ToString("s"), color, module, msg
);
});
logs.text = _logs.Substring(Mathf.Max(0, _logs.IndexOf('\n', Mathf.Max(0, _logs.Length - 4096))));
logEntries.Add(l);
logsLength += l.Length;
}
void LogUpdate() {
logsbuf.Clear();
Game.MainLogger.Enumerate(d_addLogEntry);
while (logsLength >= 4096) {
logsLength -= logEntries[0].Length;
logEntries.RemoveAt(0);
}
foreach (var l in logEntries) {
logsbuf.Append(l);
}
logsstr.Length = logsbuf.Count;
var larr = logsstr.TrustedAsArray();
logsbuf.CopyTo(0, larr, 0, logsbuf.Count);
logs.SetText(larr, 0, logsbuf.Count);
statusbuf.Clear();
statusbuf.AppendFormat(
"FPS: i{0:0} / s{1:0}\nSMem: {2:N0} / {3:N0}\nIMem: {4:N0} / {5:N0}",
@@ -281,9 +315,9 @@ namespace Cryville.Crtr {
}
}
statusstr.Length = statusbuf.Count;
var arr = statusstr.TrustedAsArray();
statusbuf.CopyTo(0, arr, 0, statusbuf.Count);
status.SetText(arr, 0, statusbuf.Count);
var sarr = statusstr.TrustedAsArray();
statusbuf.CopyTo(0, sarr, 0, statusbuf.Count);
status.SetText(sarr, 0, statusbuf.Count);
}
#endregion
@@ -313,6 +347,8 @@ namespace Cryville.Crtr {
bool logEnabled = true;
public void ToggleLogs() {
logEntries.Clear();
logsLength = 0;
logs.text = "";
status.SetText("");
logEnabled = !logEnabled;
@@ -424,16 +460,6 @@ namespace Cryville.Crtr {
try {
diag::Stopwatch timer = new diag::Stopwatch();
timer.Reset(); timer.Start();
Logger.Log("main", 0, "Load/Prehandle", "Initializing textures");
foreach (var t in texs) {
if (frames.ContainsKey(t.Key)) {
Logger.Log("main", 3, "Load/Prehandle", "Duplicated texture name: {0}", t.Key);
continue;
}
var f = new SpriteFrame(t.Value);
f.Init();
frames.Add(t.Key, f);
}
Logger.Log("main", 0, "Load/Prehandle", "Prehandling (iteration 2)");
cbus.BroadcastPreInit();
Logger.Log("main", 0, "Load/Prehandle", "Prehandling (iteration 3)");
@@ -447,15 +473,18 @@ namespace Cryville.Crtr {
Logger.Log("main", 0, "Load/Prehandle", "Cleaning up");
GC.Collect();
if (disableGC) GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;
cbus.ForwardByTime(startOffset);
bbus.ForwardByTime(startOffset);
timer.Stop();
Logger.Log("main", 1, "Load/Prehandle", "Prehandling done ({0}ms)", timer.Elapsed.TotalMilliseconds);
if (Settings.Default.ClearLogOnPlay) {
logs.text = "";
logEntries.Clear();
logsLength = 0;
Game.MainLogger.Enumerate((level, module, msg) => { });
logs.text = "";
}
Game.AudioSequencer.Playing = true;
atime0 = Game.AudioClient.BufferPosition;
Thread.Sleep((int)((atime0 - Game.AudioClient.Position) * 1000));
inputProxy.SyncTime(cbus.Time);
started = true;
}
@@ -476,6 +505,9 @@ namespace Cryville.Crtr {
if (tbus != null) { tbus.Dispose(); tbus = null; }
if (bbus != null) { bbus.Dispose(); bbus = null; }
if (cbus != null) { cbus.Dispose(); cbus.DisposeAll(); cbus = null; }
effectManager.Dispose();
effectManager = null;
etor = null;
Logger.Log("main", 1, "Game", "Stopped");
}
catch (Exception ex) {
@@ -559,7 +591,7 @@ namespace Cryville.Crtr {
inputProxy = new InputProxy(pruleset, judge);
inputProxy.LoadFrom(_rscfg.inputs);
if (!inputProxy.IsCompleted) {
if (!inputProxy.IsCompleted()) {
throw new ArgumentException("Input config not completed\nPlease complete the input settings");
}
@@ -617,6 +649,7 @@ namespace Cryville.Crtr {
skin.LoadPdt(dir);
pskin = skin.Root;
pskin.Optimize(etor);
effectManager = new EffectManager(pskin);
}
#endregion
}

View File

@@ -1,12 +1,21 @@
using System;
using UnityEngine;
namespace Cryville.Crtr.Components {
[DisallowMultipleComponent]
public abstract class MeshBase : SkinComponent {
public MeshBase() {
SubmitProperty("color", new PropOp.Color(v => Color = v));
SubmitProperty("opacity", new PropOp.Float(v => {
var c = Color;
c.a *= v;
Color = c;
}));
SubmitProperty("zindex", new PropOp.Integer(v => ZIndex = (short)v));
}
protected MeshWrapper mesh = new MeshWrapper();
protected Material[] materials;
short _zindex;
public short ZIndex {
@@ -22,9 +31,36 @@ namespace Cryville.Crtr.Components {
}
protected void UpdateZIndex() {
if (!mesh.Initialized) return;
foreach (var mat in mesh.Renderer.materials) {
foreach (var mat in materials) {
mat.renderQueue = _zindex;
}
}
Color _color = Color.white;
public Color Color {
get { return _color; }
set {
_color = value;
UpdateColor();
}
}
protected void UpdateColor() {
if (!mesh.Initialized) return;
foreach (var mat in materials) {
mat.color = _color;
}
}
protected override void OnDestroy() {
DestroyMaterials();
mesh.Destroy();
}
protected void DestroyMaterials() {
if (materials == null) return;
foreach (var mat in materials) {
Material.Destroy(mat);
}
}
}
}

View File

@@ -19,11 +19,7 @@ namespace Cryville.Crtr.Components {
public SectionalGameObject() {
SubmitProperty("partial", new PropOp.Boolean(v => part = Part.idle));
SubmitProperty("part", new PropOp.Enum<Part>(v => part = v, v => (Part)v), 2);
}
protected override void OnDestroy() {
mesh.Destroy();
SubmitProperty("part", new PropOp.Enum<Part>(v => part = v, v => (Part)v), 1);
}
public override void Init() {
@@ -67,7 +63,7 @@ namespace Cryville.Crtr.Components {
SubmitProperty("head", new PropOp.String(v => head.FrameName = v));
SubmitProperty("body", new PropOp.String(v => body.FrameName = v));
SubmitProperty("tail", new PropOp.String(v => tail.FrameName = v));
SubmitProperty("shape", new op_set_shape(this), 2);
SubmitProperty("shape", new op_set_shape(this), 1);
}
#pragma warning disable IDE1006
@@ -76,7 +72,7 @@ namespace Cryville.Crtr.Components {
public op_set_shape(PolygonSGO self) : base(1) {
_self = self;
}
protected unsafe override void Execute() {
protected override unsafe void Execute() {
var o = GetOperand(0);
if (o.Type != PdtInternalType.Vector) throw new ArgumentException("Not a vector");
_self._shapeLength = (o.Length - sizeof(int)) / sizeof(Vector2);
@@ -103,7 +99,6 @@ namespace Cryville.Crtr.Components {
public SpriteInfo body = new SpriteInfo();
public SpriteInfo tail = new SpriteInfo();
Material[] mats;
List<Vector3> vertices;
List<float> lengths;
float sumLength = 0;
@@ -112,23 +107,25 @@ namespace Cryville.Crtr.Components {
base.Init();
mesh.Init(transform);
mats = mesh.Renderer.materials = new Material[] { mesh.NewMaterial, mesh.NewMaterial, mesh.NewMaterial };
head.Bind(mats[0]);
body.Bind(mats[1]);
tail.Bind(mats[2]);
mesh.Renderer.sharedMaterials = materials = new Material[] {
MeshWrapper.NewMaterial(),
MeshWrapper.NewMaterial(),
MeshWrapper.NewMaterial(),
};
head.Bind(materials[0]);
body.Bind(materials[1]);
tail.Bind(materials[2]);
UpdateZIndex();
}
protected override void OnDestroy() {
base.OnDestroy();
Reset();
foreach (var m in mats) Material.Destroy(m);
if (_shape != null) _shapePool.Return(_shape);
if (vertices != null) {
_ptPool.Return(vertices);
_lPool.Return(lengths);
}
base.OnDestroy();
}
protected override void AppendPointInternal(Vector3 p, Quaternion r) {

View File

@@ -0,0 +1,89 @@
using Cryville.Common;
using System;
using UnityEngine;
using Logger = Cryville.Common.Logger;
namespace Cryville.Crtr.Components {
public class SkinAnimation : SkinComponent {
public SkinAnimation() {
SubmitProperty("name", new PropOp.Identifier(v => Name = v));
SubmitProperty("duration", new PropOp.Float(v => Duration = v));
SubmitProperty("iteration", new PropOp.Float(v => Iteration = v));
SubmitProperty("direction", new PropOp.Enum<AnimationDirection>(v => Direction = v, v => (AnimationDirection)v));
SubmitProperty("delay", new PropOp.Float(v => Delay = v));
Iteration = 1;
}
SkinContext _skinContext;
Transform _writeTransform;
AnimationSpan _anim;
int _name;
public int Name {
set {
if (_name == value) return;
_name = value;
if (value == 0) {
_anim = null;
}
else {
var id = new Identifier(value);
AnimationSpan anim;
if (!ChartPlayer.pskin.animations.TryGetValue(id, out anim)) {
Logger.Log("main", 4, "Skin", "Animation {0} not found", id.Name);
_anim = null;
return;
}
_anim = anim;
}
}
}
public float Duration { get; private set; }
public float Iteration { get; private set; }
public AnimationDirection Direction { get; private set; }
public float Delay { get; private set; }
double _startTime;
public override void Init() {
_skinContext = new SkinContext(transform);
}
public override void Rewind(double time, Transform target) {
_startTime = time;
if (target == null) target = transform;
_writeTransform = target;
}
public override void Tick(SkinContainer c, double time) {
float _rtime = (float)(time - _startTime - Delay) / Duration;
if (_rtime < 0) _rtime = 0;
else if (_rtime > Iteration) {
if (Direction.HasFlag(AnimationDirection.alternate)) {
_rtime = Iteration % 2;
if (_rtime > 1) _rtime = 2 - _rtime;
}
else {
_rtime = Iteration % 1;
if (_rtime == 0) _rtime = 1;
}
}
else {
if (Direction.HasFlag(AnimationDirection.alternate)) {
_rtime %= 2;
if (_rtime > 1) _rtime = 2 - _rtime;
}
else {
_rtime %= 1;
}
}
if (Direction.HasFlag(AnimationDirection.reverse)) _rtime = 1 - _rtime;
if (_anim != null) c.MatchAnimation(_anim, _rtime, new RuntimeSkinContext(_skinContext, _writeTransform));
}
protected override void OnDestroy() { }
}
[Flags]
public enum AnimationDirection {
normal = 0,
reverse = 1,
alternate = 2,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 80318e36af5412345871bdbf80d49ef2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -14,8 +14,8 @@ namespace Cryville.Crtr.Components {
/// </summary>
/// <param name="name">The name of the property.</param>
/// <param name="property">The property.</param>
protected void SubmitProperty(string name, PdtOperator property, int uct = 1) {
Properties.Add(IdentifierManager.SharedInstance.Request(name), new SkinProperty(property, uct));
protected void SubmitProperty(string name, PdtOperator property, int udl = 0) {
Properties.Add(IdentifierManager.SharedInstance.Request(name), new SkinProperty(property, udl));
}
/// <summary>
@@ -26,14 +26,16 @@ namespace Cryville.Crtr.Components {
}
public virtual void Init() { }
public virtual void Rewind(double time, Transform target) { }
public virtual void Tick(SkinContainer c, double time) { }
protected abstract void OnDestroy();
}
public struct SkinProperty {
public PdtOperator Operator { get; set; }
public int UpdateCloneType { get; set; }
public SkinProperty(PdtOperator op, int uct = 1) {
public int UpdateDynamicLevel { get; set; }
public SkinProperty(PdtOperator op, int udl = 0) {
Operator = op;
UpdateCloneType = uct;
UpdateDynamicLevel = udl;
}
}
}

View File

@@ -25,10 +25,6 @@ namespace Cryville.Crtr.Components {
}
#pragma warning restore IDE1006
protected override void OnDestroy() {
mesh.Destroy();
}
Vector2 _scale = Vector2.one;
public Vector2 Scale {
get { return _scale; }
@@ -92,7 +88,9 @@ namespace Cryville.Crtr.Components {
protected void InternalInit(string meshName = "quad") {
mesh.Init(transform);
mesh.Renderer.sharedMaterials = materials = new Material[] { MeshWrapper.NewMaterial() };
mesh.Mesh = GenericResources.Meshes[meshName];
UpdateColor();
UpdateScale();
UpdateZIndex();
}

View File

@@ -29,19 +29,12 @@ namespace Cryville.Crtr.Components {
return Rect.width / Rect.height;
}
}
bool _loaded;
Material _mat;
public void Bind(Material mat) {
_loaded = true;
_mat = mat;
Reload();
}
public void Load() {
_loaded = true;
Reload();
}
public void Reload() {
if (!_loaded) return;
if (!string.IsNullOrEmpty(FrameName)) {
if (ChartPlayer.frames.ContainsKey(FrameName)) {
Frame = ChartPlayer.frames[FrameName];
@@ -56,13 +49,18 @@ namespace Cryville.Crtr.Components {
_mat.mainTexture = Frame == null ? null : Frame.Texture;
}
}
public static bool IsNullOrEmpty(SpriteInfo sprite) {
return sprite == null || sprite.Frame == null;
}
}
public class SpritePlane : SpriteBase {
public SpritePlane() {
SubmitProperty("frame", new PropOp.String(v => Frame = v));
SubmitProperty("frames", new PropOp.StringArray(v => Frames = v));
SubmitProperty("index", new PropOp.Integer(v => Index = v));
SubmitProperty("fit", new PropOp.Enum<FitMode>(v => Fit = v, v => (FitMode)v));
SubmitProperty("opacity", new PropOp.Float(v => Opacity = v));
SubmitProperty("shader", new PropOp.String(v => Shader = v));
}
static Vector2[] _origuv;
@@ -83,52 +81,73 @@ namespace Cryville.Crtr.Components {
}
}
protected SpriteInfo frameInfo = new SpriteInfo();
public string Frame {
get { return frameInfo.FrameName; }
int m_index;
public int Index {
get { return m_index; }
set {
frameInfo.FrameName = value;
m_index = value;
OnFrameUpdate();
}
}
SpriteInfo[] m_frames = new SpriteInfo[] { new SpriteInfo() };
public string[] Frames {
set {
m_frames = new SpriteInfo[value.Length];
for (int i = 0; i < value.Length; i++) {
m_frames[i] = new SpriteInfo() { FrameName = value[i] };
}
OnFrameUpdate();
}
}
public string Frame {
set {
if (value == CurrentFrame.FrameName) return;
CurrentFrame.FrameName = value;
OnFrameUpdate();
}
}
protected SpriteInfo CurrentFrame {
get {
if (m_frames.Length == 0) return null;
if (m_index < 0) m_index = 0;
else if (m_index >= m_frames.Length) m_index = m_frames.Length - 1;
return m_frames[m_index];
}
}
protected void OnFrameUpdate() {
if (!mesh.Initialized) return;
if (frameInfo.Frame == null) {
var frame = CurrentFrame;
if (SpriteInfo.IsNullOrEmpty(frame)) {
mesh.Renderer.enabled = false;
return;
}
mesh.Renderer.enabled = true;
mesh.Renderer.sharedMaterial.mainTexture = frame.Frame.Texture;
UpdateUV();
UpdateScale();
}
Shader m_shader;
public string Shader {
set {
m_shader = GenericResources.Shaders[value];
UpdateShader();
}
}
void UpdateShader() {
if (!mesh.Initialized) return;
if (m_shader == null) m_shader = GenericResources.Shaders["default"];
mesh.Renderer.sharedMaterial.shader = m_shader;
UpdateZIndex();
}
readonly Vector2[] _uvs = new Vector2[4];
protected virtual void UpdateUV() {
if (frameInfo.Frame == null) {
Logger.Log("main", 4, "Skin", "Unable to load texture {0}", frameInfo.FrameName);
return;
}
var frame = CurrentFrame;
if (SpriteInfo.IsNullOrEmpty(frame)) return;
Vector2[] muv = OriginalUV;
Vector2[] uv = new Vector2[muv.Length];
for (int i = 0; i < uv.Length; i++) {
uv[i] = frameInfo.Frame.GetUV(muv[i]);
for (int i = 0; i < _uvs.Length; i++) {
_uvs[i] = frame.Frame.GetUV(muv[i]);
}
mesh.Mesh.uv = uv;
}
float _opacity = 1;
public float Opacity {
get { return _opacity; }
set {
_opacity = value;
UpdateOpacity();
}
}
void UpdateOpacity() {
if (!mesh.Initialized) return;
var c = mesh.Renderer.material.color;
c.a = _opacity;
mesh.Renderer.material.color = c;
mesh.Mesh.uv = _uvs;
}
private FitMode m_fit = FitMode.height;
@@ -144,7 +163,7 @@ namespace Cryville.Crtr.Components {
}
protected override void UpdateScale() {
if (frameInfo.Frame == null) return;
if (SpriteInfo.IsNullOrEmpty(CurrentFrame)) return;
base.UpdateScale();
if (m_fit != FitMode.none && Scale.x != Scale.y) m_fit = FitMode.none;
}
@@ -153,8 +172,8 @@ namespace Cryville.Crtr.Components {
get {
switch (m_fit) {
case FitMode.none: return Vector3.one;
case FitMode.width: return new Vector3(1, 1, 1 / frameInfo.Ratio);
case FitMode.height: return new Vector3(frameInfo.Ratio, 1, 1);
case FitMode.width: return new Vector3(1, 1, 1 / CurrentFrame.Ratio);
case FitMode.height: return new Vector3(CurrentFrame.Ratio, 1, 1);
default: throw new NotSupportedException("Unsupported fit mode");
}
}
@@ -162,9 +181,8 @@ namespace Cryville.Crtr.Components {
public override void Init() {
InternalInit();
frameInfo.Bind(mesh.Renderer.material);
OnFrameUpdate();
UpdateOpacity();
UpdateShader();
}
}
}

View File

@@ -2,22 +2,7 @@
namespace Cryville.Crtr.Components {
public class SpriteRect : SpriteBase {
public SpriteRect() {
SubmitProperty("color", new PropOp.Color(v => Color = v));
}
Color _color;
public Color Color {
get { return _color; }
set {
_color = value;
OnColorUpdate();
}
}
void OnColorUpdate() {
if (!mesh.Initialized) return;
mesh.Renderer.material.SetColor("_Color", _color);
}
public SpriteRect() { }
protected override Vector3 BaseScale {
get { return Vector3.one; }
@@ -25,7 +10,6 @@ namespace Cryville.Crtr.Components {
public override void Init() {
InternalInit();
OnColorUpdate();
}
}
}

View File

@@ -8,12 +8,12 @@ namespace Cryville.Crtr.Components {
SubmitProperty("border", new PropOp.Vector2(v => Border = v));
}
readonly static Dictionary<float, int> uvrefl
static readonly Dictionary<float, int> uvrefl
= new Dictionary<float, int>() {
{-0.5f, 0}, {-0.4f, 1}, {0.4f, 2}, {0.5f, 3},
};
static Vector2[] _origuv;
protected new static Vector2[] OriginalUV {
protected static new Vector2[] OriginalUV {
get {
if (_origuv == null) {
var m = GenericResources.Meshes["quad_scale3h"];
@@ -44,24 +44,26 @@ namespace Cryville.Crtr.Components {
UpdateUV();
}
readonly Vector2[] _uvs = new Vector2[8];
readonly Vector3[] _verts = new Vector3[8];
protected override void UpdateUV() {
Vector2[] muv = OriginalUV;
Vector2[] uv = new Vector2[muv.Length];
var frame = CurrentFrame;
if (SpriteInfo.IsNullOrEmpty(frame)) return;
var or = frameInfo.Ratio;
Vector2[] muv = OriginalUV;
var or = frame.Ratio;
var sr = Scale.x / Scale.y;
var b = new Vector2(
(or / sr) * _border.x,
1 - (or / sr) * (1 - _border.y)
);
Vector3[] vert = mesh.Mesh.vertices;
var rr = or / sr;
var b1 = rr * _border.x;
var b2 = 1 - rr * (1 - _border.y);
for (int i = 0; i < muv.Length; i++) {
float x; float bx;
switch ((int)muv[i].x) {
case 0: x = 0; bx = 0; break;
case 1: x = _border.x; bx = b.x; break;
case 2: x = _border.y; bx = b.y; break;
case 1: x = _border.x; bx = b1; break;
case 2: x = _border.y; bx = b2; break;
case 3: x = 1; bx = 1; break;
default: throw new NotSupportedException("Built-in resource corrupted");
}
@@ -71,16 +73,15 @@ namespace Cryville.Crtr.Components {
case 3: y = 1; break;
default: throw new NotSupportedException("Built-in resource corrupted");
}
uv[i] = frameInfo.Frame.GetUV(x, y);
_uvs[i] = frame.Frame.GetUV(x, y);
bx -= 0.5f; y -= 0.5f;
vert[i] = new Vector3(bx, 0, y);
_verts[i] = new Vector3(bx, 0, y);
}
mesh.Mesh.uv = uv;
mesh.Mesh.vertices = vert;
mesh.Mesh.uv = _uvs;
mesh.Mesh.vertices = _verts;
}
public override void Init() {
frameInfo.Load();
InternalInit("quad_scale3h");
OnFrameUpdate();
}

Some files were not shown because too many files have changed in this diff Show More