342 Commits

Author SHA1 Message Date
054b17811d Preserve Convert. 2023-03-22 20:04:32 +08:00
94d5f7f82e Preserve BinaryReader and StreamReader. 2023-03-19 14:13:36 +08:00
0e4445e52b Detects assembly references and determines loading order automatically. 2023-03-18 13:46:13 +08:00
ed2c216cf4 Implement extension. 2023-03-17 18:03:59 +08:00
609645c108 Import HybridCLR. 2023-03-17 18:03:22 +08:00
d280d27a0a Improve error log on resource import failure. 2023-03-17 18:00:46 +08:00
5b727065f3 Adapt conversion for RawChartResource. 2023-03-17 17:59:59 +08:00
7aa2577059 Move UMG importers to extensions. 2023-03-17 17:58:45 +08:00
c1b7e9ab55 Separate extension classes into external assembly. 2023-03-17 17:56:12 +08:00
99384397ed Remove extensions. 2023-03-17 17:49:54 +08:00
a2391aeb22 Cleanup. (Skin editor) 2023-03-15 15:44:32 +08:00
2207c80951 Fix incorrect style for single-statement blocks in expression. 2023-03-15 15:43:30 +08:00
bf578d7cb9 Make statements in expression not sortable. 2023-03-15 15:41:02 +08:00
0bc57c368f Improve scaling logic of popup list in skin editor.. 2023-03-15 15:39:31 +08:00
b64f85aaa2 Add category for expression list in skin editor. 2023-03-15 15:36:45 +08:00
93fa2f2d7e Sync some constants, operators, and functions for skin editor. (3) 2023-03-15 15:34:33 +08:00
d72216de8b Sync some constants, operators, and functions for skin editor. (2) 2023-03-15 10:02:09 +08:00
df5133a91a Sync some constants, operators, and functions for skin editor. 2023-03-15 00:46:19 +08:00
88b959a118 Modify border color of expression statement. 2023-03-15 00:44:44 +08:00
310bf91fbd Always collapses delete button in skin editor. 2023-03-15 00:43:49 +08:00
699f47f98d Fix the height of popup list in skin editor. 2023-03-15 00:43:07 +08:00
24e881b138 Sync component and property list for skin editor. 2023-03-14 23:32:35 +08:00
2eef1b5c4e Update translations for skin editor. 2023-03-14 17:27:05 +08:00
c18ceb50d4 Update skin structure in editor. 2023-03-14 17:24:32 +08:00
27ca1a7292 Implement expression in skin editor. 2023-03-14 17:22:48 +08:00
dc59176eac Fix encoding for skin editor. 2023-03-14 16:59:37 +08:00
aec7470ff8 Optimize css for skin editor. 2023-03-14 16:58:03 +08:00
983cba6843 Detects user chart path for Malody chart finder. 2023-03-11 21:41:54 +08:00
871782e73f Remove potentially buggy syncing logic. 2023-03-11 21:41:22 +08:00
9aaa96fe10 Optimize GC for input proxy. 2023-03-11 21:40:34 +08:00
22190a29c1 Fix incorrect array length for vector operator. 2023-03-11 21:39:26 +08:00
613ca467d0 Fix offset error on function anim. 2023-03-09 22:02:34 +08:00
536a3066b2 Fix array operator creating array of type error. 2023-03-09 16:27:16 +08:00
43488cd002 Add "emit effect on self" annotation. 2023-03-09 16:26:43 +08:00
a11ccbd39c Cleanup variable name. 2023-03-09 11:41:25 +08:00
76df4929a7 Implement set variable annotation. 2023-03-09 11:38:49 +08:00
505b826627 Move up non-generic collection types and add debug view. 2023-03-09 11:37:23 +08:00
26a8675922 Make animation time of subspan relative. 2023-03-09 10:07:24 +08:00
b89e1f983e Code cleanup. 2023-03-08 20:36:18 +08:00
717e77b47e Fix inaccurate beat snapping for Quaver charts. 2023-03-06 08:16:42 +08:00
2f10c79dee Adjust offset for osu chart converter. 2023-03-05 23:06:18 +08:00
55f7790f89 Fix potential error on vector property source. 2023-03-05 23:05:48 +08:00
ae5f4a8c16 (Amend to 1851bd3c) 2023-03-05 21:53:30 +08:00
1851bd3c54 Fix inaccurate beat snapping for osu charts. Fix osu charts with too low BPM not able to be imported. 2023-03-05 20:40:02 +08:00
6d74685cb7 Add anim.iteration, anim.direction, and anim.delay properties. 2023-03-03 15:10:52 +08:00
03fd7f6d01 Add inf constant. 2023-03-03 15:09:08 +08:00
28c878f3e5 Code cleanup. 2023-03-03 13:34:12 +08:00
7736eba14d Supplement generic PairCollection. 2023-03-03 13:26:11 +08:00
2e54b38d2b Supplement Insert methods for pair list. 2023-03-03 11:49:32 +08:00
da60dc0903 Fix potential order inconsistency of element and property lists. 2023-03-03 11:45:16 +08:00
215f72b3b5 Add cubic bezier functions. 2023-03-02 10:40:18 +08:00
a93c081dd8 Add easing function parameter to anim function. 2023-03-02 10:39:39 +08:00
456782930a Fix incorrect zero format specifier range. 2023-03-01 17:55:09 +08:00
ba3cbbd64c Add state-based effect. 2023-03-01 00:37:22 +08:00
dfc3e9ca06 Refactor OpenedAnchorName in ISkinnableGroup. (Amend) 2023-03-01 00:36:09 +08:00
f567a2b78e Fix error on setting anim.name to null. 2023-03-01 00:35:19 +08:00
c7e7bd8a77 Add Identifier.Empty. 2023-03-01 00:33:28 +08:00
67720fd0e1 Refactor OpenedAnchorName in ISkinnableGroup. 2023-03-01 00:33:01 +08:00
1a30149942 Prevents infinite propagation on input proxy and judge. 2023-02-28 13:47:38 +08:00
a755cc13bd Implement animation. 2023-02-27 00:17:14 +08:00
9a51cf1b56 Add rewind and tick mechanism for skin component. 2023-02-27 00:16:44 +08:00
256c656e9c Fix once annotation not working on certain properties. 2023-02-27 00:13:38 +08:00
2ac7f05316 Add contextual function anim. 2023-02-27 00:11:37 +08:00
28d46dbabe Disallows multiple meshes in one object. 2023-02-26 16:24:58 +08:00
18b3e0bc84 Code cleanup. 2023-02-26 16:24:28 +08:00
23f2e7c1f2 Fix multiple flags ignored in enum property operator. 2023-02-26 16:23:17 +08:00
998713b41f Pull some init logic in enum property operator to static constructor. 2023-02-26 16:22:37 +08:00
3561354231 Implement execute once annotation on properties. 2023-02-26 16:21:33 +08:00
0cccb170c1 Support extra annotations on skin property key. Code cleanup. 2023-02-26 16:20:25 +08:00
d2480b8a6f Update global suppressions. 2023-02-26 16:16:46 +08:00
6837d3f7ee Make the group in skin container readonly. 2023-02-24 15:25:04 +08:00
3ecf3b4bfc Code cleanup. 2023-02-21 22:47:42 +08:00
1da8647ff1 Re-add start offset stub. 2023-02-21 22:47:24 +08:00
2f19e8daad Add limit for render distance settings. 2023-02-21 22:45:51 +08:00
07f62c7aeb Reduce font size for extra tag in input config. 2023-02-21 22:43:38 +08:00
39db8dfa45 Code cleanup. 2023-02-21 18:43:21 +08:00
f04cd370f1 Allow vector as number in contextual operators. 2023-02-21 18:42:58 +08:00
5c4acd54ce Add ticking stub for effect. 2023-02-21 18:42:03 +08:00
82dbc5c479 Add event property for event. 2023-02-21 18:41:32 +08:00
1f1663d714 Rename index to effect_index. 2023-02-21 18:29:25 +08:00
a3c5392caa Optimize GC for vector property source. 2023-02-21 18:27:29 +08:00
6c983cc2cb Add backward compatibility for opacity property. 2023-02-19 22:44:12 +08:00
3bf3fdac3d Code cleanup. 2023-02-19 22:15:46 +08:00
f2f3dba098 Fix effect queue with multiple items of the same instance. 2023-02-19 22:15:25 +08:00
3728360dd2 Fix index invalidation for effects. 2023-02-19 22:13:57 +08:00
887837bb3d Fix main thread stuck on texture missing. 2023-02-19 22:13:18 +08:00
99b4c2dfc1 Fix error on text frame update if texture not found. 2023-02-19 22:11:59 +08:00
e59769158a Change materials to shared mode in components. 2023-02-19 22:08:09 +08:00
ba3238614b Pull up mesh.color. Remove *.opacity properties. 2023-02-19 22:06:20 +08:00
a115999aab Add additive shader. 2023-02-19 21:57:06 +08:00
393947db9f Add image.shader property. 2023-02-19 21:56:30 +08:00
e9b2a7f894 Fix error on dynamic expressions in static context. 2023-02-19 21:55:01 +08:00
9c73455761 Fix error on appending arg set when current length equals to capacity in string formatter. 2023-02-19 11:07:50 +08:00
59c2210359 Prevents dimension-unapplicable inputs from being assigned. 2023-02-18 15:51:21 +08:00
4fab20953a Improve text hints in input config. 2023-02-18 15:49:45 +08:00
ee7b0f5081 Make pause input optional. 2023-02-18 15:48:02 +08:00
33ee7a9a87 Code cleanup. 2023-02-18 15:46:32 +08:00
900bd7b77a Implement effect. 2023-02-18 14:51:28 +08:00
6bd32c9aef Add context cascade blocking. 2023-02-18 14:48:43 +08:00
13893b2853 Add execute once annotation. 2023-02-18 14:48:09 +08:00
23789c15eb Pull up material disposal to MeshBase. (Amend) 2023-02-18 14:46:38 +08:00
a1f7418d32 Code cleanup. 2023-02-18 14:46:08 +08:00
274a823d02 Fix log not cleared on log toggle. 2023-02-18 14:44:05 +08:00
ba6239068a Optimize GC for sprite update. 2023-02-18 14:42:42 +08:00
ff8c925f32 Optimize GC for setting image.frame. 2023-02-18 14:40:56 +08:00
2a6a33e60c Pull up material disposal to MeshBase. 2023-02-18 14:39:45 +08:00
8910b1f4a0 Allow dynamic anchor reset. 2023-02-17 23:14:51 +08:00
36dddea4d9 Code cleanup. 2023-02-17 21:13:19 +08:00
6a648c2dcd Fix error on image.frame(s) not set. 2023-02-17 21:12:41 +08:00
2d4087dc89 Fix behaviour on parameter overflow. 2023-02-17 21:11:38 +08:00
f91aacd78e Code cleanup. 2023-02-17 18:11:04 +08:00
9c08cbf0d2 Remove some dedicated properties on ISkinnableGroup. 2023-02-17 18:10:46 +08:00
88d35e4eaf Add backward compatibility for skin. (Amend) 2023-02-17 16:27:49 +08:00
675ce68073 Add backward compatibility for skin. 2023-02-17 16:24:24 +08:00
db0165d145 Pull up ISkinnableGroup. 2023-02-17 15:19:18 +08:00
7015426300 Add error handling for setting text.frames. 2023-02-17 14:41:12 +08:00
0d4cc5e208 Add skin property image.frames and image.index. 2023-02-17 14:40:34 +08:00
e7ce0985fb Add effect emitting stub. 2023-02-15 18:13:04 +08:00
eb6dafbd60 Add animation stub and effect stub for skin. 2023-02-15 18:12:41 +08:00
b6e238780e Change fixed skin root to configurable root element in skin container. 2023-02-15 18:09:21 +08:00
c7ea6f1d4b Cleanup logic of PDT interpreter. 2023-02-15 18:07:36 +08:00
4a5b2a6889 Add effect definition. 2023-02-15 15:35:09 +08:00
b84d645aee Pull up PdtBinder. 2023-02-15 15:34:27 +08:00
67b44db1ae Code cleanup. 2023-02-13 16:09:19 +08:00
ee4399109a Optimize GC for log in gameplay scene. 2023-02-12 21:50:57 +08:00
87ef534f59 Fix resize logic in StringBuffer. 2023-02-12 21:48:39 +08:00
87362b47c5 Cleanup CategorizedPool. 2023-02-12 17:27:54 +08:00
f60ba1088d Fix input conflict in input config. 2023-02-12 17:27:15 +08:00
abb7ad6f24 Adjust offset for osu chart converter. 2023-02-11 23:13:30 +08:00
880b475c07 Update project version. 2023-02-11 23:12:01 +08:00
4707c40e6a Add object pool related debug status info. 2023-02-11 23:11:45 +08:00
7f87c23da2 Fix contextual state variables available in static context. 2023-02-11 23:11:15 +08:00
6df10837fe Eliminate Array.Copy GC in SquareMatrix. 2023-02-11 23:09:46 +08:00
42cb54de1d Add RentedCount for ObjectPool. 2023-02-11 23:09:05 +08:00
9fd685b8b3 Pull up CategorizedPool. Add Reset method for ObjectPool. 2023-02-11 23:08:43 +08:00
b364005741 Update UnsafeIL. 2023-02-10 17:52:45 +08:00
7d938de409 Code cleanup. 2023-02-10 17:36:36 +08:00
bb4ecfcd8c Add graphical offset global settings. 2023-02-10 17:36:19 +08:00
ff410529b0 Add invisible_bounds contextual variable. 2023-02-10 17:35:36 +08:00
fdc55a8e3b Pull current_time to container handler. 2023-02-10 17:34:40 +08:00
fc8512ff63 Combine score and score string property sources. 2023-02-10 17:32:59 +08:00
1b1ed42a1b Code cleanup. 2023-02-10 15:50:49 +08:00
b437925f92 Replace TrustedAsOfLength with safe As and Set. 2023-02-10 15:47:20 +08:00
c04e50e959 Modify priority logic for normal/temporary events. 2023-02-09 18:22:39 +08:00
314cdb9935 Implement transform update for static judge anchor. 2023-02-09 18:21:17 +08:00
77c91d015a Add standalone event property. 2023-02-09 18:20:36 +08:00
291a018c13 Activates anchors only on set. 2023-02-09 18:19:46 +08:00
18ff4b8e16 Code cleanup. 2023-02-09 18:18:34 +08:00
7714c277fd Modify text in status debug info. 2023-02-09 18:14:07 +08:00
d6c2ac6be6 Fix TypedChildren shared across ContainerState. 2023-02-09 18:12:33 +08:00
682fe38d40 Fix priority for manually set special anchors. 2023-02-09 18:11:32 +08:00
3e525842cb Modify texts in input config panel. 2023-02-09 18:09:40 +08:00
3dd25b51a8 Fix wrong context access in component creation. 2023-02-09 18:08:12 +08:00
041c1e374e Optimize GC for frame calculation. 2023-02-09 18:07:06 +08:00
16b1d323dc Add exception handling for invalid key interpretation in PDT. 2023-02-09 12:21:41 +08:00
c4d5e5f480 Matches member name first then generic list in PDT. 2023-02-09 12:15:07 +08:00
187f07d2c9 Optimize GC for motions. 2023-02-07 23:15:52 +08:00
4e9d7e5b87 Optimize GC for SectionalGameObject. 2023-02-07 23:15:11 +08:00
7df5b15e2e Animation cleanup. 2023-02-07 16:36:17 +08:00
4863aa0ae7 Add persist in judge definition. 2023-02-07 16:24:27 +08:00
eb53c3465b Implement pausing. 2023-02-07 16:23:16 +08:00
f683d61298 Reorganize resources. 2023-02-07 14:20:47 +08:00
fbd03c8037 Add sound offset for ruleset config. 2023-02-06 22:55:43 +08:00
da68c8b877 Move ruleset config to main scene. Add title for UI. 2023-02-06 22:55:14 +08:00
c0744a3464 Add interval function. 2023-02-06 15:16:35 +08:00
3ca3746cec Fix judge passing for inputs without any events. 2023-02-06 15:16:02 +08:00
5e76ddf2cd Fix use of discarded digits in rounded numbers in string formatter. 2023-02-06 15:14:54 +08:00
dca1ba304e Code cleanup. 2023-02-05 23:01:46 +08:00
8dd32afb74 Prevents dynamic anchor set twice. Implement special dynamic anchors. 2023-02-05 22:13:44 +08:00
313824b4bb Fix abnormal shaking at dynamic anchor. 2023-02-05 22:12:47 +08:00
b166c0f5ef Fix overflowed integral digits always prepended in string formatter. 2023-02-05 22:03:31 +08:00
300e44bd4b Code cleanup. 2023-02-05 15:59:20 +08:00
ab6f983392 Implement meta table for font. 2023-02-05 15:59:12 +08:00
596c6395e4 Prevent non-Windows system trying to initialize WindowsPointerHandler. 2023-02-05 15:58:31 +08:00
404a36f9b8 Replace text components in the main browser with TMP. 2023-02-05 15:56:56 +08:00
1711fbadf7 Add fallback logic for TMP auto font. 2023-02-05 15:55:53 +08:00
84b7a6d183 Seperate matcher from font manager. 2023-02-05 15:53:30 +08:00
6d0fd0f9ec Support multiple fonts with the same full name. 2023-02-05 15:51:18 +08:00
b407ba88c4 Add system font matcher. 2023-02-02 18:35:18 +08:00
bd256ba1a6 Reimport upgraded TextMesh Pro, modified. 2023-02-01 22:14:43 +08:00
623c53f79a Cleanup. 2023-01-31 22:56:19 +08:00
969fdc8069 Optimize GC for status info. 2023-01-31 22:56:06 +08:00
cbc874dd72 Optimize GC for proxied input variables. 2023-01-31 22:51:17 +08:00
450bd52095 Implement dynamic stack for skin. 2023-01-31 22:50:24 +08:00
5727fcf177 Introduce UnsafeIL for IL2CPP compatibility. 2023-01-31 22:49:04 +08:00
8ab0c2698b Fix TargetString stuck when length was 0. Add TargetString.TrustedAsArray. 2023-01-31 22:47:35 +08:00
6c7b52d93c Import TextMesh Pro. 2023-01-31 22:44:54 +08:00
91f55cd9a3 Add state count debug info. 2023-01-31 15:54:46 +08:00
a1ce459a0e Restructure event/container system. 2023-01-31 15:53:43 +08:00
9700992c3a Add DisposeAll. 2023-01-31 15:39:40 +08:00
f9a1ea72fe Refactor ReleaseEvent. 2023-01-31 15:30:27 +08:00
507b656eab Pull up StampedEvent.Temporary. Fix temporary event discarding. 2023-01-31 15:26:13 +08:00
c16776aee9 Code cleanup. (Amend) 2023-01-31 15:18:24 +08:00
e109e0bd24 Separate dynamic anchors. 2023-01-31 15:15:13 +08:00
776a615464 Code cleanup. 2023-01-31 15:06:31 +08:00
5514b6cf37 Pull up clip from judge definition. Add clip to event container. 2023-01-31 14:55:41 +08:00
8932d1b8d0 Add current_time variable. 2023-01-28 11:58:13 +08:00
10988847b3 Implement anchor related annotations. 2023-01-28 11:57:49 +08:00
c4b139c7a4 Code cleanup. 2023-01-27 17:30:10 +08:00
130896df1f Fix SkinSelectors.ToString. (2) 2023-01-27 16:54:11 +08:00
5d5c519a1d Remove dynamic judge anchors. (Amend) 2023-01-27 16:41:40 +08:00
3d1a11f78b Remove dynamic judge anchors. Add judge time properties. 2023-01-27 16:05:57 +08:00
cc985844cd Optimize GC for identifier and beat time property source. 2023-01-27 16:03:27 +08:00
feffbaa5a6 Refactor SkinPropertyKey. 2023-01-27 15:31:51 +08:00
d0f0c8ce6d Fix SkinSelectors.ToString. 2023-01-27 15:28:22 +08:00
3fdc236b1d Fix EmptyBinder not identifying inheritance. 2023-01-27 15:24:48 +08:00
46870e163a Code cleanup. 2023-01-26 18:12:22 +08:00
601f64cc61 Introduce no GC string formatter to optimize score string formatting. 2023-01-26 16:52:05 +08:00
c015b60dc3 Code cleanup. 2023-01-26 16:47:56 +08:00
5e01b654bd Optimize GC for enumerating TargetString. 2023-01-26 16:46:43 +08:00
2304257201 Add exception description on PDT parsing error. 2023-01-24 23:10:52 +08:00
02794d88b9 Fix config scene stuck on ruleset format error. 2023-01-22 22:29:16 +08:00
9f73c8ffad Code cleanup. 2023-01-21 20:14:41 +08:00
c1c354959d Add MotionCache. 2023-01-21 20:13:40 +08:00
94428d9e18 Append IDE warning suppression. 2023-01-21 20:12:03 +08:00
5198ecec1f Optimize code structure for input module. 2023-01-21 17:04:29 +08:00
6779b88055 Code cleanup. 2023-01-21 16:59:19 +08:00
c5dab3a232 Refactor SelectorNotAvailableException. 2023-01-20 22:50:31 +08:00
a7608bcd7e Matches dynamic on anchoring. 2023-01-20 22:50:05 +08:00
be64bc76b5 Revert "Revise update clone type to update depth."
This reverts commit 4185303bd2.
2023-01-20 22:26:56 +08:00
39bc34fd42 Fix dynamic judge anchors not updated if note is not working. 2023-01-17 22:16:40 +08:00
4185303bd2 Revise update clone type to update depth. 2023-01-17 22:16:09 +08:00
3280693e8f Update project version. 2023-01-16 22:11:19 +08:00
29432feabc Fix error on "(at) anchor" selector when no anchor is opened. 2023-01-16 20:57:19 +08:00
86559c681e Fix relative time calculation in judge report. 2023-01-16 20:55:32 +08:00
79f11b9c33 Implement judge_result contextual variable. 2023-01-16 20:54:53 +08:00
5b9149cb34 Make the output type of a property source read-only. 2023-01-16 20:53:45 +08:00
9d6bdd968f Implement write-only context. 2023-01-16 20:50:14 +08:00
bc4fec33ef Add null constant. 2023-01-16 20:47:54 +08:00
09e917dbe8 Add is function. 2023-01-16 20:46:57 +08:00
1003a0e199 Add forced variable syntax in PDT. 2023-01-16 20:45:06 +08:00
e3a805b855 Implement skin context property source injection. 2023-01-16 15:23:57 +08:00
4222176979 Add temporary event discard handling. 2023-01-16 15:09:34 +08:00
43c87fba70 Wrap Transform into SkinContext. Implement r/w context separation for skins. 2023-01-16 15:08:25 +08:00
d0a23aaf30 Add static judge anchor. Change dynamic anchors to single only. 2023-01-16 13:35:51 +08:00
a09a5686d7 Change anchor opening to single only. 2023-01-16 13:33:25 +08:00
609bb317d0 Code cleanup. 2023-01-15 11:54:11 +08:00
898fb7d557 Pull down chart field from StateBase. 2023-01-15 11:52:28 +08:00
c39f258a19 Code cleanup. 2023-01-14 22:03:08 +08:00
4fdd4e1935 Implement multiple static matching. 2023-01-14 22:01:29 +08:00
7662011d60 Pull down some judge preparation logic. 2023-01-14 21:39:10 +08:00
c24372b308 Pull up tail anchoring. 2023-01-14 21:35:15 +08:00
5e4c53113a Revise anchor data structure. 2023-01-14 21:34:13 +08:00
4f93995bbd Pull down EvaluationFailureException. 2023-01-13 22:18:13 +08:00
5b14466059 Add error handling for Discord callback. 2023-01-13 22:16:16 +08:00
1d3aa85446 Fix polysec.part. Enable judge anchor. 2023-01-13 16:46:29 +08:00
6efe70d751 Implement coevent. (2) 2023-01-13 16:37:31 +08:00
555c88855c Adapt Bestdori chart converter to coevents. 2023-01-12 18:05:20 +08:00
105aacc133 Fix config scene not unloaded if the ruleset is not present. 2023-01-10 21:41:48 +08:00
ea9000f2b0 Cleanup. 2023-01-09 22:17:42 +08:00
4e851d9b73 Implement coevent. 2023-01-09 16:28:36 +08:00
0a1e512f41 Code cleanup. 2023-01-08 16:27:02 +08:00
a7baef2c9d Add NoRequireDiscord flag when initializing Discord GameSDK. 2023-01-08 13:00:35 +08:00
723ec937ad Remove callback parameters on states. 2023-01-03 12:09:16 +08:00
7c77ba83f8 Fix polysec not mapping textures correctly if texture set partly. 2023-01-03 11:58:39 +08:00
6da4b96b24 Optimize motion invalidation performance. 2023-01-02 20:05:14 +08:00
e8f8593555 Fix conditional compilation. 2023-01-01 20:07:58 +08:00
2b5bc5dd08 Optimize GC for RMV pool. 2023-01-01 19:03:19 +08:00
cf6186aa16 Add judge anchor stub. 2023-01-01 19:02:49 +08:00
4d7773a2ac Cleanup anchor related code. 2023-01-01 19:01:34 +08:00
e8f74399f2 Implement judge report. 2023-01-01 19:00:19 +08:00
ca72f7adb5 Implement temporary event injection. (Amend) 2023-01-01 18:55:22 +08:00
5e19a8b886 Code cleanup. 2023-01-01 18:54:53 +08:00
a416f772d4 Add force sync frames. 2023-01-01 18:52:28 +08:00
989a6b5554 Fix osu chart ruleset and effect point. 2023-01-01 18:50:03 +08:00
732af15d9b Add Discord GameSDK. 2023-01-01 18:48:14 +08:00
8cdab36cd6 Fix handling for first timing point of osu chart. 2022-12-31 18:17:24 +08:00
44180c7e0f Optimize GC for PropSrc. 2022-12-25 22:20:46 +08:00
e589e37640 Code cleanup. 2022-12-24 19:12:16 +08:00
94107de97d Optimize GC for temporary anchor event injection. 2022-12-23 17:46:29 +08:00
13c55dc23e Optimize GC for PropOp.Enum<T>. 2022-12-23 17:45:07 +08:00
617eddc030 Reimplement cur anchor. 2022-12-23 16:28:48 +08:00
7475b19547 Implement temporary event injection. 2022-12-23 16:27:34 +08:00
0049ace91a Refactor polysec.suppressed to polysec.partial and polysec.part. 2022-12-23 16:25:57 +08:00
356f4df9a9 Exception cleanup. Code cleanup. 2022-12-23 15:20:16 +08:00
ff5928b556 Code cleanup. 2022-12-22 17:15:31 +08:00
1f0ac2a2e9 Add "at anchor" skin selector. 2022-12-22 17:14:48 +08:00
95628f07d1 Remove faulty toggling of anchor "cur". 2022-12-22 17:13:39 +08:00
3bead4f1b3 Add "polysec.suppressed" property. 2022-12-22 17:10:55 +08:00
ec9b23f797 Add "cur" anchor. 2022-12-22 14:43:50 +08:00
8175ca7e82 Optimize anchor identifiers. 2022-12-22 14:06:05 +08:00
451ebbe91a Code cleanup. 2022-12-22 14:02:58 +08:00
da2313ab57 Revert incorrect uct. 2022-12-22 12:30:57 +08:00
c5571e7d17 Make frame properties animatable. 2022-12-21 20:22:41 +08:00
959157255f Code cleanup. 2022-12-20 16:06:01 +08:00
06d8012675 Optimize GC for group frame. 2022-12-20 16:05:52 +08:00
571320630b Optimize performance for skin component properties. 2022-12-20 16:04:35 +08:00
207dee9932 Fix offsets for chart converters. (2) 2022-12-20 16:01:04 +08:00
d7b0ca77e9 Change state timestamp to double precision. 2022-12-19 14:55:15 +08:00
e55642cdeb Update project version. 2022-12-19 14:54:27 +08:00
595fd74662 Remove unused code. 2022-12-16 23:38:00 +08:00
3f7becf580 Temporarily change extension detection for Bestdori chart converter. 2022-12-16 17:51:23 +08:00
5d17555744 Implement preset path in file dialog. 2022-12-16 17:50:26 +08:00
e6d94f248c Logic cleanup for file dialog. 2022-12-16 17:48:43 +08:00
b0c70bc62e Pull up ExtensionInterface. 2022-12-16 17:44:41 +08:00
8eb0b11027 Add LocalResourceFinder. 2022-12-16 17:41:23 +08:00
7f2cfe94c1 Move GlobalSuppressions. 2022-12-16 15:45:51 +08:00
e4524bda0b Fix osu! charts with timing point with negative timestamp not able to be imported. 2022-12-16 15:45:26 +08:00
226fb15eb1 Resource cleanup. 2022-12-16 14:55:21 +08:00
645c4af2f2 Fix offsets for chart converters. 2022-12-16 14:36:10 +08:00
6e0f41c7fd Add osuChartConverter. 2022-12-16 14:17:32 +08:00
b9001ed9b2 Add BeatLength to TimingModel. 2022-12-13 17:53:59 +08:00
04abf59521 Fix QuaverChartConverter not generating endbeat of chart. 2022-12-13 15:10:00 +08:00
251f92532d Add QuaverChartConverter. 2022-12-13 10:51:29 +08:00
f5df56687b Add TimeTimingModel. 2022-12-13 10:51:05 +08:00
b582da90e5 Add optional offset to TimingModel constructor. 2022-12-13 10:50:34 +08:00
815f48fe06 Update Cryville.Common. 2022-12-13 09:21:52 +08:00
1470fa87dd Pull up BeatTimeTimingModel. 2022-12-13 08:59:35 +08:00
4b4356aaab Pull up FractionalBeatTimeTimingModel. 2022-12-12 23:48:15 +08:00
a8658856ca Code cleanup. 2022-12-12 22:28:08 +08:00
1477e907e6 Import YamlDotNet. 2022-12-12 22:23:49 +08:00
f559cea826 Code cleanup. 2022-12-05 12:16:42 +08:00
d363042036 Fix incorrect identifier load in PDT evaluator. 2022-12-05 11:43:31 +08:00
69e4ecd0a9 Fix BestdoriChartConverter generating track motions incorrectly. Add outro time to BestdoriChartConverter. 2022-12-01 12:34:56 +08:00
35d2e06625 Fix improper use of RMVPool. 2022-12-01 12:33:32 +08:00
358e654f51 Code cleanup. 2022-11-28 14:20:49 +08:00
d16548e570 Fix BinarySearchFirst algorithm. 2022-11-28 11:53:13 +08:00
c7201dd62c Add ingame log related settings. 2022-11-26 21:55:29 +08:00
e43a0e62b7 Fix zindex property not working on polysec component. 2022-11-26 21:55:03 +08:00
4bcf76819c Clears the input event queue on input dialog open. 2022-11-26 17:19:47 +08:00
31155c909c Make the buttons in the play scene not interactable with keyboard. 2022-11-24 22:37:59 +08:00
ab2670358a Add scroll bars to file dialog. 2022-11-24 22:37:03 +08:00
3da70bdccc Remove key count limit in Malody chart converter. 2022-11-23 12:03:24 +08:00
e370e1937c Code cleanup. 2022-11-23 12:02:25 +08:00
d9f6dd33d4 Optimize texture size. 2022-11-22 21:48:41 +08:00
e5d6e549bd Code cleanup. 2022-11-21 18:16:12 +08:00
145c0ce6c8 Optimize GC for value updating in text component. 2022-11-21 14:10:20 +08:00
a0174b94c6 Optimize GC for input proxy. 2022-11-21 14:09:44 +08:00
109b489104 Introduce TargetString to eliminate text GC. 2022-11-21 14:09:01 +08:00
784c3fc338 Disable GUI layout on Unity key receiver to avoid GC. 2022-11-21 14:06:57 +08:00
77d6ac2caf Cleanup unused functions. 2022-11-21 12:14:34 +08:00
321af22775 Code cleanup. 2022-11-20 23:17:08 +08:00
39ef9815e8 Fix verbose log about invalid resource. 2022-11-20 23:08:58 +08:00
bb3afba11f Fix import error on cover file missing. 2022-11-20 22:36:53 +08:00
e4fa160a90 Fix log typo. 2022-11-20 19:13:40 +08:00
34df9e2257 Optimize MatchDynamic performance. 2022-11-20 19:04:33 +08:00
cfdb5f021e Reconstruct skin container. Add update clone type limit to skin property. 2022-11-20 16:12:19 +08:00
d08eea5c1e Postpone skin static matching. 2022-11-20 16:09:34 +08:00
ce30b5427b Improve vector cache performance. 2022-11-20 16:02:39 +08:00
e38fed89e9 Update Cryville.Audio. 2022-11-20 13:29:29 +08:00
d4b12bf3f7 Add extra fallback logic for audio engine initialization. 2022-11-20 13:29:09 +08:00
40d75a91c6 Remove IL2CPP incompatibility workaround. 2022-11-20 09:34:37 +08:00
653 changed files with 117215 additions and 4417 deletions

