221 Commits

Author SHA1 Message Date
e40c98ae1b Update project version. 2023-08-15 21:01:19 +08:00
642a9563ba Fix conditional compilation for Android. 2023-08-15 21:01:00 +08:00
4a1fa48352 Fix incomplete ruleset config displayed on config initialization. 2023-08-15 19:16:16 +08:00
4dc0767e91 Typo fix. 2023-08-11 01:24:01 +08:00
9e82c04898 Fix event priority. 2023-08-07 13:56:17 +08:00
0776eca49d Implement custom ruleset config. (Amend) 2023-08-07 13:55:57 +08:00
af01fb2119 Fix the handle of the slider disappearing permanently after an abnormal range is assigned. 2023-08-02 17:30:20 +08:00
9044631fe7 Implement custom ruleset config. (2) 2023-08-02 17:28:55 +08:00
3b22d4fce3 Fix potential constant flag toggled off incorrectly while optimizing. 2023-08-02 17:25:49 +08:00
5393ff1451 Code cleanup with the implementation of property store. 2023-08-02 17:20:45 +08:00
e34a9cc868 Implement custom ruleset config. 2023-07-31 15:15:07 +08:00
440581261e Add contextual function precision. 2023-07-31 15:14:06 +08:00
b78e99c59c Reconstruct property sources and operators to generic types. 2023-07-31 15:12:41 +08:00
3db8f61e3b Decouple the usage of PDT evaluator of chart player. 2023-07-28 14:13:49 +08:00
8b64165fb7 Fix incorrect layout of popup in camera canvas mode. 2023-07-28 14:10:03 +08:00
799b1e12da Code cleanup. 2023-07-28 13:33:23 +08:00
957270c41a Code cleanup. 2023-07-28 12:17:03 +08:00
bc51a45df8 Rewrite property panel to adapt to ruleset config. 2023-07-27 22:07:20 +08:00
9b091a0084 Rename constraint types to avoid ambiguity. 2023-07-27 22:06:15 +08:00
98e35fc6f6 Distinguish stepped sliders by applying a tint to them. 2023-07-27 16:22:22 +08:00
d83f447e82 Fix number slider not working in camera canvas mode. 2023-07-27 16:21:27 +08:00
898885b116 Scene cleanup. 2023-07-27 16:04:42 +08:00
fd05f6c1dd Add contextual function range. 2023-07-27 16:00:22 +08:00
86da71f2cb Draft config definition. 2023-07-27 15:59:56 +08:00
ba2f1d4858 Fix attempt to save config when failed to load. 2023-07-27 15:31:47 +08:00
3687a70aec Import Android Apk Patch. 2023-07-25 22:12:17 +08:00
8da54093aa Code cleanup. 2023-07-14 23:49:27 +08:00
b057ea8074 Fix the game hanging on close. 2023-07-14 23:48:13 +08:00
e7bc9d0294 Code cleanup. 2023-07-12 23:26:36 +08:00
08de91b04d Implement updater for Windows. 2023-07-12 23:26:26 +08:00
ea70fbb051 Improve exception handling for update checker. 2023-07-12 23:25:15 +08:00
cee6a08240 Refactor some judge variables to hit variables. (Amend) 2023-07-12 23:12:55 +08:00
f04b9cfb75 Refactor some judge variables to hit variables. 2023-07-12 23:08:29 +08:00
1dcbc03829 Code cleanup. 2023-07-11 00:03:47 +08:00
d89423caf5 Code cleanup for network module. 2023-07-11 00:02:14 +08:00
c9b348dd4f Fix Discord timestamp not reset on pause and resume. 2023-07-11 00:01:15 +08:00
636f45f03f Fix dialog layout. 2023-07-04 11:13:46 +08:00
7fce9591a9 Fix crash on opening a URL on Android. 2023-07-04 11:13:28 +08:00
f65e4f1900 Cleanup network module. 2023-07-04 11:12:27 +08:00
a4d0e3867a Code cleanup. 2023-07-03 01:11:04 +08:00
83b9c27e94 Implement opening external package link. 2023-07-03 01:10:45 +08:00
864ea91be0 Implement update checker. 2023-06-22 13:23:24 +08:00
ea02fc22bd Pull down UnityNetworkTask. 2023-06-22 13:23:03 +08:00
60cc763cd0 Fix the active network task not re-enqueued when suspended. 2023-06-22 13:22:23 +08:00
8955b69cdf Fix active inputs not cleaned up while batching. 2023-06-22 13:21:01 +08:00
a7aff4d625 Code cleanup. 2023-06-22 13:18:34 +08:00
22cb8f0cb4 Implement dialog. 2023-06-22 13:15:25 +08:00
db07ace927 Code cleanup. 2023-06-13 18:13:23 +08:00
094c3fe2a3 Add contextual variable judge_delta_time. 2023-06-13 18:13:09 +08:00
cc156e0d81 Fix certain non-interactable UI blocking interaction. 2023-06-06 21:28:17 +08:00
9833052849 Improve the ordering logic for applicable input handlers in input config. 2023-06-06 21:27:33 +08:00
a6a0ac3f9e Fix memory leak during collapsing in PDT. 2023-06-06 21:13:36 +08:00
82060a6403 Disable Android input handlers in non-Android systems. 2023-06-06 11:45:01 +08:00
02441eb328 Update Cryville.Input. 2023-06-06 10:05:02 +08:00
2fe2a40e74 Add stub for config and motion definition in ruleset. 2023-06-06 09:46:39 +08:00
754e3be906 Add stub for judge action @var. 2023-06-06 09:44:00 +08:00
65c225e93b Fix incorrect miss flag on judge pass. 2023-06-02 22:40:52 +08:00
74ce265016 Fix logic of function release_timed_area. 2023-06-02 22:39:37 +08:00
2eba0e490f Code cleanup. 2023-06-02 18:23:44 +08:00
82f769f798 Add context state and context event access for judge. 2023-06-02 18:23:12 +08:00
a008760918 Add secondary judge functions in_timing and in_area. 2023-06-02 18:22:21 +08:00
832facdf5b Add stub for "call" judge action. 2023-06-02 18:20:20 +08:00
d5ba09cbea Implement primary judge result passing. 2023-06-02 18:17:10 +08:00
59b4f14fb3 Make judge functions return judge time and judge vector. 2023-06-02 18:05:25 +08:00
4d13c06f27 Rename internal judge note time variables. 2023-06-02 17:58:53 +08:00
de72fcf572 Rename function in_area to is_in. 2023-06-02 17:48:20 +08:00
1470dbb5aa Fix error while optimizing ruleset when no judge area is defined. 2023-06-02 17:46:13 +08:00
ce31f3e15f Discards context cascades on error. 2023-06-02 17:42:41 +08:00
f6741d0acc Improve error description for missing effect. 2023-06-02 17:41:09 +08:00
910e3ce277 Split (judge) area definition from judges list. 2023-06-02 11:08:43 +08:00
52adef8e9b Modify the logic of "and" and "or" operator. 2023-06-01 23:16:45 +08:00
3d7639b94e Code cleanup. 2023-06-01 23:14:14 +08:00
b306a9d3d1 Remove function contact_timing and contact_timed_area. 2023-05-31 23:19:13 +08:00
0cc15f0c8e Fix potential field align error when dereferencing pointers. 2023-05-31 22:52:18 +08:00
0959b5cc25 Code cleanup. 2023-05-30 22:14:18 +08:00
44c54cd837 Add function sphere. 2023-05-30 22:13:58 +08:00
6e553b9ebb Improve error description for evaluation failure. 2023-05-29 17:06:30 +08:00
88a46127d7 Adapt PDT evaluator to pseudo-lambda expressions. 2023-05-29 17:04:22 +08:00
4310b67e7b Implement extension importer. 2023-05-29 15:04:19 +08:00
7deff3c6be Allow playing chart without input config completed. 2023-05-25 15:07:45 +08:00
5f4d35b3b3 Add exception description for invalid child index. 2023-05-25 15:02:03 +08:00
5b510fa5da Make long motion events standalone to avoid transition overflow. 2023-05-25 14:59:02 +08:00
17042b6664 Code cleanup. 2023-05-25 14:57:42 +08:00
3fb123ff30 Optimize GC while preparing judge events. 2023-05-20 22:58:05 +08:00
ca928eb731 Make judge event internal. 2023-05-20 22:36:08 +08:00
906c82972b Fix typo in a translation file of the skin editor. 2023-05-20 16:37:59 +08:00
cee74b9e31 Code cleanup. 2023-05-20 16:31:23 +08:00
25b4f3ccb7 Add judge action fields on_hit and on_miss. 2023-05-20 16:23:59 +08:00
d1b9b9607b Move nested class JudgeEvent out of Judge. 2023-05-20 16:17:36 +08:00
6ccc86c28d Add constructors for ScoreOperation. 2023-05-20 16:15:12 +08:00
3d75cd9a11 Updates active vectors in input proxy on batch. 2023-05-19 23:58:50 +08:00
b30d35c937 Update global suppressions. 2023-05-19 23:17:56 +08:00
a8231f7c86 Code cleanup. 2023-05-19 23:17:32 +08:00
ed60859406 Add GC-less standalone input module. 2023-05-19 23:14:59 +08:00
0d0902735a Code cleanup. 2023-05-19 00:46:45 +08:00
5bed3cf05b Fix active vectors in input proxy referring to temporary property sources. 2023-05-19 00:45:14 +08:00
5d520609b5 Rename the identifier of input proxy vector. 2023-05-18 14:58:05 +08:00
bf53298706 Modify the internal effect identifier to avoid naming conflict. 2023-05-18 14:55:31 +08:00
3d09ec8c94 Make PdtExpression.Empty public. 2023-05-18 13:28:46 +08:00
bc083541aa Code cleanup. 2023-05-18 00:44:18 +08:00
5b04426cd3 Update Cryville.Crtr.Extension. 2023-05-17 20:43:04 +08:00
8d606524fc Fix the logic of area judge functions. 2023-05-14 19:22:09 +08:00
5bab0ca648 Add area judge functions. 2023-05-14 12:06:32 +08:00
fb31e833cb Code cleanup. 2023-05-14 10:48:26 +08:00
346040574a Modify the default value and the range of force sync frames settings. 2023-05-14 10:47:27 +08:00
959d07b0a9 Add area judge precision settings. 2023-05-14 10:46:32 +08:00
c41d41c881 Make the function interval contextual and linear. 2023-05-12 11:37:14 +08:00
f09e3d3545 Adapt judge functions to Vector4. 2023-05-12 11:33:56 +08:00
12b3373aeb Modify the parameter order of function clamp. 2023-05-12 11:29:06 +08:00
9480904db7 Add judge area definition. (Amend) 2023-05-11 16:19:30 +08:00
bee3401283 Make hit expression comparable. 2023-05-11 16:18:36 +08:00
fe4280aa2e Add judge area definition. 2023-05-11 16:15:57 +08:00
3e273d67ba Fix physical dimension parsing. 2023-05-10 11:10:11 +08:00
fcec43f694 Disable rendering on startup. 2023-05-09 21:28:34 +08:00
904581c520 Allows stopping during chart loading. 2023-05-09 21:27:48 +08:00
b983e32d56 Improve performance for prehandling by disabling rendering. 2023-05-09 21:25:49 +08:00
f2aea2bd40 Improve the ordering logic for input handlers in input config. 2023-05-09 19:02:43 +08:00
cc8e1f7ce4 Update Cryville.Input. 2023-05-09 19:02:17 +08:00
749e1395bc Invalidates handlers with unmatched physical dimension or nullablility in input config. 2023-05-09 19:00:49 +08:00
21af9582f8 Add field for physical dimension in input definition. 2023-05-09 18:58:45 +08:00
26dd373e7b Add function map. 2023-05-09 12:09:08 +08:00
1bd35d2c51 Cleanup. 2023-05-09 11:20:14 +08:00
d275f61602 Update docs from Cryville.Input. 2023-05-09 11:17:49 +08:00
f5f1a5de67 Update Cryville.Audio. 2023-05-09 11:16:18 +08:00
56153f5eed Cleanup. 2023-05-07 21:30:34 +08:00
b4984c0b3a Update Cryville.Input. Fix cleanup logic for input proxy. 2023-05-07 21:30:00 +08:00
dad399facf Fix audio time syncing. 2023-05-07 21:28:17 +08:00
b536871da7 Modify the format of time status debug information. 2023-05-07 21:27:18 +08:00
bd028c1b72 Update Cryville.Input. 2023-05-07 13:42:53 +08:00
fa9303c0a1 Fix chart importing. 2023-05-07 13:40:15 +08:00
d030c48b4d Optimize GC for input config. 2023-05-07 13:38:41 +08:00
beab3d7f8b Fix misspelling. 2023-05-05 00:42:20 +08:00
0b2ea3ddbc Move part of the input module to Cryville.Input. 2023-05-05 00:40:51 +08:00
b143fb49ce Move some classes to Cryville.Common. 2023-05-03 22:51:30 +08:00
8f211568be Fix error caused by threaded input handlers before time syncing. 2023-04-22 21:19:31 +08:00
6d276c99ac Add Android touch handler. 2023-04-22 21:17:00 +08:00
72a93721f9 Fix race condition for the shared evaluator when any active input handler is threaded. 2023-04-22 21:16:17 +08:00
a1fd420493 Fix error handling in PDT evaluator. 2023-04-22 21:09:53 +08:00
d72afaa75b Code cleanup. 2023-04-22 21:08:06 +08:00
2784544884 Fix memory leak from object pools. 2023-04-21 12:18:29 +08:00
c39a02a1c2 Fix event priority. (2) 2023-04-21 00:56:58 +08:00
4c397ab2f7 Switch serialization mode to text mode. 2023-04-21 00:03:13 +08:00
6b3a9c9f0a Fix event priority. 2023-04-20 20:05:59 +08:00
1c1560f17f Fix transition clipping. 2023-04-20 19:47:35 +08:00
0699bc5614 Code cleanup. 2023-04-20 19:47:10 +08:00
d86da00258 Fix unexpected shared vector references. 2023-04-20 19:46:46 +08:00
d1ad68debe Share realtime relative motion nodes across state clones. 2023-04-20 19:45:25 +08:00
b937285a74 Fix polysec not generating mesh if body not specified. 2023-04-20 19:40:50 +08:00
69fe03475b Fix mesh.color not working on polysec. 2023-04-20 19:40:12 +08:00
e5956f2b34 Fix position anchoring. (2) 2023-04-20 14:31:49 +08:00
fdb4ab55a3 (Amend to 61b72107) 2023-04-20 14:31:03 +08:00
e30df8bdbc Fix pre-graphical update not ended within a frame. 2023-04-20 14:29:50 +08:00
251b7bc352 Matches root transform with tag. 2023-04-20 11:37:19 +08:00
61b72107ae Pull up TransformHandler. 2023-04-20 11:36:38 +08:00
d6208f19fb Fix position anchoring. 2023-04-20 00:21:39 +08:00
93d9fdd4b8 Code cleanup. 2023-04-20 00:20:28 +08:00
8670482c04 Implement new transition. 2023-04-20 00:18:49 +08:00
d2b71e41c9 Fix CubicBezier algorithm. 2023-04-20 00:15:06 +08:00
29a8ac2136 Code cleanup. 2023-04-19 15:33:45 +08:00
a9fc5130bb Move BeatTime to separate file. 2023-04-19 15:33:17 +08:00
b51c7d2352 Add chart compatibility handler. 2023-04-19 15:32:16 +08:00
56fd0936bb Fix the recycle of RMV. 2023-04-19 13:56:13 +08:00
2b3898655f Re-implement relative motion. 2023-04-19 13:54:35 +08:00
1b30d3e62c Code cleanup. 2023-04-19 13:52:55 +08:00
bdbb1fcb07 Optimize GC caused by playing motions. 2023-04-19 13:49:55 +08:00
659f2165ff Remove motion lerper. Reconstruct RMV and motion node. Add motion node pool. 2023-04-19 13:48:06 +08:00
a5439430fb Fix the position of the head anchors of tracks. 2023-04-19 13:33:41 +08:00
0f683e403c Resets object on return instead of on rent. 2023-04-19 13:32:06 +08:00
cf6a7a795b Code cleanup. 2023-04-19 13:31:17 +08:00
f664708165 Optimize GC for motion string parsing. 2023-04-18 10:10:11 +08:00
a7be55f2b0 (Amend to f4411629) 2023-04-18 10:05:14 +08:00
398cec1fc5 Code cleanup. 2023-04-18 09:47:37 +08:00
a8b9ba0af4 Loads ruleset before chart loading. 2023-04-18 09:47:07 +08:00
f54564c567 Unify VecPtComp with Vec1, and VecPt with Vec2. 2023-04-18 09:45:46 +08:00
a2c5850fcd Optimize GC while prehandling. 2023-04-18 09:35:37 +08:00
f4411629e4 Obsolete transition and rate, and add end time for relative motion node. 2023-04-18 09:33:47 +08:00
17d620ff0c Fix error on element/property list is null. (2) 2023-04-14 20:32:00 +08:00
5887b1267a Fix relative node interpolation. 2023-04-14 14:47:07 +08:00
400723d83b Make parameters of relative node optional. 2023-04-14 14:46:03 +08:00
07babcb0ff Fix position and rotation of track anchors not set. 2023-04-14 14:39:48 +08:00
f7bfe07660 Fix multiple init calls on skin components. 2023-04-14 14:32:31 +08:00
3690adf5dd Add component linesec. 2023-04-14 14:31:08 +08:00
48349b598d Separate PolygonSGO to individual file. 2023-04-14 14:29:17 +08:00
d6e3d3ad00 Make clip field in JudgeDefinition dynamic. 2023-04-09 22:13:50 +08:00
c57c82bdd1 Add progress tracking for chart loading. 2023-04-09 22:11:29 +08:00
4bc921d47e Fix error on element/property list is null. 2023-04-08 13:39:00 +08:00
8907dd19b0 Remove methods for constructor in ReflectionHelper. 2023-04-08 13:36:52 +08:00
2221658e7a Fix error when member is not found with string key during PDT interpretation. 2023-04-08 13:34:37 +08:00
916c55b4b2 Fix error when trying to generate PDT error message at the very beginning or end of the source. 2023-04-08 13:31:26 +08:00
3d8a4a64a9 Fix potential order inconsistency of pass and score lists. 2023-04-07 13:56:21 +08:00
6cb36a7064 Clean up logic of object interpretation in PDT interpreter. 2023-04-07 12:21:20 +08:00
1fc5ea8ac6 Resource cleanup. 2023-04-04 22:54:11 +08:00
6fd8e44d10 Update project settings. 2023-04-04 22:12:22 +08:00
ff19b45a9f Code cleanup. 2023-04-04 22:12:10 +08:00
f467832115 Fix logic of lerping a missing relative motion node. 2023-04-04 22:11:36 +08:00
0a25b5260d Restore PDT evaluator exception. 2023-04-04 22:09:57 +08:00
c877437ab6 Fix optimization for collapse operators. 2023-04-04 22:08:38 +08:00
676d19f452 Unify absolute value and relative node of motion event. 2023-04-04 21:18:34 +08:00
fd7c1e6635 Fix constant expression flagging in PDT evaluator. 2023-04-04 20:49:46 +08:00
c98536e8ab Prune and clean up code. 2023-04-04 20:48:17 +08:00
a013d59379 Disable warnings from TextMesh Pro. 2023-04-04 20:40:12 +08:00
2e69035618 Returns whether PDT evaluation succeeded. 2023-04-03 17:00:05 +08:00
072703efe7 Pull up error handling in PDT evaluator. 2023-04-03 16:49:34 +08:00
0c796c4d7a Fix "at anchor" selector not working in effects. 2023-03-30 14:16:25 +08:00
ee4b0c5483 Adjust steps for some settings. 2023-03-30 12:20:49 +08:00
ba7a458e7c Update Cryville.Audio. 2023-03-30 12:20:03 +08:00
06d9df304e Add start offset settings. 2023-03-30 10:37:59 +08:00
578e10bbd7 Update Cryville.Audio. 2023-03-30 10:37:08 +08:00
c685e634d5 Documentation cleanup. 2023-03-27 12:52:58 +08:00
824f401b77 Fix encoding. 2023-03-26 23:25:20 +08:00
aafc326f95 Fix collapse operators not correctly parsed after the scope is downgraded. 2023-03-26 22:40:19 +08:00
88a6410439 Re-enable mipmaps for dynamic sprites. 2023-03-26 17:09:02 +08:00
d6e1b19d32 Prevents dynamically loaded sprites from creating physical shapes. 2023-03-26 17:07:19 +08:00
6fa459e5d3 Update Unity to 2021.3.21. 2023-03-26 17:06:09 +08:00
bde6216295 Optimize GC for enumeration in context cascade insertion. 2023-03-24 20:58:45 +08:00
e03dbef5ff Optimize GC for mesh wrapper. 2023-03-24 17:10:30 +08:00
e2c683567e Introduce IntKeyedDictionary to improve performance. 2023-03-24 17:06:47 +08:00
89f391f040 Update project version. 2023-03-23 19:28:18 +08:00
92a3d5018f Merge 'dev-extension' into 'master'. 2023-03-23 19:25:14 +08:00
d510fec57b Update version. 2023-03-23 19:11:24 +08:00
c5214dd477 Update gitignore. 2023-03-17 18:08:11 +08:00
477 changed files with 9994 additions and 6916 deletions

