Compare commits
96 Commits
0.6.0-rc2
...
92a3d5018f
Author | SHA1 | Date | |
---|---|---|---|
92a3d5018f | |||
d510fec57b | |||
054b17811d | |||
94d5f7f82e | |||
0e4445e52b | |||
c5214dd477 | |||
ed2c216cf4 | |||
609645c108 | |||
d280d27a0a | |||
5b727065f3 | |||
7aa2577059 | |||
c1b7e9ab55 | |||
99384397ed | |||
a2391aeb22 | |||
2207c80951 | |||
bf578d7cb9 | |||
0bc57c368f | |||
b64f85aaa2 | |||
93fa2f2d7e | |||
d72216de8b | |||
df5133a91a | |||
88b959a118 | |||
310bf91fbd | |||
699f47f98d | |||
24e881b138 | |||
2eef1b5c4e | |||
c18ceb50d4 | |||
27ca1a7292 | |||
dc59176eac | |||
aec7470ff8 | |||
983cba6843 | |||
871782e73f | |||
9aaa96fe10 | |||
22190a29c1 | |||
613ca467d0 | |||
536a3066b2 | |||
43488cd002 | |||
a11ccbd39c | |||
76df4929a7 | |||
505b826627 | |||
26a8675922 | |||
b89e1f983e | |||
717e77b47e | |||
2f10c79dee | |||
55f7790f89 | |||
ae5f4a8c16 | |||
1851bd3c54 | |||
6d74685cb7 | |||
03fd7f6d01 | |||
28c878f3e5 | |||
7736eba14d | |||
2e54b38d2b | |||
da60dc0903 | |||
215f72b3b5 | |||
a93c081dd8 | |||
456782930a | |||
ba3cbbd64c | |||
dfc3e9ca06 | |||
f567a2b78e | |||
c7e7bd8a77 | |||
67720fd0e1 | |||
1a30149942 | |||
a755cc13bd | |||
9a51cf1b56 | |||
256c656e9c | |||
2ac7f05316 | |||
28d46dbabe | |||
18b3e0bc84 | |||
23f2e7c1f2 | |||
998713b41f | |||
3561354231 | |||
0cccb170c1 | |||
d2480b8a6f | |||
6837d3f7ee | |||
3ecf3b4bfc | |||
1da8647ff1 | |||
2f19e8daad | |||
07f62c7aeb | |||
39db8dfa45 | |||
f04cd370f1 | |||
5c4acd54ce | |||
82dbc5c479 | |||
1f1663d714 | |||
a3c5392caa | |||
6c983cc2cb | |||
3bf3fdac3d | |||
f2f3dba098 | |||
3728360dd2 | |||
887837bb3d | |||
99b4c2dfc1 | |||
e59769158a | |||
ba3238614b | |||
a115999aab | |||
393947db9f | |||
e9b2a7f894 | |||
9c73455761 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -68,3 +68,4 @@ crashlytics-build.properties
|
|||||||
/UserSettings
|
/UserSettings
|
||||||
/*.zip
|
/*.zip
|
||||||
*.lnk
|
*.lnk
|
||||||
|
/HybridCLRData
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 5335612e48e4c3947808c99fb99411d5
|
guid: c4ef48e4a4983de4e9c31483df2a918e
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 6823ead66b33bc048bbad48719feb25d
|
guid: 9ec674235c0dd6744af2dab2b58dd53c
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
8
Assets/Cryville/Common/Collections/Generic/IPairList.cs
Normal file
8
Assets/Cryville/Common/Collections/Generic/IPairList.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: f5b3f3294f679f14f8ec1195b0def630
|
guid: 73fb17b484b343242bcce27c15ed7d44
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
46
Assets/Cryville/Common/Collections/Generic/PairCollection.cs
Normal file
46
Assets/Cryville/Common/Collections/Generic/PairCollection.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 23377bf2926d93a4b8e3f3ab6040c7f2
|
guid: 2517e8f040bd36f46948e5fafaf5335c
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
48
Assets/Cryville/Common/Collections/Generic/PairList.cs
Normal file
48
Assets/Cryville/Common/Collections/Generic/PairList.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 4ffe72fef6ebb9e4da3571b4117f0d6d
|
guid: d9ed5ea8b7b1a934287e7ec5971166c0
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
8
Assets/Cryville/Common/Collections/IPairList.cs
Normal file
8
Assets/Cryville/Common/Collections/IPairList.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e3c5a8bf05d5e284ba498e91cb0dd35e
|
guid: 046617672d437de4ab7e644a55defd3b
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
47
Assets/Cryville/Common/Collections/PairCollection.cs
Normal file
47
Assets/Cryville/Common/Collections/PairCollection.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Cryville/Common/Collections/PairCollection.cs.meta
Normal file
11
Assets/Cryville/Common/Collections/PairCollection.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1f87dfb8f6a1f5640b6deae741cd715c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
29
Assets/Cryville/Common/Collections/PairList.cs
Normal file
29
Assets/Cryville/Common/Collections/PairList.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Cryville/Common/Collections/PairList.cs.meta
Normal file
11
Assets/Cryville/Common/Collections/PairList.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 57fc9f037c1fda5449e2a365a835c82c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -45,7 +45,7 @@ namespace Cryville.Common.Font {
|
|||||||
return tableDirectoryOffsets;
|
return tableDirectoryOffsets;
|
||||||
}
|
}
|
||||||
public override TableDirectory GetSubTable(UInt32 item) {
|
public override TableDirectory GetSubTable(UInt32 item) {
|
||||||
var i = (UInt32)item;
|
var i = item;
|
||||||
return new TableDirectory(Reader, i);
|
return new TableDirectory(Reader, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Cryville.Common {
|
namespace Cryville.Common {
|
||||||
public struct Identifier : IEquatable<Identifier> {
|
public struct Identifier : IEquatable<Identifier> {
|
||||||
|
public static Identifier Empty = new Identifier(0);
|
||||||
public int Key { get; private set; }
|
public int Key { get; private set; }
|
||||||
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
|
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
|
||||||
public Identifier(int key) {
|
public Identifier(int key) {
|
||||||
|
44
Assets/Cryville/Common/Math/CubicBezier.cs
Normal file
44
Assets/Cryville/Common/Math/CubicBezier.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Cryville/Common/Math/CubicBezier.cs.meta
Normal file
11
Assets/Cryville/Common/Math/CubicBezier.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 17dd6f775fc965f43960da7166b55b87
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -12,12 +12,12 @@ namespace Cryville.Common.Math {
|
|||||||
/// <param name="error">The error.</param>
|
/// <param name="error">The error.</param>
|
||||||
/// <param name="n">The numerator.</param>
|
/// <param name="n">The numerator.</param>
|
||||||
/// <param name="d">The denominator.</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) {
|
public static void ToFraction(double value, double error, out int n, out int d) {
|
||||||
if (value < 0.0)
|
if (value < 0.0)
|
||||||
throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
|
throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
|
||||||
if (error <= 0.0 || error >= 1.0)
|
if (error <= 0.0 || error > 1.0)
|
||||||
throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
|
throw new ArgumentOutOfRangeException("error", "Must be > 0 and <= 1.");
|
||||||
|
|
||||||
int num = (int)System.Math.Floor(value);
|
int num = (int)System.Math.Floor(value);
|
||||||
value -= num;
|
value -= num;
|
||||||
|
@@ -5,7 +5,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// Indicates that the attributed member is an element list.
|
/// Indicates that the attributed member is an element list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <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>
|
/// </remarks>
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||||
public class ElementListAttribute : Attribute { }
|
public class ElementListAttribute : Attribute { }
|
||||||
@@ -14,7 +14,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// Indicates that the attributed member is a property list.
|
/// Indicates that the attributed member is a property list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <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>
|
/// </remarks>
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||||
public class PropertyListAttribute : Attribute { }
|
public class PropertyListAttribute : Attribute { }
|
||||||
|
@@ -92,7 +92,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public partial class PdtInterpreter {
|
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 },
|
{ '@', 7 },
|
||||||
{ '*', 6 }, { '/', 6 }, { '%', 6 },
|
{ '*', 6 }, { '/', 6 }, { '%', 6 },
|
||||||
{ '+', 5 }, { '-', 5 },
|
{ '+', 5 }, { '-', 5 },
|
||||||
@@ -103,7 +103,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
{ ',', 0 },
|
{ ',', 0 },
|
||||||
{ '$', -1 },
|
{ '$', -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 }, { '/', 0 }, { '%', 0 },
|
||||||
{ '+', 0 }, { '-', 0 },
|
{ '+', 0 }, { '-', 0 },
|
||||||
@@ -115,7 +115,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
{ '$', -1 },
|
{ '$', -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
readonly static PdtExpression _emptyexp;
|
static readonly PdtExpression _emptyexp;
|
||||||
static PdtInterpreter() {
|
static PdtInterpreter() {
|
||||||
var ins = new LinkedList<PdtInstruction>();
|
var ins = new LinkedList<PdtInstruction>();
|
||||||
ins.AddLast(new PdtInstruction.PushConstant(
|
ins.AddLast(new PdtInstruction.PushConstant(
|
||||||
@@ -143,7 +143,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("0x{0:x4}: {1}", Type, Value);
|
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,
|
Type = 0x0080,
|
||||||
Value = "$",
|
Value = "$",
|
||||||
};
|
};
|
||||||
|
@@ -6,30 +6,30 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Error type.
|
/// Error type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Error = 0x00525245;
|
public const int Error = 0x00525245;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Array of a same variable-length type, with a suffix indicating the element count and the element type.
|
/// Array of a same variable-length type, with a suffix indicating the element count and the element type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Array = 0x00525241;
|
public const int Array = 0x00525241;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Null type.
|
/// Null type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Null = 0x4c4c554e;
|
public const int Null = 0x4c4c554e;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IEEE 754 32-bit floating-point number.
|
/// IEEE 754 32-bit floating-point number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Number = 0x004d554e;
|
public const int Number = 0x004d554e;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units.
|
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int String = 0x00525453;
|
public const int String = 0x00525453;
|
||||||
/// <summary>
|
/// <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.
|
/// 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>
|
/// </summary>
|
||||||
public readonly static int Undefined = 0x00444e55;
|
public const int Undefined = 0x00444e55;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Vector of a same constant-length type, with a suffix indicating the element type.
|
/// Vector of a same constant-length type, with a suffix indicating the element type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Vector = 0x00434556;
|
public const int Vector = 0x00434556;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Cryville.Common.Collections;
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -27,7 +28,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// <item><term><c>0x1000</c></term><description>End of Key</description></item>
|
/// <item><term><c>0x1000</c></term><description>End of Key</description></item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </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
|
// 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, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
@@ -255,13 +256,13 @@ namespace Cryville.Common.Pdt {
|
|||||||
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
|
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
|
||||||
Type ptype = ReflectionHelper.GetMemberType(prop);
|
Type ptype = ReflectionHelper.GetMemberType(prop);
|
||||||
if (flag) {
|
if (flag) {
|
||||||
if (!typeof(IDictionary).IsAssignableFrom(ptype))
|
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
|
||||||
throw new InvalidOperationException("Internal error: Element list is not a dictionary");
|
var ktype = ptype.GetGenericArguments()[0];
|
||||||
var ktype = ptype.GetGenericArguments()[0];
|
var vtype = ptype.GetGenericArguments()[1];
|
||||||
var vtype = ptype.GetGenericArguments()[1];
|
object key = _binder.ChangeType(pkey, ktype, null);
|
||||||
object key = _binder.ChangeType(pkey, ktype, null);
|
object value = InterpretObject(vtype);
|
||||||
object value = InterpretObject(vtype);
|
collection.Add(key, value);
|
||||||
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
|
}
|
||||||
}
|
}
|
||||||
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
|
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
|
||||||
}
|
}
|
||||||
@@ -284,13 +285,13 @@ namespace Cryville.Common.Pdt {
|
|||||||
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
|
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
|
||||||
var ptype = ReflectionHelper.GetMemberType(prop);
|
var ptype = ReflectionHelper.GetMemberType(prop);
|
||||||
if (flag) {
|
if (flag) {
|
||||||
if (!typeof(IDictionary).IsAssignableFrom(ptype))
|
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
|
||||||
throw new InvalidOperationException("Internal error: Property list is not a dictionary");
|
var ktype = ptype.GetGenericArguments()[0];
|
||||||
var ktype = ptype.GetGenericArguments()[0];
|
var vtype = ptype.GetGenericArguments()[1];
|
||||||
var vtype = ptype.GetGenericArguments()[1];
|
object key = _binder.ChangeType(pkey, ktype, null);
|
||||||
object key = _binder.ChangeType(pkey, ktype, null);
|
object value = _binder.ChangeType(exp, vtype, null);
|
||||||
object value = _binder.ChangeType(exp, vtype, null);
|
collection.Add(key, value);
|
||||||
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
object value = _binder.ChangeType(exp, ptype, null);
|
object value = _binder.ChangeType(exp, ptype, null);
|
||||||
|
@@ -4,7 +4,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// PDT operator.
|
/// PDT operator.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe abstract class PdtOperator {
|
public abstract unsafe class PdtOperator {
|
||||||
byte* _prmem;
|
byte* _prmem;
|
||||||
int _loadindex;
|
int _loadindex;
|
||||||
readonly PdtVariableMemory[] _operands;
|
readonly PdtVariableMemory[] _operands;
|
||||||
|
@@ -28,8 +28,8 @@ namespace Cryville.Common.Unity {
|
|||||||
set { m_filter = value; }
|
set { m_filter = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, string> m_presetPaths = new Dictionary<string, string>();
|
public IReadOnlyDictionary<string, string> m_presetPaths = new Dictionary<string, string>();
|
||||||
public Dictionary<string, string> PresetPaths {
|
public IReadOnlyDictionary<string, string> PresetPaths {
|
||||||
get { return m_presetPaths; }
|
get { return m_presetPaths; }
|
||||||
set { m_presetPaths = value; }
|
set { m_presetPaths = value; }
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,6 @@ using UnityEngine;
|
|||||||
namespace Cryville.Common.Unity.UI {
|
namespace Cryville.Common.Unity.UI {
|
||||||
public abstract class SetParameterBehaviour : StateMachineBehaviour {
|
public abstract class SetParameterBehaviour : StateMachineBehaviour {
|
||||||
[SerializeField] protected string m_name;
|
[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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
138
Assets/Cryville/Crtr/Browsing/ExtensionManager.cs
Normal file
138
Assets/Cryville/Crtr/Browsing/ExtensionManager.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Cryville/Crtr/Browsing/ExtensionManager.cs.meta
Normal file
11
Assets/Cryville/Crtr/Browsing/ExtensionManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a9ea11165e6269b488f916982507a2af
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -12,6 +12,6 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
|
|
||||||
bool ImportItemFrom(string path);
|
bool ImportItemFrom(string path);
|
||||||
string[] GetSupportedFormats();
|
string[] GetSupportedFormats();
|
||||||
Dictionary<string, string> GetPresetPaths();
|
IReadOnlyDictionary<string, string> GetPresetPaths();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,7 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common;
|
||||||
using Cryville.Common.Unity;
|
using Cryville.Common.Unity;
|
||||||
|
using Cryville.Crtr.Extension;
|
||||||
|
using Cryville.Crtr.Extensions.Umg;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -15,49 +17,13 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
private DirectoryInfo[] items = new DirectoryInfo[0];
|
private DirectoryInfo[] items = new DirectoryInfo[0];
|
||||||
public string[] CurrentDirectory { get; private set; }
|
public string[] CurrentDirectory { get; private set; }
|
||||||
|
|
||||||
static readonly Dictionary<string, List<ResourceConverter>> converters
|
static bool _init;
|
||||||
= new Dictionary<string, List<ResourceConverter>>();
|
|
||||||
static readonly Dictionary<string, string> localRes
|
|
||||||
= new Dictionary<string, string>();
|
|
||||||
|
|
||||||
public LegacyResourceManager(string rootPath) {
|
public LegacyResourceManager(string rootPath) {
|
||||||
_rootPath = rootPath;
|
_rootPath = rootPath;
|
||||||
}
|
if (!_init) {
|
||||||
|
_init = true;
|
||||||
static LegacyResourceManager() {
|
ExtensionManager.Init(rootPath);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,14 +115,15 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
|
|
||||||
public bool ImportItemFrom(string path) {
|
public bool ImportItemFrom(string path) {
|
||||||
var file = new FileInfo(path);
|
var file = new FileInfo(path);
|
||||||
if (!converters.ContainsKey(file.Extension)) return false;
|
IEnumerable<ResourceConverter> converters;
|
||||||
foreach (var converter in converters[file.Extension]) {
|
if (!ExtensionManager.TryGetConverters(file.Extension, out converters)) return false;
|
||||||
|
foreach (var converter in converters) {
|
||||||
IEnumerable<Resource> resources = null;
|
IEnumerable<Resource> resources = null;
|
||||||
try {
|
try {
|
||||||
resources = converter.ConvertFrom(file);
|
resources = converter.ConvertFrom(file);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
LogAndPopup(4, ex.Message);
|
LogAndPopupExtra(4, ex, "Failed to import resource: {0}", ex.Message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
foreach (var res in resources) {
|
foreach (var res in resources) {
|
||||||
@@ -168,7 +135,7 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
var dir = new DirectoryInfo(_rootPath + "/charts/" + res.Name);
|
var dir = new DirectoryInfo(_rootPath + "/charts/" + res.Name);
|
||||||
if (!dir.Exists) dir.Create();
|
if (!dir.Exists) dir.Create();
|
||||||
using (var writer = new StreamWriter(dir.FullName + "/.json")) {
|
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")) {
|
using (var writer = new StreamWriter(dir.FullName + "/.umgc")) {
|
||||||
tres.Meta.data = "";
|
tres.Meta.data = "";
|
||||||
@@ -219,12 +186,89 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
Popup.Create(msg);
|
Popup.Create(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] GetSupportedFormats() {
|
void LogAndPopupExtra(int level, object extraLog, string format, params object[] args) {
|
||||||
return converters.Keys.ToArray();
|
var msg = string.Format(format, args);
|
||||||
|
Logger.Log("main", level, "Resource", "{0}\n{1}", msg, extraLog);
|
||||||
|
Popup.Create(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, string> GetPresetPaths() {
|
public string[] GetSupportedFormats() {
|
||||||
return localRes;
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,6 +0,0 @@
|
|||||||
namespace Cryville.Crtr.Browsing {
|
|
||||||
public abstract class LocalResourceFinder {
|
|
||||||
public abstract string Name { get; }
|
|
||||||
public abstract string GetRootPath();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -9,11 +9,11 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
public override object Value {
|
public override object Value {
|
||||||
get {
|
get {
|
||||||
float s_value = GetDisplayValue();
|
float s_value = GetDisplayValue();
|
||||||
return IntegerMode ? (object)(int)s_value : (object)s_value;
|
return IntegerMode ? (int)s_value : (object)s_value;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if (value is double) m_value = (double)value;
|
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();
|
float s_value = GetDisplayValue();
|
||||||
m_text.text = s_value.ToString();
|
m_text.text = s_value.ToString();
|
||||||
if (Range != null && MaxStep == 0) {
|
if (Range != null && MaxStep == 0) {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common;
|
||||||
using Cryville.Common.Unity.UI;
|
using Cryville.Common.Unity.UI;
|
||||||
using Cryville.Crtr.Config;
|
using Cryville.Crtr.Config;
|
||||||
using Newtonsoft.Json;
|
using Cryville.Crtr.Extension;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
@@ -94,24 +94,4 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
public AsyncDelivery<Texture2D> Cover { get; set; }
|
public AsyncDelivery<Texture2D> Cover { get; set; }
|
||||||
public ChartMeta Meta { 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
|
|
||||||
}
|
}
|
||||||
|
@@ -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)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2546fb1d514348842a14a03531be192d
|
|
||||||
timeCreated: 1637982768
|
|
||||||
licenseType: Free
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -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) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -6,6 +6,7 @@ using System.ComponentModel;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using UnsafeIL;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
[JsonConverter(typeof(BeatTimeConverter))]
|
[JsonConverter(typeof(BeatTimeConverter))]
|
||||||
@@ -154,6 +155,10 @@ namespace Cryville.Crtr {
|
|||||||
protected ChartEvent() {
|
protected ChartEvent() {
|
||||||
PropSrcs = new Dictionary<int, PropSrc>();
|
PropSrcs = new Dictionary<int, PropSrc>();
|
||||||
PropOps = new Dictionary<int, PropOp>();
|
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("long", new PropSrc.Boolean(() => IsLong));
|
||||||
SubmitPropSrc("time", new PropSrc.BeatTime(() => time.Value));
|
SubmitPropSrc("time", new PropSrc.BeatTime(() => time.Value));
|
||||||
SubmitPropSrc("endtime", new PropSrc.BeatTime(() => endtime.Value));
|
SubmitPropSrc("endtime", new PropSrc.BeatTime(() => endtime.Value));
|
||||||
@@ -320,7 +325,7 @@ namespace Cryville.Crtr {
|
|||||||
else {
|
else {
|
||||||
AbsoluteValue = Vector.Construct(registry.Type, m.Groups[11].Value);
|
AbsoluteValue = Vector.Construct(registry.Type, m.Groups[11].Value);
|
||||||
}
|
}
|
||||||
SubmitPropSrc("value", VectorSrc.Construct(() => {
|
SubmitPropSrc("value", new VectorSrc(() => {
|
||||||
if (RelativeNode != null) return RelativeNode.Value;
|
if (RelativeNode != null) return RelativeNode.Value;
|
||||||
else return AbsoluteValue;
|
else return AbsoluteValue;
|
||||||
}));
|
}));
|
||||||
|
@@ -24,7 +24,7 @@ namespace Cryville.Crtr {
|
|||||||
#region Fields
|
#region Fields
|
||||||
Chart chart;
|
Chart chart;
|
||||||
Skin skin;
|
Skin skin;
|
||||||
PdtSkin pskin;
|
public static PdtSkin pskin;
|
||||||
Ruleset ruleset;
|
Ruleset ruleset;
|
||||||
PdtRuleset pruleset;
|
PdtRuleset pruleset;
|
||||||
Dictionary<string, Texture2D> texs;
|
Dictionary<string, Texture2D> texs;
|
||||||
@@ -175,16 +175,21 @@ namespace Cryville.Crtr {
|
|||||||
string url = texLoader.url;
|
string url = texLoader.url;
|
||||||
string name = StringUtils.TrimExt(url.Substring(url.LastIndexOfAny(new char[] {'/', '\\'}) + 1));
|
string name = StringUtils.TrimExt(url.Substring(url.LastIndexOfAny(new char[] {'/', '\\'}) + 1));
|
||||||
#if UNITY_5_4_OR_NEWER
|
#if UNITY_5_4_OR_NEWER
|
||||||
if (texHandler.isDone) {
|
if (texLoader.isDone) {
|
||||||
var tex = texHandler.texture;
|
if (texHandler.isDone) {
|
||||||
tex.wrapMode = TextureWrapMode.Clamp;
|
var tex = texHandler.texture;
|
||||||
if (frames.ContainsKey(name)) {
|
tex.wrapMode = TextureWrapMode.Clamp;
|
||||||
Logger.Log("main", 3, "Load/Prehandle", "Duplicated texture name: {0}", name);
|
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 {
|
else {
|
||||||
frames.Add(name, new SpriteFrame(tex));
|
Logger.Log("main", 4, "Load/Prehandle", "Unable to load texture: {0}", name);
|
||||||
}
|
}
|
||||||
texs.Add(name, tex);
|
|
||||||
texLoader.Dispose();
|
texLoader.Dispose();
|
||||||
texHandler.Dispose();
|
texHandler.Dispose();
|
||||||
texLoader = null;
|
texLoader = null;
|
||||||
@@ -468,6 +473,8 @@ namespace Cryville.Crtr {
|
|||||||
Logger.Log("main", 0, "Load/Prehandle", "Cleaning up");
|
Logger.Log("main", 0, "Load/Prehandle", "Cleaning up");
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
if (disableGC) GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;
|
if (disableGC) GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;
|
||||||
|
cbus.ForwardByTime(startOffset);
|
||||||
|
bbus.ForwardByTime(startOffset);
|
||||||
timer.Stop();
|
timer.Stop();
|
||||||
Logger.Log("main", 1, "Load/Prehandle", "Prehandling done ({0}ms)", timer.Elapsed.TotalMilliseconds);
|
Logger.Log("main", 1, "Load/Prehandle", "Prehandling done ({0}ms)", timer.Elapsed.TotalMilliseconds);
|
||||||
if (Settings.Default.ClearLogOnPlay) {
|
if (Settings.Default.ClearLogOnPlay) {
|
||||||
@@ -478,7 +485,6 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
Game.AudioSequencer.Playing = true;
|
Game.AudioSequencer.Playing = true;
|
||||||
atime0 = Game.AudioClient.BufferPosition;
|
atime0 = Game.AudioClient.BufferPosition;
|
||||||
Thread.Sleep((int)((atime0 - Game.AudioClient.Position) * 1000));
|
|
||||||
inputProxy.SyncTime(cbus.Time);
|
inputProxy.SyncTime(cbus.Time);
|
||||||
started = true;
|
started = true;
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,15 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cryville.Crtr.Components {
|
namespace Cryville.Crtr.Components {
|
||||||
|
[DisallowMultipleComponent]
|
||||||
public abstract class MeshBase : SkinComponent {
|
public abstract class MeshBase : SkinComponent {
|
||||||
public MeshBase() {
|
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));
|
SubmitProperty("zindex", new PropOp.Integer(v => ZIndex = (short)v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,12 +35,32 @@ namespace Cryville.Crtr.Components {
|
|||||||
mat.renderQueue = _zindex;
|
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() {
|
protected override void OnDestroy() {
|
||||||
if (materials != null)
|
DestroyMaterials();
|
||||||
foreach (var mat in materials) {
|
|
||||||
Material.Destroy(mat);
|
|
||||||
}
|
|
||||||
mesh.Destroy();
|
mesh.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void DestroyMaterials() {
|
||||||
|
if (materials == null) return;
|
||||||
|
foreach (var mat in materials) {
|
||||||
|
Material.Destroy(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -72,7 +72,7 @@ namespace Cryville.Crtr.Components {
|
|||||||
public op_set_shape(PolygonSGO self) : base(1) {
|
public op_set_shape(PolygonSGO self) : base(1) {
|
||||||
_self = self;
|
_self = self;
|
||||||
}
|
}
|
||||||
protected unsafe override void Execute() {
|
protected override unsafe void Execute() {
|
||||||
var o = GetOperand(0);
|
var o = GetOperand(0);
|
||||||
if (o.Type != PdtInternalType.Vector) throw new ArgumentException("Not a vector");
|
if (o.Type != PdtInternalType.Vector) throw new ArgumentException("Not a vector");
|
||||||
_self._shapeLength = (o.Length - sizeof(int)) / sizeof(Vector2);
|
_self._shapeLength = (o.Length - sizeof(int)) / sizeof(Vector2);
|
||||||
@@ -107,7 +107,7 @@ namespace Cryville.Crtr.Components {
|
|||||||
base.Init();
|
base.Init();
|
||||||
mesh.Init(transform);
|
mesh.Init(transform);
|
||||||
|
|
||||||
mesh.Renderer.materials = materials = new Material[] {
|
mesh.Renderer.sharedMaterials = materials = new Material[] {
|
||||||
MeshWrapper.NewMaterial(),
|
MeshWrapper.NewMaterial(),
|
||||||
MeshWrapper.NewMaterial(),
|
MeshWrapper.NewMaterial(),
|
||||||
MeshWrapper.NewMaterial(),
|
MeshWrapper.NewMaterial(),
|
||||||
|
@@ -1,5 +1,89 @@
|
|||||||
namespace Cryville.Crtr.Components {
|
using Cryville.Common;
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Logger = Cryville.Common.Logger;
|
||||||
|
|
||||||
|
namespace Cryville.Crtr.Components {
|
||||||
public class SkinAnimation : SkinComponent {
|
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() { }
|
protected override void OnDestroy() { }
|
||||||
}
|
}
|
||||||
|
[Flags]
|
||||||
|
public enum AnimationDirection {
|
||||||
|
normal = 0,
|
||||||
|
reverse = 1,
|
||||||
|
alternate = 2,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,8 @@ namespace Cryville.Crtr.Components {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Init() { }
|
public virtual void Init() { }
|
||||||
|
public virtual void Rewind(double time, Transform target) { }
|
||||||
|
public virtual void Tick(SkinContainer c, double time) { }
|
||||||
protected abstract void OnDestroy();
|
protected abstract void OnDestroy();
|
||||||
}
|
}
|
||||||
public struct SkinProperty {
|
public struct SkinProperty {
|
||||||
|
@@ -88,8 +88,9 @@ namespace Cryville.Crtr.Components {
|
|||||||
|
|
||||||
protected void InternalInit(string meshName = "quad") {
|
protected void InternalInit(string meshName = "quad") {
|
||||||
mesh.Init(transform);
|
mesh.Init(transform);
|
||||||
mesh.Renderer.materials = materials = new Material[] { MeshWrapper.NewMaterial() };
|
mesh.Renderer.sharedMaterials = materials = new Material[] { MeshWrapper.NewMaterial() };
|
||||||
mesh.Mesh = GenericResources.Meshes[meshName];
|
mesh.Mesh = GenericResources.Meshes[meshName];
|
||||||
|
UpdateColor();
|
||||||
UpdateScale();
|
UpdateScale();
|
||||||
UpdateZIndex();
|
UpdateZIndex();
|
||||||
}
|
}
|
||||||
|
@@ -60,7 +60,7 @@ namespace Cryville.Crtr.Components {
|
|||||||
SubmitProperty("frames", new PropOp.StringArray(v => Frames = v));
|
SubmitProperty("frames", new PropOp.StringArray(v => Frames = v));
|
||||||
SubmitProperty("index", new PropOp.Integer(v => Index = v));
|
SubmitProperty("index", new PropOp.Integer(v => Index = v));
|
||||||
SubmitProperty("fit", new PropOp.Enum<FitMode>(v => Fit = v, v => (FitMode)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;
|
static Vector2[] _origuv;
|
||||||
@@ -122,9 +122,21 @@ namespace Cryville.Crtr.Components {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mesh.Renderer.enabled = true;
|
mesh.Renderer.enabled = true;
|
||||||
mesh.Renderer.material.mainTexture = frame.Frame.Texture;
|
mesh.Renderer.sharedMaterial.mainTexture = frame.Frame.Texture;
|
||||||
UpdateUV();
|
UpdateUV();
|
||||||
UpdateScale();
|
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();
|
UpdateZIndex();
|
||||||
}
|
}
|
||||||
readonly Vector2[] _uvs = new Vector2[4];
|
readonly Vector2[] _uvs = new Vector2[4];
|
||||||
@@ -138,21 +150,6 @@ namespace Cryville.Crtr.Components {
|
|||||||
mesh.Mesh.uv = _uvs;
|
mesh.Mesh.uv = _uvs;
|
||||||
}
|
}
|
||||||
|
|
||||||
float _opacity = 1;
|
|
||||||
public float Opacity {
|
|
||||||
get { return _opacity; }
|
|
||||||
set {
|
|
||||||
_opacity = value;
|
|
||||||
UpdateOpacity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
protected void UpdateOpacity() {
|
|
||||||
if (!mesh.Initialized) return;
|
|
||||||
var c = mesh.Renderer.material.color;
|
|
||||||
c.a = _opacity;
|
|
||||||
mesh.Renderer.material.color = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FitMode m_fit = FitMode.height;
|
private FitMode m_fit = FitMode.height;
|
||||||
public FitMode Fit {
|
public FitMode Fit {
|
||||||
get { return m_fit; }
|
get { return m_fit; }
|
||||||
@@ -185,7 +182,7 @@ namespace Cryville.Crtr.Components {
|
|||||||
public override void Init() {
|
public override void Init() {
|
||||||
InternalInit();
|
InternalInit();
|
||||||
OnFrameUpdate();
|
OnFrameUpdate();
|
||||||
UpdateOpacity();
|
UpdateShader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,22 +2,7 @@
|
|||||||
|
|
||||||
namespace Cryville.Crtr.Components {
|
namespace Cryville.Crtr.Components {
|
||||||
public class SpriteRect : SpriteBase {
|
public class SpriteRect : SpriteBase {
|
||||||
public SpriteRect() {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Vector3 BaseScale {
|
protected override Vector3 BaseScale {
|
||||||
get { return Vector3.one; }
|
get { return Vector3.one; }
|
||||||
@@ -25,7 +10,6 @@ namespace Cryville.Crtr.Components {
|
|||||||
|
|
||||||
public override void Init() {
|
public override void Init() {
|
||||||
InternalInit();
|
InternalInit();
|
||||||
OnColorUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,12 +8,12 @@ namespace Cryville.Crtr.Components {
|
|||||||
SubmitProperty("border", new PropOp.Vector2(v => Border = v));
|
SubmitProperty("border", new PropOp.Vector2(v => Border = v));
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly static Dictionary<float, int> uvrefl
|
static readonly Dictionary<float, int> uvrefl
|
||||||
= new Dictionary<float, int>() {
|
= new Dictionary<float, int>() {
|
||||||
{-0.5f, 0}, {-0.4f, 1}, {0.4f, 2}, {0.5f, 3},
|
{-0.5f, 0}, {-0.4f, 1}, {0.4f, 2}, {0.5f, 3},
|
||||||
};
|
};
|
||||||
static Vector2[] _origuv;
|
static Vector2[] _origuv;
|
||||||
protected new static Vector2[] OriginalUV {
|
protected static new Vector2[] OriginalUV {
|
||||||
get {
|
get {
|
||||||
if (_origuv == null) {
|
if (_origuv == null) {
|
||||||
var m = GenericResources.Meshes["quad_scale3h"];
|
var m = GenericResources.Meshes["quad_scale3h"];
|
||||||
@@ -84,7 +84,6 @@ namespace Cryville.Crtr.Components {
|
|||||||
public override void Init() {
|
public override void Init() {
|
||||||
InternalInit("quad_scale3h");
|
InternalInit("quad_scale3h");
|
||||||
OnFrameUpdate();
|
OnFrameUpdate();
|
||||||
UpdateOpacity();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ namespace Cryville.Crtr.Components {
|
|||||||
SubmitProperty("value", new PropOp.TargetString(() => Value));
|
SubmitProperty("value", new PropOp.TargetString(() => Value));
|
||||||
SubmitProperty("size", new PropOp.Float(v => Size = v));
|
SubmitProperty("size", new PropOp.Float(v => Size = v));
|
||||||
SubmitProperty("spacing", new PropOp.Float(v => Spacing = v));
|
SubmitProperty("spacing", new PropOp.Float(v => Spacing = v));
|
||||||
SubmitProperty("opacity", new PropOp.Float(v => Opacity = v));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable IDE1006
|
#pragma warning disable IDE1006
|
||||||
@@ -20,7 +19,7 @@ namespace Cryville.Crtr.Components {
|
|||||||
public op_set_frames(SpriteText self) : base(2) {
|
public op_set_frames(SpriteText self) : base(2) {
|
||||||
_self = self;
|
_self = self;
|
||||||
}
|
}
|
||||||
protected unsafe override void Execute() {
|
protected override unsafe void Execute() {
|
||||||
var keys = GetOperand(0).AsString();
|
var keys = GetOperand(0).AsString();
|
||||||
var values = GetOperand(1);
|
var values = GetOperand(1);
|
||||||
int arrtype; int len;
|
int arrtype; int len;
|
||||||
@@ -47,7 +46,7 @@ namespace Cryville.Crtr.Components {
|
|||||||
Dictionary<char, SpriteInfo> m_frames;
|
Dictionary<char, SpriteInfo> m_frames;
|
||||||
public Dictionary<char, SpriteInfo> Frames {
|
public Dictionary<char, SpriteInfo> Frames {
|
||||||
get { return m_frames; }
|
get { return m_frames; }
|
||||||
set { m_frames = value; UpdateFrames(); UpdateScale(); }
|
set { m_frames = value; UpdateFrames(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly TargetString m_value = new TargetString();
|
readonly TargetString m_value = new TargetString();
|
||||||
@@ -78,7 +77,11 @@ namespace Cryville.Crtr.Components {
|
|||||||
meshes.Clear();
|
meshes.Clear();
|
||||||
verts.Clear();
|
verts.Clear();
|
||||||
uvs.Clear();
|
uvs.Clear();
|
||||||
|
DestroyMaterials();
|
||||||
|
materials = new Material[m_frames.Count];
|
||||||
|
int i = 0;
|
||||||
foreach (var f in m_frames) {
|
foreach (var f in m_frames) {
|
||||||
|
if (SpriteInfo.IsNullOrEmpty(f.Value)) continue;
|
||||||
if (frameHeight == 0) frameHeight = f.Value.Rect.height;
|
if (frameHeight == 0) frameHeight = f.Value.Rect.height;
|
||||||
else if (frameHeight != f.Value.Rect.height) throw new Exception("Inconsistent frame height for text component");
|
else if (frameHeight != f.Value.Rect.height) throw new Exception("Inconsistent frame height for text component");
|
||||||
var tex = f.Value.Frame.Texture;
|
var tex = f.Value.Frame.Texture;
|
||||||
@@ -86,14 +89,17 @@ namespace Cryville.Crtr.Components {
|
|||||||
var m = new MeshWrapper();
|
var m = new MeshWrapper();
|
||||||
m.Init(mesh.MeshTransform);
|
m.Init(mesh.MeshTransform);
|
||||||
m.Mesh = new Mesh();
|
m.Mesh = new Mesh();
|
||||||
m.Renderer.material = MeshWrapper.NewMaterial(); // TODO Destroy or add to `materials`
|
var mat = MeshWrapper.NewMaterial();
|
||||||
m.Renderer.material.mainTexture = tex;
|
mat.mainTexture = tex;
|
||||||
|
m.Renderer.sharedMaterial = materials[i++] = mat;
|
||||||
meshes.Add(tex, m);
|
meshes.Add(tex, m);
|
||||||
verts.Add(tex, new List<Vector3>());
|
verts.Add(tex, new List<Vector3>());
|
||||||
uvs.Add(tex, new List<Vector2>());
|
uvs.Add(tex, new List<Vector2>());
|
||||||
tris.Add(tex, new List<int>());
|
tris.Add(tex, new List<int>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UpdateColor();
|
||||||
|
UpdateScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
float sum_x;
|
float sum_x;
|
||||||
@@ -158,23 +164,6 @@ namespace Cryville.Crtr.Components {
|
|||||||
get { return new Vector2(-0.5f, -0.5f); }
|
get { return new Vector2(-0.5f, -0.5f); }
|
||||||
}
|
}
|
||||||
|
|
||||||
float _opacity = 1;
|
|
||||||
public float Opacity {
|
|
||||||
get { return _opacity; }
|
|
||||||
set {
|
|
||||||
_opacity = value;
|
|
||||||
UpdateOpacity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void UpdateOpacity() {
|
|
||||||
if (!mesh.Initialized) return;
|
|
||||||
foreach (var m in meshes) {
|
|
||||||
var c = m.Value.Renderer.material.color;
|
|
||||||
c.a = _opacity;
|
|
||||||
m.Value.Renderer.material.color = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Init() {
|
public override void Init() {
|
||||||
InternalInit();
|
InternalInit();
|
||||||
UpdateFrames();
|
UpdateFrames();
|
||||||
|
@@ -93,10 +93,10 @@ namespace Cryville.Crtr.Config {
|
|||||||
var tsrc = src.Value;
|
var tsrc = src.Value;
|
||||||
bool flag = false;
|
bool flag = false;
|
||||||
if (proxy.IsUsed(tsrc)) {
|
if (proxy.IsUsed(tsrc)) {
|
||||||
text.text += " (Used)";
|
text.text += " <size=9>(Used)</size>";
|
||||||
}
|
}
|
||||||
else if (tsrc.Handler.GetDimension(src.Value.Type) < m_configScene.ruleset.Root.inputs[_sel].dim) {
|
else if (tsrc.Handler.GetDimension(src.Value.Type) < m_configScene.ruleset.Root.inputs[_sel].dim) {
|
||||||
text.text += " (Not Applicable)";
|
text.text += " <size=9>(Not Applicable)</size>";
|
||||||
}
|
}
|
||||||
else flag = true;
|
else flag = true;
|
||||||
btn.interactable = flag;
|
btn.interactable = flag;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using Cryville.Common.Buffers;
|
using Cryville.Common.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public class EffectGroup {
|
public class EffectGroup {
|
||||||
@@ -35,22 +36,37 @@ namespace Cryville.Crtr {
|
|||||||
while (_endQueue.Count > 0) {
|
while (_endQueue.Count > 0) {
|
||||||
var item = _endQueue[0];
|
var item = _endQueue[0];
|
||||||
if (item.EndTime > _time) break;
|
if (item.EndTime > _time) break;
|
||||||
item.OnDone();
|
|
||||||
_instances.Remove(item.Index);
|
|
||||||
_pool.Return(item);
|
|
||||||
_endQueue.RemoveAt(0);
|
_endQueue.RemoveAt(0);
|
||||||
|
if (item.OnStateDone()) {
|
||||||
|
QueueInstance(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
item.Tick(time);
|
||||||
|
_instances.Remove(item.Index);
|
||||||
|
_pool.Return(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var instance in _instances) {
|
||||||
|
instance.Value.Tick(time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Emit(float index) {
|
public void Emit(float index, Transform target = null) {
|
||||||
EffectInstance instance;
|
EffectInstance instance;
|
||||||
if (!_instances.TryGetValue(index, out instance)) {
|
bool flag = _instances.TryGetValue(index, out instance);
|
||||||
_instances.Add(index, instance = _pool.Rent());
|
if (!flag) _instances.Add(index, instance = _pool.Rent());
|
||||||
}
|
|
||||||
instance.Index = index;
|
instance.Index = index;
|
||||||
instance.OnEmit(_time);
|
if (instance.CanEmit()) {
|
||||||
var i = _endQueue.BinarySearch(instance);
|
if (flag) {
|
||||||
if (i < 0) i = ~i;
|
var i = _endQueue.BinarySearch(instance);
|
||||||
_endQueue.Insert(i, instance);
|
_endQueue.RemoveAt(i);
|
||||||
|
}
|
||||||
|
instance.OnEmit(_time, target);
|
||||||
|
QueueInstance(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void QueueInstance(EffectInstance i) {
|
||||||
|
var index = ~_endQueue.BinarySearch(i);
|
||||||
|
_endQueue.Insert(index, i);
|
||||||
}
|
}
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
_pool.DisposeAll();
|
_pool.DisposeAll();
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common;
|
||||||
using Cryville.Crtr.Components;
|
using Cryville.Crtr.Components;
|
||||||
|
using Cryville.Crtr.Event;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -10,37 +11,89 @@ namespace Cryville.Crtr {
|
|||||||
readonly EffectDefinition _def;
|
readonly EffectDefinition _def;
|
||||||
readonly SkinContainer _skinContainer;
|
readonly SkinContainer _skinContainer;
|
||||||
public Transform RootTransform { get; private set; }
|
public Transform RootTransform { get; private set; }
|
||||||
|
readonly SkinComponent[] _comps;
|
||||||
public EffectInstance(EffectDefinition def) {
|
public EffectInstance(EffectDefinition def) {
|
||||||
_def = def;
|
_def = def;
|
||||||
_skinContainer = new SkinContainer(_def.elements);
|
_skinContainer = new SkinContainer(this, _def.elements);
|
||||||
RootTransform = new GameObject("effect:" + GetHashCode().ToString(CultureInfo.InvariantCulture)).transform;
|
RootTransform = new GameObject("effect:" + GetHashCode().ToString(CultureInfo.InvariantCulture)).transform;
|
||||||
SkinContext = new SkinContext(RootTransform);
|
SkinContext = new SkinContext(RootTransform);
|
||||||
ChartPlayer.etor.ContextCascadeInsertBlock();
|
ChartPlayer.etor.ContextCascadeInsertBlock();
|
||||||
_skinContainer.MatchStatic(this);
|
_skinContainer.MatchStatic();
|
||||||
ChartPlayer.etor.ContextCascadeDiscardBlock();
|
ChartPlayer.etor.ContextCascadeDiscardBlock();
|
||||||
foreach (var i in RootTransform.GetComponentsInChildren<SkinComponent>())
|
_comps = RootTransform.GetComponentsInChildren<SkinComponent>();
|
||||||
i.Init();
|
foreach (var i in _comps) i.Init();
|
||||||
_indexSrc = new PropSrc.Float(() => Index);
|
_indexSrc = new PropSrc.Float(() => Index);
|
||||||
_durationOp = new PropOp.Float(v => _duration = v);
|
_durationOp = new PropOp.Float(v => _duration = v);
|
||||||
}
|
}
|
||||||
public float Index { get; set; }
|
public void Rewind(double time, Transform target) {
|
||||||
static readonly int _var_index = IdentifierManager.SharedInstance.Request("index");
|
_startTime = time;
|
||||||
|
foreach (var i in _comps) i.Rewind(time, target);
|
||||||
|
}
|
||||||
|
private float m_index;
|
||||||
|
public float Index {
|
||||||
|
get { return m_index; }
|
||||||
|
set {
|
||||||
|
if (m_index == value) return;
|
||||||
|
m_index = value;
|
||||||
|
_indexSrc.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Transform _currentTarget;
|
||||||
|
Identifier _currentStateName = Identifier.Empty;
|
||||||
|
EffectState _currentState;
|
||||||
|
ChartEvent _ctxev;
|
||||||
|
ContainerState _ctxstate;
|
||||||
|
internal static readonly int _VAR_EFFECT_INDEX = IdentifierManager.SharedInstance.Request("effect_index");
|
||||||
readonly PropSrc _indexSrc;
|
readonly PropSrc _indexSrc;
|
||||||
double _startTime;
|
double _startTime;
|
||||||
float _duration;
|
float _duration;
|
||||||
readonly PropOp _durationOp;
|
readonly PropOp _durationOp;
|
||||||
public double EndTime { get { return _startTime + _duration; } }
|
public double EndTime { get { return _startTime + _duration; } }
|
||||||
public void OnEmit(double time) {
|
public void Tick(double time) {
|
||||||
_startTime = time;
|
foreach (var i in _comps) i.Tick(_skinContainer, time);
|
||||||
|
}
|
||||||
|
public bool CanEmit() {
|
||||||
|
return _currentStateName.Key == 0 || _currentState.rewind.Key != 0;
|
||||||
|
}
|
||||||
|
public void OnEmit(double time, Transform target) {
|
||||||
|
_currentTarget = target;
|
||||||
|
_ctxev = ChartPlayer.etor.ContextEvent;
|
||||||
|
_ctxstate = ChartPlayer.etor.ContextState;
|
||||||
|
if (_currentStateName.Key == 0) {
|
||||||
|
EnterState(_def.init, time, _currentTarget, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (_currentState.rewind.Key == 0) throw new InvalidOperationException("Cannot rewind");
|
||||||
|
EnterState(_currentState.rewind, time, _currentTarget, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void EnterState(Identifier name, double time, Transform target, bool emitting) {
|
||||||
|
_currentStateName = name;
|
||||||
|
_currentState = _def.states[name];
|
||||||
|
Rewind(time, target);
|
||||||
RootTransform.gameObject.SetActive(true);
|
RootTransform.gameObject.SetActive(true);
|
||||||
ChartPlayer.etor.ContextCascadeInsert();
|
ChartPlayer.etor.ContextCascadeInsert();
|
||||||
ChartPlayer.etor.ContextCascadeUpdate(_var_index, _indexSrc);
|
ChartPlayer.etor.ContextCascadeUpdate(_VAR_EFFECT_INDEX, _indexSrc);
|
||||||
ChartPlayer.etor.Evaluate(_durationOp, _def.duration);
|
ChartPlayer.etor.Evaluate(_durationOp, _currentState.duration);
|
||||||
_skinContainer.MatchDynamic(this, 0);
|
if (emitting) _skinContainer.MatchDynamic(0, true);
|
||||||
|
_skinContainer.MatchDynamic(1, emitting);
|
||||||
ChartPlayer.etor.ContextCascadeDiscard();
|
ChartPlayer.etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
public void OnDone() {
|
public bool OnStateDone() {
|
||||||
RootTransform.gameObject.SetActive(false);
|
if (_currentState.next.Key == 0) {
|
||||||
|
RootTransform.gameObject.SetActive(false);
|
||||||
|
_currentStateName = Identifier.Empty;
|
||||||
|
_currentState = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ChartPlayer.etor.ContextEvent = _ctxev;
|
||||||
|
ChartPlayer.etor.ContextState = _ctxstate;
|
||||||
|
EnterState(_currentState.next, EndTime, _currentTarget, false);
|
||||||
|
ChartPlayer.etor.ContextEvent = null;
|
||||||
|
ChartPlayer.etor.ContextState = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
GameObject.Destroy(RootTransform.gameObject);
|
GameObject.Destroy(RootTransform.gameObject);
|
||||||
@@ -48,7 +101,7 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
public string TypeName { get { throw new InvalidOperationException("Type name undefined"); } }
|
public string TypeName { get { throw new InvalidOperationException("Type name undefined"); } }
|
||||||
public SkinContext SkinContext { get; private set; }
|
public SkinContext SkinContext { get; private set; }
|
||||||
public Anchor OpenedAnchor { get { throw new InvalidOperationException("Anchor not supported"); } }
|
public int OpenedAnchorName { get { return _currentStateName.Key; } }
|
||||||
public void PushAnchorEvent(double time, int name) {
|
public void PushAnchorEvent(double time, int name) {
|
||||||
throw new InvalidOperationException("Anchor not supported");
|
throw new InvalidOperationException("Anchor not supported");
|
||||||
}
|
}
|
||||||
@@ -60,7 +113,9 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int CompareTo(EffectInstance other) {
|
public int CompareTo(EffectInstance other) {
|
||||||
return EndTime.CompareTo(other.EndTime);
|
int r = EndTime.CompareTo(other.EndTime);
|
||||||
|
if (r != 0) return r;
|
||||||
|
return GetHashCode().CompareTo(other.GetHashCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public class EffectManager {
|
public class EffectManager {
|
||||||
@@ -15,6 +16,9 @@ namespace Cryville.Crtr {
|
|||||||
public void Emit(int id, float index) {
|
public void Emit(int id, float index) {
|
||||||
_groups[id].Emit(index);
|
_groups[id].Emit(index);
|
||||||
}
|
}
|
||||||
|
public void EmitSelf(int id, float index, Transform target) {
|
||||||
|
_groups[id].Emit(index, target);
|
||||||
|
}
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
foreach (var g in _groups) g.Value.Dispose();
|
foreach (var g in _groups) g.Value.Dispose();
|
||||||
}
|
}
|
||||||
|
@@ -37,10 +37,9 @@ namespace Cryville.Crtr.Event {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ContainerState ts;
|
public ContainerState ts;
|
||||||
|
|
||||||
/// <summary>
|
protected Transform RootTransform;
|
||||||
/// <see cref="GameObject"/> group, the <see cref="Transform"/> containing all the generated elements in the <see cref="ContainerHandler"/>.
|
|
||||||
/// </summary>
|
SkinComponent[] _comps;
|
||||||
protected Transform gogroup;
|
|
||||||
|
|
||||||
public Vector3 Position { get; protected set; }
|
public Vector3 Position { get; protected set; }
|
||||||
public Quaternion Rotation { get; protected set; }
|
public Quaternion Rotation { get; protected set; }
|
||||||
@@ -70,7 +69,7 @@ namespace Cryville.Crtr.Event {
|
|||||||
SkinContainer skinContainer;
|
SkinContainer skinContainer;
|
||||||
protected Judge judge;
|
protected Judge judge;
|
||||||
public void AttachSystems(PdtSkin skin, Judge judge) {
|
public void AttachSystems(PdtSkin skin, Judge judge) {
|
||||||
skinContainer = new SkinContainer(skin.elements);
|
skinContainer = new SkinContainer(this, skin.elements);
|
||||||
this.judge = judge;
|
this.judge = judge;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,15 +79,15 @@ namespace Cryville.Crtr.Event {
|
|||||||
Anchor a_cur;
|
Anchor a_cur;
|
||||||
Anchor a_head;
|
Anchor a_head;
|
||||||
Anchor a_tail;
|
Anchor a_tail;
|
||||||
readonly static int _a_cur = IdentifierManager.SharedInstance.Request("cur");
|
static readonly int _a_cur = IdentifierManager.SharedInstance.Request("cur");
|
||||||
readonly static int _a_head = IdentifierManager.SharedInstance.Request("head");
|
static readonly int _a_head = IdentifierManager.SharedInstance.Request("head");
|
||||||
readonly static int _a_tail = IdentifierManager.SharedInstance.Request("tail");
|
static readonly int _a_tail = IdentifierManager.SharedInstance.Request("tail");
|
||||||
double atime_head;
|
double atime_head;
|
||||||
double atime_tail;
|
double atime_tail;
|
||||||
public Anchor RegisterAnchor(int name, bool dyn = false, int propSrcCount = 0) {
|
public Anchor RegisterAnchor(int name, bool dyn = false, int propSrcCount = 0) {
|
||||||
var strname = IdentifierManager.SharedInstance.Retrieve(name);
|
var strname = IdentifierManager.SharedInstance.Retrieve(name);
|
||||||
var go = new GameObject("." + strname).transform;
|
var go = new GameObject("." + strname).transform;
|
||||||
go.SetParent(gogroup, false);
|
go.SetParent(RootTransform, false);
|
||||||
var result = new Anchor(name, go, propSrcCount);
|
var result = new Anchor(name, go, propSrcCount);
|
||||||
if (dyn) {
|
if (dyn) {
|
||||||
if (DynamicAnchors.ContainsKey(name))
|
if (DynamicAnchors.ContainsKey(name))
|
||||||
@@ -103,22 +102,22 @@ namespace Cryville.Crtr.Event {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
protected void OpenAnchor(Anchor anchor) {
|
protected void OpenAnchor(Anchor anchor) {
|
||||||
if (OpenedAnchor != null) throw new InvalidOperationException("An anchor has been opened");
|
if (_openedAnchor != null) throw new InvalidOperationException("An anchor has been opened");
|
||||||
anchor.Transform.gameObject.SetActive(true);
|
anchor.Transform.gameObject.SetActive(true);
|
||||||
OpenedAnchor = anchor;
|
_openedAnchor = anchor;
|
||||||
}
|
}
|
||||||
protected void CloseAnchor() {
|
protected void CloseAnchor() {
|
||||||
OpenedAnchor = null;
|
_openedAnchor = null;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Logic
|
#region Logic
|
||||||
#region Init methods: Called on prehandle
|
#region Init methods: Called on prehandle
|
||||||
public virtual void PreInit() {
|
public virtual void PreInit() {
|
||||||
gogroup = new GameObject(TypeName + ":" + Container.GetHashCode().ToString(CultureInfo.InvariantCulture)).transform;
|
RootTransform = new GameObject(TypeName + ":" + Container.GetHashCode().ToString(CultureInfo.InvariantCulture)).transform;
|
||||||
SkinContext = new SkinContext(gogroup);
|
SkinContext = new SkinContext(RootTransform);
|
||||||
if (cs.Parent != null)
|
if (cs.Parent != null)
|
||||||
gogroup.SetParent(cs.Parent.Handler.gogroup, false);
|
RootTransform.SetParent(cs.Parent.Handler.RootTransform, false);
|
||||||
a_cur = RegisterAnchor(_a_cur);
|
a_cur = RegisterAnchor(_a_cur);
|
||||||
a_head = RegisterAnchor(_a_head, true);
|
a_head = RegisterAnchor(_a_head, true);
|
||||||
a_tail = RegisterAnchor(_a_tail, true);
|
a_tail = RegisterAnchor(_a_tail, true);
|
||||||
@@ -126,16 +125,16 @@ namespace Cryville.Crtr.Event {
|
|||||||
public virtual void Init() {
|
public virtual void Init() {
|
||||||
ChartPlayer.etor.ContextState = ps;
|
ChartPlayer.etor.ContextState = ps;
|
||||||
ChartPlayer.etor.ContextEvent = Container;
|
ChartPlayer.etor.ContextEvent = Container;
|
||||||
skinContainer.MatchStatic(this);
|
skinContainer.MatchStatic();
|
||||||
ChartPlayer.etor.ContextEvent = null;
|
ChartPlayer.etor.ContextEvent = null;
|
||||||
ChartPlayer.etor.ContextState = null;
|
ChartPlayer.etor.ContextState = null;
|
||||||
foreach (var i in gogroup.GetComponentsInChildren<SkinComponent>())
|
_comps = RootTransform.GetComponentsInChildren<SkinComponent>();
|
||||||
i.Init();
|
foreach (var i in _comps) i.Init();
|
||||||
}
|
}
|
||||||
public virtual void PostInit() {
|
public virtual void PostInit() {
|
||||||
PropSrcs.Add(_var_current_time, new PropSrc.Float(() => (float)cs.rootPrototype.Time));
|
PropSrcs.Add(_var_current_time, new PropSrc.Float(() => (float)cs.rootPrototype.Time));
|
||||||
PropSrcs.Add(_var_invisible_bounds, new PropSrc.Boolean(() => atime_head > atime_tail));
|
PropSrcs.Add(_var_invisible_bounds, new PropSrc.Boolean(() => atime_head > atime_tail));
|
||||||
gogroup.gameObject.SetActive(false);
|
RootTransform.gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region Start methods
|
#region Start methods
|
||||||
@@ -146,14 +145,14 @@ namespace Cryville.Crtr.Event {
|
|||||||
public virtual void StartLogicalUpdate(ContainerState s) { }
|
public virtual void StartLogicalUpdate(ContainerState s) { }
|
||||||
protected virtual void StartPreGraphicalUpdate(ContainerState s) { }
|
protected virtual void StartPreGraphicalUpdate(ContainerState s) { }
|
||||||
protected virtual void StartGraphicalUpdate(ContainerState s) {
|
protected virtual void StartGraphicalUpdate(ContainerState s) {
|
||||||
if (gogroup) gogroup.gameObject.SetActive(true);
|
if (RootTransform) RootTransform.gameObject.SetActive(true);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
public virtual void Update(ContainerState s, StampedEvent ev) {
|
public virtual void Update(ContainerState s, StampedEvent ev) {
|
||||||
if (s.CloneType == 3) SetPreGraphicalActive(true, s);
|
if (s.CloneType == 3) SetPreGraphicalActive(true, s);
|
||||||
else if (ev is StampedEvent.Anchor) {
|
else if (ev is StampedEvent.Anchor) {
|
||||||
var tev = (StampedEvent.Anchor)ev;
|
var tev = (StampedEvent.Anchor)ev;
|
||||||
if (gogroup) {
|
if (RootTransform) {
|
||||||
OpenAnchor(tev.Target);
|
OpenAnchor(tev.Target);
|
||||||
#if UNITY_5_6_OR_NEWER
|
#if UNITY_5_6_OR_NEWER
|
||||||
tev.Target.Transform.SetPositionAndRotation(Position, Rotation);
|
tev.Target.Transform.SetPositionAndRotation(Position, Rotation);
|
||||||
@@ -172,7 +171,7 @@ namespace Cryville.Crtr.Event {
|
|||||||
}
|
}
|
||||||
anchorEvPool.Return(tev);
|
anchorEvPool.Return(tev);
|
||||||
}
|
}
|
||||||
else if (gogroup && s.CloneType == 2) MatchDynamic(s, 1);
|
else if (RootTransform && s.CloneType == 2) MatchDynamic(s, 1);
|
||||||
}
|
}
|
||||||
#region End methods
|
#region End methods
|
||||||
protected virtual void EndGraphicalUpdate(ContainerState s) { }
|
protected virtual void EndGraphicalUpdate(ContainerState s) { }
|
||||||
@@ -180,8 +179,8 @@ namespace Cryville.Crtr.Event {
|
|||||||
public virtual void EndLogicalUpdate(ContainerState s) { }
|
public virtual void EndLogicalUpdate(ContainerState s) { }
|
||||||
public virtual void EndPhysicalUpdate(ContainerState s) { }
|
public virtual void EndPhysicalUpdate(ContainerState s) { }
|
||||||
public virtual void Dispose() {
|
public virtual void Dispose() {
|
||||||
if (gogroup)
|
if (RootTransform)
|
||||||
GameObject.Destroy(gogroup.gameObject);
|
GameObject.Destroy(RootTransform.gameObject);
|
||||||
Alive = false;
|
Alive = false;
|
||||||
}
|
}
|
||||||
public virtual void DisposeAll() { }
|
public virtual void DisposeAll() { }
|
||||||
@@ -193,7 +192,7 @@ namespace Cryville.Crtr.Event {
|
|||||||
void MatchDynamic(ContainerState s, int dl) {
|
void MatchDynamic(ContainerState s, int dl) {
|
||||||
ChartPlayer.etor.ContextState = s;
|
ChartPlayer.etor.ContextState = s;
|
||||||
ChartPlayer.etor.ContextEvent = Container;
|
ChartPlayer.etor.ContextEvent = Container;
|
||||||
skinContainer.MatchDynamic(this, dl);
|
skinContainer.MatchDynamic(dl);
|
||||||
ChartPlayer.etor.ContextEvent = null;
|
ChartPlayer.etor.ContextEvent = null;
|
||||||
ChartPlayer.etor.ContextState = null;
|
ChartPlayer.etor.ContextState = null;
|
||||||
}
|
}
|
||||||
@@ -205,6 +204,7 @@ namespace Cryville.Crtr.Event {
|
|||||||
atime_head = cs.StampedContainer.Time;
|
atime_head = cs.StampedContainer.Time;
|
||||||
atime_tail = atime_head + cs.StampedContainer.Duration;
|
atime_tail = atime_head + cs.StampedContainer.Duration;
|
||||||
MatchDynamic(cs, 0);
|
MatchDynamic(cs, 0);
|
||||||
|
foreach (var i in _comps) i.Tick(skinContainer, cs.Time);
|
||||||
if (cs.Active) PushAnchorEvent(cs.Time, a_cur);
|
if (cs.Active) PushAnchorEvent(cs.Time, a_cur);
|
||||||
if (double.IsNaN(DynamicAnchorSetTime[_a_head])) DynamicAnchorSetTime[_a_head] = atime_head;
|
if (double.IsNaN(DynamicAnchorSetTime[_a_head])) DynamicAnchorSetTime[_a_head] = atime_head;
|
||||||
if (double.IsNaN(DynamicAnchorSetTime[_a_tail])) DynamicAnchorSetTime[_a_tail] = atime_tail;
|
if (double.IsNaN(DynamicAnchorSetTime[_a_tail])) DynamicAnchorSetTime[_a_tail] = atime_tail;
|
||||||
@@ -241,7 +241,8 @@ namespace Cryville.Crtr.Event {
|
|||||||
#region ISkinnableGroup
|
#region ISkinnableGroup
|
||||||
public abstract string TypeName { get; }
|
public abstract string TypeName { get; }
|
||||||
public SkinContext SkinContext { get; private set; }
|
public SkinContext SkinContext { get; private set; }
|
||||||
public Anchor OpenedAnchor { get; private set; }
|
Anchor _openedAnchor;
|
||||||
|
public int OpenedAnchorName { get { return _openedAnchor == null ? 0 : _openedAnchor.Name; } }
|
||||||
public bool TryGetAnchorsByName(int name, out IReadOnlyCollection<Anchor> result) {
|
public bool TryGetAnchorsByName(int name, out IReadOnlyCollection<Anchor> result) {
|
||||||
List<Anchor> anchors;
|
List<Anchor> anchors;
|
||||||
var ret = Anchors.TryGetValue(name, out anchors);
|
var ret = Anchors.TryGetValue(name, out anchors);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: dbc046e7cabacbb4fbf74520399a7340
|
guid: b35ffffce02252548a66e18cf98050e2
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
107
Assets/Cryville/Crtr/Extension/RefTypes.cs
Normal file
107
Assets/Cryville/Crtr/Extension/RefTypes.cs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine.Scripting;
|
||||||
|
|
||||||
|
namespace Cryville.Crtr.Extension {
|
||||||
|
[Preserve]
|
||||||
|
public static class RefTypes {
|
||||||
|
[Preserve]
|
||||||
|
public static void PreserveEnumerable() {
|
||||||
|
IEnumerable<object> p = Enumerable.Empty<object>();
|
||||||
|
p.All(i => false);
|
||||||
|
p.Any();
|
||||||
|
p.Any(i => false);
|
||||||
|
p.Cast<object>();
|
||||||
|
p.Concat(Enumerable.Empty<object>());
|
||||||
|
p.Contains(null);
|
||||||
|
p.Count();
|
||||||
|
p.Count(i => false);
|
||||||
|
p.DefaultIfEmpty();
|
||||||
|
p.DefaultIfEmpty(null);
|
||||||
|
p.Distinct();
|
||||||
|
p.ElementAt(0);
|
||||||
|
p.ElementAtOrDefault(0);
|
||||||
|
p.First();
|
||||||
|
p.First(i => false);
|
||||||
|
p.FirstOrDefault();
|
||||||
|
p.FirstOrDefault(i => false);
|
||||||
|
p.GetEnumerator();
|
||||||
|
p.Last();
|
||||||
|
p.Last(i => false);
|
||||||
|
p.LastOrDefault();
|
||||||
|
p.LastOrDefault(i => false);
|
||||||
|
p.LongCount();
|
||||||
|
p.LongCount(i => false);
|
||||||
|
p.OrderBy(i => i).ThenBy(i => i);
|
||||||
|
p.OrderByDescending(i => i).ThenByDescending(i => i);
|
||||||
|
p.Reverse();
|
||||||
|
p.Select(i => i);
|
||||||
|
p.Select((i, j) => false);
|
||||||
|
p.SequenceEqual(p);
|
||||||
|
p.Single();
|
||||||
|
p.Single(i => false);
|
||||||
|
p.SingleOrDefault();
|
||||||
|
p.SingleOrDefault(i => false);
|
||||||
|
p.Skip(0);
|
||||||
|
p.SkipLast(0);
|
||||||
|
p.SkipWhile(i => false);
|
||||||
|
p.SkipWhile((i, j) => false);
|
||||||
|
p.Take(0);
|
||||||
|
p.TakeLast(0);
|
||||||
|
p.TakeWhile(i => false);
|
||||||
|
p.TakeWhile((i, j) => false);
|
||||||
|
p.ToArray();
|
||||||
|
p.ToDictionary(i => new object());
|
||||||
|
p.ToDictionary(i => new object(), i => new object());
|
||||||
|
p.ToHashSet();
|
||||||
|
p.ToList();
|
||||||
|
p.Where(i => false);
|
||||||
|
p.Where((i, j) => false);
|
||||||
|
}
|
||||||
|
[Preserve]
|
||||||
|
public static void PreserveBinaryReader() {
|
||||||
|
BinaryReader p = new BinaryReader(null);
|
||||||
|
p.Close();
|
||||||
|
p.Dispose();
|
||||||
|
p.PeekChar();
|
||||||
|
p.Read();
|
||||||
|
p.ReadBoolean();
|
||||||
|
p.ReadByte();
|
||||||
|
p.ReadBytes(0);
|
||||||
|
p.ReadChar();
|
||||||
|
p.ReadChars(0);
|
||||||
|
p.ReadDouble();
|
||||||
|
p.ReadInt16();
|
||||||
|
p.ReadInt32();
|
||||||
|
p.ReadInt64();
|
||||||
|
p.ReadSByte();
|
||||||
|
p.ReadSingle();
|
||||||
|
p.ReadUInt16();
|
||||||
|
p.ReadUInt32();
|
||||||
|
p.ReadUInt64();
|
||||||
|
}
|
||||||
|
[Preserve]
|
||||||
|
public static void PreserveStreamReader() {
|
||||||
|
object _;
|
||||||
|
StreamReader p = new StreamReader((Stream)null);
|
||||||
|
p.Close();
|
||||||
|
_ = p.CurrentEncoding;
|
||||||
|
p.DiscardBufferedData();
|
||||||
|
p.Dispose();
|
||||||
|
_ = p.EndOfStream;
|
||||||
|
p.Peek();
|
||||||
|
p.Read();
|
||||||
|
p.ReadBlock(null, 0, 0);
|
||||||
|
p.ReadLine();
|
||||||
|
p.ReadToEnd();
|
||||||
|
}
|
||||||
|
[Preserve]
|
||||||
|
public static void PreserveConvert() {
|
||||||
|
Convert.ChangeType(0, typeof(byte));
|
||||||
|
Convert.ChangeType(0, typeof(byte), CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Cryville/Crtr/Extension/RefTypes.cs.meta
Normal file
11
Assets/Cryville/Crtr/Extension/RefTypes.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 29a6376ce10b77e4099d2613876f9549
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -1,189 +0,0 @@
|
|||||||
using Cryville.Common;
|
|
||||||
using Cryville.Common.Math;
|
|
||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions.Bestdori {
|
|
||||||
public class BestdoriChartConverter : ResourceConverter {
|
|
||||||
static readonly string[] SUPPORTED_FORMATS = { ".bestdori" };
|
|
||||||
public override string[] GetSupportedFormats() {
|
|
||||||
return SUPPORTED_FORMATS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Resource> ConvertFrom(FileInfo file) {
|
|
||||||
List<Resource> result = new List<Resource>();
|
|
||||||
List<BestdoriChartEvent> src;
|
|
||||||
using (var reader = new StreamReader(file.FullName)) {
|
|
||||||
src = JsonConvert.DeserializeObject<List<BestdoriChartEvent>>(reader.ReadToEnd());
|
|
||||||
}
|
|
||||||
var group = new Chart.Group() {
|
|
||||||
tracks = new List<Chart.Track>(),
|
|
||||||
notes = new List<Chart.Note>(),
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
};
|
|
||||||
Chart chart = new Chart {
|
|
||||||
format = 2,
|
|
||||||
time = new BeatTime(0, 0, 1),
|
|
||||||
ruleset = "bang_dream_girls_band_party",
|
|
||||||
sigs = new List<Chart.Signature>(),
|
|
||||||
sounds = new List<Chart.Sound>(),
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
groups = new List<Chart.Group> { group },
|
|
||||||
};
|
|
||||||
var tm = new BeatTimeTimingModel();
|
|
||||||
string bgm = null;
|
|
||||||
double endbeat = 0;
|
|
||||||
foreach (var ev in src) {
|
|
||||||
tm.ForwardTo(ev.StartBeat);
|
|
||||||
if (ev.StartBeat > endbeat) endbeat = ev.StartBeat;
|
|
||||||
if (ev is BestdoriChartEvent.System) {
|
|
||||||
if (bgm != null) continue;
|
|
||||||
var tev = (BestdoriChartEvent.System)ev;
|
|
||||||
bgm = StringUtils.TrimExt(tev.data);
|
|
||||||
var name = "bang_dream_girls_band_party__" + bgm;
|
|
||||||
result.Add(new SongResource(name, new FileInfo(Path.Combine(file.Directory.FullName, tev.data))));
|
|
||||||
chart.sounds.Add(new Chart.Sound { time = ToBeatTime(tev.beat), id = name });
|
|
||||||
}
|
|
||||||
else if (ev is BestdoriChartEvent.BPM) {
|
|
||||||
var tev = (BestdoriChartEvent.BPM)ev;
|
|
||||||
tm.BPM = tev.bpm;
|
|
||||||
chart.sigs.Add(new Chart.Signature { time = ToBeatTime(tev.beat), tempo = (float)tev.bpm });
|
|
||||||
}
|
|
||||||
else if (ev is BestdoriChartEvent.Single) {
|
|
||||||
var tev = (BestdoriChartEvent.Single)ev;
|
|
||||||
group.notes.Add(new Chart.Note {
|
|
||||||
time = ToBeatTime(tev.beat),
|
|
||||||
judges = new List<Chart.Judge> { new Chart.Judge { name = tev.flick ? "single_flick" : "single" } },
|
|
||||||
motions = new List<Chart.Motion> { new Chart.Motion { motion = "track:" + tev.lane.ToString(CultureInfo.InvariantCulture) } },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (ev is BestdoriChartEvent.Long) {
|
|
||||||
var tev = (BestdoriChartEvent.Long)ev;
|
|
||||||
var c1 = tev.connections[tev.connections.Count - 1];
|
|
||||||
var note = new Chart.Note {
|
|
||||||
time = ToBeatTime(tev.connections[0].beat),
|
|
||||||
endtime = ToBeatTime(c1.beat),
|
|
||||||
judges = new List<Chart.Judge>(),
|
|
||||||
};
|
|
||||||
for (int i = 0; i < tev.connections.Count; i++) {
|
|
||||||
BestdoriChartEvent.Connection c = tev.connections[i];
|
|
||||||
var motion = new Chart.Motion { motion = "track:" + c.lane.ToString(CultureInfo.InvariantCulture) };
|
|
||||||
if (i == 0) {
|
|
||||||
note.judges.Add(new Chart.Judge { name = "single" });
|
|
||||||
note.motions.Add(motion);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var cbeat = motion.endtime = ToBeatTime(c.beat);
|
|
||||||
if (i > 1) motion.time = ToBeatTime(tev.connections[i - 1].beat);
|
|
||||||
note.motions.Add(motion);
|
|
||||||
if (i == tev.connections.Count - 1)
|
|
||||||
note.judges.Add(new Chart.Judge { time = cbeat, name = c.flick ? "longend_flick" : "longend" });
|
|
||||||
else if (!c.hidden)
|
|
||||||
note.judges.Add(new Chart.Judge { time = cbeat, name = "longnode" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c1.beat > endbeat) endbeat = c1.beat;
|
|
||||||
group.notes.Add(note);
|
|
||||||
}
|
|
||||||
else throw new NotImplementedException("Unsupported event: " + ev.type);
|
|
||||||
}
|
|
||||||
if (bgm == null) throw new FormatException("Chart contains no song");
|
|
||||||
chart.endtime = ToBeatTime(endbeat + 4);
|
|
||||||
if (endbeat > tm.BeatTime) tm.ForwardTo(endbeat);
|
|
||||||
result.Add(new RawChartResource(string.Format("bang_dream_girls_band_party__{0}__{1}", bgm, StringUtils.TrimExt(file.Name)), chart, new ChartMeta {
|
|
||||||
name = string.Format("Bandori {0} {1}", bgm, StringUtils.TrimExt(file.Name)),
|
|
||||||
author = "©BanG Dream! Project ©Craft Egg Inc. ©bushiroad",
|
|
||||||
ruleset = "bang_dream_girls_band_party",
|
|
||||||
note_count = group.notes.Count,
|
|
||||||
length = (float)tm.Time,
|
|
||||||
song = new SongMetaInfo {
|
|
||||||
name = bgm,
|
|
||||||
author = "©BanG Dream! Project ©Craft Egg Inc. ©bushiroad",
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
BeatTime ToBeatTime(double beat, double error = 1e-4) {
|
|
||||||
int i, n, d;
|
|
||||||
FractionUtils.ToFraction(beat, error, out n, out d);
|
|
||||||
i = n / d; n %= d;
|
|
||||||
return new BeatTime(i, n, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable IDE1006
|
|
||||||
[JsonConverter(typeof(BestdoriChartEventCreator))]
|
|
||||||
abstract class BestdoriChartEvent {
|
|
||||||
public abstract string type { get; }
|
|
||||||
public abstract double StartBeat { get; }
|
|
||||||
public abstract class InstantEvent : BestdoriChartEvent {
|
|
||||||
public double beat;
|
|
||||||
public override double StartBeat { get { return beat; } }
|
|
||||||
}
|
|
||||||
public class BPM : InstantEvent {
|
|
||||||
public override string type { get { return "BPM"; } }
|
|
||||||
public double bpm;
|
|
||||||
}
|
|
||||||
public class System : InstantEvent {
|
|
||||||
public override string type { get { return "System"; } }
|
|
||||||
public string data;
|
|
||||||
}
|
|
||||||
public abstract class SingleBase : InstantEvent {
|
|
||||||
public double lane;
|
|
||||||
public bool skill;
|
|
||||||
public bool flick;
|
|
||||||
}
|
|
||||||
public class Single : SingleBase {
|
|
||||||
public override string type { get { return "Single"; } }
|
|
||||||
}
|
|
||||||
public class Directional : SingleBase {
|
|
||||||
public override string type { get { return "Directional"; } }
|
|
||||||
public string direction;
|
|
||||||
public int width;
|
|
||||||
}
|
|
||||||
public class Connection : SingleBase {
|
|
||||||
public override string type { get { return null; } }
|
|
||||||
public bool hidden;
|
|
||||||
}
|
|
||||||
public class Long : BestdoriChartEvent {
|
|
||||||
public override string type { get { return "Long"; } }
|
|
||||||
public List<Connection> connections;
|
|
||||||
public override double StartBeat { get { return connections[0].beat; } }
|
|
||||||
}
|
|
||||||
public class Slide : Long {
|
|
||||||
public override string type { get { return "Slide"; } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#pragma warning restore IDE1006
|
|
||||||
class BestdoriChartEventCreator : CustomCreationConverter<BestdoriChartEvent> {
|
|
||||||
string _currentType;
|
|
||||||
|
|
||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
|
|
||||||
var obj = JObject.ReadFrom(reader);
|
|
||||||
var type = obj["type"];
|
|
||||||
if (type == null) _currentType = null;
|
|
||||||
else _currentType = obj["type"].ToObject<string>();
|
|
||||||
return base.ReadJson(obj.CreateReader(), objectType, existingValue, serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override BestdoriChartEvent Create(Type objectType) {
|
|
||||||
switch (_currentType) {
|
|
||||||
case "BPM": return new BestdoriChartEvent.BPM();
|
|
||||||
case "System": return new BestdoriChartEvent.System();
|
|
||||||
case "Single": return new BestdoriChartEvent.Single();
|
|
||||||
case "Directional": return new BestdoriChartEvent.Directional();
|
|
||||||
case null: return new BestdoriChartEvent.Connection();
|
|
||||||
case "Long": return new BestdoriChartEvent.Long();
|
|
||||||
case "Slide": return new BestdoriChartEvent.Slide();
|
|
||||||
default: throw new ArgumentException("Unknown event type: " + _currentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using Cryville.Crtr.Extensions.Bestdori;
|
|
||||||
using Cryville.Crtr.Extensions.Malody;
|
|
||||||
using Cryville.Crtr.Extensions.osu;
|
|
||||||
using Cryville.Crtr.Extensions.Quaver;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions {
|
|
||||||
public class Extensions : ExtensionInterface {
|
|
||||||
public override IEnumerable<ResourceConverter> GetResourceConverters() {
|
|
||||||
return new ResourceConverter[] {
|
|
||||||
new BestdoriChartConverter(),
|
|
||||||
new MalodyChartConverter(),
|
|
||||||
new osuChartConverter(),
|
|
||||||
new QuaverChartConverter(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<LocalResourceFinder> GetResourceFinders() {
|
|
||||||
return new LocalResourceFinder[] {
|
|
||||||
new MalodyChartFinder(),
|
|
||||||
new osuChartFinder(),
|
|
||||||
new QuaverChartFinder(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: dfd44d1c0681e4842a1f031556519042
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1637936550
|
|
||||||
licenseType: Free
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -1,225 +0,0 @@
|
|||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions.Malody {
|
|
||||||
public class MalodyChartConverter : ResourceConverter {
|
|
||||||
static readonly string[] SUPPORTED_FORMATS = { ".mc", ".mcz" };
|
|
||||||
static readonly string[] MODES = { "key", "step", "dj", "catch", "pad", "taiko", "ring", "slide", "live" };
|
|
||||||
|
|
||||||
public override string[] GetSupportedFormats() {
|
|
||||||
return SUPPORTED_FORMATS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Resource> ConvertFrom(FileInfo file) {
|
|
||||||
List<Resource> result = new List<Resource>();
|
|
||||||
MalodyChart src;
|
|
||||||
if (file.Extension != ".mc") throw new NotImplementedException("mcz file is not supported yet");
|
|
||||||
using (var reader = new StreamReader(file.FullName)) {
|
|
||||||
src = JsonConvert.DeserializeObject<MalodyChart>(reader.ReadToEnd());
|
|
||||||
}
|
|
||||||
if (src.meta.mode != 0) throw new NotImplementedException(string.Format("{0} mode is not supported yet", MODES[src.meta.mode]));
|
|
||||||
|
|
||||||
var ruleset = "malody!" + MODES[src.meta.mode];
|
|
||||||
if (src.meta.mode == 0) {
|
|
||||||
ruleset += "." + src.meta.mode_ext.column.ToString(CultureInfo.InvariantCulture) + "k";
|
|
||||||
}
|
|
||||||
|
|
||||||
ChartMeta meta = new ChartMeta() {
|
|
||||||
name = src.meta.version,
|
|
||||||
author = src.meta.creator,
|
|
||||||
song = new SongMetaInfo() {
|
|
||||||
name = src.meta.song.titleorg != null ? src.meta.song.titleorg : src.meta.song.title,
|
|
||||||
author = src.meta.song.artistorg != null ? src.meta.song.artistorg : src.meta.song.artist,
|
|
||||||
},
|
|
||||||
ruleset = ruleset,
|
|
||||||
};
|
|
||||||
|
|
||||||
Chart chart = new Chart {
|
|
||||||
format = 2,
|
|
||||||
time = new BeatTime(-4, 0, 1),
|
|
||||||
ruleset = ruleset,
|
|
||||||
sigs = new List<Chart.Signature>(),
|
|
||||||
sounds = new List<Chart.Sound>(),
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
groups = new List<Chart.Group>(),
|
|
||||||
};
|
|
||||||
var group = new Chart.Group() {
|
|
||||||
tracks = new List<Chart.Track>(),
|
|
||||||
notes = new List<Chart.Note>(),
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
};
|
|
||||||
chart.groups.Add(group);
|
|
||||||
int col = src.meta.mode_ext.column;
|
|
||||||
|
|
||||||
IEnumerable<MalodyChart.IEvent> events = src.time.Cast<MalodyChart.IEvent>();
|
|
||||||
if (src.effect != null) events = events.Concat(src.effect.Cast<MalodyChart.IEvent>());
|
|
||||||
events = events.Concat(src.note.Cast<MalodyChart.IEvent>());
|
|
||||||
List<MalodyChart.IEvent> endEvents = new List<MalodyChart.IEvent>();
|
|
||||||
foreach (var ev in events)
|
|
||||||
if (ev.endbeat != null)
|
|
||||||
endEvents.Add(new MalodyChart.EndEvent {
|
|
||||||
beat = ev.endbeat,
|
|
||||||
StartEvent = ev,
|
|
||||||
});
|
|
||||||
events = events.Concat(endEvents)
|
|
||||||
.OrderBy(e => e.beat[0] + (float)e.beat[1] / e.beat[2])
|
|
||||||
.ThenBy(e => e.Priority);
|
|
||||||
|
|
||||||
Dictionary<MalodyChart.IEvent, StartEventState> longEvents
|
|
||||||
= new Dictionary<MalodyChart.IEvent, StartEventState>();
|
|
||||||
|
|
||||||
float? baseBpm = null;
|
|
||||||
var tm = new FractionalBeatTimeTimingModel();
|
|
||||||
foreach (var ev in events) {
|
|
||||||
var beat = new BeatTime(ev.beat[0], ev.beat[1], ev.beat[2]);
|
|
||||||
tm.ForwardTo(beat);
|
|
||||||
if (ev is MalodyChart.Time) {
|
|
||||||
var tev = (MalodyChart.Time)ev;
|
|
||||||
if (baseBpm == null) baseBpm = tev.bpm;
|
|
||||||
tm.BPM = tev.bpm;
|
|
||||||
chart.sigs.Add(new Chart.Signature {
|
|
||||||
time = beat,
|
|
||||||
tempo = tev.bpm,
|
|
||||||
});
|
|
||||||
chart.motions.Add(new Chart.Motion {
|
|
||||||
time = beat,
|
|
||||||
motion = "svm:" + (tev.bpm / baseBpm.Value).ToString(CultureInfo.InvariantCulture)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (ev is MalodyChart.Effect) {
|
|
||||||
var tev = (MalodyChart.Effect)ev;
|
|
||||||
if (tev.scroll != null) group.motions.Add(new Chart.Motion {
|
|
||||||
time = beat,
|
|
||||||
motion = "svm:" + tev.scroll.Value.ToString(CultureInfo.InvariantCulture)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (ev is MalodyChart.Note) {
|
|
||||||
var tev = (MalodyChart.Note)ev;
|
|
||||||
if (tev.type == 1) {
|
|
||||||
if (tev.beat[0] == 0 && tev.beat[1] == 0) {
|
|
||||||
var res = new SongResource(meta.song.name, new FileInfo(file.DirectoryName + "/" + tev.sound));
|
|
||||||
result.Add(res);
|
|
||||||
chart.sounds.Add(new Chart.Sound {
|
|
||||||
time = new BeatTime(0, 0, 1),
|
|
||||||
id = res.Name,
|
|
||||||
offset = -tev.offset / 1000f,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else throw new NotImplementedException("Key sounds are not supported yet");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var rn = new Chart.Note() {
|
|
||||||
time = beat,
|
|
||||||
motions = new List<Chart.Motion> {
|
|
||||||
new Chart.Motion() { motion = "track:" + tev.column.ToString(CultureInfo.InvariantCulture) }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
if (tev.endbeat != null) {
|
|
||||||
rn.endtime = new BeatTime(tev.endbeat[0], tev.endbeat[1], tev.endbeat[2]);
|
|
||||||
longEvents.Add(ev, new StartEventState {
|
|
||||||
Destination = rn,
|
|
||||||
Time = tm.Time,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
group.notes.Add(rn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ev is MalodyChart.EndEvent) {
|
|
||||||
var tev = (MalodyChart.EndEvent)ev;
|
|
||||||
if (tev.StartEvent is MalodyChart.Note) {
|
|
||||||
var sev = tev.StartEvent;
|
|
||||||
longEvents.Remove(sev);
|
|
||||||
}
|
|
||||||
else throw new NotSupportedException("Unrecognized long event");
|
|
||||||
}
|
|
||||||
else throw new NotSupportedException("Unrecognized event");
|
|
||||||
}
|
|
||||||
var endbeat = tm.FractionalBeatTime;
|
|
||||||
endbeat.b += 4;
|
|
||||||
chart.endtime = endbeat;
|
|
||||||
meta.length = (float)tm.Time;
|
|
||||||
meta.note_count = group.notes.Count;
|
|
||||||
string chartName = string.Format("{0} - {1}", meta.song.name, meta.name);
|
|
||||||
if (src.meta.background != null) {
|
|
||||||
meta.cover = src.meta.background;
|
|
||||||
}
|
|
||||||
result.Add(new RawChartResource(chartName, chart, meta));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StartEventState {
|
|
||||||
public double Time { get; set; }
|
|
||||||
public ChartEvent Destination { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable IDE1006
|
|
||||||
struct MalodyChart {
|
|
||||||
public interface IEvent {
|
|
||||||
int[] beat { get; set; }
|
|
||||||
int[] endbeat { get; set; }
|
|
||||||
int Priority { get; }
|
|
||||||
}
|
|
||||||
public struct EndEvent : IEvent {
|
|
||||||
public int[] beat { get; set; }
|
|
||||||
public int[] endbeat { get; set; }
|
|
||||||
public IEvent StartEvent { get; set; }
|
|
||||||
public int Priority { get { return StartEvent.Priority - 1; } }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Meta meta;
|
|
||||||
public struct Meta {
|
|
||||||
public SongInfo song;
|
|
||||||
public struct SongInfo {
|
|
||||||
public string title;
|
|
||||||
public string artist;
|
|
||||||
public string titleorg;
|
|
||||||
public string artistorg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string background;
|
|
||||||
|
|
||||||
public string creator;
|
|
||||||
public string version;
|
|
||||||
|
|
||||||
public int mode;
|
|
||||||
public ModeExt mode_ext;
|
|
||||||
public struct ModeExt {
|
|
||||||
public int column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Time> time;
|
|
||||||
public struct Time : IEvent {
|
|
||||||
public int[] beat { get; set; }
|
|
||||||
public int[] endbeat { get; set; }
|
|
||||||
public float bpm;
|
|
||||||
public int Priority { get { return -2; } }
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Effect> effect;
|
|
||||||
public struct Effect : IEvent {
|
|
||||||
public int[] beat { get; set; }
|
|
||||||
public int[] endbeat { get; set; }
|
|
||||||
public float? scroll;
|
|
||||||
public int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Note> note;
|
|
||||||
public struct Note : IEvent {
|
|
||||||
public int[] beat { get; set; }
|
|
||||||
public int[] endbeat { get; set; }
|
|
||||||
public int column;
|
|
||||||
public string sound;
|
|
||||||
public int offset;
|
|
||||||
public int type;
|
|
||||||
public int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#pragma warning restore IDE1006
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b3624013a6911ba45933085332724ff1
|
|
||||||
timeCreated: 1637936498
|
|
||||||
licenseType: Free
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -1,26 +0,0 @@
|
|||||||
using Cryville.Common;
|
|
||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions.Malody {
|
|
||||||
public class MalodyChartFinder : LocalResourceFinder {
|
|
||||||
public override string Name { get { return "Malody beatmaps"; } }
|
|
||||||
|
|
||||||
public override string GetRootPath() {
|
|
||||||
switch (Environment.OSVersion.Platform) {
|
|
||||||
case PlatformID.Unix:
|
|
||||||
return "/storage/emulated/0/data/malody/beatmap";
|
|
||||||
case PlatformID.Win32NT:
|
|
||||||
var reg = Registry.ClassesRoot.OpenSubKey(@"malody\Shell\Open\Command");
|
|
||||||
if (reg == null) return null;
|
|
||||||
var pathObj = reg.GetValue(null);
|
|
||||||
if (pathObj == null) return null;
|
|
||||||
var path = (string)pathObj;
|
|
||||||
return Path.Combine(new FileInfo(StringUtils.GetProcessPathFromCommand(path)).Directory.FullName, "beatmap");
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3c9beaff62143a2468e18ad4642232c0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -1,153 +0,0 @@
|
|||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using Quaver.API.Maps;
|
|
||||||
using Quaver.API.Maps.Structures;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions.Quaver {
|
|
||||||
public class QuaverChartConverter : ResourceConverter {
|
|
||||||
static readonly string[] SUPPORTED_FORMATS = { ".qua" };
|
|
||||||
const double OFFSET = 0.05;
|
|
||||||
|
|
||||||
public override string[] GetSupportedFormats() {
|
|
||||||
return SUPPORTED_FORMATS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Resource> ConvertFrom(FileInfo file) {
|
|
||||||
List<Resource> result = new List<Resource>();
|
|
||||||
var src = Qua.Parse(file.FullName);
|
|
||||||
var ruleset = "quaver!" + src.Mode.ToString().ToLower();
|
|
||||||
var meta = new ChartMeta {
|
|
||||||
name = src.DifficultyName,
|
|
||||||
author = src.Creator,
|
|
||||||
song = new SongMetaInfo {
|
|
||||||
name = src.Title,
|
|
||||||
author = src.Artist,
|
|
||||||
},
|
|
||||||
ruleset = ruleset,
|
|
||||||
cover = src.BackgroundFile,
|
|
||||||
note_count = src.HitObjects.Count,
|
|
||||||
};
|
|
||||||
var chart = new Chart {
|
|
||||||
format = 2,
|
|
||||||
time = new BeatTime(-4, 0, 1),
|
|
||||||
ruleset = ruleset,
|
|
||||||
sigs = new List<Chart.Signature>(),
|
|
||||||
sounds = new List<Chart.Sound> {
|
|
||||||
new Chart.Sound { time = new BeatTime(0, 0, 1), id = src.Title, offset = (float)(src.TimingPoints[0].StartTime / 1e3 + OFFSET) }
|
|
||||||
},
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
groups = new List<Chart.Group>(),
|
|
||||||
};
|
|
||||||
var group = new Chart.Group() {
|
|
||||||
tracks = new List<Chart.Track>(),
|
|
||||||
notes = new List<Chart.Note>(),
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
};
|
|
||||||
chart.groups.Add(group);
|
|
||||||
result.Add(new RawChartResource(string.Format("{0} - {1}", meta.song.name, meta.name), chart, meta));
|
|
||||||
result.Add(new SongResource(meta.song.name, new FileInfo(Path.Combine(file.DirectoryName, src.AudioFile))));
|
|
||||||
|
|
||||||
var evs = new List<EventWrapper>();
|
|
||||||
foreach (var e in src.HitObjects) evs.Add(new EventWrapper.HitObject(e));
|
|
||||||
foreach (var e in src.SliderVelocities) evs.Add(new EventWrapper.SliderVelocity(e));
|
|
||||||
foreach (var e in src.SoundEffects) evs.Add(new EventWrapper.SoundEffect(e));
|
|
||||||
foreach (var e in src.TimingPoints) evs.Add(new EventWrapper.TimingPoint(e));
|
|
||||||
var evc = evs.Count;
|
|
||||||
for (int i = 0; i < evc; i++) if (evs[i].IsLong) evs.Add(new EventWrapper.EndEvent(evs[i]));
|
|
||||||
evs.Sort();
|
|
||||||
|
|
||||||
var longevs = new Dictionary<EventWrapper, ChartEvent>();
|
|
||||||
var tm = new TimeTimingModel(src.TimingPoints[0].StartTime / 1e3);
|
|
||||||
foreach (var ev in evs) {
|
|
||||||
tm.ForwardTo(ev.StartTime / 1e3);
|
|
||||||
if (ev is EventWrapper.HitObject) {
|
|
||||||
var tev = (EventWrapper.HitObject)ev;
|
|
||||||
var rn = new Chart.Note {
|
|
||||||
time = tm.FractionalBeatTime,
|
|
||||||
motions = new List<Chart.Motion> {
|
|
||||||
new Chart.Motion { motion = string.Format(CultureInfo.InvariantCulture, "track:{0}", tev.Event.Lane - 1) }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
if (ev.IsLong) longevs.Add(ev, rn);
|
|
||||||
group.notes.Add(rn);
|
|
||||||
}
|
|
||||||
else if (ev is EventWrapper.SliderVelocity) {
|
|
||||||
var tev = (EventWrapper.SliderVelocity)ev;
|
|
||||||
group.motions.Add(new Chart.Motion {
|
|
||||||
time = tm.FractionalBeatTime,
|
|
||||||
motion = string.Format(CultureInfo.InvariantCulture, "svm:{0}", tev.Event.Multiplier),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (ev is EventWrapper.TimingPoint) {
|
|
||||||
var tev = (EventWrapper.TimingPoint)ev;
|
|
||||||
tm.BPM = tev.Event.Bpm;
|
|
||||||
chart.sigs.Add(new Chart.Signature {
|
|
||||||
time = tm.FractionalBeatTime,
|
|
||||||
tempo = tev.Event.Bpm,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (ev is EventWrapper.EndEvent) {
|
|
||||||
var tev = (EventWrapper.EndEvent)ev;
|
|
||||||
var oev = tev.Original;
|
|
||||||
longevs[oev].endtime = tm.FractionalBeatTime;
|
|
||||||
}
|
|
||||||
else throw new NotSupportedException("Sound effects are not supported yet");
|
|
||||||
}
|
|
||||||
var endbeat = tm.FractionalBeatTime;
|
|
||||||
endbeat.b += 4;
|
|
||||||
chart.endtime = endbeat;
|
|
||||||
meta.length = (float)tm.Time;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class EventWrapper : IComparable<EventWrapper> {
|
|
||||||
public abstract int StartTime { get; }
|
|
||||||
public abstract int EndTime { get; }
|
|
||||||
public bool IsLong { get { return EndTime > 0; } }
|
|
||||||
public abstract int Priority { get; }
|
|
||||||
public int CompareTo(EventWrapper other) {
|
|
||||||
var c = StartTime.CompareTo(other.StartTime);
|
|
||||||
if (c != 0) return c;
|
|
||||||
return Priority.CompareTo(other.Priority);
|
|
||||||
}
|
|
||||||
public class HitObject : EventWrapper {
|
|
||||||
public HitObjectInfo Event;
|
|
||||||
public HitObject(HitObjectInfo ev) { Event = ev; }
|
|
||||||
public override int StartTime { get { return Event.StartTime; } }
|
|
||||||
public override int EndTime { get { return Event.EndTime; } }
|
|
||||||
public override int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
public class SliderVelocity : EventWrapper {
|
|
||||||
public SliderVelocityInfo Event;
|
|
||||||
public SliderVelocity(SliderVelocityInfo ev) { Event = ev; }
|
|
||||||
public override int StartTime { get { return (int)Event.StartTime; } }
|
|
||||||
public override int EndTime { get { return 0; } }
|
|
||||||
public override int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
public class SoundEffect : EventWrapper {
|
|
||||||
public SoundEffectInfo Event;
|
|
||||||
public SoundEffect(SoundEffectInfo ev) { Event = ev; }
|
|
||||||
public override int StartTime { get { return (int)Event.StartTime; } }
|
|
||||||
public override int EndTime { get { return 0; } }
|
|
||||||
public override int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
public class TimingPoint : EventWrapper {
|
|
||||||
public TimingPointInfo Event;
|
|
||||||
public TimingPoint(TimingPointInfo ev) { Event = ev; }
|
|
||||||
public override int StartTime { get { return (int)Event.StartTime; } }
|
|
||||||
public override int EndTime { get { return 0; } }
|
|
||||||
public override int Priority { get { return -2; } }
|
|
||||||
}
|
|
||||||
public class EndEvent : EventWrapper {
|
|
||||||
public EventWrapper Original;
|
|
||||||
public EndEvent(EventWrapper ev) { if (!ev.IsLong) throw new ArgumentException("Event is not long"); Original = ev; }
|
|
||||||
public override int StartTime { get { return Original.EndTime; } }
|
|
||||||
public override int EndTime { get { return 0; } }
|
|
||||||
public override int Priority { get { return Original.Priority - 1; } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b073cac7ce0d41a4f8ca589845678aa2
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -1,24 +0,0 @@
|
|||||||
using Cryville.Common;
|
|
||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions.Quaver {
|
|
||||||
public class QuaverChartFinder : LocalResourceFinder {
|
|
||||||
public override string Name { get { return "Quaver beatmaps"; } }
|
|
||||||
|
|
||||||
public override string GetRootPath() {
|
|
||||||
switch (Environment.OSVersion.Platform) {
|
|
||||||
case PlatformID.Win32NT:
|
|
||||||
var reg = Registry.ClassesRoot.OpenSubKey(@"quaver\Shell\Open\Command");
|
|
||||||
if (reg == null) return null;
|
|
||||||
var pathObj = reg.GetValue(null);
|
|
||||||
if (pathObj == null) return null;
|
|
||||||
var path = (string)pathObj;
|
|
||||||
return Path.Combine(new FileInfo(StringUtils.GetProcessPathFromCommand(path)).Directory.FullName, "Songs");
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 68bacf7746cbeea42a78a7d55cfdbea0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -1,56 +0,0 @@
|
|||||||
using Cryville.Common.Math;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions {
|
|
||||||
public abstract class TimingModel {
|
|
||||||
public double Time { get; protected set; }
|
|
||||||
public double BeatTime { get; protected set; }
|
|
||||||
public BeatTime FractionalBeatTime { get; protected set; }
|
|
||||||
double m_bpm;
|
|
||||||
public double BPM { get { return m_bpm; } set { m_bpm = value; } }
|
|
||||||
public double BeatLength { get { return 60 / m_bpm; } set { m_bpm = 60 / value; } }
|
|
||||||
public TimingModel(double offset) {
|
|
||||||
Time = offset;
|
|
||||||
FractionalBeatTime = new BeatTime(0, 0, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class FractionalBeatTimeTimingModel : TimingModel {
|
|
||||||
public FractionalBeatTimeTimingModel(double offset = 0) : base(offset) { }
|
|
||||||
public void ForwardTo(BeatTime t) {
|
|
||||||
if (t == FractionalBeatTime) return;
|
|
||||||
if (BPM == 0) throw new InvalidOperationException("BPM not determined");
|
|
||||||
FractionalBeatTime = t;
|
|
||||||
var nt = t.Decimal;
|
|
||||||
Time += (nt - BeatTime) / BPM * 60;
|
|
||||||
BeatTime = nt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class BeatTimeTimingModel : TimingModel {
|
|
||||||
public BeatTimeTimingModel(double offset = 0) : base(offset) { }
|
|
||||||
public void ForwardTo(double t) {
|
|
||||||
if (t == BeatTime) return;
|
|
||||||
if (BPM == 0) throw new InvalidOperationException("BPM not determined");
|
|
||||||
Time += (t - BeatTime) / BPM * 60;
|
|
||||||
BeatTime = t;
|
|
||||||
FractionalBeatTime = ToBeatTime(t);
|
|
||||||
}
|
|
||||||
static BeatTime ToBeatTime(double beat, double error = 1e-4) {
|
|
||||||
int i, n, d;
|
|
||||||
FractionUtils.ToFraction(beat, error, out n, out d);
|
|
||||||
i = n / d; n %= d;
|
|
||||||
return new BeatTime(i, n, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class TimeTimingModel : TimingModel {
|
|
||||||
public TimeTimingModel(double offset = 0) : base(offset) { }
|
|
||||||
public void ForwardTo(double t) {
|
|
||||||
if (t == Time) return;
|
|
||||||
if (BPM == 0) throw new InvalidOperationException("BPM not determined");
|
|
||||||
BeatTime += (t - Time) * BPM / 60;
|
|
||||||
int n, d;
|
|
||||||
FractionUtils.ToFraction(BeatTime, 1f / 48 / BPM * 60, out n, out d);
|
|
||||||
FractionalBeatTime = new BeatTime(n, d);
|
|
||||||
Time = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5c4a1fab8f53dd742ba6501d682eb7f6
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b9bd9e24d7c553341a2a12391843542f
|
guid: 3fe9f91db8da80f459bcf70ff680644f
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
@@ -1,9 +1,10 @@
|
|||||||
using Newtonsoft.Json;
|
using Cryville.Crtr.Extension;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Cryville.Crtr.Browsing {
|
namespace Cryville.Crtr.Extensions.Umg {
|
||||||
public class ChartResourceImporter : ResourceConverter {
|
public class ChartResourceImporter : ResourceConverter {
|
||||||
static readonly string[] SUPPORTED_FORMATS = { ".umgc" };
|
static readonly string[] SUPPORTED_FORMATS = { ".umgc" };
|
||||||
public override string[] GetSupportedFormats() {
|
public override string[] GetSupportedFormats() {
|
||||||
@@ -19,4 +20,13 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 168366bb891392b42a1d0a6bfa068ff3
|
guid: bfcd614ec96fbe543aa2b2f1630aac73
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
18
Assets/Cryville/Crtr/Extensions/Umg/Extension.cs
Normal file
18
Assets/Cryville/Crtr/Extensions/Umg/Extension.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Cryville.Crtr.Extension;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Cryville.Crtr.Extensions.Umg {
|
||||||
|
public class Extension : ExtensionInterface {
|
||||||
|
public override IEnumerable<ResourceConverter> GetResourceConverters() {
|
||||||
|
return new ResourceConverter[] {
|
||||||
|
new ChartResourceImporter(),
|
||||||
|
new RulesetResourceImporter(),
|
||||||
|
new SkinResourceImporter(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<LocalResourceFinder> GetResourceFinders() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Cryville/Crtr/Extensions/Umg/Extension.cs.meta
Normal file
11
Assets/Cryville/Crtr/Extensions/Umg/Extension.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 323b670cbdea58644ac9ba20fc4c1a89
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -1,9 +1,10 @@
|
|||||||
using Newtonsoft.Json;
|
using Cryville.Crtr.Extension;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Cryville.Crtr.Browsing {
|
namespace Cryville.Crtr.Extensions.Umg {
|
||||||
public class RulesetResourceImporter : ResourceConverter {
|
public class RulesetResourceImporter : ResourceConverter {
|
||||||
static readonly string[] SUPPORTED_FORMATS = { ".umgr" };
|
static readonly string[] SUPPORTED_FORMATS = { ".umgr" };
|
||||||
public override string[] GetSupportedFormats() {
|
public override string[] GetSupportedFormats() {
|
||||||
@@ -17,4 +18,12 @@ namespace Cryville.Crtr.Browsing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: f2c1531e76f19a647865f7ec335561cd
|
guid: 9e856b78a468f644191d62ab489ae089
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
34
Assets/Cryville/Crtr/Extensions/Umg/SkinResourceImporter.cs
Normal file
34
Assets/Cryville/Crtr/Extensions/Umg/SkinResourceImporter.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using Cryville.Crtr.Extension;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Cryville.Crtr.Extensions.Umg {
|
||||||
|
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) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 9904b4c21758c5046afc341fe2fa8845
|
guid: 2afd6abf146c2ee45ab749477b8c7fda
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
@@ -1,383 +0,0 @@
|
|||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions.osu {
|
|
||||||
#pragma warning disable IDE1006
|
|
||||||
public class osuChartConverter : ResourceConverter {
|
|
||||||
#pragma warning restore IDE1006
|
|
||||||
static readonly string[] SUPPORTED_FORMATS = { ".osu" };
|
|
||||||
const double OFFSET = 0.05;
|
|
||||||
|
|
||||||
public override string[] GetSupportedFormats() {
|
|
||||||
return SUPPORTED_FORMATS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Resource> ConvertFrom(FileInfo file) {
|
|
||||||
List<Resource> result = new List<Resource>();
|
|
||||||
var meta = new ChartMeta { song = new SongMetaInfo() };
|
|
||||||
var group = new Chart.Group() {
|
|
||||||
tracks = new List<Chart.Track>(),
|
|
||||||
notes = new List<Chart.Note>(),
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
};
|
|
||||||
var chart = new Chart {
|
|
||||||
format = 2,
|
|
||||||
time = new BeatTime(-4, 0, 1),
|
|
||||||
sigs = new List<Chart.Signature>(),
|
|
||||||
sounds = new List<Chart.Sound>(),
|
|
||||||
motions = new List<Chart.Motion>(),
|
|
||||||
groups = new List<Chart.Group> { group },
|
|
||||||
};
|
|
||||||
var diff = new DifficultyInfo();
|
|
||||||
var evs = new List<osuEvent>();
|
|
||||||
|
|
||||||
bool ftc = false;
|
|
||||||
using (var reader = new StreamReader(file.FullName, Encoding.UTF8)) {
|
|
||||||
Section section = Section.General;
|
|
||||||
int version;
|
|
||||||
bool flag = false;
|
|
||||||
string line;
|
|
||||||
while ((line = reader.ReadLine()) != null) {
|
|
||||||
if (!flag) {
|
|
||||||
if (line.StartsWith("osu file format v")) {
|
|
||||||
version = int.Parse(line.Substring(17), CultureInfo.InvariantCulture);
|
|
||||||
if (version > 14) throw new NotSupportedException("osu! chart format version too high");
|
|
||||||
else if (version < 5) throw new NotImplementedException("osu! chart format version too low"); // TODO apply offset
|
|
||||||
}
|
|
||||||
else throw new NotSupportedException("Unrecognized osu! chart format");
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
if (ShouldSkipLine(line)) continue;
|
|
||||||
if (section != Section.Metadata) line = StripComments(line);
|
|
||||||
line = line.TrimEnd();
|
|
||||||
if (line.StartsWith('[') && line.EndsWith(']')) {
|
|
||||||
Enum.TryParse(line.Substring(1, line.Length - 2), out section);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ParseLine(meta, chart, diff, evs, ref ftc, section, line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (meta.ruleset == "osu!mania") {
|
|
||||||
chart.ruleset = meta.ruleset += "." + diff.CircleSize.ToString(CultureInfo.InvariantCulture) + "k";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ftc) throw new InvalidOperationException("Unconvertible chart: no timing point is present in this beatmap");
|
|
||||||
result.Add(new RawChartResource(string.Format("{0} - {1}", meta.song.name, meta.name), chart, meta));
|
|
||||||
var evc = evs.Count;
|
|
||||||
for (int i = 0; i < evc; i++) if (evs[i].IsLong) evs.Add(new osuEvent.EndEvent(evs[i]));
|
|
||||||
evs.Sort();
|
|
||||||
|
|
||||||
var longevs = new Dictionary<osuEvent, ChartEvent>();
|
|
||||||
Chart.Sound bgmEv = null;
|
|
||||||
TimeTimingModel tm = null;
|
|
||||||
foreach (var ev in evs) {
|
|
||||||
if (tm != null) tm.ForwardTo(ev.StartTime / 1e3);
|
|
||||||
if (ev is osuEvent.Audio) {
|
|
||||||
var tev = (osuEvent.Audio)ev;
|
|
||||||
chart.sounds.Add(bgmEv = new Chart.Sound { time = new BeatTime(0, 0, 1), id = meta.song.name });
|
|
||||||
result.Add(new SongResource(meta.song.name, new FileInfo(Path.Combine(file.DirectoryName, tev.AudioFile))));
|
|
||||||
}
|
|
||||||
else if (ev is osuEvent.Background) {
|
|
||||||
meta.cover = ((osuEvent.Background)ev).FileName;
|
|
||||||
}
|
|
||||||
else if (ev is osuEvent.EffectPoint) {
|
|
||||||
var tev = (osuEvent.EffectPoint)ev;
|
|
||||||
group.motions.Add(new Chart.Motion { time = tm.FractionalBeatTime, motion = string.Format(CultureInfo.InvariantCulture, "svm:{0}", tev.ScrollSpeed) });
|
|
||||||
}
|
|
||||||
else if (ev is osuEvent.EndEvent) {
|
|
||||||
if (tm == null) throw new InvalidOperationException("Unconvertible chart: timed event before first timing point");
|
|
||||||
var tev = (osuEvent.EndEvent)ev;
|
|
||||||
longevs[tev.Original].endtime = tm.FractionalBeatTime;
|
|
||||||
}
|
|
||||||
else if (ev is osuEvent.HOMania) {
|
|
||||||
if (tm == null) throw new InvalidOperationException("Unconvertible chart: timed event before first timing point");
|
|
||||||
var tev = (osuEvent.HOMania)ev;
|
|
||||||
var rn = new Chart.Note {
|
|
||||||
time = tm.FractionalBeatTime,
|
|
||||||
motions = new List<Chart.Motion> {
|
|
||||||
new Chart.Motion{ motion = string.Format(CultureInfo.InvariantCulture, "track:{0}", (int)(tev.X * diff.CircleSize / 512)) }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
group.notes.Add(rn);
|
|
||||||
if (tev.IsLong) longevs.Add(tev, rn);
|
|
||||||
}
|
|
||||||
else if (ev is osuEvent.TimingChange) {
|
|
||||||
var tev = (osuEvent.TimingChange)ev;
|
|
||||||
if (tm == null) {
|
|
||||||
tm = new TimeTimingModel(tev.StartTime / 1e3);
|
|
||||||
bgmEv.offset = (float)(tev.StartTime / 1e3 + OFFSET);
|
|
||||||
}
|
|
||||||
tm.BeatLength = tev.BeatLength / 1e3;
|
|
||||||
chart.sigs.Add(new Chart.Signature {
|
|
||||||
time = tm.FractionalBeatTime,
|
|
||||||
tempo = (float)tm.BPM,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else throw new NotSupportedException("Unsupported event detected");
|
|
||||||
}
|
|
||||||
var endbeat = tm.FractionalBeatTime;
|
|
||||||
endbeat.b += 4;
|
|
||||||
chart.endtime = endbeat;
|
|
||||||
meta.length = (float)tm.Time;
|
|
||||||
meta.note_count = group.notes.Count;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParseLine(ChartMeta meta, Chart chart, DifficultyInfo diff, List<osuEvent> evs, ref bool ftc, Section section, string line) {
|
|
||||||
switch (section) {
|
|
||||||
case Section.General: HandleGeneral(meta, chart, evs, line); return;
|
|
||||||
case Section.Metadata: HandleMetadata(meta, line); return;
|
|
||||||
case Section.Difficulty: HandleDifficulty(diff, line); return;
|
|
||||||
case Section.Events: HandleEvent(evs, line); return;
|
|
||||||
case Section.TimingPoints: HandleTimingPoint(chart, evs, ref ftc, line); return;
|
|
||||||
case Section.HitObjects: HandleHitObject(evs, line); return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleGeneral(ChartMeta meta, Chart chart, List<osuEvent> evs, string line) {
|
|
||||||
var pair = SplitKeyVal(line);
|
|
||||||
switch (pair.Key) {
|
|
||||||
case @"AudioFilename":
|
|
||||||
evs.Add(new osuEvent.Audio { StartTime = double.NegativeInfinity, AudioFile = pair.Value });
|
|
||||||
break;
|
|
||||||
case @"Mode":
|
|
||||||
int rulesetID = int.Parse(pair.Value, CultureInfo.InvariantCulture);
|
|
||||||
var ruleset = "osu!";
|
|
||||||
switch (rulesetID) {
|
|
||||||
case 0: /*ruleset += "standard";*/ throw new NotImplementedException("osu!standard mode is not supported yet");
|
|
||||||
case 1: /*ruleset += "taiko";*/ throw new NotImplementedException("osu!taiko mode is not supported yet");
|
|
||||||
case 2: /*ruleset += "catch";*/ throw new NotImplementedException("osu!catch mode is not supported yet");
|
|
||||||
case 3: ruleset += "mania"; break;
|
|
||||||
}
|
|
||||||
meta.ruleset = chart.ruleset = ruleset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleMetadata(ChartMeta meta, string line) {
|
|
||||||
var pair = SplitKeyVal(line);
|
|
||||||
switch (pair.Key) {
|
|
||||||
case @"Title": if (meta.song.name == null) meta.song.name = pair.Value; break;
|
|
||||||
case @"TitleUnicode": meta.song.name = pair.Value; break;
|
|
||||||
case @"Artist": if (meta.song.author == null) meta.song.author = pair.Value; break;
|
|
||||||
case @"ArtistUnicode": meta.song.author = pair.Value; break;
|
|
||||||
case @"Creator": meta.author = pair.Value; break;
|
|
||||||
case @"Version": meta.name = pair.Value; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleDifficulty(DifficultyInfo diff, string line) {
|
|
||||||
var pair = SplitKeyVal(line);
|
|
||||||
switch (pair.Key) {
|
|
||||||
case @"CircleSize":
|
|
||||||
diff.CircleSize = float.Parse(pair.Value, CultureInfo.InvariantCulture);
|
|
||||||
break;
|
|
||||||
case @"SliderMultiplier":
|
|
||||||
diff.SliderMultiplier = double.Parse(pair.Value, CultureInfo.InvariantCulture);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleEvent(List<osuEvent> evs, string line) {
|
|
||||||
string[] split = line.Split(',');
|
|
||||||
if (!Enum.TryParse(split[0], out LegacyEventType type))
|
|
||||||
throw new InvalidDataException($@"Unknown event type: {split[0]}");
|
|
||||||
switch (type) {
|
|
||||||
case LegacyEventType.Sprite:
|
|
||||||
if (evs.Count == 0 || !(evs[evs.Count - 1] is osuEvent.Background))
|
|
||||||
evs.Add(new osuEvent.Background { StartTime = double.NegativeInfinity, FileName = CleanFilename(split[3]) });
|
|
||||||
break;
|
|
||||||
case LegacyEventType.Background:
|
|
||||||
evs.Add(new osuEvent.Background { StartTime = double.NegativeInfinity, FileName = CleanFilename(split[2]) });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enum LegacyEventType {
|
|
||||||
Background = 0,
|
|
||||||
Video = 1,
|
|
||||||
Break = 2,
|
|
||||||
Colour = 3,
|
|
||||||
Sprite = 4,
|
|
||||||
Sample = 5,
|
|
||||||
Animation = 6
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleTimingPoint(Chart chart, List<osuEvent> evs, ref bool ftc, string line) {
|
|
||||||
string[] split = line.Split(',');
|
|
||||||
|
|
||||||
double time = double.Parse(split[0].Trim(), CultureInfo.InvariantCulture)/* + offset*/;
|
|
||||||
|
|
||||||
// beatLength is allowed to be NaN to handle an edge case in which some beatmaps use NaN slider velocity to disable slider tick generation (see LegacyDifficultyControlPoint).
|
|
||||||
double beatLength = double.Parse(split[1].Trim(), CultureInfo.InvariantCulture);
|
|
||||||
|
|
||||||
// If beatLength is NaN, speedMultiplier should still be 1 because all comparisons against NaN are false.
|
|
||||||
double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;
|
|
||||||
|
|
||||||
int timeSignature = 4;
|
|
||||||
if (split.Length >= 3)
|
|
||||||
timeSignature = split[2][0] == '0' ? 4 : int.Parse(split[2], CultureInfo.InvariantCulture);
|
|
||||||
|
|
||||||
bool timingChange = true;
|
|
||||||
if (split.Length >= 7)
|
|
||||||
timingChange = split[6][0] == '1';
|
|
||||||
|
|
||||||
//bool omitFirstBarSignature = false;
|
|
||||||
|
|
||||||
//if (split.Length >= 8) {
|
|
||||||
// int effectFlags = int.Parse(split[7], CultureInfo.InvariantCulture);
|
|
||||||
// omitFirstBarSignature = (effectFlags & 0x8) != 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (timingChange) {
|
|
||||||
if (double.IsNaN(beatLength))
|
|
||||||
throw new InvalidDataException("Beat length cannot be NaN in a timing control point");
|
|
||||||
var ev = new osuEvent.TimingChange { StartTime = time, BeatLength = beatLength, TimeSignature = timeSignature };
|
|
||||||
if (!ftc) {
|
|
||||||
ftc = true;
|
|
||||||
ev.StartTime = time % beatLength - beatLength;
|
|
||||||
}
|
|
||||||
evs.Add(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
// osu!taiko and osu!mania use effect points rather than difficulty points for scroll speed adjustments.
|
|
||||||
if (chart.ruleset == "osu!taiko" || chart.ruleset == "osu!mania")
|
|
||||||
evs.Add(new osuEvent.EffectPoint { StartTime = time, ScrollSpeed = speedMultiplier });
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleHitObject(List<osuEvent> evs, string line) {
|
|
||||||
string[] split = line.Split(',');
|
|
||||||
|
|
||||||
int posx = (int)float.Parse(split[0], CultureInfo.InvariantCulture);
|
|
||||||
// int posy = (int)float.Parse(split[1], CultureInfo.InvariantCulture);
|
|
||||||
|
|
||||||
double startTime = double.Parse(split[2], CultureInfo.InvariantCulture)/* + Offset*/;
|
|
||||||
|
|
||||||
LegacyHitObjectType type = (LegacyHitObjectType)int.Parse(split[3], CultureInfo.InvariantCulture);
|
|
||||||
|
|
||||||
// int comboOffset = (int)(type & LegacyHitObjectType.ComboOffset) >> 4;
|
|
||||||
type &= ~LegacyHitObjectType.ComboOffset;
|
|
||||||
|
|
||||||
// bool combo = type.HasFlag(LegacyHitObjectType.NewCombo);
|
|
||||||
type &= ~LegacyHitObjectType.NewCombo;
|
|
||||||
|
|
||||||
osuEvent.HitObject result;
|
|
||||||
|
|
||||||
if (type.HasFlag(LegacyHitObjectType.Circle)) {
|
|
||||||
result = new osuEvent.HOManiaHit { X = posx };
|
|
||||||
}
|
|
||||||
else if (type.HasFlag(LegacyHitObjectType.Hold)) {
|
|
||||||
double endTime = Math.Max(startTime, double.Parse(split[2], CultureInfo.InvariantCulture));
|
|
||||||
if (split.Length > 5 && !string.IsNullOrEmpty(split[5])) {
|
|
||||||
string[] ss = split[5].Split(':');
|
|
||||||
endTime = Math.Max(startTime, double.Parse(ss[0], CultureInfo.InvariantCulture));
|
|
||||||
}
|
|
||||||
result = new osuEvent.HOManiaHold { X = posx, EndTime = endTime };
|
|
||||||
}
|
|
||||||
else throw new NotSupportedException(string.Format("Hit objects of type {0} is not supported yet", type));
|
|
||||||
|
|
||||||
if (result == null) throw new InvalidDataException($"Unknown hit object type: {split[3]}");
|
|
||||||
|
|
||||||
result.StartTime = startTime;
|
|
||||||
|
|
||||||
if (result != null) evs.Add(result);
|
|
||||||
}
|
|
||||||
[Flags]
|
|
||||||
enum LegacyHitObjectType {
|
|
||||||
Circle = 1,
|
|
||||||
Slider = 1 << 1,
|
|
||||||
NewCombo = 1 << 2,
|
|
||||||
Spinner = 1 << 3,
|
|
||||||
ComboOffset = (1 << 4) | (1 << 5) | (1 << 6),
|
|
||||||
Hold = 1 << 7
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.TrimStart().StartsWith("//", StringComparison.Ordinal)
|
|
||||||
|| line.StartsWith(' ') || line.StartsWith('_');
|
|
||||||
protected string StripComments(string line) {
|
|
||||||
int index = line.IndexOf("//");
|
|
||||||
if (index > 0) return line.Substring(0, index);
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
KeyValuePair<string, string> SplitKeyVal(string line, char separator = ':', bool shouldTrim = true) {
|
|
||||||
string[] split = line.Split(separator, 2);
|
|
||||||
if (shouldTrim) {
|
|
||||||
for (int i = 0; i < split.Length; i++)
|
|
||||||
split[i] = split[i].Trim();
|
|
||||||
}
|
|
||||||
return new KeyValuePair<string, string> (
|
|
||||||
split[0],
|
|
||||||
split.Length > 1 ? split[1] : string.Empty
|
|
||||||
);
|
|
||||||
}
|
|
||||||
static string CleanFilename(string path) => path.Replace(@"\\", @"\").Trim('"');
|
|
||||||
|
|
||||||
enum Section {
|
|
||||||
General,
|
|
||||||
Editor,
|
|
||||||
Metadata,
|
|
||||||
Difficulty,
|
|
||||||
Events,
|
|
||||||
TimingPoints,
|
|
||||||
Colours,
|
|
||||||
HitObjects,
|
|
||||||
Variables,
|
|
||||||
Fonts,
|
|
||||||
CatchTheBeat,
|
|
||||||
Mania,
|
|
||||||
}
|
|
||||||
|
|
||||||
class DifficultyInfo {
|
|
||||||
public float CircleSize { get; internal set; }
|
|
||||||
public double SliderMultiplier { get; set; }
|
|
||||||
}
|
|
||||||
#pragma warning disable IDE1006 // Naming Styles
|
|
||||||
abstract class osuEvent : IComparable<osuEvent> {
|
|
||||||
public virtual double StartTime { get; set; }
|
|
||||||
public virtual double EndTime { get; set; }
|
|
||||||
public bool IsLong { get { return EndTime - StartTime > 0 && EndTime > 0; } }
|
|
||||||
public abstract int Priority { get; }
|
|
||||||
public int CompareTo(osuEvent other) {
|
|
||||||
var c = StartTime.CompareTo(other.StartTime);
|
|
||||||
if (c != 0) return c;
|
|
||||||
return Priority.CompareTo(other.Priority);
|
|
||||||
}
|
|
||||||
public class EndEvent : osuEvent {
|
|
||||||
public osuEvent Original;
|
|
||||||
public EndEvent(osuEvent ev) { if (!ev.IsLong) throw new ArgumentException("Event is not long"); Original = ev; }
|
|
||||||
public override double StartTime { get { return Original.EndTime; } }
|
|
||||||
public override double EndTime { get { return 0; } }
|
|
||||||
public override int Priority { get { return Original.Priority - 1; } }
|
|
||||||
}
|
|
||||||
public class Audio : osuEvent {
|
|
||||||
public string AudioFile { get; set; }
|
|
||||||
public override int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
public class TimingChange : osuEvent {
|
|
||||||
public double BeatLength { get; set; }
|
|
||||||
public int TimeSignature { get; set; }
|
|
||||||
public override int Priority { get { return -4; } }
|
|
||||||
}
|
|
||||||
public class EffectPoint : osuEvent {
|
|
||||||
public double ScrollSpeed { get; set; }
|
|
||||||
public override int Priority { get { return -2; } }
|
|
||||||
}
|
|
||||||
public class Background : osuEvent {
|
|
||||||
public string FileName { get; set; }
|
|
||||||
public override int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
public class HitObject : osuEvent {
|
|
||||||
public sealed override int Priority { get { return 0; } }
|
|
||||||
}
|
|
||||||
public class HOMania : HitObject {
|
|
||||||
public float X { get; set; }
|
|
||||||
}
|
|
||||||
public class HOManiaHit : HOMania { }
|
|
||||||
public class HOManiaHold : HOMania { }
|
|
||||||
}
|
|
||||||
#pragma warning restore IDE1006 // Naming Styles
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 82838dd8639c2244caf3c830edfbc59c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -1,24 +0,0 @@
|
|||||||
using Cryville.Common;
|
|
||||||
using Cryville.Crtr.Browsing;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Cryville.Crtr.Extensions.osu {
|
|
||||||
public class osuChartFinder : LocalResourceFinder {
|
|
||||||
public override string Name { get { return "osu! beatmaps"; } }
|
|
||||||
|
|
||||||
public override string GetRootPath() {
|
|
||||||
switch (Environment.OSVersion.Platform) {
|
|
||||||
case PlatformID.Win32NT:
|
|
||||||
var reg = Registry.ClassesRoot.OpenSubKey(@"osu!\Shell\Open\Command");
|
|
||||||
if (reg == null) return null;
|
|
||||||
var pathObj = reg.GetValue(null);
|
|
||||||
if (pathObj == null) return null;
|
|
||||||
var path = (string)pathObj;
|
|
||||||
return Path.Combine(new FileInfo(StringUtils.GetProcessPathFromCommand(path)).Directory.FullName, "Songs");
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 365d879536c05284fa2335a7676c6cf4
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@@ -24,7 +24,7 @@ namespace Cryville.Crtr {
|
|||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
public readonly static string FileProtocolPrefix
|
public static readonly string FileProtocolPrefix
|
||||||
#if UNITY_STANDALONE_WIN
|
#if UNITY_STANDALONE_WIN
|
||||||
= "file:///";
|
= "file:///";
|
||||||
#elif UNITY_ANDROID
|
#elif UNITY_ANDROID
|
||||||
@@ -37,9 +37,9 @@ namespace Cryville.Crtr {
|
|||||||
public static SimpleSequencerSource AudioSequencer;
|
public static SimpleSequencerSource AudioSequencer;
|
||||||
public static SimpleSequencerSession AudioSession;
|
public static SimpleSequencerSession AudioSession;
|
||||||
public static InputManager InputManager;
|
public static InputManager InputManager;
|
||||||
public readonly static NetworkTaskWorker NetworkTaskWorker = new NetworkTaskWorker();
|
public static readonly NetworkTaskWorker NetworkTaskWorker = new NetworkTaskWorker();
|
||||||
|
|
||||||
public readonly static JsonSerializerSettings GlobalJsonSerializerSettings
|
public static readonly JsonSerializerSettings GlobalJsonSerializerSettings
|
||||||
= new JsonSerializerSettings() {
|
= new JsonSerializerSettings() {
|
||||||
DefaultValueHandling = DefaultValueHandling.Ignore,
|
DefaultValueHandling = DefaultValueHandling.Ignore,
|
||||||
};
|
};
|
||||||
|
@@ -24,6 +24,7 @@ namespace Cryville.Crtr {
|
|||||||
Components.Add("polysec", typeof(PolygonSGO));
|
Components.Add("polysec", typeof(PolygonSGO));
|
||||||
Components.Add("rect", typeof(SpriteRect));
|
Components.Add("rect", typeof(SpriteRect));
|
||||||
Components.Add("scale3", typeof(SpriteScale3));
|
Components.Add("scale3", typeof(SpriteScale3));
|
||||||
|
Components.Add("sec", typeof(SectionalGameObject));
|
||||||
Components.Add("sprite", typeof(SpriteBase));
|
Components.Add("sprite", typeof(SpriteBase));
|
||||||
Components.Add("text", typeof(SpriteText));
|
Components.Add("text", typeof(SpriteText));
|
||||||
|
|
||||||
@@ -32,6 +33,9 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
Materials.Add("-SpriteMat", Resources.Load<Material>("Materials/SpriteMat"));
|
Materials.Add("-SpriteMat", Resources.Load<Material>("Materials/SpriteMat"));
|
||||||
|
|
||||||
|
Shaders.Add("default", Shader.Find("Sprites/Default"));
|
||||||
|
Shaders.Add("additive", Shader.Find("Sprites/Additive"));
|
||||||
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,8 @@ using Cryville.Common.Unity.Input;
|
|||||||
using Cryville.Crtr.Config;
|
using Cryville.Crtr.Config;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using System.Runtime.Serialization;
|
||||||
|
using RVector3 = UnityEngine.Vector3;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public class InputProxy : IDisposable {
|
public class InputProxy : IDisposable {
|
||||||
@@ -12,12 +13,11 @@ namespace Cryville.Crtr {
|
|||||||
readonly PdtRuleset _ruleset;
|
readonly PdtRuleset _ruleset;
|
||||||
readonly Judge _judge;
|
readonly Judge _judge;
|
||||||
public InputProxy(PdtRuleset ruleset, Judge judge) {
|
public InputProxy(PdtRuleset ruleset, Judge judge) {
|
||||||
unsafe {
|
for (int i = 0; i <= MAX_DEPTH; i++) {
|
||||||
fixed (byte* ptr = _vecbuf) {
|
var vecsrc = new InputVectorSrc();
|
||||||
*(int*)(ptr + 3 * sizeof(float)) = PdtInternalType.Number;
|
_vecsrcs[i] = vecsrc;
|
||||||
}
|
_vecops[i] = new InputVectorOp(vecsrc);
|
||||||
}
|
}
|
||||||
_vecsrc = new PropSrc.Arbitrary(PdtInternalType.Vector, _vecbuf);
|
|
||||||
_etor = ChartPlayer.etor;
|
_etor = ChartPlayer.etor;
|
||||||
_ruleset = ruleset;
|
_ruleset = ruleset;
|
||||||
_judge = judge;
|
_judge = judge;
|
||||||
@@ -174,14 +174,58 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
readonly object _lock = new object();
|
readonly object _lock = new object();
|
||||||
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
|
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
|
||||||
static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary();
|
const int MAX_DEPTH = 15;
|
||||||
readonly byte[] _vecbuf = new byte[3 * sizeof(float) + sizeof(int)];
|
const int MAX_DIMENSION = 3;
|
||||||
readonly PropSrc.Arbitrary _vecsrc;
|
readonly InputVectorSrc[] _vecsrcs = new InputVectorSrc[MAX_DEPTH + 1];
|
||||||
|
readonly InputVectorOp[] _vecops = new InputVectorOp[MAX_DEPTH + 1];
|
||||||
|
unsafe class InputVectorSrc : PropSrc.FixedBuffer {
|
||||||
|
public InputVectorSrc() : base(PdtInternalType.Vector, MAX_DIMENSION * sizeof(float) + sizeof(int)) {
|
||||||
|
fixed (byte* ptr = buf) {
|
||||||
|
*(int*)(ptr + MAX_DIMENSION * sizeof(float)) = PdtInternalType.Number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool IsNull { get; set; }
|
||||||
|
public void Set(RVector3 vec) {
|
||||||
|
fixed (byte* _ptr = buf) {
|
||||||
|
*(RVector3*)_ptr = vec;
|
||||||
|
}
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class InputVectorOp : PropOp {
|
||||||
|
readonly InputVectorSrc _src;
|
||||||
|
public InputVectorOp(InputVectorSrc src) {
|
||||||
|
_src = src;
|
||||||
|
}
|
||||||
|
protected override void Execute() {
|
||||||
|
var op = GetOperand(0);
|
||||||
|
if (op.Type == PdtInternalType.Null) {
|
||||||
|
_src.IsNull = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var vec = new RVector3();
|
||||||
|
int dim;
|
||||||
|
if (op.Type == PdtInternalType.Number) dim = 1;
|
||||||
|
else if (op.Type == PdtInternalType.Vector) {
|
||||||
|
int arrtype, _;
|
||||||
|
op.GetArraySuffix(out arrtype, out _);
|
||||||
|
if (arrtype != PdtInternalType.Number)
|
||||||
|
throw new InvalidCastException("Not a vector of numbers");
|
||||||
|
dim = Math.Min(3, (op.Length - sizeof(int)) / sizeof(float));
|
||||||
|
}
|
||||||
|
else throw new InvalidCastException("Invalid vector");
|
||||||
|
for (int i = 0; i < dim; i++) {
|
||||||
|
vec[i] = op.AsNumber(i * sizeof(float));
|
||||||
|
}
|
||||||
|
_src.IsNull = false;
|
||||||
|
_src.Set(vec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
readonly Dictionary<InputHandler, double> _timeOrigins = new Dictionary<InputHandler, double>();
|
readonly Dictionary<InputHandler, double> _timeOrigins = new Dictionary<InputHandler, double>();
|
||||||
readonly Dictionary<InputSource, int> _activeCounts = new Dictionary<InputSource, int>();
|
readonly Dictionary<InputSource, int> _activeCounts = new Dictionary<InputSource, int>();
|
||||||
readonly Dictionary<InputIdentifier, float> _vect = new Dictionary<InputIdentifier, float>();
|
readonly Dictionary<InputIdentifier, float> _vect = new Dictionary<InputIdentifier, float>();
|
||||||
readonly Dictionary<ProxiedInputIdentifier, PropSrc> _vecs = new Dictionary<ProxiedInputIdentifier, PropSrc>();
|
readonly Dictionary<ProxiedInputIdentifier, PropSrc> _vecs = new Dictionary<ProxiedInputIdentifier, PropSrc>();
|
||||||
static readonly PropSrc.Arbitrary _nullsrc = new PropSrc.Arbitrary(PdtInternalType.Null, new byte[0]);
|
|
||||||
double? _lockTime = null;
|
double? _lockTime = null;
|
||||||
unsafe void OnInput(InputIdentifier id, InputVector vec) {
|
unsafe void OnInput(InputIdentifier id, InputVector vec) {
|
||||||
lock (_lock) {
|
lock (_lock) {
|
||||||
@@ -191,15 +235,12 @@ namespace Cryville.Crtr {
|
|||||||
float ft, tt = (float)(_lockTime != null ? _lockTime.Value : (vec.Time - _timeOrigins[id.Source.Handler]));
|
float ft, tt = (float)(_lockTime != null ? _lockTime.Value : (vec.Time - _timeOrigins[id.Source.Handler]));
|
||||||
if (!_vect.TryGetValue(id, out ft)) ft = tt;
|
if (!_vect.TryGetValue(id, out ft)) ft = tt;
|
||||||
if (vec.IsNull) {
|
if (vec.IsNull) {
|
||||||
_etor.ContextCascadeUpdate(_var_value, _nullsrc);
|
_etor.ContextCascadeUpdate(_var_value, PropSrc.Null);
|
||||||
OnInput(id, proxy.Target, ft, tt, true);
|
OnInput(id, proxy.Target, ft, tt, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fixed (byte* ptr = _vecbuf) {
|
_vecsrcs[0].Set(vec.Vector);
|
||||||
*(Vector3*)ptr = vec.Vector;
|
_etor.ContextCascadeUpdate(_var_value, _vecsrcs[0]);
|
||||||
}
|
|
||||||
_vecsrc.Invalidate();
|
|
||||||
_etor.ContextCascadeUpdate(_var_value, _vecsrc);
|
|
||||||
OnInput(id, proxy.Target, ft, tt, false);
|
OnInput(id, proxy.Target, ft, tt, false);
|
||||||
}
|
}
|
||||||
_vect[id] = tt;
|
_vect[id] = tt;
|
||||||
@@ -209,21 +250,27 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
static readonly int _var_fv = IdentifierManager.SharedInstance.Request("fv");
|
static readonly int _var_fv = IdentifierManager.SharedInstance.Request("fv");
|
||||||
static readonly int _var_tv = IdentifierManager.SharedInstance.Request("tv");
|
static readonly int _var_tv = IdentifierManager.SharedInstance.Request("tv");
|
||||||
unsafe void OnInput(InputIdentifier id, Identifier target, float ft, float tt, bool nullflag) {
|
unsafe void OnInput(InputIdentifier id, Identifier target, float ft, float tt, bool nullflag, int depth = 0) {
|
||||||
|
if (depth >= MAX_DEPTH) throw new InputProxyException("Input propagation limit reached\nThe ruleset has invalid input definitions");
|
||||||
var def = _ruleset.inputs[target];
|
var def = _ruleset.inputs[target];
|
||||||
if (def.pass != null) {
|
if (def.pass != null) {
|
||||||
foreach (var p in def.pass) {
|
foreach (var p in def.pass) {
|
||||||
_etor.ContextCascadeInsert();
|
_etor.ContextCascadeInsert();
|
||||||
_arbop.Name = _var_value;
|
bool newNullFlag = nullflag;
|
||||||
if (!nullflag) _etor.Evaluate(_arbop, p.Value);
|
if (!newNullFlag) {
|
||||||
OnInput(id, p.Key, ft, tt, nullflag);
|
ChartPlayer.etor.Evaluate(_vecops[depth + 1], p.Value);
|
||||||
|
newNullFlag = _vecsrcs[depth + 1].IsNull;
|
||||||
|
if (newNullFlag) ChartPlayer.etor.ContextCascadeUpdate(_var_value, PropSrc.Null);
|
||||||
|
else ChartPlayer.etor.ContextCascadeUpdate(_var_value, _vecsrcs[depth + 1]);
|
||||||
|
}
|
||||||
|
OnInput(id, p.Key, ft, tt, newNullFlag, depth + 1);
|
||||||
_etor.ContextCascadeDiscard();
|
_etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var pid = new ProxiedInputIdentifier { Source = id, Target = target };
|
var pid = new ProxiedInputIdentifier { Source = id, Target = target };
|
||||||
PropSrc fv, tv = _etor.ContextCascadeLookup(_var_value);
|
PropSrc fv, tv = _etor.ContextCascadeLookup(_var_value);
|
||||||
if (!_vecs.TryGetValue(pid, out fv)) fv = _nullsrc;
|
if (!_vecs.TryGetValue(pid, out fv)) fv = PropSrc.Null;
|
||||||
if (fv.Type != PdtInternalType.Null || tv.Type != PdtInternalType.Null) {
|
if (fv.Type != PdtInternalType.Null || tv.Type != PdtInternalType.Null) {
|
||||||
if (fv.Type == PdtInternalType.Null) _activeCounts[id.Source]++;
|
if (fv.Type == PdtInternalType.Null) _activeCounts[id.Source]++;
|
||||||
_etor.ContextCascadeInsert();
|
_etor.ContextCascadeInsert();
|
||||||
@@ -306,4 +353,12 @@ namespace Cryville.Crtr {
|
|||||||
return !lhs.Equals(rhs);
|
return !lhs.Equals(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class InputProxyException : Exception {
|
||||||
|
public InputProxyException() { }
|
||||||
|
public InputProxyException(string message) : base(message) { }
|
||||||
|
public InputProxyException(string message, Exception inner) : base(message, inner) { }
|
||||||
|
protected InputProxyException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ using Cryville.Common.Pdt;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Text.Formatting;
|
using System.Text.Formatting;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
@@ -134,7 +135,7 @@ namespace Cryville.Crtr {
|
|||||||
if (actlist.Count > 0) {
|
if (actlist.Count > 0) {
|
||||||
_numbuf3 = ft; _numsrc3.Invalidate(); _etor.ContextCascadeUpdate(_var_ft, _numsrc3);
|
_numbuf3 = ft; _numsrc3.Invalidate(); _etor.ContextCascadeUpdate(_var_ft, _numsrc3);
|
||||||
_numbuf4 = tt; _numsrc4.Invalidate(); _etor.ContextCascadeUpdate(_var_tt, _numsrc4);
|
_numbuf4 = tt; _numsrc4.Invalidate(); _etor.ContextCascadeUpdate(_var_tt, _numsrc4);
|
||||||
var index = 0;
|
int index = 0, iter = 0;
|
||||||
while (index >= 0 && index < actlist.Count) {
|
while (index >= 0 && index < actlist.Count) {
|
||||||
var ev = actlist[index];
|
var ev = actlist[index];
|
||||||
_numbuf1 = (float)ev.StartTime; _numsrc1.Invalidate(); _etor.ContextCascadeUpdate(_var_fn, _numsrc1);
|
_numbuf1 = (float)ev.StartTime; _numsrc1.Invalidate(); _etor.ContextCascadeUpdate(_var_fn, _numsrc1);
|
||||||
@@ -154,19 +155,21 @@ namespace Cryville.Crtr {
|
|||||||
if (index < 0) index = ~index;
|
if (index < 0) index = ~index;
|
||||||
}
|
}
|
||||||
else index++;
|
else index++;
|
||||||
|
if (iter++ >= 16) throw new JudgePropagationException();
|
||||||
}
|
}
|
||||||
else index++;
|
else index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Pass(JudgeEvent ev, float time, Identifier[] ids) {
|
bool Pass(JudgeEvent ev, float time, Identifier[] ids, int depth = 0) {
|
||||||
|
if (depth >= 16) throw new JudgePropagationException();
|
||||||
foreach (var i in ids) {
|
foreach (var i in ids) {
|
||||||
var def = _rs.judges[i];
|
var def = _rs.judges[i];
|
||||||
if (def.hit != null) _etor.Evaluate(_flagop, def.hit);
|
if (def.hit != null) _etor.Evaluate(_flagop, def.hit);
|
||||||
else _flag = true;
|
else _flag = true;
|
||||||
if (_flag) {
|
if (_flag) {
|
||||||
if (def.scores != null) UpdateScore(def.scores);
|
if (def.scores != null) UpdateScore(def.scores);
|
||||||
if (def.pass != null) Pass(ev, time, def.pass);
|
if (def.pass != null) Pass(ev, time, def.pass, depth + 1);
|
||||||
ev.Handler.ReportJudge(ev, time, i);
|
ev.Handler.ReportJudge(ev, time, i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -323,4 +326,12 @@ namespace Cryville.Crtr {
|
|||||||
public string format = "";
|
public string format = "";
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class JudgePropagationException : Exception {
|
||||||
|
public JudgePropagationException() : base("Judge propagation limit reached\nThe ruleset has invalid judge definitions") { }
|
||||||
|
public JudgePropagationException(string message) : base(message) { }
|
||||||
|
public JudgePropagationException(string message, Exception inner) : base(message, inner) { }
|
||||||
|
protected JudgePropagationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -360,8 +360,8 @@ namespace Cryville.Crtr {
|
|||||||
public abstract void LerpWith(Vector start, float lerpedTime, ref Vector result);
|
public abstract void LerpWith(Vector start, float lerpedTime, ref Vector result);
|
||||||
public abstract float DelerpWith(Vector start, Vector value);
|
public abstract float DelerpWith(Vector start, Vector value);
|
||||||
public abstract bool IsZero();
|
public abstract bool IsZero();
|
||||||
public override abstract string ToString();
|
public abstract override string ToString();
|
||||||
public abstract float[] ToArray();
|
public abstract unsafe void ToArray(float* arr);
|
||||||
|
|
||||||
public Vector Clone() {
|
public Vector Clone() {
|
||||||
return (Vector)MemberwiseClone();
|
return (Vector)MemberwiseClone();
|
||||||
@@ -442,8 +442,8 @@ namespace Cryville.Crtr {
|
|||||||
return Value.ToString(CultureInfo.InvariantCulture);
|
return Value.ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float[] ToArray() {
|
public override unsafe void ToArray(float* arr) {
|
||||||
return new float[] { Value };
|
arr[0] = Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,8 +504,8 @@ namespace Cryville.Crtr {
|
|||||||
return Value.ToString(CultureInfo.InvariantCulture);
|
return Value.ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float[] ToArray() {
|
public override unsafe void ToArray(float* arr) {
|
||||||
return new float[] { Value };
|
arr[0] = Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,8 +566,8 @@ namespace Cryville.Crtr {
|
|||||||
return Value.ToString(CultureInfo.InvariantCulture);
|
return Value.ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float[] ToArray() {
|
public override unsafe void ToArray(float* arr) {
|
||||||
return new float[] { Value };
|
arr[0] = Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,8 +610,8 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w = aw ? rw : (float?)null;
|
w = aw ? rw : null;
|
||||||
h = ah ? rh : (float?)null;
|
h = ah ? rh : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VecPtComp Parse(string s) {
|
public static VecPtComp Parse(string s) {
|
||||||
@@ -669,8 +669,9 @@ namespace Cryville.Crtr {
|
|||||||
return ToString(w, h);
|
return ToString(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float[] ToArray() {
|
public override unsafe void ToArray(float* arr) {
|
||||||
return new float[] { w.Value, h.Value };
|
arr[0] = w.Value;
|
||||||
|
arr[1] = h.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,8 +765,10 @@ namespace Cryville.Crtr {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float[] ToArray() {
|
public override unsafe void ToArray(float* arr) {
|
||||||
return new float[] { x.Value, y.Value, z.Value };
|
arr[0] = x.Value;
|
||||||
|
arr[1] = y.Value;
|
||||||
|
arr[2] = z.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,8 +848,11 @@ namespace Cryville.Crtr {
|
|||||||
return VecPtComp.ToString(xw, xh) + "," + VecPtComp.ToString(yw, yh);
|
return VecPtComp.ToString(xw, xh) + "," + VecPtComp.ToString(yw, yh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float[] ToArray() {
|
public override unsafe void ToArray(float* arr) {
|
||||||
return new float[] { xw.Value, xh.Value, yw.Value, yh.Value };
|
arr[0] = xw.Value;
|
||||||
|
arr[1] = xh.Value;
|
||||||
|
arr[2] = yw.Value;
|
||||||
|
arr[3] = yh.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,40 +942,31 @@ namespace Cryville.Crtr {
|
|||||||
return VecPtComp.ToString(xw, xh) + "," + VecPtComp.ToString(yw, yh) + "," + (z != null ? z.Value.ToString(CultureInfo.InvariantCulture) : "");
|
return VecPtComp.ToString(xw, xh) + "," + VecPtComp.ToString(yw, yh) + "," + (z != null ? z.Value.ToString(CultureInfo.InvariantCulture) : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float[] ToArray() {
|
public override unsafe void ToArray(float* arr) {
|
||||||
return new float[] { xw.Value, xh.Value, yw.Value, yh.Value, z.Value };
|
arr[0] = xw.Value;
|
||||||
|
arr[1] = xh.Value;
|
||||||
|
arr[2] = yw.Value;
|
||||||
|
arr[3] = yh.Value;
|
||||||
|
arr[4] = z.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class VectorSrc : PropSrc {
|
public unsafe class VectorSrc : PropSrc.FixedBuffer {
|
||||||
|
const int MAX_DIMENSION = 8;
|
||||||
protected readonly Func<Vector> _cb;
|
protected readonly Func<Vector> _cb;
|
||||||
public VectorSrc(Func<Vector> cb, int type) : base(type) { _cb = cb; }
|
public VectorSrc(Func<Vector> cb) : base(PdtInternalType.Vector, MAX_DIMENSION * sizeof(float) + sizeof(int)) {
|
||||||
public static VectorSrc Construct(Func<Vector> cb) {
|
_cb = cb;
|
||||||
if (cb().Dimension == 1) return new INumber(cb);
|
fixed (byte* rptr = buf) {
|
||||||
else return new IVector(cb);
|
var ptr = (float*)rptr;
|
||||||
}
|
*(int*)(ptr + MAX_DIMENSION) = PdtInternalType.Number;
|
||||||
class INumber : VectorSrc {
|
|
||||||
public INumber(Func<Vector> cb) : base(cb, PdtInternalType.Number) { }
|
|
||||||
protected override unsafe void InternalGet() {
|
|
||||||
var arr = _cb().ToArray();
|
|
||||||
buf = new byte[sizeof(float)];
|
|
||||||
fixed (byte* ptr = buf) {
|
|
||||||
*(float*)ptr = arr[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class IVector : VectorSrc {
|
protected override void InternalGet() {
|
||||||
public IVector(Func<Vector> cb) : base(cb, PdtInternalType.Vector) { }
|
var v = _cb();
|
||||||
protected override unsafe void InternalGet() {
|
if (v.Dimension > MAX_DIMENSION) throw new NotSupportedException("Vector dimension too large");
|
||||||
var arr = _cb().ToArray();
|
fixed (byte* rptr = buf) {
|
||||||
buf = new byte[sizeof(float) * arr.Length + sizeof(int)];
|
var ptr = (float*)rptr;
|
||||||
fixed (byte* rptr = buf) {
|
v.ToArray(ptr);
|
||||||
var ptr = (float*)rptr;
|
|
||||||
for (int i = 0; i < arr.Length; i++, ptr++) {
|
|
||||||
*ptr = arr[i];
|
|
||||||
}
|
|
||||||
*(int*)ptr = PdtInternalType.Number;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -977,7 +974,7 @@ namespace Cryville.Crtr {
|
|||||||
public class VectorOp : PropOp {
|
public class VectorOp : PropOp {
|
||||||
readonly Action<float[]> _cb;
|
readonly Action<float[]> _cb;
|
||||||
public VectorOp(Action<float[]> cb) { _cb = cb; }
|
public VectorOp(Action<float[]> cb) { _cb = cb; }
|
||||||
protected unsafe override void Execute() {
|
protected override unsafe void Execute() {
|
||||||
var op = GetOperand(0);
|
var op = GetOperand(0);
|
||||||
float[] values;
|
float[] values;
|
||||||
if (op.Type == PdtInternalType.Number) {
|
if (op.Type == PdtInternalType.Number) {
|
||||||
@@ -988,7 +985,7 @@ namespace Cryville.Crtr {
|
|||||||
op.GetArraySuffix(out type, out _);
|
op.GetArraySuffix(out type, out _);
|
||||||
if (type != PdtInternalType.Number)
|
if (type != PdtInternalType.Number)
|
||||||
throw new InvalidOperationException("Not a vector of numbers");
|
throw new InvalidOperationException("Not a vector of numbers");
|
||||||
values = new float[op.Length - sizeof(int)];
|
values = new float[(op.Length - sizeof(int)) / sizeof(float)];
|
||||||
fixed (float* ptr = values) {
|
fixed (float* ptr = values) {
|
||||||
op.CopyTo((byte*)ptr, 0, op.Length - sizeof(int));
|
op.CopyTo((byte*)ptr, 0, op.Length - sizeof(int));
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
public override void Init() {
|
public override void Init() {
|
||||||
base.Init();
|
base.Init();
|
||||||
sgos = gogroup.GetComponentsInChildren<SectionalGameObject>();
|
sgos = RootTransform.GetComponentsInChildren<SectionalGameObject>();
|
||||||
foreach (var judge in judges) judge.Value.InitPropSrcs();
|
foreach (var judge in judges) judge.Value.InitPropSrcs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ namespace Cryville.Crtr {
|
|||||||
protected override void StartGraphicalUpdate(ContainerState s) {
|
protected override void StartGraphicalUpdate(ContainerState s) {
|
||||||
base.StartGraphicalUpdate(s);
|
base.StartGraphicalUpdate(s);
|
||||||
TransformAwake(s);
|
TransformAwake(s);
|
||||||
if (gogroup) {
|
if (RootTransform) {
|
||||||
if (Event.IsLong) {
|
if (Event.IsLong) {
|
||||||
foreach (var i in sgos) {
|
foreach (var i in sgos) {
|
||||||
i.Reset();
|
i.Reset();
|
||||||
@@ -79,10 +79,10 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if UNITY_5_6_OR_NEWER
|
#if UNITY_5_6_OR_NEWER
|
||||||
gogroup.SetPositionAndRotation(Position, Rotation);
|
RootTransform.SetPositionAndRotation(Position, Rotation);
|
||||||
#else
|
#else
|
||||||
gogroup.position = Position;
|
RootTransform.position = Position;
|
||||||
gogroup.rotation = Rotation;
|
RootTransform.rotation = Rotation;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ namespace Cryville.Crtr {
|
|||||||
if (s.CloneType <= 2) {
|
if (s.CloneType <= 2) {
|
||||||
Position = GetFramePoint(s.Parent, s.Track);
|
Position = GetFramePoint(s.Parent, s.Track);
|
||||||
Rotation = GetFrameRotation(s.Parent, s.Track);
|
Rotation = GetFrameRotation(s.Parent, s.Track);
|
||||||
if (s.CloneType == 2 && gogroup && Event.IsLong) {
|
if (s.CloneType == 2 && RootTransform && Event.IsLong) {
|
||||||
foreach (var i in sgos)
|
foreach (var i in sgos)
|
||||||
i.AppendPoint(Position, Rotation);
|
i.AppendPoint(Position, Rotation);
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override void EndGraphicalUpdate(ContainerState s) {
|
protected override void EndGraphicalUpdate(ContainerState s) {
|
||||||
if (gogroup) {
|
if (RootTransform) {
|
||||||
foreach (var i in sgos) i.Seal();
|
foreach (var i in sgos) i.Seal();
|
||||||
}
|
}
|
||||||
base.EndGraphicalUpdate(s);
|
base.EndGraphicalUpdate(s);
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common;
|
||||||
|
using Cryville.Common.Math;
|
||||||
using Cryville.Common.Pdt;
|
using Cryville.Common.Pdt;
|
||||||
using Cryville.Crtr.Event;
|
using Cryville.Crtr.Event;
|
||||||
using System;
|
using System;
|
||||||
@@ -13,32 +14,40 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
static readonly byte[] _nullbuf = new byte[0];
|
static readonly byte[] _nullbuf = new byte[0];
|
||||||
readonly byte[] _numbuf = new byte[4];
|
readonly byte[] _numbuf = new byte[4];
|
||||||
|
readonly PropSrc _vecsrc;
|
||||||
|
Vector _vec;
|
||||||
static readonly int _var_w = IdentifierManager.SharedInstance.Request("w");
|
static readonly int _var_w = IdentifierManager.SharedInstance.Request("w");
|
||||||
static readonly int _var_h = IdentifierManager.SharedInstance.Request("h");
|
static readonly int _var_h = IdentifierManager.SharedInstance.Request("h");
|
||||||
static readonly int _var_current_time = IdentifierManager.SharedInstance.Request("current_time");
|
static readonly int _var_inf = IdentifierManager.SharedInstance.Request("inf");
|
||||||
static readonly int _var_true = IdentifierManager.SharedInstance.Request("true");
|
static readonly int _var_true = IdentifierManager.SharedInstance.Request("true");
|
||||||
static readonly int _var_false = IdentifierManager.SharedInstance.Request("false");
|
static readonly int _var_false = IdentifierManager.SharedInstance.Request("false");
|
||||||
static readonly int _var_null = IdentifierManager.SharedInstance.Request("null");
|
static readonly int _var_null = IdentifierManager.SharedInstance.Request("null");
|
||||||
|
static readonly int _var_current_time = IdentifierManager.SharedInstance.Request("current_time");
|
||||||
protected override void GetVariable(int name, bool forced, out int type, out byte[] value) {
|
protected override void GetVariable(int name, bool forced, out int type, out byte[] value) {
|
||||||
if (name == _var_w) { LoadNum(ChartPlayer.hitRect.width); type = PdtInternalType.Number; value = _numbuf; }
|
if (name == _var_w) { LoadNum(ChartPlayer.hitRect.width); type = PdtInternalType.Number; value = _numbuf; }
|
||||||
else if (name == _var_h) { LoadNum(ChartPlayer.hitRect.height); type = PdtInternalType.Number; value = _numbuf; }
|
else if (name == _var_h) { LoadNum(ChartPlayer.hitRect.height); type = PdtInternalType.Number; value = _numbuf; }
|
||||||
|
else if (name == _var_inf) { LoadNum(float.PositiveInfinity); type = PdtInternalType.Number; value = _numbuf; }
|
||||||
else if (name == _var_true) { LoadNum(1); type = PdtInternalType.Number; value = _numbuf; }
|
else if (name == _var_true) { LoadNum(1); type = PdtInternalType.Number; value = _numbuf; }
|
||||||
else if (name == _var_false) { LoadNum(0); type = PdtInternalType.Number; value = _numbuf; }
|
else if (name == _var_false) { LoadNum(0); type = PdtInternalType.Number; value = _numbuf; }
|
||||||
else if (name == _var_null) { LoadIdent(0); type = PdtInternalType.Undefined; value = _numbuf; }
|
else if (name == _var_null) { LoadIdent(0); type = PdtInternalType.Undefined; value = _numbuf; }
|
||||||
else {
|
else {
|
||||||
var id = new Identifier(name);
|
var id = new Identifier(name);
|
||||||
PropSrc prop;
|
PropSrc prop; SkinVariable variable;
|
||||||
if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) {
|
if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) {
|
||||||
prop.Get(out type, out value);
|
prop.Get(out type, out value);
|
||||||
}
|
}
|
||||||
else if (ContextState != null && ChartPlayer.motionRegistry.ContainsKey(id)) {
|
else if (ContextState != null && ChartPlayer.motionRegistry.ContainsKey(id)) {
|
||||||
var vec = ContextState.GetRawValue(id);
|
_vec = ContextState.GetRawValue(id);
|
||||||
VectorSrc.Construct(() => vec).Get(out type, out value);
|
_vecsrc.Invalidate();
|
||||||
|
_vecsrc.Get(out type, out value);
|
||||||
}
|
}
|
||||||
else if (ContextState != null && ContextState.Handler.PropSrcs.TryGetValue(name, out prop)) {
|
else if (ContextState != null && ContextState.Handler.PropSrcs.TryGetValue(name, out prop)) {
|
||||||
prop.Get(out type, out value);
|
prop.Get(out type, out value);
|
||||||
RevokePotentialConstant();
|
RevokePotentialConstant();
|
||||||
}
|
}
|
||||||
|
else if (ContextSkinContainer != null && ContextSkinContainer.Variables.TryGetValue(name, out variable)) {
|
||||||
|
variable.Src.Get(out type, out value);
|
||||||
|
}
|
||||||
else if (ContextJudge != null && ContextJudge.TryGetScoreSrc(name, out prop)) {
|
else if (ContextJudge != null && ContextJudge.TryGetScoreSrc(name, out prop)) {
|
||||||
prop.Get(out type, out value);
|
prop.Get(out type, out value);
|
||||||
RevokePotentialConstant();
|
RevokePotentialConstant();
|
||||||
@@ -98,11 +107,12 @@ namespace Cryville.Crtr {
|
|||||||
else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", IdentifierManager.SharedInstance.Retrieve(name)));
|
else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", IdentifierManager.SharedInstance.Retrieve(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChartEvent ContextEvent { private get; set; }
|
public ChartEvent ContextEvent { get; set; }
|
||||||
public ContainerState ContextState { private get; set; }
|
public ContainerState ContextState { get; set; }
|
||||||
public Transform ContextTransform { private get; set; }
|
public SkinContainer ContextSkinContainer { get; set; }
|
||||||
public Judge ContextJudge { private get; set; }
|
public Transform ContextTransform { get; set; }
|
||||||
public PropSrc ContextSelfValue { private get; set; }
|
public Judge ContextJudge { get; set; }
|
||||||
|
public PropSrc ContextSelfValue { get; set; }
|
||||||
|
|
||||||
readonly Stack<int> ContextCascadeBlocks = new Stack<int>();
|
readonly Stack<int> ContextCascadeBlocks = new Stack<int>();
|
||||||
public void ContextCascadeInsertBlock() {
|
public void ContextCascadeInsertBlock() {
|
||||||
@@ -140,6 +150,7 @@ namespace Cryville.Crtr {
|
|||||||
public PdtEvaluator() {
|
public PdtEvaluator() {
|
||||||
ContextCascadeBlocks.Push(0);
|
ContextCascadeBlocks.Push(0);
|
||||||
for (int i = 0; i < ContextCascade.Length; i++) ContextCascade[i] = new Dictionary<int, PropSrc>();
|
for (int i = 0; i < ContextCascade.Length; i++) ContextCascade[i] = new Dictionary<int, PropSrc>();
|
||||||
|
_vecsrc = new VectorSrc(() => _vec);
|
||||||
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("screen_edge"), new func_screen_edge(() => ContextTransform));
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("screen_edge"), new func_screen_edge(() => ContextTransform));
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("int"), new func_int(() => ContextSelfValue));
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("int"), new func_int(() => ContextSelfValue));
|
||||||
@@ -147,6 +158,12 @@ namespace Cryville.Crtr {
|
|||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue));
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue));
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("abs"), new func_abs(() => ContextSelfValue));
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("abs"), new func_abs(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("anim"), new func_anim(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("cubic_bezier"), new func_cubic_bezier(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease"), new func_cubic_bezier_fixed(0.25f, 0.1f, 0.25f, 1f, () => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in"), new func_cubic_bezier_fixed(0.42f, 0f, 1f, 1f, () => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_out"), new func_cubic_bezier_fixed(0f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in_out"), new func_cubic_bezier_fixed(0.42f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
||||||
|
|
||||||
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("attack_timing"), new func_attack_timing(cccb));
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("attack_timing"), new func_attack_timing(cccb));
|
||||||
@@ -263,6 +280,7 @@ namespace Cryville.Crtr {
|
|||||||
protected override void Execute() {
|
protected override void Execute() {
|
||||||
var o0 = GetOperand(0);
|
var o0 = GetOperand(0);
|
||||||
int type = o0.Type;
|
int type = o0.Type;
|
||||||
|
if (type == PdtInternalType.Error) throw new InvalidOperationException("Error");
|
||||||
int len = o0.Length;
|
int len = o0.Length;
|
||||||
bool blit = !IsBlittable(type);
|
bool blit = !IsBlittable(type);
|
||||||
for (var i = 1; i < LoadedOperandCount; i++) {
|
for (var i = 1; i < LoadedOperandCount; i++) {
|
||||||
@@ -486,6 +504,85 @@ namespace Cryville.Crtr {
|
|||||||
ret.SetNumber(Mathf.Abs(arg));
|
ret.SetNumber(Mathf.Abs(arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class func_anim : PdtOperator {
|
||||||
|
readonly Func<PropSrc> _ctxcb;
|
||||||
|
public func_anim(Func<PropSrc> ctxcb) : base(3) {
|
||||||
|
_ctxcb = ctxcb;
|
||||||
|
}
|
||||||
|
protected override unsafe void Execute() {
|
||||||
|
var op1 = GetOperand(0);
|
||||||
|
var op2 = GetOperand(1);
|
||||||
|
var dim1 = GetDimension(op1);
|
||||||
|
var dim2 = GetDimension(op2);
|
||||||
|
var dim0 = Math.Min(dim1, dim2);
|
||||||
|
float time;
|
||||||
|
switch (LoadedOperandCount) {
|
||||||
|
case 2: time = oputil.AsNumber(_ctxcb()); break;
|
||||||
|
case 3: time = GetOperand(2).AsNumber(); break;
|
||||||
|
default: throw new ArgumentException("Argument count not 2 or 3");
|
||||||
|
}
|
||||||
|
if (dim0 == 1) {
|
||||||
|
GetReturnFrame(PdtInternalType.Number, sizeof(float))
|
||||||
|
.SetNumber(op1.AsNumber() * (1 - time) + op2.AsNumber() * time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var ret = GetReturnFrame(PdtInternalType.Vector, dim0 * sizeof(float) + sizeof(int));
|
||||||
|
for (int i = 0; i < dim0 * sizeof(float); i += sizeof(float)) {
|
||||||
|
ret.SetNumber(op1.AsNumber(i) * (1 - time) + op2.AsNumber(i) * time, i);
|
||||||
|
}
|
||||||
|
ret.SetArraySuffix(PdtInternalType.Number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int GetDimension(PdtVariableMemory op) {
|
||||||
|
switch (op.Type) {
|
||||||
|
case PdtInternalType.Number: return 1;
|
||||||
|
case PdtInternalType.Vector:
|
||||||
|
int arrtype, _;
|
||||||
|
op.GetArraySuffix(out arrtype, out _);
|
||||||
|
if (arrtype != PdtInternalType.Number)
|
||||||
|
throw new ArgumentException("Not animatable");
|
||||||
|
return (op.Length - sizeof(int)) / sizeof(float);
|
||||||
|
default: throw new ArgumentException("Not animatable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class func_cubic_bezier : PdtOperator {
|
||||||
|
readonly Func<PropSrc> _ctxcb;
|
||||||
|
public func_cubic_bezier(Func<PropSrc> ctxcb) : base(5) {
|
||||||
|
_ctxcb = ctxcb;
|
||||||
|
}
|
||||||
|
protected override unsafe void Execute() {
|
||||||
|
float x1 = GetOperand(0).AsNumber(), y1 = GetOperand(1).AsNumber();
|
||||||
|
float x2 = GetOperand(2).AsNumber(), y2 = GetOperand(3).AsNumber();
|
||||||
|
float time;
|
||||||
|
switch (LoadedOperandCount) {
|
||||||
|
case 4: time = oputil.AsNumber(_ctxcb()); break;
|
||||||
|
case 5: time = GetOperand(4).AsNumber(); break;
|
||||||
|
default: throw new ArgumentException("Argument count not 4 or 5");
|
||||||
|
}
|
||||||
|
GetReturnFrame(PdtInternalType.Number, sizeof(float))
|
||||||
|
.SetNumber(CubicBezier.Evaluate(time, x1, y1, x2, y2, 1e-5f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class func_cubic_bezier_fixed : PdtOperator {
|
||||||
|
readonly float x1, y1, x2, y2;
|
||||||
|
readonly Func<PropSrc> _ctxcb;
|
||||||
|
public func_cubic_bezier_fixed(float x1, float y1, float x2, float y2, Func<PropSrc> ctxcb) : base(1) {
|
||||||
|
this.x1 = x1; this.y1 = y1;
|
||||||
|
this.x2 = x2; this.y2 = y2;
|
||||||
|
_ctxcb = ctxcb;
|
||||||
|
}
|
||||||
|
protected override void Execute() {
|
||||||
|
float time;
|
||||||
|
switch (LoadedOperandCount) {
|
||||||
|
case 0: time = oputil.AsNumber(_ctxcb()); break;
|
||||||
|
case 1: time = GetOperand(0).AsNumber(); break;
|
||||||
|
default: throw new ArgumentException("Argument count not 0 or 1");
|
||||||
|
}
|
||||||
|
GetReturnFrame(PdtInternalType.Number, sizeof(float))
|
||||||
|
.SetNumber(CubicBezier.Evaluate(time, x1, y1, x2, y2, 1e-5f));
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region Judge Functions
|
#region Judge Functions
|
||||||
static readonly int _var_fn = IdentifierManager.SharedInstance.Request("fn");
|
static readonly int _var_fn = IdentifierManager.SharedInstance.Request("fn");
|
||||||
@@ -554,12 +651,12 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
unsafe static class oputil {
|
static unsafe class oputil {
|
||||||
public static float AsNumber(PropSrc src) {
|
public static float AsNumber(PropSrc src) {
|
||||||
if (src == null) throw new ArgumentNullException("src");
|
if (src == null) throw new ArgumentNullException("src");
|
||||||
int type; byte[] value;
|
int type; byte[] value;
|
||||||
src.Get(out type, out value);
|
src.Get(out type, out value);
|
||||||
if (type != PdtInternalType.Number)
|
if (type != PdtInternalType.Number && type != PdtInternalType.Vector)
|
||||||
throw new ArgumentException("Not a number");
|
throw new ArgumentException("Not a number");
|
||||||
fixed (byte* ptr = value) {
|
fixed (byte* ptr = value) {
|
||||||
return *(float*)ptr;
|
return *(float*)ptr;
|
||||||
|
@@ -63,7 +63,7 @@ namespace Cryville.Crtr {
|
|||||||
public class StringArray : PropOp {
|
public class StringArray : PropOp {
|
||||||
readonly Action<string[]> _cb;
|
readonly Action<string[]> _cb;
|
||||||
public StringArray(Action<string[]> cb) { _cb = cb; }
|
public StringArray(Action<string[]> cb) { _cb = cb; }
|
||||||
protected unsafe override void Execute() {
|
protected override unsafe void Execute() {
|
||||||
var op = GetOperand(0);
|
var op = GetOperand(0);
|
||||||
int arrtype; int len;
|
int arrtype; int len;
|
||||||
op.GetArraySuffix(out arrtype, out len);
|
op.GetArraySuffix(out arrtype, out len);
|
||||||
@@ -100,22 +100,25 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class Enum<T> : PropOp {
|
public class Enum<T> : PropOp {
|
||||||
readonly static Dictionary<int, int> _cache = new Dictionary<int, int>();
|
static readonly Dictionary<int, int> _cache = new Dictionary<int, int>();
|
||||||
readonly Action<T> _cb;
|
readonly Action<T> _cb;
|
||||||
readonly Func<int, T> _caster;
|
readonly Func<int, T> _caster;
|
||||||
public Enum(Action<T> cb, Func<int, T> caster) {
|
static Enum() {
|
||||||
if (!typeof(T).IsEnum)
|
if (!typeof(T).IsEnum)
|
||||||
throw new ArgumentException("Type is not enum");
|
throw new ArgumentException("Type is not enum");
|
||||||
var names = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);
|
var names = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||||
for (int i = 0; i < names.Length; i++)
|
for (int i = 0; i < names.Length; i++)
|
||||||
_cache[IdentifierManager.SharedInstance.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null));
|
_cache[IdentifierManager.SharedInstance.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null));
|
||||||
|
|
||||||
|
}
|
||||||
|
public Enum(Action<T> cb, Func<int, T> caster) {
|
||||||
_cb = cb;
|
_cb = cb;
|
||||||
_caster = caster;
|
_caster = caster;
|
||||||
}
|
}
|
||||||
protected override void Execute() {
|
protected override void Execute() {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < LoadedOperandCount; i++)
|
for (int i = 0; i < LoadedOperandCount; i++)
|
||||||
result |= _cache[GetOperand(0).AsIdentifier()];
|
result |= _cache[GetOperand(i).AsIdentifier()];
|
||||||
_cb(_caster(result));
|
_cb(_caster(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -54,6 +54,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static readonly PropSrc Null = new Arbitrary(PdtInternalType.Null, new byte[0]);
|
||||||
public class String : PropSrc {
|
public class String : PropSrc {
|
||||||
readonly Func<string> _cb;
|
readonly Func<string> _cb;
|
||||||
public String(Func<string> cb) : base(PdtInternalType.String) { _cb = cb; }
|
public String(Func<string> cb) : base(PdtInternalType.String) { _cb = cb; }
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common;
|
||||||
|
using Cryville.Common.Collections.Generic;
|
||||||
using Cryville.Common.Pdt;
|
using Cryville.Common.Pdt;
|
||||||
using Cryville.Crtr.Browsing;
|
using Cryville.Crtr.Extension;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -64,9 +65,9 @@ namespace Cryville.Crtr {
|
|||||||
public class Constraint {
|
public class Constraint {
|
||||||
static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary();
|
static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary();
|
||||||
[ElementList]
|
[ElementList]
|
||||||
public Dictionary<RulesetSelectors, Constraint> Elements = new Dictionary<RulesetSelectors, Constraint>();
|
public PairList<RulesetSelectors, Constraint> Elements = new PairList<RulesetSelectors, Constraint>();
|
||||||
[PropertyList]
|
[PropertyList]
|
||||||
public Dictionary<PropertyKey, PdtExpression> Properties = new Dictionary<PropertyKey, PdtExpression>();
|
public PairList<PropertyKey, PdtExpression> Properties = new PairList<PropertyKey, PdtExpression>();
|
||||||
public void Optimize(PdtEvaluatorBase etor) {
|
public void Optimize(PdtEvaluatorBase etor) {
|
||||||
foreach (var e in Properties) {
|
foreach (var e in Properties) {
|
||||||
etor.Optimize(e.Value);
|
etor.Optimize(e.Value);
|
||||||
|
@@ -6,7 +6,7 @@ using RangeAttribute = Cryville.Common.ComponentModel.RangeAttribute;
|
|||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public class Settings {
|
public class Settings {
|
||||||
[Category("graphics")]
|
[Category("graphics")]
|
||||||
[LogarithmicScale][Step(0.5f)][Precision(1e-2)]
|
[LogarithmicScale][Range(0.01f, 20f)][Step(0.5f)][Precision(1e-2)]
|
||||||
public float BackwardClippingDistance {
|
public float BackwardClippingDistance {
|
||||||
get {
|
get {
|
||||||
return PlayerPrefs.GetFloat("BackwardClippingDistance", 0.2f);
|
return PlayerPrefs.GetFloat("BackwardClippingDistance", 0.2f);
|
||||||
@@ -62,8 +62,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Category("gameplay")]
|
[Category("gameplay")]
|
||||||
[Step(0.01f)]
|
[Step(0.01f)][Precision(1e-3)]
|
||||||
[Precision(1e-3)]
|
|
||||||
public float GraphicalOffset {
|
public float GraphicalOffset {
|
||||||
get {
|
get {
|
||||||
return PlayerPrefs.GetFloat("GraphicalOffset", 0);
|
return PlayerPrefs.GetFloat("GraphicalOffset", 0);
|
||||||
@@ -132,7 +131,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Category("graphics")]
|
[Category("graphics")]
|
||||||
[LogarithmicScale][Step(0.5f)][Precision(1e-1)]
|
[LogarithmicScale][Range(0.1f, 200f)][Step(0.5f)][Precision(1e-1)]
|
||||||
public float RenderDistance {
|
public float RenderDistance {
|
||||||
get {
|
get {
|
||||||
return PlayerPrefs.GetFloat("RenderDistance", 4);
|
return PlayerPrefs.GetFloat("RenderDistance", 4);
|
||||||
@@ -166,8 +165,8 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Browsable(false)]
|
[Browsable(false)]
|
||||||
[Category("gameplay")]
|
[Category("debug")]
|
||||||
[Description("(Not implemented yet)")]
|
[Range(0, float.PositiveInfinity)][Step(10f)][Precision(1e-1)]
|
||||||
public float StartOffset {
|
public float StartOffset {
|
||||||
get {
|
get {
|
||||||
return PlayerPrefs.GetFloat("StartOffset", 0);
|
return PlayerPrefs.GetFloat("StartOffset", 0);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common;
|
||||||
|
using Cryville.Common.Collections.Generic;
|
||||||
using Cryville.Common.Pdt;
|
using Cryville.Common.Pdt;
|
||||||
using Cryville.Crtr.Browsing;
|
using Cryville.Crtr.Extension;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -59,7 +60,10 @@ namespace Cryville.Crtr {
|
|||||||
foreach (var e in effects) {
|
foreach (var e in effects) {
|
||||||
var effect = e.Value;
|
var effect = e.Value;
|
||||||
etor.ContextCascadeInsert();
|
etor.ContextCascadeInsert();
|
||||||
etor.Optimize(effect.duration);
|
etor.ContextCascadeUpdate(EffectInstance._VAR_EFFECT_INDEX, PropSrc.Error);
|
||||||
|
foreach(var s in effect.states) {
|
||||||
|
etor.Optimize(s.Value.duration);
|
||||||
|
}
|
||||||
effect.elements.Optimize(etor);
|
effect.elements.Optimize(etor);
|
||||||
etor.ContextCascadeDiscard();
|
etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
@@ -69,12 +73,12 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
public class SkinElement {
|
public class SkinElement {
|
||||||
[ElementList]
|
[ElementList]
|
||||||
public Dictionary<SkinSelectors, SkinElement> elements
|
public PairList<SkinSelectors, SkinElement> elements
|
||||||
= new Dictionary<SkinSelectors, SkinElement>();
|
= new PairList<SkinSelectors, SkinElement>();
|
||||||
|
|
||||||
[PropertyList]
|
[PropertyList]
|
||||||
public Dictionary<SkinPropertyKey, PdtExpression> properties
|
public PairList<SkinPropertyKey, PdtExpression> properties
|
||||||
= new Dictionary<SkinPropertyKey, PdtExpression>();
|
= new PairList<SkinPropertyKey, PdtExpression>();
|
||||||
|
|
||||||
public bool IsDynamic {
|
public bool IsDynamic {
|
||||||
get;
|
get;
|
||||||
@@ -98,18 +102,38 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class EffectDefinition {
|
public class EffectDefinition {
|
||||||
public PdtExpression duration;
|
static Identifier _ident_init = new Identifier("init");
|
||||||
|
#pragma warning disable IDE1006
|
||||||
|
public PdtExpression duration {
|
||||||
|
set {
|
||||||
|
EffectState s;
|
||||||
|
if (!states.TryGetValue(_ident_init, out s))
|
||||||
|
throw new InvalidOperationException("Cannot set duration and states at the same time");
|
||||||
|
s.duration = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma warning restore IDE1006
|
||||||
|
public Identifier init = _ident_init;
|
||||||
|
public Dictionary<Identifier, EffectState> states = new Dictionary<Identifier, EffectState> {
|
||||||
|
{ _ident_init, new EffectState() { rewind = _ident_init } }
|
||||||
|
};
|
||||||
public SkinElement elements;
|
public SkinElement elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class EffectState {
|
||||||
|
public PdtExpression duration;
|
||||||
|
public Identifier rewind;
|
||||||
|
public Identifier next;
|
||||||
|
}
|
||||||
|
|
||||||
public class AnimationSpan {
|
public class AnimationSpan {
|
||||||
[ElementList]
|
[ElementList]
|
||||||
public Dictionary<Clip, AnimationSpan> spans
|
public PairList<Clip, AnimationSpan> spans
|
||||||
= new Dictionary<Clip, AnimationSpan>();
|
= new PairList<Clip, AnimationSpan>();
|
||||||
|
|
||||||
[PropertyList]
|
[PropertyList]
|
||||||
public Dictionary<SkinPropertyKey, PdtExpression> properties
|
public PairList<SkinPropertyKey, PdtExpression> properties
|
||||||
= new Dictionary<SkinPropertyKey, PdtExpression>();
|
= new PairList<SkinPropertyKey, PdtExpression>();
|
||||||
|
|
||||||
public void Optimize(PdtEvaluator etor) {
|
public void Optimize(PdtEvaluator etor) {
|
||||||
foreach (var p in properties) {
|
foreach (var p in properties) {
|
||||||
|
@@ -1,13 +1,16 @@
|
|||||||
using Cryville.Common.Pdt;
|
using Cryville.Common.Pdt;
|
||||||
using Cryville.Crtr.Event;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Profiling;
|
using UnityEngine.Profiling;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public class SkinContainer {
|
public class SkinContainer {
|
||||||
|
readonly ISkinnableGroup _group;
|
||||||
readonly SkinElement _rootElement;
|
readonly SkinElement _rootElement;
|
||||||
readonly DynamicStack[] _stacks = new DynamicStack[2];
|
readonly DynamicStack[] _stacks = new DynamicStack[2];
|
||||||
|
readonly HashSet<SkinPropertyKey> _once = new HashSet<SkinPropertyKey>();
|
||||||
|
public readonly Dictionary<int, SkinVariable> Variables = new Dictionary<int, SkinVariable>();
|
||||||
|
|
||||||
class DynamicStack {
|
class DynamicStack {
|
||||||
public readonly List<DynamicProperty> Properties = new List<DynamicProperty>();
|
public readonly List<DynamicProperty> Properties = new List<DynamicProperty>();
|
||||||
public readonly List<DynamicElement> Elements = new List<DynamicElement>();
|
public readonly List<DynamicElement> Elements = new List<DynamicElement>();
|
||||||
@@ -26,21 +29,26 @@ namespace Cryville.Crtr {
|
|||||||
public SkinSelectors Selectors { get; set; }
|
public SkinSelectors Selectors { get; set; }
|
||||||
public SkinElement Element { get; set; }
|
public SkinElement Element { get; set; }
|
||||||
}
|
}
|
||||||
public SkinContainer(SkinElement rootElement) {
|
public SkinContainer(ISkinnableGroup group, SkinElement rootElement) {
|
||||||
|
_group = group;
|
||||||
_rootElement = rootElement;
|
_rootElement = rootElement;
|
||||||
for (int i = 0; i < _stacks.Length; i++) _stacks[i] = new DynamicStack();
|
for (int i = 0; i < _stacks.Length; i++) _stacks[i] = new DynamicStack();
|
||||||
|
_rtimeSrc = new PropSrc.Float(() => _rtime);
|
||||||
}
|
}
|
||||||
public void MatchStatic(ISkinnableGroup group) {
|
public void MatchStatic() {
|
||||||
var stack = _stacks[0];
|
var stack = _stacks[0];
|
||||||
stack.Clear();
|
stack.Clear();
|
||||||
MatchStatic(_rootElement, group, stack, new RuntimeSkinContext(group.SkinContext));
|
MatchStatic(_rootElement, stack, new RuntimeSkinContext(_group.SkinContext));
|
||||||
}
|
}
|
||||||
void MatchStatic(SkinElement rel, ISkinnableGroup group, DynamicStack stack, RuntimeSkinContext ctx) {
|
void MatchStatic(SkinElement rel, DynamicStack stack, RuntimeSkinContext ctx) {
|
||||||
var rc = ctx.ReadContext;
|
var rc = ctx.ReadContext;
|
||||||
ChartPlayer.etor.ContextTransform = rc.Transform;
|
ChartPlayer.etor.ContextTransform = rc.Transform;
|
||||||
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeInsert(rc.PropSrcs);
|
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeInsert(rc.PropSrcs);
|
||||||
foreach (var p in rel.properties) {
|
foreach (var p in rel.properties) {
|
||||||
p.Key.ExecuteStatic(group, ctx, p.Value);
|
try {
|
||||||
|
p.Key.ExecuteStatic(_group, ctx, p.Value, Variables);
|
||||||
|
}
|
||||||
|
catch (EvaluationFailureException) { }
|
||||||
if (p.Key.IsValueRequired && !p.Value.IsConstant) stack.Properties.Add(
|
if (p.Key.IsValueRequired && !p.Value.IsConstant) stack.Properties.Add(
|
||||||
new DynamicProperty { Context = ctx, Key = p.Key, Value = p.Value }
|
new DynamicProperty { Context = ctx, Key = p.Key, Value = p.Value }
|
||||||
);
|
);
|
||||||
@@ -48,13 +56,13 @@ namespace Cryville.Crtr {
|
|||||||
ChartPlayer.etor.ContextTransform = null;
|
ChartPlayer.etor.ContextTransform = null;
|
||||||
foreach (var e in rel.elements) {
|
foreach (var e in rel.elements) {
|
||||||
try {
|
try {
|
||||||
var nctxs = e.Key.MatchStatic(group, rc);
|
var nctxs = e.Key.MatchStatic(_group, rc);
|
||||||
if (nctxs != null) {
|
if (nctxs != null) {
|
||||||
var roflag = e.Key.annotations.Contains("if");
|
var roflag = e.Key.annotations.Contains("if");
|
||||||
var woflag = e.Key.annotations.Contains("then");
|
var woflag = e.Key.annotations.Contains("then");
|
||||||
foreach (var nctx in nctxs) {
|
foreach (var nctx in nctxs) {
|
||||||
var nrctx = new RuntimeSkinContext(nctx, ctx, roflag, woflag);
|
var nrctx = new RuntimeSkinContext(nctx, ctx, roflag, woflag);
|
||||||
MatchStatic(e.Value, group, stack, nrctx);
|
MatchStatic(e.Value, stack, nrctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,15 +74,19 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
|
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
public void MatchDynamic(ISkinnableGroup group, int dl) {
|
public void MatchDynamic(int dl, bool recursive = false) {
|
||||||
var stack = _stacks[dl];
|
var stack = _stacks[dl];
|
||||||
if (stack.Properties.Count == 0 && stack.Elements.Count == 0) return;
|
if (stack.Properties.Count == 0 && stack.Elements.Count == 0) return;
|
||||||
var nstack = dl + 1 < _stacks.Length ? _stacks[dl + 1] : null;
|
var nstack = dl + 1 < _stacks.Length ? _stacks[dl + 1] : null;
|
||||||
if (nstack != null) nstack.Clear();
|
if (nstack != null) nstack.Clear();
|
||||||
Profiler.BeginSample("SkinContainer.MatchDynamic");
|
Profiler.BeginSample("SkinContainer.MatchDynamic");
|
||||||
|
if (!recursive) ChartPlayer.etor.ContextSkinContainer = this;
|
||||||
for (int i = 0; i < stack.Properties.Count; i++) {
|
for (int i = 0; i < stack.Properties.Count; i++) {
|
||||||
DynamicProperty p = stack.Properties[i];
|
DynamicProperty p = stack.Properties[i];
|
||||||
p.Key.ExecuteDynamic(group, p.Context, p.Value, dl);
|
p.Key.ExecuteDynamic(_group, p.Context, p.Value, Variables, dl);
|
||||||
|
if (p.Key.annotations.Contains("once")) {
|
||||||
|
stack.Properties.RemoveAt(i--);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < stack.Elements.Count; i++) {
|
for (int i = 0; i < stack.Elements.Count; i++) {
|
||||||
DynamicElement e = stack.Elements[i];
|
DynamicElement e = stack.Elements[i];
|
||||||
@@ -82,14 +94,14 @@ namespace Cryville.Crtr {
|
|||||||
if (psrcs != null) ChartPlayer.etor.ContextCascadeInsert(psrcs);
|
if (psrcs != null) ChartPlayer.etor.ContextCascadeInsert(psrcs);
|
||||||
SkinContext nctx = null;
|
SkinContext nctx = null;
|
||||||
try {
|
try {
|
||||||
nctx = e.Selectors.MatchDynamic(group, e.Context.ReadContext);
|
nctx = e.Selectors.MatchDynamic(_group, e.Context.ReadContext);
|
||||||
}
|
}
|
||||||
catch (SelectorNotAvailableException) {
|
catch (SelectorNotAvailableException) {
|
||||||
if (nstack == null) throw;
|
if (nstack == null) throw;
|
||||||
nstack.Elements.Add(e);
|
nstack.Elements.Add(e);
|
||||||
}
|
}
|
||||||
if (nctx != null) {
|
if (nctx != null) {
|
||||||
MatchDynamic(e.Element, group, dl, nstack, new RuntimeSkinContext(
|
MatchDynamic(e.Element, dl, nstack, new RuntimeSkinContext(
|
||||||
nctx, e.Context, e.Selectors.annotations.Contains("if"), e.Selectors.annotations.Contains("then")
|
nctx, e.Context, e.Selectors.annotations.Contains("if"), e.Selectors.annotations.Contains("then")
|
||||||
));
|
));
|
||||||
if (e.Selectors.annotations.Contains("once")) {
|
if (e.Selectors.annotations.Contains("once")) {
|
||||||
@@ -98,20 +110,28 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
if (psrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
|
if (psrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
|
if (!recursive) ChartPlayer.etor.ContextSkinContainer = null;
|
||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
}
|
}
|
||||||
void MatchDynamic(SkinElement rel, ISkinnableGroup group, int dl, DynamicStack stack, RuntimeSkinContext ctx) {
|
void MatchDynamic(SkinElement rel, int dl, DynamicStack stack, RuntimeSkinContext ctx) {
|
||||||
var rc = ctx.ReadContext;
|
var rc = ctx.ReadContext;
|
||||||
ChartPlayer.etor.ContextTransform = rc.Transform;
|
ChartPlayer.etor.ContextTransform = rc.Transform;
|
||||||
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeInsert(rc.PropSrcs);
|
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeInsert(rc.PropSrcs);
|
||||||
foreach (var p in rel.properties) {
|
foreach (var p in rel.properties) {
|
||||||
p.Key.ExecuteDynamic(group, ctx, p.Value, dl);
|
if (p.Key.annotations.Contains("once")) {
|
||||||
|
if (_once.Contains(p.Key)) continue;
|
||||||
|
p.Key.ExecuteDynamic(_group, ctx, p.Value, Variables, dl);
|
||||||
|
_once.Add(p.Key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.Key.ExecuteDynamic(_group, ctx, p.Value, Variables, dl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ChartPlayer.etor.ContextTransform = null;
|
ChartPlayer.etor.ContextTransform = null;
|
||||||
foreach (var e in rel.elements) {
|
foreach (var e in rel.elements) {
|
||||||
if (e.Key.IsUpdatable(group, dl)) {
|
if (e.Key.IsUpdatable(_group, dl)) {
|
||||||
SkinContext nctx = e.Key.MatchDynamic(group, rc);
|
SkinContext nctx = e.Key.MatchDynamic(_group, rc);
|
||||||
if (nctx != null) MatchDynamic(e.Value, group, dl, stack, new RuntimeSkinContext(
|
if (nctx != null) MatchDynamic(e.Value, dl, stack, new RuntimeSkinContext(
|
||||||
nctx, ctx, e.Key.annotations.Contains("if"), e.Key.annotations.Contains("then")
|
nctx, ctx, e.Key.annotations.Contains("if"), e.Key.annotations.Contains("then")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -124,6 +144,26 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
|
if (rc.PropSrcs != null) ChartPlayer.etor.ContextCascadeDiscard();
|
||||||
}
|
}
|
||||||
|
float _rtime;
|
||||||
|
readonly PropSrc _rtimeSrc;
|
||||||
|
public void MatchAnimation(AnimationSpan span, float rtime, RuntimeSkinContext ctx) {
|
||||||
|
ChartPlayer.etor.ContextSkinContainer = this;
|
||||||
|
ChartPlayer.etor.ContextSelfValue = _rtimeSrc;
|
||||||
|
MatchAnimationInternal(span, rtime, ctx);
|
||||||
|
ChartPlayer.etor.ContextSelfValue = null;
|
||||||
|
ChartPlayer.etor.ContextSkinContainer = null;
|
||||||
|
}
|
||||||
|
void MatchAnimationInternal(AnimationSpan span, float rtime, RuntimeSkinContext ctx) {
|
||||||
|
_rtime = rtime;
|
||||||
|
_rtimeSrc.Invalidate();
|
||||||
|
foreach (var p in span.properties) {
|
||||||
|
p.Key.ExecuteDynamic(_group, ctx, p.Value, Variables, 0);
|
||||||
|
}
|
||||||
|
foreach (var s in span.spans) {
|
||||||
|
if (rtime < s.Key.Behind || rtime >= s.Key.Ahead) continue;
|
||||||
|
MatchAnimationInternal(s.Value, (rtime - s.Key.Behind) / (s.Key.Ahead - s.Key.Behind), ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public class SkinContext {
|
public class SkinContext {
|
||||||
public Transform Transform { get; private set; }
|
public Transform Transform { get; private set; }
|
||||||
@@ -162,9 +202,22 @@ namespace Cryville.Crtr {
|
|||||||
public interface ISkinnableGroup {
|
public interface ISkinnableGroup {
|
||||||
string TypeName { get; }
|
string TypeName { get; }
|
||||||
SkinContext SkinContext { get; }
|
SkinContext SkinContext { get; }
|
||||||
Anchor OpenedAnchor { get; }
|
int OpenedAnchorName { get; }
|
||||||
bool TryGetAnchorsByName(int name, out IReadOnlyCollection<Anchor> result);
|
bool TryGetAnchorsByName(int name, out IReadOnlyCollection<Anchor> result);
|
||||||
void RegisterAnchor(int name);
|
void RegisterAnchor(int name);
|
||||||
void PushAnchorEvent(double time, int name);
|
void PushAnchorEvent(double time, int name);
|
||||||
}
|
}
|
||||||
|
public class SkinVariable {
|
||||||
|
float _value;
|
||||||
|
public PropOp Op { get; private set; }
|
||||||
|
public PropSrc Src { get; private set; }
|
||||||
|
public SkinVariable() {
|
||||||
|
Op = new PropOp.Float(Set);
|
||||||
|
Src = new PropSrc.Float(() => _value);
|
||||||
|
}
|
||||||
|
void Set(float value) {
|
||||||
|
_value = value;
|
||||||
|
Src.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
using Cryville.Common;
|
using Cryville.Common.Pdt;
|
||||||
using Cryville.Common.Pdt;
|
|
||||||
using Cryville.Crtr.Components;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -58,41 +56,7 @@ namespace Cryville.Crtr {
|
|||||||
case ';':
|
case ';':
|
||||||
case ':':
|
case ':':
|
||||||
if (invalidKeyFlag) throw new FormatException("Invalid key format");
|
if (invalidKeyFlag) throw new FormatException("Invalid key format");
|
||||||
if (a.Contains("has")) {
|
return SkinPropertyKey.Construct(a, k, compKeyFlag);
|
||||||
if (k.Count != 1) throw new FormatException("Invalid anchor name");
|
|
||||||
return new SkinPropertyKey.CreateAnchor {
|
|
||||||
Name = IdentifierManager.SharedInstance.Request(k[0])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (a.Contains("at")) {
|
|
||||||
if (k.Count != 1) throw new FormatException("Invalid anchor name");
|
|
||||||
return new SkinPropertyKey.SetAnchor {
|
|
||||||
Name = IdentifierManager.SharedInstance.Request(k[0])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (a.Contains("emit")) {
|
|
||||||
if (k.Count != 1) throw new FormatException("Invalid effect name");
|
|
||||||
return new SkinPropertyKey.EmitEffect {
|
|
||||||
Name = IdentifierManager.SharedInstance.Request(k[0])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
switch (k.Count) {
|
|
||||||
case 1:
|
|
||||||
if (compKeyFlag) return new SkinPropertyKey.CreateComponent {
|
|
||||||
Component = GetComponentByName(k[0])
|
|
||||||
};
|
|
||||||
else return new SkinPropertyKey.SetProperty {
|
|
||||||
Component = typeof(TransformInterface),
|
|
||||||
Name = IdentifierManager.SharedInstance.Request(k[0])
|
|
||||||
};
|
|
||||||
case 2:
|
|
||||||
return new SkinPropertyKey.SetProperty {
|
|
||||||
Component = GetComponentByName(k[0]),
|
|
||||||
Name = IdentifierManager.SharedInstance.Request(k[1])
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
throw new FormatException("Unknown error"); // Unreachable
|
|
||||||
}
|
|
||||||
case '{':
|
case '{':
|
||||||
return new SkinSelectors(s, a);
|
return new SkinSelectors(s, a);
|
||||||
case '}':
|
case '}':
|
||||||
@@ -127,7 +91,7 @@ namespace Cryville.Crtr {
|
|||||||
if (cc != '{') throw new FormatException("Invalid span format");
|
if (cc != '{') throw new FormatException("Invalid span format");
|
||||||
return new Clip(start, end);
|
return new Clip(start, end);
|
||||||
}
|
}
|
||||||
k.Clear();
|
a.Clear(); k.Clear();
|
||||||
while (true) {
|
while (true) {
|
||||||
int pp = Position;
|
int pp = Position;
|
||||||
switch (cc) {
|
switch (cc) {
|
||||||
@@ -139,20 +103,7 @@ namespace Cryville.Crtr {
|
|||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
case ':':
|
case ':':
|
||||||
switch (k.Count) {
|
return SkinPropertyKey.Construct(a, k, false);
|
||||||
case 1:
|
|
||||||
return new SkinPropertyKey.SetProperty {
|
|
||||||
Component = typeof(TransformInterface),
|
|
||||||
Name = IdentifierManager.SharedInstance.Request(k[0])
|
|
||||||
};
|
|
||||||
case 2:
|
|
||||||
return new SkinPropertyKey.SetProperty {
|
|
||||||
Component = GetComponentByName(k[0]),
|
|
||||||
Name = IdentifierManager.SharedInstance.Request(k[1])
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
throw new FormatException("Unknown error"); // Unreachable
|
|
||||||
}
|
|
||||||
case '{':
|
case '{':
|
||||||
throw new FormatException("Invalid token");
|
throw new FormatException("Invalid token");
|
||||||
case '}':
|
case '}':
|
||||||
@@ -167,10 +118,5 @@ namespace Cryville.Crtr {
|
|||||||
if (Position == pp) throw new FormatException("Invalid selector or key format");
|
if (Position == pp) throw new FormatException("Invalid selector or key format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static Type GetComponentByName(string name) {
|
|
||||||
Type result;
|
|
||||||
if (GenericResources.Components.TryGetValue(name, out result)) return result;
|
|
||||||
throw new ArgumentException(string.Format("Component type \"{0}\" not found", name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,38 +2,87 @@
|
|||||||
using Cryville.Common.Pdt;
|
using Cryville.Common.Pdt;
|
||||||
using Cryville.Crtr.Components;
|
using Cryville.Crtr.Components;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public abstract class SkinPropertyKey {
|
public abstract class SkinPropertyKey {
|
||||||
|
public static SkinPropertyKey Construct(HashSet<string> a, IReadOnlyList<string> k, bool compKeyFlag) {
|
||||||
|
if (a.Remove("has")) {
|
||||||
|
if (k.Count != 1) throw new FormatException("Invalid anchor name");
|
||||||
|
return new CreateAnchor(a, IdentifierManager.SharedInstance.Request(k[0]));
|
||||||
|
}
|
||||||
|
else if (a.Remove("at")) {
|
||||||
|
if (k.Count != 1) throw new FormatException("Invalid anchor name");
|
||||||
|
return new SetAnchor(a, IdentifierManager.SharedInstance.Request(k[0]));
|
||||||
|
}
|
||||||
|
else if (a.Remove("emit")) {
|
||||||
|
if (k.Count != 1) throw new FormatException("Invalid effect name");
|
||||||
|
return new EmitEffect(a, IdentifierManager.SharedInstance.Request(k[0]));
|
||||||
|
}
|
||||||
|
else if (a.Remove("emit_self")) {
|
||||||
|
if (k.Count != 1) throw new FormatException("Invalid effect name");
|
||||||
|
return new EmitEffect(a, IdentifierManager.SharedInstance.Request(k[0]), true);
|
||||||
|
}
|
||||||
|
else if (a.Remove("var")) {
|
||||||
|
if (k.Count != 1) throw new FormatException("Invalid variable name");
|
||||||
|
return new SetVariable(a, IdentifierManager.SharedInstance.Request(k[0]));
|
||||||
|
}
|
||||||
|
switch (k.Count) {
|
||||||
|
case 1:
|
||||||
|
if (compKeyFlag) return new CreateComponent(a, GetComponentByName(k[0]));
|
||||||
|
else return new SetProperty(a, typeof(TransformInterface), IdentifierManager.SharedInstance.Request(k[0]));
|
||||||
|
case 2:
|
||||||
|
return new SetProperty(a, GetComponentByName(k[0]), IdentifierManager.SharedInstance.Request(k[1]));
|
||||||
|
default:
|
||||||
|
throw new FormatException("Unknown error");
|
||||||
|
}
|
||||||
|
static Type GetComponentByName(string name) {
|
||||||
|
Type result;
|
||||||
|
if (GenericResources.Components.TryGetValue(name, out result)) return result;
|
||||||
|
throw new ArgumentException(string.Format("Component type \"{0}\" not found", name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public readonly HashSet<string> annotations;
|
||||||
|
public SkinPropertyKey(IEnumerable<string> a) {
|
||||||
|
annotations = a.ToHashSet();
|
||||||
|
}
|
||||||
public abstract override string ToString();
|
public abstract override string ToString();
|
||||||
public abstract bool IsValueRequired { get; }
|
public abstract bool IsValueRequired { get; }
|
||||||
public abstract void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp);
|
public abstract void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars);
|
||||||
public abstract void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl);
|
public abstract void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars, int dl);
|
||||||
public class CreateComponent : SkinPropertyKey {
|
public class CreateComponent : SkinPropertyKey {
|
||||||
public Type Component { get; set; }
|
public Type Component { get; private set; }
|
||||||
|
public CreateComponent(IEnumerable<string> a, Type component) : base(a) {
|
||||||
|
Component = component;
|
||||||
|
}
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("*{0}", Component.Name);
|
return string.Format("*{0}", Component.Name);
|
||||||
}
|
}
|
||||||
public override bool IsValueRequired { get { return false; } }
|
public override bool IsValueRequired { get { return false; } }
|
||||||
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) {
|
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars) {
|
||||||
ctx.WriteTransform.gameObject.AddComponent(Component);
|
ctx.WriteTransform.gameObject.AddComponent(Component);
|
||||||
}
|
}
|
||||||
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) {
|
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars, int dl) {
|
||||||
throw new InvalidOperationException("Component creation in dynamic context is not allowed");
|
throw new InvalidOperationException("Component creation in dynamic context is not allowed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class SetProperty : SkinPropertyKey {
|
public class SetProperty : SkinPropertyKey {
|
||||||
public Type Component { get; set; }
|
public Type Component { get; private set; }
|
||||||
public int Name { get; set; }
|
public int Name { get; private set; }
|
||||||
|
public SetProperty(IEnumerable<string> a, Type component, int name) : base(a) {
|
||||||
|
Component = component;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("{0}.{1}", Component.Name, IdentifierManager.SharedInstance.Retrieve(Name));
|
return string.Format("{0}.{1}", Component.Name, IdentifierManager.SharedInstance.Retrieve(Name));
|
||||||
}
|
}
|
||||||
public override bool IsValueRequired { get { return true; } }
|
public override bool IsValueRequired { get { return true; } }
|
||||||
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) {
|
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars) {
|
||||||
Execute(ctx, GetPropOp(ctx.WriteTransform).Operator, exp);
|
Execute(ctx, GetPropOp(ctx.WriteTransform).Operator, exp);
|
||||||
}
|
}
|
||||||
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) {
|
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars, int dl) {
|
||||||
var prop = GetPropOp(ctx.WriteTransform);
|
var prop = GetPropOp(ctx.WriteTransform);
|
||||||
if (dl > prop.UpdateDynamicLevel) return;
|
if (dl > prop.UpdateDynamicLevel) return;
|
||||||
Execute(ctx, prop.Operator, exp);
|
Execute(ctx, prop.Operator, exp);
|
||||||
@@ -61,33 +110,37 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class CreateAnchor : SkinPropertyKey {
|
public class CreateAnchor : SkinPropertyKey {
|
||||||
public int Name { get; set; }
|
public int Name { get; private set; }
|
||||||
|
public CreateAnchor(IEnumerable<string> a, int name) : base(a) {
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("@has {0}", IdentifierManager.SharedInstance.Retrieve(Name));
|
return string.Format("@has {0}", IdentifierManager.SharedInstance.Retrieve(Name));
|
||||||
}
|
}
|
||||||
public override bool IsValueRequired { get { return false; } }
|
public override bool IsValueRequired { get { return false; } }
|
||||||
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) {
|
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars) {
|
||||||
group.RegisterAnchor(Name);
|
group.RegisterAnchor(Name);
|
||||||
}
|
}
|
||||||
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) {
|
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars, int dl) {
|
||||||
throw new InvalidOperationException("Anchor creation in dynamic context is not allowed");
|
throw new InvalidOperationException("Anchor creation in dynamic context is not allowed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class SetAnchor : SkinPropertyKey {
|
public class SetAnchor : SkinPropertyKey {
|
||||||
public int Name { get; set; }
|
public int Name { get; private set; }
|
||||||
public SetAnchor() {
|
public SetAnchor(IEnumerable<string> a, int name) : base(a) {
|
||||||
|
Name = name;
|
||||||
_timeOp = new PropOp.Float(v => _time = v);
|
_timeOp = new PropOp.Float(v => _time = v);
|
||||||
}
|
}
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("@at {0}", IdentifierManager.SharedInstance.Retrieve(Name));
|
return string.Format("@at {0}", IdentifierManager.SharedInstance.Retrieve(Name));
|
||||||
}
|
}
|
||||||
public override bool IsValueRequired { get { return true; } }
|
public override bool IsValueRequired { get { return true; } }
|
||||||
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) {
|
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars) {
|
||||||
throw new InvalidOperationException("Setting anchor in static context is not allowed");
|
throw new InvalidOperationException("Setting anchor in static context is not allowed");
|
||||||
}
|
}
|
||||||
float _time;
|
float _time;
|
||||||
readonly PropOp _timeOp;
|
readonly PropOp _timeOp;
|
||||||
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) {
|
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars, int dl) {
|
||||||
if (dl > 0) return;
|
if (dl > 0) return;
|
||||||
var psrcs = ctx.ReadContext.PropSrcs;
|
var psrcs = ctx.ReadContext.PropSrcs;
|
||||||
if (psrcs != null) ChartPlayer.etor.ContextCascadeInsert(psrcs);
|
if (psrcs != null) ChartPlayer.etor.ContextCascadeInsert(psrcs);
|
||||||
@@ -97,22 +150,48 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public class EmitEffect : SkinPropertyKey {
|
public class EmitEffect : SkinPropertyKey {
|
||||||
public int Name { get; set; }
|
public int Name { get; private set; }
|
||||||
public EmitEffect() {
|
public bool IsSelf { get; private set; }
|
||||||
|
public EmitEffect(IEnumerable<string> a, int name, bool isSelf = false) : base(a) {
|
||||||
|
Name = name;
|
||||||
|
IsSelf = isSelf;
|
||||||
_op = new PropOp.Float(v => _index = v);
|
_op = new PropOp.Float(v => _index = v);
|
||||||
}
|
}
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("@emit {0}", IdentifierManager.SharedInstance.Retrieve(Name));
|
return string.Format(IsSelf ? "@emit_self {0}" : "@emit {0}", IdentifierManager.SharedInstance.Retrieve(Name));
|
||||||
}
|
}
|
||||||
public override bool IsValueRequired { get { return true; } }
|
public override bool IsValueRequired { get { return true; } }
|
||||||
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp) {
|
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars) {
|
||||||
throw new InvalidOperationException("Emitting effect in static context is not allowed");
|
throw new InvalidOperationException("Emitting effect in static context is not allowed");
|
||||||
}
|
}
|
||||||
float _index;
|
float _index;
|
||||||
readonly PropOp _op;
|
readonly PropOp _op;
|
||||||
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, int dl) {
|
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars, int dl) {
|
||||||
ChartPlayer.etor.Evaluate(_op, exp);
|
ChartPlayer.etor.Evaluate(_op, exp);
|
||||||
ChartPlayer.effectManager.Emit(Name, _index);
|
if (IsSelf) ChartPlayer.effectManager.EmitSelf(Name, _index, ctx.WriteTransform);
|
||||||
|
else ChartPlayer.effectManager.Emit(Name, _index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class SetVariable : SkinPropertyKey {
|
||||||
|
public int Name { get; private set; }
|
||||||
|
public SetVariable(IEnumerable<string> a, int name) : base(a) {
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
public override string ToString() {
|
||||||
|
return string.Format("@var {0}", IdentifierManager.SharedInstance.Retrieve(Name));
|
||||||
|
}
|
||||||
|
public override bool IsValueRequired { get { return true; } }
|
||||||
|
public override void ExecuteStatic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars) {
|
||||||
|
SkinVariable v;
|
||||||
|
if (!vars.TryGetValue(Name, out v))
|
||||||
|
vars.Add(Name, v = new SkinVariable());
|
||||||
|
ChartPlayer.etor.Evaluate(v.Op, exp);
|
||||||
|
}
|
||||||
|
public override void ExecuteDynamic(ISkinnableGroup group, RuntimeSkinContext ctx, PdtExpression exp, Dictionary<int, SkinVariable> vars, int dl) {
|
||||||
|
SkinVariable v;
|
||||||
|
if (!vars.TryGetValue(Name, out v))
|
||||||
|
throw new InvalidOperationException(string.Format("Variable \"{0}\" not defined", IdentifierManager.SharedInstance.Retrieve(Name)));
|
||||||
|
ChartPlayer.etor.Evaluate(v.Op, exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -101,7 +101,7 @@ namespace Cryville.Crtr {
|
|||||||
public override string ToString() { return string.Format("..{0}", IdentifierManager.SharedInstance.Retrieve(Name)); }
|
public override string ToString() { return string.Format("..{0}", IdentifierManager.SharedInstance.Retrieve(Name)); }
|
||||||
|
|
||||||
public override SkinContext MatchDynamic(ISkinnableGroup g, SkinContext c) {
|
public override SkinContext MatchDynamic(ISkinnableGroup g, SkinContext c) {
|
||||||
return g.OpenedAnchor != null && g.OpenedAnchor.Name == Name ? c : null;
|
return g.OpenedAnchorName == Name ? c : null;
|
||||||
}
|
}
|
||||||
public override bool IsUpdatable(ISkinnableGroup g, int dl) {
|
public override bool IsUpdatable(ISkinnableGroup g, int dl) {
|
||||||
return dl >= 1;
|
return dl >= 1;
|
||||||
|
@@ -16,7 +16,7 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
public override void Init() {
|
public override void Init() {
|
||||||
base.Init();
|
base.Init();
|
||||||
sgos = gogroup.GetComponentsInChildren<SectionalGameObject>();
|
sgos = RootTransform.GetComponentsInChildren<SectionalGameObject>();
|
||||||
}
|
}
|
||||||
SectionalGameObject[] sgos;
|
SectionalGameObject[] sgos;
|
||||||
Vector3 bpos; Quaternion brot;
|
Vector3 bpos; Quaternion brot;
|
||||||
@@ -33,7 +33,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
protected override void StartGraphicalUpdate(ContainerState s) {
|
protected override void StartGraphicalUpdate(ContainerState s) {
|
||||||
base.StartGraphicalUpdate(s);
|
base.StartGraphicalUpdate(s);
|
||||||
if (gogroup) {
|
if (RootTransform) {
|
||||||
TransformAwake(s);
|
TransformAwake(s);
|
||||||
var p = GetCurrentWorldPoint();
|
var p = GetCurrentWorldPoint();
|
||||||
foreach (var i in sgos) {
|
foreach (var i in sgos) {
|
||||||
@@ -82,7 +82,7 @@ namespace Cryville.Crtr {
|
|||||||
|
|
||||||
ptime = s.Time;
|
ptime = s.Time;
|
||||||
|
|
||||||
if (!gogroup || s.CloneType == 3) return;
|
if (!RootTransform || s.CloneType == 3) return;
|
||||||
var p = GetCurrentWorldPoint();
|
var p = GetCurrentWorldPoint();
|
||||||
foreach (var i in sgos)
|
foreach (var i in sgos)
|
||||||
i.AppendPoint(p, s.QuatDir);
|
i.AppendPoint(p, s.QuatDir);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user