1
.gitignore vendored
View File

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

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2e0c61e29fd90f04b9e41265d93e2029
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d815e4d844e6a1c4d849e96e199f8881
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 82867c59112ff5a419fbea2ebff2d3b9
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

View File

@@ -1,8 +0,0 @@
using System.Reflection;
[assembly: AssemblyCompany("Cryville")]
[assembly: AssemblyCopyright("Copyright © Cryville 2020-2022")]
[assembly: AssemblyDefaultAlias("Cosmo Resona")]
[assembly: AssemblyProduct("Cosmo Resona")]
[assembly: AssemblyTitle("Cosmo Resona")]
[assembly: AssemblyVersion("0.5.0")]

Binary file not shown.

View File

@@ -33,12 +33,12 @@ namespace Cryville.Common {
public override object ChangeType(object value, Type type, CultureInfo culture) {
if (value == null)
return null;
else if (type == value.GetType())
else if (type.IsAssignableFrom(value.GetType()))
return value;
else if (type.IsEnum && value is string) {
return Enum.Parse(type, (string)value);
}
throw new InvalidCastException();
throw new InvalidCastException(string.Format("Cannot cast {0} to {1}", value.GetType(), type));
}
public override void ReorderArgumentArray(ref object[] args, object state) {

View File

@@ -0,0 +1,90 @@
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,5 +1,5 @@
fileFormatVersion: 2
guid: 9ed0687e714ce1042921c0057f42039f
guid: ec18f22479042d747b88c093aa90c5c0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -14,6 +14,10 @@
_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>
@@ -24,6 +28,7 @@
_objs[_index++] = null;
}
if (obj == null) obj = Construct();
else Reset(obj);
return obj;
}
/// <summary>
@@ -38,5 +43,10 @@
/// </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