View File

@@ -1,6 +1,9 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
[*]
charset = utf-8
# C# files
[*.cs]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace Cryville.Common {
/// <summary>

View File

@@ -13,7 +13,7 @@ namespace Cryville.Common {
public static Binder CreateBinderOfType(Type type) {
var l = type.GetCustomAttributes(typeof(BinderAttribute), true);
if (l.Length > 0) {
return (Binder)ReflectionHelper.InvokeEmptyConstructor(
return (Binder)Activator.CreateInstance(
((BinderAttribute)l[0]).BinderType
);
}

View File

@@ -1,65 +0,0 @@
namespace Cryville.Common.Buffers {
/// <summary>
/// A resource pool that allows reusing instances of arrays of type <typeparamref name="T" />.
/// </summary>
/// <typeparam name="T">The item type of the arrays in the pool.</typeparam>
public class ArrayPool<T> {
private class Bucket : ObjectPool<T[]> {
readonly int _size;
public Bucket(int size, int capacity) : base(capacity) {
_size = size;
}
protected override T[] Construct() {
return new T[_size];
}
}
readonly Bucket[] _buckets;
/// <summary>
/// Creates an instance of the <see cref="ArrayPool{T}" /> class with the default maximum list size and bucket capacity.
/// </summary>
public ArrayPool() : this(0x40000000, 256) { }
/// <summary>
/// Creates an instance of the <see cref="ArrayPool{T}" /> class.
/// </summary>
/// <param name="maxSize">The maximum size of the arrays in the pool.</param>
/// <param name="capacityPerBucket">The capacity of each bucket. The pool groups arrays of similar sizes into buckets for faster access.</param>
public ArrayPool(int maxSize, int capacityPerBucket) {
if (maxSize < 16) maxSize = 16;
int num = GetID(maxSize) + 1;
_buckets = new Bucket[num];
for (int i = 0; i < num; i++) {
_buckets[i] = new Bucket(GetSize(i), capacityPerBucket);
}
}
/// <summary>
/// Rents an array that is at least the specified size from the pool.
/// </summary>
/// <param name="size">The minimum size of the array.</param>
/// <returns>An array of type <see cref="T" /> that is at least the specified size.</returns>
public T[] Rent(int size) {
int len2 = size;
if (len2 < 16) len2 = 16;
var arr = _buckets[GetID(len2)].Rent();
return arr;
}
/// <summary>
/// Returns a rented array to the pool.
/// </summary>
/// <param name="arr">The array to return.</param>
public void Return(T[] arr) {
int len2 = arr.Length;
if (len2 < 16) len2 = 16;
_buckets[GetID(len2)].Return(arr);
}
static int GetID(int size) {
size -= 1;
size >>= 4;
int num = 0;
for (; size != 0; size >>= 1) num++;
return num;
}
static int GetSize(int id) {
return 0x10 << id;
}
}
}

View File

@@ -1,90 +0,0 @@
using System.Collections.Generic;
namespace Cryville.Common.Buffers {
/// <summary>
/// A set of resource pools categorized by a category type.
/// </summary>
/// <typeparam name="TCategory">The category type.</typeparam>
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
public abstract class CategorizedPool<TCategory, TObject> where TObject : class {
/// <summary>
/// The set of underlying pools.
/// </summary>
/// <remarks>
/// <para>The <see cref="Rent(TCategory)" /> and <see cref="Return(TCategory, TObject)" /> method select an underlying pool directly from this set with the category as the key. When overridden, this set must be available since construction.</para>
/// </remarks>
protected abstract IReadOnlyDictionary<TCategory, ObjectPool<TObject>> Buckets { get; }
/// <summary>
/// The count of objects rented from the set of pools.
/// </summary>
public int RentedCount { get; private set; }
/// <summary>
/// Rents an object from the pool.
/// </summary>
/// <param name="category">The category.</param>
/// <returns>The rented object.</returns>
public TObject Rent(TCategory category) {
var obj = Buckets[category].Rent();
RentedCount++;
return obj;
}
/// <summary>
/// Returns a rented object to the pool.
/// </summary>
/// <param name="category">The category.</param>
/// <param name="obj">The object to return.</param>
public void Return(TCategory category, TObject obj) {
Buckets[category].Return(obj);
--RentedCount;
}
}
/// <summary>
/// A utility to access a categorized pool, representing a single unit that uses a shared categorized pool.
/// </summary>
/// <typeparam name="TCategory">The category type.</typeparam>
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
public class CategorizedPoolAccessor<TCategory, TObject> where TObject : class {
readonly CategorizedPool<TCategory, TObject> _pool;
static readonly SimpleObjectPool<Dictionary<TObject, TCategory>> _dictPool
= new SimpleObjectPool<Dictionary<TObject, TCategory>>(1024);
Dictionary<TObject, TCategory> _rented;
/// <summary>
/// Creates an instance of the <see cref="CategorizedPoolAccessor{TCategory, TObject}" /> class.
/// </summary>
/// <param name="pool">The categorized pool.</param>
public CategorizedPoolAccessor(CategorizedPool<TCategory, TObject> pool) {
_pool = pool;
}
/// <summary>
/// Rents an object from the pool.
/// </summary>
/// <param name="category">The category.</param>
/// <returns>The rented object.</returns>
public TObject Rent(TCategory category) {
var obj = _pool.Rent(category);
if (_rented == null) _rented = _dictPool.Rent();
_rented.Add(obj, category);
return obj;
}
/// <summary>
/// Returns a rented object to the pool.
/// </summary>
/// <param name="obj">The object to return.</param>
public void Return(TObject obj) {
_pool.Return(_rented[obj], obj);
_rented.Remove(obj);
}
/// <summary>
/// Returns all objects rented by this accessor to the pool.
/// </summary>
public void ReturnAll() {
if (_rented == null) return;
foreach (var obj in _rented) {
_pool.Return(obj.Value, obj.Key);
}
_rented.Clear();
_dictPool.Return(_rented);
_rented = null;
}
}
}

View File

@@ -1,71 +0,0 @@
using System.Collections.Generic;
namespace Cryville.Common.Buffers {
/// <summary>
/// A resource pool that allows reusing instances of lists of type <typeparamref name="T" />.
/// </summary>
/// <typeparam name="T">The item type of the lists in the pool.</typeparam>
public class ListPool<T> {
private class Bucket : ObjectPool<List<T>> {
readonly int _size;
public Bucket(int size, int capacity) : base(capacity) {
_size = size;
}
protected override List<T> Construct() {
return new List<T>(_size);
}
}
readonly Bucket[] _buckets;
/// <summary>
/// Creates an instance of the <see cref="ListPool{T}" /> class with the default maximum list size and bucket capacity.
/// </summary>
public ListPool() : this(0x40000000, 256) { }
/// <summary>
/// Creates an instance of the <see cref="ListPool{T}" /> class.
/// </summary>
/// <param name="maxSize">The maximum size of the lists in the pool.</param>
/// <param name="capacityPerBucket">The capacity of each bucket. The pool groups lists of similar sizes into buckets for faster access.</param>
public ListPool(int maxSize, int capacityPerBucket) {
if (maxSize < 16) maxSize = 16;
int num = GetID(maxSize) + 1;
_buckets = new Bucket[num];
for (int i = 0; i < num; i++) {
_buckets[i] = new Bucket(GetSize(i), capacityPerBucket);
}
}
/// <summary>
/// Rents a list of the specified size from the pool. The size of the list must not be changed when it is rented.
/// </summary>
/// <param name="size">The size of the list.</param>
/// <returns>A <see cref="List{T}" /> of the specified size.</returns>
public List<T> Rent(int size) {
int len2 = size;
if (len2 < 16) len2 = 16;
var list = _buckets[GetID(len2)].Rent();
if (list.Count < size)
for (int i = list.Count; i < size; i++) list.Add(default(T));
else if (list.Count > size)
list.RemoveRange(size, list.Count - size);
return list;
}
/// <summary>
/// Returns a rented list to the pool.
/// </summary>
/// <param name="list">The list to return.</param>
public void Return(List<T> list) {
int len2 = list.Capacity;
if (len2 < 16) len2 = 16;
_buckets[GetID(len2)].Return(list);
}
static int GetID(int size) {
size -= 1;
size >>= 4;
int num = 0;
for (; size != 0; size >>= 1) num++;
return num;
}
static int GetSize(int id) {
return 0x10 << id;
}
}
}

View File

@@ -1,52 +0,0 @@
namespace Cryville.Common.Buffers {
/// <summary>
/// A resource pool that allows reusing instances of type <typeparamref name="T" />.
/// </summary>
/// <typeparam name="T">The type of the objects in the pool.</typeparam>
public abstract class ObjectPool<T> where T : class {
int _index;
readonly T[] _objs;
/// <summary>
/// Creates an instance of the <see cref="ObjectPool{T}" /> class.
/// </summary>
/// <param name="capacity">The capacity of the pool.</param>
public ObjectPool(int capacity) {
_objs = new T[capacity];
}
/// <summary>
/// The count of objects rented from the pool.
/// </summary>
public int RentedCount { get { return _index; } }
/// <summary>
/// Rents a object from the pool.
/// </summary>
/// <returns>The rented object.</returns>
public T Rent() {
T obj = null;
if (_index < _objs.Length) {
obj = _objs[_index];
_objs[_index++] = null;
}
if (obj == null) obj = Construct();
else Reset(obj);
return obj;
}
/// <summary>
/// Returns a rented object to the pool.
/// </summary>
/// <param name="obj">The object to return.</param>
public void Return(T obj) {
if (_index > 0) _objs[--_index] = obj;
}
/// <summary>
/// Constructs a new instance of type <typeparamref name="T" />.
/// </summary>
/// <returns>The new instance.</returns>
protected abstract T Construct();
/// <summary>
/// Resets an object.
/// </summary>
/// <param name="obj">The object.</param>
protected virtual void Reset(T obj) { }
}
}

View File

@@ -1,16 +0,0 @@
namespace Cryville.Common.Buffers {
/// <summary>
/// A resource pool that allows reusing instances of type <typeparamref name="T" />, which has a parameterless constructor.
/// </summary>
/// <typeparam name="T">The type of the objects in the pool.</typeparam>
public class SimpleObjectPool<T> : ObjectPool<T> where T : class, new() {
/// <summary>
/// Creates an instance of the <see cref="SimpleObjectPool{T}" /> class.
/// </summary>
/// <param name="capacity">The capacity of the pool.</param>
public SimpleObjectPool(int capacity) : base(capacity) { }
protected override T Construct() {
return new T();
}
}
}

View File

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

View File

@@ -1,135 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Cryville.Common.Buffers {
/// <summary>
/// An auto-resized <see cref="char" /> array as a variable-length string used as a target that is modified frequently.
/// </summary>
public class TargetString : IEnumerable<char> {
public event Action OnUpdate;
char[] _arr;
bool _invalidated;
/// <summary>
/// Creates an instance of the <see cref="TargetString" /> class with a capacity of 16.
/// </summary>
public TargetString() : this(16) { }
/// <summary>
/// Creates an instance of the <see cref="TargetString" /> class.
/// </summary>
/// <param name="capacity">The initial capacity of the string.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity" /> is less than or equal to 0.</exception>
public TargetString(int capacity) {
if (capacity <= 0) throw new ArgumentOutOfRangeException("capacity");
_arr = new char[capacity];
}
/// <summary>
/// Gets or sets one of the characters in the string.
/// </summary>
/// <param name="index">The zero-based index of the character.</param>
/// <returns>The character at the given index.</returns>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> is less than 0 or not less than <see cref="Length" />.</exception>
/// <remarks>
/// <para>Set <see cref="Length" /> to a desired value before updating the characters.</para>
/// <para>Call <see cref=" Validate" /> after all the characters are updated.</para>
/// </remarks>
public char this[int index] {
get {
if (index < 0 || index >= m_length)
throw new ArgumentOutOfRangeException("index");
return _arr[index];
}
set {
if (index < 0 || index >= m_length)
throw new ArgumentOutOfRangeException("index");
if (_arr[index] == value) return;
_arr[index] = value;
_invalidated = true;
}
}
int m_length;
/// <summary>
/// The length of the string.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">The value specified for a set operation is less than 0.</exception>
public int Length {
get {
return m_length;
}
set {
if (Length < 0) throw new ArgumentOutOfRangeException("length");
if (m_length == value) return;
if (_arr.Length < value) {
var len = _arr.Length;
while (len < value) len *= 2;
var arr2 = new char[len];
Array.Copy(_arr, arr2, m_length);
_arr = arr2;
}
m_length = value;
_invalidated = true;
}
}
/// <summary>
/// Validates the string.
/// </summary>
public void Validate() {
if (!_invalidated) return;
_invalidated = false;
var ev = OnUpdate;
if (ev != null) ev.Invoke();
}
internal char[] TrustedAsArray() { return _arr; }
/// <summary>
/// Returns an enumerator that iterates through the <see cref="TargetString" />.
/// </summary>
/// <returns>A <see cref="Enumerator" /> for the <see cref="TargetString" />.</returns>
public Enumerator GetEnumerator() {
return new Enumerator(this);
}
IEnumerator<char> IEnumerable<char>.GetEnumerator() {
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator() {
return new Enumerator(this);
}
public struct Enumerator : IEnumerator<char> {
readonly TargetString _self;
int _index;
internal Enumerator(TargetString self) {
_self = self;
_index = -1;
}
public char Current {
get {
if (_index < 0)
throw new InvalidOperationException(_index == -1 ? "Enum not started" : "Enum ended");
return _self[_index];
}
}
object IEnumerator.Current { get { return Current; } }
public void Dispose() {
_index = -2;
}
public bool MoveNext() {
if (_index == -2) return false;
_index++;
if (_index >= _self.Length) {
_index = -2;
return false;
}
return true;
}
public void Reset() {
_index = -1;
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace Cryville.Common.ComponentModel {
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace Cryville.Common.ComponentModel {
[AttributeUsage(AttributeTargets.Property, Inherited = false)]

View File

@@ -1,14 +1,14 @@
using System;
using System;
namespace Cryville.Common.ComponentModel {
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class RangeAttribute : Attribute {
public RangeAttribute(float min, float max) {
public RangeAttribute(double min, double max) {
Min = min;
Max = max;
}
public float Min { get; set; }
public float Max { get; set; }
public double Min { get; set; }
public double Max { get; set; }
}
}

View File

@@ -1,11 +1,11 @@
using System;
using System;
namespace Cryville.Common.ComponentModel {
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class StepAttribute : Attribute {
public StepAttribute(float step) {
public StepAttribute(double step) {
Step = step;
}
public float Step { get; set; }
public double Step { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace Cryville.Common {
public class Coroutine {
readonly IEnumerator<float> _enumerator;
readonly Stopwatch _stopwatch = new Stopwatch();
public float Progress { get; private set; }
public Coroutine(IEnumerator<float> enumerator) {
_enumerator = enumerator;
}
public bool TickOnce() {
if (!_enumerator.MoveNext()) return false;
Progress = _enumerator.Current;
return true;
}
public bool Tick(double minTime) {
_stopwatch.Restart();
while (_stopwatch.Elapsed.TotalSeconds < minTime) {
if (!_enumerator.MoveNext()) return false;
Progress = _enumerator.Current;
}
return true;
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 2745c44c3cc32be4ab3a43888c14b9a1
guid: 387adc7d494be0147b7cb930bc2e726b
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections;
using System.Collections.Generic;

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace Cryville.Common {
public class FileStringAttribute : Attribute {

View File

@@ -1,4 +1,4 @@
using Cryville.Common.IO;
using Cryville.Common.IO;
using System;
using System.Collections;
using System.Collections.Generic;

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;

View File

@@ -1,4 +1,4 @@
using Cryville.Common.Culture;
using Cryville.Common.Culture;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -6,295 +6,295 @@ using System.Linq;
namespace Cryville.Common.Font {
public abstract class FontMatcher {
protected FontManager Manager { get; private set; }
public FontMatcher(FontManager manafer) { Manager = manafer; }
public FontMatcher(FontManager manager) { Manager = manager; }
public abstract IEnumerable<Typeface> MatchScript(string script = null, bool distinctFamily = false);
}
public class FallbackListFontMatcher : FontMatcher {
public Dictionary<string, List<string>> MapScriptToTypefaces = new Dictionary<string, List<string>>();
public void LoadDefaultWindowsFallbackList() {
if (Environment.OSVersion.Platform != PlatformID.Win32NT) return;
MapScriptToTypefaces.Clear();
ScriptUtils.FillKeysWithScripts(MapScriptToTypefaces, () => new List<string>());
public static Dictionary<string, List<string>> GetDefaultWindowsFallbackMap() {
var map = new Dictionary<string, List<string>>();
ScriptUtils.FillKeysWithScripts(map, () => new List<string>());
// Reference: https://github.com/chromium/chromium/blob/main/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc
MapScriptToTypefaces["zyyy"].Insert(0, "SimSun"); // Custom
MapScriptToTypefaces["zyyy"].Insert(0, "SimHei"); // Custom
MapScriptToTypefaces["zyyy"].Insert(0, "Microsoft YaHei"); // Custom
MapScriptToTypefaces["zyyy"].Insert(0, "Arial");
MapScriptToTypefaces["zyyy"].Insert(0, "Times New Roman");
MapScriptToTypefaces["zyyy"].Insert(0, "Segoe UI"); // Custom
MapScriptToTypefaces["arab"].Insert(0, "Tahoma");
MapScriptToTypefaces["cyrl"].Insert(0, "Times New Roman");
MapScriptToTypefaces["grek"].Insert(0, "Times New Roman");
MapScriptToTypefaces["hebr"].Insert(0, "David");
MapScriptToTypefaces["jpan"].Insert(0, "MS PGothic");
MapScriptToTypefaces["latn"].Insert(0, "Times New Roman");
MapScriptToTypefaces["hans"].Insert(0, "SimSun");
MapScriptToTypefaces["hans"].Insert(0, "SimHei"); // Custom
MapScriptToTypefaces["thai"].Insert(0, "Tahoma");
MapScriptToTypefaces["hans"].Insert(0, "PMingLiU");
map["zyyy"].Insert(0, "SimSun"); // Custom
map["zyyy"].Insert(0, "SimHei"); // Custom
map["zyyy"].Insert(0, "Microsoft YaHei"); // Custom
map["zyyy"].Insert(0, "Arial");
map["zyyy"].Insert(0, "Times New Roman");
map["zyyy"].Insert(0, "Segoe UI"); // Custom
map["arab"].Insert(0, "Tahoma");
map["cyrl"].Insert(0, "Times New Roman");
map["grek"].Insert(0, "Times New Roman");
map["hebr"].Insert(0, "David");
map["jpan"].Insert(0, "MS PGothic");
map["latn"].Insert(0, "Times New Roman");
map["hans"].Insert(0, "SimSun");
map["hans"].Insert(0, "SimHei"); // Custom
map["thai"].Insert(0, "Tahoma");
map["hans"].Insert(0, "PMingLiU");
// Reference: https://learn.microsoft.com/en-us/globalization/input/font-support
var ver = Environment.OSVersion.Version;
if (ver >= new Version(5, 0)) { // Windows 2000
MapScriptToTypefaces["armn"].Insert(0, "Sylfaen");
MapScriptToTypefaces["deva"].Insert(0, "Mangal");
MapScriptToTypefaces["geor"].Insert(0, "Sylfaen");
MapScriptToTypefaces["taml"].Insert(0, "Latha");
map["armn"].Insert(0, "Sylfaen");
map["deva"].Insert(0, "Mangal");
map["geor"].Insert(0, "Sylfaen");
map["taml"].Insert(0, "Latha");
}
if (ver >= new Version(5, 1)) { // Windows XP
MapScriptToTypefaces["gujr"].Insert(0, "Shruti");
MapScriptToTypefaces["guru"].Insert(0, "Raavi");
MapScriptToTypefaces["knda"].Insert(0, "Tunga");
MapScriptToTypefaces["syrc"].Insert(0, "Estrangelo Edessa");
MapScriptToTypefaces["telu"].Insert(0, "Gautami");
MapScriptToTypefaces["thaa"].Insert(0, "MV Boli");
map["gujr"].Insert(0, "Shruti");
map["guru"].Insert(0, "Raavi");
map["knda"].Insert(0, "Tunga");
map["syrc"].Insert(0, "Estrangelo Edessa");
map["telu"].Insert(0, "Gautami");
map["thaa"].Insert(0, "MV Boli");
// SP2
MapScriptToTypefaces["beng"].Insert(0, "Vrinda");
MapScriptToTypefaces["mlym"].Insert(0, "Kartika");
map["beng"].Insert(0, "Vrinda");
map["mlym"].Insert(0, "Kartika");
}
if (ver >= new Version(6, 0)) { // Windows Vista
MapScriptToTypefaces["cans"].Insert(0, "Euphemia");
MapScriptToTypefaces["cher"].Insert(0, "Plantagenet");
MapScriptToTypefaces["ethi"].Insert(0, "Nyala");
MapScriptToTypefaces["khmr"].Insert(0, "DaunPenh MoolBoran");
MapScriptToTypefaces["laoo"].Insert(0, "DokChampa");
MapScriptToTypefaces["mong"].Insert(0, "Mongolian Baiti");
MapScriptToTypefaces["orya"].Insert(0, "Kalinga");
MapScriptToTypefaces["sinh"].Insert(0, "Iskoola Pota");
MapScriptToTypefaces["tibt"].Insert(0, "Microsoft Himalaya");
MapScriptToTypefaces["yiii"].Insert(0, "Microsoft Yi Baiti");
MapScriptToTypefaces["arab"].Insert(0, "Segoe UI");
MapScriptToTypefaces["cyrl"].Insert(0, "Segoe UI");
MapScriptToTypefaces["grek"].Insert(0, "Segoe UI");
MapScriptToTypefaces["latn"].Insert(0, "Segoe UI");
MapScriptToTypefaces["hans"].Add("SimSun-ExtB");
MapScriptToTypefaces["hant"].Add("MingLiU-ExtB");
MapScriptToTypefaces["hant"].Add("MingLiU_HKSCS-ExtB");
MapScriptToTypefaces["arab"].Add("Microsoft Uighur");
MapScriptToTypefaces["zmth"].Insert(0, "Cambria Math");
map["cans"].Insert(0, "Euphemia");
map["cher"].Insert(0, "Plantagenet");
map["ethi"].Insert(0, "Nyala");
map["khmr"].Insert(0, "DaunPenh MoolBoran");
map["laoo"].Insert(0, "DokChampa");
map["mong"].Insert(0, "Mongolian Baiti");
map["orya"].Insert(0, "Kalinga");
map["sinh"].Insert(0, "Iskoola Pota");
map["tibt"].Insert(0, "Microsoft Himalaya");
map["yiii"].Insert(0, "Microsoft Yi Baiti");
map["arab"].Insert(0, "Segoe UI");
map["cyrl"].Insert(0, "Segoe UI");
map["grek"].Insert(0, "Segoe UI");
map["latn"].Insert(0, "Segoe UI");
map["hans"].Add("SimSun-ExtB");
map["hant"].Add("MingLiU-ExtB");
map["hant"].Add("MingLiU_HKSCS-ExtB");
map["arab"].Add("Microsoft Uighur");
map["zmth"].Insert(0, "Cambria Math");
// Reference: https://en.wikipedia.org/wiki/List_of_CJK_fonts
MapScriptToTypefaces["jpan"].Insert(0, "Meiryo");
MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei");
map["jpan"].Insert(0, "Meiryo");
map["hans"].Insert(0, "Microsoft YaHei");
}
if (ver >= new Version(6, 1)) { // Windows 7
MapScriptToTypefaces["brai"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["dsrt"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["talu"].Insert(0, "Microsoft New Tai Lue");
MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["osma"].Insert(0, "Ebrima");
MapScriptToTypefaces["phag"].Insert(0, "Microsoft PhagsPa");
MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["zsym"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["tale"].Insert(0, "Microsoft Tai Le");
MapScriptToTypefaces["tfng"].Insert(0, "Ebrima");
MapScriptToTypefaces["vaii"].Insert(0, "Ebrima");
map["brai"].Insert(0, "Segoe UI Symbol");
map["dsrt"].Insert(0, "Segoe UI Symbol");
map["talu"].Insert(0, "Microsoft New Tai Lue");
map["ogam"].Insert(0, "Segoe UI Symbol");
map["osma"].Insert(0, "Ebrima");
map["phag"].Insert(0, "Microsoft PhagsPa");
map["runr"].Insert(0, "Segoe UI Symbol");
map["zsym"].Insert(0, "Segoe UI Symbol");
map["tale"].Insert(0, "Microsoft Tai Le");
map["tfng"].Insert(0, "Ebrima");
map["vaii"].Insert(0, "Ebrima");
}
if (ver >= new Version(6, 2)) { // Windows 8
MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["hang"].Add("Malgun Gothic");
MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["lisu"].Insert(0, "Segoe UI");
MapScriptToTypefaces["mymr"].Insert(0, "Myanmar Text");
MapScriptToTypefaces["nkoo"].Insert(0, "Ebrima");
MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["ethi"].Insert(0, "Ebrima");
MapScriptToTypefaces["cans"].Insert(0, "Gadugi");
MapScriptToTypefaces["hant"].Insert(0, "Microsoft JhengHei UI");
MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei UI");
MapScriptToTypefaces["beng"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["deva"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["gujr"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["guru"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
MapScriptToTypefaces["knda"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
MapScriptToTypefaces["mlym"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["orya"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["sinh"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
MapScriptToTypefaces["taml"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
MapScriptToTypefaces["telu"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["armn"].Insert(0, "Segoe UI");
MapScriptToTypefaces["geor"].Insert(0, "Segoe UI");
MapScriptToTypefaces["hebr"].Insert(0, "Segoe UI");
map["glag"].Insert(0, "Segoe UI Symbol");
map["goth"].Insert(0, "Segoe UI Symbol");
map["hang"].Add("Malgun Gothic");
map["ital"].Insert(0, "Segoe UI Symbol");
map["lisu"].Insert(0, "Segoe UI");
map["mymr"].Insert(0, "Myanmar Text");
map["nkoo"].Insert(0, "Ebrima");
map["orkh"].Insert(0, "Segoe UI Symbol");
map["ethi"].Insert(0, "Ebrima");
map["cans"].Insert(0, "Gadugi");
map["hant"].Insert(0, "Microsoft JhengHei UI");
map["hans"].Insert(0, "Microsoft YaHei UI");
map["beng"].Insert(0, "Nirmala UI");
map["deva"].Insert(0, "Nirmala UI");
map["gujr"].Insert(0, "Nirmala UI");
map["guru"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
map["knda"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
map["mlym"].Insert(0, "Nirmala UI");
map["orya"].Insert(0, "Nirmala UI");
map["sinh"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
map["taml"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
map["telu"].Insert(0, "Nirmala UI");
map["armn"].Insert(0, "Segoe UI");
map["geor"].Insert(0, "Segoe UI");
map["hebr"].Insert(0, "Segoe UI");
}
if (ver >= new Version(6, 3)) { // Windows 8.1
MapScriptToTypefaces["bugi"].Insert(0, "Leelawadee UI");
MapScriptToTypefaces["copt"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["java"].Insert(0, "Javanese Text");
MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Symbol");
MapScriptToTypefaces["olck"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["sora"].Insert(0, "Nirmala UI");
MapScriptToTypefaces["khmr"].Insert(0, "Leelawadee UI");
MapScriptToTypefaces["laoo"].Insert(0, "Leelawadee UI");
MapScriptToTypefaces["thai"].Insert(0, "Leelawadee UI");
MapScriptToTypefaces["zsye"].Insert(0, "Segoe UI Emoji");
map["bugi"].Insert(0, "Leelawadee UI");
map["copt"].Insert(0, "Segoe UI Symbol");
map["java"].Insert(0, "Javanese Text");
map["merc"].Insert(0, "Segoe UI Symbol");
map["olck"].Insert(0, "Nirmala UI");
map["sora"].Insert(0, "Nirmala UI");
map["khmr"].Insert(0, "Leelawadee UI");
map["laoo"].Insert(0, "Leelawadee UI");
map["thai"].Insert(0, "Leelawadee UI");
map["zsye"].Insert(0, "Segoe UI Emoji");
}
if (ver >= new Version(10, 0)) { // Windows 10
MapScriptToTypefaces["brah"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["cari"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["cprt"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["egyp"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["armi"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["phli"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["prti"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["khar"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["lyci"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["lydi"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["phnx"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["xpeo"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["sarb"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["shaw"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["xsux"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["ugar"].Insert(0, "Segoe UI Historic");
map["brah"].Insert(0, "Segoe UI Historic");
map["cari"].Insert(0, "Segoe UI Historic");
map["cprt"].Insert(0, "Segoe UI Historic");
map["egyp"].Insert(0, "Segoe UI Historic");
map["armi"].Insert(0, "Segoe UI Historic");
map["phli"].Insert(0, "Segoe UI Historic");
map["prti"].Insert(0, "Segoe UI Historic");
map["khar"].Insert(0, "Segoe UI Historic");
map["lyci"].Insert(0, "Segoe UI Historic");
map["lydi"].Insert(0, "Segoe UI Historic");
map["phnx"].Insert(0, "Segoe UI Historic");
map["xpeo"].Insert(0, "Segoe UI Historic");
map["sarb"].Insert(0, "Segoe UI Historic");
map["shaw"].Insert(0, "Segoe UI Historic");
map["xsux"].Insert(0, "Segoe UI Historic");
map["ugar"].Insert(0, "Segoe UI Historic");
// Segoe UI Symbol -> Segoe UI Historic
MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Historic");
MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Historic");
map["glag"].Insert(0, "Segoe UI Historic");
map["goth"].Insert(0, "Segoe UI Historic");
map["merc"].Insert(0, "Segoe UI Historic");
map["ogam"].Insert(0, "Segoe UI Historic");
map["ital"].Insert(0, "Segoe UI Historic");
map["orkh"].Insert(0, "Segoe UI Historic");
map["runr"].Insert(0, "Segoe UI Historic");
//
MapScriptToTypefaces["jpan"].Insert(0, "Yu Gothic UI");
MapScriptToTypefaces["zsym"].Add("Segoe MDL2 Assets");
map["jpan"].Insert(0, "Yu Gothic UI");
map["zsym"].Add("Segoe MDL2 Assets");
}
return map;
}
public void LoadDefaultAndroidFallbackList() {
if (Environment.OSVersion.Platform != PlatformID.Unix) return;
MapScriptToTypefaces.Clear();
ScriptUtils.FillKeysWithScripts(MapScriptToTypefaces, () => new List<string>());
MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK TC"); // TODO Modify default fallback
MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK JP");
MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK SC");
MapScriptToTypefaces["zyyy"].Insert(0, "Roboto");
MapScriptToTypefaces["zsye"].Insert(0, "Noto Color Emoji");
MapScriptToTypefaces["zsye"].Add("Noto Color Emoji Flags");
MapScriptToTypefaces["arab"].Insert(0, "Noto Naskh Arabic");
MapScriptToTypefaces["adlm"].Insert(0, "Noto Sans Adlam");
MapScriptToTypefaces["ahom"].Insert(0, "Noto Sans Ahom");
MapScriptToTypefaces["hluw"].Insert(0, "Noto Sans Anatolian Hieroglyphs");
MapScriptToTypefaces["armn"].Insert(0, "Noto Sans Armenian");
MapScriptToTypefaces["avst"].Insert(0, "Noto Sans Avestan");
MapScriptToTypefaces["bali"].Insert(0, "Noto Sans Balinese");
MapScriptToTypefaces["bamu"].Insert(0, "Noto Sans Bamum");
MapScriptToTypefaces["bass"].Insert(0, "Noto Sans Bassa Vah");
MapScriptToTypefaces["batk"].Insert(0, "Noto Sans Batak");
MapScriptToTypefaces["beng"].Insert(0, "Noto Sans Bengali");
MapScriptToTypefaces["bhks"].Insert(0, "Noto Sans Bhaiksuki");
MapScriptToTypefaces["brah"].Insert(0, "Noto Sans Brahmi");
MapScriptToTypefaces["bugi"].Insert(0, "Noto Sans Buginese");
MapScriptToTypefaces["buhd"].Insert(0, "Noto Sans Buhid");
MapScriptToTypefaces["jpan"].Insert(0, "Noto Sans CJK JP");
MapScriptToTypefaces["kore"].Insert(0, "Noto Sans CJK KR");
MapScriptToTypefaces["hans"].Insert(0, "Noto Sans CJK SC");
MapScriptToTypefaces["hant"].Insert(0, "Noto Sans CJK TC");
MapScriptToTypefaces["hant"].Add("Noto Sans CJK HK");
MapScriptToTypefaces["cans"].Insert(0, "Noto Sans Canadian Aboriginal");
MapScriptToTypefaces["cari"].Insert(0, "Noto Sans Carian");
MapScriptToTypefaces["cakm"].Insert(0, "Noto Sans Chakma");
MapScriptToTypefaces["cham"].Insert(0, "Noto Sans Cham");
MapScriptToTypefaces["cher"].Insert(0, "Noto Sans Cherokee");
MapScriptToTypefaces["copt"].Insert(0, "Noto Sans Coptic");
MapScriptToTypefaces["xsux"].Insert(0, "Noto Sans Cuneiform");
MapScriptToTypefaces["cprt"].Insert(0, "Noto Sans Cypriot");
MapScriptToTypefaces["dsrt"].Insert(0, "Noto Sans Deseret");
MapScriptToTypefaces["deva"].Insert(0, "Noto Sans Devanagari");
MapScriptToTypefaces["egyp"].Insert(0, "Noto Sans Egyptian Hieroglyphs");
MapScriptToTypefaces["elba"].Insert(0, "Noto Sans Elbasan");
MapScriptToTypefaces["ethi"].Insert(0, "Noto Sans Ethiopic");
MapScriptToTypefaces["geor"].Insert(0, "Noto Sans Georgian");
MapScriptToTypefaces["glag"].Insert(0, "Noto Sans Glagolitic");
MapScriptToTypefaces["goth"].Insert(0, "Noto Sans Gothic");
MapScriptToTypefaces["gran"].Insert(0, "Noto Sans Grantha");
MapScriptToTypefaces["gujr"].Insert(0, "Noto Sans Gujarati");
MapScriptToTypefaces["gong"].Insert(0, "Noto Sans Gunjala Gondi");
MapScriptToTypefaces["guru"].Insert(0, "Noto Sans Gurmukhi");
MapScriptToTypefaces["rohg"].Insert(0, "Noto Sans Hanifi Rohingya");
MapScriptToTypefaces["hano"].Insert(0, "Noto Sans Hanunoo");
MapScriptToTypefaces["hatr"].Insert(0, "Noto Sans Hatran");
MapScriptToTypefaces["hebr"].Insert(0, "Noto Sans Hebrew");
MapScriptToTypefaces["armi"].Insert(0, "Noto Sans Imperial Aramaic");
MapScriptToTypefaces["phli"].Insert(0, "Noto Sans Inscriptional Pahlavi");
MapScriptToTypefaces["prti"].Insert(0, "Noto Sans Inscriptional Parthian");
MapScriptToTypefaces["java"].Insert(0, "Noto Sans Javanese");
MapScriptToTypefaces["kthi"].Insert(0, "Noto Sans Kaithi");
MapScriptToTypefaces["knda"].Insert(0, "Noto Sans Kannada");
MapScriptToTypefaces["kali"].Insert(0, "Noto Sans KayahLi");
MapScriptToTypefaces["khar"].Insert(0, "Noto Sans Kharoshthi");
MapScriptToTypefaces["khmr"].Insert(0, "Noto Sans Khmer");
MapScriptToTypefaces["khoj"].Insert(0, "Noto Sans Khojki");
MapScriptToTypefaces["laoo"].Insert(0, "Noto Sans Lao");
MapScriptToTypefaces["lepc"].Insert(0, "Noto Sans Lepcha");
MapScriptToTypefaces["limb"].Insert(0, "Noto Sans Limbu");
MapScriptToTypefaces["lina"].Insert(0, "Noto Sans Linear A");
MapScriptToTypefaces["linb"].Insert(0, "Noto Sans Linear B");
MapScriptToTypefaces["lisu"].Insert(0, "Noto Sans Lisu");
MapScriptToTypefaces["lyci"].Insert(0, "Noto Sans Lycian");
MapScriptToTypefaces["lydi"].Insert(0, "Noto Sans Lydian");
MapScriptToTypefaces["mlym"].Insert(0, "Noto Sans Malayalam");
MapScriptToTypefaces["mand"].Insert(0, "Noto Sans Mandiac");
MapScriptToTypefaces["mani"].Insert(0, "Noto Sans Manichaean");
MapScriptToTypefaces["marc"].Insert(0, "Noto Sans Marchen");
MapScriptToTypefaces["gonm"].Insert(0, "Noto Sans Masaram Gondi");
MapScriptToTypefaces["medf"].Insert(0, "Noto Sans Medefaidrin");
MapScriptToTypefaces["mtei"].Insert(0, "Noto Sans Meetei Mayek");
MapScriptToTypefaces["merc"].Insert(0, "Noto Sans Meroitic");
MapScriptToTypefaces["mero"].Insert(0, "Noto Sans Meroitic");
MapScriptToTypefaces["plrd"].Insert(0, "Noto Sans Miao");
MapScriptToTypefaces["modi"].Insert(0, "Noto Sans Modi");
MapScriptToTypefaces["mong"].Insert(0, "Noto Sans Mongolian");
MapScriptToTypefaces["mroo"].Insert(0, "Noto Sans Mro");
MapScriptToTypefaces["mult"].Insert(0, "Noto Sans Multani");
MapScriptToTypefaces["mymr"].Insert(0, "Noto Sans Myanmar");
MapScriptToTypefaces["nkoo"].Insert(0, "Noto Sans Nko");
MapScriptToTypefaces["nbat"].Insert(0, "Noto Sans Nabataean");
MapScriptToTypefaces["talu"].Insert(0, "Noto Sans New Tai Lue");
MapScriptToTypefaces["newa"].Insert(0, "Noto Sans Newa");
MapScriptToTypefaces["ogam"].Insert(0, "Noto Sans Ogham");
MapScriptToTypefaces["olck"].Insert(0, "Noto Sans Ol Chiki");
MapScriptToTypefaces["ital"].Insert(0, "Noto Sans Old Italian");
MapScriptToTypefaces["narb"].Insert(0, "Noto Sans Old North Arabian");
MapScriptToTypefaces["perm"].Insert(0, "Noto Sans Old Permic");
MapScriptToTypefaces["xpeo"].Insert(0, "Noto Sans Old Persian");
MapScriptToTypefaces["sarb"].Insert(0, "Noto Sans Old South Arabian");
MapScriptToTypefaces["orkh"].Insert(0, "Noto Sans Old Turkic");
MapScriptToTypefaces["orya"].Insert(0, "Noto Sans Oriya");
MapScriptToTypefaces["osge"].Insert(0, "Noto Sans Osage");
MapScriptToTypefaces["osma"].Insert(0, "Noto Sans Osmanya");
MapScriptToTypefaces["hmng"].Insert(0, "Noto Sans Pahawh Hmong");
MapScriptToTypefaces["palm"].Insert(0, "Noto Sans Palmyrene");
MapScriptToTypefaces["pauc"].Insert(0, "Noto Sans Pau Cin Hau");
MapScriptToTypefaces["phag"].Insert(0, "Noto Sans Phags Pa");
MapScriptToTypefaces["phnx"].Insert(0, "Noto Sans Phoenician");
MapScriptToTypefaces["rjng"].Insert(0, "Noto Sans Rejang");
MapScriptToTypefaces["runr"].Insert(0, "Noto Sans Runic");
MapScriptToTypefaces["samr"].Insert(0, "Noto Sans Samaritan");
MapScriptToTypefaces["saur"].Insert(0, "Noto Sans Saurashtra");
MapScriptToTypefaces["shrd"].Insert(0, "Noto Sans Sharada");
MapScriptToTypefaces["shaw"].Insert(0, "Noto Sans Shavian");
MapScriptToTypefaces["sinh"].Insert(0, "Noto Sans Sinhala");
MapScriptToTypefaces["sora"].Insert(0, "Noto Sans Sora Sompeng");
MapScriptToTypefaces["soyo"].Insert(0, "Noto Sans Soyombo");
MapScriptToTypefaces["sund"].Insert(0, "Noto Sans Sundanese");
MapScriptToTypefaces["sylo"].Insert(0, "Noto Sans Syloti Nagri");
MapScriptToTypefaces["zsym"].Insert(0, "Noto Sans Symbols");
MapScriptToTypefaces["syrn"].Insert(0, "Noto Sans Syriac Eastern");
MapScriptToTypefaces["syre"].Insert(0, "Noto Sans Syriac Estrangela");
MapScriptToTypefaces["syrj"].Insert(0, "Noto Sans Syriac Western");
MapScriptToTypefaces["tglg"].Insert(0, "Noto Sans Tagalog");
MapScriptToTypefaces["tagb"].Insert(0, "Noto Sans Tagbanwa");
MapScriptToTypefaces["tale"].Insert(0, "Noto Sans Tai Le");
MapScriptToTypefaces["lana"].Insert(0, "Noto Sans Tai Tham");
MapScriptToTypefaces["tavt"].Insert(0, "Noto Sans Tai Viet");
MapScriptToTypefaces["takr"].Insert(0, "Noto Sans Takri");
MapScriptToTypefaces["taml"].Insert(0, "Noto Sans Tamil");
MapScriptToTypefaces["telu"].Insert(0, "Noto Sans Telugu");
MapScriptToTypefaces["thaa"].Insert(0, "Noto Sans Thaana");
MapScriptToTypefaces["thai"].Insert(0, "Noto Sans Thai");
MapScriptToTypefaces["tfng"].Insert(0, "Noto Sans Tifinagh");
MapScriptToTypefaces["ugar"].Insert(0, "Noto Sans Ugaritic");
MapScriptToTypefaces["vaii"].Insert(0, "Noto Sans Vai");
MapScriptToTypefaces["wcho"].Insert(0, "Noto Sans Wancho");
MapScriptToTypefaces["wara"].Insert(0, "Noto Sans Warang Citi");
MapScriptToTypefaces["yiii"].Insert(0, "Noto Sans Yi");
public static Dictionary<string, List<string>> GetDefaultAndroidFallbackMap() {
var map = new Dictionary<string, List<string>>();
ScriptUtils.FillKeysWithScripts(map, () => new List<string>());
map["zyyy"].Insert(0, "Noto Sans CJK TC"); // TODO Modify default fallback
map["zyyy"].Insert(0, "Noto Sans CJK JP");
map["zyyy"].Insert(0, "Noto Sans CJK SC");
map["zyyy"].Insert(0, "Roboto");
map["zsye"].Insert(0, "Noto Color Emoji");
map["zsye"].Add("Noto Color Emoji Flags");
map["arab"].Insert(0, "Noto Naskh Arabic");
map["adlm"].Insert(0, "Noto Sans Adlam");
map["ahom"].Insert(0, "Noto Sans Ahom");
map["hluw"].Insert(0, "Noto Sans Anatolian Hieroglyphs");
map["armn"].Insert(0, "Noto Sans Armenian");
map["avst"].Insert(0, "Noto Sans Avestan");
map["bali"].Insert(0, "Noto Sans Balinese");
map["bamu"].Insert(0, "Noto Sans Bamum");
map["bass"].Insert(0, "Noto Sans Bassa Vah");
map["batk"].Insert(0, "Noto Sans Batak");
map["beng"].Insert(0, "Noto Sans Bengali");
map["bhks"].Insert(0, "Noto Sans Bhaiksuki");
map["brah"].Insert(0, "Noto Sans Brahmi");
map["bugi"].Insert(0, "Noto Sans Buginese");
map["buhd"].Insert(0, "Noto Sans Buhid");
map["jpan"].Insert(0, "Noto Sans CJK JP");
map["kore"].Insert(0, "Noto Sans CJK KR");
map["hans"].Insert(0, "Noto Sans CJK SC");
map["hant"].Insert(0, "Noto Sans CJK TC");
map["hant"].Add("Noto Sans CJK HK");
map["cans"].Insert(0, "Noto Sans Canadian Aboriginal");
map["cari"].Insert(0, "Noto Sans Carian");
map["cakm"].Insert(0, "Noto Sans Chakma");
map["cham"].Insert(0, "Noto Sans Cham");
map["cher"].Insert(0, "Noto Sans Cherokee");
map["copt"].Insert(0, "Noto Sans Coptic");
map["xsux"].Insert(0, "Noto Sans Cuneiform");
map["cprt"].Insert(0, "Noto Sans Cypriot");
map["dsrt"].Insert(0, "Noto Sans Deseret");
map["deva"].Insert(0, "Noto Sans Devanagari");
map["egyp"].Insert(0, "Noto Sans Egyptian Hieroglyphs");
map["elba"].Insert(0, "Noto Sans Elbasan");
map["ethi"].Insert(0, "Noto Sans Ethiopic");
map["geor"].Insert(0, "Noto Sans Georgian");
map["glag"].Insert(0, "Noto Sans Glagolitic");
map["goth"].Insert(0, "Noto Sans Gothic");
map["gran"].Insert(0, "Noto Sans Grantha");
map["gujr"].Insert(0, "Noto Sans Gujarati");
map["gong"].Insert(0, "Noto Sans Gunjala Gondi");
map["guru"].Insert(0, "Noto Sans Gurmukhi");
map["rohg"].Insert(0, "Noto Sans Hanifi Rohingya");
map["hano"].Insert(0, "Noto Sans Hanunoo");
map["hatr"].Insert(0, "Noto Sans Hatran");
map["hebr"].Insert(0, "Noto Sans Hebrew");
map["armi"].Insert(0, "Noto Sans Imperial Aramaic");
map["phli"].Insert(0, "Noto Sans Inscriptional Pahlavi");
map["prti"].Insert(0, "Noto Sans Inscriptional Parthian");
map["java"].Insert(0, "Noto Sans Javanese");
map["kthi"].Insert(0, "Noto Sans Kaithi");
map["knda"].Insert(0, "Noto Sans Kannada");
map["kali"].Insert(0, "Noto Sans KayahLi");
map["khar"].Insert(0, "Noto Sans Kharoshthi");
map["khmr"].Insert(0, "Noto Sans Khmer");
map["khoj"].Insert(0, "Noto Sans Khojki");
map["laoo"].Insert(0, "Noto Sans Lao");
map["lepc"].Insert(0, "Noto Sans Lepcha");
map["limb"].Insert(0, "Noto Sans Limbu");
map["lina"].Insert(0, "Noto Sans Linear A");
map["linb"].Insert(0, "Noto Sans Linear B");
map["lisu"].Insert(0, "Noto Sans Lisu");
map["lyci"].Insert(0, "Noto Sans Lycian");
map["lydi"].Insert(0, "Noto Sans Lydian");
map["mlym"].Insert(0, "Noto Sans Malayalam");
map["mand"].Insert(0, "Noto Sans Mandiac");
map["mani"].Insert(0, "Noto Sans Manichaean");
map["marc"].Insert(0, "Noto Sans Marchen");
map["gonm"].Insert(0, "Noto Sans Masaram Gondi");
map["medf"].Insert(0, "Noto Sans Medefaidrin");
map["mtei"].Insert(0, "Noto Sans Meetei Mayek");
map["merc"].Insert(0, "Noto Sans Meroitic");
map["mero"].Insert(0, "Noto Sans Meroitic");
map["plrd"].Insert(0, "Noto Sans Miao");
map["modi"].Insert(0, "Noto Sans Modi");
map["mong"].Insert(0, "Noto Sans Mongolian");
map["mroo"].Insert(0, "Noto Sans Mro");
map["mult"].Insert(0, "Noto Sans Multani");
map["mymr"].Insert(0, "Noto Sans Myanmar");
map["nkoo"].Insert(0, "Noto Sans Nko");
map["nbat"].Insert(0, "Noto Sans Nabataean");
map["talu"].Insert(0, "Noto Sans New Tai Lue");
map["newa"].Insert(0, "Noto Sans Newa");
map["ogam"].Insert(0, "Noto Sans Ogham");
map["olck"].Insert(0, "Noto Sans Ol Chiki");
map["ital"].Insert(0, "Noto Sans Old Italian");
map["narb"].Insert(0, "Noto Sans Old North Arabian");
map["perm"].Insert(0, "Noto Sans Old Permic");
map["xpeo"].Insert(0, "Noto Sans Old Persian");
map["sarb"].Insert(0, "Noto Sans Old South Arabian");
map["orkh"].Insert(0, "Noto Sans Old Turkic");
map["orya"].Insert(0, "Noto Sans Oriya");
map["osge"].Insert(0, "Noto Sans Osage");
map["osma"].Insert(0, "Noto Sans Osmanya");
map["hmng"].Insert(0, "Noto Sans Pahawh Hmong");
map["palm"].Insert(0, "Noto Sans Palmyrene");
map["pauc"].Insert(0, "Noto Sans Pau Cin Hau");
map["phag"].Insert(0, "Noto Sans Phags Pa");
map["phnx"].Insert(0, "Noto Sans Phoenician");
map["rjng"].Insert(0, "Noto Sans Rejang");
map["runr"].Insert(0, "Noto Sans Runic");
map["samr"].Insert(0, "Noto Sans Samaritan");
map["saur"].Insert(0, "Noto Sans Saurashtra");
map["shrd"].Insert(0, "Noto Sans Sharada");
map["shaw"].Insert(0, "Noto Sans Shavian");
map["sinh"].Insert(0, "Noto Sans Sinhala");
map["sora"].Insert(0, "Noto Sans Sora Sompeng");
map["soyo"].Insert(0, "Noto Sans Soyombo");
map["sund"].Insert(0, "Noto Sans Sundanese");
map["sylo"].Insert(0, "Noto Sans Syloti Nagri");
map["zsym"].Insert(0, "Noto Sans Symbols");
map["syrn"].Insert(0, "Noto Sans Syriac Eastern");
map["syre"].Insert(0, "Noto Sans Syriac Estrangela");
map["syrj"].Insert(0, "Noto Sans Syriac Western");
map["tglg"].Insert(0, "Noto Sans Tagalog");
map["tagb"].Insert(0, "Noto Sans Tagbanwa");
map["tale"].Insert(0, "Noto Sans Tai Le");
map["lana"].Insert(0, "Noto Sans Tai Tham");
map["tavt"].Insert(0, "Noto Sans Tai Viet");
map["takr"].Insert(0, "Noto Sans Takri");
map["taml"].Insert(0, "Noto Sans Tamil");
map["telu"].Insert(0, "Noto Sans Telugu");
map["thaa"].Insert(0, "Noto Sans Thaana");
map["thai"].Insert(0, "Noto Sans Thai");
map["tfng"].Insert(0, "Noto Sans Tifinagh");
map["ugar"].Insert(0, "Noto Sans Ugaritic");
map["vaii"].Insert(0, "Noto Sans Vai");
map["wcho"].Insert(0, "Noto Sans Wancho");
map["wara"].Insert(0, "Noto Sans Warang Citi");
map["yiii"].Insert(0, "Noto Sans Yi");
return map;
}
public FallbackListFontMatcher(FontManager manager) : base(manager) { }
public override IEnumerable<Typeface> MatchScript(string script = null, bool distinctFamily = false) {

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

View File

@@ -1,4 +1,4 @@
using System.IO;
using System.IO;
using System.Linq;
namespace Cryville.Common.Font {

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Text;

View File

@@ -1,15 +1,15 @@
using System;
using System;
namespace Cryville.Common {
public struct Identifier : IEquatable<Identifier> {
public static Identifier Empty = new Identifier(0);
public int Key { get; private set; }
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
public object Name { get { return IdentifierManager.Shared.Retrieve(Key); } }
public Identifier(int key) {
Key = key;
}
public Identifier(object name) {
Key = IdentifierManager.SharedInstance.Request(name);
Key = IdentifierManager.Shared.Request(name);
}
public override bool Equals(object obj) {
if (obj == null || !(obj is Identifier)) return false;

View File

@@ -1,52 +0,0 @@
using System.Collections.Generic;
namespace Cryville.Common {
/// <summary>
/// A manager that assigns each given identifiers a unique integer ID.
/// </summary>
public class IdentifierManager {
/// <summary>
/// A shared instance of the <see cref="IdentifierManager" /> class.
/// </summary>
public static IdentifierManager SharedInstance = new IdentifierManager();
readonly Dictionary<object, int> _idents = new Dictionary<object, int>();
readonly List<object> _ids = new List<object>();
readonly object _syncRoot = new object();
/// <summary>
/// Creates an instance of the <see cref="IdentifierManager" /> class.
/// </summary>
public IdentifierManager() {
Request(this);
}
/// <summary>
/// Requests an integer ID for an identifier.
/// </summary>
/// <param name="ident">The identifier.</param>
/// <returns>The integer ID.</returns>
public int Request(object ident) {
lock (_syncRoot) {
int id;
if (!_idents.TryGetValue(ident, out id)) {
_idents.Add(ident, id = _idents.Count);
_ids.Add(ident);
}
return id;
}
}
/// <summary>
/// Retrieves the identifier assigned with an integer ID.
/// </summary>
/// <param name="id">The integer ID.</param>
/// <returns>The identifier.</returns>
public object Retrieve(int id) {
lock (_syncRoot) {
return _ids[id];
}
}
}
}

View File

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

View File

@@ -1,128 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
namespace Cryville.Common {
/// <summary>
/// A logger.
/// </summary>
public abstract class Logger {
static readonly Dictionary<string, Logger> Instances = new Dictionary<string, Logger>();
static readonly Dictionary<string, StreamWriter> Files = new Dictionary<string, StreamWriter>();
static string logPath = null;
/// <summary>
/// Sets the path where the log files shall be stored.
/// </summary>
/// <param name="path">The path.</param>
public static void SetLogPath(string path) {
logPath = path;
var dir = new DirectoryInfo(path);
if (!dir.Exists) dir.Create();
}
/// <summary>
/// Logs to the specified logger.
/// </summary>
/// <param name="key">The key of the logger.</param>
/// <param name="level">The severity level.</param>
/// <param name="module">The module that is logging.</param>
/// <param name="format">The format string.</param>
/// <param name="args">The arguments for formatting.</param>
public static void Log(string key, int level, string module, string format, params object[] args) {
if (!Instances.ContainsKey(key)) return;
Instances[key].Log(level, module, string.Format(format, args));
if (Files.ContainsKey(key)) Files[key].WriteLine("[{0:O}] [{1}] <{2}> {3}", DateTime.UtcNow, level, module, string.Format(format, args));
}
/// <summary>
/// Adds a created logger to the shared logger manager.
/// </summary>
/// <param name="key">The key of the logger.</param>
/// <param name="logger">The logger.</param>
public static void Create(string key, Logger logger) {
Instances[key] = logger;
if (logPath != null) {
Files[key] = new StreamWriter(logPath + "/" + ((int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds).ToString(CultureInfo.InvariantCulture) + "-" + key + ".log") {
AutoFlush = true
};
}
}
/// <summary>
/// Closes all loggers and related file streams.
/// </summary>
public static void Close() {
Instances.Clear();
foreach (var f in Files) f.Value.Dispose();
Files.Clear();
}
/// <summary>
/// Logs to the logger.
/// </summary>
/// <param name="level">The severity level.</param>
/// <param name="module">The module that is logging.</param>
/// <param name="msg">The message.</param>
public virtual void Log(int level, string module, string msg) { }
}
/// <summary>
/// A <see cref="Logger" /> that calls a callback function on log.
/// </summary>
public class InstantLogger : Logger {
readonly Action<int, string, string> callback;
/// <summary>
/// Creates an instance of the <see cref="InstantLogger" /> class.
/// </summary>
/// <param name="callback">The callback function.</param>
/// <exception cref="ArgumentNullException"><paramref name="callback" /> is <see langword="null" />.</exception>
public InstantLogger(Action<int, string, string> callback) {
if (callback == null)
throw new ArgumentNullException("callback");
this.callback = callback;
}
/// <inheritdoc />
public override void Log(int level, string module, string msg) {
base.Log(level, module, msg);
callback(level, module, msg);
}
}
/// <summary>
/// A <see cref="Logger" /> that buffers the logs for enumeration.
/// </summary>
public class BufferedLogger : Logger {
readonly List<LogEntry> buffer = new List<LogEntry>();
/// <summary>
/// Creates an instance of the <see cref="BufferedLogger" /> class.
/// </summary>
public BufferedLogger() { }
/// <inheritdoc />
public override void Log(int level, string module, string msg) {
base.Log(level, module, msg);
lock (buffer) {
buffer.Add(new LogEntry(level, module, msg));
}
}
/// <summary>
/// Enumerates the buffered logs.
/// </summary>
/// <param name="callback">The callback function to receive the logs.</param>
public void Enumerate(Action<int, string, string> callback) {
lock (buffer) {
foreach (var i in buffer) {
callback(i.level, i.module, i.msg);
}
}
buffer.Clear();
}
}
struct LogEntry {
public int level;
public string module;
public string msg;
public LogEntry(int level, string module, string msg) {
this.level = level;
this.module = module;
this.msg = msg;
}
}
}

View File

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

View File

@@ -1,44 +1,27 @@
using SMath = System.Math;
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;
}
float x = t, t0 = 0, t1 = 1, t2 = x;
t0 = 0; t1 = 1; t2 = x;
if (t2 < t0) return CurveY(t0, y1, y2);
if (t2 > t1) return CurveY(t1, y1, y2);
if (t2 < t0) return Curve(t0, y1, y2);
if (t2 > t1) return Curve(t1, y1, y2);
while (t0 < t1) {
tx = CurveX(t2, x1, x2);
if (SMath.Abs(tx - x) < epsilon) return CurveY(t2, y1, y2);
float tx = Curve(t2, x1, x2);
if (SMath.Abs(tx - x) < epsilon) return Curve(t2, y1, y2);
if (x > tx) t0 = t2;
else t1 = t2;
t2 = (t1 - t0) * .5f + t0;
}
return CurveY(t2, y1, y2);
return Curve(t2, y1, y2);
}
static float CurveX(float t, float x1, float x2) {
static float Curve(float t, float p1, float p2) {
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;
return 3 * v * v * t * p1 + 3 * v * t * t * p2 + t * t * t;
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace Cryville.Common.Math {
/// <summary>

View File

@@ -1,4 +1,4 @@
using UnsafeIL;
using UnsafeIL;
namespace Cryville.Common.Math {
/// <summary>

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 53f4e3167a1eee2478b0abc6302aee8f
guid: 1a624371d4108614b9cdc4acca1499e2
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,14 +1,14 @@
using Cryville.Common.Logging;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
namespace Cryville.Common.Network {
public class HttpClient {
namespace Cryville.Common.Network.Http11 {
public class Http11Client : IDisposable {
private readonly string _directHost;
protected string DirectHost { get { return _directHost; } }
@@ -18,29 +18,17 @@ namespace Cryville.Common.Network {
readonly Uri _baseUri;
readonly int origPort;
protected string Version = "HTTP/1.1";
protected const string Version = "HTTP/1.1";
protected TcpClient TcpClient { get; private set; }
protected Stream RawTcpStream {
get {
return TcpClient.GetStream();
}
}
protected virtual Stream Stream {
get {
return TcpClient.GetStream();
}
}
protected virtual string WindowsProxyProtocolName {
get {
return "http";
}
}
protected Stream RawTcpStream { get { return TcpClient.GetStream(); } }
protected virtual Stream Stream { get { return TcpClient.GetStream(); } }
protected virtual string WindowsProxyProtocolName { get { return "http"; } }
private readonly bool _proxied = false;
public Dictionary<string, string> Headers { get; set; }
public HttpClient(Uri baseUri, int port = 80) {
public Http11Client(Uri baseUri, int port = 80) {
_directHost = baseUri.Host;
_directPort = port;
_baseUri = baseUri;
@@ -60,18 +48,29 @@ namespace Cryville.Common.Network {
public virtual void Close() {
TcpClient.Close();
}
public HttpResponse Request(string method, Uri uri, string body = null, Encoding encoding = null) {
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing) {
if (disposing) {
Close();
}
}
public Http11Response Request(string method, Uri uri, string body = null, Encoding encoding = null) {
string struri = GetUri(uri).PathAndQuery;
return Request(Stream, method, struri, body, encoding);
}
public HttpResponse Request(Stream stream, string method, string uri, string body = null, Encoding encoding = null) {
var headers = new Dictionary<string, string>();
Http11Response Request(Stream stream, string method, string uri, string body = null, Encoding encoding = null) {
var headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var h in Headers)
headers.Add(h.Key, h.Value);
headers["Host"] = _baseUri.Host;
byte[] payload = new byte[0];
byte[] payload = null;
if (body != null) {
if (encoding == null)
encoding = Encoding.UTF8;
@@ -79,22 +78,24 @@ namespace Cryville.Common.Network {
headers.Add("Content-Encoding", encoding.EncodingName);
headers.Add("Content-Length", payload.Length.ToString(CultureInfo.InvariantCulture));
}
string request_line = string.Format(
"{0} {1} {2}\r\n", method, uri, Version
);
string header_fields = string.Concat((
from h in headers select h.Key + ":" + h.Value + "\r\n"
).ToArray());
byte[] buffer0 = Encoding.ASCII.GetBytes(string.Format(
"{0}{1}\r\n", request_line, header_fields
));
byte[] buffer1 = new byte[buffer0.Length + payload.Length];
Array.Copy(buffer0, buffer1, buffer0.Length);
Array.Copy(payload, 0, buffer1, buffer0.Length, payload.Length);
Logger.Log("main", 0, "Network", Encoding.UTF8.GetString(buffer1));
stream.Write(buffer1, 0, buffer1.Length);
stream.Flush();
var response = new HttpResponse(stream);
using (var writer = new StreamWriter(stream, Encoding.ASCII, 1024, true)) {
writer.Write(method);
writer.Write(' ');
writer.Write(uri);
writer.Write(' ');
writer.Write(Version);
writer.Write("\r\n");
foreach (var header in headers) {
writer.Write(header.Key);
writer.Write(':');
writer.Write(header.Value);
writer.Write("\r\n");
}
writer.Write("\r\n");
if (payload != null) writer.Write(payload);
writer.Flush();
}
var response = new Http11Response(stream);
Logger.Log("main", 0, "Network", "{0}", response);
return response;
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: ec18f22479042d747b88c093aa90c5c0
guid: 5a795e416e54c69418de1a3c27a88932
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,30 +1,41 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Cryville.Common.Network {
public class HttpResponse {
namespace Cryville.Common.Network.Http11 {
public class Http11Response : IDisposable {
static readonly char[] spchar = new char[]{ ' ' };
public string HttpVersion { get; private set; }
public string StatusCode { get; private set; }
public string ReasonPhase { get; private set; }
public Dictionary<string, string> Headers { get; private set; }
public HttpResponseStream MessageBody { get; private set; }
internal HttpResponse(Stream stream) {
public Http11ResponseStream MessageBody { get; private set; }
internal Http11Response(Stream stream) {
var reader = new BinaryReader(stream, Encoding.ASCII);
var statu_line = ReadLine(reader).Split(spchar, 3);
HttpVersion = statu_line[0];
StatusCode = statu_line[1];
ReasonPhase = statu_line[2];
Logger.Log("main", 0, "Network", "Receive Response: {0} {1} {2}", HttpVersion, StatusCode, ReasonPhase);
Headers = new Dictionary<string, string>();
Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
while (ParseHeader(reader, Headers)) ;
if (Headers.ContainsKey("content-length")) {
int length = int.Parse(Headers["content-length"]);
MessageBody = new HttpResponseBlockStream(reader, length);
MessageBody = new Http11ResponseBlockStream(reader, length);
}
else if (Headers.ContainsKey("transfer-encoding") && Headers["transfer-encoding"] == "chunked") {
MessageBody = new HttpResponseChunkedStream(reader);
MessageBody = new Http11ResponseChunkedStream(reader);
}
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing) {
if (disposing) {
MessageBody.Dispose();
}
}
@@ -36,12 +47,11 @@ namespace Cryville.Common.Network {
// TODO Multiline header
var header = ReadLine(reader);
if (header == "") return false;
var s = header.Split(':');
var s = header.Split(':', 2);
string field_name = s[0].Trim().ToLower();
string field_value = s[1].Trim();
if (headers.ContainsKey(field_name)) headers[field_name] += "," + field_value;
else headers.Add(field_name, field_value);
Logger.Log("main", 0, "Network", "Receive Header {0}: {1}", field_name, field_value);
return true;
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: df66519fa93e1b94ea5bb1702cc91b3f
guid: 71234dd1c93d47b4893750686b2333a3
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,11 +1,11 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
namespace Cryville.Common.Network {
public abstract class HttpResponseStream : Stream {
namespace Cryville.Common.Network.Http11 {
public abstract class Http11ResponseStream : Stream {
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return false; } }
@@ -36,11 +36,11 @@ namespace Cryville.Common.Network {
}
}
internal sealed class HttpResponseBlockStream : HttpResponseStream {
internal sealed class Http11ResponseBlockStream : Http11ResponseStream {
readonly BinaryReader _reader;
readonly int _length;
int _pos = 0;
internal HttpResponseBlockStream(BinaryReader reader, int length) {
internal Http11ResponseBlockStream(BinaryReader reader, int length) {
_reader = reader;
_length = length;
}
@@ -50,7 +50,6 @@ namespace Cryville.Common.Network {
if (recv_len == 0) return 0;
while (recv < recv_len) {
recv += _reader.Read(buffer, offset + recv, count - recv);
Logger.Log("main", 0, "Network", "Message body received: {0}/{1}/{2}", recv, recv_len, _length);
}
_pos += recv_len;
return recv_len;
@@ -62,36 +61,34 @@ namespace Cryville.Common.Network {
}
}
internal sealed class HttpResponseChunkedStream : HttpResponseStream {
internal sealed class Http11ResponseChunkedStream : Http11ResponseStream {
readonly BinaryReader _reader;
byte[] _chunk = null;
int _pos = 0;
internal HttpResponseChunkedStream(BinaryReader reader) {
internal Http11ResponseChunkedStream(BinaryReader reader) {
_reader = reader;
ReadChunk();
}
public void ReadChunk() {
if (_chunk != null && _chunk.Length == 0) return;
string[] chunkHeader = HttpResponse.ReadLine(_reader).Split(';');
// int chunkSize = Array.IndexOf(LEN, chunkHeader[0].ToLower()[0]);
int chunkSize = int.Parse(chunkHeader[0], NumberStyles.HexNumber);
if (chunkSize == -1)
string[] chunkHeader = Http11Response.ReadLine(_reader).Split(';');
int chunkSize;
if (!int.TryParse(chunkHeader[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out chunkSize))
throw new IOException("Corrupted chunk received");
if (chunkSize == 0) {
_chunk = new byte[0];
// TODO TE Header, now just discard
var headers = new Dictionary<string, string>();
while (HttpResponse.ParseHeader(_reader, headers)) ;
while (Http11Response.ParseHeader(_reader, headers)) ;
return;
}
_chunk = new byte[chunkSize];
int recv = 0;
while (recv < chunkSize) {
recv += _reader.Read(_chunk, recv, chunkSize - recv);
Logger.Log("main", 0, "Network", "Message chunk received: {0}/{1}", recv, chunkSize);
}
_pos = 0;
if (HttpResponse.ReadLine(_reader) != "")
if (Http11Response.ReadLine(_reader) != "")
throw new IOException("Corrupted chunk received");
}
public override int Read(byte[] buffer, int offset, int count) {
@@ -130,4 +127,4 @@ namespace Cryville.Common.Network {
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 2b7b45ff20c33ac47b476371673b037c
guid: 49a8d5b9869e5bb42bafbe71f84fecc5
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,8 +1,8 @@
using System;
using System.IO;
namespace Cryville.Common.Network {
public class HttpsClient : HttpClient {
namespace Cryville.Common.Network.Http11 {
public class Https11Client : Http11Client {
readonly TlsClient _tlsClient;
protected override Stream Stream {
@@ -16,7 +16,7 @@ namespace Cryville.Common.Network {
}
}
public HttpsClient(Uri baseUri) : base(baseUri, 443) {
public Https11Client(Uri baseUri) : base(baseUri, 443) {
_tlsClient = new TlsClient(RawTcpStream, baseUri.Host);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ using Org.BouncyCastle.Security;
using Org.BouncyCastle.Tls;
using Org.BouncyCastle.Tls.Crypto;
using Org.BouncyCastle.Tls.Crypto.Impl.BC;
using System;
using System.Collections;
using System.IO;
using System.Linq;
@@ -9,7 +10,7 @@ using System.Text;
using BcTlsClient = Org.BouncyCastle.Tls.TlsClient;
namespace Cryville.Common.Network {
public class TlsClient {
public class TlsClient : IDisposable {
readonly TlsClientProtocol _protocol;
readonly BcTlsClient _tlsClient;
public Stream Stream { get; private set; }
@@ -27,6 +28,17 @@ namespace Cryville.Common.Network {
_protocol.Close();
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing) {
if (disposing) {
Close();
}
}
private class InternalTlsClient : DefaultTlsClient {
readonly string _host;
@@ -71,20 +83,6 @@ namespace Cryville.Common.Network {
public override TlsAuthentication GetAuthentication() {
return new NullTlsAuthentication();
}
public override void NotifyAlertReceived(short alertLevel, short alertDescription) {
Logger.Log("main", 0, "Network/TLS", "TLS Alert {0} {1}", alertLevel, alertDescription);
}
public override void NotifyServerVersion(ProtocolVersion serverVersion) {
base.NotifyServerVersion(serverVersion);
Logger.Log("main", 0, "Network/TLS", "NotifyServerVersion {0}", serverVersion);
}
public override void NotifySelectedCipherSuite(int selectedCipherSuite) {
base.NotifySelectedCipherSuite(selectedCipherSuite);
Logger.Log("main", 0, "Network/TLS", "NotifySelectedCipherSuite {0}", selectedCipherSuite);
}
}
private class NullTlsAuthentication : TlsAuthentication {

View File

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

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
@@ -17,32 +17,30 @@ namespace Cryville.Common.Pdt {
readonly StackFrame[] _stack = new StackFrame[256];
readonly byte[] _mem = new byte[0x100000];
bool _revokepttconst;
LinkedListNode<PdtInstruction> _rip;
/// <summary>
/// Evaluates an expression and passes the result to a target operator.
/// </summary>
/// <param name="target">The target operator.</param>
/// <param name="exp">The expression to evaluate.</param>
public void Evaluate(PdtOperator target, PdtExpression exp) {
_framecount = 0;
_goffset = 0;
_revokepttconst = false;
for (_rip = exp.Instructions.First; _rip != null; _rip = _rip.Next)
_rip.Value.Execute(this);
Operate(target, _framecount, true);
if (exp.IsPotentialConstant) {
exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst;
/// <returns>Whether the evaluaton succeeded.</returns>
public bool Evaluate(PdtOperator target, PdtExpression exp) {
var prevFrameCount = _framecount;
try {
_revokepttconst = false;
for (var ip = exp.Instructions.First; ip != null; ip = ip.Next)
ip.Value.Execute(this, ref ip);
if (exp.IsPotentialConstant) {
exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst;
}
var ret = Operate(target, _framecount - prevFrameCount, true);
return ret;
}
catch (Exception ex) {
throw new EvaluationFailureException(exp, ex);
}
finally {
for (var i = prevFrameCount; i < _framecount; i++) DiscardStack();
}
}
/// <summary>
/// Patches an expression with a lefthand variable and a compound operator.
/// </summary>
/// <param name="target">The name of the lefthand variable.</param>
/// <param name="op">The name of the compound operator.</param>
/// <param name="exp">The expression.</param>
public void PatchCompound(int target, int op, PdtExpression exp) {
exp.Instructions.AddFirst(new PdtInstruction.PushVariable(target));
exp.Instructions.AddLast(new PdtInstruction.Operate(op, 2));
}
/// <summary>
/// Optimizes an expression by merging its instructions.
@@ -54,12 +52,14 @@ namespace Cryville.Common.Pdt {
List<PdtInstruction.Collapse> ct;
var cols = new Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>>();
var il = exp.Instructions;
for (_rip = il.First; _rip != null; _rip = _rip == null ? il.First : _rip.Next) {
var i = _rip.Value;
var ip = il.First;
while (ip != null) {
bool nextFlag = false;
var i = ip.Value;
if (i is PdtInstruction.Operate) {
int fc0 = _framecount;
int fc1 = ((PdtInstruction.Operate)i).Signature.ParamCount;
try { i.Execute(this); } catch (Exception) { }
try { i.Execute(this, ref ip); } catch (Exception) { }
if (fc0 - _framecount == fc1) {
unsafe {
fixed (StackFrame* frame = &_stack[_framecount++]) {
@@ -71,29 +71,38 @@ namespace Cryville.Common.Pdt {
}
else {
var frame = _stack[_framecount - 1];
_rip = il.AddAfter(_rip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length));
for (var j = 0; j <= fc1; j++) il.Remove(_rip.Previous);
if (frame.Type != PdtInternalType.Error) {
ReplaceIP(il, ref ip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
for (var j = 0; j < fc1; j++) il.Remove(ip.Previous);
}
}
}
else if (i is PdtInstruction.Collapse) {
var t = (PdtInstruction.Collapse)i;
try {
var pins = _rip;
i.Execute(this);
if (_rip == pins) {
_rip = _rip.Next;
il.Remove(_rip.Previous);
il.Remove(_rip.Previous);
_rip = _rip.Previous;
var pins = ip;
i.Execute(this, ref ip);
if (_stack[_framecount - 1].Type == PdtInternalType.Error) {
throw new EvaluationFailureException();
}
if (ip == pins) {
ip = ip.Next;
il.Remove(ip.Previous);
il.Remove(ip.Previous);
ip = ip.Previous;
if (ip == null) {
ip = il.First;
nextFlag = true;
}
}
else {
_rip = pins.Previous;
while (_rip.Next != t.Target) il.Remove(_rip.Next);
il.Remove(_rip.Next);
ip = pins.Previous;
while (ip.Next != t.Target) il.Remove(ip.Next);
il.Remove(ip.Next);
if (cols.TryGetValue(t.Target, out ct)) {
foreach (var u in ct) u.Target = _rip;
foreach (var u in ct) u.Target = ip;
cols.Remove(t.Target);
cols.Add(_rip, ct);
cols.Add(ip, ct);
}
}
}
@@ -103,15 +112,14 @@ namespace Cryville.Common.Pdt {
}
}
else if (i is PdtInstruction.PushVariable) {
i.Execute(this);
i.Execute(this, ref ip);
var frame = _stack[_framecount - 1];
if (frame.Type != PdtInternalType.Undefined && frame.Type != PdtInternalType.Error) {
_rip = il.AddAfter(_rip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length));
il.Remove(_rip.Previous);
ReplaceIP(il, ref ip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
}
}
else i.Execute(this);
if (_rip != null && cols.TryGetValue(_rip, out ct)) {
else i.Execute(this, ref ip);
if (ip != null && cols.TryGetValue(ip, out ct)) {
unsafe {
fixed (StackFrame* frame = &_stack[_framecount - 1]) {
frame->Type = PdtInternalType.Error;
@@ -120,19 +128,24 @@ namespace Cryville.Common.Pdt {
}
}
}
if (!nextFlag) ip = ip.Next;
}
exp.IsConstant = true;
exp.IsPotentialConstant = true;
for (var ins = il.First; ins != null; ins = ins.Next) {
if (!(ins.Value is PdtInstruction.PushConstant)) {
exp.IsConstant = false;
}
else if (!(ins.Value is PdtInstruction.PushVariable)) {
exp.IsPotentialConstant = false;
return;
break;
}
}
}
void ReplaceIP(LinkedList<PdtInstruction> il, ref LinkedListNode<PdtInstruction> ip, PdtInstruction ins, Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>> cols) {
List<PdtInstruction.Collapse> cins;
if (cols.TryGetValue(ip, out cins)) cols.Remove(ip);
ip = il.AddAfter(ip, ins);
il.Remove(ip.Previous);
if (cins != null) cols.Add(ip, cins);
}
/// <summary>
/// Revokes the potential constant mark of the current expression.
/// </summary>
@@ -184,23 +197,36 @@ namespace Cryville.Common.Pdt {
/// <returns>An operator of the specific name.</returns>
/// <remarks>The parameter count of the returned operator does not necessarily equal to <paramref name="pc" />.</remarks>
protected abstract PdtOperator GetOperator(PdtOperatorSignature sig);
unsafe void Operate(PdtOperator op, int pc, bool noset = false) {
unsafe bool Operate(PdtOperator op, int pc, bool noset = false) {
fixed (byte* pmem = _mem) {
op.Begin(this, pc);
for (int i = 0; i < pc; i++) {
var frame = _stack[--_framecount];
if (frame.Type == PdtInternalType.Error) {
_framecount -= pc - i - 1;
_stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = -1, Length = 0 };
return false;
}
op.LoadOperand(new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length));
_goffset -= frame.Length;
}
op.Call(pmem + _goffset, noset);
return true;
}
}
internal unsafe void Collapse(int name, LinkedListNode<PdtInstruction> target) {
internal unsafe void Collapse(int name, ref LinkedListNode<PdtInstruction> self, LinkedListNode<PdtInstruction> target) {
fixed (byte* pmem = _mem) {
var frame = _stack[--_framecount];
_goffset -= frame.Length;
if (frame.Type == PdtInternalType.Error) {
_stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = -1, Length = 0 };
self = target;
return;
}
if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) {
_framecount++;
_rip = target;
_goffset += frame.Length;
self = target;
}
}
}
@@ -226,7 +252,7 @@ namespace Cryville.Common.Pdt {
}
/// <summary>
/// The exception that is thrown when the evalution of a <see cref="PdtExpression" /> fails.
/// The exception that is thrown when the evaluation of a <see cref="PdtExpression" /> fails.
/// </summary>
public class EvaluationFailureException : Exception {
/// <inheritdoc />
@@ -237,5 +263,16 @@ namespace Cryville.Common.Pdt {
public EvaluationFailureException(string message, Exception innerException) : base(message, innerException) { }
/// <inheritdoc />
protected EvaluationFailureException(SerializationInfo info, StreamingContext context) : base(info, context) { }
/// <summary>
/// Creates an instance of the <see cref="EvaluationFailureException" /> class with the failing expression.
/// </summary>
/// <param name="exp">The failing expression.</param>
public EvaluationFailureException(PdtExpression exp) : base("Evaluation failed for the expression: " + exp.ToString()) { }
/// <summary>
/// Creates an instance of the <see cref="EvaluationFailureException" /> class with the failing expression and the inner exception.
/// </summary>
/// <param name="exp">The failing expression.</param>
/// <param name="innerException">The inner exception.</param>
public EvaluationFailureException(PdtExpression exp, Exception innerException) : base("Evaluation failed for the expression: " + exp.ToString(), innerException) { }
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Text;
@@ -7,6 +7,18 @@ namespace Cryville.Common.Pdt {
/// PDT expression.
/// </summary>
public class PdtExpression {
/// <summary>
/// The empty expression.
/// </summary>
public static readonly PdtExpression Empty;
static PdtExpression() {
var ins = new LinkedList<PdtInstruction>();
ins.AddLast(new PdtInstruction.PushConstant(
PdtInternalType.Number, BitConverter.GetBytes(1f)
));
Empty = new PdtExpression(ins);
}
internal LinkedList<PdtInstruction> Instructions;
/// <summary>
/// Whether the value of this expression is constant.
@@ -27,9 +39,19 @@ namespace Cryville.Common.Pdt {
}
return r;
}
/// <summary>
/// Patches an expression with a lefthand variable and a compound operator.
/// </summary>
/// <param name="target">The name of the lefthand variable.</param>
/// <param name="op">The name of the compound operator.</param>
/// <param name="exp">The expression.</param>
public static void PatchCompound(int target, int op, PdtExpression exp) {
exp.Instructions.AddFirst(new PdtInstruction.PushVariable(target));
exp.Instructions.AddLast(new PdtInstruction.Operate(op, 2));
}
}
internal abstract class PdtInstruction {
internal abstract void Execute(PdtEvaluatorBase etor);
internal abstract void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self);
public class PushConstant : PdtInstruction {
public int Type { get; private set; }
public byte[] Value { get; private set; }
@@ -42,7 +64,7 @@ namespace Cryville.Common.Pdt {
Value = new byte[len];
Array.Copy(buffer, offset, Value, 0, len);
}
internal override void Execute(PdtEvaluatorBase etor) {
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
etor.PushConstant(Type, Value);
}
public override string ToString() {
@@ -53,12 +75,12 @@ namespace Cryville.Common.Pdt {
public int Name { get; private set; }
public bool Forced { get; private set; }
public PushVariable(int name, bool forced = false) { Name = name; Forced = forced; }
public PushVariable(string name, bool forced = false) : this(IdentifierManager.SharedInstance.Request(name)) { Forced = forced; }
internal override void Execute(PdtEvaluatorBase etor) {
public PushVariable(string name, bool forced = false) : this(IdentifierManager.Shared.Request(name)) { Forced = forced; }
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
etor.PushVariable(Name, Forced);
}
public override string ToString() {
return string.Format(Forced ? "pushv ?{0}" : "pushv {0}", IdentifierManager.SharedInstance.Retrieve(Name));
return string.Format(Forced ? "pushv ?{0}" : "pushv {0}", IdentifierManager.Shared.Retrieve(Name));
}
}
public class Operate : PdtInstruction {
@@ -69,7 +91,7 @@ namespace Cryville.Common.Pdt {
public Operate(string name, int paramCount) {
Signature = new PdtOperatorSignature(name, paramCount);
}
internal override void Execute(PdtEvaluatorBase etor) {
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
etor.Operate(Signature);
}
public override string ToString() {
@@ -80,14 +102,14 @@ namespace Cryville.Common.Pdt {
public int Name { get; private set; }
public LinkedListNode<PdtInstruction> Target { get; internal set; }
public Collapse(string name, LinkedListNode<PdtInstruction> target) {
Name = IdentifierManager.SharedInstance.Request(name);
Name = IdentifierManager.Shared.Request(name);
Target = target;
}
internal override void Execute(PdtEvaluatorBase etor) {
etor.Collapse(Name, Target);
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
etor.Collapse(Name, ref self, Target);
}
public override string ToString() {
return string.Format("col {0}{{{1}}}", IdentifierManager.SharedInstance.Retrieve(Name), Target.Value);
return string.Format("col {0}{{{1}}}", IdentifierManager.Shared.Retrieve(Name), Target.Value);
}
}
}
@@ -115,15 +137,6 @@ namespace Cryville.Common.Pdt {
{ '$', -1 },
};
static readonly PdtExpression _emptyexp;
static PdtInterpreter() {
var ins = new LinkedList<PdtInstruction>();
ins.AddLast(new PdtInstruction.PushConstant(
PdtInternalType.Number, BitConverter.GetBytes(1f)
));
_emptyexp = new PdtExpression(ins);
}
PdtExpToken GetToken() {
ws();
var result = new PdtExpToken {
@@ -195,7 +208,7 @@ namespace Cryville.Common.Pdt {
default: pc++; break;
}
}
else if (OP_TYPE[t2.Value[0]] == 1) {
if (OP_TYPE[t2.Value[0]] == 1) {
colp = new Dictionary<LinkedListNode<PdtInstruction>, string> { { ins.Last, t2.Value } };
}
t1 = t2;

View File

@@ -0,0 +1,59 @@
using System;
using System.Reflection;
namespace Cryville.Common.Pdt {
/// <summary>
/// Interpreter for fragments in Property Definition Tree (PDT) file format.
/// </summary>
public class PdtFragmentInterpreter : PdtInterpreter {
public PdtFragmentInterpreter() : base(null, new EmptyBinder()) { }
/// <summary>
/// Sets the new source string for the fragment interpreter and resets the position.
/// </summary>
/// <param name="value">The new source string.</param>
public void SetSource(string value) {
Source = value;
Position = 0;
}
/// <summary>
/// The binder.
/// </summary>
public Binder Binder {
get { return _binder; }
set { _binder = value; }
}
/// <summary>
/// Reads the current character and increments the position.
/// </summary>
/// <returns>The current character.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
public new char GetChar() { return base.GetChar(); }
/// <summary>
/// Reads an identifier.
/// </summary>
/// <returns>An identifier.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
public new string GetIdentifier() { return base.GetIdentifier(); }
/// <summary>
/// Reads a number.
/// </summary>
/// <returns>A number.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
public new string GetNumber() { return base.GetNumber(); }
/// <summary>
/// Reads a string.
/// </summary>
/// <returns>A string.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
public new string GetString() { return base.GetString(); }
/// <summary>
/// Reads an expression.
/// </summary>
/// <returns>An expression.</returns>
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
public new PdtExpression GetExp() { return base.GetExp(); }
}
}

View File

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

View File

@@ -1,4 +1,4 @@
namespace Cryville.Common.Pdt {
namespace Cryville.Common.Pdt {
/// <summary>
/// The identifiers of the internal types of PDT.
/// </summary>

View File

@@ -1,10 +1,12 @@
using Cryville.Common.Collections;
using Cryville.Common.Collections;
using Cryville.Common.Logging;
using Cryville.Common.Reflection;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using CMath = System.Math;
namespace Cryville.Common.Pdt {
/// <summary>
@@ -61,12 +63,12 @@ namespace Cryville.Common.Pdt {
/// <summary>
/// The source string.
/// </summary>
public string Source { get; private set; }
Binder _binder;
public string Source { get; protected set; }
protected Binder _binder;
/// <summary>
/// The current position in the string being parsed by the interpreter.
/// </summary>
public int Position { get; private set; }
public int Position { get; protected set; }
#pragma warning disable IDE1006
/// <summary>
/// The character at the current position.
@@ -228,8 +230,8 @@ namespace Cryville.Common.Pdt {
if (!flag) throw new FormatException("Format directive not found");
}
object InterpretObject(Type type) {
var result = ReflectionHelper.InvokeEmptyConstructor(type);
bool dictflag = typeof(IDictionary).IsAssignableFrom(type);
var result = Activator.CreateInstance(type);
bool pcflag = PairCollection.IsPairCollection(type);
while (true) {
try { ws(); }
catch (IndexOutOfRangeException) { return result; }
@@ -241,69 +243,54 @@ namespace Cryville.Common.Pdt {
char c = GetChar();
switch (c) {
case '{':
if (dictflag) {
var ktype = type.GetGenericArguments()[0];
var ptype = type.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = InterpretObject(ptype);
((IDictionary)result).Add(key, value);
}
else {
MemberInfo prop = null;
bool flag = false;
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<ElementListAttribute>(type, out prop);
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
Type ptype = ReflectionHelper.GetMemberType(prop);
if (flag) {
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = InterpretObject(vtype);
collection.Add(key, value);
}
}
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
}
InterpretObjectInternal<ElementListAttribute>(pcflag, type, pkey, result, type => InterpretObject(type));
break;
case ':':
case ';':
var exp = c == ';' ? _emptyexp : GetExp();
if (dictflag) {
var ktype = type.GetGenericArguments()[0];
var vtype = type.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = _binder.ChangeType(exp, vtype, null);
((IDictionary)result).Add(key, value);
}
else {
MemberInfo prop = null;
bool flag = false;
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<PropertyListAttribute>(type, out prop);
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
var ptype = ReflectionHelper.GetMemberType(prop);
if (flag) {
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = _binder.ChangeType(exp, vtype, null);
collection.Add(key, value);
}
}
else {
object value = _binder.ChangeType(exp, ptype, null);
ReflectionHelper.SetValue(prop, result, value, _binder);
}
}
var exp = c == ';' ? PdtExpression.Empty : GetExp();
InterpretObjectInternal<PropertyListAttribute>(pcflag, type, pkey, result, type => _binder.ChangeType(exp, type, null));
break;
default:
throw new InvalidOperationException("Internal error: Invalid key interpretation");
}
}
}
void InterpretObjectInternal<T>(bool pcflag, Type type, object pkey, object result, Func<Type, object> vfunc) where T : Attribute {
if (pcflag) {
using (var collection = new PairCollection(result)) {
var ktype = type.GetGenericArguments()[0];
var ptype = type.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = vfunc(ptype);
collection.Add(key, value);
}
}
else {
MemberInfo prop = null;
bool flag = false;
if (pkey is string) prop = FieldLikeHelper.GetMember(type, (string)pkey);
if (prop == null) {
prop = FieldLikeHelper.FindMemberWithAttribute<T>(type);
flag = true;
}
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
Type ptype = FieldLikeHelper.GetMemberType(prop);
if (flag) {
var origCollection = FieldLikeHelper.GetValue(prop, result);
if (origCollection == null) {
FieldLikeHelper.SetValue(prop, result, origCollection = Activator.CreateInstance(ptype));
}
using (var collection = new PairCollection(origCollection)) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = vfunc(vtype);
collection.Add(key, value);
}
}
else FieldLikeHelper.SetValue(prop, result, vfunc(ptype), _binder);
}
}
/// <summary>
/// Interprets a key from the current position.
/// </summary>
@@ -324,13 +311,13 @@ namespace Cryville.Common.Pdt {
int pos = interpreter.Position;
if (pos >= src.Length) return "Failed to interpret the PDT: There are some missing or redundant tokens";
int lineStartPos = src.LastIndexOf('\n', pos) + 1;
int previewStartPos = src.LastIndexOf('\n', pos, 64);
int previewStartPos = src.LastIndexOf('\n', pos, CMath.Min(64, pos));
if (previewStartPos == -1) {
previewStartPos = pos - 64;
if (previewStartPos < 0) previewStartPos = 0;
}
else previewStartPos++;
int previewEndPos = src.IndexOf('\n', pos, 64);
int previewEndPos = src.IndexOf('\n', pos, CMath.Min(64, src.Length - pos));
if (previewEndPos == -1) {
previewEndPos = pos + 64;
if (previewEndPos > src.Length) previewEndPos = src.Length;

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace Cryville.Common.Pdt {
/// <summary>
@@ -91,7 +91,7 @@ namespace Cryville.Common.Pdt {
/// <param name="name">The name of the operator.</param>
/// <param name="paramCount">The parameter count.</param>
public PdtOperatorSignature(string name, int paramCount)
: this(IdentifierManager.SharedInstance.Request(name), paramCount) { }
: this(IdentifierManager.Shared.Request(name), paramCount) { }
/// <summary>
/// Creates an operator signature.
/// </summary>
@@ -113,7 +113,7 @@ namespace Cryville.Common.Pdt {
return _hash;
}
public override string ToString() {
return string.Format("{0}({1})", IdentifierManager.SharedInstance.Retrieve(Name), ParamCount);
return string.Format("{0}({1})", IdentifierManager.Shared.Retrieve(Name), ParamCount);
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using UnsafeIL;
namespace Cryville.Common.Pdt {

View File

@@ -1,186 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Cryville.Common {
/// <summary>
/// Provides a set of <see langword="static" /> methods for refletion.
/// </summary>
public static class ReflectionHelper {
static readonly Type[] emptyTypeArray = {};
/// <summary>
/// Gets the parameterless constructor of a type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>The parameterless constructor of the type.</returns>
public static ConstructorInfo GetEmptyConstructor(Type type) {
return type.GetConstructor(emptyTypeArray);
}
static readonly object[] emptyObjectArray = {};
/// <summary>
/// Invokes the parameterless constructor of a type and returns the result.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>The created instance.</returns>
public static object InvokeEmptyConstructor(Type type) {
return GetEmptyConstructor(type).Invoke(emptyObjectArray);
}
/// <summary>
/// Tries to find a member with the specified attribute type in a type.
/// </summary>
/// <typeparam name="T">The attribute type.</typeparam>
/// <param name="t">The type containing the member with the specified attribute type.</param>
/// <param name="mi">The member.</param>
/// <returns>Whether the member is found.</returns>
public static bool TryFindMemberWithAttribute<T>(Type t, out MemberInfo mi) where T : Attribute {
try {
mi = FindMemberWithAttribute<T>(t);
return true;
}
catch (MissingMemberException) {
mi = null;
return false;
}
}
/// <summary>
/// Finds a member with the specified attribute type in a type.
/// </summary>
/// <typeparam name="T">The attribute type.</typeparam>
/// <param name="type">The type containing the member with the specified attribute type.</param>
/// <returns></returns>
/// <exception cref="MissingMemberException">The member is not found or multiple members are found.</exception>
public static MemberInfo FindMemberWithAttribute<T>(Type type) where T : Attribute {
var mil = type.FindMembers(
MemberTypes.Field | MemberTypes.Property,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
(m, o) => m.GetCustomAttributes(typeof(T), true).Length != 0,
null
);
if (mil.Length != 1)
throw new MissingMemberException(type.Name, typeof(T).Name);
return mil[0];
}
/// <summary>
/// Gets whether a type is a <see cref="Dictionary{TKey, TValue}" />.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>Whether the type is a <see cref="Dictionary{TKey, TValue}" />.</returns>
public static bool IsGenericDictionary(Type type) {
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
}
/// <summary>
/// Gets the member from a type with the specified name.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="name">The name of the member.</param>
/// <returns>The member.</returns>
/// <exception cref="MissingMemberException">The member is not found or multiple members are found.</exception>
public static MemberInfo GetMember(Type type, string name) {
var mil = type.GetMember(
name,
MemberTypes.Field | MemberTypes.Property,
BindingFlags.Public | BindingFlags.Instance
);
if (mil.Length != 1)
throw new MissingMemberException(type.Name, name);
return mil[0];
}
/// <summary>
/// Gets the type of a member.
/// </summary>
/// <param name="mi">The member.</param>
/// <returns>The type of the member.</returns>
/// <exception cref="ArgumentException"><paramref name="mi" /> is not a field or a property.</exception>
public static Type GetMemberType(MemberInfo mi) {
if (mi is FieldInfo)
return ((FieldInfo)mi).FieldType;
if (mi is PropertyInfo)
return ((PropertyInfo)mi).PropertyType;
else
throw new ArgumentException("Member is not field or property.");
}
/// <summary>
/// Gets the value of a member of an object.
/// </summary>
/// <param name="mi">The member.</param>
/// <param name="obj">The object.</param>
/// <returns>The value.</returns>
/// <exception cref="ArgumentException"><paramref name="mi" /> is not a field or a property.</exception>
public static object GetValue(MemberInfo mi, object obj) {
if (mi is FieldInfo)
return ((FieldInfo)mi).GetValue(obj);
else if (mi is PropertyInfo)
return ((PropertyInfo)mi).GetValue(obj, new object[]{});
else
throw new ArgumentException();
}
/// <summary>
/// Sets the value of a member of an object.
/// </summary>
/// <param name="mi">The member.</param>
/// <param name="obj">The object.</param>
/// <param name="value">The value.</param>
/// <param name="binder">An optional binder to convert the value.</param>
/// <exception cref="ArgumentException"><paramref name="mi" /> is not a field or a property.</exception>
public static void SetValue(MemberInfo mi, object obj, object value, Binder binder = null) {
if (mi is FieldInfo)
((FieldInfo)mi).SetValue(obj, value, BindingFlags.Default, binder, null);
else if (mi is PropertyInfo)
((PropertyInfo)mi).SetValue(obj, value, BindingFlags.Default, binder, emptyObjectArray, null);
else
throw new ArgumentException();
}
/// <summary>
/// Gets all the subclasses of a type in the current app domain.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <returns>An array containing all the subclasses of the type in the current app domain.</returns>
public static Type[] GetSubclassesOf<T>() where T : class {
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
IEnumerable<Type> r = Enumerable.Empty<Type>();
foreach (var a in assemblies)
r = r.Concat(a.GetTypes().Where(
t => t.IsClass
&& !t.IsAbstract
&& t.IsSubclassOf(typeof(T))
));
return r.ToArray();
}
/// <summary>
/// Gets a simple name of a type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>A simple name of the class.</returns>
public static string GetSimpleName(Type type) {
string result = type.Name;
var typeargs = type.GetGenericArguments();
if (typeargs.Length > 0) {
result = string.Format("{0}[{1}]", result, string.Join(",", from a in typeargs select GetSimpleName(a)));
}
return result;
}
/// <summary>
/// Gets the namespace qualified name of a type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>The namespace qualified name of the class.</returns>
public static string GetNamespaceQualifiedName(Type type) {
string result = type.Namespace + "." + type.Name;
var typeargs = type.GetGenericArguments();
if (typeargs.Length > 0) {
result = string.Format("{0}[{1}]", result, string.Join(",", from a in typeargs select GetNamespaceQualifiedName(a)));
}
return result;
}
}
}

View File

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

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Text;
using System.Text.RegularExpressions;

View File

@@ -1,4 +1,4 @@
using System;
using System;
using UnityEngine;
namespace Cryville.Common.Unity {

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

View File

@@ -1,109 +0,0 @@
using System;
using UnityEngine;
namespace Cryville.Common.Unity.Input {
public delegate void InputEventDelegate(InputIdentifier id, InputVector vec);
public abstract class InputHandler : IDisposable {
InputEventDelegate m_onInput;
public event InputEventDelegate OnInput {
add {
if (m_onInput == null) Activate();
m_onInput -= value;
m_onInput += value;
}
remove {
if (m_onInput == null) return;
m_onInput -= value;
if (m_onInput == null) Deactivate();
}
}
~InputHandler() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract void Activate();
protected abstract void Deactivate();
public abstract void Dispose(bool disposing);
public abstract bool IsNullable(int type);
public abstract byte GetDimension(int type);
public abstract string GetTypeName(int type);
public abstract double GetCurrentTimestamp();
protected void Feed(int type, int id, InputVector vec) {
var del = m_onInput;
if (del != null) del(new InputIdentifier { Source = new InputSource { Handler = this, Type = type }, Id = id }, vec);
}
}
public struct InputSource : IEquatable<InputSource> {
public InputHandler Handler { get; set; }
public int Type { get; set; }
public override bool Equals(object obj) {
if (obj == null || !(obj is InputSource)) return false;
return Equals((InputSource)obj);
}
public bool Equals(InputSource other) {
return Handler == other.Handler && Type == other.Type;
}
public override int GetHashCode() {
return Handler.GetHashCode() ^ Type;
}
public override string ToString() {
return string.Format("{0}:{1}", ReflectionHelper.GetSimpleName(Handler.GetType()), Handler.GetTypeName(Type));
}
public static bool operator ==(InputSource lhs, InputSource rhs) {
return lhs.Equals(rhs);
}
public static bool operator !=(InputSource lhs, InputSource rhs) {
return !lhs.Equals(rhs);
}
}
public struct InputIdentifier : IEquatable<InputIdentifier> {
public InputSource Source { get; set; }
public int Id { get; set; }
public override bool Equals(object obj) {
if (obj == null || !(obj is InputIdentifier)) return false;
return Equals((InputIdentifier)obj);
}
public bool Equals(InputIdentifier other) {
return Source == other.Source && Id == other.Id;
}
public override int GetHashCode() {
return Source.GetHashCode() ^ ((Id << 16) | (Id >> 16));
}
public override string ToString() {
return string.Format("{0},{1}", Source, Id);
}
public static bool operator ==(InputIdentifier lhs, InputIdentifier rhs) {
return lhs.Equals(rhs);
}
public static bool operator !=(InputIdentifier lhs, InputIdentifier rhs) {
return !lhs.Equals(rhs);
}
}
public struct InputVector {
public double Time { get; set; }
public bool IsNull { get; set; }
public Vector3 Vector { get; set; }
public InputVector(double time) {
Time = time;
IsNull = true;
Vector = default(Vector3);
}
public InputVector(double time, Vector3 vector) {
Time = time;
IsNull = false;
Vector = vector;
}
public override string ToString() {
if (IsNull) return string.Format("null@{0}", Time);
else return string.Format("{0}@{1}", Vector.ToString("G9"), Time);
}
}
}

View File

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

View File

@@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Cryville.Common.Unity.Input {
public class InputManager {
static readonly HashSet<Type> HandlerRegistries = new HashSet<Type> {
typeof(WindowsPointerHandler),
typeof(UnityKeyHandler<UnityKeyboardReceiver>),
typeof(UnityKeyHandler<UnityMouseButtonReceiver>),
typeof(UnityMouseHandler),
typeof(UnityTouchHandler),
};
readonly HashSet<InputHandler> _handlers = new HashSet<InputHandler>();
readonly Dictionary<Type, InputHandler> _typemap = new Dictionary<Type, InputHandler>();
public InputManager() {
foreach (var t in HandlerRegistries) {
try {
if (!typeof(InputHandler).IsAssignableFrom(t)) continue;
var h = (InputHandler)ReflectionHelper.InvokeEmptyConstructor(t);
_typemap.Add(t, h);
_handlers.Add(h);
Logger.Log("main", 1, "Input", "Initialized {0}", ReflectionHelper.GetSimpleName(t));
}
catch (TargetInvocationException ex) {
Logger.Log("main", 1, "Input", "Cannot initialize {0}: {1}", ReflectionHelper.GetSimpleName(t), ex.InnerException.Message);
}
}
}
public InputHandler GetHandler(string name) {
return _typemap[Type.GetType(name)];
}
public void EnumerateHandlers(Action<InputHandler> cb) {
foreach (var h in _handlers) cb(h);
}
}
public struct InputEvent {
public InputIdentifier Id { get; set; }
public InputVector From { get; set; }
public InputVector To { get; set; }
public override string ToString() {
return string.Format("[{0}] {1} -> {2}", Id, From, To);
}
}
}

View File

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

View File

@@ -1,528 +0,0 @@
namespace Cryville.Common.Unity.Input {
public enum WindowMessages : uint {
WM_NULL = 0x0000,
WM_CREATE = 0x0001,
WM_DESTROY = 0x0002,
WM_MOVE = 0x0003,
WM_SIZE = 0x0005,
WM_ACTIVATE = 0x0006,
/*
* WM_ACTIVATE state values
*/
WA_INACTIVE = 0,
WA_ACTIVE = 1,
WA_CLICKACTIVE = 2,
WM_SETFOCUS = 0x0007,
WM_KILLFOCUS = 0x0008,
WM_ENABLE = 0x000A,
WM_SETREDRAW = 0x000B,
WM_SETTEXT = 0x000C,
WM_GETTEXT = 0x000D,
WM_GETTEXTLENGTH = 0x000E,
WM_PAINT = 0x000F,
WM_CLOSE = 0x0010,
//#ifndef _WIN32_WCE
WM_QUERYENDSESSION = 0x0011,
WM_QUERYOPEN = 0x0013,
WM_ENDSESSION = 0x0016,
//#endif
WM_QUIT = 0x0012,
WM_ERASEBKGND = 0x0014,
WM_SYSCOLORCHANGE = 0x0015,
WM_SHOWWINDOW = 0x0018,
WM_WININICHANGE = 0x001A,
//#if(WINVER >= 0x0400)
WM_SETTINGCHANGE = WM_WININICHANGE,
//#endif /* WINVER >= 0x0400 */
WM_DEVMODECHANGE = 0x001B,
WM_ACTIVATEAPP = 0x001C,
WM_FONTCHANGE = 0x001D,
WM_TIMECHANGE = 0x001E,
WM_CANCELMODE = 0x001F,
WM_SETCURSOR = 0x0020,
WM_MOUSEACTIVATE = 0x0021,
WM_CHILDACTIVATE = 0x0022,
WM_QUEUESYNC = 0x0023,
WM_GETMINMAXINFO = 0x0024,
WM_PAINTICON = 0x0026,
WM_ICONERASEBKGND = 0x0027,
WM_NEXTDLGCTL = 0x0028,
WM_SPOOLERSTATUS = 0x002A,
WM_DRAWITEM = 0x002B,
WM_MEASUREITEM = 0x002C,
WM_DELETEITEM = 0x002D,
WM_VKEYTOITEM = 0x002E,
WM_CHARTOITEM = 0x002F,
WM_SETFONT = 0x0030,
WM_GETFONT = 0x0031,
WM_SETHOTKEY = 0x0032,
WM_GETHOTKEY = 0x0033,
WM_QUERYDRAGICON = 0x0037,
WM_COMPAREITEM = 0x0039,
//#if(WINVER >= 0x0500)
//#ifndef _WIN32_WCE
WM_GETOBJECT = 0x003D,
//#endif
//#endif /* WINVER >= 0x0500 */
WM_COMPACTING = 0x0041,
WM_COMMNOTIFY = 0x0044, /* no longer suported */
WM_WINDOWPOSCHANGING = 0x0046,
WM_WINDOWPOSCHANGED = 0x0047,
WM_POWER = 0x0048,
/*
* wParam for WM_POWER window message and DRV_POWER driver notification
*/
/*PWR_OK = 1,
PWR_FAIL = (-1),
PWR_SUSPENDREQUEST = 1,
PWR_SUSPENDRESUME = 2,
PWR_CRITICALRESUME = 3,*/
WM_COPYDATA = 0x004A,
WM_CANCELJOURNAL = 0x004B,
//#if(WINVER >= 0x0400)
WM_NOTIFY = 0x004E,
WM_INPUTLANGCHANGEREQUEST = 0x0050,
WM_INPUTLANGCHANGE = 0x0051,
WM_TCARD = 0x0052,
WM_HELP = 0x0053,
WM_USERCHANGED = 0x0054,
WM_NOTIFYFORMAT = 0x0055,
NFR_ANSI = 1,
NFR_UNICODE = 2,
NF_QUERY = 3,
NF_REQUERY = 4,
WM_CONTEXTMENU = 0x007B,
WM_STYLECHANGING = 0x007C,
WM_STYLECHANGED = 0x007D,
WM_DISPLAYCHANGE = 0x007E,
WM_GETICON = 0x007F,
WM_SETICON = 0x0080,
//#endif /* WINVER >= 0x0400 */
WM_NCCREATE = 0x0081,
WM_NCDESTROY = 0x0082,
WM_NCCALCSIZE = 0x0083,
WM_NCHITTEST = 0x0084,
WM_NCPAINT = 0x0085,
WM_NCACTIVATE = 0x0086,
WM_GETDLGCODE = 0x0087,
//#ifndef _WIN32_WCE
WM_SYNCPAINT = 0x0088,
//#endif
WM_NCMOUSEMOVE = 0x00A0,
WM_NCLBUTTONDOWN = 0x00A1,
WM_NCLBUTTONUP = 0x00A2,
WM_NCLBUTTONDBLCLK = 0x00A3,
WM_NCRBUTTONDOWN = 0x00A4,
WM_NCRBUTTONUP = 0x00A5,
WM_NCRBUTTONDBLCLK = 0x00A6,
WM_NCMBUTTONDOWN = 0x00A7,
WM_NCMBUTTONUP = 0x00A8,
WM_NCMBUTTONDBLCLK = 0x00A9,
//#if(_WIN32_WINNT >= 0x0500)
WM_NCXBUTTONDOWN = 0x00AB,
WM_NCXBUTTONUP = 0x00AC,
WM_NCXBUTTONDBLCLK = 0x00AD,
//#endif /* _WIN32_WINNT >= 0x0500 */
//#if(_WIN32_WINNT >= 0x0501)
WM_INPUT_DEVICE_CHANGE = 0x00FE,
//#endif /* _WIN32_WINNT >= 0x0501 */
//#if(_WIN32_WINNT >= 0x0501)
WM_INPUT = 0x00FF,
//#endif /* _WIN32_WINNT >= 0x0501 */
WM_KEYFIRST = 0x0100,
WM_KEYDOWN = 0x0100,
WM_KEYUP = 0x0101,
WM_CHAR = 0x0102,
WM_DEADCHAR = 0x0103,
WM_SYSKEYDOWN = 0x0104,
WM_SYSKEYUP = 0x0105,
WM_SYSCHAR = 0x0106,
WM_SYSDEADCHAR = 0x0107,
//#if(_WIN32_WINNT >= 0x0501)
WM_UNICHAR = 0x0109,
WM_KEYLAST = 0x0109,
UNICODE_NOCHAR = 0xFFFF,
//#else
WM_KEYLAST__WIN2000 = 0x0108,
//#endif /* _WIN32_WINNT >= 0x0501 */
//#if(WINVER >= 0x0400)
WM_IME_STARTCOMPOSITION = 0x010D,
WM_IME_ENDCOMPOSITION = 0x010E,
WM_IME_COMPOSITION = 0x010F,
WM_IME_KEYLAST = 0x010F,
//#endif /* WINVER >= 0x0400 */
WM_INITDIALOG = 0x0110,
WM_COMMAND = 0x0111,
WM_SYSCOMMAND = 0x0112,
WM_TIMER = 0x0113,
WM_HSCROLL = 0x0114,
WM_VSCROLL = 0x0115,
WM_INITMENU = 0x0116,
WM_INITMENUPOPUP = 0x0117,
//#if(WINVER >= 0x0601)
WM_GESTURE = 0x0119,
WM_GESTURENOTIFY = 0x011A,
//#endif /* WINVER >= 0x0601 */
WM_MENUSELECT = 0x011F,
WM_MENUCHAR = 0x0120,
WM_ENTERIDLE = 0x0121,
//#if(WINVER >= 0x0500)
//#ifndef _WIN32_WCE
WM_MENURBUTTONUP = 0x0122,
WM_MENUDRAG = 0x0123,
WM_MENUGETOBJECT = 0x0124,
WM_UNINITMENUPOPUP = 0x0125,
WM_MENUCOMMAND = 0x0126,
//#ifndef _WIN32_WCE
//#if(_WIN32_WINNT >= 0x0500)
WM_CHANGEUISTATE = 0x0127,
WM_UPDATEUISTATE = 0x0128,
WM_QUERYUISTATE = 0x0129,
/*
* LOWORD(wParam) values in WM_*UISTATE*
*/
UIS_SET = 1,
UIS_CLEAR = 2,
UIS_INITIALIZE = 3,
/*
* HIWORD(wParam) values in WM_*UISTATE*
*/
UISF_HIDEFOCUS = 0x1,
UISF_HIDEACCEL = 0x2,
//#if(_WIN32_WINNT >= 0x0501)
UISF_ACTIVE = 0x4,
//#endif /* _WIN32_WINNT >= 0x0501 */
//#endif /* _WIN32_WINNT >= 0x0500 */
//#endif
//#endif
//#endif /* WINVER >= 0x0500 */
WM_CTLCOLORMSGBOX = 0x0132,
WM_CTLCOLOREDIT = 0x0133,
WM_CTLCOLORLISTBOX = 0x0134,
WM_CTLCOLORBTN = 0x0135,
WM_CTLCOLORDLG = 0x0136,
WM_CTLCOLORSCROLLBAR = 0x0137,
WM_CTLCOLORSTATIC = 0x0138,
MN_GETHMENU = 0x01E1,
WM_MOUSEFIRST = 0x0200,
WM_MOUSEMOVE = 0x0200,
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_LBUTTONDBLCLK = 0x0203,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_RBUTTONDBLCLK = 0x0206,
WM_MBUTTONDOWN = 0x0207,
WM_MBUTTONUP = 0x0208,
WM_MBUTTONDBLCLK = 0x0209,
//#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
WM_MOUSEWHEEL = 0x020A,
//#endif
//#if (_WIN32_WINNT >= 0x0500)
WM_XBUTTONDOWN = 0x020B,
WM_XBUTTONUP = 0x020C,
WM_XBUTTONDBLCLK = 0x020D,
//#endif
//#if (_WIN32_WINNT >= 0x0600)
WM_MOUSEHWHEEL = 0x020E,
//#endif
//#if (_WIN32_WINNT >= 0x0600)
WM_MOUSELAST = 0x020E,
//#elif (_WIN32_WINNT >= 0x0500)
WM_MOUSELAST__WIN2000 = 0x020D,
//#elif (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
WM_MOUSELAST__WIN4 = 0x020A,
//#else
WM_MOUSELAST__WIN3 = 0x0209,
//#endif /* (_WIN32_WINNT >= 0x0600) */
//#if(_WIN32_WINNT >= 0x0400)
/* Value for rolling one detent */
WHEEL_DELTA = 120,
//GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
/* Setting to scroll one page for SPI_GET/SETWHEELSCROLLLINES */
WHEEL_PAGESCROLL = (uint.MaxValue),
//#endif /* _WIN32_WINNT >= 0x0400 */
//#if(_WIN32_WINNT >= 0x0500)
//GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
//GET_NCHITTEST_WPARAM(wParam) ((short)LOWORD(wParam))
//GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
/* XButton values are WORD flags */
XBUTTON1 = 0x0001,
XBUTTON2 = 0x0002,
/* Were there to be an XBUTTON3, its value would be 0x0004 */
//#endif /* _WIN32_WINNT >= 0x0500 */
WM_PARENTNOTIFY = 0x0210,
WM_ENTERMENULOOP = 0x0211,
WM_EXITMENULOOP = 0x0212,
//#if(WINVER >= 0x0400)
WM_NEXTMENU = 0x0213,
WM_SIZING = 0x0214,
WM_CAPTURECHANGED = 0x0215,
WM_MOVING = 0x0216,
WM_POWERBROADCAST = 0x0218,
//#endif /* WINVER >= 0x0400 */
//#if(WINVER >= 0x0400)
WM_DEVICECHANGE = 0x0219,
//#endif /* WINVER >= 0x0400 */
WM_MDICREATE = 0x0220,
WM_MDIDESTROY = 0x0221,
WM_MDIACTIVATE = 0x0222,
WM_MDIRESTORE = 0x0223,
WM_MDINEXT = 0x0224,
WM_MDIMAXIMIZE = 0x0225,
WM_MDITILE = 0x0226,
WM_MDICASCADE = 0x0227,
WM_MDIICONARRANGE = 0x0228,
WM_MDIGETACTIVE = 0x0229,
WM_MDISETMENU = 0x0230,
WM_ENTERSIZEMOVE = 0x0231,
WM_EXITSIZEMOVE = 0x0232,
WM_DROPFILES = 0x0233,
WM_MDIREFRESHMENU = 0x0234,
//#if(WINVER >= 0x0602)
WM_POINTERDEVICECHANGE = 0x238,
WM_POINTERDEVICEINRANGE = 0x239,
WM_POINTERDEVICEOUTOFRANGE = 0x23A,
//#endif /* WINVER >= 0x0602 */
//#if(WINVER >= 0x0601)
WM_TOUCH = 0x0240,
//#endif /* WINVER >= 0x0601 */
//#if(WINVER >= 0x0602)
WM_NCPOINTERUPDATE = 0x0241,
WM_NCPOINTERDOWN = 0x0242,
WM_NCPOINTERUP = 0x0243,
WM_POINTERUPDATE = 0x0245,
WM_POINTERDOWN = 0x0246,
WM_POINTERUP = 0x0247,
WM_POINTERENTER = 0x0249,
WM_POINTERLEAVE = 0x024A,
WM_POINTERACTIVATE = 0x024B,
WM_POINTERCAPTURECHANGED = 0x024C,
WM_TOUCHHITTESTING = 0x024D,
WM_POINTERWHEEL = 0x024E,
WM_POINTERHWHEEL = 0x024F,
DM_POINTERHITTEST = 0x0250,
WM_POINTERROUTEDTO = 0x0251,
WM_POINTERROUTEDAWAY = 0x0252,
WM_POINTERROUTEDRELEASED = 0x0253,
//#endif /* WINVER >= 0x0602 */
//#if(WINVER >= 0x0400)
WM_IME_SETCONTEXT = 0x0281,
WM_IME_NOTIFY = 0x0282,
WM_IME_CONTROL = 0x0283,
WM_IME_COMPOSITIONFULL = 0x0284,
WM_IME_SELECT = 0x0285,
WM_IME_CHAR = 0x0286,
//#endif /* WINVER >= 0x0400 */
//#if(WINVER >= 0x0500)
WM_IME_REQUEST = 0x0288,
//#endif /* WINVER >= 0x0500 */
//#if(WINVER >= 0x0400)
WM_IME_KEYDOWN = 0x0290,
WM_IME_KEYUP = 0x0291,
//#endif /* WINVER >= 0x0400 */
//#if((_WIN32_WINNT >= 0x0400) || (WINVER >= 0x0500))
WM_MOUSEHOVER = 0x02A1,
WM_MOUSELEAVE = 0x02A3,
//#endif
//#if(WINVER >= 0x0500)
WM_NCMOUSEHOVER = 0x02A0,
WM_NCMOUSELEAVE = 0x02A2,
//#endif /* WINVER >= 0x0500 */
//#if(_WIN32_WINNT >= 0x0501)
WM_WTSSESSION_CHANGE = 0x02B1,
WM_TABLET_FIRST = 0x02c0,
WM_TABLET_LAST = 0x02df,
//#endif /* _WIN32_WINNT >= 0x0501 */
//#if(WINVER >= 0x0601)
WM_DPICHANGED = 0x02E0,
//#endif /* WINVER >= 0x0601 */
//#if(WINVER >= 0x0605)
WM_DPICHANGED_BEFOREPARENT = 0x02E2,
WM_DPICHANGED_AFTERPARENT = 0x02E3,
WM_GETDPISCALEDSIZE = 0x02E4,
//#endif /* WINVER >= 0x0605 */
WM_CUT = 0x0300,
WM_COPY = 0x0301,
WM_PASTE = 0x0302,
WM_CLEAR = 0x0303,
WM_UNDO = 0x0304,
WM_RENDERFORMAT = 0x0305,
WM_RENDERALLFORMATS = 0x0306,
WM_DESTROYCLIPBOARD = 0x0307,
WM_DRAWCLIPBOARD = 0x0308,
WM_PAINTCLIPBOARD = 0x0309,
WM_VSCROLLCLIPBOARD = 0x030A,
WM_SIZECLIPBOARD = 0x030B,
WM_ASKCBFORMATNAME = 0x030C,
WM_CHANGECBCHAIN = 0x030D,
WM_HSCROLLCLIPBOARD = 0x030E,
WM_QUERYNEWPALETTE = 0x030F,
WM_PALETTEISCHANGING = 0x0310,
WM_PALETTECHANGED = 0x0311,
WM_HOTKEY = 0x0312,
//#if(WINVER >= 0x0400)
WM_PRINT = 0x0317,
WM_PRINTCLIENT = 0x0318,
//#endif /* WINVER >= 0x0400 */
//#if(_WIN32_WINNT >= 0x0500)
WM_APPCOMMAND = 0x0319,
//#endif /* _WIN32_WINNT >= 0x0500 */
//#if(_WIN32_WINNT >= 0x0501)
WM_THEMECHANGED = 0x031A,
//#endif /* _WIN32_WINNT >= 0x0501 */
//#if(_WIN32_WINNT >= 0x0501)
WM_CLIPBOARDUPDATE = 0x031D,
//#endif /* _WIN32_WINNT >= 0x0501 */
//#if(_WIN32_WINNT >= 0x0600)
WM_DWMCOMPOSITIONCHANGED = 0x031E,
WM_DWMNCRENDERINGCHANGED = 0x031F,
WM_DWMCOLORIZATIONCOLORCHANGED= 0x0320,
WM_DWMWINDOWMAXIMIZEDCHANGE = 0x0321,
//#endif /* _WIN32_WINNT >= 0x0600 */
//#if(_WIN32_WINNT >= 0x0601)
WM_DWMSENDICONICTHUMBNAIL = 0x0323,
WM_DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326,
//#endif /* _WIN32_WINNT >= 0x0601 */
//#if(WINVER >= 0x0600)
WM_GETTITLEBARINFOEX = 0x033F,
//#endif /* WINVER >= 0x0600 */
//#if(WINVER >= 0x0400)
//#endif /* WINVER >= 0x0400 */
//#if(WINVER >= 0x0400)
WM_HANDHELDFIRST = 0x0358,
WM_HANDHELDLAST = 0x035F,
WM_AFXFIRST = 0x0360,
WM_AFXLAST = 0x037F,
//#endif /* WINVER >= 0x0400 */
WM_PENWINFIRST = 0x0380,
WM_PENWINLAST = 0x038F,
//#if(WINVER >= 0x0400)
WM_APP = 0x8000,
//#endif /* WINVER >= 0x0400 */
/*
* NOTE: All Message Numbers below 0x0400 are RESERVED.
*
* Private Window Messages Start Here:
*/
WM_USER = 0x0400,
//#if(WINVER >= 0x0400)
/* wParam for WM_SIZING message */
WMSZ_LEFT = 1,
WMSZ_RIGHT = 2,
WMSZ_TOP = 3,
WMSZ_TOPLEFT = 4,
WMSZ_TOPRIGHT = 5,
WMSZ_BOTTOM = 6,
WMSZ_BOTTOMLEFT = 7,
WMSZ_BOTTOMRIGHT = 8,
//#endif /* WINVER >= 0x0400 */
//#ifndef NONCMESSAGES
/*
* WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes
*/
/*HTERROR = (-2),
HTTRANSPARENT = (-1),
HTNOWHERE = 0,
HTCLIENT = 1,
HTCAPTION = 2,
HTSYSMENU = 3,
HTGROWBOX = 4,
HTSIZE = HTGROWBOX,
HTMENU = 5,
HTHSCROLL = 6,
HTVSCROLL = 7,
HTMINBUTTON = 8,
HTMAXBUTTON = 9,
HTLEFT = 10,
HTRIGHT = 11,
HTTOP = 12,
HTTOPLEFT = 13,
HTTOPRIGHT = 14,
HTBOTTOM = 15,
HTBOTTOMLEFT = 16,
HTBOTTOMRIGHT = 17,
HTBORDER = 18,
HTREDUCE = HTMINBUTTON,
HTZOOM = HTMAXBUTTON,
HTSIZEFIRST = HTLEFT,
HTSIZELAST = HTBOTTOMRIGHT,
//#if(WINVER >= 0x0400)
HTOBJECT = 19,
HTCLOSE = 20,
HTHELP = 21,
//#endif /* WINVER >= 0x0400 */
}
}

View File

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

View File

@@ -1,252 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Cryville.Common.Unity.Input {
static class NativeMethods {
[StructLayout(LayoutKind.Sequential)]
public struct MONITORINFO {
public int cbSize;
public RECT rcMonitor;
public RECT rcWork;
public uint dwFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int Left, Top, Right, Bottom;
public RECT(int left, int top, int right, int bottom) {
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public int X {
get { return Left; }
set {
Right -= (Left - value);
Left = value;
}
}
public int Y {
get { return Top; }
set {
Bottom -= (Top - value);
Top = value;
}
}
public int Height {
get { return Bottom - Top; }
set { Bottom = value + Top; }
}
public int Width {
get { return Right - Left; }
set { Right = value + Left; }
}
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetTouchInputInfo(IntPtr hTouchInput, int cInputs, [Out] TOUCHINPUT[] pInputs, int cbSize);
[StructLayout(LayoutKind.Sequential)]
public struct TOUCHINPUT {
public int x;
public int y;
public IntPtr hSource;
public int dwID;
public TOUCHINPUT_Flags dwFlags;
public TOUCHINPUT_Mask dwMask;
public int dwTime;
public IntPtr dwExtraInfo;
public int cxContact;
public int cyContact;
}
[Flags]
public enum TOUCHINPUT_Flags : int {
TOUCHEVENTF_MOVE = 0x0001,
TOUCHEVENTF_DOWN = 0x0002,
TOUCHEVENTF_UP = 0x0004,
TOUCHEVENTF_INRANGE = 0x0008,
TOUCHEVENTF_PRIMARY = 0x0010,
TOUCHEVENTF_NOCOALESCE = 0x0020,
TOUCHEVENTF_PEN = 0x0040,
TOUCHEVENTF_PALM = 0x0080,
}
[Flags]
public enum TOUCHINPUT_Mask : int {
TOUCHINPUTMASKF_CONTACTAREA = 0x0004,
TOUCHINPUTMASKF_EXTRAINFO = 0x0002,
TOUCHINPUTMASKF_TIMEFROMSYSTEM = 0x0001,
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPointerInfo(int pointerID, ref POINTER_INFO pPointerInfo);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct POINTER_INFO {
public POINTER_INPUT_TYPE pointerType;
public UInt32 pointerId;
public UInt32 frameId;
public POINTER_FLAGS pointerFlags;
public IntPtr sourceDevice;
public IntPtr hwndTarget;
public POINT ptPixelLocation;
public POINT ptHimetricLocation;
public POINT ptPixelLocationRaw;
public POINT ptHimetricLocationRaw;
public UInt32 dwTime;
public UInt32 historyCount;
public Int32 inputData;
public UInt32 dwKeyStates;
public UInt64 PerformanceCount;
public POINTER_BUTTON_CHANGE_TYPE ButtonChangeType;
}
public enum POINTER_INPUT_TYPE {
PT_POINTER = 0x00000001,
PT_TOUCH = 0x00000002,
PT_PEN = 0x00000003,
PT_MOUSE = 0x00000004,
PT_TOUCHPAD = 0x00000005,
}
[Flags]
public enum POINTER_FLAGS {
POINTER_FLAG_NONE = 0x00000000,
POINTER_FLAG_NEW = 0x00000001,
POINTER_FLAG_INRANGE = 0x00000002,
POINTER_FLAG_INCONTACT = 0x00000004,
POINTER_FLAG_FIRSTBUTTON = 0x00000010,
POINTER_FLAG_SECONDBUTTON = 0x00000020,
POINTER_FLAG_THIRDBUTTON = 0x00000040,
POINTER_FLAG_FOURTHBUTTON = 0x00000080,
POINTER_FLAG_FIFTHBUTTON = 0x00000100,
POINTER_FLAG_PRIMARY = 0x00002000,
POINTER_FLAG_CONFIDENCE = 0x00004000,
POINTER_FLAG_CANCELED = 0x00008000,
POINTER_FLAG_DOWN = 0x00010000,
POINTER_FLAG_UPDATE = 0x00020000,
POINTER_FLAG_UP = 0x00040000,
POINTER_FLAG_WHEEL = 0x00080000,
POINTER_FLAG_HWHEEL = 0x00100000,
POINTER_FLAG_CAPTURECHANGED = 0x00200000,
POINTER_FLAG_HASTRANSFORM = 0x00400000,
}
public enum POINTER_BUTTON_CHANGE_TYPE {
POINTER_CHANGE_NONE,
POINTER_CHANGE_FIRSTBUTTON_DOWN,
POINTER_CHANGE_FIRSTBUTTON_UP,
POINTER_CHANGE_SECONDBUTTON_DOWN,
POINTER_CHANGE_SECONDBUTTON_UP,
POINTER_CHANGE_THIRDBUTTON_DOWN,
POINTER_CHANGE_THIRDBUTTON_UP,
POINTER_CHANGE_FOURTHBUTTON_DOWN,
POINTER_CHANGE_FOURTHBUTTON_UP,
POINTER_CHANGE_FIFTHBUTTON_DOWN,
POINTER_CHANGE_FIFTHBUTTON_UP,
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT {
public int X;
public int Y;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPointerTouchInfo(int pointerId, ref POINTER_TOUCH_INFO touchInfo);
[StructLayout(LayoutKind.Sequential)]
public struct POINTER_TOUCH_INFO {
public POINTER_INFO pointerInfo;
public TOUCH_FLAGS touchFlags;
public TOUCH_MASK touchMask;
public RECT rcContact;
public RECT rcContactRaw;
public uint orientation;
public uint pressure;
}
[Flags]
public enum TOUCH_FLAGS {
TOUCH_FLAG_NONE = 0x00000000,
}
[Flags]
public enum TOUCH_MASK {
TOUCH_MASK_NONE = 0x00000000,
TOUCH_MASK_CONTACTAREA = 0x00000001,
TOUCH_MASK_ORIENTATION = 0x00000002,
TOUCH_MASK_PRESSURE = 0x00000004,
}
[DllImport("user32.dll")]
public static extern IntPtr EnableMouseInPointer(bool value);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
public delegate bool EnumWindowsProc(IntPtr hWnd,IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumThreadWindows(uint dwThreadId, EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
[DllImport("user32.dll")]
public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
public static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
public static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint msg, IntPtr wParam,
IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterTouchWindow(IntPtr hWnd, TOUCH_WINDOW_FLAGS ulFlags);
[Flags]
public enum TOUCH_WINDOW_FLAGS {
TWF_FINETOUCH = 1,
TWF_WANTPALM = 2,
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnregisterTouchWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern void CloseTouchInputHandle(IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
public static extern ushort GlobalAddAtom(string lpString);
[DllImport("Kernel32.dll")]
public static extern ushort GlobalDeleteAtom(ushort nAtom);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int SetProp(IntPtr hWnd, string lpString, int hData);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int RemoveProp(IntPtr hWnd, string lpString);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern uint QueryPerformanceFrequency(out Int64 lpFrequency);
[DllImport("kernel32.dll")]
public static extern uint QueryPerformanceCounter(out Int64 lpPerformanceCount);
}
}

View File

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

View File

@@ -1,49 +0,0 @@
using System;
using System.Collections.Generic;
namespace Cryville.Common.Unity.Input {
public class SimpleInputConsumer {
readonly InputManager _manager;
readonly object _lock = new object();
readonly Dictionary<InputIdentifier, InputVector> _vectors = new Dictionary<InputIdentifier, InputVector>();
readonly List<InputEvent> _events = new List<InputEvent>();
public SimpleInputConsumer(InputManager manager) { _manager = manager; }
public void Activate() {
lock (_lock) {
_events.Clear();
}
_manager.EnumerateHandlers(h => h.OnInput += OnInput);
}
public void Deactivate() {
_manager.EnumerateHandlers(h => h.OnInput -= OnInput);
}
protected void OnInput(InputIdentifier id, InputVector vec) {
lock (_lock) {
InputVector vec0;
if (_vectors.TryGetValue(id, out vec0)) {
_events.Add(new InputEvent {
Id = id,
From = vec0,
To = vec,
});
if (vec.IsNull) _vectors.Remove(id);
else _vectors[id] = vec;
}
else {
_events.Add(new InputEvent {
Id = id,
From = new InputVector(vec.Time),
To = vec,
});
_vectors.Add(id, vec);
}
}
}
public void EnumerateEvents(Action<InputEvent> cb) {
lock (_lock) {
foreach (var ev in _events) cb(ev);
_events.Clear();
}
}
}
}

View File

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

View File

@@ -1,12 +0,0 @@
using UnityEngine;
namespace Cryville.Common.Unity.Input {
public static class UnityCameraUtils {
public static Vector2 ScreenToWorldPoint(Vector2 pos) {
Vector3 i = pos;
i.z = -Camera.main.transform.localPosition.z;
i = Camera.main.ScreenToWorldPoint(i);
return i;
}
}
}

View File

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

View File

@@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Common.Unity.Input {
public class UnityKeyHandler<T> : InputHandler where T : UnityKeyReceiver<T> {
GameObject receiver;
T recvcomp;
public UnityKeyHandler() { }
protected override void Activate() {
receiver = new GameObject("__keyrecv__");
recvcomp = receiver.AddComponent<T>();
recvcomp.SetCallback(Feed);
}
protected override void Deactivate() {
if (receiver) GameObject.Destroy(receiver);
}
public override void Dispose(bool disposing) {
if (disposing) {
Deactivate();
}
}
public override bool IsNullable(int type) {
return false;
}
public override byte GetDimension(int type) {
return 0;
}
public override string GetTypeName(int type) {
return recvcomp.GetKeyName(type);
}
public override double GetCurrentTimestamp() {
return Time.realtimeSinceStartupAsDouble;
}
}
public abstract class UnityKeyReceiver<T> : MonoBehaviour where T : UnityKeyReceiver<T> {
protected Action<int, int, InputVector> Callback;
protected readonly HashSet<int> Keys = new HashSet<int>();
public void SetCallback(Action<int, int, InputVector> h) {
Callback = h;
}
public abstract string GetKeyName(int type);
void Awake() {
useGUILayout = false;
}
void Update() {
double time = Time.realtimeSinceStartupAsDouble;
foreach (var k in Keys) {
Callback(k, 0, new InputVector(time, Vector3.zero));
}
}
}
public class UnityKeyboardReceiver : UnityKeyReceiver<UnityKeyboardReceiver> {
public override string GetKeyName(int type) {
return Enum.GetName(typeof(KeyCode), type);
}
void OnGUI() {
var e = Event.current;
if (e.keyCode == KeyCode.None) return;
double time = Time.realtimeSinceStartupAsDouble;
var key = (int)e.keyCode;
switch (e.type) {
case EventType.KeyDown:
if (!Keys.Contains(key)) {
Callback(key, 0, new InputVector(time, Vector3.zero));
Keys.Add(key);
}
break;
case EventType.KeyUp:
Keys.Remove(key);
Callback(key, 0, new InputVector(time));
break;
}
}
}
public class UnityMouseButtonReceiver : UnityKeyReceiver<UnityMouseButtonReceiver> {
public override string GetKeyName(int type) {
switch (type) {
case 0: return "Mouse Left";
case 1: return "Mouse Right";
case 2: return "Mouse Middle";
default: return string.Format("Mouse Button {0}", type);
}
}
void OnGUI() {
var e = Event.current;
double time = Time.realtimeSinceStartupAsDouble;
var key = e.button;
switch (e.type) {
case EventType.MouseDown:
if (!Keys.Contains(key)) {
Callback(key, 0, new InputVector(time, Vector3.zero));
Keys.Add(key);
}
break;
case EventType.MouseUp:
Keys.Remove(key);
Callback(key, 0, new InputVector(time));
break;
}
}
}
}

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