@@ -0,0 +1,135 @@
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,5 +1,5 @@
fileFormatVersion: 2
guid: d6a3a023271b82a4985d1bbcc86e6fa8
guid: f0fc34ac257793d4883a9cfcdb6941b9
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9ec674235c0dd6744af2dab2b58dd53c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 520554ce9a8205b4b91e0ff2b8011673
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -0,0 +1,113 @@
using Cryville.Common.IO;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace Cryville.Common.Font {
public abstract class FontFile : IEnumerable<Typeface> {
public abstract int Count { get; }
public abstract Typeface this[int index] { get; }
protected FileInfo File { get; private set; }
protected BinaryReader Reader { get; private set; }
public FontFile(FileInfo file) {
File = file;
Reader = new BinaryReaderBE(new FileStream(file.FullName, FileMode.Open, FileAccess.Read));
}
public void Close() { Reader.Close(); }
public static FontFile Create(FileInfo file) {
switch (file.Extension) {
case ".ttf": case ".otf": return new FontFileTTF(file);
case ".ttc": case ".otc": return new FontFileTTC(file);
default: return null;
}
}
public Enumerator GetEnumerator() {
return new Enumerator(this);
}
IEnumerator<Typeface> IEnumerable<Typeface>.GetEnumerator() {
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public struct Enumerator : IEnumerator<Typeface> {
readonly FontFile _self;
int _index;
internal Enumerator(FontFile self) {
_self = self;
_index = -1;
}
public Typeface 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.Count) {
_index = -2;
return false;
}
return true;
}
public void Reset() {
_index = -1;
}
}
}
public class FontFileTTF : FontFile {
public override int Count { get { return 1; } }
public override Typeface this[int index] {
get {
if (index != 0) throw new ArgumentOutOfRangeException("index");
try {
return new TypefaceTTF(Reader, File, index);
}
catch (Exception) {
throw new InvalidDataException("Invalid font");
}
}
}
public FontFileTTF(FileInfo file) : base(file) { }
}
public class FontFileTTC : FontFile {
readonly IReadOnlyList<uint> _offsets;
public override int Count { get { return _offsets.Count; } }
public override Typeface this[int index] {
get {
if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index");
Reader.BaseStream.Position = _offsets[index];
try {
return new TypefaceTTF(Reader, File, index);
}
catch (Exception) {
throw new InvalidDataException("Invalid font");
}
}
}
public FontFileTTC(FileInfo file) : base(file) {
try {
_offsets = new TTCHeader(Reader, 0).GetItems();
}
catch (Exception) {
throw new InvalidDataException("Invalid font");
}
}
}
}

View File

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

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Cryville.Common.Font {
public abstract class FontManager {
public IReadOnlyDictionary<string, IReadOnlyCollection<Typeface>> MapFullNameToTypeface { get; private set; }
public IReadOnlyDictionary<string, IReadOnlyCollection<Typeface>> MapNameToTypefaces { get; private set; }
public FontManager() {
var map1 = new Dictionary<string, List<Typeface>>();
var map2 = new Dictionary<string, List<Typeface>>();
foreach (var f in EnumerateAllTypefaces()) {
List<Typeface> set1;
if (!map1.TryGetValue(f.FullName, out set1)) {
map1.Add(f.FullName, set1 = new List<Typeface>());
}
set1.Add(f);
List<Typeface> set2;
if (!map2.TryGetValue(f.FamilyName, out set2)) {
map2.Add(f.FamilyName, set2 = new List<Typeface>());
}
set2.Add(f);
}
MapFullNameToTypeface = map1.ToDictionary(i => i.Key, i => (IReadOnlyCollection<Typeface>)i.Value);
MapNameToTypefaces = map2.ToDictionary(i => i.Key, i => (IReadOnlyCollection<Typeface>)i.Value);
}
protected abstract IEnumerable<Typeface> EnumerateAllTypefaces();
protected static IEnumerable<Typeface> ScanDirectoryForTypefaces(string dir) {
foreach (var f in new DirectoryInfo(dir).EnumerateFiles()) {
FontFile file;
try {
file = FontFile.Create(f);
}
catch (InvalidDataException) {
continue;
}
if (file == null) continue;
var enumerator = file.GetEnumerator();
while (enumerator.MoveNext()) {
Typeface ret;
try {
ret = enumerator.Current;
}
catch (InvalidDataException) {
continue;
}
yield return ret;
}
file.Close();
}
}
}
public class FontManagerAndroid : FontManager {
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
return ScanDirectoryForTypefaces("/system/fonts");
}
}
public class FontManagerWindows : FontManager {
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
return ScanDirectoryForTypefaces("C:/Windows/Fonts");
}
}
}

View File

@@ -0,0 +1,329 @@
using Cryville.Common.Culture;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Cryville.Common.Font {
public abstract class FontMatcher {
protected FontManager Manager { get; private set; }
public FontMatcher(FontManager manafer) { Manager = manafer; }
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>());
// 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");
// 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");
}
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");
// SP2
MapScriptToTypefaces["beng"].Insert(0, "Vrinda");
MapScriptToTypefaces["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");
// Reference: https://en.wikipedia.org/wiki/List_of_CJK_fonts
MapScriptToTypefaces["jpan"].Insert(0, "Meiryo");
MapScriptToTypefaces["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");
}
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");
}
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");
}
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");
// 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");
//
MapScriptToTypefaces["jpan"].Insert(0, "Yu Gothic UI");
MapScriptToTypefaces["zsym"].Add("Segoe MDL2 Assets");
}
}
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 FallbackListFontMatcher(FontManager manager) : base(manager) { }
public override IEnumerable<Typeface> MatchScript(string script = null, bool distinctFamily = false) {
if (string.IsNullOrEmpty(script)) script = ScriptUtils.UltimateFallbackScript;
List<string> candidates;
IEnumerable<string> candidateScripts = new string[] { script };
while (candidateScripts != null) {
foreach (var candidateScript in candidateScripts) {
if (MapScriptToTypefaces.TryGetValue(candidateScript, out candidates)) {
foreach (var candidate in candidates) {
IReadOnlyCollection<Typeface> typefaces1;
if (Manager.MapFullNameToTypeface.TryGetValue(candidate, out typefaces1)) {
foreach (var typeface in typefaces1) {
yield return typeface;
}
}
if (distinctFamily) continue;
IReadOnlyCollection<Typeface> typefaces2;
if (Manager.MapNameToTypefaces.TryGetValue(candidate, out typefaces2)) {
foreach (var typeface in typefaces2) {
if (typefaces1.Contains(typeface)) continue;
yield return typeface;
}
}
}
}
}
candidateScripts = ScriptUtils.EnumerateFallbackScripts(script);
}
}
}
}

View File

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

View File

@@ -0,0 +1,222 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Cryville.Common.Font {
public abstract class FontTable<T> {
protected UInt32 Offset { get; private set; }
protected BinaryReader Reader { get; private set; }
protected FontTable(BinaryReader reader, UInt32 offset) {
Reader = reader;
Offset = offset;
reader.BaseStream.Position = offset;
}
public abstract IReadOnlyList<T> GetItems();
}
public abstract class FontTable<T, U> : FontTable<T> {
protected FontTable(BinaryReader reader, UInt32 offset) : base(reader, offset) { }
public abstract U GetSubTable(T item);
}
public sealed class TTCHeader : FontTable<UInt32, TableDirectory> {
readonly String ttcTag;
readonly UInt16 majorVersion;
readonly UInt16 minorVersion;
readonly UInt32 numFonts;
readonly List<UInt32> tableDirectoryOffsets = new List<UInt32>();
readonly String dsigTag;
readonly UInt32 dsigLength;
readonly UInt32 dsigOffset;
public TTCHeader(BinaryReader reader, UInt32 offset) : base(reader, offset) {
ttcTag = reader.ReadTag();
if (ttcTag != "ttcf") throw new NotImplementedException();
majorVersion = reader.ReadUInt16();
minorVersion = reader.ReadUInt16();
numFonts = reader.ReadUInt32();
for (UInt32 i = 0; i < numFonts; i++) tableDirectoryOffsets.Add(reader.ReadUInt32());
if (majorVersion == 2) {
dsigTag = reader.ReadTag();
dsigLength = reader.ReadUInt32();
dsigOffset = reader.ReadUInt32();
}
}
public override IReadOnlyList<UInt32> GetItems() {
return tableDirectoryOffsets;
}
public override TableDirectory GetSubTable(UInt32 item) {
var i = item;
return new TableDirectory(Reader, i);
}
}
public sealed class TableDirectory : FontTable<TableRecord, object> {
readonly UInt32 sfntVersion;
readonly UInt16 numTables;
readonly UInt16 searchRange;
readonly UInt16 entrySelector;
readonly UInt16 rangeShift;
readonly List<TableRecord> tableRecords = new List<TableRecord>();
public TableDirectory(BinaryReader reader, UInt32 offset) : base(reader, offset) {
sfntVersion = reader.ReadUInt32();
numTables = reader.ReadUInt16();
searchRange = reader.ReadUInt16();
entrySelector = reader.ReadUInt16();
rangeShift = reader.ReadUInt16();
for (int i = 0; i < numTables; i++)
tableRecords.Add(new TableRecord {
tableTag = reader.ReadTag(),
checksum = reader.ReadUInt32(),
offset = reader.ReadUInt32(),
length = reader.ReadUInt32(),
});
}
public override IReadOnlyList<TableRecord> GetItems() {
return tableRecords;
}
public override object GetSubTable(TableRecord item) {
switch (item.tableTag) {
case "name": return new NameTable(Reader, item.offset);
case "meta": return new MetaTable(Reader, item.offset);
default: throw new NotImplementedException();
}
}
}
public struct TableRecord {
public string tableTag;
public UInt32 checksum;
public UInt32 offset;
public UInt32 length;
}
public sealed class NameTable : FontTable<NameRecord> {
readonly UInt16 version;
readonly UInt16 count;
readonly UInt16 storageOffset;
readonly List<NameRecord> nameRecord = new List<NameRecord>();
readonly UInt16 langTagCount;
readonly List<LangTagRecord> langTagRecord = new List<LangTagRecord>();
public NameTable(BinaryReader reader, UInt32 offset) : base(reader, offset) {
version = reader.ReadUInt16();
count = reader.ReadUInt16();
storageOffset = reader.ReadUInt16();
for (UInt16 i = 0; i < count; i++)
nameRecord.Add(new NameRecord {
platformID = reader.ReadUInt16(),
encodingID = reader.ReadUInt16(),
languageID = reader.ReadUInt16(),
nameID = (NameID)reader.ReadUInt16(),
length = reader.ReadUInt16(),
stringOffset = reader.ReadUInt16(),
});
if (version == 1) {
langTagCount = reader.ReadUInt16();
for (UInt16 i = 0; i < langTagCount; i++)
langTagRecord.Add(new LangTagRecord {
length = reader.ReadUInt16(),
langTagOffset = reader.ReadUInt16(),
});
}
UInt32 origin = (UInt32)reader.BaseStream.Position;
for (int i = 0; i < nameRecord.Count; i++) nameRecord[i] = nameRecord[i].Load(reader, origin);
for (int i = 0; i < langTagRecord.Count; i++) langTagRecord[i] = langTagRecord[i].Load(reader, origin);
}
public sealed override IReadOnlyList<NameRecord> GetItems() {
return nameRecord;
}
}
public struct NameRecord {
public UInt16 platformID;
public UInt16 encodingID;
public UInt16 languageID;
public NameID nameID;
public UInt16 length;
public UInt16 stringOffset;
public String value { get; private set; }
public NameRecord Load(BinaryReader reader, UInt32 origin) {
reader.BaseStream.Position = origin + stringOffset;
Encoding encoding;
switch (platformID) {
case 0: encoding = Encoding.BigEndianUnicode; break;
case 3: encoding = Encoding.BigEndianUnicode; break;
default: return this;
}
value = encoding.GetString(reader.ReadBytes(length));
return this;
}
}
public enum NameID : UInt16 {
CopyrightNotice = 0,
FontFamilyName = 1,
FontSubfamilyName = 2,
UniqueFontIdentifier = 3,
FullFontName = 4,
VersionString = 5,
PostScriptName = 6,
Trademark = 7,
ManufacturerName = 8,
Designer = 9,
Description = 10,
URLVendor = 11,
URLDesigner = 12,
LicenseDescription = 13,
LicenseInfoURL = 14,
TypographicFamilyName = 16,
TypographicSubfamilyName = 17,
CompatibleFull = 18,
SampleText = 19,
PostScriptCIDFindfontName = 20,
WWSFamilyName = 21,
WWSSubfamilyName = 22,
LightBackgroundPalette = 23,
DarkBackgroundPalette = 24,
VariationsPostScriptNamePrefix = 25,
}
public struct LangTagRecord {
public UInt16 length;
public UInt16 langTagOffset;
public String value { get; private set; }
public LangTagRecord Load(BinaryReader reader, UInt32 origin) {
reader.BaseStream.Position = origin + langTagOffset;
value = Encoding.BigEndianUnicode.GetString(reader.ReadBytes(length));
return this;
}
}
public sealed class MetaTable : FontTable<DataMap> {
readonly UInt32 version;
readonly UInt32 flags;
readonly UInt32 dataMapCount;
readonly List<DataMap> dataMaps = new List<DataMap>();
public MetaTable(BinaryReader reader, UInt32 offset) : base(reader, offset) {
version = reader.ReadUInt32();
flags = reader.ReadUInt32();
reader.ReadUInt32();
dataMapCount = reader.ReadUInt32();
for (UInt32 i = 0; i < dataMapCount; i++)
dataMaps.Add(new DataMap {
tag = reader.ReadTag(),
dataOffset = reader.ReadUInt32(),
dataLength = reader.ReadUInt32(),
});
for (int i = 0; i < dataMaps.Count; i++) dataMaps[i] = dataMaps[i].Load(reader, offset);
}
public sealed override IReadOnlyList<DataMap> GetItems() {
return dataMaps;
}
}
public struct DataMap {
public String tag;
public UInt32 dataOffset;
public UInt32 dataLength;
public String value { get; private set; }
public DataMap Load(BinaryReader reader, UInt32 origin) {
reader.BaseStream.Position = origin + dataOffset;
value = Encoding.ASCII.GetString(reader.ReadBytes((int)dataLength));
return this;
}
}
public static class BinaryReaderExtensions {
public static string ReadTag(this BinaryReader reader) {
return Encoding.ASCII.GetString(reader.ReadBytes(4));
}
}
}

View File

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

View File

@@ -1,9 +0,0 @@
using System.Globalization;
namespace Cryville.Common.Font {
public static class FontUtil {
/*public static string MatchFontNameWithLang(string lang) {
}*/
}
}

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