Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2215482c2 | ||
|
|
59dae0f601 | ||
|
|
4d70e13629 | ||
|
|
83bc17970a | ||
|
|
72078e4fec | ||
|
|
f5bd835496 | ||
|
|
f2fe179109 | ||
|
|
b1d91ab5d8 | ||
|
|
f09e89e324 | ||
|
|
3c8f7c08ec | ||
|
|
ee9d492bec | ||
|
|
afc251cde7 | ||
|
|
b7615eb8dd | ||
|
|
d2ead0ce4c | ||
|
|
22297ee6ed | ||
|
|
353473a980 | ||
|
|
9e39b1bfdb | ||
|
|
ab884e1362 | ||
|
|
86c6f95cae | ||
|
|
7a3422bda6 | ||
|
|
fdc73624cf | ||
|
|
ae5654322c | ||
|
|
1cfe8b77a4 | ||
|
|
15bf019c2d | ||
|
|
d47ba73464 | ||
|
|
716aeef72d | ||
|
|
c48a20a03c | ||
|
|
7b2cd882d3 | ||
|
|
954810903c | ||
|
|
7f22a34d7e | ||
|
|
bf6b8eecb8 | ||
|
|
77d829e888 | ||
|
|
f2633bb335 | ||
|
|
de36ca87e8 | ||
|
|
9749402714 | ||
|
|
9e08f9d0bc | ||
|
|
e8d91e0f1f | ||
|
|
87fc681c56 | ||
|
|
709280c9a8 | ||
|
|
20d3e4fb62 | ||
|
|
05c81bc622 | ||
|
|
b42cd4b6e1 | ||
|
|
8bbd7bc466 | ||
|
|
347df2cdea | ||
|
|
4ff781bd3a | ||
|
|
423d80059c | ||
|
|
7bbd0e882b | ||
|
|
f9d8203238 | ||
|
|
a18bab932f | ||
|
|
ade57d9bb7 | ||
|
|
347f7cfecb | ||
|
|
18f5e25496 | ||
|
|
0001be960d | ||
|
|
38c8bc94ca | ||
|
|
d60fe0726f | ||
|
|
2e4115a33c | ||
|
|
bdf51dcd43 | ||
|
|
01d4242392 | ||
|
|
86f2f44b46 | ||
|
|
ac102396d7 | ||
|
|
663e7b307c | ||
|
|
afd27bf183 | ||
|
|
90712bf1e6 | ||
|
|
2a4968115f | ||
|
|
395915cb31 | ||
|
|
5de97f420c | ||
|
|
e51ae1098a | ||
|
|
da1e8e4664 | ||
|
|
1d82546c29 | ||
|
|
f42dcecab6 | ||
|
|
fdf6a3a2c6 | ||
|
|
e60cb6bfc5 | ||
|
|
4de27f4231 | ||
|
|
8f952acf91 | ||
|
|
8b8c1cc489 | ||
|
|
41e10f5f21 | ||
|
|
f18734f0b4 | ||
|
|
6949bd97e4 | ||
|
|
5ed1ef404b | ||
|
|
aa2d6db7e0 | ||
|
|
801074735e | ||
|
|
fe10c0dad6 | ||
|
|
0207197644 | ||
|
|
9730ee1c9e | ||
|
|
093eb708ed | ||
|
|
da1933397a | ||
|
|
47110a34b0 | ||
|
|
4f96d2c070 | ||
|
|
bd23b5c12f | ||
|
|
539048b57b | ||
|
|
7102cda49d | ||
|
|
7bdcd59797 | ||
|
|
957a339676 | ||
|
|
5ee192439b | ||
|
|
c239639ac7 | ||
|
|
1762affd7a | ||
|
|
a62e1c08ab | ||
|
|
0b6198f23a | ||
|
|
eff4bcfdf3 | ||
|
|
f5f2fb0fc8 | ||
|
|
a86ff05f69 | ||
|
|
209cdcff2a | ||
|
|
d25346ee39 | ||
|
|
16376c0897 | ||
|
|
6fe2089bea | ||
|
|
27fd960fb3 | ||
|
|
adbe5ba7cb | ||
|
|
2bb5397c2b | ||
|
|
1fce75feb9 | ||
|
|
83bfccc101 | ||
|
|
f0a5188cb1 | ||
|
|
28cbf3767a | ||
|
|
e7cd38ee85 | ||
|
|
c1be637101 | ||
|
|
6ab6bc62e7 | ||
|
|
8592b44c72 | ||
|
|
01bce88823 | ||
|
|
6aa8bc3ce9 | ||
|
|
840c0431ec | ||
|
|
4ca9a21ec6 | ||
|
|
fec0f66029 | ||
|
|
30efedb930 | ||
|
|
32c507999a | ||
|
|
9f6ea20f3e | ||
|
|
5b892c8814 | ||
|
|
504b22126b | ||
|
|
67aec2464b | ||
|
|
c99d4438db | ||
|
|
ac37968f73 | ||
|
|
3752232e3a | ||
|
|
7d5fa627cb | ||
|
|
4db9d7718c | ||
|
|
cf3e2e05bf | ||
|
|
b97012a10d | ||
|
|
e0af5e282e | ||
|
|
d6ce9e2dff | ||
|
|
c0a483f003 | ||
|
|
179d8294e4 | ||
|
|
c8f2056823 | ||
|
|
89e05e200e | ||
|
|
475c7cbf80 | ||
|
|
92331dd8bf | ||
|
|
eba3c2b2b1 | ||
|
|
0e82016232 | ||
|
|
0969465139 | ||
|
|
0e967ebefb | ||
|
|
8730812cf5 | ||
|
|
d7fc2ebff6 | ||
|
|
e4ed5b9cc8 | ||
|
|
7f8a1ab6d0 | ||
|
|
5e7aaf6894 | ||
|
|
4d501f05c3 | ||
|
|
a25f3e5fb8 | ||
|
|
eb4d9e9323 | ||
|
|
970a29cd5f | ||
|
|
8e20209391 | ||
|
|
05b703e93d | ||
|
|
a079593fdc | ||
|
|
c08a6a86a0 | ||
|
|
dbda7e02ca | ||
|
|
20fc36ea59 | ||
|
|
523b9c16eb | ||
|
|
b75add7c59 | ||
|
|
fabddc93ab | ||
|
|
4abbd9c15c | ||
|
|
a599c6513b | ||
|
|
05f9764236 | ||
|
|
5824529c12 | ||
|
|
54a15c7045 | ||
|
|
2136f6f5c3 | ||
|
|
b50dc69e05 | ||
|
|
fe45b409ef | ||
|
|
9d45aeb6ce | ||
|
|
778bbfd0f5 | ||
|
|
aac8f598d9 | ||
|
|
bde533def5 | ||
|
|
5eaa248451 | ||
|
|
276e8bb248 | ||
|
|
ec4fef6424 | ||
|
|
567aa28905 | ||
|
|
e15d39d102 | ||
|
|
04e120dfc9 | ||
|
|
9d12646452 | ||
|
|
ec59410b68 | ||
|
|
5ecccbf7fc | ||
|
|
e17a0d047a | ||
|
|
afeb263ae1 | ||
|
|
7af0a69584 | ||
|
|
378001f8ea | ||
|
|
824bb306f9 | ||
|
|
496cffdf99 | ||
|
|
d344741f85 | ||
|
|
9f695a28f5 | ||
|
|
5b7e567eb2 | ||
|
|
93ccad566c | ||
|
|
be68ebb920 | ||
|
|
b83672caab | ||
|
|
56dabfd5c9 | ||
|
|
71d7d929b4 | ||
|
|
866055018f | ||
|
|
e4d12d2a5a | ||
|
|
c71b06c9f2 | ||
|
|
72d3d4546f | ||
|
|
17cfd2e2f8 | ||
|
|
71d7fe0cf6 | ||
|
|
1c46c98c84 | ||
|
|
02c49ba645 | ||
|
|
a2cd0ef4ca | ||
|
|
64b99fedcc | ||
|
|
f7d6ce4a98 | ||
|
|
8b3372cdab | ||
|
|
f460b604e2 | ||
|
|
f1aade4b58 | ||
|
|
ccc2383402 | ||
|
|
3250f28217 | ||
|
|
544a531434 | ||
|
|
222eee19bf | ||
|
|
47830ffaf3 | ||
|
|
b582826fba | ||
|
|
5d14e4f667 | ||
|
|
97b09ba966 | ||
|
|
e72b67df70 | ||
|
|
c382cee930 | ||
|
|
d3ad9d9311 | ||
|
|
0b086689e8 | ||
|
|
cc91faaccc | ||
|
|
790e3fb097 | ||
|
|
982e2b72c1 | ||
|
|
e0a6253310 | ||
|
|
134984ea0b | ||
|
|
19610c4309 | ||
|
|
03f6cc1552 | ||
|
|
d6c6d75a45 | ||
|
|
ea4f0a4d28 | ||
|
|
66d191d431 | ||
|
|
bd99345a3c | ||
|
|
cfdbbb81d4 | ||
|
|
7f7197f216 | ||
|
|
2f949d4af0 | ||
|
|
bc06e7fcc1 | ||
|
|
a01b4ce4af | ||
|
|
965d2053cf | ||
|
|
bdedc0aad2 | ||
|
|
b23b008861 | ||
|
|
acbfa69d48 | ||
|
|
648ca8fd13 | ||
|
|
90eabf0b38 | ||
|
|
b3959a5935 | ||
|
|
cdca3bf307 | ||
|
|
e491c5e841 | ||
|
|
f9b125e44a | ||
|
|
1ceb4fad1a | ||
|
|
21fc59c997 | ||
|
|
0cbde53f86 | ||
|
|
5119cf1b72 | ||
|
|
927f3fc300 | ||
|
|
d1e4a17f46 | ||
|
|
ec868f8ef5 | ||
|
|
1e0a238463 | ||
|
|
e07e59a288 | ||
|
|
d6410d5e42 | ||
|
|
5974c1a482 | ||
|
|
ffdcbdbf21 | ||
|
|
3b27ec5b66 | ||
|
|
56a56dbfaa | ||
|
|
537bd5dd83 | ||
|
|
b0fd471f8a | ||
|
|
3633df3fdc | ||
|
|
e6234397f5 | ||
|
|
68ce5ce90b | ||
|
|
a6066f9905 | ||
|
|
75506f71a9 | ||
|
|
c4b5462a5a | ||
|
|
47d4d77c86 | ||
|
|
acf17f6165 | ||
|
|
2db26070c6 | ||
|
|
e0f9c7336b | ||
|
|
a28a28ae4c | ||
|
|
7160f748eb | ||
|
|
c8e60bed34 | ||
|
|
11c826daa6 | ||
|
|
6c887b4632 | ||
|
|
ecfb897dae | ||
|
|
56d5767004 | ||
|
|
7d3bfa32ca | ||
|
|
348647f486 | ||
|
|
48ed659800 | ||
|
|
8aafe62f9c | ||
|
|
0f7859bfb6 | ||
|
|
c3d3d2e547 | ||
|
|
37dc3461af | ||
|
|
c11ac1f658 | ||
|
|
47bbf67ae6 | ||
|
|
528e9e4f03 | ||
|
|
7626700495 | ||
|
|
0d2a663346 | ||
|
|
22736b27da | ||
|
|
dcfad7b7e8 | ||
|
|
ef625b3d9d | ||
|
|
6ce3a2e93e | ||
|
|
b8c2854007 | ||
|
|
04fffe8ade | ||
|
|
c37862445f | ||
|
|
0613e9d295 | ||
|
|
bed249dca0 | ||
|
|
139940f9ec | ||
|
|
36e2f47577 | ||
|
|
ce493a03c9 | ||
|
|
aabd1aa9f7 | ||
|
|
89029220e4 | ||
|
|
dca54de087 | ||
|
|
15bef89d71 | ||
|
|
6c1f3800db | ||
|
|
8507f799a1 | ||
|
|
dba2794780 | ||
|
|
48752e444c | ||
|
|
8a1d74b82c | ||
|
|
0d1db6ae9e | ||
|
|
1f1851990f | ||
|
|
67d2a9811b | ||
|
|
a782b3f9e8 | ||
|
|
74e28a18ff | ||
|
|
220636e01e | ||
|
|
4f316003af | ||
|
|
1a04e35db7 | ||
|
|
d3e83dd72d | ||
|
|
c4e2b900c1 | ||
|
|
ac3178118c | ||
|
|
681f7a6d07 | ||
|
|
aa24c94782 | ||
|
|
7075c8af4b | ||
|
|
efc33403b6 | ||
|
|
25a42b8182 | ||
|
|
0389af2202 | ||
|
|
b694ec08d6 | ||
|
|
423ccfab98 | ||
|
|
edc1f7113b | ||
|
|
f0b50de9fa | ||
|
|
0ad2d507ef | ||
|
|
6c13444211 | ||
|
|
5a0b4310a2 | ||
|
|
6b1fc0372b | ||
|
|
cf69125d25 | ||
|
|
84b2d5b48d | ||
|
|
dcb5b3a935 | ||
|
|
011f1541b1 | ||
|
|
13c1bf8ac0 | ||
|
|
1893f2b2f6 | ||
|
|
a0caa41edc | ||
|
|
456b2ff6c4 | ||
|
|
a1d1b1b2d1 | ||
|
|
0db4ce11b7 | ||
|
|
340fd5dcf1 | ||
|
|
d569690a51 | ||
|
|
4a5afa2fc7 | ||
|
|
59c593b812 | ||
|
|
6ba9e00a9f | ||
|
|
ec7bdd32e2 | ||
|
|
939528a9bd | ||
|
|
08b3af959d | ||
|
|
cea54e394c | ||
|
|
e710198afe | ||
|
|
bf3601ea8d | ||
|
|
c5566c8644 | ||
|
|
5944f5b55d | ||
|
|
077fbf6978 | ||
|
|
f02bdc4225 | ||
|
|
8da9ed4ea0 | ||
|
|
5ed4a2ddd0 | ||
|
|
6293e2808b | ||
|
|
c6dc562769 | ||
|
|
a607396d04 | ||
|
|
365f8dcfea | ||
|
|
b3eb709f4e | ||
|
|
fcbce0a66b | ||
|
|
05032e3126 | ||
|
|
b8a7189e24 | ||
|
|
881aba3b03 | ||
|
|
5480774afe | ||
|
|
d62c8af20c | ||
|
|
7d0644f3c8 | ||
|
|
fe21c0addd | ||
|
|
219143c02d | ||
|
|
03930a29c3 | ||
|
|
5d378cd9f2 | ||
|
|
e5db402025 | ||
|
|
d348ef3127 | ||
|
|
9301c0c7dd | ||
|
|
02ee8e64c8 | ||
|
|
40eab2e461 | ||
|
|
d6a65ca681 | ||
|
|
f8841bab35 | ||
|
|
dc23a116dd | ||
|
|
024994e85a | ||
|
|
9be1633320 | ||
|
|
3b15873fc7 | ||
|
|
786f19c57d | ||
|
|
ccb874e97a | ||
|
|
f7fd7a57c3 | ||
|
|
23f79aef58 | ||
|
|
2c394cc636 | ||
|
|
d7a0139e4f | ||
|
|
562d23005d | ||
|
|
671c152463 | ||
|
|
3ce7c7939f | ||
|
|
28450ccfc6 | ||
|
|
31dbd68194 | ||
|
|
29d776061c | ||
|
|
0805ec914e | ||
|
|
98ac6a6ce1 | ||
|
|
823120cdef | ||
|
|
1b13c6c53b | ||
|
|
036de96143 | ||
|
|
0b046cae9c | ||
|
|
a4c5341b3b | ||
|
|
5cbfab4f99 | ||
|
|
baf887155b | ||
|
|
a5bbe94871 | ||
|
|
ab26b28130 | ||
|
|
2606031ed2 | ||
|
|
72f9d32a2f | ||
|
|
4b87bbf1cd | ||
|
|
c9802fdcf2 | ||
|
|
e7f252953d | ||
|
|
7f299d8348 | ||
|
|
9d83d05c96 | ||
|
|
d6919683c3 | ||
|
|
879955c4a2 | ||
|
|
6026e0b908 | ||
|
|
32ef5404d8 | ||
|
|
3544a36de0 | ||
|
|
06a1894946 | ||
|
|
40bb5b7a74 | ||
|
|
062c2fa331 | ||
|
|
49846dbc13 | ||
|
|
e5a47aa74d | ||
|
|
77fffdf370 | ||
|
|
eaad0f2450 | ||
|
|
77faf38d61 | ||
|
|
134d220298 | ||
|
|
d4610f5f16 | ||
|
|
f5129b3283 | ||
|
|
ee6583fa82 | ||
|
|
af72895e54 | ||
|
|
8d17ad3dd1 | ||
|
|
723dd81e2b | ||
|
|
5c45d24e2e | ||
|
|
ffe72b89a7 | ||
|
|
bc92d6cebf | ||
|
|
b4bc3ca6cf | ||
|
|
8439272d00 | ||
|
|
c5a7442415 | ||
|
|
31b7fdf02b | ||
|
|
dafe4fe918 | ||
|
|
6737146571 | ||
|
|
33d1fd578e | ||
|
|
0c9edf93c3 | ||
|
|
241f140a98 | ||
|
|
0311c7373e | ||
|
|
ca95fa78c4 | ||
|
|
7fa5d77db7 | ||
|
|
dcc3baae26 | ||
|
|
ccb270612c | ||
|
|
404b601012 | ||
|
|
02d83a766d | ||
|
|
f40da353a2 | ||
|
|
c0c550e209 | ||
|
|
29ac2ad58b | ||
|
|
9b0b273004 | ||
|
|
17f120f5ee | ||
|
|
284cfc7ebc | ||
|
|
aa5d30eecc | ||
|
|
c11ecfcb6f | ||
|
|
aa251af116 | ||
|
|
ea7bc750d2 | ||
|
|
a043512f0e | ||
|
|
5805c310c1 | ||
|
|
bf0135d48e | ||
|
|
e1f950d3e6 | ||
|
|
018780620d | ||
|
|
ba2f8df30b | ||
|
|
ba77fc6677 | ||
|
|
ff3a5c4b9b | ||
|
|
3aef0e5432 | ||
|
|
83fb754e8e | ||
|
|
5042448e98 | ||
|
|
bca18170e7 | ||
|
|
524468135d | ||
|
|
de5fe9b950 | ||
|
|
17ed98ee4d | ||
|
|
1b6c2d1f93 | ||
|
|
7c90aee994 | ||
|
|
96bdfac0b9 | ||
|
|
359661b549 | ||
|
|
1e43902fff | ||
|
|
84a79f6833 | ||
|
|
bcd3b03a75 | ||
|
|
1ff79a7825 | ||
|
|
c3cdddc46e | ||
|
|
ac2f1f602b | ||
|
|
40ea803c56 | ||
|
|
dce987b345 | ||
|
|
5804aa100d | ||
|
|
f1276a64a0 | ||
|
|
503bbaaa46 | ||
|
|
0dbd8439bd | ||
|
|
40e5d1a4c1 | ||
|
|
58803cd221 | ||
|
|
ff0a226f53 | ||
|
|
1d19286f6b | ||
|
|
5cf114143c | ||
|
|
8331a1fa7f | ||
|
|
db7bee7902 | ||
|
|
2ba0f37a5a | ||
|
|
31f873ffc2 | ||
|
|
f7b5d5c62f | ||
|
|
94570d8c7c | ||
|
|
f6036343c9 | ||
|
|
cc8060db5b | ||
|
|
511f4d5b64 | ||
|
|
b04a7708b1 | ||
|
|
dd512d02e7 | ||
|
|
ff89c09b6f | ||
|
|
429e018749 | ||
|
|
babe37a0f0 | ||
|
|
122df21223 | ||
|
|
016c53061c | ||
|
|
429704676a | ||
|
|
cda1ca6897 | ||
|
|
8954dee6d6 | ||
|
|
b71e12ec5c | ||
|
|
c2055a322d | ||
|
|
583700006c | ||
|
|
928c2fcc19 | ||
|
|
3c913d29e3 | ||
|
|
52e015ad14 | ||
|
|
bef8cf9a0e | ||
|
|
eae4cb2160 | ||
|
|
955c94ed79 | ||
|
|
95109daedb | ||
|
|
00f28fdb79 | ||
|
|
aad014a0ba | ||
|
|
4917bd0591 | ||
|
|
54943b22f8 | ||
|
|
ec6e26c298 | ||
|
|
3db958a76b | ||
|
|
f5f2a2ac4c | ||
|
|
26fe00b559 | ||
|
|
899d793e1c | ||
|
|
430e2b9dcc | ||
|
|
9189c35585 | ||
|
|
0855b4da4e | ||
|
|
ad9c6581ff | ||
|
|
293d303c16 | ||
|
|
e4a4197482 | ||
|
|
2886e29d58 | ||
|
|
5868cb1d78 |
@@ -14,7 +14,7 @@ body:
|
||||
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
|
||||
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
|
||||
- label: I have properly titled my issue
|
||||
- label: I did not have any mods installed when I encountered this issue
|
||||
- label: I did not have any mods installed when I encountered this issue, or the issue is related to mods
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
@@ -48,19 +48,19 @@ body:
|
||||
attributes:
|
||||
label: Mobile Device Model
|
||||
description: (Mobile users only) What mobile device are you playing on?
|
||||
placeholder: ex. iPhone 17, Galaxy S25, iPad 11th Gen
|
||||
placeholder: ex. iPhone 17, Galaxy S26, iPad 11th Gen
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Mobile OS Version
|
||||
description: (Mobile users only) What version is your Operating System?
|
||||
placeholder: ex. iOS 26.2, Android 16, iPadOS 26.2
|
||||
placeholder: ex. iOS 26.4, Android 16, iPadOS 26.4
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.8.1
|
||||
placeholder: ex. 0.8.6 or 0.9 Feature Preview 3
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ body:
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.8.1
|
||||
placeholder: ex. 0.8.6 or 0.9 Feature Preview 3
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -52,7 +52,7 @@ body:
|
||||
attributes:
|
||||
label: Location
|
||||
description: Where did you find the issue(s)? Include the name of the song, the variation, the difficulty, the time/section of the song, and any images or videos.
|
||||
placeholder: ex. Cocoa Erect on Erect/Nightmare difficulties at Section 30
|
||||
placeholder: ex. Cocoa Erect [Nightmare] at Section 30, step 5
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ body:
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you compiling? The game version is in the bottom left corner of the main menu or in the project.hxp file.
|
||||
placeholder: ex. 0.8.1
|
||||
placeholder: ex. 0.8.6 or `preview/public-playtest`
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ body:
|
||||
- label: I have read the [Contributing Guide](https://github.com/FunkinCrew/Funkin/blob/main/docs/CONTRIBUTING.md)
|
||||
- label: I have checked the Issues/Discussions pages to see if my issue has already been reported
|
||||
- label: I have properly titled my issue
|
||||
- label: I did not have any mods installed when I encountered this issue
|
||||
- label: I did not have any mods installed when I encountered this issue, or the issue is related to mods
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
@@ -49,19 +49,19 @@ body:
|
||||
attributes:
|
||||
label: Mobile Device Model
|
||||
description: (Mobile users only) What mobile device are you playing on?
|
||||
placeholder: ex. iPhone 17, Galaxy S25, iPad 11th Gen
|
||||
placeholder: ex. iPhone 17, Galaxy S26, iPad 11th Gen
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Mobile OS Version
|
||||
description: (Mobile users only) What version is your Operating System?
|
||||
placeholder: ex. iOS 26.2, Android 16, iPadOS 26.2
|
||||
placeholder: ex. iOS 26.4, Android 16, iPadOS 26.4
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you playing on? The game version is in the bottom left corner of the main menu.
|
||||
placeholder: ex. 0.8.1
|
||||
placeholder: ex. 0.8.6 or 0.9 Feature Preview 3
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ inputs:
|
||||
haxe:
|
||||
description: 'Version of haxe to install'
|
||||
required: true
|
||||
default: '4.3.6'
|
||||
default: '4.3.7'
|
||||
hxcpp-cache:
|
||||
description: 'Whether to use a shared hxcpp compile cache'
|
||||
required: true
|
||||
@@ -71,7 +71,7 @@ runs:
|
||||
|
||||
- name: Restore cached dependencies
|
||||
id: cache-hmm
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .haxelib
|
||||
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
|
||||
@@ -98,7 +98,7 @@ runs:
|
||||
# by default use a shared hxcpp cache
|
||||
- if: ${{ inputs.hxcpp-cache == 'true' }}
|
||||
name: Restore hxcpp cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ inputs.hxcpp-cache-path }}
|
||||
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
@@ -114,7 +114,7 @@ runs:
|
||||
# if it's explicitly disabled, still cache export/ since that then contains the builds
|
||||
- if: ${{ inputs.hxcpp-cache != 'true' }}
|
||||
name: Restore export cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ inputs.hxcpp-cache-path }}
|
||||
key: haxe-export-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
|
||||
@@ -61,7 +61,7 @@ runs:
|
||||
- name: Get latest butler version
|
||||
shell: bash
|
||||
run: |
|
||||
LATEST=$(curl -sfL https://broth.itch.ovh/butler/$OS_AND_ARCH/LATEST)
|
||||
LATEST=$(curl -sfL https://broth.itch.zone/butler/$OS_AND_ARCH/LATEST)
|
||||
echo BUTLER_LATEST=$LATEST >> "$GITHUB_ENV"
|
||||
|
||||
command -v butler \
|
||||
@@ -70,7 +70,7 @@ runs:
|
||||
|
||||
- name: Try to get butler from cache
|
||||
id: cache-butler
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ env.BUTLER_INSTALL_PATH }}
|
||||
key: butler-${{ runner.os }}-${{ env.BUTLER_LATEST }}
|
||||
@@ -88,7 +88,7 @@ runs:
|
||||
mkdir -p $BUTLER_INSTALL_PATH
|
||||
cd $BUTLER_INSTALL_PATH
|
||||
|
||||
curl -L -o butler.zip https://broth.itch.ovh/butler/$OS_AND_ARCH/LATEST/archive/default
|
||||
curl -L -o butler.zip https://broth.itch.zone/butler/$OS_AND_ARCH/LATEST/archive/default
|
||||
unzip butler.zip
|
||||
chmod +x butler
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@ jobs:
|
||||
trigger-build: ${{ steps.should-trigger.outputs.result }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: funkincrew/ci-checkout@v7.3.3
|
||||
uses: funkincrew/ci-checkout@v7.4
|
||||
with:
|
||||
submodules: false
|
||||
- uses: dorny/paths-filter@v3
|
||||
- uses: dorny/paths-filter@v4
|
||||
id: filter
|
||||
with:
|
||||
base: ${{ github.ref }}
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
list: ${{ steps.build-tags.outputs.list }}
|
||||
steps:
|
||||
- name: Gather build tags
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
id: build-tags
|
||||
with:
|
||||
script: |
|
||||
@@ -96,17 +96,20 @@ jobs:
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: funkincrew/ci-checkout@v7.3.3
|
||||
uses: funkincrew/ci-checkout@v7.4
|
||||
with:
|
||||
submodules: false
|
||||
- name: Log into GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
with:
|
||||
context: ./build
|
||||
push: true
|
||||
@@ -143,14 +146,14 @@ jobs:
|
||||
run: |
|
||||
git config --global --replace-all safe.directory $GITHUB_WORKSPACE
|
||||
- name: Get checkout token
|
||||
uses: actions/create-github-app-token@v1
|
||||
uses: actions/create-github-app-token@v3
|
||||
id: app_token
|
||||
with:
|
||||
app-id: ${{ vars.APP_ID }}
|
||||
private-key: ${{ secrets.APP_PEM }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
- name: Checkout repo
|
||||
uses: funkincrew/ci-checkout@v7.3.3
|
||||
uses: funkincrew/ci-checkout@v7.4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
token: ${{ steps.app_token.outputs.token }}
|
||||
@@ -184,7 +187,7 @@ jobs:
|
||||
timeout-minutes: 120
|
||||
- name: Save build artifact to Github Actions
|
||||
if: ${{ github.event.inputs.save-artifact }}
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: build-${{ matrix.target }}
|
||||
path: export/release/${{matrix.target}}/bin/
|
||||
@@ -212,14 +215,14 @@ jobs:
|
||||
BUILD_DEFINES: ${{ github.event.inputs.build-defines || '-DGITHUB_BUILD' }}
|
||||
steps:
|
||||
- name: Get checkout token
|
||||
uses: actions/create-github-app-token@v1
|
||||
uses: actions/create-github-app-token@v3
|
||||
id: app_token
|
||||
with:
|
||||
app-id: ${{ vars.APP_ID }}
|
||||
private-key: ${{ secrets.APP_PEM }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
- name: Checkout repo
|
||||
uses: funkincrew/ci-checkout@v7.3.3
|
||||
uses: funkincrew/ci-checkout@v7.4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
token: ${{ steps.app_token.outputs.token }}
|
||||
@@ -233,7 +236,7 @@ jobs:
|
||||
echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV"
|
||||
- name: Restore cached dependencies
|
||||
id: cache-hmm
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .haxelib
|
||||
key: haxe-hmm-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
|
||||
@@ -242,15 +245,35 @@ jobs:
|
||||
run: |
|
||||
git config --global 'url.https://x-access-token:${{ steps.app_token.outputs.token }}@github.com/.insteadOf' https://github.com/
|
||||
git config --global advice.detachedHead false
|
||||
haxelib --global git haxelib https://github.com/FunkinCrew/haxelib.git
|
||||
haxelib --global git hmm https://github.com/FunkinCrew/hmm.git
|
||||
haxelib --global run hmm install -q
|
||||
cd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml
|
||||
haxelib --global fixrepo
|
||||
haxelib --global list
|
||||
pushd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml && popd
|
||||
- if: ${{ matrix.target != 'html5' }}
|
||||
name: Restore hxcpp cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: /usr/share/hxcpp
|
||||
key: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
restore-keys: haxe-hxcpp-${{ runner.os }}-${{ github.ref_name }}
|
||||
- name: Restore lime rebuild cache
|
||||
id: cache-lime
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .haxelib/lime/git/ndll/Linux64
|
||||
key: haxe-lime-linux64-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}-${{ github.sha }}
|
||||
restore-keys: haxe-lime-linux64-${{ runner.os }}-${{ hashFiles('**/hmm.json') }}
|
||||
- name: Setup lime
|
||||
run: |
|
||||
haxelib --always run lime setup
|
||||
haxelib run lime rebuild hxcpp
|
||||
- if: ${{ steps.cache-lime.outputs.cache-hit != 'true' }}
|
||||
name: Rebuild lime
|
||||
run: |
|
||||
haxelib run lime rebuild cpp -64
|
||||
git -C .haxelib/lime/git status || true
|
||||
- name: Populate .env
|
||||
run: |
|
||||
touch .env
|
||||
@@ -262,7 +285,7 @@ jobs:
|
||||
timeout-minutes: 120
|
||||
- name: Save build artifact to Github Actions
|
||||
if: ${{ github.event.inputs.save-artifact }}
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: build-${{ matrix.target }}
|
||||
path: export/release/${{matrix.target}}/bin/
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Cancel queued workflows for ${{ github.event.pull_request.head.ref }}
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
result-encoding: string
|
||||
retries: 3
|
||||
|
||||
@@ -27,4 +27,4 @@ jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/label-actions@v4
|
||||
- uses: dessant/label-actions@v5
|
||||
|
||||
@@ -7,6 +7,11 @@ on:
|
||||
types:
|
||||
- opened
|
||||
|
||||
# Ensure only one task can execute for a given PR at a time.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref }}
|
||||
queue: max
|
||||
|
||||
|
||||
jobs:
|
||||
# Apply `status: pending triage` to newly created pull requests
|
||||
|
||||
@@ -13,6 +13,10 @@ name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
# Ensure only one task can execute for a given PR at a time.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref }}
|
||||
queue: max
|
||||
|
||||
jobs:
|
||||
# Apply labels to pull requests based on which files were edited
|
||||
@@ -23,7 +27,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set basic labels
|
||||
uses: actions/labeler@v5
|
||||
uses: actions/labeler@v6
|
||||
with:
|
||||
sync-labels: true
|
||||
# Apply labels to pull requests based on how many lines were edited
|
||||
|
||||
@@ -17,6 +17,14 @@ NewgroundsCredentials.hx
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
# Dox output and types
|
||||
docs/dox/output
|
||||
docs/dox/Windows.xml
|
||||
docs/dox/Mac.xml
|
||||
docs/dox/iOS.xml
|
||||
docs/dox/Linux.xml
|
||||
docs/dox/Android.xml
|
||||
|
||||
# Mobile signing stuff
|
||||
.apple/
|
||||
.env
|
||||
|
||||
Vendored
+7
-2
@@ -80,13 +80,13 @@
|
||||
{ "name": "html5", "enabled": true, "label": "HTML5" },
|
||||
{ "name": "android", "enabled": true, "label": "Android" },
|
||||
{ "name": "ios", "enabled": true, "label": "iOS" },
|
||||
|
||||
// Disabled targets
|
||||
{ "name": "hl", "enabled": false, "label": "HashLink" },
|
||||
{ "name": "air", "enabled": false },
|
||||
{ "name": "electron", "enabled": false },
|
||||
{ "name": "flash", "enabled": false },
|
||||
{ "name": "neko", "enabled": false },
|
||||
{ "name": "tvos", "enabled": false }
|
||||
{ "name": "hl", "enabled": false }
|
||||
],
|
||||
"lime.defaultTargetConfiguration": "Windows / Debug",
|
||||
"lime.targetConfigurations": [
|
||||
@@ -144,6 +144,11 @@
|
||||
"target": "windows",
|
||||
"args": ["-debug", "-DLATENCY", "-DFEATURE_DEBUG_FUNCTIONS"]
|
||||
},
|
||||
{
|
||||
"label": "Windows / Debug (No Asset Redirect)",
|
||||
"target": "windows",
|
||||
"args": ["-debug", "-DNO_REDIRECT_ASSETS_FOLDER"]
|
||||
},
|
||||
{
|
||||
"label": "Windows / Debug (Waveform Test)",
|
||||
"target": "windows",
|
||||
|
||||
+395
-25
@@ -4,6 +4,375 @@ All notable changes will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.8.7] - 2026-08-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- [ANDROID] Fixed a crash when opening an FNFC chart file.
|
||||
- [ANDROID] Fixed errors and crashes related to the lime backend.
|
||||
- [ANDROID] Fixed a shader not displaying correctly in some places.
|
||||
|
||||
|
||||
|
||||
## [0.8.6] - 2026-08-12
|
||||
|
||||
### Added
|
||||
|
||||
- Added the ability to toggle Discord RPC statuses and hide song info.
|
||||
- [LINUX] Added support for Wayland, which the game now defaults to. (Thanks Starexify!)
|
||||
- Added the game version as a compilation flag for modders to access. ([e51ae10](https://github.com/FunkinCrew/Funkin/commit/e51ae1098a9392c7ec3a903543f3aa4fc4220da1)) - by @zxcksharks in [#7659](https://github.com/FunkinCrew/Funkin/pull/7659)
|
||||
- Added a shouldBop property to HealthIconData to allow animated icons to bop. ([cc91faa](https://github.com/FunkinCrew/Funkin/commit/cc91faaccc63d2050270723bd49477f8b518ab6f)) - by @Starexify in [#6901](https://github.com/FunkinCrew/Funkin/pull/6901)
|
||||
- Added album and sticker pack fields to the Chart Editor Metadata window. ([790e3fb](https://github.com/FunkinCrew/Funkin/commit/790e3fb097b7054e7cf4010d6b588264414d283a)) - by @Starexify in [#6266](https://github.com/FunkinCrew/Funkin/pull/6266)
|
||||
|
||||
### Changed
|
||||
|
||||
- [HTML5] The “Touch To Play” sprite now smoothly scales when hovered.
|
||||
- Made some improvements to width/height and cliprect functionality for FunkinGroup.
|
||||
- The Chart Editor now consistently exports chart data in the same order. (Thanks TechnikTil!)
|
||||
- Discord RPC images can now be configured in the album and song data files.
|
||||
- Discord RPC now pulls icons based on character icon data. ([bd23b5c](https://github.com/FunkinCrew/Funkin/commit/bd23b5c12f734eae529a8d2d2593fd1d6eb9a27b)) - by @7oltan in [#7643](https://github.com/FunkinCrew/Funkin/pull/7643)
|
||||
- Forced animations for the player character now unmute the player's vocals. ([e0a6253](https://github.com/FunkinCrew/Funkin/commit/e0a625331010a2dddde639a24953dd88f25010b1)) - by @Lasercar in [#4314](https://github.com/FunkinCrew/Funkin/pull/4314)
|
||||
- The Animation Editor now plays the Chart Editor theme music and click sounds. ([f42dcec](https://github.com/FunkinCrew/Funkin/commit/f42dcecab6966f77162308a0564af558616ea81b)) - by @JVNpixels in [#7556](https://github.com/FunkinCrew/Funkin/pull/7556)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Made some niche fixes to Polymod.
|
||||
- Argument count validation no longer crashes the game entirely in some instances. (Thanks Starexify!)
|
||||
- The `cast` keyword no longer throws a parsing error. (Thanks gamerbross!)
|
||||
- Every non-Windows platform is now case-insensitive. (Thanks TechnikTil!)
|
||||
- Preprocessors that span the entire file no longer throw an error. (Thanks KoloInDaCrib!)
|
||||
- Scripted class extending no longer breaks with multiple scripted layers. (Thanks TechnikTil!)
|
||||
- Imports with module names (ex. `funkin.play.character.BaseCharacter.CharacterType`) no longer throw an import error. (Thanks NotHyper-474!)
|
||||
- [iOS] Connecting a keyboard no longer freezes the game.
|
||||
- The Darken blend mode no longer renders with black boxes, fixing the Boyfriend Freeplay DJ Dad animation.
|
||||
- The Open File dialog now opens from the latest directory, not the root directory.
|
||||
- The Chart Editor now exports charts with correct suffixes for vocal tracks.
|
||||
- Clicking the Save Chart button now displays a notification in the Chart Editor.
|
||||
- Disconnecting a controller while in the gamepad controls menu no longer crashes the game. ([6fe2089](https://github.com/FunkinCrew/Funkin/commit/6fe2089beac639124d3561d4c2c1af1ffb7dfe11)) - by @MrMadera in [#7214](https://github.com/FunkinCrew/Funkin/pull/7214)
|
||||
- Hot-reloading and re-entering the Lag Adjustment menu no longer crashes the game. ([adbe5ba](https://github.com/FunkinCrew/Funkin/commit/adbe5ba7cb53f67363ec205c5e555744e69215de)) - by @AnimatingLegend in [#7304](https://github.com/FunkinCrew/Funkin/pull/7304)
|
||||
- `onExit` is now properly called when exiting the game. ([90712bf](https://github.com/FunkinCrew/Funkin/commit/90712bf1e62a20d1201c3da15b4554720e9fff46)) - by @AnimatingLegend in [#7321](https://github.com/FunkinCrew/Funkin/pull/7321)
|
||||
- Focusing into the game with 0 volume and Pause on Unfocus disabled no longer increases the volume. ([18f5e25](https://github.com/FunkinCrew/Funkin/commit/18f5e25496d2cb74fff24e490a95db29a1fb59e3)) - by @ahmed7p in [#7750](https://github.com/FunkinCrew/Funkin/pull/7750)
|
||||
- Save Data prompts no longer allow scrolling the Options menu behind them. ([83bfccc](https://github.com/FunkinCrew/Funkin/commit/83bfccc10115b089f6b8d747c366c2be64c4335c)) - by @Starexify in [#7213](https://github.com/FunkinCrew/Funkin/pull/7213)
|
||||
- Adjusted the Lag Adjustment overlay to fit the whole screen. ([27fd960](https://github.com/FunkinCrew/Funkin/commit/27fd960fb369b2baf3c3377fa317732bf80a5230)) - by @JVNpixels in [#7358](https://github.com/FunkinCrew/Funkin/pull/7358)
|
||||
- Input latency is now calculated correctly when hitting a note late in the Lag Adjustment menu. ([de36ca8](https://github.com/FunkinCrew/Funkin/commit/de36ca87e8b95d8fe4d40d458c355baf52e4d94a)) - by @nykwono in [#7792](https://github.com/FunkinCrew/Funkin/pull/7792)
|
||||
- Weeks with non-default variation songs no longer use default variation scripts. ([2a49681](https://github.com/FunkinCrew/Funkin/commit/2a4968115f0ed5e81d4209bedba3f8bf153aab6a)) - by @requazar in [#7586](https://github.com/FunkinCrew/Funkin/pull/7586)
|
||||
- Scrolling Freeplay after the rank slam animation now properly updates the song preview. ([347f7cf](https://github.com/FunkinCrew/Funkin/commit/347f7cfecbe91fc06e71a502ee58a5d7859be5fc)) - by @AnimatingLegend in [#7230](https://github.com/FunkinCrew/Funkin/pull/7230)
|
||||
- Earning a new rank no longer causes the song title to clip incorrectly. ([0b6198f](https://github.com/FunkinCrew/Funkin/commit/0b6198f23ad7a957d40eaaf6d4af9b976e6e1a36)) - by @KoloInDaCrib in [#7350](https://github.com/FunkinCrew/Funkin/pull/7350)
|
||||
- Selecting a Freeplay song capsule no longer occasionally squashes the text. ([bdf51dc](https://github.com/FunkinCrew/Funkin/commit/bdf51dcd4392a7d99c9837bd3b56b4e6497cf207)) - by @Lasercar in [#6038](https://github.com/FunkinCrew/Funkin/pull/6038)
|
||||
- The Freeplay backing image now respects modified alpha values. ([840c043](https://github.com/FunkinCrew/Funkin/commit/840c0431ecaf3004901bd09a346c126eb8e2f484)) - by @Luscious77 in [#7576](https://github.com/FunkinCrew/Funkin/pull/7576)
|
||||
- Removed clipping from the OST Vol 1 album title sprite. ([90282d7](https://github.com/FunkinCrew/funkin.assets/commit/90282d78c6a326f1c1e05bec3f3638d3f0cd66a9)) - by @LeGooeyy in [funkin.assets#410](https://github.com/FunkinCrew/funkin.assets/pull/410)
|
||||
- The Freeplay change character hint now updates consistently when a gamepad is connected. ([e0af5e2](https://github.com/FunkinCrew/Funkin/commit/e0af5e282e6cf2ad0a63dbf633eb325204fbd649)) - by @MrMadera in [#7409](https://github.com/FunkinCrew/Funkin/pull/7409)
|
||||
- Character Select nametags no longer become stuck pixelated when switching between characters. ([a62e1c0](https://github.com/FunkinCrew/Funkin/commit/a62e1c08ab4a8cbe1f0bc790e4c228b5b64f0071)) - by @NotHyper-474 in [#7217](https://github.com/FunkinCrew/Funkin/pull/7217)
|
||||
- Pressing a note with two different keybinds now properly penalizes health. ([d60fe07](https://github.com/FunkinCrew/Funkin/commit/d60fe0726f1cab3999a35ff497ba32e82afbd1b8)) - by @realvirtu in [#7744](https://github.com/FunkinCrew/Funkin/pull/7744)
|
||||
- Input latency is now calculated correctly when hitting a note late. ([b97012a](https://github.com/FunkinCrew/Funkin/commit/b97012a10d54e222a3f370956d0e42f8d8eaab47)) - by @Lasercar in [#7367](https://github.com/FunkinCrew/Funkin/pull/7367)
|
||||
- Conductor events are no longer dispatched when a substate is active. ([19610c4](https://github.com/FunkinCrew/Funkin/commit/19610c43099dfaf4a8b9ae70dc7f4b1833f420a9)) - by @KoloInDaCrib in [#6886](https://github.com/FunkinCrew/Funkin/pull/6886)
|
||||
- Health icon angles now lerp at the proper rate. ([2bb5397](https://github.com/FunkinCrew/Funkin/commit/2bb5397c2b9e7fcc9d62670c6a86ebce64737f46)) - by @Starexify in [#7222](https://github.com/FunkinCrew/Funkin/pull/7222)
|
||||
- Hold note covers no longer disappear when too many are on screen at once. ([f0a5188](https://github.com/FunkinCrew/Funkin/commit/f0a5188cb11cde3f6646254a39953e7b064dd7e9)) - by @realvirtu in [#7593](https://github.com/FunkinCrew/Funkin/pull/7593)
|
||||
- The notestyle now properly falls back to the default notestyle in PlayState. ([ac10239](https://github.com/FunkinCrew/Funkin/commit/ac102396d71609b61f8864c2dad72b8d4b647dd1)) - by @NotHyper-474 in [#7721](https://github.com/FunkinCrew/Funkin/pull/7721)
|
||||
- Using characters outside of PlayState no longer tries to create health icons. ([da1e8e4](https://github.com/FunkinCrew/Funkin/commit/da1e8e4664dfdd098794aa7187e15c85d020508c)) - by @zxcksharks in [#7646](https://github.com/FunkinCrew/Funkin/pull/7646)
|
||||
- Pausing the game on the same frame a camera event is triggered no longer cancels the event. ([0e967eb](https://github.com/FunkinCrew/Funkin/commit/0e967ebefb61cb007cc84fc2032dc4a1d7c399a5)) - by @realvirtu in [#7472](https://github.com/FunkinCrew/Funkin/pull/7472)
|
||||
- Pausing while a dialogue conversation is fading out now pauses the fade tween. ([c0a483f](https://github.com/FunkinCrew/Funkin/commit/c0a483f003ca901679e7a4a3fe5a9dfacd86ea15)) - by @ahmed7p in [#7359](https://github.com/FunkinCrew/Funkin/pull/7359)
|
||||
- A-Bot's eyes now consistently follow the Focus Camera event. ([0de4f94](https://github.com/FunkinCrew/funkin.assets/commit/0de4f94e10f09f637dca2dedf2538d5ae45dcd97)) - by @ahmed7p in [funkin.assets#408](https://github.com/FunkinCrew/funkin.assets/pull/408)
|
||||
- Doppelganger Pico's vocals are now fully muted after encountering an easter egg. ([09e3b50](https://github.com/FunkinCrew/funkin.assets/commit/09e3b5025268e53c5c9415e9d2c40122c5ec4493)) - by @trayfellow in [funkin.assets#401](https://github.com/FunkinCrew/funkin.assets/pull/401)
|
||||
- The passing car in Week 4 stages no longer floats when the camera is zoomed out. ([baacbaa](https://github.com/FunkinCrew/funkin.assets/commit/baacbaa45469a5497e0ac4e35dc772214beef763)) - by @realvirtu in [funkin.assets#415](https://github.com/FunkinCrew/funkin.assets/pull/415)
|
||||
- Spirit's icon no longer renders behind the health bar in some cases. ([4f96d2c](https://github.com/FunkinCrew/Funkin/commit/4f96d2c070c2768327c6fcd5983dd6a4458f61b3)) - by @NotHyper-474 in [#7676](https://github.com/FunkinCrew/Funkin/pull/7676)
|
||||
- The Stress background tankmen now pause their flickering when the game is paused. ([25c7810](https://github.com/FunkinCrew/funkin.assets/commit/25c781024d4299c15c42a23d2ed788c9e34785fa)) - by @ahmed7p in [funkin.assets#405](https://github.com/FunkinCrew/funkin.assets/pull/405)
|
||||
- Optimized the rimlight shader to improve performance in the Week 7 Erect stage. ([0e82016](https://github.com/FunkinCrew/Funkin/commit/0e8201623240ed189ce8517431e73eb6a0d8b50c)) - by @iLauncherDev in [#7517](https://github.com/FunkinCrew/Funkin/pull/7517)
|
||||
- Selecting between events of different types while searching in the Events window no longer crashes the Chart Editor. ([05c81bc](https://github.com/FunkinCrew/Funkin/commit/05c81bc622fbe8eeaefbc685389c18d8944243b2)) - by @Infinite-SUDO67 in [#7767](https://github.com/FunkinCrew/Funkin/pull/7767)
|
||||
- Selecting between notes with different notekinds while searching in the Notes window no longer crashes the Chart Editor. ([b42cd4b](https://github.com/FunkinCrew/Funkin/commit/b42cd4b6e17ac9bbff9934a69b10c7fbb2e6f5e6)) - by @kiryvajiravuth in [#7761](https://github.com/FunkinCrew/Funkin/pull/7761)
|
||||
- Chart Editor dropdowns no longer lock focus onto them after selecting an item. ([86f2f44](https://github.com/FunkinCrew/Funkin/commit/86f2f44b468a25c060240911765a8b210867418b)) - by @VICK-sys in [#7528](https://github.com/FunkinCrew/Funkin/pull/7528)
|
||||
- Health icons now consistently appear in the Chart Editor. ([1fce75f](https://github.com/FunkinCrew/Funkin/commit/1fce75feb99988a4757f620968f4ab53d68111c7)) - by @Starexify in [#7193](https://github.com/FunkinCrew/Funkin/pull/7193)
|
||||
- Chart Editor Results Screen music no longer persists into gameplay when hot-reloading with F5. ([0b08668](https://github.com/FunkinCrew/Funkin/commit/0b086689e82c6fd6cac0d96b4cdca7b18543659d)) - by @AnimatingLegend in [#7126](https://github.com/FunkinCrew/Funkin/pull/7126)
|
||||
- Chart Editor playtests now only carry over custom playback rates when "Use Editor Audio Settings" is enabled. ([7f8a1ab](https://github.com/FunkinCrew/Funkin/commit/7f8a1ab6d067db0b2cd7d16f75d08cc2bce6731d)) - by @NotHyper-474 in [#7483](https://github.com/FunkinCrew/Funkin/pull/7483)
|
||||
- Packaged song scripts no longer create errors during Chart Editor playtests. ([b75add7](https://github.com/FunkinCrew/Funkin/commit/b75add7c59d338606b7004f5814e976aaa074a8f)) - by @ahmed7p in [#7470](https://github.com/FunkinCrew/Funkin/pull/7470)
|
||||
- Saving a chart or metadata file through the Difficulty toolbox now saves with the correct file name. ([6aa8bc3](https://github.com/FunkinCrew/Funkin/commit/6aa8bc3ce93affbe69bf7b39300c62f60e912cce)) - by @NebulaStellaNova in [#7571](https://github.com/FunkinCrew/Funkin/pull/7571)
|
||||
- The Chart Editor background now scales properly on widescreen resolutions. ([2e4115a](https://github.com/FunkinCrew/Funkin/commit/2e4115a33cee591f28433b92da4ead2e64da90fa)) - by @JVNpixels in [#7741](https://github.com/FunkinCrew/Funkin/pull/7741)
|
||||
- The Stage Editor no longer crashes when loading in Texture Atlas props. ([e8d91e0](https://github.com/FunkinCrew/Funkin/commit/e8d91e0f1f6aff6a62b4946868f5dfe6d6b2d461)) - by @KoloInDaCrib in [#7674](https://github.com/FunkinCrew/Funkin/pull/7674)
|
||||
- Folders in the mod folder without Polymod metadata no longer display an error. ([6ab6bc6](https://github.com/FunkinCrew/Funkin/commit/6ab6bc62e7bd81e218747ed4446089f04a938811)) - by @Starexify in [#7282](https://github.com/FunkinCrew/Funkin/pull/7282)
|
||||
- Enforced the Polymod blacklist in ReflectUtil. ([66d191d](https://github.com/FunkinCrew/Funkin/commit/66d191d43102f75f672478bd2efd9c7e820c1c05)) - by @FuroYT in [#7005](https://github.com/FunkinCrew/Funkin/pull/7005)
|
||||
- Blacklisted a class for security. ([3752232](https://github.com/FunkinCrew/Funkin/commit/3752232e3ab6ed0cb41445cb50729e74f338fa44)) - by @charlesisfeline in [#7512](https://github.com/FunkinCrew/Funkin/pull/7512)
|
||||
|
||||
## New Contributors for 0.8.6
|
||||
|
||||
* @moxie-coder made their first contribution in [#7187](https://github.com/FunkinCrew/Funkin/pull/7187)
|
||||
* @ahmed7p made their first contribution in [#7470](https://github.com/FunkinCrew/Funkin/pull/7470)
|
||||
* @iLauncherDev made their first contribution in [#7517](https://github.com/FunkinCrew/Funkin/pull/7517)
|
||||
* @Luscious77 made their first contribution in [#7576](https://github.com/FunkinCrew/Funkin/pull/7576)
|
||||
* @VICK-sys made their first contribution in [#7528](https://github.com/FunkinCrew/Funkin/pull/7528)
|
||||
* @MRK2009 made their first contribution in [#7686](https://github.com/FunkinCrew/Funkin/pull/7686)
|
||||
* @kiryvajiravuth made their first contribution in [#7761](https://github.com/FunkinCrew/Funkin/pull/7761)
|
||||
* @Infinite-SUDO67 made their first contribution in [#7767](https://github.com/FunkinCrew/Funkin/pull/7767)
|
||||
* @nykwono made their first contribution in [#7792](https://github.com/FunkinCrew/Funkin/pull/7792)
|
||||
* @WizardMantis441 made their first contribution in [funkin.assets#413](https://github.com/FunkinCrew/funkin.assets/pull/413)
|
||||
|
||||
|
||||
|
||||
## [0.8.5] - 2026-04-06
|
||||
|
||||
### Fixed
|
||||
|
||||
- [ANDROID] Fixed various issues with visuals, controls, and gamepad functionality.
|
||||
|
||||
|
||||
|
||||
## [0.8.4] - 2026-03-26
|
||||
|
||||
### Added
|
||||
|
||||
- Added several new features to Polymod:
|
||||
- Added FULL support for abstracts! (Previously, only `FlxColor` was supported)
|
||||
- Added support for getting the code of a single character string (i.e `’h’.code`) (Thanks NotHyper-474!)
|
||||
- Added support for import defaults (`import.hx`/`import.hxc`), allowing scripted classes with the same package to share imports. (Thanks KoloInDaCrib!)
|
||||
- Added `scriptInit` and `listScriptClasses` functions to scripted classes. (Thanks KoloInDaCrib!)
|
||||
- `.hx` files can now be parsed. (Thanks Starexify!)
|
||||
- Added support for preprocessing (`#if`/`#else` syntax), allowing for platform-specific code to be implemented in an easier way. (Thanks KoloInDaCrib!)
|
||||
- Added support for mod IDs. (Thanks Starexify!)
|
||||
- Implemented `_merge` support for scripts. (Thanks KoloInDaCrib!)
|
||||
- Please refer to the Cookbook to learn how to use this.
|
||||
- Added widescreen scale properties to the Zoom Camera event in the Chart Editor to account for widescreen resolutions.
|
||||
- Added a flipY field for Story Mode level props. ([48ed659](https://github.com/FunkinCrew/Funkin/commit/48ed65980005366371fda7a66c04f73bb5b86200)) - by @ExtraCode75 in [#6340](https://github.com/FunkinCrew/Funkin/pull/6340)
|
||||
- Implemented working start and end times for Freeplay song previews. ([40eab2e](https://github.com/FunkinCrew/Funkin/commit/40eab2e4618ebb6dc67a06ef67df817920773c56)) - by @ADA-Funni in [#6725](https://github.com/FunkinCrew/Funkin/pull/6725)
|
||||
- Added a new albumOSTName property to Freeplay album data to make the "OFFICIAL OST" text moddable. ([67d2a98](https://github.com/FunkinCrew/Funkin/commit/67d2a9811b5c92409bdc76e287c984d5777d8621)) - by @NotHyper-474 in [#6578](https://github.com/FunkinCrew/Funkin/pull/6578)
|
||||
- Added an optional 'capsule' field to level data to display any week label on Freeplay capsules. ([528e9e4](https://github.com/FunkinCrew/Funkin/commit/528e9e4f03c40e59f3932d8b4c522b6eeb66783b)) - by @Trayfellow in [#7149](https://github.com/FunkinCrew/Funkin/pull/7149)
|
||||
- Implemented ScriptedBaseFreeplayDJ, allowing modders to customize how custom Freeplay DJs are rendered. ([423ccfa](https://github.com/FunkinCrew/Funkin/commit/423ccfab98a29646e4998dacedaf403319d956ff)) - by @PurSnake in [#6806](https://github.com/FunkinCrew/Funkin/pull/6806)
|
||||
- Added a new FunkinGroup class to make groups of sprites easier to modify. ([4f31600](https://github.com/FunkinCrew/Funkin/commit/4f316003af9a6ca46c77bf4971059e20543cbd7b)) - by @MightyTheArmiddilo in [#6758](https://github.com/FunkinCrew/Funkin/pull/6758)
|
||||
- Added `Reflect.makeVarArgs` to allow modders to create functions with a variable number of arguments. ([3633df3](https://github.com/FunkinCrew/Funkin/commit/3633df3fdc6dc0af4f9886fcb1e1d4a8d2b8d5aa)) - by @Starexify in [#6738](https://github.com/FunkinCrew/Funkin/pull/6738)
|
||||
- Added script event support for song events. ([15bef89](https://github.com/FunkinCrew/Funkin/commit/15bef89d71982c5685f4ce6f6d7e6e4d8321508c)) - by @KoloInDaCrib in [#4130](https://github.com/FunkinCrew/Funkin/pull/4130)
|
||||
- Added a new Chart Editor event type: Set Target Bop Speed. ([1893f2b](https://github.com/FunkinCrew/Funkin/commit/1893f2b2f679d8a4d262052793dde24e94719ee6)) - by @roma-perec-bp in [#6769](https://github.com/FunkinCrew/Funkin/pull/6769)
|
||||
- Added shortcuts to select all notes above or below the playhead in the Chart Editor. ([08b3af9](https://github.com/FunkinCrew/Funkin/commit/08b3af959d6657511bfe8418da545731050cb24a)) - by @Lasercar in [#4306](https://github.com/FunkinCrew/Funkin/pull/4306)
|
||||
- Added the ability to view and edit the timing of a note or event through the Chart Editor context menu. ([a782b3f](https://github.com/FunkinCrew/Funkin/commit/a782b3f9e8498634babb864341fd1437bb2c01f6)) - by @Lasercar in [#4200](https://github.com/FunkinCrew/Funkin/pull/4200)
|
||||
- Added an "Edit Note" option to the Chart Editor context menu that opens the Notes window. ([e710198](https://github.com/FunkinCrew/Funkin/commit/e710198afec9a0fe19effe4cd196ab3a247f4784)) - by @Honton129 in [#7010](https://github.com/FunkinCrew/Funkin/pull/7010)
|
||||
- Added the ability to Ctrl-click on health icons in the Chart Editor to open character previews. ([011f154](https://github.com/FunkinCrew/Funkin/commit/011f1541b197fd4f962ab8a910cbd417f78c2d09)) - by @Trofem in [#7089](https://github.com/FunkinCrew/Funkin/pull/7089)
|
||||
|
||||
### Changed
|
||||
|
||||
- Upgraded the input handling system from SDL2 to SDL3!
|
||||
- Added an “Unlocked Framerate” preference to Desktop platforms.
|
||||
- The input system is now much more responsive and accurate down to the nanosecond.
|
||||
- The game now properly supports more controllers and input devices.
|
||||
- The game now shows popups when installed mods have issues, such as when the API version is incorrect.
|
||||
- Unfocusing the game now reduces the game’s volume to 25% (down from 50%).
|
||||
- The notekinds dropdown are no longer hardcoded in the Chart Editor.
|
||||
- The Character Select key is now hidden in the Controls menu until a new character is unlocked. ([6c13444](https://github.com/FunkinCrew/Funkin/commit/6c134442118d3f5f61b9e3faa631512d210422fb)) - by @Lasercar in [#4882](https://github.com/FunkinCrew/Funkin/pull/4882)
|
||||
- The Story Mode level score now displays with commas. ([04fffe8](https://github.com/FunkinCrew/Funkin/commit/04fffe8ade4c4b236d59a236f08534e8eede179f)) - by @JVNpixels in [#4965](https://github.com/FunkinCrew/Funkin/pull/4965)
|
||||
- Freeplay capsule week labels are now softcoded and rendered using a font. ([48752e4](https://github.com/FunkinCrew/Funkin/commit/48752e444cc5f1b8cd0a3b579f843e9ab6580c46)) - by @KoloInDaCrib in [#5249](https://github.com/FunkinCrew/Funkin/pull/5249)
|
||||
- The Freeplay change character hint now changes when a gamepad is connected. ([0f7859b](https://github.com/FunkinCrew/Funkin/commit/0f7859bfb6b829290804efab9d5c67fbdbec0903)) - by @MrMadera in [#6609](https://github.com/FunkinCrew/Funkin/pull/6609)
|
||||
- Moved the Winter Horrorland intro cutscene logic into a script. ([9bbe73b](https://github.com/FunkinCrew/funkin.assets/commit/9bbe73b21ccbea29a5d5187709f91b4822bf7e31)) - by @mario64thane in [funkin.assets#63](https://github.com/FunkinCrew/funkin.assets/pull/63)
|
||||
- Merged FlxFilteredSprite functionality into FunkinSprite. ([22736b2](https://github.com/FunkinCrew/Funkin/commit/22736b27da7d8de8b11ab6cc6c2a622e5579dccd)) - by @TechnikTil in [#7114](https://github.com/FunkinCrew/Funkin/pull/7114)
|
||||
- Adjusted some wording in the Chart/Stage Editor backup window to be clearer. ([a607396](https://github.com/FunkinCrew/Funkin/commit/a607396d04f24388691ee23bd04022681ca54756)) - by @Marcosayfi in [#7071](https://github.com/FunkinCrew/Funkin/pull/7071)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Conjoined string interpolation `$a$b` now parses properly in Polymod.
|
||||
- Video cutscenes are no longer muted at volumes of 3 or lower.
|
||||
- Video cutscenes no longer occasionally show glitches at the beginning.
|
||||
- [MOBILE] Loading a cloud save from Newgrounds no longer carries over the volume level from Desktop.
|
||||
- [HTML5] Scrolling the game out of view now pauses the game instead of allowing gameplay to continue processing.
|
||||
- The Boyfriend Freeplay DJ new rank animation now transitions smoothly back to its idle animation.
|
||||
- Hold notes now score much more consistently across different framerate values.
|
||||
- The bricks in Week 7 stages are now better quality.
|
||||
- Trimmed out the silent beat at the beginning of Ugh Erect.
|
||||
- Camera bopping no longer stops at zoom values of 1.35x or higher.
|
||||
- Charting many hold notes in a row no longer breaks audio handling.
|
||||
- Adding collapsible frames in event schemas no longer crashes the game.
|
||||
- Some event properties have been grouped under Advanced frames.
|
||||
- Chart Editor dropdowns no longer refocus when a tooltip appears.
|
||||
- Focus and Zoom Camera event durations now account for playback speed.
|
||||
- [WINDOWS] Exiting the game no longer leaves it running as a background process. ([881aba3](https://github.com/FunkinCrew/Funkin/commit/881aba3b03a26764374441cab244cd2d360a30b9)) - by @AnimatingLegend in [#6885](https://github.com/FunkinCrew/Funkin/pull/6885)
|
||||
- Story Mode now only shows difficulties that all of a level's songs have. ([365f8dc](https://github.com/FunkinCrew/Funkin/commit/365f8dcfea9569f2edba1ebfceb3d49819ad2b57)) - by @Starexify in [#7046](https://github.com/FunkinCrew/Funkin/pull/7046)
|
||||
- The Girlfriend Story Mode prop now bops continuously when scrolling through levels. ([84b2d5b](https://github.com/FunkinCrew/Funkin/commit/84b2d5b48d9eb76c918fdba6987ccc1f5da76133)) - by @Redar13 in [#6830](https://github.com/FunkinCrew/Funkin/pull/6830)
|
||||
- The Freeplay new rank slam animation now properly plays its glow effect. ([fcbce0a](https://github.com/FunkinCrew/Funkin/commit/fcbce0a66b75b0c1224c6a0e2907c170b71998ad)) - by @FuroYT in [#7015](https://github.com/FunkinCrew/Funkin/pull/7015)
|
||||
- The Freeplay Random capsule no longer displays BPM and difficulty numbers. ([0ad2d50](https://github.com/FunkinCrew/Funkin/commit/0ad2d507efa9dcb577184e28bfd04091b3424bfb)) - by @Lasercar in [#4927](https://github.com/FunkinCrew/Funkin/pull/4927)
|
||||
- Favoriting a song in Freeplay no longer breaks capsule text cycling. ([ce493a0](https://github.com/FunkinCrew/Funkin/commit/ce493a03c9ffb4c43c2c27885ed0fab0c1c3531d)) - by @realvirtu in [#7134](https://github.com/FunkinCrew/Funkin/pull/7134)
|
||||
- Freeplay songs with invalid pixel icons no longer duplicate the icon from the previous song in the list. ([b3eb709](https://github.com/FunkinCrew/Funkin/commit/b3eb709f4ed535ed2544f3bb530ff3724e07be3f)) - by @FuroYT in [#7006](https://github.com/FunkinCrew/Funkin/pull/7006)
|
||||
- A Freeplay clear percent of 100% now properly exits to the right when returning to the Main Menu. ([5974c1a](https://github.com/FunkinCrew/Funkin/commit/5974c1a48293f3185c5f249acb9130ebd6b35ae4)) - by @Trayfellow in [#7183](https://github.com/FunkinCrew/Funkin/pull/7183)
|
||||
- Nudged the Freeplay backing image down by one pixel to align with the bottom of the screen. ([b8c2854](https://github.com/FunkinCrew/Funkin/commit/b8c2854007f36ac7a2b6897eead3f979e11f0ad7)) - by @SuperEric1 in [#6893](https://github.com/FunkinCrew/Funkin/pull/6893)
|
||||
- Improved performance for songs that use a lot of events. ([3b27ec5](https://github.com/FunkinCrew/Funkin/commit/3b27ec5b66b2fa00d59a77f6ec07aff68e440860)) - by @KoloInDaCrib in [#7171](https://github.com/FunkinCrew/Funkin/pull/7171)
|
||||
- Adjusted hit window logic to accurately reflect threshold values for all judgments. ([dcb5b3a](https://github.com/FunkinCrew/Funkin/commit/dcb5b3a9358a9bb126153b57aa2d38dc0684c39d)) - by @Rudyrue in [#7104](https://github.com/FunkinCrew/Funkin/pull/7104)
|
||||
- Adjusted offsets for all health icons to be more consistent. ([83d8134](https://github.com/FunkinCrew/funkin.assets/commit/83d8134f9d0b3cf3b59e9e1d972fa1e200a98ba1)) - by @LeGooeyy in [funkin.assets#278](https://github.com/FunkinCrew/funkin.assets/pull/278)
|
||||
- Hold notes no longer shift upward when hit early. ([d62c8af](https://github.com/FunkinCrew/Funkin/commit/d62c8af20c90ec3d6e4274aba8ddbfb378ab0256)) - by @realvirtu in [#7060](https://github.com/FunkinCrew/Funkin/pull/7060)
|
||||
- The opponent no longer stops singing upon missing if Boyfriend has no vocals file. ([cea54e3](https://github.com/FunkinCrew/Funkin/commit/cea54e394c78544dd0ec0339721faaac140caa65)) - by @FuroYT in [#7007](https://github.com/FunkinCrew/Funkin/pull/7007)
|
||||
- onPause script functions now properly trigger when pausing during a cutscene or dialogue. ([5a0b431](https://github.com/FunkinCrew/Funkin/commit/5a0b4310a2c39b033989e0e36b8f456bdac65a5b)) - by @MightyTheArmiddilo in [#6804](https://github.com/FunkinCrew/Funkin/pull/6804)
|
||||
- Camera events now consistently pause when the Pause Menu is opened. ([e623439](https://github.com/FunkinCrew/Funkin/commit/e6234397f57d2af37035a0ff2504b8241e23949d)) - by @realvirtu in [#7145](https://github.com/FunkinCrew/Funkin/pull/7145)
|
||||
- The Pause Menu global offset value now adjusts at the same rate across all framerates. ([348647f](https://github.com/FunkinCrew/Funkin/commit/348647f48629a24ee3bd2b759bbfc1bff168fb81)) - by @KolzeYT in [#7147](https://github.com/FunkinCrew/Funkin/pull/7147)
|
||||
- Spirit's trail effect now renders consistently across all framerates. ([75506f7](https://github.com/FunkinCrew/Funkin/commit/75506f71a97d468f516a0232c8be5560afb0682e)) - by @KolzeYT in [#7179](https://github.com/FunkinCrew/Funkin/pull/7179)
|
||||
- The sound tray now appears consistently and plays sound effects at the right volume. ([2b9906d](https://github.com/FunkinCrew/Funkin/commit/2b9906df29660057410d3054e897012896896d6a)) - by @Raltyro in [#7068](https://github.com/FunkinCrew/Funkin/pull/7068)
|
||||
- The sticker transition now properly pauses when losing focus with Pause on Unfocus enabled. ([8a1d74b](https://github.com/FunkinCrew/Funkin/commit/8a1d74b82cceab97e777dc49e7a2117b8d27e59b)) - by @ComedyLost in [#7129](https://github.com/FunkinCrew/Funkin/pull/7129)
|
||||
- [HTML5] Rimlight alt masks now render properly. ([0613e9d](https://github.com/FunkinCrew/Funkin/commit/0613e9d295179e66d30db3d2f6805870eac847d6)) - by @realvirtu in [#6900](https://github.com/FunkinCrew/Funkin/pull/6900)
|
||||
- The Week 2 Erect stage lightning strike fade now pauses and cancels appropriately. ([cd05267](https://github.com/FunkinCrew/funkin.assets/commit/cd05267023859d04cc8920c787b8280682e5f0f5)) - by @ComedyLost in [funkin.assets#390](https://github.com/FunkinCrew/funkin.assets/pull/390)
|
||||
- A-Bot (Dark)'s frame no longer renders as completely dark in Week 2 Erect. ([a142530](https://github.com/FunkinCrew/funkin.assets/commit/a142530cae6198ca17b560ff73e36d50f1582768)) - by @ComedyLost in [funkin.assets#368](https://github.com/FunkinCrew/funkin.assets/pull/368)
|
||||
- Dying on the same frame as a lightning strike in Week 2 Erect no longer throws a script error. ([ef89bde](https://github.com/FunkinCrew/funkin.assets/commit/ef89bde19c397f15a53b0fda2f64ba93ff96f56f)) - by @KoloInDaCrib in [funkin.assets#363](https://github.com/FunkinCrew/funkin.assets/pull/363)
|
||||
- Pico (Dark) and Nene (Dark) no longer throw script errors in debug editors. ([b16ce44](https://github.com/FunkinCrew/funkin.assets/commit/b16ce44beb43d4511c61418c824929fb4dfabb63)) - by @ComedyLost in [funkin.assets#367](https://github.com/FunkinCrew/funkin.assets/pull/367)
|
||||
- Girlfriend's hair no longer falls when restarting the song in a Week 3 stage. ([ade80ab](https://github.com/FunkinCrew/funkin.assets/commit/ade80ab72915ddd47724c380bb41d6df4c1b79bd)) - by @AnimatingLegend in [funkin.assets#370](https://github.com/FunkinCrew/funkin.assets/pull/370)
|
||||
- The camera transition to Results no longer reveals the edges of stage art in the Week 6 Erect stage. ([ecf4c54](https://github.com/FunkinCrew/funkin.assets/commit/ecf4c5458a2e1fadba7db31c3272cea485d22b2f)) - by @ComedyLost in [funkin.assets#383](https://github.com/FunkinCrew/funkin.assets/pull/383)
|
||||
- Fine-tuned offsets for pixel characters. ([8b3c268](https://github.com/FunkinCrew/funkin.assets/commit/8b3c2680a6a966e81b62598e783c60f46355c759)) - by @CEliuxJV in [funkin.assets#376](https://github.com/FunkinCrew/funkin.assets/pull/376)
|
||||
- Tankman's game over lines now properly play during game overs in Ugh (Pico Mix) and Guns (Pico Mix). ([b900208](https://github.com/FunkinCrew/funkin.assets/commit/b900208143f980adee25d70db247e0b176dd659c)) - by @hucks5 in [funkin.assets#373](https://github.com/FunkinCrew/funkin.assets/pull/373)
|
||||
- Restarting during the mid-song animation in Stress (Pico Mix) now properly resets the characters' animations. ([2ca92de](https://github.com/FunkinCrew/funkin.assets/commit/2ca92de46eced3f53d305579704fcb7e8c051f3a)) - by @requazar in [funkin.assets#364](https://github.com/FunkinCrew/funkin.assets/pull/364)
|
||||
- The rain shader now properly fades out with the transition to the Results Screen. ([a0caa41](https://github.com/FunkinCrew/Funkin/commit/a0caa41edcb26298e4f8c243a5eed0b4fe93fcf7)) - by @realvirtu in [#6776](https://github.com/FunkinCrew/Funkin/pull/6776)
|
||||
- Exiting a Chart Editor playtest while using the pixel notestyle no longer crashes the game. ([6c1f380](https://github.com/FunkinCrew/Funkin/commit/6c1f3800dbc9b13fb4b409abce53c1dafc9bbe8f)) - by @Starexify and @KoloInDaCrib in [#7108](https://github.com/FunkinCrew/Funkin/pull/7108)
|
||||
- Chart Editor Edit buttons are now appropriately disabled when nothing is selected. ([6b1fc03](https://github.com/FunkinCrew/Funkin/commit/6b1fc0372bca202d80f4ccf316580b13a5a80879)) - by @Lasercar in [#4386](https://github.com/FunkinCrew/Funkin/pull/4386)
|
||||
- Undoing a Chart Editor event now plays the undo sound. ([f7fd7a5](https://github.com/FunkinCrew/Funkin/commit/f7fd7a57c36f0461f56c2ab627a17d752cb82320)) - by @realvirtu in [#6963](https://github.com/FunkinCrew/Funkin/pull/6963)
|
||||
- The playback speed audio setting no longer rounds incorrectly upon reopening the Chart Editor. ([3b15873](https://github.com/FunkinCrew/Funkin/commit/3b15873fc7d0c20840c313f1d2cfed91014c664f)) - by @AnimatingLegend in [#7023](https://github.com/FunkinCrew/Funkin/pull/7023)
|
||||
- The Chart Editor easing preview graph now properly displays tweens that exceed start/end values. ([7626700](https://github.com/FunkinCrew/Funkin/commit/7626700495743862caddbf50a7dafef51529a2a6)) - by @echolotl in [#7152](https://github.com/FunkinCrew/Funkin/pull/7152)
|
||||
- The Chart Editor playbar head is no longer draggable during a playtest. ([ccb874e](https://github.com/FunkinCrew/Funkin/commit/ccb874e97a121859c26a8a71b394743d27f6ed37)) - by @ComedyLost in [#6987](https://github.com/FunkinCrew/Funkin/pull/6987)
|
||||
- The Results Screen no longer shows up after a Chart Editor playtest with Bot Play enabled. ([786f19c](https://github.com/FunkinCrew/Funkin/commit/786f19c57d999dba9309cae28d912b080968670d)) - by @ComedyLost in [#7022](https://github.com/FunkinCrew/Funkin/pull/7022)
|
||||
- The Osu!Mania Chart Editor importer no longer accepts non-Osu!Mania beatmaps. ([456b2ff](https://github.com/FunkinCrew/Funkin/commit/456b2ff6c4a127733120cef3d03d6102bdd7522f)) - by @FuroYT in [#6624](https://github.com/FunkinCrew/Funkin/pull/6624)
|
||||
- Characters in the Stage Editor no longer fly away when clicking and dragging them. ([0389af2](https://github.com/FunkinCrew/Funkin/commit/0389af2202aa4dc6a21ce9b7eea95944bfaa6946)) - by @KoloInDaCrib in [#7002](https://github.com/FunkinCrew/Funkin/pull/7002)
|
||||
- Characters with alternating idle animations now properly play danceLeft when pressing Space in the Animation Editor. ([05032e3](https://github.com/FunkinCrew/Funkin/commit/05032e3126eda78a2bbf70e8c975bcb04eed201b)) - by @ComedyLost in [#7056](https://github.com/FunkinCrew/Funkin/pull/7056)
|
||||
- [LINUX] Paths are now properly sanitized as they are on other platforms. ([219143c](https://github.com/FunkinCrew/Funkin/commit/219143c02dcf65e68aec80701a82023ca0d70db6)) - by @NotHyper-474 in [#6395](https://github.com/FunkinCrew/Funkin/pull/6395)
|
||||
- OpenFL and some Lime classes are now accessible to modders. ([56a56db](https://github.com/FunkinCrew/Funkin/commit/56a56dbfaa3f62a3f684df49c682f69a496e45f4)) - by @FuroYT in [#7115](https://github.com/FunkinCrew/Funkin/pull/7115)
|
||||
- Sandboxed API classes can now be accessed by mods. ([03930a2](https://github.com/FunkinCrew/Funkin/commit/03930a29c3d8aa6a310147a7131c6b7cddefd475)) - by @MightyTheArmiddilo in [#6952](https://github.com/FunkinCrew/Funkin/pull/6952)
|
||||
- Blacklisted some more classes for security.
|
||||
- And even more fixes!
|
||||
|
||||
## New Contributors for 0.8.4
|
||||
|
||||
* @roma-perec-bp made their first contribution in [#6769](https://github.com/FunkinCrew/Funkin/pull/6769)
|
||||
* @Redar13 made their first contribution in [#6830](https://github.com/FunkinCrew/Funkin/pull/6830)
|
||||
* @SuperEric1 made their first contribution in [#6893](https://github.com/FunkinCrew/Funkin/pull/6893)
|
||||
* @AnimatingLegend made their first contribution in [#7023](https://github.com/FunkinCrew/Funkin/pull/7023)
|
||||
* @Marcosayfi made their first contribution in [#7071](https://github.com/FunkinCrew/Funkin/pull/7071)
|
||||
* @Rudyrue made their first contribution in [#7104](https://github.com/FunkinCrew/Funkin/pull/7104)
|
||||
* @KolzeYT made their first contribution in [#7147](https://github.com/FunkinCrew/Funkin/pull/7147)
|
||||
* @echolotl made their first contribution in [#7152](https://github.com/FunkinCrew/Funkin/pull/7152)
|
||||
* @mario64thane made their first contribution in [funkin.assets#63](https://github.com/FunkinCrew/funkin.assets/pull/63)
|
||||
* @LeGooeyy made their first contribution in [funkin.assets#278](https://github.com/FunkinCrew/funkin.assets/pull/278)
|
||||
* @requazar made their first contribution in [funkin.assets#364](https://github.com/FunkinCrew/funkin.assets/pull/364)
|
||||
|
||||
|
||||
|
||||
## [0.8.3] - 2026-02-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- [HTML5] Hitting a can in 2hot no longer creates a script error. (Thanks NotHyper-474!)
|
||||
- The game no longer consistently lag spikes during gameplay. ([823120c](https://github.com/FunkinCrew/Funkin/commit/823120cdef7bfbb2d3ec37c7085878fcbeebcb30)) - by @ACrazyTown in [#6970](https://github.com/FunkinCrew/Funkin/pull/6970)
|
||||
|
||||
|
||||
|
||||
## [0.8.2] - 2026-02-23
|
||||
|
||||
### Added
|
||||
|
||||
- Added 14 new blend modes, allowing the engine to render better visual effects.
|
||||
- Added a PlayState parameter that mirrors notes during a song.
|
||||
- Added preview graphs for Chart Editor event easing types. ([eea1265](https://github.com/FunkinCrew/Funkin/commit/eea12657b1d8131014a3fdc270c3f351fae6e851)) - by @PurSnake in [#6374](https://github.com/FunkinCrew/Funkin/pull/6374)
|
||||
- Added the ability to mirror notes on the X and Y axes in the Chart Editor. ([fd0c2df](https://github.com/FunkinCrew/Funkin/commit/fd0c2df35ee8cda3f1566a297c4faec984d809bb)) - by @Lasercar in [#4372](https://github.com/FunkinCrew/Funkin/pull/4372)
|
||||
- Added a deselect button and shortcut to the Stage Editor. ([a9f1d41](https://github.com/FunkinCrew/Funkin/commit/a9f1d41771f0c97fdd70d4d6c54087ac0e64ff38)) - by @Lasercar in [#5281](https://github.com/FunkinCrew/Funkin/pull/5281)
|
||||
|
||||
### Changed
|
||||
|
||||
- Made some improvements to Polymod:
|
||||
- Added string interpolation support. (Thanks NotHyper-474!)
|
||||
- Scripted classes can now extend nothing. (Thanks NotHyper-474!)
|
||||
- Scripted classes can now extend other scripted classes. (Thanks KoloInDaCrib!)
|
||||
- Tweaked some error messages to be more verbose.
|
||||
- Added `scriptHas` and `staticScriptHas` functions to check if a script has a specific variable/function.
|
||||
- The `is` operator is now more accurate to regular Haxe. (Thanks Starexify!)
|
||||
- Static functions can now use static extensions (`using`s). (Thanks NotHyper-474!)
|
||||
- `interface`s can now be properly parsed. (Thanks Starexify!)
|
||||
- Optional fields and extensions can now be used in `typedef`s. (Thanks Starexify!)
|
||||
- Added stricter checking for default/optional arguments in functions. (Thanks Starexify!)
|
||||
- May be a breaking change for some scripts, so please update your scripts to account for this!
|
||||
- Enums now have multiple arguments. (Thanks Starexify!)
|
||||
- Basic types (e.g `String`, `Int`, `Bool`, etc.) can now be used with the `is` operator without having to import the type first.
|
||||
- Tweaked charts for the following songs:
|
||||
- Bopeebo (Pico Mix) [Normal/Hard] - Adjusted note timings and added a “hey” animation event in Sections 18, 26, and 27.
|
||||
- Fresh Erect [Nightmare] - Added 2 notes where Boyfriend’s vocals echo.
|
||||
- DadBattle Erect [Nightmare] - Added a missing jack note in Section 38, added holds to two notes in Section 63.
|
||||
- DadBattle (Pico Mix) [all difficulties] - Adjusted timings for various notes in Sections 37-40 and 60.
|
||||
- Spookeez Erect [Erect/Nightmare] - Adjusted many hold note lengths to better match vocals.
|
||||
- Spookeez (Pico Mix) - Added one missing note to Section 14.
|
||||
- South Erect [Erect/Nightmare] - Adjusted many hold note lengths to better match vocals.
|
||||
- Pico [Easy] - Adjusted timings for one note each in Sections 36 and 38.
|
||||
- Pico [Normal/Hard] - Adjusted timings for Boyfriend’s right notes to be a bit earlier in Sections 31-42.
|
||||
- Pico [all difficulties] - Added a Focus Camera event on Girlfriend during the duet.
|
||||
- Satin Panties Erect [Erect/Nightmare] - Split a hold note into two for Mom in Sections 14 and 18.
|
||||
- High Erect [Erect/Nightmare] - Adjusted timing for one note each in Sections 25 and 41.
|
||||
- M.I.L.F [Easy] - Adjusted timings for two notes in Section 73.
|
||||
- M.I.L.F [Hard] - Changed one down note into an up note in Section 15 for consistency.
|
||||
- Cocoa Erect [Nightmare] - Fixed one note not being a Mom notekind in Section 24, added holds to 2 notes in Section 67.
|
||||
- Cocoa (Pico Mix) [all difficulties] - Adjusted timings for two notes in Section 15.
|
||||
- Eggnog Erect [Erect/Nightmare] - Adjusted how a grace note is charted in Section 52, added 2 missing notes for Mom in Section 72, adjusted Camera Bop event in Section 63.
|
||||
- Senpai (Pico Mix) [all difficulties] - Adjusted timing for one note in Section 10.
|
||||
- Roses [Normal] - Adjusted timings for four notes in Sections 30, 32, 41, and 43.
|
||||
- Thorns Erect [Erect] - Adjusted timings for two notes in Section 36, removed some double notes to differentiate the chart from Nightmare.
|
||||
- Ugh Erect [Erect/Nightmare] - Adjusted some Zoom Camera events around Section 24.
|
||||
- Guns (Pico Mix) [all difficulties] - Fixed many timing issues throughout the whole song.
|
||||
- SPAGHETTI [Normal/Hard] - Added one note to match Boyfriend’s rapping.
|
||||
- Darnell (BF Mix) [all difficulties] - Removed extra notes from Sections 49 and 50, adjusted various note timings throughout the song.
|
||||
- Lit Up [Normal] - Added one missing note each in Sections 40 and 60.
|
||||
- Lit Up (BF Mix) [Normal/Hard] - Adjusted timings for various grace notes in Sections 1, 52, 55, and 56.
|
||||
- 2hot [Easy/Normal] - Recharted many sections to be more predictable.
|
||||
- [macOS] Disabled high DPI to significantly improve performance on some displays.
|
||||
- Improved the Lag Adjustment menu to better handle very large offsets.
|
||||
- Chart Editor exporting now omits default values and orders values more consistently.
|
||||
- Chart Editor playtests now processes all events before the starting position.
|
||||
- Optimized the Week 2 Spooky Mansion stage background by using a texture atlas. ([2bdd5a7](https://github.com/FunkinCrew/funkin.assets/commit/2bdd5a713f0b5c7e945c457e2a4a92bdb367cc02)) - by @MaybeMaru and @Trayfellow in [funkin.assets#348](https://github.com/FunkinCrew/funkin.assets/pull/348)
|
||||
- Added more default imports for mods. ([1620cf3](https://github.com/FunkinCrew/Funkin/commit/1620cf388973eab5d83e151eec28b2c8abc84eb1)) - by @Starexify in [#6706](https://github.com/FunkinCrew/Funkin/pull/6706)
|
||||
- The Set Camera Bop event now supports decimal values for rate and offset at 0.25 precision. ([ffaba34](https://github.com/FunkinCrew/Funkin/commit/ffaba343258c4a0e5ee7e1bd7fa0e8138ae60bc1)) - by @KoloInDaCrib in [#6741](https://github.com/FunkinCrew/Funkin/pull/6741)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed some issues with Polymod:
|
||||
- The super constructor for scripted classes can now accept more than 4 arguments. (Thanks NotHyper-474!)
|
||||
- Functions can now accept more than 8 arguments. (Thanks NotHyper-474!)
|
||||
- Script variables are no longer dropped early when passing them to a callback (ex. `FlxTimer`). (Thanks NotHyper-474!)
|
||||
- Fix a memory leak that could happen if a script tried to reference an anonymous object with a lot of `StringMap`s. (Thanks NotHyper-474!)
|
||||
- Properties (`get_`/`set_` functions) are now much more accurate to regular Haxe. (Thanks NotHyper-474!)
|
||||
- Re-exported some assets to fix some issues:
|
||||
- Re-exported all variations of Pico as texture atlases to optimize memory usage.
|
||||
- Freeplay DJ Pico’s table sparks no longer persist when his gun is lifted.
|
||||
- Pico (Blazin’)’s game over retry animation now properly displays its blend modes.
|
||||
- Pico (Christmas) no longer shows several stray marks around his sprites.
|
||||
- Nene (Christmas) no longer becomes slightly offset when her knife is raised.
|
||||
- The running tankmen in Stress (Pico Mix) no longer tank the game’s performance.
|
||||
- Daddy Dearest now properly holds his up pose.
|
||||
- Monster (Christmas)’s hat no longer moves while he holds a pose.
|
||||
- Darnell’s can in 2hot now shows a sparkling effect.
|
||||
- [DESKTOP] Modded atlas characters with both .png and .astc spritesheets no longer crash the game.
|
||||
- [DESKTOP] The game display no longer sometimes becomes offset from the window.
|
||||
- [MOBILE] Selecting a song using touch controls when a keyboard is connected no longer disables the keyboard strumline layout.
|
||||
- [ANDROID] Improved Freeplay scrolling behavior on high framerate displays.
|
||||
- [WINDOWS] Chart Editor save dialog windows no longer freeze the game.
|
||||
- The Chart Editor Results Screen playtest option now consistently shows the Results Screen after each playtest.
|
||||
- Scrolling really quickly in Freeplay no longer crashes the game. ([76699b2](https://github.com/FunkinCrew/Funkin/commit/76699b235cd5b359bc34e6950cd05bbbb13918f8)) - by @ComedyLost in [#6962](https://github.com/FunkinCrew/Funkin/pull/6962)
|
||||
- Fixed a memory leak in the Freeplay menu. ([910ba65](https://github.com/FunkinCrew/Funkin/commit/910ba650b0c1011802b151b85f4a9d8177ae95c7)) - by @KoloInDaCrib in [#6615](https://github.com/FunkinCrew/Funkin/pull/6615)
|
||||
- Modded difficulty dots and graphics now render correctly in Freeplay. ([90b856d](https://github.com/FunkinCrew/Funkin/commit/90b856d88635ac4e5517e934298e3820b2e5f45c)) - by @ComedyLost in [#6205](https://github.com/FunkinCrew/Funkin/pull/6205)
|
||||
- Freeplay capsules with long song names no longer display too far to the left during the new rank animation. ([17a914c](https://github.com/FunkinCrew/Funkin/commit/17a914c933592cb3ba79881ca6a8d900b8513cbc)) - by @realvirtu in [#6690](https://github.com/FunkinCrew/Funkin/pull/6690)
|
||||
- Freeplay capsule BPM values ending in 1 now display with proper spacing. ([e5b4351](https://github.com/FunkinCrew/Funkin/commit/e5b43510dd810a74a7d06f7f02c52892d11d6f8b)) - by @realvirtu in [#6696](https://github.com/FunkinCrew/Funkin/pull/6696)
|
||||
- The Freeplay pixel icon now properly plays its confirm animation when mashing the capsule. ([a56bc44](https://github.com/FunkinCrew/Funkin/commit/a56bc4462d1c49e8ec71462b9bd7ff338b743c93)) - by @realvirtu in [#6723](https://github.com/FunkinCrew/Funkin/pull/6723)
|
||||
- [HTML5] Scrolling with the mouse now works properly in Story Mode and Freeplay. ([506d80b](https://github.com/FunkinCrew/Funkin/commit/506d80b287b969121dc3601714c2459cc71f7e55)) - by @realvirtu in [#6621](https://github.com/FunkinCrew/Funkin/pull/6621)
|
||||
- Optimized rendering in the Character Select menu. ([2ecebf7](https://github.com/FunkinCrew/Funkin/commit/2ecebf79205a66b64148d64bbb3162c9fc073d85)) - by @MaybeMaru in [#6789](https://github.com/FunkinCrew/Funkin/pull/6789)
|
||||
- [MOBILE] Tapping on a lock in Character Select now plays its reject animation. ([05148f0](https://github.com/FunkinCrew/Funkin/commit/05148f0e5dad4d60089e6074e616b583ba29a5e6)) - by @realvirtu in [#6779](https://github.com/FunkinCrew/Funkin/pull/6779)
|
||||
- Hold note covers now follow when the strumline position is modified. ([77c6651](https://github.com/FunkinCrew/Funkin/commit/77c6651e245ea276b1bdf33e5d6732073dcb6037)) - by @MightyTheArmiddilo in [#6746](https://github.com/FunkinCrew/Funkin/pull/6746)
|
||||
- The pause and game over screens no longer sometimes play the wrong character's themes. ([878644a](https://github.com/FunkinCrew/Funkin/commit/878644aee7ba425e482707b94b9f887ec23f6306)) - by @KoloInDaCrib in [#6812](https://github.com/FunkinCrew/Funkin/pull/6812)
|
||||
- The game over camera focus point is now consistent, regardless of which animation was previously playing. ([18cceb4](https://github.com/FunkinCrew/Funkin/commit/18cceb4946a51fda0009d77baae1115437694415)) - by @KoloInDaCrib in [#6705](https://github.com/FunkinCrew/Funkin/pull/6705)
|
||||
- Pico (Pixel) and other pixel characters now use RetroCameraFade as Boyfriend (Pixel) does. ([d1382aa](https://github.com/FunkinCrew/Funkin/commit/d1382aa985f97e3b40b0b629cb3d04301ebfb55e)) - by @afreetoplaynoob in [#6526](https://github.com/FunkinCrew/Funkin/pull/6526)
|
||||
- [MOBILE] The back button can no longer exit during the Boyfriend fakeout death animation. ([9d06018](https://github.com/FunkinCrew/Funkin/commit/9d0601813e912de9e25a851ad9204a654316625a)) - by @ActualMandM in [#6917](https://github.com/FunkinCrew/Funkin/pull/6917)
|
||||
- The song name text is now properly hidden at the beginning of the Results Screen animation. ([a5b15b9](https://github.com/FunkinCrew/Funkin/commit/a5b15b9424f16d8eadc7a92f1c355da647990c3a)) - by @NotHyper-474 and @Trayfellow in [#6931](https://github.com/FunkinCrew/Funkin/pull/6931)
|
||||
- The sticker transition no longer covers the volume soundtray. ([616546d](https://github.com/FunkinCrew/Funkin/commit/616546d298a06c4135a32ffad41483be208552f1)) - by @realvirtu in [#6727](https://github.com/FunkinCrew/Funkin/pull/6727)
|
||||
- Lightning now appears more regularly during South Erect and South (Pico Mix). ([9ca2092](https://github.com/FunkinCrew/funkin.assets/commit/9ca20929bc3dde6b07d74100c45fb45e48769c35)) - by @JackXson-Real in [funkin.assets#345](https://github.com/FunkinCrew/funkin.assets/pull/345)
|
||||
- [HTML5] The city lights in the Week 3 stages now show up. ([603684f](https://github.com/FunkinCrew/funkin.assets/commit/603684ffb327f03d8216aaeaba143ca5f9cd77f0)) - by @realvirtu in [funkin.assets#342](https://github.com/FunkinCrew/funkin.assets/pull/342)
|
||||
- The Week 3 Pico doppelganger cutscene background music no longer cuts off at the end. ([8ef58aa](https://github.com/FunkinCrew/funkin.assets/commit/8ef58aabdba8287d4c88808e2f0ecc0ac385b383)) - by @Trayfellow in [funkin.assets#349](https://github.com/FunkinCrew/funkin.assets/pull/349)
|
||||
- The Story Mode cutscene before Stress now properly plays when viewed more than once. ([6ec45ec](https://github.com/FunkinCrew/funkin.assets/commit/6ec45ec82ca77188b1b2b9c58ada172f5c357103)) - by @NotHyper-474 in [funkin.assets#341](https://github.com/FunkinCrew/funkin.assets/pull/341)
|
||||
- Darnell's can sound effects in 2hot no longer play twice with high offsets or when lagging. ([6315e25](https://github.com/FunkinCrew/funkin.assets/commit/6315e25eaaa8be4ca85e9b607f547595c699997a)) - by @JackXson-Real in [funkin.assets#354](https://github.com/FunkinCrew/funkin.assets/pull/354)
|
||||
- [MOBILE] The cutscene after 2hot now properly accounts for different resolutions. ([dd3371a](https://github.com/FunkinCrew/Funkin/commit/dd3371a549f4e10f68f1a458f40ec1a342f07876)) - by @ActualMandM in [#6937](https://github.com/FunkinCrew/Funkin/pull/6937)
|
||||
- Made the AttractState video skipping pie smoother. ([5a161b1](https://github.com/FunkinCrew/Funkin/commit/5a161b1d7342d7931950edf37554ce3a338736f9)) - by @PurSnake in [#6728](https://github.com/FunkinCrew/Funkin/pull/6728)
|
||||
- The screenshot preview no longer breaks when changing states. ([dc78db8](https://github.com/FunkinCrew/Funkin/commit/dc78db8808a7ea205fe75eba006e4ec1c57a8190)) - by @Lasercar in [#6792](https://github.com/FunkinCrew/Funkin/pull/6792)
|
||||
- Holding Ctrl and clicking on a hold note trail no longer crashes the Chart Editor (again). ([86ac336](https://github.com/FunkinCrew/Funkin/commit/86ac336d62a65fb420cdd6b1be739c3262d21159)) - by @Lasercar in [#6912](https://github.com/FunkinCrew/Funkin/pull/6912)
|
||||
- Chart Editor tooltips no longer appear when hovering over a deleted note or event. ([091c18b](https://github.com/FunkinCrew/Funkin/commit/091c18bccd95b588ba0d4577a94d83acf5942417)) - by @KoloInDaCrib in [#6929](https://github.com/FunkinCrew/Funkin/pull/6929)
|
||||
- Chart Editor vocal waveforms now render more accurately after BPM changes in the song. ([4e8f48d](https://github.com/FunkinCrew/Funkin/commit/4e8f48d5f0f1be4438c4ef9571137eaa35935f67)) - by @gamerbross in [#6833](https://github.com/FunkinCrew/Funkin/pull/6833)
|
||||
- The Chart Editor vocal waveforms now display in the proper position regardless of the game's aspect ratio. ([1fb9040](https://github.com/FunkinCrew/Funkin/commit/1fb9040470432528a0441d7938d217e424ce27fd)) - by @Starexify in [#6193](https://github.com/FunkinCrew/Funkin/pull/6193)
|
||||
- The second section number and divider now renders consistently in the Chart Editor. ([ac539bd](https://github.com/FunkinCrew/Funkin/commit/ac539bdf26ee7b5ecdcc52665c7c95287ef491c0)) - by @NotHyper-474 in [#6765](https://github.com/FunkinCrew/Funkin/pull/6765)
|
||||
- The Chart Editor now saves the Show Results Screen setting. ([c893a73](https://github.com/FunkinCrew/Funkin/commit/c893a7320d72abd3743bc5c1ddeaecf073035eb1)) - by @MightyTheArmiddilo in [#6854](https://github.com/FunkinCrew/Funkin/pull/6854)
|
||||
- Closing the game while in the Stage Editor no longer crashes the game. ([99cd4e2](https://github.com/FunkinCrew/Funkin/commit/99cd4e2cbd7fba87249b02b072a1e60f07c2c907)) - by @realvirtu in [#6775](https://github.com/FunkinCrew/Funkin/pull/6775)
|
||||
- The onion skin now properly renders as transparent after changing characters in the Animation Editor. ([5c444f1](https://github.com/FunkinCrew/Funkin/commit/5c444f1109e5af04735a4383e577c69682b3713f)) - by @realvirtu in [#6545](https://github.com/FunkinCrew/Funkin/pull/6545)
|
||||
- Blacklisted a class for security. ([3a113c2](https://github.com/FunkinCrew/Funkin/commit/3a113c270f92a6b14dfcda221124742437e1670a)) - by @charlesisfeline in [#6573](https://github.com/FunkinCrew/Funkin/pull/6573)
|
||||
- Even more tiny fixes!
|
||||
|
||||
|
||||
|
||||
## [0.8.1] - 2026-01-04
|
||||
|
||||
### Added
|
||||
@@ -20,7 +389,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
|
||||
|
||||
## [0.8.0] - 2025-12-31
|
||||
## [0.8.0] - 2026-01-03
|
||||
|
||||
The LE SSERAFIM collab update!
|
||||
|
||||
@@ -83,7 +452,7 @@ The LE SSERAFIM collab update!
|
||||
- Freeplay song previews now fade out before restarting. ([aaf5084](https://github.com/FunkinCrew/Funkin/commit/aaf5084fd9e9c2d3b7e823767a93db82ce908d86)) - by @JVNpixels in [#6094](https://github.com/FunkinCrew/Funkin/pull/6094)
|
||||
- The game's volume is now reduced when unfocused without pausing. ([3040692](https://github.com/FunkinCrew/Funkin/commit/30406928522f88762eab4bbf571fedf1424f7569)) - by @PurSnake in [#6250](https://github.com/FunkinCrew/Funkin/pull/6250)
|
||||
- Optimized the way the windows in Week 3 are handled. ([70d433d](https://github.com/FunkinCrew/funkin.assets/commit/70d433de3027badb39027d295d1b18d20a130741)) - by @CrusherNotDrip in [funkin.assets#291](https://github.com/FunkinCrew/funkin.assets/pull/291)
|
||||
- Script create events now also run after hot-reloading with F5, rather than only during initialization. ([2f865a5](https://github.com/FunkinCrew/Funkin/commit/2f865a5c7f4d8712f1b1e0bc70cb910f4fed08dc)) - by @VirtuGuy in [#6084](https://github.com/FunkinCrew/Funkin/pull/6084)
|
||||
- Script create events now also run after hot-reloading with F5, rather than only during initialization. ([2f865a5](https://github.com/FunkinCrew/Funkin/commit/2f865a5c7f4d8712f1b1e0bc70cb910f4fed08dc)) - by @realvirtu in [#6084](https://github.com/FunkinCrew/Funkin/pull/6084)
|
||||
- Hot-reloading with F5 during a Chart Editor playtest no longer returns to the Chart Editor. ([c1988f1](https://github.com/FunkinCrew/Funkin/commit/c1988f1858344a78a82bf335774d986703cac942)) - by @KoloInDaCrib in [#6275](https://github.com/FunkinCrew/Funkin/pull/6275)
|
||||
- Opening the Chart Editor during a song now places the playhead at the current song position. ([71b4a58](https://github.com/FunkinCrew/Funkin/commit/71b4a58cab821c3b5a530e3a2be6d73966faa2a6)) - by @KoloInDaCrib in [#6210](https://github.com/FunkinCrew/Funkin/pull/6210)
|
||||
- The Easing property for Chart Editor events is now split into two separate dropdowns: type and direction. ([d1d77dd](https://github.com/FunkinCrew/Funkin/commit/d1d77dd85c3daed22ee954353fa41e81279ced3c)) - by @PurSnake in [#5612](https://github.com/FunkinCrew/Funkin/pull/5612)
|
||||
@@ -112,7 +481,6 @@ The LE SSERAFIM collab update!
|
||||
- [iOS] The navigation bar is no longer unlocked after watching an ad.
|
||||
- [iOS] The “larger text” accessibility setting no longer causes the game to not fill the whole screen.
|
||||
- [iOS] The game now displays error popups.
|
||||
- [ANDROID] Keyboard detection and strumline positioning now work properly.
|
||||
- [ANDROID] Taking a screenshot no longer pauses the game for a moment.
|
||||
- The Title Screen no longer switches to Attract Mode while the Girlfriend’s Ringtone easter egg is playing.
|
||||
- Holding Escape in the Main Menu no longer quickly closes the game.
|
||||
@@ -144,21 +512,22 @@ The LE SSERAFIM collab update!
|
||||
- Pause on Unfocus now properly applies to Chart Editor playtests.
|
||||
- Unfocusing while the Chart Editor is playing audio now pauses the playback.
|
||||
- Fixed a memory leak with the Freeplay backing card scrolling text. ([67846d6](https://github.com/FunkinCrew/Funkin/commit/67846d6c4bfd2f42e002fa129a51772f0717329d)) - by @FuroYT in [#5963](https://github.com/FunkinCrew/Funkin/pull/5963)
|
||||
- Using a static pixel icon in Character Select no longer crashes the game. ([96f8ee8](https://github.com/FunkinCrew/Funkin/commit/96f8ee85e0c2281834b7334b87d1862003e5fa05)) - by @VirtuGuy in [#6171](https://github.com/FunkinCrew/Funkin/pull/6171)
|
||||
- Using a static pixel icon in Character Select no longer crashes the game. ([96f8ee8](https://github.com/FunkinCrew/Funkin/commit/96f8ee85e0c2281834b7334b87d1862003e5fa05)) - by @realvirtu in [#6171](https://github.com/FunkinCrew/Funkin/pull/6171)
|
||||
- A-Bot's visualizer no longer causes a memory leak during gameplay or in Character Select. ([6607645](https://github.com/FunkinCrew/Funkin/commit/6607645786ed8611436fa5f92a35027c2a64f1d0)) - by @FuroYT in [#5908](https://github.com/FunkinCrew/Funkin/pull/5908)
|
||||
- The Credits menu no longer crashes when not using hardcoded credits. ([4366fbe](https://github.com/FunkinCrew/Funkin/commit/4366fbe51274438ad2bc190afcca42e37987386d)) - by @sphis-sinco in [#5982](https://github.com/FunkinCrew/Funkin/pull/5982)
|
||||
- The game no longer lag spikes when Darnell throws his can in 2hot. ([a0bc6d6](https://github.com/FunkinCrew/funkin.assets/commit/a0bc6d61fde5799a7fc619b7fdea691b0d8bae05)) - by @KoloInDaCrib in [funkin.assets#313](https://github.com/FunkinCrew/funkin.assets/pull/313)
|
||||
- Hold note covers no longer get permanently stuck playing after a lag spike. ([66882d9](https://github.com/FunkinCrew/Funkin/commit/66882d9677268396320ee003478a3e2627655755)) - by @KoloInDaCrib in [#6066](https://github.com/FunkinCrew/Funkin/pull/6066)
|
||||
- Scrolling through Freeplay songs for the first time no longer stutters. ([cc486ad](https://github.com/FunkinCrew/Funkin/commit/cc486ad94b5e9806d18fb65165663fea0ce0d7b4)) - by @mikolka9144 in [#4851](https://github.com/FunkinCrew/Funkin/pull/4851)
|
||||
- Re-implemented an error that appears when a video file does not exist. ([2ad5933](https://github.com/FunkinCrew/Funkin/commit/2ad593341f8bea8384646f4803dc8795a9efe32a)) - by @TechnikTil in [#6253](https://github.com/FunkinCrew/Funkin/pull/6253)
|
||||
- [ANDROID] Keyboard detection and strumline positioning now work properly. ([5763ae5](https://github.com/FunkinCrew/Funkin/commit/5763ae5b728359c5639bbc578f15b65a16fa57b1)) - by @NotHyper-474 in [#6328](https://github.com/FunkinCrew/Funkin/pull/6328)
|
||||
- The game now properly parses .json files beginning with a bracket. ([c7367ae](https://github.com/FunkinCrew/Funkin/commit/c7367ae33d7e11f57b821f7d5fbff39a3edc1604)) - by @NotHyper-474 in [#6164](https://github.com/FunkinCrew/Funkin/pull/6164)
|
||||
- The Newgrounds logo no longer covers the intro text. ([28883fb](https://github.com/FunkinCrew/Funkin/commit/28883fb9ed025abf9f9aee2621f365cd6f4d8b6c)) - by @hucks5 in [#6196](https://github.com/FunkinCrew/Funkin/pull/6196)
|
||||
- Exiting from the Save Data Options menu no longer exits the Options Menu as well. ([26b253d](https://github.com/FunkinCrew/Funkin/commit/26b253d8cac97f0dcd09a5ef233f7058cd26008e)) - by @VirtuGuy in [#6036](https://github.com/FunkinCrew/Funkin/pull/6036)
|
||||
- Exiting from the Save Data Options menu no longer exits the Options Menu as well. ([26b253d](https://github.com/FunkinCrew/Funkin/commit/26b253d8cac97f0dcd09a5ef233f7058cd26008e)) - by @realvirtu in [#6036](https://github.com/FunkinCrew/Funkin/pull/6036)
|
||||
- Numeric values in the Options Menu are now rounded to prevent near-zero precision errors. ([934bce7](https://github.com/FunkinCrew/Funkin/commit/934bce7bdc5780e09623d845eda97a27c0ad0ecf)) - by @Starexify in [#6225](https://github.com/FunkinCrew/Funkin/pull/6225)
|
||||
- The Test/Offset Calibration menu no longer starts playing after exiting the Lag Adjustment menu. ([23a38f7](https://github.com/FunkinCrew/Funkin/commit/23a38f76f9c79c5fab5b9af5e2d98e51597e05a8)) - by @VioletSnowLeopard in [#6088](https://github.com/FunkinCrew/Funkin/pull/6088)
|
||||
- [MOBILE] The Back button now fades out when entering a Week in Story Mode. ([1ebce74](https://github.com/FunkinCrew/Funkin/commit/1ebce748d4e3306b4464a7bf82fab56bcb427a62)) - by @VirtuGuy in [#6255](https://github.com/FunkinCrew/Funkin/pull/6255)
|
||||
- [MOBILE] The Back button now fades out when entering a Week in Story Mode. ([1ebce74](https://github.com/FunkinCrew/Funkin/commit/1ebce748d4e3306b4464a7bf82fab56bcb427a62)) - by @realvirtu in [#6255](https://github.com/FunkinCrew/Funkin/pull/6255)
|
||||
- The Freeplay difficulty can now only be changed in one direction at a time. ([95af46c](https://github.com/FunkinCrew/Funkin/commit/95af46cbf72291d9d3226df91ed17f1aa3d3839f)) - by @Starexify in [#6262](https://github.com/FunkinCrew/Funkin/pull/6262)
|
||||
- Pico's backing card now renders properly in widescreen aspect ratios. ([aa29b3d](https://github.com/FunkinCrew/funkin.assets/commit/aa29b3dcc1ee2f8e89d2622c480b2e997410d57d)) - by @VirtuGuy in [funkin.assets#297](https://github.com/FunkinCrew/funkin.assets/pull/297)
|
||||
- Pico's backing card now renders properly in widescreen aspect ratios. ([aa29b3d](https://github.com/FunkinCrew/funkin.assets/commit/aa29b3dcc1ee2f8e89d2622c480b2e997410d57d)) - by @realvirtu in [funkin.assets#297](https://github.com/FunkinCrew/funkin.assets/pull/297)
|
||||
- The album titles in Freeplay are now positioned consistently. ([ed8cca4](https://github.com/FunkinCrew/funkin.assets/commit/ed8cca4694a098ae6aa56c4d2a231587edb9688c)) - by @Donothan73 in [funkin.assets#257](https://github.com/FunkinCrew/funkin.assets/pull/257)
|
||||
- Health icons now bop independently from the framerate. ([8e6fa51](https://github.com/FunkinCrew/Funkin/commit/8e6fa51c27ceaa830efec06bb8a52e281a008255)) - by @PurSnake in [#6035](https://github.com/FunkinCrew/Funkin/pull/6035)
|
||||
- The note resetting animation on song restart is now consistent between Downscroll and Upscroll. ([7b8d657](https://github.com/FunkinCrew/Funkin/commit/7b8d6577eddba568f20c3d23663dded054699090)) - by @FuroYT in [#6220](https://github.com/FunkinCrew/Funkin/pull/6220)
|
||||
@@ -167,19 +536,19 @@ The LE SSERAFIM collab update!
|
||||
- The path for a notestyle's countdown sound is now properly loaded as a sound instead of an image. ([dd5ea77](https://github.com/FunkinCrew/Funkin/commit/dd5ea7748b3b1878139998c209aa06db0fa05e0b)) - by @gamerbross in [#6232](https://github.com/FunkinCrew/Funkin/pull/6232)
|
||||
- The Pause Menu theme no longer plays at maximum volume for a split second when pausing. ([6ba44d6](https://github.com/FunkinCrew/Funkin/commit/6ba44d6cb0c71deb29eb23b82b61f58b2e95193e)) - by @ComedyLost in [#6334](https://github.com/FunkinCrew/Funkin/pull/6334)
|
||||
- The scrolling text in the Results Screen is now positioned consistently. ([200f798](https://github.com/FunkinCrew/Funkin/commit/200f7984379cb1bd911e49de92be312750893420)) - by @NotHyper-474 in [#6595](https://github.com/FunkinCrew/Funkin/pull/6595)
|
||||
- The scrolling text in the Results Screen is now FPS-independent. ([8c43f6f](https://github.com/FunkinCrew/Funkin/commit/8c43f6f67a362bde4de4ad8dbd72966d7c4a9f60)) - by @VirtuGuy in [#6476](https://github.com/FunkinCrew/Funkin/pull/6476)
|
||||
- The scrolling text in the Results Screen is now FPS-independent. ([8c43f6f](https://github.com/FunkinCrew/Funkin/commit/8c43f6f67a362bde4de4ad8dbd72966d7c4a9f60)) - by @realvirtu in [#6476](https://github.com/FunkinCrew/Funkin/pull/6476)
|
||||
- The Results Screen theme now loops more smoothly. ([592bf1a](https://github.com/FunkinCrew/Funkin/commit/592bf1a9221d4dcef53ae421571eddf78ed631e4)) - by @FuroYT in [#6477](https://github.com/FunkinCrew/Funkin/pull/6477)
|
||||
- Transition stickers now render properly with the window resized to any aspect ratio. ([4215b1c](https://github.com/FunkinCrew/Funkin/commit/4215b1c72e4391b2176014825885799b81dde2ba)) - by @PurSnake in [#6156](https://github.com/FunkinCrew/Funkin/pull/6156)
|
||||
- Boyfriend now stands in the same position in the Week 3 and Week 3 Erect stages. ([d2d15f1](https://github.com/FunkinCrew/funkin.assets/commit/d2d15f114256125d53c6331b46415701ae291c1f)) - by @CEliuxJV in [funkin.assets#261](https://github.com/FunkinCrew/funkin.assets/pull/261)
|
||||
- Pico's game over music now properly loops after his explosion death in 2hot. ([f1a1db0](https://github.com/FunkinCrew/Funkin/commit/f1a1db08347c3f9248fd16909cff06027297ad13)) - by @KoloInDaCrib in [#6216](https://github.com/FunkinCrew/Funkin/pull/6216)
|
||||
- 2hot now smoothly transitions into the cutscene. ([462b1b6](https://github.com/FunkinCrew/funkin.assets/commit/462b1b6e6e9b622ad8fd15f15a1f39c7dffa4764)) - by @hucks5 in [funkin.assets#286](https://github.com/FunkinCrew/funkin.assets/pull/286)
|
||||
- Nene now swings her legs during in-game cutscenes. ([6a5d9b2](https://github.com/FunkinCrew/funkin.assets/commit/6a5d9b265732d60da28083fb1c3d7b7b854edf63)) - by @hucks5 in [funkin.assets#289](https://github.com/FunkinCrew/funkin.assets/pull/289)
|
||||
- Nene's 50 combo animation now renders its heart properly. ([bcd96ee](https://github.com/FunkinCrew/funkin.assets/commit/bcd96eeb78b9b03cf7b24dc956ac3bc36438193e)) - by @VirtuGuy in [funkin.assets#296](https://github.com/FunkinCrew/funkin.assets/pull/296)
|
||||
- Nene's 50 combo animation now renders its heart properly. ([bcd96ee](https://github.com/FunkinCrew/funkin.assets/commit/bcd96eeb78b9b03cf7b24dc956ac3bc36438193e)) - by @realvirtu in [funkin.assets#296](https://github.com/FunkinCrew/funkin.assets/pull/296)
|
||||
- A-Bot (Christmas) now properly looks at the opponent. ([f81cc16](https://github.com/FunkinCrew/funkin.assets/commit/f81cc16c8f99655f76b7e27ce221819798c9c94e)) - by @ComedyLost in [funkin.assets#279](https://github.com/FunkinCrew/funkin.assets/pull/279)
|
||||
- Nene (Pixel) now raises and lowers her knife properly. ([1d9f50d](https://github.com/FunkinCrew/funkin.assets/commit/1d9f50d405f202e07efd883aeef5d6c1e9eaaa90)) - by @VirtuGuy in [funkin.assets#274](https://github.com/FunkinCrew/funkin.assets/pull/274)
|
||||
- Nene (Pixel) now raises and lowers her knife properly. ([1d9f50d](https://github.com/FunkinCrew/funkin.assets/commit/1d9f50d405f202e07efd883aeef5d6c1e9eaaa90)) - by @realvirtu in [funkin.assets#274](https://github.com/FunkinCrew/funkin.assets/pull/274)
|
||||
- Pico (Pixel)'s game over theme now plays at the right time. ([e8a4d24](https://github.com/FunkinCrew/funkin.assets/commit/e8a4d2472ca2dc28b03be05953dff3d7b5ec7433)) - by @JackXson-Real and @ComedyLost in [funkin.assets#288](https://github.com/FunkinCrew/funkin.assets/pull/288)
|
||||
- Pico holding Nene's idle animation no longer lasts too long. ([3483345](https://github.com/FunkinCrew/funkin.assets/commit/348334583746ec45f1c6ab2c5e1715a67038cc5c)) - by @JackXson-Real in [funkin.assets#271](https://github.com/FunkinCrew/funkin.assets/pull/271)
|
||||
- The tankmen in Stress no longer briefly appear behind the speakers when restarting. ([7f79ad8](https://github.com/FunkinCrew/funkin.assets/commit/7f79ad8c08d66fb909a9382de2c09f0430b756f1)) - by @VirtuGuy in [funkin.assets#298](https://github.com/FunkinCrew/funkin.assets/pull/298)
|
||||
- The tankmen in Stress no longer briefly appear behind the speakers when restarting. ([7f79ad8](https://github.com/FunkinCrew/funkin.assets/commit/7f79ad8c08d66fb909a9382de2c09f0430b756f1)) - by @realvirtu in [funkin.assets#298](https://github.com/FunkinCrew/funkin.assets/pull/298)
|
||||
- Encountering a Set Health Icon event during Minimal playtesting no longer crashes the Chart Editor. ([9f0a498](https://github.com/FunkinCrew/Funkin/commit/9f0a4988a3cc47581916a9750731bb7e63f168f3)) - by @charlesisfeline in [#6481](https://github.com/FunkinCrew/Funkin/pull/6481)
|
||||
- Typing in Chart Editor text fields no longer triggers bound key functions. ([3b5e589](https://github.com/FunkinCrew/Funkin/commit/3b5e5893c01c2b56036e53626eaea8d41e70f640)) - by @MightyTheArmiddilo in [#6601](https://github.com/FunkinCrew/Funkin/pull/6601)
|
||||
- Clicking between Chart Editor events no longer converts the second event's dropdown values into those of the first. ([c170c25](https://github.com/FunkinCrew/Funkin/commit/c170c256934ae316a735d38620ad5e24c2f15f4d)) - by @NotHyper-474 in [#6211](https://github.com/FunkinCrew/Funkin/pull/6211)
|
||||
@@ -187,19 +556,19 @@ The LE SSERAFIM collab update!
|
||||
- Placing a note and removing it no longer breaks the cursor in the Chart Editor. ([8cb5ed9](https://github.com/FunkinCrew/Funkin/commit/8cb5ed91baf50b6f78eefc2e50612a01195a2742)) - by @Lasercar in [#4237](https://github.com/FunkinCrew/Funkin/pull/4237)
|
||||
- Playtesting in the Chart Editor now properly loads song variation scripts. ([055f620](https://github.com/FunkinCrew/Funkin/commit/055f62026ef44a928876d9065cc388da0905e9f1)) - by @PurSnake in [#6405](https://github.com/FunkinCrew/Funkin/pull/6405)
|
||||
- Playtesting in the Chart Editor no longer sometimes moves on to another song like Story Mode. ([9497378](https://github.com/FunkinCrew/Funkin/commit/9497378600bad44639ff8b3fc92cb329052fd08a)) - by @KoloInDaCrib in [#6192](https://github.com/FunkinCrew/Funkin/pull/6192)
|
||||
- The cursor is now hidden when playtesting through the Chart Editor. ([0471872](https://github.com/FunkinCrew/Funkin/commit/047187257b6712e61bf05fdebab33c7b3e9ac0f6)) - by @VirtuGuy in [#6137](https://github.com/FunkinCrew/Funkin/pull/6137)
|
||||
- The cursor is now hidden when playtesting through the Chart Editor. ([0471872](https://github.com/FunkinCrew/Funkin/commit/047187257b6712e61bf05fdebab33c7b3e9ac0f6)) - by @realvirtu in [#6137](https://github.com/FunkinCrew/Funkin/pull/6137)
|
||||
- The Chart Editor note moving sound no longer plays when dragging outside the grid. ([593456e](https://github.com/FunkinCrew/Funkin/commit/593456e53e02c53e71189fdb154e4a3e4f2b3092)) - by @amyspark-ng in [#4157](https://github.com/FunkinCrew/Funkin/pull/4157)
|
||||
- The Chart Editor music now fades in after a period of silence when enabled. ([960d2f3](https://github.com/FunkinCrew/Funkin/commit/960d2f3cf166400c6fecee212b87961f3df10c2e)) - by @Lasercar in [#4148](https://github.com/FunkinCrew/Funkin/pull/4148)
|
||||
- The Chart Editor Difficulty toolbox no longer displays the incorrect song name. ([dff2a1e](https://github.com/FunkinCrew/Funkin/commit/dff2a1e487dc20f86ef4f526a259083a7726ea6a)) - by @VirtuGuy in [#6547](https://github.com/FunkinCrew/Funkin/pull/6547)
|
||||
- The Chart Editor Difficulty toolbox no longer displays the incorrect song name. ([dff2a1e](https://github.com/FunkinCrew/Funkin/commit/dff2a1e487dc20f86ef4f526a259083a7726ea6a)) - by @realvirtu in [#6547](https://github.com/FunkinCrew/Funkin/pull/6547)
|
||||
- Chart Editor notifications now display a bit higher. ([9e645db](https://github.com/FunkinCrew/Funkin/commit/9e645db0074424ffb2de42b27afb3adaff55de62)) - by @MightyTheArmiddilo in [#6445](https://github.com/FunkinCrew/Funkin/pull/6445)
|
||||
- The Yes and No text in the Chart Editor exit confirmation prompt buttons now always render properly. ([4c0d925](https://github.com/FunkinCrew/Funkin/commit/4c0d92507ae0b81a744d223e5292bf8d27013abd)) - by @NotHyper-474 in [#6173](https://github.com/FunkinCrew/Funkin/pull/6173)
|
||||
- Exiting the Chart Editor now consistently saves your audio preferences. ([2f77ccf](https://github.com/FunkinCrew/Funkin/commit/2f77ccfc6e93fabef27d3e06447f9f6edd8e840d)) - by @VioletSnowLeopard in [#6127](https://github.com/FunkinCrew/Funkin/pull/6127)
|
||||
- The Chart Editor and Stage Editor backup window now properly retrieves the most recently edited backup. ([a8dec0c](https://github.com/FunkinCrew/Funkin/commit/a8dec0cd7053f88865757f30a7d9f0ca5eb0fb02)) - by @Lasercar in [#6119](https://github.com/FunkinCrew/Funkin/pull/6119)
|
||||
- The Chart Editor backup dialog no longer appears if the latest backup is deleted. ([bc1d36d](https://github.com/FunkinCrew/Funkin/commit/bc1d36ddeab81a790e3604598248a9b2fe869cac)) - by @KoloInDaCrib in [#6027](https://github.com/FunkinCrew/Funkin/pull/6027)
|
||||
- Switching between Animation and Spritesheet mode no longer crashes the Animation Editor. ([a61016d](https://github.com/FunkinCrew/Funkin/commit/a61016d2dfc2ac6a50aae230969c036f0753cfaa)) - by @VirtuGuy in [#6114](https://github.com/FunkinCrew/Funkin/pull/6114)
|
||||
- Switching between Animation and Spritesheet mode no longer crashes the Animation Editor. ([a61016d](https://github.com/FunkinCrew/Funkin/commit/a61016d2dfc2ac6a50aae230969c036f0753cfaa)) - by @realvirtu in [#6114](https://github.com/FunkinCrew/Funkin/pull/6114)
|
||||
- The Animation Editor no longer displays a missing object icon next to the dropdown menus. ([b30ea36](https://github.com/FunkinCrew/Funkin/commit/b30ea36fcc982ce4ac0be9143fd4701e180fc684)) - by @KoloInDaCrib in [#6177](https://github.com/FunkinCrew/Funkin/pull/6177)
|
||||
- The Animation Editor onion skin now properly accounts for character scale and offsets. ([a76a868](https://github.com/FunkinCrew/Funkin/commit/a76a868cb6a27c1c76d09177b90cf6df3df29d17)) - by @VirtuGuy in [#6123](https://github.com/FunkinCrew/Funkin/pull/6123)
|
||||
- The debug cursor is now properly hidden when exiting the Animation Editor. ([f2f6b4c](https://github.com/FunkinCrew/Funkin/commit/f2f6b4c8591e1ab4a8c6f0ed998d6d25d7cc9f43)) - by @VirtuGuy in [#6112](https://github.com/FunkinCrew/Funkin/pull/6112)
|
||||
- The Animation Editor onion skin now properly accounts for character scale and offsets. ([a76a868](https://github.com/FunkinCrew/Funkin/commit/a76a868cb6a27c1c76d09177b90cf6df3df29d17)) - by @realvirtu in [#6123](https://github.com/FunkinCrew/Funkin/pull/6123)
|
||||
- The debug cursor is now properly hidden when exiting the Animation Editor. ([f2f6b4c](https://github.com/FunkinCrew/Funkin/commit/f2f6b4c8591e1ab4a8c6f0ed998d6d25d7cc9f43)) - by @realvirtu in [#6112](https://github.com/FunkinCrew/Funkin/pull/6112)
|
||||
- Plenty more tiny fixes.
|
||||
|
||||
## New Contributors for 0.8.0
|
||||
@@ -258,13 +627,13 @@ The LE SSERAFIM collab update!
|
||||
- Freeplay ranks no longer pop out when scrolling through song capsules. ([747446e](https://github.com/FunkinCrew/Funkin/commit/747446e2e420449f422fbc69aafda6128ac8d16e)) - by @VioletSnowLeopard in [#5822](https://github.com/FunkinCrew/Funkin/pull/5822)
|
||||
- The Freeplay intro no longer plays when returning from a sticker transition. ([63ec749](https://github.com/FunkinCrew/Funkin/commit/63ec749c7a3c90d529e9e8f2f3ed1c8913e8f9a1)) - by @PurSnake in [#5942](https://github.com/FunkinCrew/Funkin/pull/5942)
|
||||
- Hot-reloading with F5 after earning a rank no longer crashes Freeplay. ([79e8b5d](https://github.com/FunkinCrew/Funkin/commit/79e8b5d71e052953b77b81b66e0a83a7bbeeeeed)) - by @KoloInDaCrib in [#5971](https://github.com/FunkinCrew/Funkin/pull/5971)
|
||||
- The Main Menu music now fades in consistently when exiting from Freeplay to the Title Screen. ([a10bbf6](https://github.com/FunkinCrew/Funkin/commit/a10bbf60acbbeadfb5a91930745ef4fd338b1a24)) - by @VirtuGuy in [#5855](https://github.com/FunkinCrew/Funkin/pull/5855)
|
||||
- The Main Menu music now fades in consistently when exiting from Freeplay to the Title Screen. ([a10bbf6](https://github.com/FunkinCrew/Funkin/commit/a10bbf60acbbeadfb5a91930745ef4fd338b1a24)) - by @realvirtu in [#5855](https://github.com/FunkinCrew/Funkin/pull/5855)
|
||||
- The game now falls back to default audio files when files specified by the metadata don't exist. ([b5357ac](https://github.com/FunkinCrew/Funkin/commit/b5357acf98bde81a4121a3723061f7c559a0640f)) - by @VioletSnowLeopard in [#5954](https://github.com/FunkinCrew/Funkin/pull/5954)
|
||||
- The cutscene pause menu no longer persists across songs after exiting a video cutscene. ([c2305f3](https://github.com/FunkinCrew/Funkin/commit/c2305f32f0147f6326e8665d21a6b8a793f45033)) - by @KoloInDaCrib in [#5880](https://github.com/FunkinCrew/Funkin/pull/5880)
|
||||
- Mashing to skip the Eggnog Erect cutscene no longer crashes the game. ([5ca3c6a](https://github.com/FunkinCrew/funkin.assets/commit/5ca3c6a5745b61a457db149c289784c08e560ee9)) - by @VioletSnowLeopard in [funkin.assets#258](https://github.com/FunkinCrew/funkin.assets/pull/258)
|
||||
- Stress (Pico Mix) no longer lag spikes when loading in the background tankmen. ([6701405](https://github.com/FunkinCrew/funkin.assets/commit/670140571239ca08c1ae1c5286773d99c2875c2d)) - by @NotHyper-474 and @KoloInDaCrib in [funkin.assets#242](https://github.com/FunkinCrew/funkin.assets/pull/242)
|
||||
- Stress (Pico Mix) no longer lag spikes when Tankman changes sprites. ([aa5956a](https://github.com/FunkinCrew/Funkin/commit/aa5956a30bdc47d53ebebb4b61a7ebb3f04c7dc6)) - by @NotHyper-474 in [#5939](https://github.com/FunkinCrew/Funkin/pull/5939)
|
||||
- The bricks in Stress (Pico Mix) no longer move after restarting the song. ([9cfee03](https://github.com/FunkinCrew/Funkin/commit/9cfee0398a057567f80ad68ff6052964da63af09)) - by @VirtuGuy in [#5875](https://github.com/FunkinCrew/Funkin/pull/5875)
|
||||
- The bricks in Stress (Pico Mix) no longer move after restarting the song. ([9cfee03](https://github.com/FunkinCrew/Funkin/commit/9cfee0398a057567f80ad68ff6052964da63af09)) - by @realvirtu in [#5875](https://github.com/FunkinCrew/Funkin/pull/5875)
|
||||
- Pico now properly shoots after restarting Stress. ([b0ef0d3](https://github.com/FunkinCrew/funkin.assets/commit/b0ef0d352c199e93903652a95ffdf16a3dc2d569)) - by @7oltan in [funkin.assets#254](https://github.com/FunkinCrew/funkin.assets/pull/254)
|
||||
- A-Bot's visualizer now zeroes out when restarting the song. ([ba3a8b0](https://github.com/FunkinCrew/funkin.assets/commit/ba3a8b0cbbf785a0729dcf85e25b6e59c0c12657)) - by @KoloInDaCrib in [funkin.assets#246](https://github.com/FunkinCrew/funkin.assets/pull/246)
|
||||
- Notekinds now properly receive dispatched events last in PlayState. ([89b2b7f](https://github.com/FunkinCrew/Funkin/commit/89b2b7fcc3130db0af1f782594af72ae1f4ce320)) - by @Az989YT in [#5936](https://github.com/FunkinCrew/Funkin/pull/5936)
|
||||
@@ -337,7 +706,7 @@ The LE SSERAFIM collab update!
|
||||
- The HOME and END keys now jump to the top and bottom of the Story Mode menu, respectively. ([d1a96f7](https://github.com/FunkinCrew/Funkin/commit/d1a96f791f2ed35accc1c1e9ff548a75b2b9d7ef)) - by @JVNpixels in [#4591](https://github.com/FunkinCrew/Funkin/pull/4591)
|
||||
- Freeplay favorite songs are now separated by variation. ([b4b2e8d](https://github.com/FunkinCrew/Funkin/commit/b4b2e8da9dde41d730556a41e6bb18b0f3d8d7db)) - by @KoloInDaCrib in [#5154](https://github.com/FunkinCrew/Funkin/pull/5154)
|
||||
- Freeplay preview volumes now play at 70% volume, up from 40%. ([4ecef6d](https://github.com/FunkinCrew/Funkin/commit/4ecef6db744bab7e3fe5de0d680d813cc3bd1ea7)) - by @JackXson-Real in [#5645](https://github.com/FunkinCrew/Funkin/pull/5645)
|
||||
- Selecting a song in the Freeplay menu now plays a fade-out transition. ([705e6b3](https://github.com/FunkinCrew/Funkin/commit/705e6b330806c3157bca7301b1e43cd78acdb23a)) - by @VirtuGuy in [#5626](https://github.com/FunkinCrew/Funkin/pull/5626)
|
||||
- Selecting a song in the Freeplay menu now plays a fade-out transition. ([705e6b3](https://github.com/FunkinCrew/Funkin/commit/705e6b330806c3157bca7301b1e43cd78acdb23a)) - by @realvirtu in [#5626](https://github.com/FunkinCrew/Funkin/pull/5626)
|
||||
- Implemented null safety to PlayState and LoadingState. ([34ce13c](https://github.com/FunkinCrew/Funkin/commit/34ce13c5dfd52760675a1d09efa489bcb108e607)) - by @NotHyper-474 in [#4789](https://github.com/FunkinCrew/Funkin/pull/4789)
|
||||
- Health icons now have an offset variable. ([8bab619](https://github.com/FunkinCrew/Funkin/commit/8bab6196e50420c6586441f2d321bd1c139567c3)) - by @PurSnake in [#5760](https://github.com/FunkinCrew/Funkin/pull/5760)
|
||||
- The "hey" notekind now plays the animation for BF (Christmas). ([91d5970](https://github.com/FunkinCrew/funkin.assets/commit/91d5970e0274aa0a31fc6f2b05c114730256408f)) - by @JackXson-Real in [funkin.assets#225](https://github.com/FunkinCrew/funkin.assets/pull/225)
|
||||
@@ -385,8 +754,8 @@ The LE SSERAFIM collab update!
|
||||
- Fullscreen keybinds now work properly on Web builds. ([1fbb760](https://github.com/FunkinCrew/Funkin/commit/1fbb7604ddf4fb8d311b9b414cbcfa0fd9bab255)) - by @NotHyper-474 in [#5664](https://github.com/FunkinCrew/Funkin/pull/5664)
|
||||
- Corrected the heights of characters in the intro text font. ([90242e2](https://github.com/FunkinCrew/funkin.assets/commit/90242e2e200fca38f5f535986db49b7a53282d1f)) - by @SpritersBlock in [funkin.assets#190](https://github.com/FunkinCrew/funkin.assets/pull/190)
|
||||
- PureColor shaders now properly apply anti-aliasing. ([8d1bfa1](https://github.com/FunkinCrew/Funkin/commit/8d1bfa105c89f68ab1f14a197f8c0a5e4fe7fb14)) - by @MaybeMaru in [#5781](https://github.com/FunkinCrew/Funkin/pull/5781)
|
||||
- The Preferences menu camera now remembers its position when exiting and re-entering. ([3d88fbb](https://github.com/FunkinCrew/Funkin/commit/3d88fbb11fea2b52d399f37cb8154795329c31c2)) - by @VirtuGuy in [#5608](https://github.com/FunkinCrew/Funkin/pull/5608)
|
||||
- The Freeplay DJ no longer flickers between animations. ([1b91f3b](https://github.com/FunkinCrew/Funkin/commit/1b91f3b57cda3310db2f5196650b89c8d88e69be)) - by @VirtuGuy in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
|
||||
- The Preferences menu camera now remembers its position when exiting and re-entering. ([3d88fbb](https://github.com/FunkinCrew/Funkin/commit/3d88fbb11fea2b52d399f37cb8154795329c31c2)) - by @realvirtu in [#5608](https://github.com/FunkinCrew/Funkin/pull/5608)
|
||||
- The Freeplay DJ no longer flickers between animations. ([1b91f3b](https://github.com/FunkinCrew/Funkin/commit/1b91f3b57cda3310db2f5196650b89c8d88e69be)) - by @realvirtu in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
|
||||
- The Freeplay DJ's turntable lights now glow properly. ([0c5a965](https://github.com/FunkinCrew/funkin.assets/commit/0c5a965400937cbdac55ed9317a2a00a9d4343ae)) - by @Johferson in [funkin.assets#211](https://github.com/FunkinCrew/funkin.assets/pull/211)
|
||||
- The Random capsule now opens the selected song with the correct variation. ([1605514](https://github.com/FunkinCrew/Funkin/commit/160551442453fccc0961c570701bdba7bee95ef0)) - by @PurSnake in [#5611](https://github.com/FunkinCrew/Funkin/pull/5611)
|
||||
- Newly earned Freeplay ranks no longer appear larger than others. ([47813ea](https://github.com/FunkinCrew/Funkin/commit/47813eac3157927f851713cc4c41c5eb5fac2e19)) - by @anysad in [#5768](https://github.com/FunkinCrew/Funkin/pull/5768)
|
||||
@@ -404,7 +773,7 @@ The LE SSERAFIM collab update!
|
||||
- The Week 3 train now consistently plays its sound. ([469ce39](https://github.com/FunkinCrew/funkin.assets/commit/469ce397b8eef3be47f8fadaa61a500e1a87ca3a)) - by @Lasercar in [funkin.assets#212](https://github.com/FunkinCrew/funkin.assets/pull/212)
|
||||
- Nene no longer freezes after playing two animations at once. ([d346ebd](https://github.com/FunkinCrew/funkin.assets/commit/d346ebdbf4781b49a081e0719221cf584fc3fe55)) - by @NotHyper-474 in [funkin.assets#228](https://github.com/FunkinCrew/funkin.assets/pull/228)
|
||||
- The Week 4 car now properly pauses with the game. ([26d1cff](https://github.com/FunkinCrew/funkin.assets/commit/26d1cffe19793c67a89f299b7a60be95c5656282)) - by @NotHyper-474 in [funkin.assets#114](https://github.com/FunkinCrew/funkin.assets/pull/114)
|
||||
- Pressing Reset and Pause at the same time no longer breaks the game over animation in Blazin'. ([8cd3785](https://github.com/FunkinCrew/Funkin/commit/8cd3785e3c3e913ed791204814eba86eb7142a5d)) - by @VirtuGuy in [#5639](https://github.com/FunkinCrew/Funkin/pull/5639)
|
||||
- Pressing Reset and Pause at the same time no longer breaks the game over animation in Blazin'. ([8cd3785](https://github.com/FunkinCrew/Funkin/commit/8cd3785e3c3e913ed791204814eba86eb7142a5d)) - by @realvirtu in [#5639](https://github.com/FunkinCrew/Funkin/pull/5639)
|
||||
- Pico's Blazin' death animation no longer lags and offsets improperly. ([2cb42fe](https://github.com/FunkinCrew/funkin.assets/commit/2cb42fec422313db4e8000c963be0539221c9e21)) - by @KoloInDaCrib in [funkin.assets#217](https://github.com/FunkinCrew/funkin.assets/pull/217)
|
||||
- Pico and Darnell now properly punch with their other arms in Blazin'. ([4fb015f](https://github.com/FunkinCrew/funkin.assets/commit/4fb015f20261995ce41370910989094f4f2f26bb)) - by @Honton129 in [funkin.assets#221](https://github.com/FunkinCrew/funkin.assets/pull/221)
|
||||
- Pico's Perfect Results Screen animation now syncs with the music. ([0531e27](https://github.com/FunkinCrew/funkin.assets/commit/0531e27feed83dcc9a1703b3df654fd3bba1bd8a)) - by @JackXson-Real in [funkin.assets#201](https://github.com/FunkinCrew/funkin.assets/pull/201)
|
||||
@@ -418,12 +787,12 @@ The LE SSERAFIM collab update!
|
||||
- Chart Editor event properties now have minimum values. ([9b81ebc](https://github.com/FunkinCrew/Funkin/commit/9b81ebc4f2c1c70b33d7351210c40c9a0e48ecc8)) - by @Lasercar in [#4110](https://github.com/FunkinCrew/Funkin/pull/4110)
|
||||
- Added missing notekinds to the Chart Editor Notes window. ([b7a5761](https://github.com/FunkinCrew/Funkin/commit/b7a5761730d43f27891dfec1c23fcb5e66daccf1)) - by @Lasercar in [#4286](https://github.com/FunkinCrew/Funkin/pull/4286)
|
||||
- Playback speed is now preserved when a new song or variation is loaded in the Chart Editor. ([3f82f37](https://github.com/FunkinCrew/Funkin/commit/3f82f3792b056a03724a0d1a320b7549a7b59844)) - by @Lasercar in [#4212](https://github.com/FunkinCrew/Funkin/pull/4212)
|
||||
- The Legacy Chart Importer now properly imports scroll speeds. ([2645d56](https://github.com/FunkinCrew/Funkin/commit/2645d56514dd1a27a050ff432c3cd4122f958e10)) - by @VirtuGuy in [#5655](https://github.com/FunkinCrew/Funkin/pull/5655)
|
||||
- The Legacy Chart Importer now properly imports scroll speeds. ([2645d56](https://github.com/FunkinCrew/Funkin/commit/2645d56514dd1a27a050ff432c3cd4122f958e10)) - by @realvirtu in [#5655](https://github.com/FunkinCrew/Funkin/pull/5655)
|
||||
- Opponent characters now play singing animations when selected as the player character. ([8ee24c8](https://github.com/FunkinCrew/funkin.assets/commit/8ee24c84de6aa6e6313699198f35f61991612d04)) - by @Lasercar in [funkin.assets#141](https://github.com/FunkinCrew/funkin.assets/pull/141)
|
||||
- The Chart Editor character selector window no longer opens when clicking while playtesting. ([223e837](https://github.com/FunkinCrew/Funkin/commit/223e837fe8d9ce227e289a38bdfc095e4d81c48a)) - by @Lasercar in [#4350](https://github.com/FunkinCrew/Funkin/pull/4350)
|
||||
- Renamed Nene's pixel variant to Nene (Pixel) in the Chart Editor. ([69a7898](https://github.com/FunkinCrew/funkin.assets/commit/69a78988e3d6042d2e4779c9a4055c5de73ee775)) - by @JVNpixels in [funkin.assets#208](https://github.com/FunkinCrew/funkin.assets/pull/208)
|
||||
- Renamed Tankman's variants in the Chart Editor. ([70c43b7](https://github.com/FunkinCrew/funkin.assets/commit/70c43b792078d913c4c4d9fc019e378249d08b78)) - by @ExtraCode75 in [funkin.assets#209](https://github.com/FunkinCrew/funkin.assets/pull/209)
|
||||
- Pressing F4 in the Chart Editor now properly resets the window title. ([86e69cf](https://github.com/FunkinCrew/Funkin/commit/86e69cfbd1b1bd3daa49181b827fa813cb716703)) - by @VirtuGuy in [#5651](https://github.com/FunkinCrew/Funkin/pull/5651)
|
||||
- Pressing F4 in the Chart Editor now properly resets the window title. ([86e69cf](https://github.com/FunkinCrew/Funkin/commit/86e69cfbd1b1bd3daa49181b827fa813cb716703)) - by @realvirtu in [#5651](https://github.com/FunkinCrew/Funkin/pull/5651)
|
||||
- Saving a character in the Animation Editor no longer crashes the game. ([da5f691](https://github.com/FunkinCrew/Funkin/commit/da5f6918656d4a1ad3e83233b358034db92ca675)) - by @anysad in [#5519](https://github.com/FunkinCrew/Funkin/pull/5519)
|
||||
- The Stage Editor can now properly load modded stages. ([50c601a](https://github.com/FunkinCrew/Funkin/commit/50c601a7f0f27fc0f155e2bfbcb8ef54631aeac7)) - by @KoloInDaCrib in [#5744](https://github.com/FunkinCrew/Funkin/pull/5744)
|
||||
- XML files exported from the Stage Editor now account for rotated frames. ([661ddb1](https://github.com/FunkinCrew/Funkin/commit/661ddb15f72c2dae22f41a922a521740ab3617f0)) - by @KoloInDaCrib in [#5303](https://github.com/FunkinCrew/Funkin/pull/5303)
|
||||
@@ -431,9 +800,10 @@ The LE SSERAFIM collab update!
|
||||
|
||||
## New Contributors for 0.7.4
|
||||
|
||||
* @Trofem made their first contribution in [#5476](https://github.com/FunkinCrew/Funkin/pull/5476)
|
||||
* @ThatOneCalculator made their first contribution in [#5507](https://github.com/FunkinCrew/Funkin/pull/5507)
|
||||
* @SrtHero278 made their first contribution in [#5565](https://github.com/FunkinCrew/Funkin/pull/5565)
|
||||
* @VirtuGuy made their first contribution in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
|
||||
* @realvirtu made their first contribution in [#5598](https://github.com/FunkinCrew/Funkin/pull/5598)
|
||||
* @SpritersBlock made their first contribution in [funkin.assets#190](https://github.com/FunkinCrew/funkin.assets/pull/190)
|
||||
* @Johferson made their first contribution in [funkin.assets#211](https://github.com/FunkinCrew/funkin.assets/pull/211)
|
||||
* @Honton129 made their first contribution in [funkin.assets#213](https://github.com/FunkinCrew/funkin.assets/pull/213)
|
||||
|
||||
+1
-1
@@ -197,7 +197,7 @@ You can view the `funkin-assets` license here: (https://github.com/FunkinCrew/fu
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2020-2024 The Funkin' Crew Inc.
|
||||
Copyright 2020-2026 The Funkin' Crew Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
Submodule art updated: 2e68e371f8...429ab728b1
+1
-1
Submodule assets updated: 39d4b3fc95...724eba9de9
@@ -9,6 +9,10 @@
|
||||
"asset": "assets/preload/images/NOTE_assets.png",
|
||||
"blocksize": "4x4"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/characters/darnell/spritemap1.png",
|
||||
"blocksize": "4x4"
|
||||
},
|
||||
{
|
||||
"asset": "assets/preload/images/NOTE_hold_assets.png",
|
||||
"blocksize": "4x4"
|
||||
@@ -41,6 +45,22 @@
|
||||
"asset": "assets/shared/images/characters/sserafim/chaewon/spritemap1.png",
|
||||
"blocksize": "4x4"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/characters/pico-dark/spritemap1.png",
|
||||
"blocksize": "4x4"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/characters/pico/basic-animations/spritemap1.png",
|
||||
"blocksize": "6x6"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/characters/pico/explosion-death/spritemap1.png",
|
||||
"blocksize": "8x8"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/characters/pico/playable-animations/spritemap1.png",
|
||||
"blocksize": "6x6"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/holdCoverBlue.png",
|
||||
"blocksize": "4x4"
|
||||
@@ -109,6 +129,10 @@
|
||||
"asset": "assets/week1/image/erect/lights.png",
|
||||
"blocksize": "6x6"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/characters/pico/death/spritemap1.png",
|
||||
"blocksize": "6x6"
|
||||
},
|
||||
{
|
||||
"asset": "assets/week1/images/erect/crowd.png",
|
||||
"blocksize": "8x8"
|
||||
@@ -127,6 +151,7 @@
|
||||
}
|
||||
],
|
||||
"excludes": [
|
||||
"assets/fonts/vcr-bmp.png",
|
||||
"assets/preload/images/cursor/",
|
||||
"assets/preload/images/fonts/",
|
||||
"assets/preload/images/freeplay/",
|
||||
@@ -134,8 +159,8 @@
|
||||
"assets/preload/images/soundtray/",
|
||||
"assets/preload/images/stageBuild/",
|
||||
"assets/preload/images/storymenu/titles/",
|
||||
"assets/preload/images/titleEnter.png",
|
||||
"assets/preload/images/titleEnter_mobile.png",
|
||||
"assets/preload/images/title-screen-text/spritemap1.png",
|
||||
"assets/preload/images/title-screen-text-mobile/spritemap1.png",
|
||||
"assets/preload/images/ui/popup/pixel/*",
|
||||
"assets/shared/images/characters/abotPixel/*",
|
||||
"assets/shared/images/characters/bfPixel.png",
|
||||
@@ -177,6 +202,8 @@
|
||||
"assets/week1/images/erect/orangeLight.png",
|
||||
"assets/week2/images/erect/stairsDark.png",
|
||||
"assets/week2/images/erect/stairsLight.png",
|
||||
"assets/week6/"
|
||||
"assets/week6/",
|
||||
"assets/week7/images/bricksGround.png",
|
||||
"assets/week7/images/erect/bricksGround.png"
|
||||
]
|
||||
}
|
||||
|
||||
+19
-17
@@ -1,8 +1,8 @@
|
||||
FROM ubuntu:noble
|
||||
|
||||
ARG haxe_version=4.3.6
|
||||
ARG haxelib_version=4.1.0
|
||||
ARG neko_version=2.4.0
|
||||
ARG haxe_version=4.3.7
|
||||
ARG haxelib_version=4.2.0
|
||||
ARG neko_version=2.4.1
|
||||
|
||||
# prepare runner
|
||||
ENV GITHUB_HOME="/github/home"
|
||||
@@ -80,11 +80,13 @@ EOF
|
||||
# Haxe native dependencies
|
||||
RUN <<EOF
|
||||
apt-fast install -y --no-install-recommends \
|
||||
libc6-dev libffi-dev \
|
||||
libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev \
|
||||
libgl-dev libgl1-mesa-dev \
|
||||
build-essential \
|
||||
libc6-dev libffi-dev libdbus-1-dev libudev-dev libgbm-dev \
|
||||
libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev libxcursor-dev libxss-dev \
|
||||
libgl-dev libgl1-mesa-dev libglu1-mesa-dev libdrm-dev \
|
||||
libasound2-dev libpulse-dev \
|
||||
libvlc-dev libvlccore-dev
|
||||
libvlc-dev libvlccore-dev \
|
||||
gcc-multilib g++-multilib
|
||||
EOF
|
||||
|
||||
# Janky libffi.6 fix
|
||||
@@ -98,11 +100,11 @@ EOF
|
||||
# neko
|
||||
# https://github.com/HaxeFoundation/neko/releases/download/v2-3-0/neko-2.3.0-linux64.tar.gz
|
||||
RUN <<EOF
|
||||
#neko_url=$(curl https://api.github.com/repos/HaxeFoundation/neko/releases -fL \
|
||||
# | jq '.[] | select(.name == "'"$neko_version"'")' \
|
||||
# | jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
|
||||
# | jq -r '.browser_download_url')
|
||||
neko_url="https://geo.thei.rs/funkin/neko-2.4.1-linux64.tar.gz"
|
||||
neko_url=$(curl https://api.github.com/repos/HaxeFoundation/neko/releases -fL \
|
||||
| jq '.[] | select(.name == "'"$neko_version"'")' \
|
||||
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
|
||||
| jq -r '.browser_download_url')
|
||||
#neko_url="https://geo.thei.rs/funkin/neko-2.4.1-linux64.tar.gz"
|
||||
curl -fL "$neko_url" | tar -xz -C /usr/local
|
||||
EOF
|
||||
|
||||
@@ -112,16 +114,16 @@ ln -s "$neko_path" /usr/local/neko
|
||||
EOF
|
||||
|
||||
ENV NEKOPATH="/usr/local/neko"
|
||||
ENV LD_LIBRARY_PATH="$NEKOPATH:$LD_LIBRARY_PATH"
|
||||
ENV LD_LIBRARY_PATH="$NEKOPATH"
|
||||
ENV PATH="$NEKOPATH:$PATH"
|
||||
|
||||
# haxe
|
||||
# https://github.com/HaxeFoundation/haxe/releases/download/4.0.5/haxe-4.0.5-linux64.tar.gz
|
||||
RUN <<EOF
|
||||
#haxe_url=$(curl https://api.github.com/repos/HaxeFoundation/haxe/releases -fL \
|
||||
# | jq '.[] | select(.name == "'"$haxe_version"'")' \
|
||||
# | jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
|
||||
# | jq -r '.browser_download_url')
|
||||
haxe_url=$(curl https://api.github.com/repos/HaxeFoundation/haxe/releases -fL \
|
||||
| jq '.[] | select(.name == "'"$haxe_version"'")' \
|
||||
| jq '.assets[] | select(.name | endswith("linux64.tar.gz"))' \
|
||||
| jq -r '.browser_download_url')
|
||||
haxe_url="https://geo.thei.rs/funkin/haxe-4.3.6-linux64.tar.gz"
|
||||
curl -fL "$haxe_url" | tar -xz -C /usr/local
|
||||
EOF
|
||||
|
||||
+409
-151
@@ -1,4 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"exclude": {},
|
||||
"defaultSeverity": "INFO",
|
||||
"extendsConfigPath": "",
|
||||
"numberOfCheckerThreads": 5,
|
||||
@@ -6,113 +8,152 @@
|
||||
"defineCombinations": [],
|
||||
"checks": [
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, prevents using anonymous types inline without creating a typedef for them.",
|
||||
"props": { "severity": "INFO" },
|
||||
"type": "Anonymous"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates spacing around array access syntax.",
|
||||
"props": {
|
||||
"spaceBefore": false,
|
||||
"spaceInside": false
|
||||
"spaceInside": false,
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "ArrayAccess"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, mandates array literals be defined with [] instead of 'new'.",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "ArrayLiteral"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates specific syntax for the use of array literals.",
|
||||
"props": {
|
||||
"allowSingleArgParens": true,
|
||||
"allowReturn": true,
|
||||
"allowFunction": true,
|
||||
"allowCurlyBody": true
|
||||
"allowCurlyBody": true,
|
||||
|
||||
"enforceArrowForNonMemberFunctions": true,
|
||||
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "ArrowFunction"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"avoidIdentifiers": []
|
||||
},
|
||||
"comment": "Specify a list of variable and function names which are not allowed and should be renamed. Doesn't support regex.",
|
||||
"props": { "avoidIdentifiers": [], "severity": "WARNING" },
|
||||
"type": "AvoidIdentifier"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, prevents imports like 'import flixel.*' from being used.",
|
||||
"props": { "severity": "INFO" },
|
||||
"type": "AvoidStarImport"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, prevents ternary operators from being nested.",
|
||||
"props": {
|
||||
"severity": "INFO",
|
||||
"maxDepth": 1
|
||||
},
|
||||
"type": "AvoidTernaryOperator"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, prevents conditional compilation from crossing blocks. This prevents the case where conditional compilation could potentially create invalid syntax.",
|
||||
"props": { "severity": "INFO" },
|
||||
"type": "BlockBreakingConditional"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for the parameter of a catch block.",
|
||||
"props": {
|
||||
"format": "^(e|t|ex|[a-z][a-z][a-zA-Z]+)$"
|
||||
"format": "^(e|t|ex|[a-z][a-z][a-zA-Z]+)$",
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "CatchParameterName"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, flags when large blocks of similar code should be extracted to a function.",
|
||||
"props": {
|
||||
"thresholdSimilar": 120,
|
||||
"severityIdentical": "WARNING",
|
||||
"thresholdIdentical": 60
|
||||
"severity": "IGNORE",
|
||||
"thresholdIdentical": 60,
|
||||
"severityIdentical": "IGNORE"
|
||||
},
|
||||
"type": "CodeSimilarity"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, flags Haxe code that is commented out. Unused code should be removed and accessed via version control later if needed.",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "CommentedOutCode"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, flags when conditional compilation blocks are not properly aligned. NOTE:Disabled because it's kinda broken.",
|
||||
"props": {
|
||||
"severity": "IGNORE",
|
||||
"policy": "aligned",
|
||||
"allowSingleline": true
|
||||
"allowSingleline": true,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "ConditionalCompilation"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for static var identifiers.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^?:_[a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*$",
|
||||
"tokens": ["INLINE", "NOTINLINE"]
|
||||
"tokens": ["INLINE", "NOTINLINE", "NOTFINAL"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "ConstantName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for static final identifiers.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[A-Z]([_A-Z0-9]+)*$",
|
||||
"tokens": ["INLINE", "NOTINLINE", "FINAL"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "ConstantName"
|
||||
},
|
||||
{
|
||||
"comment": "Calculates the complexity of methods using the McCabe metric, and throws warnings at certain thresholds. Indicates that a function should be refactored or split up.",
|
||||
"props": {
|
||||
"thresholds": [
|
||||
{
|
||||
"complexity": 20,
|
||||
"severity": "WARNING"
|
||||
},
|
||||
{
|
||||
"complexity": 25,
|
||||
"severity": "ERROR"
|
||||
}
|
||||
{ "complexity": 20, "severity": "WARNING" },
|
||||
{ "complexity": 25, "severity": "ERROR" }
|
||||
],
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "CyclomaticComplexity"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, the default case of a switch statement must be last.",
|
||||
"props": { "severity": "INFO" },
|
||||
"type": "DefaultComesLast"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies the format for doc-style comments ().",
|
||||
"props": {
|
||||
"startStyle": "twostars",
|
||||
"endStyle": "onestar",
|
||||
"lineStyle": "onestar",
|
||||
"startStyle": "ignore"
|
||||
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "DocCommentStyle"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, prevents the use of the Dynamic type.",
|
||||
"props": { "severity": "IGNORE" },
|
||||
"type": "Dynamic"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, ensures ~/.../ is used instead of 'new EReg()'",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "ERegLiteral"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces specific syntax on empty blocks (require only one line, etc.)",
|
||||
"props": {
|
||||
"tokens": [
|
||||
"CLASS_DEF",
|
||||
@@ -129,11 +170,13 @@
|
||||
"TRY",
|
||||
"CATCH"
|
||||
],
|
||||
"option": "empty"
|
||||
"option": "empty",
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "EmptyBlock"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, flags when consecutive empty lines are used.",
|
||||
"props": {
|
||||
"requireEmptyLineAfterPackage": true,
|
||||
"requireEmptyLineAfterInterface": true,
|
||||
@@ -141,17 +184,18 @@
|
||||
"allowEmptyLineAfterSingleLineComment": true,
|
||||
"max": 1,
|
||||
"requireEmptyLineAfterClass": true,
|
||||
"allowEmptyLineAfterMultiLineComment": true
|
||||
"allowEmptyLineAfterMultiLineComment": true,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "EmptyLines"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"enforceEmptyPackage": true
|
||||
},
|
||||
"comment": "If enabled, mandates the use of 'package;' on root level modules.",
|
||||
"props": { "enforceEmptyPackage": true, "severity": "WARNING" },
|
||||
"type": "EmptyPackage"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, provides advanced checking for when consecutive empty lines are used.",
|
||||
"props": {
|
||||
"none": [],
|
||||
"upto": [],
|
||||
@@ -160,45 +204,61 @@
|
||||
"max": 1,
|
||||
"ignore": [],
|
||||
"atleast": [],
|
||||
"skipSingleLineTypes": true
|
||||
"skipSingleLineTypes": true,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "ExtendedEmptyLines"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates documentation comments for public fields.",
|
||||
"props": {
|
||||
"requireParams": true,
|
||||
"fieldType": "BOTH",
|
||||
"requireReturn": true,
|
||||
"ignoreOverride": true,
|
||||
"tokens": ["ABSTRACT_DEF", "CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF"],
|
||||
"tokens": ["ABSTRACT_DEF", "CLASS_DEF", "INTERFACE_DEF"],
|
||||
"modifier": "PUBLIC",
|
||||
"excludeNames": ["new", "toString"]
|
||||
"excludeNames": ["new", "toString"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "FieldDocComment"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates documentation comments for public fields.",
|
||||
"props": {
|
||||
"max": 1000,
|
||||
"ignoreEmptyLines": true,
|
||||
"severity": "IGNORE"
|
||||
"requireParams": true,
|
||||
"fieldType": "FUNCTIONS",
|
||||
"requireReturn": true,
|
||||
"ignoreOverride": true,
|
||||
"tokens": ["ENUM_DEF"],
|
||||
"modifier": "PUBLIC",
|
||||
"excludeNames": ["new", "toString"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "FieldDocComment"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, warns if files exceed a certain number of lines.",
|
||||
"props": { "max": 1000, "ignoreEmptyLines": true, "severity": "IGNORE" },
|
||||
"type": "FileLength"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, requires modules match the casing of their file name.",
|
||||
"type": "FileNameCase",
|
||||
"props": {}
|
||||
"props": { "severity": "WARNING" }
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, requires inline/static variables to be declared final.",
|
||||
"type": "Final",
|
||||
"props": {}
|
||||
"props": { "severity": "IGNORE" }
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"option": "upperCase"
|
||||
},
|
||||
"comment": "If enabled, requires hexadecimal literals to be in upper case. 0xFFFFFF is valid and 0xffffff is invalid.",
|
||||
"props": { "option": "upperCase", "severity": "WARNING" },
|
||||
"type": "HexadecimalLiteral"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, warns if a local variable or parameter shadows an existing field.",
|
||||
"props": {
|
||||
"ignoreSetter": true,
|
||||
"ignoreFormat": "^(main|run)$",
|
||||
@@ -207,21 +267,21 @@
|
||||
"type": "HiddenField"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"character": " ",
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"comment": "If enabled, mandates indentation.",
|
||||
"props": { "character": "", "severity": "IGNORE" },
|
||||
"type": "Indentation"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates characters used for indentation.",
|
||||
"props": {
|
||||
"character": "space",
|
||||
"severity": "INFO",
|
||||
"severity": "IGNORE",
|
||||
"ignorePattern": "^$"
|
||||
},
|
||||
"type": "IndentationCharacter"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, warns about assignments performed within another expression, like 'if (a=b){}'",
|
||||
"props": {
|
||||
"ignoreReturnAssignments": true,
|
||||
"severity": "WARNING"
|
||||
@@ -229,161 +289,261 @@
|
||||
"type": "InnerAssignment"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces that interfaces should not contain properties.",
|
||||
"props": {
|
||||
"allowProperties": false,
|
||||
"allowMarkerInterfaces": true
|
||||
"allowMarkerInterfaces": true,
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"type": "Interface"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces a newline before the left curly brace of a block.",
|
||||
"props": {
|
||||
"option": "nl",
|
||||
"ignoreEmptySingleline": true,
|
||||
"tokens": [
|
||||
"CLASS_DEF",
|
||||
"ENUM_DEF",
|
||||
"ABSTRACT_DEF",
|
||||
"TYPEDEF_DEF",
|
||||
"INTERFACE_DEF",
|
||||
"FUNCTION",
|
||||
"FOR",
|
||||
"IF",
|
||||
"WHILE",
|
||||
"SWITCH",
|
||||
"TRY",
|
||||
"CATCH",
|
||||
"ARRAY_COMPREHENSION"
|
||||
],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "LeftCurly"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces the left curly brace occurs on the end of the line, without a newline.",
|
||||
"props": {
|
||||
"option": "eol",
|
||||
"ignoreEmptySingleline": true,
|
||||
"tokens": ["OBJECT_DECL"],
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "LeftCurly"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, warns when lines of code exceed a certain length.",
|
||||
"props": {
|
||||
"max": 160,
|
||||
"ignorePattern": "^(\\s*['\"][^'\"]*['\"].*)$"
|
||||
"ignorePattern": "^(\\s*['\"][^'\"]*['\"].*)$",
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "LineLength"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates a specific naming convention for listener methods.",
|
||||
"props": {
|
||||
"listeners": ["addEventListener", "addListener", "on", "once"],
|
||||
"format": "^_?[a-z][a-zA-Z0-9]*$"
|
||||
"format": "^_?[a-z][a-zA-Z0-9]*$",
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "ListenerName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for local var variables.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[a-z][a-zA-Z0-9]*$",
|
||||
"tokens": []
|
||||
"tokens": ["NOTFINAL"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "LocalVariableName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for local final variables.",
|
||||
"props": {
|
||||
"ignoreNumbers": [-1, 0, 1, 2],
|
||||
"severity": "IGNORE"
|
||||
"ignoreExtern": true,
|
||||
"format": "^[A-Z][_A-Z0-9]*$",
|
||||
"tokens": ["FINAL"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "LocalVariableName"
|
||||
},
|
||||
{
|
||||
"comment": "Puts a warning on long numbers without separators. 1000000 is invalid and 1_000_000 is valid.",
|
||||
"props": {
|
||||
"severity": "INFO",
|
||||
|
||||
"decimalGroupSize": 3,
|
||||
"fractionalGroupSize": -1,
|
||||
"binaryGroupSize": 8,
|
||||
"hexadecimalGroupSize": 8,
|
||||
|
||||
"decimalMinimum": 10000
|
||||
},
|
||||
"type": "LongNumber"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, warns when unlabelled numeric values get used. Use named constants instead to improve code clarity.",
|
||||
"props": { "ignoreNumbers": [-1, 0, 1, 2], "severity": "IGNORE" },
|
||||
"type": "MagicNumber"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for public abstract member fields.",
|
||||
"props": {
|
||||
"format": "^[A-Z][a-zA-Z0-9]*$",
|
||||
"tokens": ["ABSTRACT"]
|
||||
"format": "^[a-zA-Z][_a-zA-Z0-9]*$",
|
||||
"tokens": ["PUBLIC", "ABSTRACT"]
|
||||
},
|
||||
"type": "MemberName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for private abstract member fields.",
|
||||
"props": {
|
||||
"format": "^[_a-zA-Z][a-z][a-zA-Z0-9]*$",
|
||||
"tokens": ["ABSTRACT"]
|
||||
"tokens": ["PRIVATE", "ABSTRACT"]
|
||||
},
|
||||
"type": "MemberName"
|
||||
},
|
||||
|
||||
{
|
||||
"comment": "Specifies a specific naming format for public class member fields.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[_a-z][a-zA-Z0-9]*$",
|
||||
"tokens": ["PUBLIC", "PRIVATE", "CLASS", "TYPEDEF"]
|
||||
"format": "^[a-zA-Z][a-z][a-zA-Z0-9]*$",
|
||||
"tokens": ["PUBLIC", "CLASS"]
|
||||
},
|
||||
"type": "MemberName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for private class member fields.",
|
||||
"props": {
|
||||
"format": "^[_a-zA-Z][_a-zA-Z0-9]*$",
|
||||
"tokens": ["PRIVATE", "CLASS"]
|
||||
},
|
||||
"type": "MemberName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for enum member fields.",
|
||||
"props": {
|
||||
"format": "^[a-zA-Z][_a-zA-Z0-9]*$",
|
||||
"tokens": ["PUBLIC", "ENUM"]
|
||||
},
|
||||
"type": "MemberName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for typedef member fields.",
|
||||
"props": {
|
||||
"format": "^[_a-zA-Z][a-z][a-zA-Z0-9]*$",
|
||||
"tokens": ["TYPEDEF"]
|
||||
},
|
||||
"type": "MemberName"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces that modules should not exceed a certain number of methods.",
|
||||
"props": {
|
||||
"maxPrivate": 100,
|
||||
"maxPublic": 100,
|
||||
"maxTotal": 100
|
||||
"maxTotal": 100,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "MethodCount"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"max": 50,
|
||||
"ignoreEmptyLines": true,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"comment": "If enabled, enforces that methods should not exceed a certain number of lines of code, excluding empty lines.",
|
||||
"props": { "max": 50, "ignoreEmptyLines": true, "severity": "IGNORE" },
|
||||
"type": "MethodLength"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for method names.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[a-z][a-zA-Z0-9]*$",
|
||||
"format": "^[a-z][_a-zA-Z0-9]*$",
|
||||
"tokens": [],
|
||||
"severity": "IGNORE"
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "MethodName"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific order for modifiers on fields.",
|
||||
"props": {
|
||||
"modifiers": [
|
||||
"OVERRIDE",
|
||||
"OVERLOAD",
|
||||
|
||||
"PUBLIC_PRIVATE",
|
||||
"STATIC",
|
||||
"MACRO",
|
||||
"OVERRIDE",
|
||||
"ABSTRACT",
|
||||
|
||||
"EXTERN",
|
||||
"INLINE",
|
||||
|
||||
"DYNAMIC",
|
||||
"MACRO",
|
||||
"FINAL"
|
||||
],
|
||||
"severity": "IGNORE"
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "ModifierOrder"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, complains when a specific string literal is used in the same file multiple times. Use a named constant instead.",
|
||||
"props": {
|
||||
"minLength": 2,
|
||||
"ignore": "^\\s+$",
|
||||
"allowDuplicates": 5
|
||||
"allowDuplicates": 5,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "MultipleStringLiterals"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, complains when a multiple variables are declared in a single expression. Use individual lines.",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "MultipleVariableDeclarations"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates the use of braces on specific block types, unless they fit on a single line.",
|
||||
"props": {
|
||||
"allowSingleLineStatement": true,
|
||||
"tokens": ["ELSE_IF", "WHILE", "DO_WHILE"]
|
||||
"tokens": ["FUNCTION", "FOR", "IF", "IF_WITH_ELSE", "ELSE"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "NeedBraces"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates the use of braces on specific block types, and prevent them from being placed on a single line.",
|
||||
"props": {
|
||||
"max": 3,
|
||||
"severity": "IGNORE"
|
||||
"allowSingleLineStatement": false,
|
||||
"tokens": ["IF_WITH_ELSE", "CATCH", "WHILE", "DO_WHILE", "ELSE_IF"],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "NeedBraces"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, complains when control flow statements are nested too deep (indicating high complexity).",
|
||||
"props": { "max": 3, "severity": "IGNORE" },
|
||||
"type": "NestedControlFlow"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"max": 1,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"comment": "If enabled, complains when 'for' loops are nested too deep (indicating high complexity).",
|
||||
"props": { "max": 1, "severity": "IGNORE" },
|
||||
"type": "NestedForDepth"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"max": 4
|
||||
},
|
||||
"comment": "If enabled, complains when 'if' statements are nested too deep (indicating high complexity).",
|
||||
"props": { "max": 4, "severity": "IGNORE" },
|
||||
"type": "NestedIfDepth"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"max": 1
|
||||
},
|
||||
"comment": "If enabled, complains when try/catch statements are nested too deep (indicating high complexity).",
|
||||
"props": { "max": 1, "severity": "INFO" },
|
||||
"type": "NestedTryDepth"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"option": "questionMark"
|
||||
},
|
||||
"comment": "If enabled, enforces ?value rather than value = null.",
|
||||
"props": { "option": "questionMark", "severity": "INFO" },
|
||||
"type": "NullableParameter"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces that operators should be surrounded by whitespace.",
|
||||
"props": {
|
||||
"oldFunctionTypePolicy": "none",
|
||||
"unaryOpPolicy": "none",
|
||||
@@ -401,6 +561,7 @@
|
||||
"type": "OperatorWhitespace"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces that most operators should be after a newline rather than before.",
|
||||
"props": {
|
||||
"tokens": [
|
||||
"+",
|
||||
@@ -443,54 +604,52 @@
|
||||
"type": "OperatorWrap"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"tokens": ["="],
|
||||
"option": "eol"
|
||||
},
|
||||
"comment": "If enabled, enforces that assignment operators should be before a newline rather than after.",
|
||||
"props": { "tokens": ["="], "option": "eol" },
|
||||
"type": "OperatorWrap"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for method parameter names.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^(_|[a-z][a-zA-Z0-9]*$)",
|
||||
"tokens": []
|
||||
"tokens": [],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "ParameterName"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"max": 7,
|
||||
"ignoreOverriddenMethods": false
|
||||
},
|
||||
"comment": "If enabled, complains when there are too many parameters on a method.",
|
||||
"props": { "max": 7, "ignoreOverriddenMethods": false },
|
||||
"type": "ParameterNumber"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"comment": "If enabled, complains when you make a property accessor method public.",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "PublicAccessor"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"prohibitMeta": false
|
||||
},
|
||||
"comment": "If enabled, complains when an @:access metadata is redundant.",
|
||||
"props": { "prohibitMeta": false, "severity": "INFO" },
|
||||
"type": "RedundantAccessMeta"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"prohibitMeta": false
|
||||
},
|
||||
"comment": "If enabled, complains when an @:allow metadata is redundant.",
|
||||
"props": { "prohibitMeta": false, "severity": "INFO" },
|
||||
"type": "RedundantAllowMeta"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, complains when an access modifier is redundant.",
|
||||
"props": {
|
||||
"enforcePrivate": false,
|
||||
"enforcePublic": true,
|
||||
"enforcePublicPrivate": false
|
||||
"enforcePublicPrivate": false,
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"type": "RedundantModifier"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces that a return type is specified for all methods.",
|
||||
"props": {
|
||||
"enforceReturnTypeForAnonymous": false,
|
||||
"allowEmptyReturn": true,
|
||||
@@ -499,44 +658,67 @@
|
||||
"type": "Return"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"ignoreFormat": "^$",
|
||||
"max": 2,
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"comment": "If enabled, mandates a maximum number of 'return' statements in a method.",
|
||||
"props": { "ignoreFormat": "^$", "max": 2, "severity": "IGNORE" },
|
||||
"type": "ReturnCount"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforces a specific placement for curly braces. TODO:Choose between Allman/K&R and enforce project-wide.",
|
||||
"props": {
|
||||
"option": "aloneorsingle",
|
||||
"tokens": [
|
||||
"CLASS_DEF",
|
||||
"ENUM_DEF",
|
||||
"ABSTRACT_DEF",
|
||||
"TYPEDEF_DEF",
|
||||
"INTERFACE_DEF",
|
||||
"OBJECT_DECL",
|
||||
"FUNCTION",
|
||||
"FOR",
|
||||
"IF",
|
||||
"WHILE",
|
||||
"SWITCH",
|
||||
"TRY",
|
||||
"CATCH",
|
||||
"REIFICATION",
|
||||
"ARRAY_COMPREHENSION"
|
||||
],
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"type": "RightCurly"
|
||||
},
|
||||
{
|
||||
"comment": "Enforces specific whitespace around certain separators, such as commas and semicolons.",
|
||||
"props": {
|
||||
"commaPolicy": "after",
|
||||
"semicolonPolicy": "after",
|
||||
"allowTrailingComma": false,
|
||||
"dotPolicy": "none"
|
||||
"dotPolicy": "none",
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "SeparatorWhitespace"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"tokens": [","],
|
||||
"option": "eol"
|
||||
},
|
||||
"comment": "Enforces specific line wrapping for certain separators, such as commas and semicolons.",
|
||||
"props": { "tokens": [","], "option": "eol" },
|
||||
"type": "SeparatorWrap"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, complains about overly complicated boolean expressions.",
|
||||
"props": {
|
||||
"severity": "WARNING",
|
||||
|
||||
"allowEqualsFalse": false
|
||||
},
|
||||
"type": "SimplifyBooleanExpression"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, complains about overly complicated boolean return statements.",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "SimplifyBooleanReturn"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, enforce spacing in and around conditional statements and certain operators.",
|
||||
"props": {
|
||||
"spaceIfCondition": "should",
|
||||
"spaceAroundBinop": true,
|
||||
@@ -550,94 +732,171 @@
|
||||
"type": "Spacing"
|
||||
},
|
||||
{
|
||||
"comment": "Enforce a specific string literal style (either ' or \").",
|
||||
"props": {
|
||||
"policy": "onlySingle",
|
||||
"allowException": true,
|
||||
"severity": "IGNORE"
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "StringLiteral"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, requires that switch conditions be wrapped in parenthesis.",
|
||||
"props": {
|
||||
"format": "^\\s*(TODO|FIXME|HACK|XXX|BUG)"
|
||||
"policy": "require",
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "SwitchParentheses"
|
||||
},
|
||||
{
|
||||
"comment": "Puts a warning on unresolved TODO/FIXME comments.",
|
||||
"props": {
|
||||
"format": "^\\s*(TODO|FIXME|HACK|XXX|BUG)",
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "TODOComment"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"ignorePattern": "^$"
|
||||
},
|
||||
"comment": "Checks if there are any tabs in the middle of a line.",
|
||||
"props": { "severity": "INFO" },
|
||||
"type": "TabForAligning"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"severity": "IGNORE"
|
||||
},
|
||||
"comment": "If enabled, complains whenever trace() gets used in code.",
|
||||
"props": { "severity": "IGNORE" },
|
||||
"type": "Trace"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, complains about trailing commas at the end of array and object literals.",
|
||||
"props": {
|
||||
"severity": "INFO",
|
||||
"enforceArrayComprehension": false,
|
||||
"enforceArrayLiterals": false,
|
||||
"enforceObjectLiterals": false
|
||||
},
|
||||
"type": "TrailingComma"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, complains about trailing whitespaces at the end of lines.",
|
||||
"props": { "severity": "INFO" },
|
||||
"type": "TrailingWhitespace"
|
||||
},
|
||||
{
|
||||
"type": "Type",
|
||||
"props": {
|
||||
"ignoreEnumAbstractValues": true
|
||||
}
|
||||
"comment": "If enabled, requires type be specified on member fields.",
|
||||
"props": { "ignoreEnumAbstractValues": true, "severity": "INFO" },
|
||||
"type": "Type"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates documentation comments on classes and interfaces.",
|
||||
"props": {
|
||||
"tokens": ["CLASS_DEF", "ENUM_DEF", "INTERFACE_DEF", "TYPEDEF_DEF"]
|
||||
"tokens": [
|
||||
"CLASS_DEF",
|
||||
"INTERFACE_DEF",
|
||||
"TYPEDEF_DEF",
|
||||
"ABSTRACT_DEF",
|
||||
"ENUM_DEF"
|
||||
],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "TypeDocComment"
|
||||
},
|
||||
{
|
||||
"comment": "Specifies a specific naming format for abstract types.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[A-Z]+[a-zA-Z0-9]*$",
|
||||
"tokens": []
|
||||
"tokens": ["ABSTRACT"],
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"type": "TypeName"
|
||||
},
|
||||
|
||||
{
|
||||
"comment": "Specifies a specific naming format for class types.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[A-Z]+[a-zA-Z0-9]*$",
|
||||
"tokens": ["CLASS"],
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"type": "TypeName"
|
||||
},
|
||||
|
||||
{
|
||||
"comment": "Specifies a specific naming format for enum types.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[A-Z]+[a-zA-Z0-9]*$",
|
||||
"tokens": ["ENUM"],
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"type": "TypeName"
|
||||
},
|
||||
|
||||
{
|
||||
"comment": "Specifies a specific naming format for interface types.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[A-Z]+[a-zA-Z0-9]*$",
|
||||
"tokens": ["INTERFACE"],
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"type": "TypeName"
|
||||
},
|
||||
|
||||
{
|
||||
"comment": "Specifies a specific naming format for typedefs.",
|
||||
"props": {
|
||||
"ignoreExtern": true,
|
||||
"format": "^[A-Z]+[a-zA-Z0-9]*$",
|
||||
"tokens": ["TYPEDEF"],
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"type": "TypeName"
|
||||
},
|
||||
{
|
||||
"props": {},
|
||||
"comment": "If enabled, complains when a class with only static fields and values has a redundant constructor.",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "UnnecessaryConstructor"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"moduleTypeMap": {},
|
||||
"ignoreModules": []
|
||||
},
|
||||
"comment": "If enabled, complains when a module contains unused imports. NOTE:Sometimes complains about required imports.",
|
||||
"props": { "moduleTypeMap": {}, "ignoreModules": [], "severity": "INFO" },
|
||||
"type": "UnusedImport"
|
||||
},
|
||||
{
|
||||
"props": {
|
||||
"severity": "WARNING"
|
||||
},
|
||||
"comment": "If enabled, complains when a local variable is unused.",
|
||||
"props": { "severity": "WARNING" },
|
||||
"type": "UnusedLocalVar"
|
||||
},
|
||||
{
|
||||
"type": "VarTypeHint",
|
||||
"comment": "If enabled, requires type hints for certain variables.",
|
||||
"props": {
|
||||
"typeHintPolicy": "enforce_all",
|
||||
"ignoreEnumAbstractValues": true,
|
||||
"severity": "IGNORE"
|
||||
}
|
||||
},
|
||||
"type": "VarTypeHint"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, complains when a class member variable is initialized at the class level rather than the constructor.",
|
||||
"type": "VariableInitialisation",
|
||||
"props": {
|
||||
"allowFinal": false
|
||||
"allowFinal": true,
|
||||
"severity": "IGNORE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates whitespace after certain tokens.",
|
||||
"props": {
|
||||
"tokens": [",", ";"],
|
||||
"allowTrailingComma": false
|
||||
"allowTrailingComma": false,
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "WhitespaceAfter"
|
||||
},
|
||||
{
|
||||
"comment": "If enabled, mandates whitespace around certain tokens.",
|
||||
"props": {
|
||||
"tokens": [
|
||||
"=",
|
||||
@@ -672,11 +931,10 @@
|
||||
"&=",
|
||||
"^=",
|
||||
"=>"
|
||||
]
|
||||
],
|
||||
"severity": "INFO"
|
||||
},
|
||||
"type": "WhitespaceAround"
|
||||
}
|
||||
],
|
||||
"exclude": {},
|
||||
"version": 1
|
||||
]
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ Check [COMPILING.md](./COMPILING.md) if you haven’t done that yet.
|
||||
setx ANDROID_HOME "C:\path\to\your\folder" /M
|
||||
```
|
||||
3. Download [Android Studio Command-line Tools](https://developer.android.com/studio#command-line-tools-only).
|
||||
4. Extract the ZIP into your folder from step 1.
|
||||
4. Extract the ZIP into your folder from step 0.
|
||||
5. (Optional) Close and reopen the terminal if needed.
|
||||
6. Run:
|
||||
```bash
|
||||
@@ -69,10 +69,10 @@ Check [COMPILING.md](./COMPILING.md) if you haven’t done that yet.
|
||||
```
|
||||
|
||||
## iOS
|
||||
Note that you can only build the game for iOS on a computer running MacOS.
|
||||
Note that you can only build the game for iOS on a computer running macOS.
|
||||
|
||||
0. Build the game for desktop to make sure everything works. Check [COMPILING.md](./COMPILING.md).
|
||||
1. Get Xcode from the app store on your MacOS Machine.
|
||||
1. Get Xcode from the app store on your macOS Machine.
|
||||
2. Download the iPhone SDK (First thing that pops up in Xcode)
|
||||
3. Open up a terminal tab and run `lime test ios -xcode`
|
||||
4. You will need to sign your own copy in order to run the game with a real iOS device! That requires an Apple Developer account, sorry!
|
||||
@@ -81,11 +81,11 @@ Note that you can only build the game for iOS on a computer running MacOS.
|
||||
### iOS Troubleshooting
|
||||
|
||||
- **A required plugin failed to load. Please ensure system content is up-to-date — try running 'xcodebuild -runFirstLaunch'.**
|
||||
Make sure you have the iOS SDK isntalled, see Step 2.
|
||||
Make sure you have the iOS SDK installed, see Step 2.
|
||||
|
||||
- **error: No Accounts: Add a new account in Accounts settings. (in target 'Funkin' from project 'Funkin')**
|
||||
|
||||
Open XCode, press CMD+, to open Settings, select Accounts, add an Apple ID.
|
||||
Open Xcode, press CMD+, to open Settings, select Accounts, add an Apple ID.
|
||||
|
||||
- error: No Account for Team "Z7G7AVNGSH". Add a new account in Accounts settings or verify that your accounts have valid credentials.
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ This section provides guidelines to follow when [opening an issue](https://githu
|
||||
|
||||
## Requirements
|
||||
Make sure you're playing:
|
||||
- the latest version of the game (currently v0.8.1)
|
||||
- without any mods
|
||||
- the latest version of the game (currently v0.8.6, or v0.8.7 for Android) or a public playtest version (v0.9 Feature Preview builds)
|
||||
- without any mods (unless the issue involves mods)
|
||||
- on [Newgrounds](https://www.newgrounds.com/portal/view/770371) or downloaded from [itch.io](https://ninja-muffin24.itch.io/funkin)
|
||||
|
||||
## Rejected Features
|
||||
@@ -86,6 +86,7 @@ Here's a list of commonly suggested features and the reasons why they won't be a
|
||||
| Importing Charts from Psych Engine (and other mod content) | https://github.com/FunkinCrew/Funkin/issues/2586#issuecomment-2125733327 |
|
||||
| Backwards Compatibility for Modding | https://github.com/FunkinCrew/Funkin/issues/3949#issuecomment-2608391329 |
|
||||
| Lua Support | https://github.com/FunkinCrew/Funkin/issues/2643#issuecomment-2143718093 |
|
||||
| Note Hitsounds | https://github.com/FunkinCrew/Funkin/pull/4112#issuecomment-5347549977 |
|
||||
|
||||
## Issue Types
|
||||
Choose the issue template that best suits your needs!
|
||||
|
||||
@@ -8,9 +8,7 @@ Most of this functionality is only available on debug builds of the game!
|
||||
- `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too!
|
||||
- `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out!
|
||||
- `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data).
|
||||
- `CTRL-ALT-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace. (Only works in the Main Menu on debug builds).
|
||||
|
||||
- `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace.
|
||||
- `CTRL-ALT-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace.
|
||||
|
||||
## **Play State**
|
||||
- `H`: ***HIDE UI***: Makes the user interface invisible. Works in Pause Menu, great for screenshots.
|
||||
@@ -27,6 +25,7 @@ Most of this functionality is only available on debug builds of the game!
|
||||
- `P`: ***SWITCH TO PICO/BF***: Switch to Pico or BF (reopens Freeplay as the other character).
|
||||
- `T`: ***TEST RANK ANIMATION***: Play the Gold Perfect rank animation on the currently selected song.
|
||||
- `SHIFT-ACCEPT`: ***BOTPLAY MODE***: Start a song with Botplay mode enabled.
|
||||
- `CTRL-ACCEPT`: ***MIRRORED MODE***: Start a song with mirrored notes enabled.
|
||||
- `CTRL-Switch Song`: Play the first unlocked alternate instrumental as the song preview.
|
||||
|
||||
## **Title State**
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Install Dox
|
||||
`haxelib install dox`
|
||||
|
||||
# To generate documentation
|
||||
Run the script for your operating system, and then it will generate docs into `docs/dox/output/`
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Funkin' Theme",
|
||||
"author": "The Funkin' Crew Inc"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,332 @@
|
||||
#theme-toggle:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dark-theme {
|
||||
background-color: #111 !important;
|
||||
color: #ccc;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
.dark-theme body {
|
||||
background-color: #111 !important;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark-theme .navbar-inner {
|
||||
background-color: #222 !important;
|
||||
}
|
||||
|
||||
.dark-theme .brand {
|
||||
color: #CCC !important;
|
||||
}
|
||||
.dark-theme .brand .img {
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.dark-theme .well {
|
||||
background-color: #222;
|
||||
border: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme .input-append .add-on,
|
||||
.dark-theme .input-prepend .add-on {
|
||||
background-color: #333;
|
||||
border: 1px solid #333;
|
||||
padding: 3px 5px;
|
||||
text-shadow: 0 0 0 #000;
|
||||
}
|
||||
|
||||
.dark-theme h1 {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark-theme a {
|
||||
color: #0087ff;
|
||||
}
|
||||
|
||||
.dark-theme a:hover,
|
||||
.dark-theme a:focus {
|
||||
color: #00b7ff;
|
||||
}
|
||||
|
||||
.dark-theme input,
|
||||
.dark-theme textarea {
|
||||
background-color: #151515;
|
||||
border: 1px solid #333;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.dark-theme .btn-group.open .btn.dropdown-toggle {
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
.dark-theme .dropdown-menu {
|
||||
background-color: #111;
|
||||
}
|
||||
|
||||
.dark-theme .dropdown-menu>li>a {
|
||||
color: #EEE;
|
||||
}
|
||||
|
||||
.dark-theme .dropdown-menu>li>a:hover,
|
||||
.dark-theme .dropdown-menu>li>a:focus,
|
||||
.dark-theme .dropdown-submenu:hover>a,
|
||||
.dark-theme .dropdown-submenu:focus>a {
|
||||
color: #EEE;
|
||||
background-color: #2f2f2f;
|
||||
background-image: linear-gradient(to bottom, #262626, #2f2f2f);
|
||||
}
|
||||
|
||||
.dark-theme .btn:focus,
|
||||
.dark-theme .btn:hover {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.dark-theme .nav>li>a:hover,
|
||||
.dark-theme .nav>li>a:focus {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.dark-theme .nav-list>.active>a {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.dark-theme .nav-list>.active>a.treeLink,
|
||||
.dark-theme .nav-list>.active>a.treeLink:hover,
|
||||
.dark-theme .nav-list>.active>a.treeLink:focus {
|
||||
background: #269;
|
||||
}
|
||||
|
||||
.dark-theme .btn {
|
||||
color: #d5d5d5;
|
||||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);
|
||||
background-color: #313131;
|
||||
background-image: linear-gradient(to bottom, #313131, #282828);
|
||||
border: 1px solid #424141;
|
||||
border-bottom-color: #393939;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.dark-theme .btn {
|
||||
color: #d5d5d5;
|
||||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);
|
||||
background-color: #313131;
|
||||
background-image: linear-gradient(to bottom, #313131, #282828);
|
||||
border: 1px solid #424141;
|
||||
border-bottom-color: rgb(66, 65, 65);
|
||||
border-bottom-color: #393939;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.dark-theme .btn:focus,
|
||||
.dark-theme .btn:hover {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.dark-theme .btn.active,
|
||||
.dark-theme .btn:active {
|
||||
background-image: none;
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
|
||||
.dark-theme .btn.disabled,
|
||||
.dark-theme .btn[disabled] {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.65;
|
||||
box-shadow: none;
|
||||
border-color: #393939;
|
||||
}
|
||||
|
||||
.dark-theme .btn:focus {
|
||||
color: #d5d5d5;
|
||||
background-color: #313131;
|
||||
border-color: #424141;
|
||||
}
|
||||
|
||||
.dark-theme .btn:active:hover,
|
||||
.dark-theme .btn:focus:hover {
|
||||
color: #fff;
|
||||
background-color: #313131;
|
||||
border-color: #393939;
|
||||
}
|
||||
|
||||
.dark-theme a.btn.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.dark-theme .section.site-footer {
|
||||
background: #111 !important;
|
||||
}
|
||||
|
||||
.dark-theme .copyright>p {
|
||||
color: #CCC !important;
|
||||
}
|
||||
|
||||
.dark-theme .table th,
|
||||
.dark-theme .table td {
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme .table .fa {
|
||||
color: #222;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.dark-theme .alert,
|
||||
.dark-theme .alert h4 {
|
||||
color: #ffc96c;
|
||||
}
|
||||
|
||||
.dark-theme .availability {
|
||||
color: #69b;
|
||||
}
|
||||
|
||||
.dark-theme .section-availability {
|
||||
color: #69b;
|
||||
}
|
||||
|
||||
.dark-theme .alert {
|
||||
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.dark-theme .alert {
|
||||
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
|
||||
background-color: #332b00;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dark-theme hr {
|
||||
border-top: none;
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme .page-header {
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme .section {
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme .field+.field {
|
||||
border-top: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme code {
|
||||
color: #ddd;
|
||||
background-color: #111;
|
||||
border: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme pre {
|
||||
background-color: #222;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.dark-theme .example code {
|
||||
color: #ddd;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dark-theme pre code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.dark-theme pre.example::before {
|
||||
color: #DDD;
|
||||
background: #191919;
|
||||
}
|
||||
|
||||
.dark-theme h3 code {
|
||||
box-shadow: 0 0 15px rgb(20, 20, 20);
|
||||
}
|
||||
|
||||
.dark-theme .label,
|
||||
.dark-theme .badge {
|
||||
color: #DDD;
|
||||
background-color: #404040;
|
||||
}
|
||||
|
||||
.dark-theme .label.label-meta {
|
||||
background: #333379;
|
||||
}
|
||||
|
||||
.dark-theme code .identifier {
|
||||
color: #eff;
|
||||
}
|
||||
|
||||
.dark-theme table.params {
|
||||
border-left: 5px solid #222;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.dark-theme .table-bordered {
|
||||
border: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme table.params th {
|
||||
background: #111;
|
||||
}
|
||||
|
||||
.dark-theme .table-bordered th,
|
||||
.dark-theme .table-bordered td {
|
||||
border-left: 1px solid #222;
|
||||
}
|
||||
|
||||
.dark-theme .indent {
|
||||
border-left: 5px solid #222;
|
||||
}
|
||||
|
||||
|
||||
/* Types without links */
|
||||
|
||||
.dark-theme code .type {
|
||||
color: #29e;
|
||||
}
|
||||
|
||||
|
||||
/* dark code examples (from try-haxe) */
|
||||
|
||||
.dark-theme code,
|
||||
.dark-theme pre {
|
||||
color: #DDD;
|
||||
}
|
||||
|
||||
.dark-theme code a {
|
||||
color: #29e
|
||||
}
|
||||
|
||||
.dark-theme pre .type {
|
||||
color: #DECB6B
|
||||
}
|
||||
|
||||
.dark-theme pre .kwd {
|
||||
color: #C792EA
|
||||
}
|
||||
|
||||
.dark-theme pre .val {
|
||||
color: #FF5370
|
||||
}
|
||||
|
||||
.dark-theme div.pre .str,
|
||||
.dark-theme pre .str,
|
||||
.dark-theme pre .str .kwd,
|
||||
.dark-theme pre .str .type,
|
||||
.dark-theme pre .str .val {
|
||||
color: #C3E88D
|
||||
}
|
||||
|
||||
.dark-theme pre .cmt,
|
||||
.dark-theme pre .cmt .kwd,
|
||||
.dark-theme pre .cmt .str,
|
||||
.dark-theme pre .cmt .type,
|
||||
.dark-theme pre .cmt .val {
|
||||
color: #545454
|
||||
}
|
||||
|
||||
.dark-theme .last-modified {
|
||||
color: #666
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/** to be overridden in sub-themes */
|
||||
@@ -0,0 +1,189 @@
|
||||
nav.nav {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav .fa {
|
||||
color: #777;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
body nav * {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
nav .navbar-inner {
|
||||
background: #13110f;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
nav .navbar .nav {
|
||||
margin: 0;
|
||||
|
||||
}
|
||||
|
||||
nav .dropdown-menu {
|
||||
background: #2c2722;
|
||||
font-size: 14px;
|
||||
border-radius: 0px 0px 2px 2px;
|
||||
padding: 10px 0px;
|
||||
border: 1px solid #2c2722;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
nav .navbar .nav>li>a {
|
||||
padding: 14px 12px 15px 12px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
nav .dropdown-menu li a {
|
||||
color: #b8b5b5;
|
||||
padding: 3px 15px;
|
||||
}
|
||||
|
||||
nav .divider {
|
||||
background-color: transparent;
|
||||
border-right: 1px solid #39332d;
|
||||
margin: 5px 20px 5px 10px;
|
||||
height: 39px;
|
||||
}
|
||||
|
||||
nav .dropdown-menu .divider {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #39332d;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
nav .navbar-inverse .nav .active>a,
|
||||
nav .navbar-inverse .nav .active>a:hover,
|
||||
nav .navbar-inverse .nav .active>a:focus,
|
||||
nav .navbar-inverse .nav li.dropdown.open>.dropdown-toggle,
|
||||
nav .navbar-inverse .nav li.dropdown.active>.dropdown-toggle,
|
||||
nav .navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle {
|
||||
color: #fff;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
nav .navbar-inverse .nav .active>a:hover {
|
||||
background: #39332d;
|
||||
}
|
||||
|
||||
nav .dropdown-menu>.active>a,
|
||||
nav .dropdown-menu>.active>a:hover,
|
||||
nav .dropdown-menu>.active>a:focus {
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
background-image: none;
|
||||
background: #39332d;
|
||||
}
|
||||
|
||||
nav .dropdown-menu>li>a:hover,
|
||||
.dropdown-menu>li>a:focus,
|
||||
nav .dropdown-submenu:hover>a,
|
||||
nav .dropdown-submenu:focus>a {
|
||||
background: #39332d;
|
||||
}
|
||||
|
||||
nav .navbar .nav>li>.dropdown-menu:after {
|
||||
border-bottom-color: #2c2722;
|
||||
}
|
||||
|
||||
/** MEDIA Q **/
|
||||
|
||||
@media (max-width: 979px) {
|
||||
|
||||
nav .navbar-fixed-top .navbar-inner,
|
||||
nav .navbar-fixed-bottom .navbar-inner {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
nav .navbar-fixed-top {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** SUB BRAND LOGOS **/
|
||||
|
||||
.navbar .brand.haxe-logo {
|
||||
padding-right: 0;
|
||||
margin: 3px 0 0 0px;
|
||||
}
|
||||
|
||||
.navbar .brand.haxe-logo:hover {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.navbar .brand.haxe-logo:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
/* create arrow */
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 22px solid transparent;
|
||||
border-bottom: 22px solid transparent;
|
||||
border-left: 7px solid #13110f;
|
||||
/* same color as nav bar */
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.navbar .brand.sub {
|
||||
background: #39332d;
|
||||
/* Old browsers */
|
||||
background: -moz-linear-gradient(top, #39332d 50%, #2c2722 51%);
|
||||
/* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(50%, #39332d), color-stop(51%, #2c2722));
|
||||
/* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, #39332d 50%, #2c2722 51%);
|
||||
/* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, #39332d 50%, #2c2722 51%);
|
||||
/* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, #39332d 50%, #2c2722 51%);
|
||||
/* IE10+ */
|
||||
background: linear-gradient(to bottom, #39332d 50%, #2c2722 51%);
|
||||
/* W3C */
|
||||
padding: 14px 20px 13px 20px;
|
||||
margin: 0 10px 0 0;
|
||||
font: bold 18px "arial black", "open sans";
|
||||
line-height: 22px;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.navbar .brand.sub:hover {
|
||||
color: rgb(230, 230, 230);
|
||||
background: #2c2722;
|
||||
/* Old browsers */
|
||||
}
|
||||
|
||||
.navbar .brand.sub:before {
|
||||
content: "..";
|
||||
/* two dots */
|
||||
position: absolute;
|
||||
margin-left: -33px;
|
||||
margin-top: -28px;
|
||||
line-height: 0px;
|
||||
font: bold 40px "Open Sans", sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #fff200;
|
||||
}
|
||||
|
||||
/** SUB BRAND COLORS **/
|
||||
|
||||
.navbar .brand.sub.try:before {
|
||||
color: #f89c0e;
|
||||
}
|
||||
|
||||
.navbar .brand.sub.api:before {
|
||||
color: #eedc16;
|
||||
}
|
||||
|
||||
.navbar .brand.sub.lib:before {
|
||||
color: #f1471d;
|
||||
}
|
||||
|
||||
.navbar .brand.sub.ide:before {
|
||||
color: #f89c0e;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
Code Highlighting
|
||||
**/
|
||||
html pre,
|
||||
html pre code {
|
||||
font-family: consolas, monospace;
|
||||
white-space: pre;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
code {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
code a {
|
||||
color: #08c;
|
||||
}
|
||||
|
||||
pre {
|
||||
color: #333;
|
||||
margin: 15px 0;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
pre .type {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
pre .kwd {
|
||||
color: #00a;
|
||||
}
|
||||
|
||||
pre .val {
|
||||
color: #44a;
|
||||
}
|
||||
|
||||
pre .str,
|
||||
div.pre .str,
|
||||
pre .str .kwd,
|
||||
pre .str .val,
|
||||
pre .str .type {
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
pre .cmt {
|
||||
color: #008800;
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Make sure keywords inside comments are not highlighted*/
|
||||
pre .cmt .kwd,
|
||||
pre .cmt .str,
|
||||
pre .cmt .val,
|
||||
pre .cmt .type {
|
||||
color: #998;
|
||||
}
|
||||
|
||||
.last-modified {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.semantic {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// highlighter adapted/modified from code.haxe.org
|
||||
(function (console) { "use strict";
|
||||
var EReg = function(r,opt) {
|
||||
opt = opt.split("u").join("");
|
||||
this.r = new RegExp(r,opt);
|
||||
};
|
||||
EReg.prototype = {
|
||||
replace: function(s,by) {
|
||||
return s.replace(this.r,by);
|
||||
}
|
||||
};
|
||||
var Highlighter = function() { };
|
||||
Highlighter.main = function() {
|
||||
var _g = 0;
|
||||
var _g1 = window.document.body.querySelectorAll("pre code");
|
||||
while(_g < _g1.length) {
|
||||
var el = _g1[_g];
|
||||
++_g;
|
||||
if(!Highlighter.hasClass(el,"highlighted")) {
|
||||
el.innerHTML = Highlighter.syntaxHighlight(el.innerHTML);
|
||||
el.className += " highlighted";
|
||||
}
|
||||
}
|
||||
};
|
||||
Highlighter.hasClass = function(el,className) {
|
||||
return el.className.indexOf(className) != -1;
|
||||
};
|
||||
Highlighter.syntaxHighlight = function(html) {
|
||||
var kwds = ["abstract","break","case","cast","catch","class","continue","default","do","dynamic","else","enum","extends","extern","false","final","for","function","if","implements","import","in","inline","interface","macro","new","operator","overload","override","package","private","public","return","static","switch","this","throw","true","try","typedef","untyped","using","var","while"];
|
||||
var kwds1 = new EReg("\\b(" + kwds.join("|") + ")\\b","g");
|
||||
var vals = ["null","true","false","this"];
|
||||
var vals1 = new EReg("\\b(" + vals.join("|") + ")\\b","g");
|
||||
var types = new EReg("\\b([A-Z][a-zA-Z0-9]*)\\b","g");
|
||||
html = kwds1.replace(html,"<span class='kwd'>$1</span>");
|
||||
html = vals1.replace(html,"<span class='val'>$1</span>");
|
||||
html = types.replace(html,"<span class='type'>$1</span>");
|
||||
html = new EReg("(\"[^\"]*\")","g").replace(html,"<span class='str'>$1</span>");
|
||||
html = new EReg("(//.+?)(\n|$)","g").replace(html,"<span class='cmt'>$1</span>$2");
|
||||
html = new EReg("(/\\*\\*?(.|\n)+?\\*?\\*/)","g").replace(html,"<span class='cmt'>$1</span>");
|
||||
return html;
|
||||
};
|
||||
Highlighter.main();
|
||||
})(typeof console != "undefined" ? console : {log:function(){}});
|
||||
@@ -0,0 +1,319 @@
|
||||
function createCookie(name, value) {
|
||||
localStorage.setItem(name, value);
|
||||
}
|
||||
|
||||
function readCookie(name) {
|
||||
return localStorage.getItem(name);
|
||||
}
|
||||
|
||||
function isDarkTheme() {
|
||||
return document.querySelector("html").classList.contains("dark-theme");
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
const htmlTag = document.querySelector("html");
|
||||
let isDark = isDarkTheme();
|
||||
if (isDark) {
|
||||
htmlTag.classList.remove("dark-theme");
|
||||
} else {
|
||||
htmlTag.classList.add("dark-theme");
|
||||
}
|
||||
isDark = isDarkTheme();
|
||||
localStorage.theme = isDark ? "dark" : "light";
|
||||
}
|
||||
|
||||
function toggleInherited(el) {
|
||||
var toggle = $(el).closest(".toggle");
|
||||
toggle.toggleClass("toggle-on");
|
||||
if (toggle.hasClass("toggle-on")) {
|
||||
$("i", toggle).removeClass("fa-folder").addClass("fa-folder-open");
|
||||
} else {
|
||||
$("i", toggle).addClass("fa-folder").removeClass("fa-folder-open");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function toggleCollapsed(el) {
|
||||
var toggle = $(el).closest(".expando");
|
||||
toggle.toggleClass("expanded");
|
||||
|
||||
if (toggle.hasClass("expanded")) {
|
||||
$(toggle).find("i").first().removeClass("fa-folder").addClass("fa-folder-open");
|
||||
} else {
|
||||
$(toggle).find("i").first().addClass("fa-folder").removeClass("fa-folder-open");
|
||||
}
|
||||
updateTreeState();
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateTreeState() {
|
||||
var states = [];
|
||||
$("#nav .expando").each(function (i, e) {
|
||||
states.push($(e).hasClass("expanded") ? 1 : 0);
|
||||
});
|
||||
var treeState = JSON.stringify(states);
|
||||
createCookie("treeState", treeState);
|
||||
}
|
||||
|
||||
function setPlatform(platform) {
|
||||
createCookie("platform", platform);
|
||||
$("#select-platform").val(platform);
|
||||
|
||||
var styles = ".platform { display:none }";
|
||||
var platforms = dox.platforms;
|
||||
if (platform == "flash" || platform == "js") {
|
||||
styles += ".package-sys { display:none; } ";
|
||||
}
|
||||
for (var i = 0; i < platforms.length; i++) {
|
||||
var p = platforms[i];
|
||||
if (platform == "sys") {
|
||||
if (p != "flash" && p != "js") {
|
||||
styles += ".platform-" + p + " { display:inherit } ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (platform == "all" || p == platform) {
|
||||
styles += ".platform-" + p + " { display:inherit } ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (platform != "flash" && platform != "js") {
|
||||
styles += ".platform-sys { display:inherit } ";
|
||||
}
|
||||
|
||||
$("#dynamicStylesheet").text(styles);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$("#nav").html(navContent);
|
||||
var treeState = readCookie("treeState");
|
||||
|
||||
$("#nav .expando").each(function (i, e) {
|
||||
$("i", e).first().addClass("fa-folder").removeClass("fa-folder-open");
|
||||
});
|
||||
|
||||
$(".treeLink").each(function () {
|
||||
this.href = this.href.replace("::rootPath::", dox.rootPath);
|
||||
});
|
||||
|
||||
if (treeState != null) {
|
||||
var states = JSON.parse(treeState);
|
||||
$("#nav .expando").each(function (i, e) {
|
||||
if (states[i]) {
|
||||
$(e).addClass("expanded");
|
||||
$("i", e).first().removeClass("fa-folder").addClass("fa-folder-open");
|
||||
}
|
||||
});
|
||||
}
|
||||
$("head").append("<style id='dynamicStylesheet'></style>");
|
||||
|
||||
setPlatform(readCookie("platform") == null ? "all" : readCookie("platform"));
|
||||
|
||||
$("#search").on("input", function (e) {
|
||||
searchQuery(e.target.value);
|
||||
});
|
||||
$(document).bind("keyup keydown", function (e) {
|
||||
if (e.ctrlKey && e.keyCode == 80) { // ctrl + p
|
||||
$("#search").focus();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
function getItems() {
|
||||
return $("#search-results-list a").toArray();
|
||||
}
|
||||
$("#search").bind("keyup", function (e) {
|
||||
switch (e.keyCode) {
|
||||
case 27: // escape
|
||||
searchQuery("");
|
||||
$("#search").val("")
|
||||
$("#search").blur();
|
||||
return false;
|
||||
|
||||
case 13: // enter
|
||||
var items = getItems();
|
||||
for (i = 0; i < items.length; i++) {
|
||||
var item = $(items[i]);
|
||||
if (item.hasClass("selected")) {
|
||||
window.location = items[i].href;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
$("#search").bind("keydown", function (e) {
|
||||
function mod(a, b) {
|
||||
var r = a % b;
|
||||
return r < 0 ? r + b : r;
|
||||
}
|
||||
function changeSelection(amount) {
|
||||
var previousSelection = null;
|
||||
var items = getItems();
|
||||
for (i = 0; i < items.length; i++) {
|
||||
var item = $(items[i]);
|
||||
if (item.hasClass("selected")) {
|
||||
item.removeClass("selected");
|
||||
previousSelection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var newSelection = mod(previousSelection + amount, items.length);
|
||||
$(items[newSelection]).addClass("selected");
|
||||
items[newSelection].scrollIntoView(false);
|
||||
}
|
||||
switch (e.keyCode) {
|
||||
case 38: // up
|
||||
changeSelection(-1);
|
||||
return false;
|
||||
|
||||
case 40: // down
|
||||
changeSelection(1);
|
||||
return false;
|
||||
|
||||
case 13: // enter
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$("#select-platform").selectpicker().on("change", function (e) {
|
||||
var value = $(":selected", this).val();
|
||||
setPlatform(value);
|
||||
});
|
||||
|
||||
$("#nav a").each(function () {
|
||||
if (this.href == location.href) {
|
||||
$(this.parentElement).addClass("active");
|
||||
}
|
||||
});
|
||||
|
||||
$("a.expand-button").click(function (e) {
|
||||
var container = $(this).parent().next();
|
||||
container.toggle();
|
||||
$("i", this).removeClass("fa-folder-open")
|
||||
.removeClass("fa-folder")
|
||||
.addClass(container.is(":visible") ? "fa-folder-open" : "fa-folder");
|
||||
return false;
|
||||
});
|
||||
|
||||
// Because there is no CSS parent selector
|
||||
$("code.prettyprint").parents("pre").addClass("example");
|
||||
});
|
||||
|
||||
function searchQuery(query) {
|
||||
$("#searchForm").removeAttr("action");
|
||||
query = query.replace(/[&<>"']/g, "");
|
||||
if (!query || query.length < 2) {
|
||||
$("#nav").removeClass("searching");
|
||||
$("#nav li").each(function (index, element) {
|
||||
var e = $(element);
|
||||
e.css("display", "");
|
||||
});
|
||||
$("#nav ul:first-child").css("display", "block");
|
||||
$("#search-results-list").css("display", "none");
|
||||
return;
|
||||
}
|
||||
var queryParts = query.toLowerCase().split(" ");
|
||||
var listItems = [];
|
||||
var bestMatch = 200;
|
||||
$("#nav").addClass("searching");
|
||||
$("#nav ul:first-child").css("display", "none");
|
||||
$("#nav li").each(function (index, element) {
|
||||
var e = $(element);
|
||||
if (!e.hasClass("expando")) {
|
||||
var content = e.attr("data_path");
|
||||
var score = searchMatch(content, queryParts);
|
||||
if (score >= 0) {
|
||||
if (score < bestMatch) {
|
||||
var url = dox.rootPath + e.attr("data_path").split(".").join("/") + ".html";
|
||||
$("#searchForm").attr("action", url);
|
||||
// best match will be form action
|
||||
bestMatch = score;
|
||||
}
|
||||
|
||||
var elLink = $("a", element);
|
||||
// highlight matched parts
|
||||
var elLinkContent = elLink.text().replace(new RegExp("(" + queryParts.join("|").split(".").join("|") + ")", "ig"), "<strong>$1</strong>");
|
||||
var liStyle = (score == 0) ? ("font-weight:bold") : "";
|
||||
listItems.push({ score: score, item: "<li style='" + liStyle + "'><a href='" + elLink.attr("href") + "'>" + elLinkContent + "</a></li>" });
|
||||
}
|
||||
}
|
||||
});
|
||||
if ($("#search-results-list").length == 0) {
|
||||
// append to nav
|
||||
$("#nav").parent().append("<ul id='search-results-list' class='nav nav-list'></ul>");
|
||||
}
|
||||
listItems.sort(function (x, y) { return x.score - y.score; }); // put in order
|
||||
$("#search-results-list").css("display", "block").html(listItems.map(function (x) { return x.item; }).join(""));
|
||||
// pre-select the first item
|
||||
$("#search-results-list a").removeClass("selected");
|
||||
$("#search-results-list a:first").addClass("selected");
|
||||
}
|
||||
|
||||
function match(textParts, query) {
|
||||
var queryParts = query.split(".");
|
||||
if (queryParts.length == 1) {
|
||||
var queryPart = queryParts[0];
|
||||
for (var i = 0; i < textParts.length; ++i) {
|
||||
var textPart = textParts[i];
|
||||
if (textPart.indexOf(queryPart) > -1) {
|
||||
// We don't want to match the same part twice, so let's remove it
|
||||
textParts[i] = textParts[i].split(queryPart).join("");
|
||||
return textPart.length - queryPart.length;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var offset = -1;
|
||||
outer:
|
||||
while (true) {
|
||||
++offset;
|
||||
if (queryParts.length + offset > textParts.length) {
|
||||
return -1;
|
||||
}
|
||||
var scoreSum = 0;
|
||||
for (var i = 0; i < queryParts.length; ++i) {
|
||||
var queryPart = queryParts[i];
|
||||
var textPart = textParts[i + offset];
|
||||
var index = textPart.indexOf(queryPart);
|
||||
if (index != 0) {
|
||||
continue outer;
|
||||
}
|
||||
scoreSum += textPart.length - queryPart.length;
|
||||
}
|
||||
return scoreSum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function searchMatch(text, queryParts) {
|
||||
text = text.toLowerCase();
|
||||
var textParts = text.split(".");
|
||||
var scoreSum = 0;
|
||||
for (var i = 0; i < queryParts.length; ++i) {
|
||||
var score = match(textParts, queryParts[i]);
|
||||
if (score == -1) {
|
||||
return -1;
|
||||
}
|
||||
scoreSum += score + text.length;
|
||||
}
|
||||
return scoreSum;
|
||||
}
|
||||
|
||||
function errorSearch() {
|
||||
var errorURL = "";
|
||||
if (!!window.location.pathname) {
|
||||
errorURL = window.location.pathname;
|
||||
} else if (!!window.location.href) {
|
||||
errorURL = window.location.href;
|
||||
}
|
||||
if (!!errorURL) {
|
||||
var searchTerm = errorURL.split("/").pop();
|
||||
if (searchTerm.indexOf(".html") > -1) { searchTerm = searchTerm.split(".html").join(""); }
|
||||
if (!!searchTerm) {
|
||||
// update filter with search term
|
||||
$("#search").val(searchTerm);
|
||||
searchQuery(searchTerm);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,527 @@
|
||||
.main-content {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.dark {
|
||||
background: rgb(20, 20, 25);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dark a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dark a:hover {
|
||||
color: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
.dark blockquote {
|
||||
border-left: 3px solid rgb(126, 126, 129);
|
||||
}
|
||||
|
||||
.dark blockquote small {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dark blockquote small:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* #nav { */
|
||||
/* float: left; */
|
||||
/* width: 250px; */
|
||||
/* background: green; */
|
||||
/* } */
|
||||
/*#content .header { position:absolute; background:rgba(255,255,255,0.9); left:250px; right:15px; padding:0px 12px; border-bottom:1px solid #EEE;}*/
|
||||
/*#content .body { padding-top:80px;}*/
|
||||
.nav-list {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.nav-list>li>a,
|
||||
.nav-list .nav-header {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.nav-list>li>a.treeLink {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.nav-list a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 14px;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
.nav-list>.active>a.treeLink,
|
||||
.nav-list>.active>a.treeLink:hover,
|
||||
.nav-list>.active>a.treeLink:focus {
|
||||
background: #999;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav>li>a.selected,
|
||||
.nav>li>a:hover {
|
||||
background-color: #00000010;
|
||||
}
|
||||
|
||||
.nav-list li i.fa {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
color: rgb(200, 200, 200);
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.viewsource {
|
||||
float: right
|
||||
}
|
||||
|
||||
/** Footer sitemap **/
|
||||
footer {
|
||||
font-size: 14px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.section.site-footer {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
padding: 6px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.dark .copyright a {
|
||||
color: #F48821;
|
||||
}
|
||||
|
||||
/* .doc { margin-top:16px; } */
|
||||
.toggle-hide {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.toggle-show {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.toggle-on .toggle-hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.toggle-on .toggle-show {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.related-types .toggle-hide {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
/* #nav li { list-style-type: none; } */
|
||||
#nav .expando>ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#nav .expando.expanded>ul {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
/* #nav ul, #nav li li { margin-left: 10px; } */
|
||||
#nav img {
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
#nav .pack {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* .nav .nav li { margin-left: 14px; } */
|
||||
|
||||
.dropdown {
|
||||
padding: 0 9px;
|
||||
}
|
||||
|
||||
#nav.searching .expando>ul {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
#nav.searching .expando>a {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#nav.searching ul {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
#nav.searching .pack {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#nav.searching .nav-list .nav-list {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.nav-header {
|
||||
text-transform: none;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.availability {
|
||||
color: #e48931;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.section-availability {
|
||||
color: #e48931;
|
||||
}
|
||||
|
||||
h3 code {
|
||||
background: none;
|
||||
box-shadow: 0 0 15px rgb(240, 240, 240);
|
||||
padding: 4px 8px;
|
||||
white-space: inherit;
|
||||
display: inline-block;
|
||||
line-height: 1.5em;
|
||||
margin-left: -10px;
|
||||
}
|
||||
|
||||
h3 span.label,
|
||||
.label-meta {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.label.label-meta {
|
||||
background: #5959AC;
|
||||
}
|
||||
|
||||
/* only show some specific whitelisted metadata */
|
||||
|
||||
.label-meta {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.label-meta-callable,
|
||||
.label-meta-commutative,
|
||||
.label-meta-op,
|
||||
.label-meta-arrayAccess,
|
||||
.label-meta-resolve,
|
||||
.label-meta-to,
|
||||
.label-meta-from,
|
||||
.label-meta-using,
|
||||
.label-meta-forward,
|
||||
.label-meta-forwardStatics {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.alert.alert-deprecated {
|
||||
font-size: 90%;
|
||||
margin-bottom: 10px;
|
||||
padding: 4px 35px 4px 14px;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||
font-weight: normal;
|
||||
color: #666;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
white-space: nowrap;
|
||||
border-radius: 3px;
|
||||
padding: 2px 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
code .identifier {
|
||||
font-family: bold 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #002b36;
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
|
||||
code .identifier,
|
||||
code.type {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* code { background:#FDF6E3; color:#002b36; tab-size:4; } [> light <] */
|
||||
code a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
code a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*code.dark { background:#272822; color:#F8F8F2; border:none; } */
|
||||
code .type {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* code .keyword { color:#dc322f; } */
|
||||
/* code .directive { color:#2aa198; } */
|
||||
/* code .constant { color:#AE81FF; } */
|
||||
/* code .comment { color:#75715E; } */
|
||||
/* code .string { color:#E6DB74; } */
|
||||
/* code .macro { color:#A6E22A; } */
|
||||
/* code .inactive { color:#75715E; } */
|
||||
|
||||
/* .navbar-fixed-top { position: fixed; } */
|
||||
/* .navbar-fixed-top .navbar-inner, */
|
||||
/* .navbar-fixed-bottom .navbar-inner { padding: 0; } */
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-size: 16px;
|
||||
font-family: "Open Sans", sans-serif;
|
||||
color: #1e1e1e;
|
||||
line-height: 1.5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
font-weight: 600;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
color: #171717;
|
||||
}
|
||||
|
||||
h1 small {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
h5,
|
||||
h5 code {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
padding: 9px 0;
|
||||
}
|
||||
|
||||
#explorer {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#searchForm {
|
||||
padding: 0 9px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#searchForm .control-group {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.indent {
|
||||
margin-left: 20px;
|
||||
border-left: 5px solid #eeeeee;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
table.params {
|
||||
border-left: 5px solid #eeeeee;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
table.params th {
|
||||
background: #fcfcfc;
|
||||
}
|
||||
|
||||
.doc-main {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.section {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.table p {
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
border-top: 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.table a small {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.table .fa {
|
||||
color: rgb(200, 200, 200);
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.javadoc {
|
||||
/* font-weight: normal; */
|
||||
/* font-size: small; */
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.inline-content * {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stuff for input-block-level:
|
||||
* http://stackoverflow.com/questions/13306670/bootstrap-prepended-and-appended-input-how-to-max-input-field-width
|
||||
*/
|
||||
.input-append.input-block-level,
|
||||
.input-prepend.input-block-level {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.input-append.input-block-level .add-on,
|
||||
.input-prepend.input-block-level .add-on {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.input-append.input-block-level>input,
|
||||
.input-prepend.input-block-level>input {
|
||||
box-sizing: border-box;
|
||||
/* use bootstrap mixin or include vendor variants */
|
||||
-moz-box-sizing: border-box;
|
||||
/* for Firefox */
|
||||
-webkit-box-sizing: border-box;
|
||||
/* for Firefox */
|
||||
-ms-box-sizing: border-box;
|
||||
/* for Firefox */
|
||||
-o-box-sizing: border-box;
|
||||
/* for Firefox */
|
||||
display: table;
|
||||
/* table-cell is not working well in Chrome for small widths */
|
||||
min-height: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-append.input-block-level>input {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.input-prepend.input-block-level>input {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.field {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.field+.field {
|
||||
border-top: 1px solid #eee;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.fields {
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.field-source {
|
||||
margin-top: 15px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.field:hover .field-source {
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
pre.example {
|
||||
position: relative;
|
||||
padding-top: 34.5px;
|
||||
}
|
||||
|
||||
pre.example:before {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
|
||||
content: "Example";
|
||||
color: #999;
|
||||
padding: 2px 6px;
|
||||
background: #fff;
|
||||
font-weight: bold;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
|
||||
-moz-border-radius: 4px 0;
|
||||
-ms-border-radius: 4px 0;
|
||||
-webkit-border-radius: 4px 0;
|
||||
border-radius: 4px 0;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.inherited-fields {
|
||||
padding: 5px 20px;
|
||||
margin-top: 1em;
|
||||
background: #fcfcfc;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
|
||||
.navbar-fixed-top,
|
||||
.navbar-fixed-bottom,
|
||||
.navbar-static-top {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.navbar .divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 979px) {
|
||||
.main-content {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,12 @@
|
||||
::use 'main.mtt'::
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(errorSearch);
|
||||
</script>
|
||||
|
||||
<h1><small>404</small> Page not found</h1>
|
||||
|
||||
<p>Page not found, sorry.</p>
|
||||
|
||||
::end::
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
::use 'main.mtt'::
|
||||
<div class="page-header">
|
||||
<span ::cond api.hasSourceLink(type):: class="viewsource">
|
||||
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
|
||||
</span>
|
||||
<h1><small>::if api.isEnumAbstract(type)::enum ::end::abstract</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)::if !api.isCoreType(type)::($$printLinkedType(::type.athis::,::false::))::end::</h1>
|
||||
$$printPackage(::type::)
|
||||
<h4 ::cond (type.from != null || type.to != null)::>
|
||||
::foreach t type.from::
|
||||
::if t.field == null::
|
||||
<small>::if(repeat.t.index==0)::from ::end::$$printLinkedType(::t.t::,::false::)::if((type.from.length!=1)&&(repeat.t.index<type.from.length-1))::, ::end::</small>
|
||||
::end::
|
||||
::end::
|
||||
::foreach t type.to::
|
||||
::if t.field == null::
|
||||
<small>::if(repeat.t.index==0):: to ::end::$$printLinkedType(::t.t::,::false::)::if((type.to.length!=1)&&(repeat.t.index<type.to.length-1))::, ::end::</small>
|
||||
::end::
|
||||
::end::
|
||||
</h4>
|
||||
$$printModule(::type.module::)
|
||||
$$printMeta(::type::)
|
||||
$$printDeprecation(::type::)
|
||||
$$printPlatforms(::type.platforms::,::true::)
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
<div class="doc doc-main" ::cond type.doc != null::>
|
||||
::raw type.doc::
|
||||
</div>
|
||||
|
||||
::if type.impl != null::
|
||||
$$printClassBody(::type.impl::)
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
@@ -0,0 +1,68 @@
|
||||
::use 'main.mtt'::
|
||||
<div class="page-header">
|
||||
<span ::cond api.hasSourceLink(type):: class="viewsource">
|
||||
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
|
||||
</span>
|
||||
|
||||
<h1>
|
||||
<small>::if type.isFinal::final ::end::::if type.isInterface::interface::else::class::end::</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)
|
||||
</h1>
|
||||
$$printPackage(::type::)
|
||||
::if type.superClass != null::
|
||||
<h4>
|
||||
::set inheritedFields = api.getInheritedFields(type)::
|
||||
<small>extends
|
||||
::if (inheritedFields.types.length>0)::
|
||||
::foreach t inheritedFields.types::
|
||||
$$printLinkedPath(::t.path::,::null::,::false::)::if ((inheritedFields.types.length!=1)&&(repeat.t.index<(inheritedFields.types.length-1))):: › ::end::
|
||||
::end::
|
||||
::else::
|
||||
$$printLinkedPath(::type.superClass.path::,::null::,::false::)
|
||||
::end::
|
||||
</small>
|
||||
</h4>
|
||||
::end::
|
||||
|
||||
<h4 ::cond (type.interfaces.length>0)::>
|
||||
<small>::if type.isInterface::extends::else::implements::end::
|
||||
::foreach i type.interfaces::
|
||||
$$printLinkedPath(::i.path::,::i.params::,::false::)::if ((type.interfaces.length!=1)&&(repeat.i.index<(type.interfaces.length-1)))::, ::end::
|
||||
::end::
|
||||
</small>
|
||||
</h4>
|
||||
|
||||
$$printModule(::type.module::)
|
||||
|
||||
<h4 ::cond subClasses !=null::>
|
||||
<small>
|
||||
::set title = "extended by "::
|
||||
::set infos = subClasses::
|
||||
::use "related_types.mtt"::::end::
|
||||
</small>
|
||||
</h4>
|
||||
<h4 ::cond implementors !=null::>
|
||||
<small>
|
||||
::if type.isInterface::
|
||||
::set title = "extended by "::
|
||||
::else::
|
||||
::set title = "implemented by "::
|
||||
::end::
|
||||
::set infos = implementors::
|
||||
::use "related_types.mtt"::::end::
|
||||
</small>
|
||||
</h4>
|
||||
|
||||
$$printMeta(::type::)
|
||||
$$printDeprecation(::type::)
|
||||
|
||||
$$printPlatforms(::type.platforms::,::true::)
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="doc doc-main" ::cond type.doc != null::>
|
||||
::raw type.doc::
|
||||
</div>
|
||||
$$printClassBody(::type::)
|
||||
|
||||
$$printInheritedFields(::type::)
|
||||
</div>
|
||||
::end::
|
||||
@@ -0,0 +1,27 @@
|
||||
::if (field.doc != null && field.doc != "<p></p>") || !field.isOverride::
|
||||
|
||||
<div class="field ::if (depth == 0 && api.isPlatform(name)) " platform platform-" + name else ""::">
|
||||
::if source_url != null && field.line != null::
|
||||
<a href="::source_url::#L::field.line::" class="field-source pull-right" target="_blank">
|
||||
<i class="fa fa-eye"></i> View source
|
||||
</a>
|
||||
::end::
|
||||
|
||||
<a ::attr name field.name::></a>
|
||||
|
||||
<h3 class="anchor">$$printFieldSignature(::field::,::isStatic::,::type::)</h3>
|
||||
::if field.overloads != null::
|
||||
::foreach field field.overloads::
|
||||
<h3 class="anchor">$$printFieldSignature(::field::,::isStatic::,::type::)</h3>
|
||||
::end::
|
||||
::end::
|
||||
|
||||
$$printDeprecation(::field::)
|
||||
$$printFieldPlatforms(::field::)
|
||||
|
||||
::if field.doc != null::
|
||||
<div class="doc">::raw field.doc::</div>
|
||||
::end::
|
||||
</div>
|
||||
|
||||
::end::
|
||||
@@ -0,0 +1,56 @@
|
||||
::if info.deprecated != null::
|
||||
<div class="alert inline-content">
|
||||
<strong>Deprecated</strong>: ::raw info.deprecated.doc::
|
||||
</div>
|
||||
::end::
|
||||
|
||||
::raw info.doc::
|
||||
|
||||
::if info.params.length > 0::
|
||||
<p class="javadoc">Parameters:</p>
|
||||
<table class="table table-bordered params">
|
||||
::foreach param info.params::
|
||||
<tr><th style="width:25%;"><code>::param.value::</code></th><td>::raw param.doc::</td></tr>
|
||||
::end::
|
||||
</table>
|
||||
::end::
|
||||
|
||||
::if info.returns != null::
|
||||
<p class="javadoc">Returns:</p>
|
||||
<div class="indent inline-content">
|
||||
::raw info.returns.doc::
|
||||
</div>
|
||||
::end::
|
||||
|
||||
::if info.throws.length > 0::
|
||||
<p class="javadoc">Throws:</p>
|
||||
<table class="table table-bordered params">
|
||||
::foreach throws info.throws::
|
||||
<tr class="indent"><th style="width:25%;"><code>::throws.value::</code></th><td>::raw throws.doc::</td></tr>
|
||||
::end::
|
||||
</table>
|
||||
::end::
|
||||
|
||||
::if info.events.length > 0::
|
||||
<p class="javadoc">Events:</p>
|
||||
<table class="table table-bordered params">
|
||||
::foreach event info.events::
|
||||
<tr class="indent"><th style="width:25%;"><code>::event.value::</code></th><td>::raw event.doc::</td></tr>
|
||||
::end::
|
||||
</table>
|
||||
::end::
|
||||
|
||||
::if info.since != null::
|
||||
<div class="javadoc inline-content">
|
||||
Available since ::raw info.since.doc::.
|
||||
</div>
|
||||
::end::
|
||||
|
||||
::if info.sees.length > 0::
|
||||
<p class="javadoc">See also:</p>
|
||||
<ul>
|
||||
::foreach see info.sees::
|
||||
<li><div class="inline-content">::raw see.doc::</div></li>
|
||||
::end::
|
||||
</ul>
|
||||
::end::
|
||||
@@ -0,0 +1,26 @@
|
||||
::use 'main.mtt'::
|
||||
<div class="page-header">
|
||||
<span ::cond api.hasSourceLink(type):: class="viewsource">
|
||||
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
|
||||
</span>
|
||||
<h1><small>enum</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)</h1>
|
||||
$$printPackage(::type::)
|
||||
$$printModule(::type.module::)
|
||||
$$printMeta(::type::)
|
||||
$$printDeprecation(::type::)
|
||||
$$printPlatforms(::type.platforms::,::true::)
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="doc doc-main" ::cond type.doc != null::>
|
||||
::raw type.doc::
|
||||
</div>
|
||||
::if type.constructors.length > 0::
|
||||
<h3 class="section">Values</h3>
|
||||
<div class="fields">
|
||||
::foreach ctor type.constructors::
|
||||
::use "enum_field.mtt"::::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
@@ -0,0 +1,19 @@
|
||||
<div class="field">
|
||||
|
||||
<h3>
|
||||
<code>
|
||||
<a name="::ctor.name::" href="#::ctor.name::">
|
||||
<span class="identifier">::ctor.name::</span>
|
||||
</a>
|
||||
::if ctor.args != null::
|
||||
(::foreach arg ctor.args::::arg.name:::$$printLinkedType(::arg.t::,::false::)::if !repeat.arg.last::, ::end::::end::)
|
||||
::end::
|
||||
</code>
|
||||
</h3>
|
||||
$$printDeprecation(::ctor::)
|
||||
$$printFieldPlatforms(::ctor::)
|
||||
|
||||
<div class="doc" ::cond ctor.doc != null::>
|
||||
::raw ctor.doc::
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<footer class="section site-footer" style="background:$$getHexValue(::themeColor::)">
|
||||
<div class="container">
|
||||
<div class="copyright">
|
||||
<p ::cond api.isDefined("version")::>This documentation is generated for version ::api.getValue('version')::</p>
|
||||
<p>© ::api.config.date.getFullYear()::
|
||||
<a ::cond api.isDefined("website"):: ::attr href api.getValue("website")::>The Funkin' Crew Inc</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -0,0 +1,36 @@
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<link href="::api.config.rootPath::bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="::api.config.rootPath::bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" />
|
||||
<link href="::api.config.rootPath::bootstrap/css/bootstrap-select.min.css" rel="stylesheet" />
|
||||
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,700italic,400italic' rel='stylesheet' type='text/css'/>
|
||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:200,600,600italic,400' rel='stylesheet' type='text/css'/>
|
||||
<link href='https://netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css' rel='stylesheet' type='text/css' />
|
||||
|
||||
<script src="::api.config.rootPath::jquery-3.6.0.min.js"></script>
|
||||
<script src="::api.config.rootPath::bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="::api.config.rootPath::bootstrap/js/bootstrap-select.min.js"></script>
|
||||
<link href="::api.config.rootPath::styles.css" rel="stylesheet" />
|
||||
<link href="::api.config.rootPath::extra-styles.css" rel="stylesheet" />
|
||||
<link href="::api.config.rootPath::haxe-nav.css" rel="stylesheet" />
|
||||
<link href="::api.config.rootPath::dark-mode.css" rel="stylesheet" />
|
||||
<script>var dox = {
|
||||
rootPath: "::api.config.rootPath::",
|
||||
platforms: [
|
||||
::foreach pf api.config.platforms::
|
||||
"::pf::"
|
||||
::if !repeat.pf.last::,::end::
|
||||
::end::
|
||||
]
|
||||
};</script>
|
||||
<script src="::api.config.rootPath::nav.js"></script>
|
||||
<script src="::api.config.rootPath::index.js"></script>
|
||||
<link rel="icon" href="https://funkin.me/img/construction-icon.ico" type="image/x-icon"/>
|
||||
<title>::api.currentPageName::::if api.config.pageTitle !=null:: - ::api.config.pageTitle::::end::</title>
|
||||
|
||||
::set description = api.getShortDesc(type)::
|
||||
::set description = description.substr(3, description.length-7)::
|
||||
<meta name="description" ::cond type.doc!=null && description.length>0:: content="::description::"/>
|
||||
::use "extra-headers.mtt"::::end::
|
||||
</head>
|
||||
@@ -0,0 +1,336 @@
|
||||
<macro name="printTypeParams(params)">
|
||||
::if params.length > 0::
|
||||
<
|
||||
::foreach param params::
|
||||
<span class="type">::param::</span>
|
||||
::if !repeat.param.last::, ::end::
|
||||
::end::
|
||||
>
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="getHexValue(value)">::value.split("0x").join("#")::</macro>
|
||||
|
||||
<macro name="printPlatforms(platforms, useSeparator)">
|
||||
::if (useSeparator && api.config.platforms.length>1)::<hr/>::end::
|
||||
<p class="availability" ::cond (api.config.platforms.length>1)::>
|
||||
<em>
|
||||
Available on
|
||||
::if platforms.length == api.config.platforms.length:: all platforms
|
||||
::elseif platforms.length > 1:: ::platforms.join(", ")::
|
||||
::else:: ::platforms.join("")::
|
||||
::end::
|
||||
</em>
|
||||
</p>
|
||||
</macro>
|
||||
|
||||
<macro name="printFieldPlatforms(field)">
|
||||
::if field.platforms.length != type.platforms.length && field.platforms.length > 0 && field.platforms.length < api.config.platforms.length::
|
||||
$$printPlatforms(::field.platforms::,::false::)
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="printLinkedPath(path, params, qualified)">
|
||||
::if api.isKnownType(path)::
|
||||
<a class="type" title="::api.getSentenceDesc(api.resolveType(path))::" ::attr href api.pathToUrl(path)::>
|
||||
::if qualified::
|
||||
::path::
|
||||
::else::
|
||||
::api.getPathName(path)::
|
||||
::end::
|
||||
</a>
|
||||
::else::
|
||||
<span class="type">::api.getPathName(path)::</span>
|
||||
::end::
|
||||
::if params != null && params.length > 0::
|
||||
<
|
||||
::foreach param params::
|
||||
$$printLinkedType(::param::,::qualified::)
|
||||
::if !repeat.param.last::, ::end::
|
||||
::end::
|
||||
>
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="printLinkedType(ctype, qualified)">
|
||||
::switch ctype::
|
||||
::case::Unknown
|
||||
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
|
||||
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
|
||||
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
|
||||
::case::
|
||||
::if args[0].length != 1 || args[0][0].name != ""::(::end::
|
||||
::foreach arg args[0]::
|
||||
::if arg.name != ""::
|
||||
::arg.name:::
|
||||
::end::
|
||||
$$printLinkedType(::arg.t::,::qualified::)
|
||||
::if !repeat.arg.last::, ::end::
|
||||
::end::
|
||||
::if args[0].length != 1 || args[0][0].name != ""::)::end::
|
||||
‑>
|
||||
$$printLinkedType(::args[1]::,::qualified::)
|
||||
::case::
|
||||
{
|
||||
::foreach field args[0]::
|
||||
::field.name:::$$printLinkedType(::field.type::,::qualified::)
|
||||
::if !repeat.field.last::, ::end::
|
||||
::end::
|
||||
}
|
||||
::case::$$printLinkedPath(::"Dynamic"::,::null::,::qualified::)::if args[0] != null::<$$printLinkedType(::args[0]::,::qualified::)>::end::
|
||||
::case::$$printLinkedPath(::args[0]::,::args[1]::,::qualified::)
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="printModule(module)">
|
||||
<h4 ::cond module != null && module != "StdTypes"::><small>import <a ::attr href api.pathToUrl(module)::>::module::</a></small></h4>
|
||||
</macro>
|
||||
|
||||
<macro name="printDeprecation(field)">
|
||||
::if (field.meta != null)::
|
||||
::foreach meta field.meta::
|
||||
::if (meta.name == ":deprecated")::
|
||||
<div class="alert alert-warning alert-deprecated">
|
||||
<strong>Deprecated:</strong>
|
||||
::if (meta.params != null && meta.params.length > 0)::
|
||||
::foreach param meta.params::
|
||||
::param::
|
||||
::if !repeat.param.last::, ::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
::end::
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="printMeta(field)">
|
||||
::if (field.meta != null)::
|
||||
::foreach meta field.meta::
|
||||
::if (meta.name != ":deprecated")::::if false::<!--skip deprecation meta, see printDeprecation -->::end::
|
||||
::set metaName = meta.name.substr(1)::
|
||||
::set displayMetaName = "@" + meta.name::
|
||||
<span class="label label-meta label-meta-::metaName::" title="::api.getMetaDesc(meta.name)::">::displayMetaName::
|
||||
::if (meta.params != null && meta.params.length > 0)::(
|
||||
::foreach param meta.params::
|
||||
$$printMetaParam(::param::)
|
||||
::if !repeat.param.last::,::end::
|
||||
::end::
|
||||
)::end::</span>
|
||||
::end::
|
||||
::end::
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="printMetaParam(param)">::if (param.substr(0,9) == "<![CDATA[")::::param.substr(9,param.length-3-9)::::else::::param::::end::</macro>
|
||||
|
||||
<macro name="printFieldSignature(field, isStatic, type)">
|
||||
<code>
|
||||
::if !field.isPublic::
|
||||
<span class="label label-private">private</span>
|
||||
::end::
|
||||
|
||||
$$printMeta(::field::)
|
||||
|
||||
::if isStatic::
|
||||
<span class="label label-static">static</span>
|
||||
::end::
|
||||
|
||||
::set fieldInfo = api.getFieldInfo(field)::
|
||||
|
||||
::if fieldInfo.modifiers.isOptional::
|
||||
<span class="label label-optional">optional</span>
|
||||
::end::
|
||||
|
||||
::if fieldInfo.modifiers.isFinal::
|
||||
<span class="label label-final">final</span>
|
||||
::end::
|
||||
|
||||
::if fieldInfo.modifiers.isDynamic::
|
||||
<span class="label label-dynamic">dynamic</span>
|
||||
::end::
|
||||
|
||||
::if fieldInfo.modifiers.isInline::
|
||||
<span class="label label-inline">inline</span>
|
||||
::end::
|
||||
|
||||
::switch fieldInfo.kind::
|
||||
::switch field.set::
|
||||
::case 1::
|
||||
<span class="label">read only</span>
|
||||
::end::
|
||||
::switch field.get::
|
||||
::case 1::
|
||||
<span class="label">write only</span>
|
||||
::end::
|
||||
|
||||
<a href="#::field.name::"><span class="identifier">::field.name::</span></a>:$$printLinkedType(::field.type::,::false::)$$printInitExpr(::field.expr::)
|
||||
|
||||
::case 2::
|
||||
<a href="#::field.name::"><span class="identifier">::field.name::</span></a>
|
||||
$$printTypeParams(::field.params::)(
|
||||
::foreach arg args[0]::
|
||||
<span style="white-space:nowrap">
|
||||
::if arg.opt && (arg.value == null || arg.value == "null")::?::end::
|
||||
::arg.name:::$$printLinkedType(::arg.t::,::false::)
|
||||
::if arg.value != null && arg.value != "null":: = ::arg.value::::end::
|
||||
::if !repeat.arg.last::,::end::
|
||||
</span>
|
||||
::if !repeat.arg.last:: ::end::
|
||||
::end::
|
||||
)
|
||||
::if field.name != "new"::
|
||||
:$$printLinkedType(::args[1]::,::false::)
|
||||
::end::
|
||||
::end::
|
||||
</code>
|
||||
</macro>
|
||||
|
||||
<macro name="printInitExpr(expr)">
|
||||
<span ::cond expr != null::>
|
||||
= ::expr::
|
||||
</span>
|
||||
</macro>
|
||||
|
||||
<macro name="printClassBody(type)">
|
||||
::set showSection = false::
|
||||
::foreach field type.statics::
|
||||
::if !api.isMethod(field)::
|
||||
::eval showSection = true::
|
||||
::end::
|
||||
::end::
|
||||
::if showSection::
|
||||
<h3 class="section">Static variables</h3>
|
||||
<div class="fields">
|
||||
::foreach field type.statics::
|
||||
::set isStatic = true::
|
||||
::if !api.isMethod(field)::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
|
||||
::set showSection = false::
|
||||
::foreach field type.statics::
|
||||
::if api.isMethod(field)::
|
||||
::eval showSection = true::
|
||||
::end::
|
||||
::end::
|
||||
::if showSection::
|
||||
<h3 class="section">Static methods</h3>
|
||||
<div class="fields">
|
||||
::foreach field type.statics::
|
||||
::set isStatic = true::
|
||||
::if api.isMethod(field)::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
|
||||
::set showSection = false::
|
||||
::foreach field type.fields::
|
||||
::if field.name == "new" && api.isMethod(field)::
|
||||
::eval showSection = true::
|
||||
::end::
|
||||
::end::
|
||||
::if showSection::
|
||||
<h3 class="section">Constructor</h3>
|
||||
<div class="fields">
|
||||
::foreach field type.fields::
|
||||
::set isStatic = false::
|
||||
::if field.name == "new" && api.isMethod(field)::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
|
||||
::set showSection = false::
|
||||
::foreach field type.fields::
|
||||
::if !api.isMethod(field)::
|
||||
::eval showSection = true::
|
||||
::end::
|
||||
::end::
|
||||
::if showSection::
|
||||
<h3 class="section">Variables</h3>
|
||||
<div class="fields">
|
||||
::foreach field type.fields::
|
||||
::set isStatic = false::
|
||||
::if !api.isMethod(field)::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
|
||||
::set showSection = false::
|
||||
::foreach field type.fields::
|
||||
::if field.name != "new" && api.isMethod(field)::
|
||||
::eval showSection = true::
|
||||
::end::
|
||||
::end::
|
||||
::if showSection::
|
||||
<h3 class="section">Methods</h3>
|
||||
<div class="fields">
|
||||
::foreach field type.fields::
|
||||
::set isStatic = false::
|
||||
::if field.name != "new" && api.isMethod(field)::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="printInheritedFields(type)">
|
||||
::if type.superClass != null::
|
||||
::set inheritedFields = api.getInheritedFields(type)::
|
||||
::set hasFields = inheritedFields.fields.keys().hasNext()::
|
||||
::set hasMethods = inheritedFields.methods.keys().hasNext()::
|
||||
|
||||
<div class="inherited-fields well" ::cond hasFields || hasMethods::>
|
||||
<h3 class="section" ::cond hasFields::>Inherited Variables</h3>
|
||||
<div class="fields" ::cond hasFields::>
|
||||
::set fields=inheritedFields.fields::
|
||||
::foreach cl inheritedFields.types::
|
||||
<h4 ::cond fields.get(cl).length>0::><a href="#" class="expand-button"><i class="fa fa-arrow-circle-o-right"></i></a> Defined by $$printLinkedPath(::cl.path::,::null::,::false::)</h4>
|
||||
<div style="display:none">
|
||||
::foreach field fields.get(cl)::
|
||||
::set isStatic = false::
|
||||
::set type=cl::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
</div>
|
||||
|
||||
<h3 class="section" ::cond hasMethods::>Inherited Methods</h3>
|
||||
<div class="fields" ::cond hasMethods::>
|
||||
::set fields=inheritedFields.methods::
|
||||
::foreach cl inheritedFields.types::
|
||||
<h4 ::cond fields.get(cl).length>0::><a href="#" class="expand-button"><i class="fa fa-arrow-circle-o-right"></i></a> Defined by $$printLinkedPath(::cl.path::,::null::,::false::)</h4>
|
||||
<div style="display:none">
|
||||
::foreach field fields.get(cl)::
|
||||
::set isStatic = false::
|
||||
::if field.name != "new" ::
|
||||
::set type=cl::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
</div>
|
||||
</div>
|
||||
::end::
|
||||
</macro>
|
||||
|
||||
<macro name="printPackage(type)">
|
||||
::if type.path.indexOf(".", 0) >= 0::
|
||||
::set packagePath = type.path.split(".").slice(0, -1).join(".")::
|
||||
<h4><small>package <a ::attr href api.packageToUrl(packagePath)::>::packagePath::</a></small></h4>
|
||||
::else::
|
||||
<h4><small><a href="./">no package</a></small></h4>
|
||||
::end::
|
||||
</macro>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<!-- use theme color or fallback -->
|
||||
::set themeColor="0xFAFAFA"::
|
||||
::if (api.isDefined("themeColor"))::::set themeColor=api.getValue("themeColor")::::end::
|
||||
|
||||
<!--use textcolor from settings, otherwise create a contrasting color to theme color-->
|
||||
::set textColor="0xFFFFFF"::
|
||||
::if (api.isDefined("textColor"))::::set textColor=api.getValue("textColor")::
|
||||
::elseif (api.std.parseInt(themeColor) > 7829367)::::set textColor="0x000000"::::end::
|
||||
|
||||
::use "header.mtt"::::end::
|
||||
<body>
|
||||
<script>
|
||||
/* Here to prevent flash of unstyled content */
|
||||
let systemDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
if ((!localStorage.theme && systemDarkMode) || localStorage.theme == "dark") {
|
||||
document.body.style.backgroundColor = "#111";
|
||||
document.body.style.opacity = "0";
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
toggleTheme();
|
||||
document.body.style.backgroundColor = "";
|
||||
document.body.style.opacity = "";
|
||||
});
|
||||
}
|
||||
</script>
|
||||
::use "topbar.mtt"::::end::
|
||||
<div class="container main-content">
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
<div class="well sidebar-nav">
|
||||
<form class="form-search" id="searchForm">
|
||||
<div class="input-prepend input-block-level">
|
||||
<span class="add-on"><i class="fa fa-search"></i></span>
|
||||
<input id="search" type="text" placeholder="Filter (Ctrl+P)" autocomplete="off"/>
|
||||
</div>
|
||||
</form>
|
||||
<div class="dropdown" ::cond (api.config.platforms.length>1)::>
|
||||
<select id="select-platform" class="selectpicker" title="Filter by platform" data-width="100%">
|
||||
<option value="all" selected="selected">All Platforms</option>
|
||||
::foreach i api.config.platforms::
|
||||
<option>::i::</option>
|
||||
::end::
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="well sidebar-nav" id="explorer">
|
||||
<div id="nav"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span9">::raw __content__::</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
::use "footer.mtt"::::end::
|
||||
|
||||
|
||||
<script src="::api.config.rootPath::highlighter.js"></script>
|
||||
<link href="::api.config.rootPath::highlighter.css" rel="stylesheet" />
|
||||
|
||||
::if (api.isDefined("googleAnalytics"))::
|
||||
::set trackingID=api.getValue("googleAnalytics")::
|
||||
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=::trackingID::"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', '::trackingID::');
|
||||
</script>
|
||||
::end::
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<macro name="makeTree(tree,depth)">
|
||||
::switch tree::
|
||||
<li ::attr data_path api.getTreePath(tree)::>
|
||||
::set pack = api.getTreePack(tree)::
|
||||
<a class="treeLink" href="::api.getTreeUrl(tree)::" title=":: pack + "." + api.getTreeName(tree) ::">
|
||||
::api.getTreeName(tree)::
|
||||
::if pack != ""::
|
||||
<span class="pack"> - ::pack::</span>
|
||||
::end::
|
||||
</a>
|
||||
</li>
|
||||
::case::
|
||||
::set name = args[0]::
|
||||
<li ::cond name.charAt(0) != "_"::
|
||||
::attr class "expando " + if (depth == 0 && api.isPlatform(name)) "platform platform-" + name else if (depth == 0) "package-" + name else "" ::>
|
||||
<a class="nav-header" href="#" onclick="return toggleCollapsed(this)">
|
||||
<i class="fa fa-folder"></i>
|
||||
::api.getTreeName(tree)::
|
||||
</a>
|
||||
<ul class="nav nav-list">
|
||||
::foreach sub args[2]::
|
||||
$$makeTree(::sub::,::depth + 1::)
|
||||
::end::
|
||||
</ul>
|
||||
</li>
|
||||
::end::
|
||||
</macro>
|
||||
var navContent='<ul class="nav nav-list">
|
||||
::foreach tree root::
|
||||
$$makeTree(::tree::,::0::)
|
||||
::end::
|
||||
</ul>
|
||||
';
|
||||
@@ -0,0 +1,37 @@
|
||||
::use 'main.mtt'::
|
||||
|
||||
::use 'package_description.mtt'::::end::
|
||||
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
<tr ::cond full != ""::>
|
||||
<th style="width:200px;">
|
||||
<i class="fa fa-folder-o"></i>
|
||||
<a href="::api.packageToUrl(full.split(".").slice(0,-1).join("."))::" title="::full.split(".").slice(0,-1).join(".")::">..</a>
|
||||
</th>
|
||||
<td></td>
|
||||
</tr>
|
||||
::foreach tree subs::
|
||||
::set name = api.getTreeName(tree)::
|
||||
::set treeType = api.getTreeType(tree)::
|
||||
<tr class="::treeType::" ::cond name.charAt(0) != "_"::>
|
||||
::if (treeType=="package")::
|
||||
<td colspan="2">
|
||||
<i class="fa fa-folder-o"></i>
|
||||
<a href="::api.getTreeUrl(tree)::" title="::full::.::name::">::name::</a>
|
||||
</td>
|
||||
::else::
|
||||
<td style="width:200px;">
|
||||
<a href="::api.getTreeUrl(tree)::" title="::full::.::name::">::name::</a>
|
||||
</td>
|
||||
<td>
|
||||
::raw api.getTreeShortDesc(tree)::
|
||||
</td>
|
||||
::end::
|
||||
</tr>
|
||||
::end::
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
::end::
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<h1>::api.currentPageName:: <small ::cond api.isDefined("version") && full == ""::>version ::api.getValue('version')::</small></h1>
|
||||
<p ::cond api.isDefined("description")::>::api.getValue("description")::</p>
|
||||
@@ -0,0 +1,4 @@
|
||||
<span class="muted">::title::</span>
|
||||
::foreach info infos::
|
||||
$$printLinkedPath(::info.path::,::null::,::false::)::if !repeat.info.last::, ::end::
|
||||
::end::
|
||||
@@ -0,0 +1,23 @@
|
||||
<style>
|
||||
::raw "
|
||||
.navbar .brand {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
text-shadow: 0 0 0 transparent;
|
||||
}
|
||||
"::
|
||||
</style>
|
||||
<nav class="nav">
|
||||
<div class="navbar">
|
||||
<div class="navbar-inner" style="background:$$getHexValue(::themeColor::); border-bottom:1px solid rgba(0,0,0,.09)">
|
||||
<div class="container">
|
||||
<a href="https://funkin.me/" class="brand"><img alt="The Funkin' Crew Inc main website" src="https://funkin.me/img/api/funkin-api-export.svg" width="150" height="50"/></a>
|
||||
<a href="https://funkin.me/api-reference/" class="brand" style="color:$$getHexValue(::textColor::)">::if api.config.pageTitle!=null::::api.config.pageTitle::::else::API Documentation::end::</a>
|
||||
<div class="brand">
|
||||
<p>|</p>
|
||||
</div>
|
||||
<a href="https://funkin.me/cookbook/" class="brand" style="color:$$getHexValue(::textColor::)">Cookbook</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -0,0 +1,49 @@
|
||||
::use 'main.mtt'::
|
||||
<div class="page-header">
|
||||
<span ::cond api.hasSourceLink(type):: class="viewsource">
|
||||
<a href="::api.getSourceLink(type)::" class="btn btn-medium"><i class="fa fa-eye"></i> View source</a>
|
||||
</span>
|
||||
<h1><small>typedef</small> ::api.getPathName(type.path)::$$printTypeParams(::type.params::)</h1>
|
||||
$$printPackage(::type::)
|
||||
$$printModule(::type.module::)
|
||||
$$printMeta(::type::)
|
||||
$$printDeprecation(::type::)
|
||||
$$printPlatforms(::type.platforms::,::true::)
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
<div class="doc doc-main" ::cond type.doc != null::>
|
||||
::raw type.doc::
|
||||
</div>
|
||||
|
||||
::set multiplePlatforms = api.lambda.array(type.types).length > 1::
|
||||
::foreach platform type.types.keys()::
|
||||
::set platformType = type.types.get(platform)::
|
||||
::if multiplePlatforms::
|
||||
<h4 class="section section-availability">::platform::</h4>
|
||||
::end::
|
||||
::switch platformType::
|
||||
::if !multiplePlatforms::<h3 class="section">Alias</h3>::end::
|
||||
<div class="fields">
|
||||
<div class="field">
|
||||
<em>alias for </em><code>$$printLinkedType(::platformType::,::true::)</code>
|
||||
</div>
|
||||
</div>
|
||||
::case 5::
|
||||
::if !multiplePlatforms::<h3 class="section">Fields</h3>::end::
|
||||
<div class="fields">
|
||||
::switch platformType::
|
||||
::case 5::
|
||||
::if args[0].length == 0::
|
||||
<em>empty structure</em>
|
||||
::else::
|
||||
::foreach field args[0]::
|
||||
::use "class_field.mtt"::::end::
|
||||
::end::
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
::end::
|
||||
</div>
|
||||
::end::
|
||||
@@ -0,0 +1,42 @@
|
||||
cd ../..
|
||||
|
||||
# ask for version
|
||||
$version = Read-Host "Enter version (Will display on the website)"
|
||||
|
||||
# regenerate XML files?
|
||||
$regenerateXml = Read-Host "Regenerate XML files? (y/n)"
|
||||
|
||||
if ($regenerateXml -eq "y") {
|
||||
Write-Host "Regenerating XML files..."
|
||||
echo "Generating docs for version $version..."
|
||||
|
||||
lime build linux -xml -cpp --no-output -Ddoc-gen
|
||||
lime build windows -xml -cpp --no-output -Ddoc-gen
|
||||
|
||||
copy export\release\windows\types.xml docs\dox\Windows.xml
|
||||
copy export\release\linux\types.xml docs\dox\Linux.xml
|
||||
} else {
|
||||
Write-Host "Skipping XML regeneration..."
|
||||
}
|
||||
|
||||
# Then run dox
|
||||
haxelib run dox `
|
||||
-i .\docs\dox\ `
|
||||
-o docs/dox/output `
|
||||
--title "Funkin'" `
|
||||
-theme "docs/dox/funkin-theme" `
|
||||
-D version "$version" `
|
||||
-D source-path "https://github.com/FunkinCrew/Funkin/tree/main/source" `
|
||||
-D website "https://funkin.me/" `
|
||||
-D description "Friday Night Funkin' API Reference" `
|
||||
-in "funkin" `
|
||||
-in "openfl" `
|
||||
-in "lime" `
|
||||
-in "flixel" `
|
||||
-ex "funkin.ui.debug.*" `
|
||||
-ex "funkin.macro.*" `
|
||||
-ex "funkin.save.*" `
|
||||
-ex "funkin.api.*" `
|
||||
-ex "funkin.vis.*"
|
||||
|
||||
cd docs/dox
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
cd ../..
|
||||
|
||||
# ask for version
|
||||
read -p "Enter version (Will display on the website): " version
|
||||
|
||||
# regenerate XML files?
|
||||
read -p "Regenerate XML files? (y/n): " regenerateXml
|
||||
|
||||
if [ "$regenerateXml" == "y" ]; then
|
||||
echo "Regenerating XML files..."
|
||||
|
||||
echo "Generating docs for version $version..."
|
||||
|
||||
lime build windows -xml -cpp --no-output -Ddoc-gen
|
||||
lime build linux -xml -cpp --no-output -Ddoc-gen
|
||||
|
||||
cp export/release/linux/types.xml docs/dox/Linux.xml
|
||||
cp export/release/windows/types.xml docs/dox/Windows.xml
|
||||
else
|
||||
echo "Skipping XML regeneration..."
|
||||
fi
|
||||
|
||||
# Then run dox
|
||||
haxelib run dox \
|
||||
-i ./docs/dox/ \
|
||||
-o docs/dox/output \
|
||||
-theme "docs/dox/funkin-theme" \
|
||||
--title "Funkin'" \
|
||||
-D version "$version" \
|
||||
-D source-path "https://github.com/FunkinCrew/Funkin/tree/main/source" \
|
||||
-D website "https://funkin.me/" \
|
||||
-D description "Friday Night Funkin' API Reference" \
|
||||
-in "funkin" \
|
||||
-in "openfl" \
|
||||
-in "lime" \
|
||||
-in "flixel" \
|
||||
-ex "funkin.ui.debug.*" \
|
||||
-ex "funkin.macro.*" \
|
||||
-ex "funkin.save.*" \
|
||||
-ex "funkin.api.*" \
|
||||
-ex "funkin.vis.*"
|
||||
|
||||
cd docs/dox
|
||||
@@ -6,7 +6,7 @@
|
||||
"name": "EliteMasterEric"
|
||||
}
|
||||
],
|
||||
"api_version": "0.7.0",
|
||||
"api_version": "0.8.0",
|
||||
"mod_version": "1.0.0",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"name": "EliteMasterEric"
|
||||
}
|
||||
],
|
||||
"api_version": "0.7.0",
|
||||
"api_version": "0.8.0",
|
||||
"mod_version": "1.0.0",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
|
||||
@@ -4,75 +4,91 @@
|
||||
"name": "FlxPartialSound",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "26ed20b9c181a576f4cbe18ccdea38912c01476e",
|
||||
"ref": "13a0949395250216b9b500ca0731b46841e46085",
|
||||
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
|
||||
},
|
||||
{
|
||||
"name": "astc-compressor",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "b7a91b3072dc16e785a9bde847f17ba0ef15dd47",
|
||||
"ref": "6c0fa6f46d3547ca58859b6ede87e659018a7ff5",
|
||||
"url": "https://github.com/KarimAkra/astc-compressor"
|
||||
},
|
||||
{
|
||||
"name": "extension-admob",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "4c69bb43f1fb89fd6003dc98d2f3a9d75c5364b6",
|
||||
"ref": "68fc73c4090c5765709597b68fbe87389f3548c0",
|
||||
"url": "https://github.com/FunkinCrew/extension-admob"
|
||||
},
|
||||
{
|
||||
"name": "extension-agesignals",
|
||||
"type": "git",
|
||||
"ref": "dd3f56ccbb313a43d40cba8826fca2b1ec7c7e5d",
|
||||
"url": "https://github.com/FunkinCrew/extension-agesignals"
|
||||
},
|
||||
{
|
||||
"name": "extension-androidtools",
|
||||
"type": "haxelib",
|
||||
"version": "2.2.2"
|
||||
},
|
||||
{
|
||||
"name": "extension-haptics",
|
||||
"name": "dox",
|
||||
"type": "haxelib",
|
||||
"version": "1.0.4"
|
||||
"version": "1.6.0"
|
||||
},
|
||||
{
|
||||
"name": "extension-haptics",
|
||||
"type": "git",
|
||||
"ref": "8978b34b437f943a0d164bd6b3d8b69bd0025081",
|
||||
"url": "https://github.com/LimeExtensions/extension-haptics"
|
||||
},
|
||||
{
|
||||
"name": "extension-iapcore",
|
||||
"type": "haxelib",
|
||||
"version": "1.0.4"
|
||||
"type": "git",
|
||||
"ref": "5fbb4a8e56ff0f4d8ffc71b561d57a367419ead8",
|
||||
"url": "https://github.com/LimeExtensions/extension-iapcore"
|
||||
},
|
||||
{
|
||||
"name": "extension-iarcore",
|
||||
"type": "haxelib",
|
||||
"version": "1.0.3"
|
||||
"type": "git",
|
||||
"ref": "a78e49fe69feecef9abcdbcfd08ccc510ed00c6c",
|
||||
"url": "https://github.com/LimeExtensions/extension-iarcore"
|
||||
},
|
||||
{
|
||||
"name": "extension-webviewcore",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "d13109450d65c40678244ca23b1aa88ac18d77e6",
|
||||
"ref": "98c059722491b182ee932ff47c5d7b564c967165",
|
||||
"url": "https://github.com/LimeExtensions/extension-webviewcore"
|
||||
},
|
||||
{
|
||||
"name": "flixel",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "c8e79d2a42f9c11c639519ef2a6fd7ef2379a8aa",
|
||||
"ref": "141f23c400c0508c76d5a09a143f5ce6790f8122",
|
||||
"url": "https://github.com/FunkinCrew/flixel"
|
||||
},
|
||||
{
|
||||
"name": "flixel-addons",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "6fa30b3f5209146c852c25f3d1003e08898083e2",
|
||||
"ref": "7628435364c4a45440d1e5db656741b66a8cd2ec",
|
||||
"url": "https://github.com/FunkinCrew/flixel-addons"
|
||||
},
|
||||
{
|
||||
"name": "flixel-animate",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "c61476f4b3a3d225631ab3065e4e925a4b63c076",
|
||||
"ref": "c5e3393c70b71a191f20fa902114cea92042e486",
|
||||
"url": "https://github.com/MaybeMaru/flixel-animate"
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
"type": "haxelib",
|
||||
"version": "3.5.0"
|
||||
"version": "3.8.0"
|
||||
},
|
||||
{
|
||||
"name": "svg",
|
||||
"type": "haxelib",
|
||||
"version": "1.1.3"
|
||||
},
|
||||
{
|
||||
"name": "funkin.vis",
|
||||
@@ -88,6 +104,11 @@
|
||||
"ref": "6409f3c6d1b4c52176813d3ede86c0d34e8af2c1",
|
||||
"url": "https://github.com/FunkinCrew/grig.audio"
|
||||
},
|
||||
{
|
||||
"name": "tink_core",
|
||||
"type": "haxelib",
|
||||
"version": "1.26.0"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest",
|
||||
"type": "haxelib",
|
||||
@@ -97,7 +118,7 @@
|
||||
"name": "haxeui-core",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "088b153b35985f8e4419ef710057ebd5b3749513",
|
||||
"ref": "998534fb830450ca1e60c47a9524af5730431145",
|
||||
"url": "https://github.com/FunkinCrew/haxeui-core"
|
||||
},
|
||||
{
|
||||
@@ -107,18 +128,10 @@
|
||||
"ref": "100f2c96beab619cfe72c567a058c41c71e3e998",
|
||||
"url": "https://github.com/haxeui/haxeui-flixel"
|
||||
},
|
||||
{
|
||||
"name": "hscript",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "dcc6f822e0866ca4fda300ed23e99559260f7bf5",
|
||||
"url": "https://github.com/FunkinCrew/hscript"
|
||||
},
|
||||
{
|
||||
"name": "hxcpp",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "5932340d095a7eea8635fe4d1355f1c0efd0b3c2",
|
||||
"ref": "0376e9b19af9a4d91f9d9afc131a358467856a10",
|
||||
"url": "https://github.com/FunkinCrew/hxcpp"
|
||||
},
|
||||
{
|
||||
@@ -153,13 +166,13 @@
|
||||
{
|
||||
"name": "hxvlc",
|
||||
"type": "haxelib",
|
||||
"version": "2.2.5"
|
||||
"version": "2.3.0"
|
||||
},
|
||||
{
|
||||
"name": "json2object",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "a7e4cef3d444bea8d8244d6e59ab82f5a593f597",
|
||||
"ref": "dc945d58c1239a6ab6e37e0a6c128387193c9af5",
|
||||
"url": "https://github.com/FunkinCrew/json2object"
|
||||
},
|
||||
{
|
||||
@@ -175,30 +188,28 @@
|
||||
{
|
||||
"name": "lime",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "318253ea3a28a3299a167748912c40444f403777",
|
||||
"ref": "268dacfb2609766e14bef9ea5b669e91501852d2",
|
||||
"url": "https://github.com/FunkinCrew/lime"
|
||||
},
|
||||
{
|
||||
"name": "newgrounds",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "b2b53cd0a5f030af74efd325732951cddbea8826",
|
||||
"ref": "60162762e6ca65da011ffee7a6617f547ea5dff9",
|
||||
"url": "https://github.com/FunkinCrew/Newgrounds"
|
||||
},
|
||||
{
|
||||
"name": "openfl",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "a69a6e778816c6a57eba7a91bfb0b60295508e88",
|
||||
"ref": "74a51908a116d6df74be1083e219abb9fa057636",
|
||||
"url": "https://github.com/FunkinCrew/openfl"
|
||||
},
|
||||
{
|
||||
"name": "polymod",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "9824bf4f00863c152d5afe3ac4bbcac173d80684",
|
||||
"url": "https://github.com/larsiusprime/polymod"
|
||||
"ref": "acfdc2e26722f20339a2bc0cc8cd7dd5fe0c6b5e",
|
||||
"url": "https://github.com/FunkinCrew/polymod"
|
||||
},
|
||||
{
|
||||
"name": "thx.core",
|
||||
|
||||
+535
-6
@@ -1,30 +1,559 @@
|
||||
{
|
||||
"disableFormatting": false,
|
||||
|
||||
"emptyLines": {
|
||||
"finalNewline": true,
|
||||
|
||||
"maxAnywhereInFile": 1,
|
||||
|
||||
"beforePackage": 0,
|
||||
"afterPackage": 1,
|
||||
|
||||
"importAndUsing": {
|
||||
"betweenImports": 0,
|
||||
"betweenImportsLevel": "firstLevelPackage",
|
||||
"beforeUsing": 1,
|
||||
"beforeType": 1
|
||||
},
|
||||
|
||||
"betweenTypes": 1,
|
||||
|
||||
"lineCommentsBetweenTypes": "one",
|
||||
"lineCommentsBetweenFunctions": "one",
|
||||
|
||||
"betweenSingleLineTypes": 0,
|
||||
|
||||
"beforeRightCurly": "remove",
|
||||
"afterLeftCurly": "remove",
|
||||
"afterReturn": "remove",
|
||||
|
||||
"beforeBlocks": "remove",
|
||||
"afterBlocks": "remove",
|
||||
|
||||
"enumAbstractEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenVars": 0,
|
||||
"afterVars": 1,
|
||||
"betweenFunctions": 1,
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"classEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenStaticVars": 0,
|
||||
"afterStaticVars": 1,
|
||||
"afterPrivateVars": 1,
|
||||
"betweenVars": 0,
|
||||
"afterVars": 1,
|
||||
"afterStaticFunctions": 1,
|
||||
"betweenStaticFunctions": 1,
|
||||
"afterPrivateFunctions": 1,
|
||||
"betweenFunctions": 1,
|
||||
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"macroClassEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenStaticVars": 0,
|
||||
"afterStaticVars": 1,
|
||||
"afterPrivateVars": 1,
|
||||
"betweenVars": 0,
|
||||
"afterVars": 1,
|
||||
"afterStaticFunctions": 1,
|
||||
"betweenStaticFunctions": 1,
|
||||
"afterPrivateFunctions": 1,
|
||||
"betweenFunctions": 1,
|
||||
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"externClassEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenVars": 0,
|
||||
"afterVars": 0,
|
||||
"betweenFunctions": 0,
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"abstractEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenStaticVars": 0,
|
||||
"afterStaticVars": 1,
|
||||
"afterPrivateVars": 1,
|
||||
"betweenVars": 0,
|
||||
"afterVars": 1,
|
||||
"afterStaticFunctions": 1,
|
||||
"betweenStaticFunctions": 1,
|
||||
"afterPrivateFunctions": 1,
|
||||
"betweenFunctions": 1,
|
||||
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"interfaceEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenVars": 0,
|
||||
"afterVars": 0,
|
||||
"betweenFunctions": 0,
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"enumEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenFields": 0,
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"typedefEmptyLines": {
|
||||
"beginType": 0,
|
||||
"endType": 0,
|
||||
|
||||
"betweenFields": 0,
|
||||
"existingBetweenFields": "remove"
|
||||
},
|
||||
|
||||
"conditionalsEmptyLines": {
|
||||
"afterIf": 0,
|
||||
"beforeElse": 0,
|
||||
"afterElse": 0,
|
||||
"beforeEnd": 0,
|
||||
"beforeError": 0,
|
||||
"afterError": 0
|
||||
},
|
||||
|
||||
"beforeDocCommentEmptyLines": "one",
|
||||
"afterFieldsWithDocComments": "one",
|
||||
|
||||
"afterFileHeaderComment": 1,
|
||||
"betweenMultilineComments": 0
|
||||
},
|
||||
|
||||
"indentation": {
|
||||
"conditionalPolicy": "aligned",
|
||||
|
||||
"character": " ",
|
||||
"tabWidth": 2,
|
||||
|
||||
"trailingWhitespace": false,
|
||||
|
||||
"indentObjectLiteral": true,
|
||||
"indentComplexValueExpressions": false,
|
||||
"indentCaseLabels": true
|
||||
},
|
||||
|
||||
"lineEnds": {
|
||||
"lineEndCharacter": "auto",
|
||||
|
||||
"metadataType": "after",
|
||||
"metadataVar": "forceAfterLast",
|
||||
"metadataFunction": "forceAfterLast",
|
||||
"metadataOther": "none",
|
||||
|
||||
"caseColon": "after",
|
||||
"sharp": "after",
|
||||
|
||||
"leftCurly": "both",
|
||||
"rightCurly": "both",
|
||||
"emptyCurly": "noBreak",
|
||||
|
||||
"blockCurly": {
|
||||
"emptyCurly": "break",
|
||||
"leftCurly": "both",
|
||||
"rightCurly": "both"
|
||||
},
|
||||
|
||||
"anonFunctionCurly": {
|
||||
"emptyCurly": "break",
|
||||
"leftCurly": "both",
|
||||
"rightCurly": "both"
|
||||
},
|
||||
|
||||
"anonTypeCurly": {
|
||||
"emptyCurly": "break",
|
||||
"leftCurly": "both",
|
||||
"rightCurly": "both"
|
||||
},
|
||||
|
||||
"objectLiteralCurly": {
|
||||
"emptyCurly": "break",
|
||||
"leftCurly": "after",
|
||||
"rightCurly": "both"
|
||||
},
|
||||
"leftCurly": "both",
|
||||
"rightCurly": "both"
|
||||
|
||||
"typedefCurly": {
|
||||
"emptyCurly": "break",
|
||||
"leftCurly": "both",
|
||||
"rightCurly": "both"
|
||||
}
|
||||
},
|
||||
|
||||
"sameLine": {
|
||||
"ifBody": "same",
|
||||
"elseBody": "next",
|
||||
|
||||
"ifElse": "next",
|
||||
"doWhile": "next",
|
||||
|
||||
"elseIf": "same",
|
||||
"ifElseSemicolonNextLine": true,
|
||||
|
||||
"expressionIf": "same",
|
||||
"expressionIfWithBlocks": false,
|
||||
|
||||
"forBody": "same",
|
||||
|
||||
"comprehensionFor": "same",
|
||||
|
||||
"whileBody": "next",
|
||||
"doWhileBody": "next",
|
||||
|
||||
"doWhile": "same",
|
||||
|
||||
"tryBody": "next",
|
||||
"tryCatch": "next"
|
||||
"catchBody": "next",
|
||||
|
||||
"tryCatch": "next",
|
||||
|
||||
"caseBody": "next",
|
||||
"expressionCase": "next",
|
||||
"expressionTry": "same",
|
||||
|
||||
"functionBody": "same",
|
||||
"anonFunctionBody": "same",
|
||||
"returnBody": "same",
|
||||
"returnBodySingleLine": "same",
|
||||
|
||||
"untypedBody": "same"
|
||||
},
|
||||
|
||||
"whitespace": {
|
||||
"switchPolicy": "around"
|
||||
}
|
||||
"parenConfig": {
|
||||
"metadataParens": {
|
||||
"openingPolicy": "none",
|
||||
"closingPolicy": "none",
|
||||
"removeInnerWhenEmpty": true
|
||||
}
|
||||
},
|
||||
|
||||
"bracesConfig": {},
|
||||
|
||||
"bracketConfig": {
|
||||
"arrayLiteralBrackets": {
|
||||
"openingPolicy": "noneAfter",
|
||||
"closingPolicy": "none",
|
||||
"removeInnerWhenEmpty": true
|
||||
},
|
||||
"mapLiteralBrackets": {
|
||||
"openingPolicy": "noneAfter",
|
||||
"closingPolicy": "none",
|
||||
"removeInnerWhenEmpty": true
|
||||
},
|
||||
|
||||
"accessBrackets": {
|
||||
"openingPolicy": "noneAfter",
|
||||
"closingPolicy": "none",
|
||||
"removeInnerWhenEmpty": true
|
||||
},
|
||||
"comprehensionBrackets": {
|
||||
"openingPolicy": "none",
|
||||
"closingPolicy": "none",
|
||||
"removeInnerWhenEmpty": true
|
||||
},
|
||||
|
||||
"unknownBrackets": {
|
||||
"openingPolicy": "noneAfter",
|
||||
"closingPolicy": "none",
|
||||
"removeInnerWhenEmpty": true
|
||||
}
|
||||
},
|
||||
|
||||
"typeParamOpenPolicy": "none",
|
||||
"typeParamClosePolicy": "none",
|
||||
|
||||
"typeExtensionPolicy": "after",
|
||||
|
||||
"commaPolicy": "onlyAfter",
|
||||
"dotPolicy": "none",
|
||||
"colonPolicy": "none",
|
||||
"caseColonPolicy": "onlyAfter",
|
||||
"objectFieldColonPolicy": "after",
|
||||
"typeHintColonPolicy": "none",
|
||||
"typeCheckColonPolicy": "around",
|
||||
"ternaryPolicy": "around",
|
||||
"semicolonPolicy": "onlyAfter",
|
||||
"ifPolicy": "after",
|
||||
"doPolicy": "after",
|
||||
"whilePolicy": "after",
|
||||
"forPolicy": "after",
|
||||
"switchPolicy": "around",
|
||||
"tryPolicy": "after",
|
||||
"catchPolicy": "after",
|
||||
"binopPolicy": "around",
|
||||
"intervalPolicy": "none",
|
||||
"arrowFunctionsPolicy": "around",
|
||||
"functionTypeHaxe3Policy": "none",
|
||||
"functionTypeHaxe4Policy": "around",
|
||||
|
||||
"compressSuccessiveParenthesis": true,
|
||||
"formatStringInterpolation": true,
|
||||
"addLineCommentSpace": true
|
||||
},
|
||||
|
||||
"wrapping": {
|
||||
"maxLineLength": 160,
|
||||
|
||||
"arrayMatrixWrap": "matrixWrapWithAlign",
|
||||
|
||||
"arrayWrap": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0,
|
||||
"rules": [
|
||||
{
|
||||
"type": "noWrap",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "itemCount <= n",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"cond": "totalItemLength <= n",
|
||||
"value": 160
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "anyItemLength >= n",
|
||||
"value": 32
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "itemCount >= n",
|
||||
"value": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "hasMultilineItems",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "totalItemLength >= n",
|
||||
"value": 160
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"mapWrap": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0,
|
||||
"rules": [
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "anyItemLength >= n",
|
||||
"value": 32
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "itemCount >= n",
|
||||
"value": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "hasMultilineItems",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "lineLength >= n",
|
||||
"value": 160
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"methodChain": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0,
|
||||
"rules": [
|
||||
{
|
||||
"additionalIndent": 0,
|
||||
"location": "afterLast",
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "lineLength >= n",
|
||||
"value": 160
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"callParameter": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0,
|
||||
"rules": [
|
||||
{
|
||||
"additionalIndent": 0,
|
||||
"location": "afterLast",
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "lineLength >= n",
|
||||
"value": 160
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"objectLiteral": {
|
||||
"defaultWrap": "onePerLine",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"opBoolChain": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "beforeLast",
|
||||
"defaultAdditionalIndent": 0,
|
||||
"rules": [
|
||||
{
|
||||
"additionalIndent": 0,
|
||||
"location": "beforeLast",
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "lineLength >= n",
|
||||
"value": 160
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"opAddSubChain": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "beforeLast",
|
||||
"defaultAdditionalIndent": 0,
|
||||
"rules": [
|
||||
{
|
||||
"additionalIndent": 0,
|
||||
"location": "beforeLast",
|
||||
"type": "onePerLine",
|
||||
"conditions": [
|
||||
{
|
||||
"cond": "lineLength >= n",
|
||||
"value": 160
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"implementsExtends": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"metadataCallParameter": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"anonFunctionSignature": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"anonType": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"casePattern": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"functionSignature": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"multiVar": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
},
|
||||
|
||||
"typeParameter": {
|
||||
"defaultWrap": "noWrap",
|
||||
"defaultLocation": "afterLast",
|
||||
"defaultAdditionalIndent": 0
|
||||
}
|
||||
},
|
||||
|
||||
"excludes": [
|
||||
"_Provide a list of regular expressions to exclude from formatting.",
|
||||
".haxelib",
|
||||
".git",
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
||||
+157
-200
@@ -32,13 +32,13 @@ class Project extends HXProject
|
||||
* REMEMBER TO CHANGE THIS WHEN THE GAME UPDATES!
|
||||
* You only have to change it here, the rest of the game will query this value.
|
||||
*/
|
||||
static final VERSION:String = "0.8.1";
|
||||
static final VERSION:String = "0.8.7";
|
||||
|
||||
/**
|
||||
* The build's number and version code.
|
||||
* Used when publishing the game to mobile app stores. Should increment with each patch.
|
||||
*/
|
||||
static final BUILD_NUMBER:Int = 70;
|
||||
static final BUILD_NUMBER:Int = 102;
|
||||
|
||||
/**
|
||||
* The game's name. Used as the default window title.
|
||||
@@ -105,15 +105,8 @@ class Project extends HXProject
|
||||
//
|
||||
|
||||
/**
|
||||
* The app's minimal Android SDK version.
|
||||
* The app's lime Android java extensions.
|
||||
*/
|
||||
static final ANDROID_MINIMUM_SDK_VERSION:Int = 28;
|
||||
|
||||
/**
|
||||
* The app's target Android SDK version.
|
||||
*/
|
||||
static final ANDROID_TARGET_SDK_VERSION:Int = 35;
|
||||
|
||||
static final ANDROID_EXTENSIONS:Array<String> = [
|
||||
"funkin.extensions.CallbackUtil",
|
||||
"funkin.extensions.FNFCExtension",
|
||||
@@ -171,11 +164,7 @@ class Project extends HXProject
|
||||
/**
|
||||
* Asset path globs to exclude on platforms with `CENSOR_EXPLETIVES` disabled.
|
||||
*/
|
||||
static final EXCLUDE_ASSETS_UNCENSORED:Array<String> = [
|
||||
"stressCutscene-censored.mp4",
|
||||
"stressPicoCutscene-censored.mp4",
|
||||
"darnellCutscene-censored.mp4"
|
||||
];
|
||||
static final EXCLUDE_ASSETS_UNCENSORED:Array<String> = ["stressCutscene-censored.mp4", "stressPicoCutscene-censored.mp4", "darnellCutscene-censored.mp4"];
|
||||
|
||||
//
|
||||
// ASSET EMBEDDING
|
||||
@@ -184,9 +173,7 @@ class Project extends HXProject
|
||||
/**
|
||||
* The songs whose audio files should be embedded inside the executable.
|
||||
*/
|
||||
static final EMBED_SONGS_AUDIO:Array<String> = [
|
||||
"spaghetti"
|
||||
];
|
||||
static final EMBED_SONGS_AUDIO:Array<String> = ["spaghetti"];
|
||||
|
||||
//
|
||||
// BUILD FLAGS
|
||||
@@ -216,6 +203,13 @@ class Project extends HXProject
|
||||
*/
|
||||
static final EXCLUDE_ARMV7:FeatureFlag = "EXCLUDE_ARMV7";
|
||||
|
||||
/**
|
||||
* `-DFORCE_BLEND_SHADER`
|
||||
* If this flag is enabled, the game will force the use of shaders to render
|
||||
* certain blend modes, even if the device supports the needed OpenGL extensions.
|
||||
*/
|
||||
static final FORCE_BLEND_SHADER:FeatureFlag = "FORCE_BLEND_SHADER";
|
||||
|
||||
/**
|
||||
* `-DGITHUB_BUILD`
|
||||
* If this flag is enabled, the game will use the configuration used by GitHub Actions
|
||||
@@ -387,10 +381,16 @@ class Project extends HXProject
|
||||
|
||||
/**
|
||||
* `-DFEATURE_MOBILE_WEBVIEW`
|
||||
* If this feature flag is enabled, the user may sometimes be prompted to review the app on their respective store.
|
||||
* If this feature flag is enabled, the game will be able to load WebViews, mainly needed for the Newgrounds impl.
|
||||
*/
|
||||
static final FEATURE_MOBILE_WEBVIEW:FeatureFlag = "FEATURE_MOBILE_WEBVIEW";
|
||||
|
||||
/**
|
||||
* `-DFEATURE_MOBILE_AGESIGNALS`
|
||||
* If this feature flag is enabled, the game will be able to use age singals.
|
||||
*/
|
||||
static final FEATURE_MOBILE_AGESIGNALS:FeatureFlag = "FEATURE_MOBILE_AGESIGNALS";
|
||||
|
||||
/**
|
||||
* `-DFEATURE_NAUGHTYNESS`
|
||||
* If this feature flag is enabled, naughtyness will be a toggleable option in the Options Menu.
|
||||
@@ -534,19 +534,34 @@ class Project extends HXProject
|
||||
{
|
||||
super();
|
||||
|
||||
#if !target.unicode
|
||||
if (isWindowsHost())
|
||||
{
|
||||
// Enable code page 65001 for unicode support
|
||||
Sys.command("chcp 65001 > nul");
|
||||
}
|
||||
#end
|
||||
|
||||
envConfig = readEnvironmentFile("./.env");
|
||||
|
||||
flair();
|
||||
|
||||
displayTarget();
|
||||
|
||||
configureApp();
|
||||
|
||||
displayTarget();
|
||||
configureOutputDir();
|
||||
|
||||
if (isRun() || isInstall())
|
||||
{
|
||||
// These commands dont really need much in order to run so to improve the speed, we return here.
|
||||
return;
|
||||
}
|
||||
|
||||
configureFeatureFlags();
|
||||
configureCompileDefines();
|
||||
configureIncludeMacros();
|
||||
configureCustomMacros();
|
||||
configureOutputDir();
|
||||
configurePolymod();
|
||||
configureHaxelibs();
|
||||
configureASTCTextures();
|
||||
@@ -577,7 +592,7 @@ class Project extends HXProject
|
||||
buildHxCppTools();
|
||||
}
|
||||
|
||||
if (!isDisplay())
|
||||
if (!(isDisplay() || isCleanCommand()))
|
||||
{
|
||||
checkLibraries();
|
||||
}
|
||||
@@ -606,11 +621,6 @@ class Project extends HXProject
|
||||
{
|
||||
this.meta.title = isMobile() ? TITLE_MOBILE : TITLE;
|
||||
|
||||
// ios uses this character code instead of spaces...
|
||||
// We don't have spaces in our title for mobile anymore
|
||||
// But keeping incase anybody source-modding ever does add spaces
|
||||
if (isIOS()) this.meta.title = ~/ /ig.replace(TITLE_MOBILE, "\u2002");
|
||||
|
||||
this.meta.version = VERSION;
|
||||
this.meta.packageName = PACKAGE_NAME;
|
||||
this.meta.company = COMPANY;
|
||||
@@ -636,17 +646,6 @@ class Project extends HXProject
|
||||
// Set the build number, required for publishing the game to mobile stores.
|
||||
this.meta.buildNumber = Std.string(BUILD_NUMBER);
|
||||
|
||||
// These values are only used by the SWF target I think.
|
||||
// this.app.path
|
||||
// this.app.init
|
||||
// this.app.swfVersion
|
||||
// this.app.url
|
||||
|
||||
// These values are only used by... FIREFOX MARKETPLACE WHAT?
|
||||
// this.meta.description = "";
|
||||
// this.meta.companyId = COMPANY;
|
||||
// this.meta.companyUrl = COMPANY;
|
||||
|
||||
// Configure the window.
|
||||
// Automatically configure FPS.
|
||||
this.window.fps = 60;
|
||||
@@ -659,7 +658,7 @@ class Project extends HXProject
|
||||
this.window.hardware = true;
|
||||
this.window.vsync = false;
|
||||
// force / allow high DPI
|
||||
this.window.allowHighDPI = true;
|
||||
this.window.allowHighDPI = !isMac();
|
||||
|
||||
if (isWeb())
|
||||
{
|
||||
@@ -691,8 +690,28 @@ class Project extends HXProject
|
||||
this.excludeArchitectures.push(Architecture.ARMV7);
|
||||
}
|
||||
|
||||
config.set("android.minimum-sdk-version", ANDROID_MINIMUM_SDK_VERSION);
|
||||
config.set("android.target-sdk-version", ANDROID_TARGET_SDK_VERSION);
|
||||
if (isRelease())
|
||||
{
|
||||
if (envConfig != null)
|
||||
{
|
||||
keystore = new Keystore();
|
||||
keystore.path = Std.string(envConfig.get('KEYSTORE_PATH'));
|
||||
keystore.alias = Std.string(envConfig.get('KEYSTORE_ALIAS'));
|
||||
keystore.password = Std.string(envConfig.get('KEYSTORE_PASSWORD'));
|
||||
}
|
||||
|
||||
if (isBundle())
|
||||
{
|
||||
config.set("android.gradle-project-directory", "bin-bundle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isIOS())
|
||||
{
|
||||
config.set("ios.non-exempt-encryption", "false");
|
||||
config.set("ios.team-id", IOS_TEAM_ID);
|
||||
config.set("ios.deployment", "16.0");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,7 +745,6 @@ class Project extends HXProject
|
||||
// case Platform.PS3:
|
||||
// case Platform.PS4:
|
||||
// case Platform.TIZEN:
|
||||
// case Platform.TVOS:
|
||||
// case Platform.VITA:
|
||||
// case Platform.WEBOS:
|
||||
// case Platform.WIIU:
|
||||
@@ -738,42 +756,22 @@ class Project extends HXProject
|
||||
switch (this.platformType)
|
||||
{
|
||||
case PlatformType.DESKTOP:
|
||||
info('Platform Type: Desktop');
|
||||
info('Target Platform Type: Desktop');
|
||||
case PlatformType.MOBILE:
|
||||
info('Platform Type: Mobile');
|
||||
info('Target Platform Type: Mobile');
|
||||
case PlatformType.WEB:
|
||||
info('Platform Type: Web');
|
||||
info('Target Platform Type: Web');
|
||||
case PlatformType.CONSOLE:
|
||||
info('Platform Type: Console');
|
||||
info('Target Platform Type: Console');
|
||||
default:
|
||||
error('Unknown platform type (got ${platformType})');
|
||||
}
|
||||
|
||||
// Print whether we are using HXCPP, HashLink, or something else.
|
||||
// Print whether we are using HXCPP, JavaScript, or something else.
|
||||
if (isWeb())
|
||||
{
|
||||
info('Target Language: JavaScript (HTML5)');
|
||||
}
|
||||
else if (isHashLink())
|
||||
{
|
||||
info('Target Language: HashLink');
|
||||
}
|
||||
else if (isNeko())
|
||||
{
|
||||
info('Target Language: Neko');
|
||||
}
|
||||
else if (isJava())
|
||||
{
|
||||
info('Target Language: Java');
|
||||
}
|
||||
else if (isNodeJS())
|
||||
{
|
||||
info('Target Language: JavaScript (NodeJS)');
|
||||
}
|
||||
else if (isCSharp())
|
||||
{
|
||||
info('Target Language: C#');
|
||||
}
|
||||
else if (isCPP())
|
||||
{
|
||||
info('Target Language: C++');
|
||||
@@ -789,23 +787,13 @@ class Project extends HXProject
|
||||
switch (arch)
|
||||
{
|
||||
case Architecture.X86:
|
||||
info('Architecture: x86');
|
||||
info('Target Architecture: x86');
|
||||
case Architecture.X64:
|
||||
info('Architecture: x64');
|
||||
case Architecture.ARMV5:
|
||||
info('Architecture: ARMv5');
|
||||
case Architecture.ARMV6:
|
||||
info('Architecture: ARMv6');
|
||||
info('Target Architecture: x64');
|
||||
case Architecture.ARMV7:
|
||||
info('Architecture: ARMv7');
|
||||
case Architecture.ARMV7S:
|
||||
info('Architecture: ARMv7S');
|
||||
info('Target Architecture: ARMv7');
|
||||
case Architecture.ARM64:
|
||||
info('Architecture: ARMx64');
|
||||
case Architecture.MIPS:
|
||||
info('Architecture: MIPS');
|
||||
case Architecture.MIPSEL:
|
||||
info('Architecture: MIPSEL');
|
||||
info('Target Architecture: ARM64');
|
||||
case null:
|
||||
if (!isWeb())
|
||||
{
|
||||
@@ -813,7 +801,7 @@ class Project extends HXProject
|
||||
}
|
||||
else
|
||||
{
|
||||
info('Architecture: Web');
|
||||
info('Target Architecture: Web');
|
||||
}
|
||||
default:
|
||||
error('Unsupported architecture (got ${arch})');
|
||||
@@ -855,14 +843,15 @@ class Project extends HXProject
|
||||
// Should be true on mobile builds.
|
||||
CENSOR_EXPLETIVES.apply(this, isMobile());
|
||||
|
||||
// Should be true on Android.
|
||||
// Some Android devices support native blends, but it causes issues
|
||||
// with other shaders, so we'll disable it for now.
|
||||
FORCE_BLEND_SHADER.apply(this, isAndroid());
|
||||
|
||||
//
|
||||
// FEATURE FLAGS
|
||||
//
|
||||
|
||||
// Should be true on debug builds or if GITHUB_BUILD is enabled.
|
||||
FEATURE_DEBUG_FUNCTIONS.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
|
||||
FEATURE_RESULTS_DEBUG.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this));
|
||||
|
||||
FEATURE_FUNKVIS.apply(this, true);
|
||||
FEATURE_LOG_TRACE.apply(this, true);
|
||||
FEATURE_DEBUG_FILE_LOGGING.apply(this, FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
|
||||
@@ -872,8 +861,7 @@ class Project extends HXProject
|
||||
FEATURE_POLYMOD_MODS.apply(this, true);
|
||||
|
||||
// Video playback should be enabled on desktop, web, and mobile.
|
||||
// HXCPP has trouble with iOS simulator builds though...
|
||||
FEATURE_VIDEO_PLAYBACK.apply(this, !(isIOSSimulator() || isHashLink()));
|
||||
FEATURE_VIDEO_PLAYBACK.apply(this, true);
|
||||
|
||||
// Video subtitles only work via using hxvlc.
|
||||
FEATURE_VIDEO_SUBTITLES.apply(this, FEATURE_VIDEO_PLAYBACK.isEnabled(this) && !isWeb());
|
||||
@@ -908,13 +896,13 @@ class Project extends HXProject
|
||||
// Should be true except on web builds (some asset stuff breaks it)
|
||||
FEATURE_LAG_ADJUSTMENT.apply(this, !isWeb());
|
||||
|
||||
// Should be true except on web and mobile builds.
|
||||
// Screenshots doesn't work there, and mobile has its own screenshots anyway.
|
||||
FEATURE_SCREENSHOTS.apply(this, !(isWeb() || isMobile()));
|
||||
// Should be true only on Desktop builds.
|
||||
// Mobile has its own screenshot methods.
|
||||
// Web has it disabled due to performance cost of `preserveDrawingBuffer`.
|
||||
FEATURE_SCREENSHOTS.apply(this, isDesktop());
|
||||
|
||||
// Should be true except on MacOS and mobile builds.
|
||||
// Dragging and dropping files onto the window doesn't work there.
|
||||
FEATURE_FILE_DROP.apply(this, !(isMac() || isMobile()));
|
||||
// Should be true except on mobile builds.
|
||||
FEATURE_FILE_DROP.apply(this, !isMobile());
|
||||
|
||||
// Audio context issues only exist on web builds.
|
||||
FEATURE_TOUCH_HERE_TO_PLAY.apply(this, isWeb());
|
||||
@@ -924,10 +912,11 @@ class Project extends HXProject
|
||||
FEATURE_TOUCH_CONTROLS.apply(this, isMobile());
|
||||
|
||||
// Should be true only on mobile release builds. Remember you can add the flag manually for testing.
|
||||
FEATURE_MOBILE_ADVERTISEMENTS.apply(this, (isMobile() && isRelease() && !isIOSSimulator()) && envConfig != null);
|
||||
FEATURE_MOBILE_IAP.apply(this, (isMobile() && isRelease() && !isIOSSimulator()) && envConfig != null);
|
||||
FEATURE_MOBILE_IAR.apply(this, isMobile() && isRelease() && !isIOSSimulator());
|
||||
FEATURE_MOBILE_ADVERTISEMENTS.apply(this, (isMobile() && isRelease()) && envConfig != null);
|
||||
FEATURE_MOBILE_IAP.apply(this, (isMobile() && isRelease()) && envConfig != null);
|
||||
FEATURE_MOBILE_IAR.apply(this, isMobile() && isRelease());
|
||||
FEATURE_MOBILE_WEBVIEW.apply(this, isMobile() && FEATURE_NEWGROUNDS.isEnabled(this));
|
||||
FEATURE_MOBILE_AGESIGNALS.apply(this, isMobile() && isRelease());
|
||||
|
||||
// The coveted ghost tapping feature.
|
||||
// Essential on mobile but delayed on desktop.
|
||||
@@ -958,16 +947,6 @@ class Project extends HXProject
|
||||
var unicodeCheck:String = "✓ ";
|
||||
var unicodeCross:String = "× ";
|
||||
|
||||
if (isWindowsHost())
|
||||
{
|
||||
#if (!target.unicode)
|
||||
// lime build tools uses neko (unless compiling with `-eval`), and neko on windows doesn't support UTF8/unicode characters
|
||||
// so we need to remove our cute emoji!
|
||||
unicodeCheck = "o ";
|
||||
unicodeCross = "x ";
|
||||
#end
|
||||
}
|
||||
|
||||
for (flagStr in this.haxedefs.keys())
|
||||
{
|
||||
if (!flagStr.startsWith(FeatureFlag.INVERSE_PREFIX))
|
||||
@@ -1016,6 +995,9 @@ class Project extends HXProject
|
||||
*/
|
||||
function configureCompileDefines()
|
||||
{
|
||||
// Add Funkin's version as a compilation flag so Polymod scripts can use it.
|
||||
setHaxedef("funkin", VERSION);
|
||||
|
||||
// Enable OpenFL's error handler. Required for the crash logger.
|
||||
setHaxedef("openfl-enable-handle-error");
|
||||
|
||||
@@ -1029,8 +1011,6 @@ class Project extends HXProject
|
||||
setHaxedef("HXCPP_STACK_TRACE");
|
||||
setHaxedef("hscriptPos");
|
||||
|
||||
setHaxedef("safeMode");
|
||||
|
||||
if (FEATURE_DEBUG_FUNCTIONS.isDisabled(this))
|
||||
{
|
||||
setHaxedef("FLX_NO_DEBUG"); // If we aren't using the Flixel debugger, strip it out.
|
||||
@@ -1123,6 +1103,13 @@ class Project extends HXProject
|
||||
// Ensure all flixel-animate classes are available at runtime.
|
||||
addHaxeMacro("include('animate')");
|
||||
|
||||
// Ensure all openfl classes are available at runtime.
|
||||
addHaxeMacro("include('openfl')");
|
||||
|
||||
// Ensure all lime classes are available at runtime.
|
||||
// Explicitly ignore tools and internal packages.
|
||||
addHaxeMacro("include('lime', true, ['lime.tools.*', 'lime._internal.*'])");
|
||||
|
||||
// Ensure all Flixel classes are available at runtime.
|
||||
// Explicitly ignore packages which require additional dependencies.
|
||||
addHaxeMacro("include('flixel', true, [ 'flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*', 'flixel.addons.tile.FlxRayCastTilemap' ])");
|
||||
@@ -1133,8 +1120,9 @@ class Project extends HXProject
|
||||
*/
|
||||
function configureCustomMacros()
|
||||
{
|
||||
// This macro allows addition of new functionality to existing Flixel. -->
|
||||
// These macros allow additions of new functionality to existing Flixel. -->
|
||||
addHaxeMacro("addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic')");
|
||||
addHaxeMacro("addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxSprite())', 'flixel.FlxSprite')");
|
||||
}
|
||||
|
||||
function configureOutputDir()
|
||||
@@ -1158,22 +1146,6 @@ class Project extends HXProject
|
||||
{
|
||||
javaPaths.push(Path.join([SOURCE_DIR, 'funkin/external/android/java']));
|
||||
|
||||
if (isRelease())
|
||||
{
|
||||
if (envConfig != null)
|
||||
{
|
||||
keystore = new Keystore();
|
||||
keystore.path = Std.string(envConfig.get('KEYSTORE_PATH'));
|
||||
keystore.alias = Std.string(envConfig.get('KEYSTORE_ALIAS'));
|
||||
keystore.password = Std.string(envConfig.get('KEYSTORE_PASSWORD'));
|
||||
}
|
||||
|
||||
if (isBundle())
|
||||
{
|
||||
config.set("android.gradle-project-directory", "bin-bundle");
|
||||
}
|
||||
}
|
||||
|
||||
// Custom android.application XML Children for the AndroidManifest
|
||||
final modsFolderProvider:Xml = Xml.createElement('provider');
|
||||
modsFolderProvider.set('android:authorities', '$PACKAGE_NAME.docprovider');
|
||||
@@ -1218,21 +1190,12 @@ class Project extends HXProject
|
||||
intentFilter.addChild(category);
|
||||
}
|
||||
|
||||
final intentFilterDatas:Map<String, Array<String>> = [
|
||||
"android:mimeType" => ["application/zip"],
|
||||
// When this is added, it makes the game show up only when it's a FNFC file.
|
||||
final intentFilterDatas:Map<String,
|
||||
Array<String>> = ["android:mimeType" => ["application/zip"], // When this is added, it makes the game show up only when it's a FNFC file.
|
||||
// But it also for some reason make it not show up at all in ZArchiver no matter what the file is...
|
||||
// "android:host" => ["*"],
|
||||
"android:scheme" => ["file", "content"],
|
||||
// I think having all these makes it so the extension check would work even when the files has dots like "epic-song-v2.0.fnfc"
|
||||
"android:pathPattern" => [
|
||||
".*\\.fnfc",
|
||||
".*\\..*\\.fnfc",
|
||||
".*\\..*\\..*\\.fnfc",
|
||||
".*\\..*\\..*\\..*\\.fnfc",
|
||||
".*\\..*\\..*\\..*\\..*\\.fnfc"
|
||||
]
|
||||
];
|
||||
"android:scheme" => ["file", "content"], // I think having all these makes it so the extension check would work even when the files has dots like "epic-song-v2.0.fnfc"
|
||||
"android:pathPattern" => [".*\\.fnfc", ".*\\..*\\.fnfc", ".*\\..*\\..*\\.fnfc", ".*\\..*\\..*\\..*\\.fnfc", ".*\\..*\\..*\\..*\\..*\\.fnfc"]];
|
||||
|
||||
for (key => values in intentFilterDatas)
|
||||
{
|
||||
@@ -1269,10 +1232,6 @@ class Project extends HXProject
|
||||
|
||||
function configureIOS()
|
||||
{
|
||||
config.set("ios.non-exempt-encryption", "false");
|
||||
config.set("ios.team-id", IOS_TEAM_ID);
|
||||
config.set("ios.deployment", "16.0");
|
||||
|
||||
// launchStoryboard = new LaunchStoryboard();
|
||||
// launchStoryboard.path = "./LaunchScreen.storyboard";
|
||||
|
||||
@@ -1325,7 +1284,6 @@ class Project extends HXProject
|
||||
addHaxelib('flixel'); // Game engine
|
||||
|
||||
addHaxelib('flixel-addons'); // Additional utilities for Flixel
|
||||
addHaxelib('hscript'); // Scripting
|
||||
|
||||
if (FEATURE_HAXEUI.isEnabled(this))
|
||||
{
|
||||
@@ -1342,15 +1300,13 @@ class Project extends HXProject
|
||||
addHaxelib('thx.core'); // General utility library, "the lodash of Haxe"
|
||||
addHaxelib('thx.semver'); // Version string handling
|
||||
|
||||
if (isDebug())
|
||||
if (isDebug() && isCPP())
|
||||
{
|
||||
addHaxelib('hxcpp-debug-server'); // VSCode debug support
|
||||
}
|
||||
|
||||
if (isDesktop() || isMobile() && !isHashLink() && FEATURE_VIDEO_PLAYBACK.isEnabled(this))
|
||||
if ((isDesktop() || isMobile()) && FEATURE_VIDEO_PLAYBACK.isEnabled(this))
|
||||
{
|
||||
// hxvlc doesn't function on HashLink or non-desktop platforms
|
||||
// It's also unnecessary if video playback is disabled
|
||||
addHaxelib('hxvlc'); // Video playback
|
||||
}
|
||||
|
||||
@@ -1409,12 +1365,20 @@ class Project extends HXProject
|
||||
{
|
||||
addHaxelib('extension-webviewcore'); // WebView Extension
|
||||
}
|
||||
|
||||
if (FEATURE_MOBILE_AGESIGNALS.isEnabled(this))
|
||||
{
|
||||
addHaxelib('extension-agesignals'); // WebView Extension
|
||||
}
|
||||
}
|
||||
|
||||
function configureAssets()
|
||||
{
|
||||
// Delete the assets folder from the export folder before adding anything.
|
||||
clearAssets();
|
||||
if (!(isDisplay() || isCleanCommand()))
|
||||
{
|
||||
// Delete the assets folder from the export folder before adding anything.
|
||||
clearAssets();
|
||||
}
|
||||
|
||||
var exclude = EXCLUDE_ASSETS.concat(isWeb() ? EXCLUDE_ASSETS_WEB : EXCLUDE_ASSETS_NATIVE);
|
||||
var shouldPreload = PRELOAD_ALL.isEnabled(this);
|
||||
@@ -1500,8 +1464,6 @@ class Project extends HXProject
|
||||
addAssetLibrary("sserafim", shouldEmbed, shouldPreload);
|
||||
addAssetPath("assets/sserafim", "assets/sserafim", "sserafim", ["*"], exclude, shouldEmbed, "assets");
|
||||
|
||||
|
||||
|
||||
// Art asset library (where README and CHANGELOG pull from)
|
||||
var shouldEmbedArt = false;
|
||||
var shouldPreloadArt = false;
|
||||
@@ -1528,7 +1490,7 @@ class Project extends HXProject
|
||||
var exportPath:Null<String> = app.path ?? "";
|
||||
|
||||
// mac target uses `macos` for the export folder instead of `mac`
|
||||
var platform:String = (!isMac() ? Std.string(this.target) : 'macos');
|
||||
var platform:String = !isMac() ? Std.string(this.target) : 'macos';
|
||||
var basePath:String = Path.join([exportPath, platform, "bin"]);
|
||||
var assetsPath:String = "";
|
||||
|
||||
@@ -1548,6 +1510,10 @@ class Project extends HXProject
|
||||
{
|
||||
assetsPath = Path.join([basePath, "app", "src", "main", "assets", "assets"]);
|
||||
}
|
||||
else if (isIOS())
|
||||
{
|
||||
assetsPath = Path.join([exportPath, platform, '${this.app.file}', "assets", "assets"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
@@ -1646,14 +1612,10 @@ class Project extends HXProject
|
||||
*/
|
||||
function configureASTCTextures()
|
||||
{
|
||||
if (!(isDisplay() || isClean()))
|
||||
if (!(isDisplay() && isCleanCommand()) && FEATURE_COMPRESSED_TEXTURES.isEnabled(this))
|
||||
{
|
||||
readASTCExclusion();
|
||||
|
||||
if (FEATURE_COMPRESSED_TEXTURES.isEnabled(this))
|
||||
{
|
||||
runASTCCompressor();
|
||||
}
|
||||
runASTCCompressor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1759,31 +1721,6 @@ class Project extends HXProject
|
||||
return this.target == Platform.IOS && this.targetFlags.exists("simulator");
|
||||
}
|
||||
|
||||
public function isHashLink():Bool
|
||||
{
|
||||
return this.targetFlags.exists("hl");
|
||||
}
|
||||
|
||||
public function isNeko():Bool
|
||||
{
|
||||
return this.targetFlags.exists("neko");
|
||||
}
|
||||
|
||||
public function isJava():Bool
|
||||
{
|
||||
return this.targetFlags.exists("java");
|
||||
}
|
||||
|
||||
public function isNodeJS():Bool
|
||||
{
|
||||
return this.targetFlags.exists("nodejs");
|
||||
}
|
||||
|
||||
public function isCSharp():Bool
|
||||
{
|
||||
return this.targetFlags.exists("cs");
|
||||
}
|
||||
|
||||
public function isCPP():Bool
|
||||
{
|
||||
return this.defines.exists("cpp");
|
||||
@@ -1794,11 +1731,26 @@ class Project extends HXProject
|
||||
return this.command == "display";
|
||||
}
|
||||
|
||||
public function isClean():Bool
|
||||
public function isCleanCommand():Bool
|
||||
{
|
||||
return this.command == "clean";
|
||||
}
|
||||
|
||||
public function isCleanFlag():Bool
|
||||
{
|
||||
return this.targetFlags.exists("clean");
|
||||
}
|
||||
|
||||
public function isRun():Bool
|
||||
{
|
||||
return this.command == "run";
|
||||
}
|
||||
|
||||
public function isInstall():Bool
|
||||
{
|
||||
return this.command == "install";
|
||||
}
|
||||
|
||||
public function isBuild():Bool
|
||||
{
|
||||
return this.command == "test" || this.command == "build";
|
||||
@@ -2092,7 +2044,7 @@ class Project extends HXProject
|
||||
@SuppressWarnings('checkstyle:Dynamic')
|
||||
function checkLibraries():Void
|
||||
{
|
||||
var diffrentLibraries:Map<String, Array<String>> = new Map<String, Array<String>>();
|
||||
var differentLibraries:Map<String, Array<String>> = new Map<String, Array<String>>();
|
||||
|
||||
var hmmData:Dynamic = haxe.Json.parse(sys.io.File.getContent(#if ios '../../../../../' + #end 'hmm.json'));
|
||||
|
||||
@@ -2113,11 +2065,11 @@ class Project extends HXProject
|
||||
switch (library.type)
|
||||
{
|
||||
case 'haxelib':
|
||||
diffrentLibraries.set(libraryName, [libraryDev, libraryCurrentCommitHash, library.version, 'haxelib']);
|
||||
differentLibraries.set(libraryName, [libraryDev, libraryCurrentCommitHash, library.version, 'haxelib']);
|
||||
case 'git':
|
||||
if (libraryCurrentCommitHash != library.ref)
|
||||
{
|
||||
diffrentLibraries.set(libraryName, [libraryDev, libraryCurrentCommitHash, library.ref, 'git']);
|
||||
differentLibraries.set(libraryName, [libraryDev, libraryCurrentCommitHash, library.ref, 'git']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2128,18 +2080,18 @@ class Project extends HXProject
|
||||
case 'haxelib':
|
||||
if (library.version != libraryCurrentVersion)
|
||||
{
|
||||
diffrentLibraries.set(libraryName, ['', libraryCurrentVersion, library.version, 'haxelib']);
|
||||
differentLibraries.set(libraryName, ['', libraryCurrentVersion, library.version, 'haxelib']);
|
||||
}
|
||||
case 'git':
|
||||
if (libraryCurrentCommitHash != library.ref)
|
||||
{
|
||||
diffrentLibraries.set(libraryName, ['', libraryCurrentCommitHash, library.ref, 'git']);
|
||||
differentLibraries.set(libraryName, ['', libraryCurrentCommitHash, library.ref, 'git']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Lambda.count(diffrentLibraries) > 0)
|
||||
if (Lambda.count(differentLibraries) > 0)
|
||||
{
|
||||
warn("Some libraries differ from the versions defined in hmm.json.".bold().yellow());
|
||||
warn("To ensure consistency, it's recommended to stop the build and run `hmm reinstall [library]`.".bold().yellow());
|
||||
@@ -2147,9 +2099,9 @@ class Project extends HXProject
|
||||
|
||||
Sys.println('');
|
||||
|
||||
for (libraryName in diffrentLibraries.keys())
|
||||
for (libraryName in differentLibraries.keys())
|
||||
{
|
||||
var infos:Null<Array<String>> = diffrentLibraries.get(libraryName);
|
||||
var infos:Null<Array<String>> = differentLibraries.get(libraryName);
|
||||
|
||||
if (infos == null) continue;
|
||||
|
||||
@@ -2160,9 +2112,8 @@ class Project extends HXProject
|
||||
|
||||
if (haxe.io.Path.isAbsolute(devPath))
|
||||
{
|
||||
Sys.println("- " + libraryName.replace(",", ".") + " (Development Build)".blue().bold());
|
||||
Sys.println((" Path: " + haxe.io.Path.removeTrailingSlashes(devPath)).blue());
|
||||
|
||||
Sys.println("- " + libraryName.replace(",", ".") + " (Development Build)".bright_cyan());
|
||||
Sys.println((" Path: " + haxe.io.Path.removeTrailingSlashes(devPath)).bright_blue());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2181,7 +2132,7 @@ class Project extends HXProject
|
||||
{
|
||||
var path = getLibraryCurrentFile(libraryName);
|
||||
|
||||
if (sys.FileSystem.exists(path)) return sys.io.File.getContent(path);
|
||||
if (sys.FileSystem.exists(path)) return sys.io.File.getContent(path).trim();
|
||||
|
||||
return '';
|
||||
}
|
||||
@@ -2190,7 +2141,7 @@ class Project extends HXProject
|
||||
{
|
||||
var path = getLibraryDevFile(libraryName);
|
||||
|
||||
if (sys.FileSystem.exists(path)) return sys.io.File.getContent(path);
|
||||
if (sys.FileSystem.exists(path)) return sys.io.File.getContent(path).trim();
|
||||
|
||||
return '';
|
||||
}
|
||||
@@ -2328,7 +2279,7 @@ class Project extends HXProject
|
||||
*/
|
||||
public function info(message:String):Void
|
||||
{
|
||||
if (!(isDisplay() || isClean()))
|
||||
if (!(isDisplay() || isCleanCommand() || isRun() || isInstall()))
|
||||
{
|
||||
Sys.println(' INFO '.bold().bg_blue() + " " + message);
|
||||
}
|
||||
@@ -2339,7 +2290,7 @@ class Project extends HXProject
|
||||
*/
|
||||
public function warn(message:String):Void
|
||||
{
|
||||
if (!(isDisplay() || isClean()))
|
||||
if (!(isDisplay() || isCleanCommand() || isRun() || isInstall()))
|
||||
{
|
||||
Sys.println(' WARNING '.bold().bg_yellow() + " " + message);
|
||||
}
|
||||
@@ -2485,8 +2436,14 @@ class Project extends HXProject
|
||||
info('Compressing ASTC textures...');
|
||||
|
||||
var args:Array<String> = ['run', 'astc-compressor', 'compress-from-json'];
|
||||
|
||||
args = args.concat(['-json', './astc-compression-data.json']);
|
||||
|
||||
if (isCleanFlag())
|
||||
{
|
||||
args = args.concat(['-clean']);
|
||||
}
|
||||
|
||||
Sys.command('haxelib', args);
|
||||
|
||||
info('Done compressing ASTC textures.');
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package scripts;
|
||||
|
||||
using DateTools;
|
||||
|
||||
class Postbuild
|
||||
{
|
||||
static function main()
|
||||
{
|
||||
/* trace('creating NG zip');
|
||||
var binFolder:String = 'export/release/html5/bin/';
|
||||
|
||||
var date = Date.now();
|
||||
var outputName:String = 'NG-' + date.format("%Y%m%d--%H%M") + '.zip';
|
||||
|
||||
var out = sys.io.File.write(outputName);
|
||||
var zip = new haxe.zip.Writer(out);
|
||||
zip.write(getEntries(binFolder));
|
||||
trace('Finished creating ZIP');
|
||||
*/
|
||||
}
|
||||
|
||||
static function getEntries(dir:String, entries:List<haxe.zip.Entry> = null, inDir:Null<String> = null)
|
||||
{
|
||||
if (entries == null) entries = new List<haxe.zip.Entry>();
|
||||
if (inDir == null) inDir = dir;
|
||||
|
||||
for (file in sys.FileSystem.readDirectory(dir))
|
||||
{
|
||||
var path = haxe.io.Path.join([dir, file]);
|
||||
if (sys.FileSystem.isDirectory(path)) getEntries(path, entries, inDir);
|
||||
else
|
||||
{
|
||||
var bytes:haxe.io.Bytes = haxe.io.Bytes.ofData(sys.io.File.getBytes(path).getData());
|
||||
var entry:haxe.zip.Entry = {
|
||||
fileName: StringTools.replace(path, inDir, ""),
|
||||
fileSize: bytes.length,
|
||||
fileTime: Date.now(),
|
||||
compressed: false,
|
||||
dataSize: sys.FileSystem.stat(path).size,
|
||||
data: bytes,
|
||||
crc32: haxe.crypto.Crc32.make(bytes)
|
||||
};
|
||||
entries.push(entry);
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
import haxe.Json;
|
||||
import haxe.Log;
|
||||
import haxe.macro.Compiler;
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
|
||||
using StringTools;
|
||||
|
||||
#if !interp
|
||||
package scripts;
|
||||
|
||||
// needs this thing to be run by interp, just for me lol!
|
||||
#end
|
||||
// general use of this!!
|
||||
// if run in INTERP MODE:
|
||||
// - scripts>haxe --main SongConverter --interp
|
||||
// - song to convert: ../assets/preload/data/
|
||||
// it will run through EVERY folder in there and convert the old songs to the new format!
|
||||
// TODO make instructions for the C# script version!
|
||||
class SongConverter
|
||||
{
|
||||
public static var VERSION:String = '0.1.0';
|
||||
|
||||
// TODO
|
||||
// Update engine shit, to accomodate single file
|
||||
|
||||
static function main()
|
||||
{
|
||||
// trace(Compiler.get);
|
||||
// trace(Compiler.getDefine('sysfsd'));
|
||||
|
||||
Sys.stdout().writeString('Please type directory you want to convert: ');
|
||||
Sys.stdout().flush();
|
||||
final input = Sys.stdin().readLine();
|
||||
trace('Hello ${input}!');
|
||||
|
||||
/* Sys.stdout().writeString('What type of conversion do you need?\n\t0: Old charts to new chart\n\t1: new chart to .... new chart? lol\n>');
|
||||
Sys.stdout().flush();
|
||||
final deleteShitIDK = Std.parseInt(Sys.stdin().readLine());
|
||||
|
||||
trace(deleteShitIDK); */
|
||||
|
||||
var songCount:Int = 0;
|
||||
|
||||
for (fileThing in FileSystem.readDirectory('${input}/.'))
|
||||
{
|
||||
// trace(fileThing);
|
||||
// trace(FileSystem.isDirectory(${input} + "/" + fileThing));
|
||||
|
||||
if (FileSystem.isDirectory(${input} + "/" + fileThing) && fileThing.toLowerCase() != 'smash')
|
||||
{
|
||||
trace('Formatting $fileThing');
|
||||
formatSongs(fileThing, input);
|
||||
|
||||
songCount++;
|
||||
}
|
||||
}
|
||||
|
||||
trace('CONVERTED $songCount SONGS!!');
|
||||
|
||||
var timer:Int = 5;
|
||||
|
||||
while (timer > 0)
|
||||
{
|
||||
Sys.stdout().writeString('CLOSING IN $timer SECONDS!');
|
||||
Sys.sleep(1);
|
||||
Sys.print("\r");
|
||||
timer -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static function formatSongs(songName:String, root:String)
|
||||
{
|
||||
var existsArray:Array<Bool> = [];
|
||||
|
||||
var songMap:Map<String, Dynamic> = new Map();
|
||||
var speedMap:Map<String, Dynamic> = new Map();
|
||||
|
||||
for (songFile in FileSystem.readDirectory('$root/$songName/'))
|
||||
{
|
||||
if (!songFile.endsWith('json') || !songFile.startsWith(songName)) continue; // ACCOMODATE FOR PICO SPEAKER EVENTUALLY!
|
||||
|
||||
var funnyFile:Dynamic = cast Json.parse(File.getContent('$root/$songName/$songFile'));
|
||||
|
||||
var songSplit:Array<String> = songFile.split('-');
|
||||
var songShit:String = 'normal';
|
||||
|
||||
if (songSplit.length > 1)
|
||||
{
|
||||
if (songSplit[1] == 'new.json')
|
||||
{
|
||||
FileSystem.deleteFile('$root/$songName/$songFile');
|
||||
trace('DELETEING $songFile');
|
||||
continue;
|
||||
}
|
||||
|
||||
songShit = songSplit[1].substr(0, songSplit[1].length - 5);
|
||||
}
|
||||
|
||||
if (songShit != 'normal')
|
||||
{
|
||||
songMap[songShit] = funnyFile.song.notes;
|
||||
speedMap[songShit] = funnyFile.song.speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
|
||||
if (funnyFile.song.notes is Array)
|
||||
{
|
||||
songMap[songShit] = funnyFile.song.notes[1];
|
||||
speedMap[songShit] = funnyFile.song.speed[1];
|
||||
}
|
||||
else if (Type.typeof(funnyFile.song.notes) == TObject)
|
||||
{
|
||||
var dipshitMap:Map<String, Dynamic> = cast funnyFile.song.notes;
|
||||
|
||||
// songMap[songShit] = dipshitMap.get('normal');
|
||||
}
|
||||
else
|
||||
{
|
||||
songMap[songShit] = funnyFile.song.notes;
|
||||
speedMap[songShit] = funnyFile.song.speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var fileNormal:Dynamic = cast Json.parse(File.getContent('$root/$songName/$songName.json'));
|
||||
|
||||
fileNormal.song.notes = songMap;
|
||||
fileNormal.song.speed = speedMap;
|
||||
|
||||
fileNormal.song.hasDialogueFile = false;
|
||||
fileNormal.song.stageDefault = getStage(songName);
|
||||
|
||||
fileNormal.version = 'FNF SongConverter $VERSION';
|
||||
|
||||
var daJson = Json.stringify(fileNormal, null, "\t");
|
||||
// trace(daJson);
|
||||
File.saveContent('$root/$songName/$songName.json', daJson);
|
||||
}
|
||||
|
||||
static function noteCleaner(notes:Array<Dynamic>):Array<Dynamic>
|
||||
{
|
||||
var swagArray:Array<Dynamic> = [];
|
||||
for (i in notes)
|
||||
{
|
||||
if (i.sectionNotes.length > 0) swagArray.push(i);
|
||||
}
|
||||
|
||||
return swagArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quicky lil function just for me formatting the old songs hehehe
|
||||
*/
|
||||
static function getStage(songName:String):String
|
||||
{
|
||||
switch (songName)
|
||||
{
|
||||
case 'spookeez' | 'monster' | 'south':
|
||||
return "spooky";
|
||||
case 'pico' | 'blammed' | 'philly':
|
||||
return 'philly';
|
||||
case "milf" | 'satin-panties' | 'high':
|
||||
return 'limo';
|
||||
case "cocoa" | 'eggnog':
|
||||
return 'mall';
|
||||
case 'winter-horrorland':
|
||||
return 'mallEvil';
|
||||
case 'senpai' | 'roses':
|
||||
return 'school';
|
||||
case 'thorns':
|
||||
return 'schoolEvil';
|
||||
case 'guns' | 'stress' | 'ugh':
|
||||
return 'tank';
|
||||
default:
|
||||
return 'stage';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import csv
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
# This script imports a CSV file, and bulk updates the chart metadata files
|
||||
#
|
||||
# Requirements:
|
||||
# python3 I believe
|
||||
# and you need to have npm/npx, as we use that to run prettier to keep the same formatting
|
||||
#
|
||||
# Usage:
|
||||
# In our Google Sheets, export as .csv file
|
||||
#
|
||||
# Then in here from within this directory, run:
|
||||
# python3 sheetsToCharts.py path/to/csv/file.csv
|
||||
#
|
||||
# use from within this directory, as the paths to the chart metadata files are relative to this directory
|
||||
|
||||
|
||||
# Get the command line argument, if one wasn't already provided
|
||||
if len(sys.argv) < 2:
|
||||
csv_file = input("Please provide the CSV file path: ")
|
||||
else:
|
||||
csv_file = sys.argv[1]
|
||||
|
||||
# Open the CSV file
|
||||
with open(csv_file, 'r') as file:
|
||||
reader = csv.reader(file)
|
||||
|
||||
# Which rows for each difficulty are we looking for
|
||||
diff_rows = {}
|
||||
|
||||
# Iterate over each row in the CSV file
|
||||
for idx, row in enumerate(reader):
|
||||
|
||||
# The first row has headers for the columns, stuff like "Easy - Difficulty", so we want
|
||||
# to know which rows corresponde to which difficulty
|
||||
if idx == 0:
|
||||
pattern = r"\b(?:difficulty)\b"
|
||||
|
||||
diff_cols = []
|
||||
diff_words = []
|
||||
|
||||
# Go through each column, and see if it includes the word "difficulty"
|
||||
# then append the column index, and the first word of the column (usually what difficulty it is, "easy", "normal", "hard", etc.)
|
||||
for colindex, column in enumerate(row):
|
||||
txt = re.findall(pattern, column, flags=re.IGNORECASE)
|
||||
if txt:
|
||||
diff_cols.append(colindex)
|
||||
diff_words.append(column.split()[0].lower())
|
||||
|
||||
# We then create a dictionary for use later, where the key is the difficulty, and the value is the column index
|
||||
diff_rows = dict(zip(diff_words, diff_cols))
|
||||
else:
|
||||
# Some song title parsing, to match the filenames we used in for the chart files
|
||||
song_title = row[1].lower() # we use lowercase for filenames, SOUTH -> south
|
||||
song_title = song_title.replace(" ", "-") # usually we change spaces to dashes, PHILLY NICE -> philly-nice
|
||||
song_title = song_title.replace(".", "") # M.I.L.F. -> milf
|
||||
song_title = song_title.replace("'", "") # blazin' -> blazin
|
||||
|
||||
# we open the chart metadata json file for writing and reading ("r+")
|
||||
with open(f"../../../assets/preload/data/songs/{song_title}/{song_title}-metadata.json", "r+") as chart_metadata_file:
|
||||
|
||||
json_data = json.load(chart_metadata_file) # load the file as a python data structure/dict
|
||||
play_data = json_data["playData"] # we want to modify the "playData" section, as that holds the difficulty
|
||||
|
||||
# note to self, python equals(=) operator seems to create a reference for the variable,
|
||||
# so modifying play_data will also modify json_data, so we can save json_data easily later
|
||||
|
||||
# if the chart metadata file doesn't already have a "ratings" dict/section, we create one here with 0 for each
|
||||
if "ratings" not in play_data:
|
||||
play_data["ratings"] = {'easy': 0, 'normal': 0, 'hard': 0}
|
||||
|
||||
ratings = play_data["ratings"]
|
||||
|
||||
# Now we go through our data from the csv file, and the data we kept from the columns there
|
||||
# will be put into our new ratings var, if it exists
|
||||
for diff, col in diff_rows.items():
|
||||
if row[col] == "":
|
||||
continue
|
||||
if diff in ratings:
|
||||
ratings[diff] = round(float(row[col])) # convert the string to a float, and then round it to nearest int
|
||||
|
||||
# Convert the python json_data dict back to a json string
|
||||
json_output = json.dumps(json_data)
|
||||
|
||||
# Write the json string back to the file, and truncate the rest of the file
|
||||
chart_metadata_file.seek(0)
|
||||
chart_metadata_file.write(json_output)
|
||||
chart_metadata_file.truncate()
|
||||
chart_metadata_file.close()
|
||||
|
||||
# Bit hacky, but we simply run `npx prettier` using the same rules we use for FNF here
|
||||
# essnetially running it via cli and passing in the songs folder and our prettier config file
|
||||
# This should make the spacing and formatting consistent
|
||||
command = "npx prettier ../../../assets/preload/data/songs --write --config ../../../.prettierrc.js"
|
||||
subprocess.run(command, shell=True)
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Find all files in OGG format and execute ffmpeg to convert them to MP3
|
||||
# Skips files that are already in MP3 format
|
||||
find "../assets/" -name "*.ogg" -exec sh -c 'ffmpeg -n -i {} "${0%.*}.mp3"' {} \;
|
||||
@@ -0,0 +1,218 @@
|
||||
import requests
|
||||
import sys
|
||||
|
||||
PROJECT_ID = 5582053
|
||||
|
||||
TEMPLATE = 'jQuery("#new-event-name").val("{event}"); jQuery("#save-new-event").click();'
|
||||
|
||||
EVENT_TEMPLATES = [
|
||||
"start-game",
|
||||
"watch-cartoon",
|
||||
"open-credits",
|
||||
|
||||
"start-song_{songId}-{variation}",
|
||||
"blueballs_{songId}-{variation}",
|
||||
"complete-song_{songId}-{variation}",
|
||||
"start-level_{levelId}",
|
||||
"complete-level_{levelId}",
|
||||
"earn-rank_{rankName}",
|
||||
]
|
||||
|
||||
SONG_IDS = [
|
||||
{ "songId": "tutorial", "variation": "default" },
|
||||
{ "songId": "tutorial", "variation": "erect" },
|
||||
{ "songId": "tutorial", "variation": "pico" },
|
||||
|
||||
{ "songId": "bopeebo", "variation": "default" },
|
||||
{ "songId": "bopeebo", "variation": "erect" },
|
||||
{ "songId": "bopeebo", "variation": "pico" },
|
||||
|
||||
{ "songId": "fresh", "variation": "default" },
|
||||
{ "songId": "fresh", "variation": "erect" },
|
||||
{ "songId": "fresh", "variation": "pico" },
|
||||
|
||||
{ "songId": "dadbattle", "variation": "default" },
|
||||
{ "songId": "dadbattle", "variation": "erect" },
|
||||
{ "songId": "dadbattle", "variation": "pico" },
|
||||
|
||||
{ "songId": "spookeez", "variation": "default" },
|
||||
{ "songId": "spookeez", "variation": "erect" },
|
||||
{ "songId": "spookeez", "variation": "pico" },
|
||||
|
||||
{ "songId": "south", "variation": "default" },
|
||||
{ "songId": "south", "variation": "erect" },
|
||||
{ "songId": "south", "variation": "pico" },
|
||||
|
||||
{ "songId": "monster", "variation": "default" },
|
||||
{ "songId": "monster", "variation": "erect" },
|
||||
{ "songId": "monster", "variation": "pico" },
|
||||
|
||||
{ "songId": "pico", "variation": "default" },
|
||||
{ "songId": "pico", "variation": "erect" },
|
||||
{ "songId": "pico", "variation": "pico" },
|
||||
|
||||
{ "songId": "philly-nice", "variation": "default" },
|
||||
{ "songId": "philly-nice", "variation": "erect" },
|
||||
{ "songId": "philly-nice", "variation": "pico" },
|
||||
|
||||
{ "songId": "blammed", "variation": "default" },
|
||||
{ "songId": "blammed", "variation": "erect" },
|
||||
{ "songId": "blammed", "variation": "pico" },
|
||||
|
||||
{ "songId": "satin-panties", "variation": "default" },
|
||||
{ "songId": "satin-panties", "variation": "erect" },
|
||||
{ "songId": "satin-panties", "variation": "pico" },
|
||||
|
||||
{ "songId": "high", "variation": "default" },
|
||||
{ "songId": "high", "variation": "erect" },
|
||||
{ "songId": "high", "variation": "pico" },
|
||||
|
||||
{ "songId": "milf", "variation": "default" },
|
||||
{ "songId": "milf", "variation": "erect" },
|
||||
{ "songId": "milf", "variation": "pico" },
|
||||
|
||||
{ "songId": "cocoa", "variation": "default" },
|
||||
{ "songId": "cocoa", "variation": "erect" },
|
||||
{ "songId": "cocoa", "variation": "pico" },
|
||||
|
||||
{ "songId": "eggnog", "variation": "default" },
|
||||
{ "songId": "eggnog", "variation": "erect" },
|
||||
{ "songId": "eggnog", "variation": "pico" },
|
||||
|
||||
{ "songId": "winter-horrorland", "variation": "default" },
|
||||
{ "songId": "winter-horrorland", "variation": "erect" },
|
||||
{ "songId": "winter-horrorland", "variation": "pico" },
|
||||
|
||||
{ "songId": "senpai", "variation": "default" },
|
||||
{ "songId": "senpai", "variation": "erect" },
|
||||
{ "songId": "senpai", "variation": "pico" },
|
||||
|
||||
{ "songId": "roses", "variation": "default" },
|
||||
{ "songId": "roses", "variation": "erect" },
|
||||
{ "songId": "roses", "variation": "pico" },
|
||||
|
||||
{ "songId": "thorns", "variation": "default" },
|
||||
{ "songId": "thorns", "variation": "erect" },
|
||||
{ "songId": "thorns", "variation": "pico" },
|
||||
|
||||
{ "songId": "ugh", "variation": "default" },
|
||||
{ "songId": "ugh", "variation": "erect" },
|
||||
{ "songId": "ugh", "variation": "pico" },
|
||||
|
||||
{ "songId": "guns", "variation": "default" },
|
||||
{ "songId": "guns", "variation": "erect" },
|
||||
{ "songId": "guns", "variation": "pico" },
|
||||
|
||||
{ "songId": "stress", "variation": "default" },
|
||||
{ "songId": "stress", "variation": "erect" },
|
||||
{ "songId": "stress", "variation": "pico" },
|
||||
|
||||
{ "songId": "darnell", "variation": "default" },
|
||||
{ "songId": "darnell", "variation": "erect" },
|
||||
{ "songId": "darnell", "variation": "bf" },
|
||||
|
||||
{ "songId": "lit-up", "variation": "default" },
|
||||
{ "songId": "lit-up", "variation": "erect" },
|
||||
{ "songId": "lit-up", "variation": "bf" },
|
||||
|
||||
{ "songId": "2hot", "variation": "default" },
|
||||
{ "songId": "2hot", "variation": "erect" },
|
||||
{ "songId": "2hot", "variation": "bf" },
|
||||
|
||||
{ "songId": "blazin", "variation": "default" },
|
||||
{ "songId": "blazin", "variation": "erect" },
|
||||
{ "songId": "blazin", "variation": "bf" },
|
||||
]
|
||||
|
||||
LEVEL_IDS = [
|
||||
"tutorial",
|
||||
"week1",
|
||||
"week2",
|
||||
"week3",
|
||||
"week4",
|
||||
"week5",
|
||||
"week6",
|
||||
"week7",
|
||||
"weekend1",
|
||||
"week8",
|
||||
]
|
||||
|
||||
RANKS = [
|
||||
"PERFECT_GOLD",
|
||||
"PERFECT",
|
||||
"EXCELLENT",
|
||||
"GREAT",
|
||||
"GOOD",
|
||||
"SHIT",
|
||||
]
|
||||
|
||||
|
||||
def formatEventSong(event):
|
||||
result = []
|
||||
for song in SONG_IDS:
|
||||
result.append(event.format(
|
||||
songId = song["songId"],
|
||||
variation = song["variation"]
|
||||
))
|
||||
return result
|
||||
|
||||
def formatEventLevel(event):
|
||||
result = []
|
||||
for level in LEVEL_IDS:
|
||||
result.append(event.format(
|
||||
levelId = level
|
||||
))
|
||||
return result
|
||||
|
||||
def formatEventRank(event):
|
||||
result = []
|
||||
for rank in RANKS:
|
||||
result.append(event.format(
|
||||
rankName = rank
|
||||
))
|
||||
return result
|
||||
|
||||
def formatEvent(event):
|
||||
if "{songId}" in event or "{variation}" in event:
|
||||
return formatEventSong(event)
|
||||
|
||||
if "{levelId}" in event:
|
||||
return formatEventLevel(event)
|
||||
|
||||
if "{rankName}" in event:
|
||||
return formatEventRank(event)
|
||||
|
||||
return [event]
|
||||
|
||||
def createEvent(event):
|
||||
print(TEMPLATE.format(event=event))
|
||||
|
||||
def main():
|
||||
event_list = []
|
||||
|
||||
for event in EVENT_TEMPLATES:
|
||||
event_list.extend(formatEvent(event))
|
||||
|
||||
# Filter out duplicates then sort alphabetically
|
||||
event_list = list(set(event_list))
|
||||
event_list.sort()
|
||||
|
||||
for event in event_list:
|
||||
createEvent(event)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
|
||||
#function sleep(ms) {
|
||||
# console.log("sleeping for " + ms + "ms");
|
||||
# return new Promise(resolve => setTimeout(resolve, ms));
|
||||
#}
|
||||
#async function example() {
|
||||
# jQuery("#new-event-name").val("blueballs_blazin-erect"); jQuery("#save-new-event").click();
|
||||
# await sleep(1000);
|
||||
# jQuery("#new-event-name").val("blueballs_blazin-erect"); jQuery("#save-new-event").click();
|
||||
# await sleep(1000);
|
||||
#}
|
||||
#example();
|
||||
@@ -0,0 +1,11 @@
|
||||
@echo off
|
||||
color 0a
|
||||
cd ..
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build html5 -final
|
||||
echo UPLOADING TO ITCH
|
||||
butler push ./export/release/html5/bin ninja-muffin24/funkin-secret:html5
|
||||
butler status ninja-muffin24/funkin-secret:html5
|
||||
echo ITCH SHIT UPDATED LMAOOOOO
|
||||
pause
|
||||
@@ -0,0 +1,11 @@
|
||||
@echo off
|
||||
color 0a
|
||||
cd ..
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build html5 -debug
|
||||
echo UPLOADING TO ITCH
|
||||
butler push ./export/debug/html5/bin ninja-muffin24/funkin-secret:html5
|
||||
butler status ninja-muffin24/funkin-secret:html5
|
||||
echo ITCH SHIT UPDATED LMAOOOOO
|
||||
pause
|
||||
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
color 0a
|
||||
cd ..
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build windows -final -clean
|
||||
echo UPLOADING 64 BIT VERSION TO ITCH
|
||||
butler push ./export/release/windows/bin ninja-muffin24/funkin:windows-64bit
|
||||
lime build windows -final -32
|
||||
echo UPLOADING 32 BIT VERSION TO ITCH
|
||||
butler push ./export/release/windows/bin ninja-muffin24/funkin:windows-32bit
|
||||
butler status ninja-muffin24/funkin:windows-32bit
|
||||
butler status ninja-muffin24/funkin:windows-64bit
|
||||
echo ITCH SHIT UPDATED LMAOOOOO
|
||||
pause
|
||||
@@ -0,0 +1,11 @@
|
||||
@echo off
|
||||
color 0a
|
||||
cd ..
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build windows -debug
|
||||
echo UPLOADING 64 BIT VERSION TO ITCH
|
||||
butler push ./export/debug/windows/bin ninja-muffin24/funkin:windows-secretBeta
|
||||
butler status ninja-muffin24/funkin:windows-secretBeta
|
||||
echo ITCH SHIT UPDATED LMAOOOOO
|
||||
pause
|
||||
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
color 0a
|
||||
cd ..
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build windows -release
|
||||
echo UPLOADING 64 BIT VERSION TO ITCH
|
||||
butler push ./export/release/windows/bin ninja-muffin24/funkin:windows-64bit
|
||||
lime build windows -release -32
|
||||
echo UPLOADING 32 BIT VERSION TO ITCH
|
||||
butler push ./export/release/windows/bin ninja-muffin24/funkin:windows-32bit
|
||||
butler status ninja-muffin24/funkin:windows-32bit
|
||||
butler status ninja-muffin24/funkin:windows-64bit
|
||||
echo ITCH SHIT UPDATED LMAOOOOO
|
||||
pause
|
||||
@@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
color 0a
|
||||
cd ..
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build html5 -final -Dng
|
||||
echo ZIPPING
|
||||
cd export
|
||||
7z a -tzip -r swag release\html5\bin
|
||||
start .
|
||||
start https://www.newgrounds.com/projects/games/1528775
|
||||
pause
|
||||
@@ -0,0 +1,27 @@
|
||||
@echo off
|
||||
cd ..
|
||||
@echo on
|
||||
echo REBUILDING LIME FOR EXPORT (VERBOSE)
|
||||
@echo off
|
||||
color 0b
|
||||
@echo on
|
||||
lime rebuild windows -clean -v
|
||||
@echo off
|
||||
color 0a
|
||||
@echo on
|
||||
lime rebuild switch -clean -v
|
||||
@echo off
|
||||
color 0e
|
||||
@echo on
|
||||
lime rebuild tools -clean -v
|
||||
echo HOPE AND PRAY...
|
||||
@echo off
|
||||
color 0a
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build switch -final -clean -v
|
||||
@echo off
|
||||
color 0b
|
||||
@echo on
|
||||
echo NSP FILE CREATED
|
||||
pause
|
||||
@@ -0,0 +1,110 @@
|
||||
// Highlight keyframes in flash
|
||||
// drag .jsfl script in
|
||||
// will export the layer info of the first(?) element it finds?
|
||||
// maybe someone can extend this to add more depth / functionality!
|
||||
// see FramesJSFLParser.hx and CharSelectGF.hx for sample implementation
|
||||
|
||||
function splitArrayIntoChunks(array, chunkSize) {
|
||||
var result = [];
|
||||
for (var i = 0; i < array.length; i += chunkSize) {
|
||||
var chunk = array.slice(i, i + chunkSize);
|
||||
result.push(chunk);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
var isJson = false;
|
||||
|
||||
function addField(name, variable, end)
|
||||
{
|
||||
return (isJson) ? addFJson(name, variable, end) : addF(variable, end);
|
||||
}
|
||||
function addFJson(name, variable, end) {
|
||||
return "\"" + name + "\": " + variable + ((!end) ? "," : "");
|
||||
}
|
||||
function addF(variable, end) {
|
||||
return variable + ((end)? "" : " ");
|
||||
}
|
||||
|
||||
|
||||
fl.outputPanel.clear();
|
||||
|
||||
var timeline = fl.getDocumentDOM().getTimeline();
|
||||
var daSelection = timeline.getSelectedFrames();
|
||||
var splitArrays = splitArrayIntoChunks(daSelection, 3);
|
||||
var uri = undefined;
|
||||
|
||||
|
||||
if (fl.version.substring(4).split(",")[0] < 13)
|
||||
{
|
||||
var macFormat = "Folder|TEXT[*.||";
|
||||
var winFormat = "Folder|*.||";
|
||||
var previewArea = {};
|
||||
uri = fl.browseForFileURL("save", "where to save files pick folder...", previewArea, macFormat, winFormat);
|
||||
}
|
||||
else
|
||||
uri = fl.browseForFileURL("save", "where to save files pick folder..", "Folder(*.)", "*.");
|
||||
|
||||
|
||||
for (var i = 0; i < splitArrays.length; i+=1)
|
||||
{
|
||||
var curLayerInfo = splitArrays[i];
|
||||
var curLayerInd = curLayerInfo[0];
|
||||
var curLayer = fl.getDocumentDOM().getTimeline().layers[curLayerInd];
|
||||
|
||||
var layerURI = uri;
|
||||
var fileName = "";
|
||||
var uris = uri.split("/");
|
||||
|
||||
fileName = uris[uris.length - 1];
|
||||
|
||||
|
||||
FLfile.createFolder(layerURI);
|
||||
|
||||
|
||||
var fileData = "{\n";
|
||||
if (!isJson)
|
||||
fileData = "";
|
||||
|
||||
var selectedFrames = curLayer.frames;
|
||||
var sliceLength = curLayerInfo[2] - curLayerInfo[1];
|
||||
selectedFrames =selectedFrames.slice(curLayerInfo[1],curLayerInfo[2]);
|
||||
|
||||
if (isJson)
|
||||
fileData += "\"frames\": [";
|
||||
|
||||
for (var frameInd = curLayerInfo[1]; frameInd < curLayerInfo[2]; frameInd+=1)
|
||||
{
|
||||
if (isJson)
|
||||
fileData += "\n{"
|
||||
var curFrame = curLayer.frames[frameInd];
|
||||
if (curFrame.isEmpty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var elementInd = 0; elementInd < curFrame.elements.length; elementInd+=1)
|
||||
{
|
||||
|
||||
var curElement = curFrame.elements[elementInd];
|
||||
|
||||
fileData += addField("x", curElement.left, false);
|
||||
fileData += addField("y", curElement.top, false);
|
||||
fileData += addField("alpha", (curElement.colorAlphaPercent == undefined) ? 100 : curElement.colorAlphaPercent, false);
|
||||
fileData += addField("scaleX", curElement.scaleX, false);
|
||||
fileData += addField("scaleY", curElement.scaleY, true);
|
||||
if (frameInd != curLayerInfo[2] - 1)
|
||||
fileData += "\n";
|
||||
}
|
||||
|
||||
if (isJson)
|
||||
fileData += "},";
|
||||
}
|
||||
if (isJson)
|
||||
fileData += "]";
|
||||
|
||||
if (isJson)
|
||||
fileData += "\n}";
|
||||
|
||||
FLfile.write(layerURI + "/" + fileName + ".txt", fileData);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# README
|
||||
|
||||
jsfl is a scripting format with javascript syntax, I believe it's old js (no `let`, idk the spec!)
|
||||
|
||||
Official Adobe JSFL docuementation
|
||||
[https://github.com/AdobeDocs/developers-animatesdk-docs/tree/master](https://github.com/AdobeDocs/developers-animatesdk-docs/tree/master)
|
||||
Executable
+120
@@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
set -e # Exit immediately if a command exits with a non-zero status
|
||||
|
||||
echo "Note! This should be run from the root of the main Funkin repo, after creating a universal macOS build!"
|
||||
echo "This script will assist in codesigning the Funkin.app for macOS"
|
||||
echo ""
|
||||
|
||||
TEAM_ID="Z7G7AVNGSH"
|
||||
ISSUER_ID="5205caca-2a9b-4b5e-9390-1db124cf51f4"
|
||||
DEVELOPER_CERT_NAME="Developer ID Application: The Funkin' Crew Incorporated ($TEAM_ID)"
|
||||
APP_PATH="export/release/macosUniversal/Funkin.app"
|
||||
|
||||
# Check if app exists
|
||||
if [ ! -d "$APP_PATH" ]; then
|
||||
echo "Error: $APP_PATH does not exist! Please build the app first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Preparing/Checking the AuthKey"
|
||||
team_key_path=~/.appstoreconnect/private_keys/
|
||||
# Check if directory exists, if not, create it
|
||||
if [ ! -d "$team_key_path" ]; then
|
||||
echo "The directory $team_key_path does not exist! Creating it now."
|
||||
mkdir -p "$team_key_path"
|
||||
echo ""
|
||||
echo "$team_key_path created, put the private key file in there (should be called 'AuthKey_XXXXXXX.p8')"
|
||||
echo "Ask Cameron for the private key file!"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# wait for the user to put the file in the directory, if it's not there
|
||||
while [ ! -f "${team_key_path}"AuthKey_*.p8 ]; do
|
||||
echo "Waiting for the private key file to be placed in $team_key_path... (press Ctrl+C to exit)"
|
||||
sleep 5
|
||||
done
|
||||
|
||||
key_id=$(ls "$team_key_path" | grep -oE '[A-Z0-9]{10}' | head -n 1)
|
||||
if [ -z "$key_id" ]; then
|
||||
echo "Error: Could not extract key ID from the AuthKey file name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Found AuthKey with key id: $key_id"
|
||||
key_path="${team_key_path}AuthKey_${key_id}.p8"
|
||||
|
||||
cd export/release/macosUniversal || { echo "Failed to change directory"; exit 1; }
|
||||
|
||||
echo "Ensuring properly formatted Entitlements.plist"
|
||||
if [ ! -f "Funkin.app/Contents/Entitlements.plist" ]; then
|
||||
echo "Error: Entitlements.plist not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
plutil -convert xml1 Funkin.app/Contents/Entitlements.plist
|
||||
plutil -convert xml1 Funkin.app/Contents/Info.plist
|
||||
plutil -lint Funkin.app/Contents/Entitlements.plist
|
||||
plutil -lint Funkin.app/Contents/Info.plist
|
||||
echo "Entitlements.plist and Info.plist should be properly formatted..."
|
||||
echo "Codesigning - Funkin.app"
|
||||
# Check the keychain for the funkin crew certificate
|
||||
echo "Checking for The Funkin' Crew certificate in the keychain..."
|
||||
if ! security find-identity -p codesigning | grep -q "The Funkin' Crew Incorporated"; then
|
||||
echo "The Funkin' Crew Developer ID Application certificate was not found in the keychain!"
|
||||
echo "Download the certificate from:"
|
||||
echo "https://developer.apple.com/account/resources/certificates/download/Z62SXF29U7"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Codesigning - Funkin.app"
|
||||
codesign --force --deep --timestamp --sign "$DEVELOPER_CERT_NAME" --options runtime Funkin.app || {
|
||||
echo "Code signing failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Codesigning - Funkin.app done!"
|
||||
# Debug info to see if the app is properly signed
|
||||
codesign -vv --deep --strict Funkin.app || {
|
||||
echo "Code signing verification failed"
|
||||
exit 1
|
||||
}
|
||||
echo ""
|
||||
echo "Zipping Funkin.app for notarization (using ditto)..."
|
||||
# Check if Funkin.app.zip already exists, if so, delete it
|
||||
if [ -f Funkin.app.zip ]; then
|
||||
echo "Funkin.app.zip already exists, deleting it..."
|
||||
rm -rf Funkin.app.zip
|
||||
fi
|
||||
|
||||
ditto -c -k --keepParent Funkin.app Funkin.app.zip || {
|
||||
echo "Failed to create zip file"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Funkin.app zipped, now sending to Apple for notarization..."
|
||||
xcrun notarytool submit Funkin.app.zip --issuer "$ISSUER_ID" --key-id "$key_id" --key "$key_path" --wait || {
|
||||
echo "Notarization submission failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Clean up zip file
|
||||
rm -rf Funkin.app.zip
|
||||
|
||||
echo "Stapling Funkin.app"
|
||||
xcrun stapler staple Funkin.app || {
|
||||
echo "Stapling failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Code sign information!"
|
||||
codesign -dv --verbose=4 Funkin.app
|
||||
|
||||
echo "Notarization information (stapler):"
|
||||
xcrun stapler validate Funkin.app || {
|
||||
echo "Stapler validation failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
cd ../../.. || { echo "Failed to return to original directory"; exit 1; }
|
||||
echo "Notarization complete! Funkin.app is now codesigned and notarized!"
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
echo "Note! This should be run from the root of the main Funkin repo, after creating a universal macOS build!"
|
||||
echo "This script will assist in creating a universal build of Funkin.app for macOS"
|
||||
echo ""
|
||||
lime build mac -64 -release
|
||||
cd export/release
|
||||
rm -rf macosUniversal
|
||||
mkdir macosUniversal
|
||||
cp -r macos/bin/Funkin.app macosUniversal
|
||||
cd ../..
|
||||
lime build mac -arm64 -release
|
||||
cd export/release
|
||||
cp -r macos/bin/Funkin.app/Contents/MacOS/Funkin macosUniversal/Funkin.app/Contents/MacOS/FunkinArm
|
||||
cp -r macos/bin/Funkin.app/Contents/MacOS/lime.ndll macosUniversal/Funkin.app/Contents/MacOS/limeArm.ndll
|
||||
cd macosUniversal/Funkin.app/Contents/MacOS
|
||||
mv Funkin Funkin64
|
||||
mv lime.ndll lime64.ndll
|
||||
lipo -create -output lime.ndll lime64.ndll limeArm.ndll
|
||||
lipo -create -output Funkin Funkin64 FunkinArm
|
||||
rm FunkinArm Funkin64 lime64.ndll limeArm.ndll
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Find all files in PNG format and execute oxipng to optimize file sizes
|
||||
cd ../assets/ && oxipng -o 6 --strip safe --alpha {} **/*.png
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Resize each health icon to 512x512
|
||||
find "../art/discord/" -name "icon-*.png" -exec sh -c 'ffmpeg -i {} -vf scale=512:512 "${0%.*}2.png"' {} \;
|
||||
+34
-20
@@ -11,6 +11,8 @@ import funkin.util.logging.CrashHandler;
|
||||
import funkin.ui.debug.FunkinDebugDisplay;
|
||||
import funkin.ui.debug.FunkinDebugDisplay.DebugDisplayMode;
|
||||
import funkin.save.Save;
|
||||
import funkin.FunkinMemory;
|
||||
import funkin.audio.FunkinSound;
|
||||
#if hxvlc
|
||||
import hxvlc.util.Handle;
|
||||
#end
|
||||
@@ -87,11 +89,28 @@ class Main extends Sprite
|
||||
removeEventListener(Event.ADDED_TO_STAGE, init);
|
||||
}
|
||||
|
||||
#if (!html5 && !mobile)
|
||||
// Force-kill the game to prevent background processing.
|
||||
openfl.Lib.application.onExit.add((_) ->
|
||||
{
|
||||
// Dispose of cached audio and textures.
|
||||
funkin.audio.FunkinSound.stopAllAudio(true, true);
|
||||
funkin.FunkinMemory.purgeCache(true);
|
||||
|
||||
// Dispose of any assets still in the OpenFL cache, just incase.
|
||||
openfl.Assets.cache.clear();
|
||||
|
||||
trace(' EXITING '.bold().bg_red() + ' Resources are disposed, Game is closing now.');
|
||||
|
||||
Sys.exit(0);
|
||||
}, 99);
|
||||
#end
|
||||
|
||||
// Manually crash the game when using a software renderer in order to give a nicer error message.
|
||||
var context = stage.window.context.type;
|
||||
if (context != WEBGL && context != OPENGL && context != OPENGLES)
|
||||
{
|
||||
var tech:String = #if web "WebGL" #elseif desktop "OpenGL" #else "OpenGL ES" #end;
|
||||
var tech:String = #if web 'WebGL' #elseif desktop 'OpenGL' #else 'OpenGL ES' #end;
|
||||
var requiredVersion:String = #if web '$tech 1.0 or newer' #elseif desktop '$tech 3.0 or newer' #else '$tech 2.0 or newer' #end;
|
||||
var desc:String = 'Failed to initialize the $tech rendering context!\n\n';
|
||||
#if web
|
||||
@@ -136,7 +155,8 @@ class Main extends Sprite
|
||||
|
||||
#if hxvlc
|
||||
// Initialize hxvlc's Handle here so the videos are loading faster.
|
||||
Handle.initAsync(function(success:Bool):Void {
|
||||
Handle.initAsync(function(success:Bool):Void
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
trace(' HXVLC '.bold().bg_orange() + ' LibVLC instance initialized!');
|
||||
@@ -148,16 +168,15 @@ class Main extends Sprite
|
||||
});
|
||||
#end
|
||||
|
||||
// Don't call anything from the preferences until the save is loaded!
|
||||
#if web
|
||||
// set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx
|
||||
// The framerate cap will more thoroughly initialize via Preferences in InitState.hx
|
||||
funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
|
||||
#end
|
||||
|
||||
WindowUtil.setVSyncMode(funkin.Preferences.vsyncMode);
|
||||
|
||||
var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, Preferences.framerate, Preferences.framerate, skipSplash,
|
||||
// Force a `FunkinCamera` to be the default camera.
|
||||
// This allows the blend mode shader to work everywhere.
|
||||
untyped FlxG.cameras = new funkin.graphics.FunkinCameraFrontEnd();
|
||||
|
||||
var framerate:Int = Preferences.unlockedFramerate ? 0 : Preferences.framerate;
|
||||
|
||||
var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, framerate, framerate, skipSplash,
|
||||
(FlxG.stage.window.fullscreen || Preferences.autoFullscreen));
|
||||
|
||||
// FlxG.game._customSoundTray wants just the class, it calls new from
|
||||
@@ -169,7 +188,7 @@ class Main extends Sprite
|
||||
addChild(game);
|
||||
|
||||
#if FEATURE_DEBUG_FUNCTIONS
|
||||
game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil());
|
||||
#if !FLX_NO_DEBUG game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil()); #end
|
||||
funkin.util.macro.ConsoleMacro.init();
|
||||
#end
|
||||
|
||||
@@ -231,14 +250,7 @@ class Main extends Sprite
|
||||
function repositionCounters(lerp:Bool):Void
|
||||
{
|
||||
// Calling this so it gets scaled based on the resolution of the game and device's resolution.
|
||||
var scale:Float = Math.min(FlxG.stage.stageWidth / FlxG.width, FlxG.stage.stageHeight / FlxG.height);
|
||||
|
||||
#if android
|
||||
scale = Math.max(scale, 1);
|
||||
#else
|
||||
scale = Math.min(scale, 1);
|
||||
#end
|
||||
final thypos:Float = Math.max(FullScreenScaleMode.notchSize.x, 10);
|
||||
var scale:Float = Math.max(Math.min(FlxG.stage.stageWidth / FlxG.width, FlxG.stage.stageHeight / FlxG.height), 1);
|
||||
|
||||
if (debugDisplay != null)
|
||||
{
|
||||
@@ -246,13 +258,15 @@ class Main extends Sprite
|
||||
|
||||
if (FlxG.game != null)
|
||||
{
|
||||
final thypos:Float = Math.max(FullScreenScaleMode.notchSize.x, 10);
|
||||
|
||||
if (lerp)
|
||||
{
|
||||
debugDisplay.x = flixel.math.FlxMath.lerp(debugDisplay.x, FlxG.game.x + thypos, FlxG.elapsed * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
debugDisplay.x = FlxG.game.x + FullScreenScaleMode.notchSize.x + 10;
|
||||
debugDisplay.x = FlxG.game.x + thypos;
|
||||
}
|
||||
|
||||
debugDisplay.y = FlxG.game.y + (3 * scale);
|
||||
|
||||
+5
-10
@@ -36,12 +36,7 @@ class Postbuild
|
||||
|
||||
static function format(time:Float, decimals:Int = 1):String
|
||||
{
|
||||
var units = [
|
||||
{name: "day", secs: 86400},
|
||||
{name: "hour", secs: 3600},
|
||||
{name: "minute", secs: 60},
|
||||
{name: "second", secs: 1}
|
||||
];
|
||||
var units = [{name: 'day', secs: 86400}, {name: 'hour', secs: 3600}, {name: 'minute', secs: 60}, {name: 'second', secs: 1}];
|
||||
|
||||
var parts:Array<String> = [];
|
||||
var remaining:Float = time;
|
||||
@@ -49,13 +44,13 @@ class Postbuild
|
||||
|
||||
for (u in units)
|
||||
{
|
||||
var value:Float = (u.name == "second") ? Math.round(remaining * factor) / factor : Math.floor(remaining / u.secs);
|
||||
var value:Float = (u.name == 'second') ? Math.round(remaining * factor) / factor : Math.floor(remaining / u.secs);
|
||||
|
||||
if (u.name != "second") remaining %= u.secs;
|
||||
if (u.name != 'second') remaining %= u.secs;
|
||||
|
||||
if (value > 0 || (u.name == "second" && parts.length == 0)) parts.push('${value} ${u.name}${value == 1 ? "" : "s"}');
|
||||
if (value > 0 || (u.name == 'second' && parts.length == 0)) parts.push('${value} ${u.name}${value == 1 ? "" : "s"}');
|
||||
}
|
||||
|
||||
return parts.join(" ");
|
||||
return parts.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -2,6 +2,8 @@ package source; // Yeah, I know...
|
||||
|
||||
import sys.io.File;
|
||||
|
||||
using tools.AnsiUtil;
|
||||
|
||||
/**
|
||||
* A script which executes before the game is built.
|
||||
*/
|
||||
@@ -12,13 +14,13 @@ class Prebuild
|
||||
static function main():Void
|
||||
{
|
||||
var start:Float = Sys.time();
|
||||
// Sys.println('[INFO] Performing pre-build tasks...');
|
||||
// Sys.println(' INFO '.bold().bg_blue() + " Performing pre-build tasks...");
|
||||
|
||||
saveBuildTime();
|
||||
|
||||
var end:Float = Sys.time();
|
||||
var duration:Float = end - start;
|
||||
// Sys.println('[INFO] Finished pre-build tasks in $duration seconds.');
|
||||
// Sys.println(' INFO '.bold().bg_blue() + ' Finished pre-build tasks in $duration seconds.');
|
||||
}
|
||||
|
||||
static function saveBuildTime():Void
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Pulled from Tracey profiler PR
|
||||
* @see https://github.com/HaxeFoundation/haxe/pull/11772
|
||||
*/
|
||||
@@ -6,7 +6,7 @@
|
||||
package cpp.vm.tracy;
|
||||
|
||||
#if (!HXCPP_TRACY)
|
||||
#error "This class cannot be used without -D HXCPP_TRACY"
|
||||
#error 'This class cannot be used without -D HXCPP_TRACY'
|
||||
#end
|
||||
enum abstract PlotFormatType(cpp.UInt8) from cpp.UInt8 to cpp.UInt8
|
||||
{
|
||||
@@ -19,68 +19,68 @@ enum abstract PlotFormatType(cpp.UInt8) from cpp.UInt8 to cpp.UInt8
|
||||
extern class Native_TracyProfiler
|
||||
{
|
||||
/**
|
||||
Mark a frame. Call this at the end of each frame loop.
|
||||
**/
|
||||
* Mark a frame. Call this at the end of each frame loop.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_framemark')
|
||||
public static function frameMark():Void;
|
||||
|
||||
/**
|
||||
Mark a named frame. Allows creating multiple frame sets for different timing categories.
|
||||
Each unique name creates a separate frame set in the Tracy timeline.
|
||||
**/
|
||||
* Mark a named frame. Allows creating multiple frame sets for different timing categories.
|
||||
* Each unique name creates a separate frame set in the Tracy timeline.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_framemark_named')
|
||||
public static function frameMarkNamed(_name:String):Void;
|
||||
|
||||
/**
|
||||
Mark the start of a discontinuous frame. Use for periodic work with gaps.
|
||||
Must be paired with frameMarkEnd() using the same name.
|
||||
**/
|
||||
* Mark the start of a discontinuous frame. Use for periodic work with gaps.
|
||||
* Must be paired with frameMarkEnd() using the same name.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_framemark_start')
|
||||
public static function frameMarkStart(_name:String):Void;
|
||||
|
||||
/**
|
||||
Mark the end of a discontinuous frame. Use for periodic work with gaps.
|
||||
Must be paired with frameMarkStart() using the same name.
|
||||
**/
|
||||
* Mark the end of a discontinuous frame. Use for periodic work with gaps.
|
||||
* Must be paired with frameMarkStart() using the same name.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_framemark_end')
|
||||
public static function frameMarkEnd(_name:String):Void;
|
||||
|
||||
/**
|
||||
Print a message into Tracy's log.
|
||||
**/
|
||||
* Print a message into Tracy's log.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_message')
|
||||
public static function message(_msg:String, ?_color:Int = 0x000000):Void;
|
||||
|
||||
/**
|
||||
Tracy can collect additional information about the profiled application,
|
||||
which will be available in the trace description.
|
||||
This can include data such as the source repository revision,
|
||||
the application’s environment (dev/prod), etc.
|
||||
**/
|
||||
* Tracy can collect additional information about the profiled application,
|
||||
* which will be available in the trace description.
|
||||
* This can include data such as the source repository revision,
|
||||
* the application’s environment (dev/prod), etc.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_message_app_info')
|
||||
public static function messageAppInfo(_info:String):Void;
|
||||
|
||||
/**
|
||||
Plot a named value to tracy. This will generate a graph in the profiler for you.
|
||||
**/
|
||||
* Plot a named value to tracy. This will generate a graph in the profiler for you.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_plot')
|
||||
public static function plot(_name:String, _val:cpp.Float32):Void;
|
||||
|
||||
/**
|
||||
Configure how values are plotted and displayed.
|
||||
**/
|
||||
* Configure how values are plotted and displayed.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_plot_config')
|
||||
public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false, ?_color:Int = 0x000000):Void;
|
||||
|
||||
/**
|
||||
Set a name for the current thread this function is called in. Supply an optional groupHint so threads become grouped in Tracy's UI.
|
||||
**/
|
||||
* Set a name for the current thread this function is called in. Supply an optional groupHint so threads become grouped in Tracy's UI.
|
||||
*/
|
||||
@:native('::__hxcpp_tracy_set_thread_name_and_group')
|
||||
public static function setThreadName(_name:String, ?_groupHint:Int = 1):Void;
|
||||
|
||||
/**
|
||||
Create a custom named scoped zone in your code.
|
||||
**/
|
||||
* Create a custom named scoped zone in your code.
|
||||
*/
|
||||
@:native('HXCPP_TRACY_ZONE')
|
||||
public static function zoneScoped(_name:String):Void;
|
||||
}
|
||||
@@ -89,44 +89,35 @@ extern class Native_TracyProfiler
|
||||
class Cppia_TracyProfiler
|
||||
{
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.frameMark)
|
||||
public static function frameMark()
|
||||
Native_TracyProfiler.frameMark();
|
||||
public static function frameMark() Native_TracyProfiler.frameMark();
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.frameMarkNamed)
|
||||
public static function frameMarkNamed(_name:String)
|
||||
Native_TracyProfiler.frameMarkNamed(_name);
|
||||
public static function frameMarkNamed(_name:String) Native_TracyProfiler.frameMarkNamed(_name);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.frameMarkStart)
|
||||
public static function frameMarkStart(_name:String)
|
||||
Native_TracyProfiler.frameMarkStart(_name);
|
||||
public static function frameMarkStart(_name:String) Native_TracyProfiler.frameMarkStart(_name);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.frameMarkEnd)
|
||||
public static function frameMarkEnd(_name:String)
|
||||
Native_TracyProfiler.frameMarkEnd(_name);
|
||||
public static function frameMarkEnd(_name:String) Native_TracyProfiler.frameMarkEnd(_name);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.message)
|
||||
public static function message(_msg:String, ?_color:Int = 0x000000)
|
||||
Native_TracyProfiler.message(_msg, _color);
|
||||
public static function message(_msg:String, ?_color:Int = 0x000000) Native_TracyProfiler.message(_msg, _color);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.messageAppInfo)
|
||||
public static function messageAppInfo(_info:String)
|
||||
Native_TracyProfiler.messageAppInfo(_info);
|
||||
public static function messageAppInfo(_info:String) Native_TracyProfiler.messageAppInfo(_info);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.plot)
|
||||
public static function plot(_name:String, _val:Float)
|
||||
Native_TracyProfiler.plot(_name, _val);
|
||||
public static function plot(_name:String, _val:Float) Native_TracyProfiler.plot(_name, _val);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.plotConfig)
|
||||
public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false, ?_color:Int = 0x000000)
|
||||
Native_TracyProfiler.plotConfig(_name, _format, _step, _fill, _color);
|
||||
public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false,
|
||||
?_color:Int = 0x000000) Native_TracyProfiler.plotConfig(_name, _format, _step, _fill, _color);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.setThreadName)
|
||||
public static function setThreadName(_name:String, ?_groupHint:Int = 1)
|
||||
Native_TracyProfiler.setThreadName(_name, _groupHint);
|
||||
public static function setThreadName(_name:String, ?_groupHint:Int = 1) Native_TracyProfiler.setThreadName(_name, _groupHint);
|
||||
|
||||
@:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.zoneScoped)
|
||||
public static function zoneScoped(_name:String)
|
||||
Native_TracyProfiler.zoneScoped(_name);
|
||||
public static function zoneScoped(_name:String) Native_TracyProfiler.zoneScoped(_name);
|
||||
}
|
||||
|
||||
typedef TracyProfiler = Cppia_TracyProfiler;
|
||||
|
||||
@@ -362,7 +362,7 @@ class Conductor
|
||||
static function get_instance():Conductor
|
||||
{
|
||||
if (Conductor._instance == null) set_instance(new Conductor());
|
||||
if (Conductor._instance == null) throw "Could not initialize singleton Conductor!";
|
||||
if (Conductor._instance == null) throw 'Could not initialize singleton Conductor!';
|
||||
return Conductor._instance;
|
||||
}
|
||||
|
||||
@@ -381,7 +381,9 @@ class Conductor
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function new() {}
|
||||
public function new()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcibly defines the current BPM of the song.
|
||||
@@ -847,7 +849,7 @@ class Conductor
|
||||
* @param type The type of length to return. Either "step", "beat", or "measure" works, along with their first character.
|
||||
* @return The length of a step/beat/measure in milliseconds.
|
||||
*/
|
||||
public function getTypeLengthAtMs(ms:Float, type:String = "beat"):Float
|
||||
public function getTypeLengthAtMs(ms:Float, type:String = 'beat'):Float
|
||||
{
|
||||
if (timeChanges.length == 0) return 0;
|
||||
var wantedTimeChange:SongTimeChange = timeChanges[0];
|
||||
@@ -866,10 +868,14 @@ class Conductor
|
||||
var wantedBeatLengthMs:Float = ((Constants.SECS_PER_MIN / wantedTimeChange.bpm) * Constants.MS_PER_SEC) * (4 / wantedTimeChange.timeSignatureDen);
|
||||
return switch (type.toLowerCase())
|
||||
{
|
||||
case "measure", "m": wantedBeatLengthMs * wantedTimeChange.timeSignatureNum;
|
||||
case "beat", "b": wantedBeatLengthMs;
|
||||
case "step", "s": wantedBeatLengthMs / Constants.STEPS_PER_BEAT;
|
||||
default: wantedBeatLengthMs;
|
||||
case 'measure', 'm':
|
||||
wantedBeatLengthMs * wantedTimeChange.timeSignatureNum;
|
||||
case 'beat', 'b':
|
||||
wantedBeatLengthMs;
|
||||
case 'step', 's':
|
||||
wantedBeatLengthMs / Constants.STEPS_PER_BEAT;
|
||||
default:
|
||||
wantedBeatLengthMs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+131
-100
@@ -12,7 +12,7 @@ import lime.app.Promise;
|
||||
|
||||
/**
|
||||
* Handles caching of textures and sounds for the game.
|
||||
* TODO: Remove this once Eric finishes the memory system.
|
||||
* I did this hello, this can be improved later on and I have ideas on how, but for now this functions well enough. -Zack
|
||||
*/
|
||||
@:nullSafety
|
||||
class FunkinMemory
|
||||
@@ -20,13 +20,10 @@ class FunkinMemory
|
||||
static var permanentCachedTextures:Map<String, FlxGraphic> = [];
|
||||
static var currentCachedTextures:Map<String, FlxGraphic> = [];
|
||||
static var previousCachedTextures:Map<String, FlxGraphic> = [];
|
||||
|
||||
// waow
|
||||
static var permanentCachedSounds:Map<String, Sound> = [];
|
||||
static var currentCachedSounds:Map<String, Sound> = [];
|
||||
static var previousCachedSounds:Map<String, Sound> = [];
|
||||
|
||||
static var purgeFilter:Array<String> = ["/week", "/characters", "/charSelect", "/results"];
|
||||
static var purgeFilter:Array<String> = ['/week', '/characters', '/charSelect', '/results'];
|
||||
|
||||
/**
|
||||
* Caches textures that are always required.
|
||||
@@ -37,42 +34,42 @@ class FunkinMemory
|
||||
|
||||
for (file in allImages)
|
||||
{
|
||||
if (!(file.endsWith(".png") #if FEATURE_COMPRESSED_TEXTURES || file.endsWith(".astc") #end)
|
||||
|| file.contains("chart-editor")
|
||||
|| !file.contains("ui/"))
|
||||
if (!(file.endsWith('.png') #if FEATURE_COMPRESSED_TEXTURES || file.endsWith('.astc') #end)
|
||||
|| file.contains('chart-editor')
|
||||
|| !file.contains('ui/'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
file = file.replace(" ", ""); // Handle stray spaces.
|
||||
file = file.replace(' ', ''); // Handle stray spaces.
|
||||
|
||||
if (file.contains("shared") || Assets.exists('shared:$file', AssetType.IMAGE))
|
||||
if (file.contains('shared') || Assets.exists('shared:$file', AssetType.IMAGE))
|
||||
{
|
||||
file = 'shared:$file';
|
||||
}
|
||||
permanentCacheTexture(file);
|
||||
}
|
||||
|
||||
permanentCacheTexture(Paths.image("healthBar"));
|
||||
permanentCacheTexture(Paths.image("menuDesat"));
|
||||
permanentCacheTexture(Paths.image("notes", "shared"));
|
||||
permanentCacheTexture(Paths.image("noteSplashes", "shared"));
|
||||
permanentCacheTexture(Paths.image("noteStrumline", "shared"));
|
||||
permanentCacheTexture(Paths.image("NOTE_hold_assets"));
|
||||
permanentCacheTexture(Paths.image('healthBar'));
|
||||
permanentCacheTexture(Paths.image('menuDesat'));
|
||||
permanentCacheTexture(Paths.image('notes', 'shared'));
|
||||
permanentCacheTexture(Paths.image('noteSplashes', 'shared'));
|
||||
permanentCacheTexture(Paths.image('noteStrumline', 'shared'));
|
||||
permanentCacheTexture(Paths.image('NOTE_hold_assets'));
|
||||
// dude
|
||||
permanentCacheTexture(Paths.image("fonts/bold", null));
|
||||
permanentCacheTexture(Paths.image("fonts/default", null));
|
||||
permanentCacheTexture(Paths.image("fonts/freeplay-clear", null));
|
||||
permanentCacheTexture(Paths.image('fonts/bold', null));
|
||||
permanentCacheTexture(Paths.image('fonts/default', null));
|
||||
permanentCacheTexture(Paths.image('fonts/freeplay-clear', null));
|
||||
|
||||
var allSounds:Array<String> = Assets.list(AssetType.SOUND);
|
||||
|
||||
for (file in allSounds)
|
||||
{
|
||||
if (!file.endsWith(".ogg") || !file.contains("countdown/")) continue;
|
||||
if (!file.endsWith('.ogg') || !file.contains('countdown/')) continue;
|
||||
|
||||
file = file.replace(" ", "");
|
||||
file = file.replace(' ', '');
|
||||
|
||||
if (file.contains("shared") || Assets.exists('shared:$file', AssetType.SOUND))
|
||||
if (file.contains('shared') || Assets.exists('shared:$file', AssetType.SOUND))
|
||||
{
|
||||
file = 'shared:$file';
|
||||
}
|
||||
@@ -80,26 +77,29 @@ class FunkinMemory
|
||||
permanentCacheSound(file);
|
||||
}
|
||||
|
||||
permanentCacheSound(Paths.sound("cancelMenu"));
|
||||
permanentCacheSound(Paths.sound("confirmMenu"));
|
||||
permanentCacheSound(Paths.sound("screenshot"));
|
||||
permanentCacheSound(Paths.sound("scrollMenu"));
|
||||
permanentCacheSound(Paths.sound("soundtray/Voldown"));
|
||||
permanentCacheSound(Paths.sound("soundtray/VolMAX"));
|
||||
permanentCacheSound(Paths.sound("soundtray/Volup"));
|
||||
permanentCacheSound(Paths.music("freakyMenu/freakyMenu"));
|
||||
permanentCacheSound(Paths.music("offsetsLoop/offsetsLoop"));
|
||||
permanentCacheSound(Paths.music("offsetsLoop/drumsLoop"));
|
||||
permanentCacheSound(Paths.sound("missnote1", "shared"));
|
||||
permanentCacheSound(Paths.sound("missnote2", "shared"));
|
||||
permanentCacheSound(Paths.sound("missnote3", "shared"));
|
||||
permanentCacheSound(Paths.sound('cancelMenu'));
|
||||
permanentCacheSound(Paths.sound('confirmMenu'));
|
||||
permanentCacheSound(Paths.sound('screenshot'));
|
||||
permanentCacheSound(Paths.sound('scrollMenu'));
|
||||
permanentCacheSound(Paths.sound('soundtray/Voldown'));
|
||||
permanentCacheSound(Paths.sound('soundtray/VolMAX'));
|
||||
permanentCacheSound(Paths.sound('soundtray/Volup'));
|
||||
permanentCacheSound(Paths.music('freakyMenu/freakyMenu'));
|
||||
permanentCacheSound(Paths.music('offsetsLoop/offsetsLoop'));
|
||||
permanentCacheSound(Paths.music('offsetsLoop/drumsLoop'));
|
||||
permanentCacheSound(Paths.sound('missnote1', 'shared'));
|
||||
permanentCacheSound(Paths.sound('missnote2', 'shared'));
|
||||
permanentCacheSound(Paths.sound('missnote3', 'shared'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current texture and sound caches.
|
||||
* @param callGarbageCollector Whether to call the system's garbage collector after purging.
|
||||
*/
|
||||
public static inline function purgeCache(callGarbageCollector:Bool = false):Void
|
||||
{
|
||||
trace(' CLEARING CACHE '.bg_bright_lilac().bold() + ' Disposing all cached textures, assets and sounds...');
|
||||
|
||||
preparePurgeTextureCache();
|
||||
purgeTextureCache();
|
||||
preparePurgeSoundCache();
|
||||
@@ -111,16 +111,6 @@ class FunkinMemory
|
||||
|
||||
///// TEXTURES /////
|
||||
|
||||
/**
|
||||
* Determine whether the texture with the given key is cached.
|
||||
* @param key The key of the texture to check.
|
||||
* @return Whether the texture is cached.
|
||||
*/
|
||||
public static function isTextureCached(key:String):Bool
|
||||
{
|
||||
return FlxG.bitmap.get(key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a texture with the given key is cached.
|
||||
* @param key The key of the texture to cache.
|
||||
@@ -173,30 +163,6 @@ class FunkinMemory
|
||||
currentCachedTextures = permanentCachedTextures.copy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the GPU to load and upload a FlxGraphic.
|
||||
*/
|
||||
private static function forceRender(graphic:FlxGraphic):Void
|
||||
{
|
||||
if (graphic == null) return;
|
||||
|
||||
var bmp:Null<FlxGraphic> = FlxG.bitmap.get(graphic.key);
|
||||
if (bmp != null && bmp.bitmap != null) var _:Int = bmp.bitmap.width; // Trigger
|
||||
|
||||
// Draws sprite and actually caches it.
|
||||
var sprite = new flixel.FlxSprite();
|
||||
sprite.loadGraphic(graphic);
|
||||
sprite.draw(); // Draw sprite and load it into game's memory.
|
||||
graphic.bitmap?.getTexture(FlxG.stage.context3D); // Just in case that didn't work...
|
||||
sprite.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, if graphic with given path cached in memory.
|
||||
*/
|
||||
public static inline function isGraphicCached(path:String):Bool
|
||||
return permanentCachedTextures.exists(path) || currentCachedTextures.exists(path) || previousCachedTextures.exists(path);
|
||||
|
||||
public static function getCachedGraphic(path:String):Null<FlxGraphic>
|
||||
{
|
||||
if (permanentCachedTextures.exists(path)) return permanentCachedTextures.get(path);
|
||||
@@ -209,7 +175,7 @@ class FunkinMemory
|
||||
/**
|
||||
* Prepares the cache for purging unused textures.
|
||||
*/
|
||||
public inline static function preparePurgeTextureCache():Void
|
||||
public static inline function preparePurgeTextureCache():Void
|
||||
{
|
||||
previousCachedTextures = currentCachedTextures.copy();
|
||||
|
||||
@@ -237,7 +203,7 @@ class FunkinMemory
|
||||
continue;
|
||||
}
|
||||
|
||||
if (graphicKey.contains("fonts")) continue;
|
||||
if (graphicKey.contains('fonts')) continue;
|
||||
|
||||
var graphic:Null<FlxGraphic> = previousCachedTextures.get(graphicKey);
|
||||
if (graphic != null)
|
||||
@@ -261,7 +227,7 @@ class FunkinMemory
|
||||
{
|
||||
var obj:Null<FlxGraphic> = FlxG.bitmap.get(key);
|
||||
|
||||
if (obj == null || (obj.persist && permanentCachedTextures.exists(key)) || key.contains("fonts"))
|
||||
if (obj == null || (obj.persist && permanentCachedTextures.exists(key)) || key.contains('fonts'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -281,35 +247,69 @@ class FunkinMemory
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the GPU to load and upload a FlxGraphic.
|
||||
* @param graphic The graphic to force render.
|
||||
*/
|
||||
static function forceRender(graphic:FlxGraphic):Void
|
||||
{
|
||||
if (graphic == null) return;
|
||||
|
||||
var bmp:Null<FlxGraphic> = FlxG.bitmap.get(graphic.key);
|
||||
if (bmp != null && bmp.bitmap != null) var _:Int = bmp.bitmap.width; // Trigger
|
||||
|
||||
// Draws sprite and actually caches it.
|
||||
var sprite = new flixel.FlxSprite();
|
||||
sprite.loadGraphic(graphic);
|
||||
sprite.draw(); // Draw sprite and load it into game's memory.
|
||||
graphic.bitmap?.getTexture(FlxG.stage.context3D); // Just in case that didn't work...
|
||||
sprite.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the texture with the given key is cached.
|
||||
* @param key The key of the texture to check.
|
||||
* @return Whether the texture is cached.
|
||||
*/
|
||||
public static function isTextureCached(key:String):Bool
|
||||
{
|
||||
return FlxG.bitmap.get(key) != null
|
||||
&& (permanentCachedTextures.exists(key) || currentCachedTextures.exists(key) || previousCachedTextures.exists(key));
|
||||
}
|
||||
|
||||
///// NOTE STYLE //////
|
||||
|
||||
/**
|
||||
* Caches all assets for the given note style.
|
||||
* @param style The note style to cache.
|
||||
*/
|
||||
public static function cacheNoteStyle(style:NoteStyle):Void
|
||||
{
|
||||
// TODO: Texture paths should fall back to the default values.
|
||||
cacheTexture(Paths.image(style.getNoteAssetPath() ?? "note"));
|
||||
cacheTexture(style.getHoldNoteAssetPath() ?? "noteHold");
|
||||
cacheTexture(Paths.image(style.getStrumlineAssetPath() ?? "strumline"));
|
||||
cacheTexture(Paths.image(style.getSplashAssetPath() ?? "noteSplash"));
|
||||
cacheTexture(Paths.image(style.getNoteAssetPath() ?? 'note'));
|
||||
cacheTexture(style.getHoldNoteAssetPath() ?? 'noteHold');
|
||||
cacheTexture(Paths.image(style.getStrumlineAssetPath() ?? 'strumline'));
|
||||
cacheTexture(Paths.image(style.getSplashAssetPath() ?? 'noteSplash'));
|
||||
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(LEFT) ?? "LEFT"));
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(RIGHT) ?? "RIGHT"));
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(UP) ?? "UP"));
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(DOWN) ?? "DOWN"));
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(LEFT) ?? 'LEFT'));
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(RIGHT) ?? 'RIGHT'));
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(UP) ?? 'UP'));
|
||||
cacheTexture(Paths.image(style.getHoldCoverDirectionAssetPath(DOWN) ?? 'DOWN'));
|
||||
|
||||
// cacheTexture(Paths.image(style.buildCountdownSpritePath(THREE) ?? "THREE"));
|
||||
cacheTexture(Paths.image(style.buildCountdownSpritePath(TWO) ?? "TWO"));
|
||||
cacheTexture(Paths.image(style.buildCountdownSpritePath(ONE) ?? "ONE"));
|
||||
cacheTexture(Paths.image(style.buildCountdownSpritePath(GO) ?? "GO"));
|
||||
cacheTexture(Paths.image(style.buildCountdownSpritePath(TWO) ?? 'TWO'));
|
||||
cacheTexture(Paths.image(style.buildCountdownSpritePath(ONE) ?? 'ONE'));
|
||||
cacheTexture(Paths.image(style.buildCountdownSpritePath(GO) ?? 'GO'));
|
||||
|
||||
cacheSound(style.getCountdownSoundPath(THREE) ?? "THREE");
|
||||
cacheSound(style.getCountdownSoundPath(TWO) ?? "TWO");
|
||||
cacheSound(style.getCountdownSoundPath(ONE) ?? "ONE");
|
||||
cacheSound(style.getCountdownSoundPath(GO) ?? "GO");
|
||||
cacheSound(style.getCountdownSoundPath(THREE) ?? 'THREE');
|
||||
cacheSound(style.getCountdownSoundPath(TWO) ?? 'TWO');
|
||||
cacheSound(style.getCountdownSoundPath(ONE) ?? 'ONE');
|
||||
cacheSound(style.getCountdownSoundPath(GO) ?? 'GO');
|
||||
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath("sick") ?? 'sick'));
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath("good") ?? 'good'));
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath("bad") ?? 'bad'));
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath("shit") ?? 'shit'));
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath('sick') ?? 'sick'));
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath('good') ?? 'good'));
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath('bad') ?? 'bad'));
|
||||
cacheTexture(Paths.image(style.buildJudgementSpritePath('shit') ?? 'shit'));
|
||||
|
||||
cacheTexture(Paths.image(style.buildComboNumSpritePath(0) ?? '0'));
|
||||
cacheTexture(Paths.image(style.buildComboNumSpritePath(1) ?? '1'));
|
||||
@@ -325,6 +325,10 @@ class FunkinMemory
|
||||
|
||||
///// SOUND //////
|
||||
|
||||
/**
|
||||
* Caches a sound with the given key.
|
||||
* @param key The key of the sound to cache.
|
||||
*/
|
||||
public static function cacheSound(key:String):Void
|
||||
{
|
||||
if (currentCachedSounds.exists(key)) return;
|
||||
@@ -339,23 +343,40 @@ class FunkinMemory
|
||||
}
|
||||
|
||||
var sound:Null<Sound> = Assets.getSound(key, true);
|
||||
if (sound == null) return;
|
||||
if (sound == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentCachedSounds.set(key, sound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permanently caches a sound with the given key.
|
||||
* @param key The key of the sound to cache.
|
||||
*/
|
||||
public static function permanentCacheSound(key:String):Void
|
||||
{
|
||||
if (permanentCachedSounds.exists(key)) return;
|
||||
|
||||
var sound:Null<Sound> = Assets.getSound(key, true);
|
||||
if (sound == null) return;
|
||||
if (sound == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
permanentCachedSounds.set(key, sound);
|
||||
}
|
||||
|
||||
if (sound != null) currentCachedSounds.set(key, sound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the cache for purging unused sounds.
|
||||
*/
|
||||
public static function preparePurgeSoundCache():Void
|
||||
{
|
||||
previousCachedSounds = currentCachedSounds.copy();
|
||||
@@ -391,10 +412,10 @@ class FunkinMemory
|
||||
previousCachedSounds.remove(key);
|
||||
}
|
||||
}
|
||||
Assets.cache.clear("songs");
|
||||
Assets.cache.clear("music");
|
||||
Assets.cache.clear('songs');
|
||||
Assets.cache.clear('music');
|
||||
// Felt lazy.
|
||||
var key = Paths.music("freakyMenu/freakyMenu");
|
||||
var key = Paths.music('freakyMenu/freakyMenu');
|
||||
var sound:Null<Sound> = Assets.getSound(key, true);
|
||||
if (sound != null)
|
||||
{
|
||||
@@ -405,6 +426,9 @@ class FunkinMemory
|
||||
|
||||
///// MISC /////
|
||||
|
||||
/**
|
||||
* Clears all Freeplay assets from memory.
|
||||
*/
|
||||
public static inline function clearFreeplay():Void
|
||||
{
|
||||
var keysToRemove:Array<String> = [];
|
||||
@@ -412,8 +436,8 @@ class FunkinMemory
|
||||
@:privateAccess
|
||||
for (key in FlxG.bitmap._cache.keys())
|
||||
{
|
||||
if (!key.contains("freeplay")) continue;
|
||||
if (permanentCachedTextures.exists(key) || key.contains("fonts")) continue;
|
||||
if (!key.contains('freeplay')) continue;
|
||||
if (permanentCachedTextures.exists(key) || key.contains('fonts')) continue;
|
||||
|
||||
keysToRemove.push(key);
|
||||
}
|
||||
@@ -436,6 +460,9 @@ class FunkinMemory
|
||||
purgeSoundCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all sticker assets from memory.
|
||||
*/
|
||||
public static inline function clearStickers():Void
|
||||
{
|
||||
var keysToRemove:Array<String> = [];
|
||||
@@ -443,8 +470,8 @@ class FunkinMemory
|
||||
@:privateAccess
|
||||
for (key in FlxG.bitmap._cache.keys())
|
||||
{
|
||||
if (!key.contains("stickers")) continue;
|
||||
if (permanentCachedTextures.exists(key) || key.contains("fonts")) continue;
|
||||
if (!key.contains('stickers')) continue;
|
||||
if (permanentCachedTextures.exists(key) || key.contains('fonts')) continue;
|
||||
|
||||
keysToRemove.push(key);
|
||||
}
|
||||
@@ -464,6 +491,10 @@ class FunkinMemory
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a trace with fancy ANSI colors.
|
||||
* @param message The message to log.
|
||||
*/
|
||||
static function log(message:String):Void
|
||||
{
|
||||
trace(' MEMORY '.bg_bright_lilac().bold() + ' ${message}');
|
||||
|
||||
+13
-16
@@ -49,20 +49,19 @@ abstract Tallies(RawTallies)
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
this =
|
||||
{
|
||||
combo: 0,
|
||||
missed: 0,
|
||||
shit: 0,
|
||||
bad: 0,
|
||||
good: 0,
|
||||
sick: 0,
|
||||
totalNotes: 0,
|
||||
totalNotesHit: 0,
|
||||
maxCombo: 0,
|
||||
score: 0,
|
||||
isNewHighscore: false
|
||||
}
|
||||
this = {
|
||||
combo: 0,
|
||||
missed: 0,
|
||||
shit: 0,
|
||||
bad: 0,
|
||||
good: 0,
|
||||
sick: 0,
|
||||
totalNotes: 0,
|
||||
totalNotesHit: 0,
|
||||
maxCombo: 0,
|
||||
score: 0,
|
||||
isNewHighscore: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +82,7 @@ typedef RawTallies =
|
||||
var good:Int;
|
||||
var sick:Int;
|
||||
var maxCombo:Int;
|
||||
|
||||
var score:Int;
|
||||
|
||||
var isNewHighscore:Bool;
|
||||
|
||||
/**
|
||||
|
||||
+101
-74
@@ -10,7 +10,6 @@ import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.system.debug.log.LogStyle;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.graphics.FunkinSprite;
|
||||
import funkin.data.dialogue.ConversationRegistry;
|
||||
import funkin.data.dialogue.DialogueBoxRegistry;
|
||||
import funkin.data.dialogue.SpeakerRegistry;
|
||||
@@ -20,6 +19,7 @@ import funkin.data.freeplay.style.FreeplayStyleRegistry;
|
||||
import funkin.data.notestyle.NoteStyleRegistry;
|
||||
import funkin.data.song.SongRegistry;
|
||||
import funkin.data.stickers.StickerRegistry;
|
||||
import funkin.play.event.SongEventHelper;
|
||||
import funkin.data.event.SongEventRegistry;
|
||||
import funkin.data.stage.StageRegistry;
|
||||
import funkin.data.story.level.LevelRegistry;
|
||||
@@ -66,7 +66,7 @@ class InitState extends FlxState
|
||||
/**
|
||||
* Perform a bunch of game setup, then immediately transition to the title screen.
|
||||
*/
|
||||
public override function create():Void
|
||||
override public function create():Void
|
||||
{
|
||||
// Setup a bunch of important Flixel stuff.
|
||||
setupShit();
|
||||
@@ -124,6 +124,11 @@ class InitState extends FlxState
|
||||
funkin.mobile.util.WebViewUtil.init();
|
||||
#end
|
||||
|
||||
#if FEATURE_MOBILE_AGESIGNALS
|
||||
// Setup AgeSignals
|
||||
funkin.mobile.util.AgeSignalsUtil.init();
|
||||
#end
|
||||
|
||||
#if android
|
||||
// Setup Callback util.
|
||||
funkin.external.android.CallbackUtil.init();
|
||||
@@ -136,9 +141,11 @@ class InitState extends FlxState
|
||||
|
||||
#if mobile
|
||||
// Setup Mobile FNFC launcher.
|
||||
funkin.mobile.util.FNFCUtil.init();
|
||||
funkin.mobile.util.FNFCProvider.init();
|
||||
#end
|
||||
|
||||
SongEventHelper.generateEaseGraphsBitmaps();
|
||||
|
||||
// This ain't a pixel art game! (most of the time)
|
||||
FlxSprite.defaultAntialiasing = true;
|
||||
|
||||
@@ -185,7 +192,8 @@ class InitState extends FlxState
|
||||
FlxTransitionableState.defaultTransOut = new TransitionData(FADE, FlxColor.BLACK, 0.7, new FlxPoint(0, 1), tileData,
|
||||
new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
||||
|
||||
FlxG.signals.gameResized.add(function(width:Int, height:Int) {
|
||||
FlxG.signals.gameResized.add(function(width:Int, height:Int)
|
||||
{
|
||||
FlxTransitionableState.defaultTransIn = new TransitionData(FADE, FlxColor.BLACK, 1, new FlxPoint(0, -1), tileData,
|
||||
new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
||||
FlxTransitionableState.defaultTransOut = new TransitionData(FADE, FlxColor.BLACK, 0.7, new FlxPoint(0, 1), tileData,
|
||||
@@ -196,10 +204,12 @@ class InitState extends FlxState
|
||||
// Since we don't really need VSync on Android we're gonna forcefully disable it on these signals for now
|
||||
// This is fixed on SDL3 from what I've heared but that doodoo isn't working poperly for Android
|
||||
#if android
|
||||
FlxG.signals.focusLost.add(function() {
|
||||
FlxG.signals.focusLost.add(function()
|
||||
{
|
||||
WindowUtil.setVSyncMode(lime.ui.WindowVSyncMode.OFF);
|
||||
});
|
||||
FlxG.signals.focusGained.add(function() {
|
||||
FlxG.signals.focusGained.add(function()
|
||||
{
|
||||
WindowUtil.setVSyncMode(lime.ui.WindowVSyncMode.OFF);
|
||||
});
|
||||
#end
|
||||
@@ -215,9 +225,13 @@ class InitState extends FlxState
|
||||
// DISCORD API SETUP
|
||||
//
|
||||
#if FEATURE_DISCORD_RPC
|
||||
DiscordClient.instance.init();
|
||||
if (Preferences.enabledDiscordRPC)
|
||||
{
|
||||
DiscordClient.instance.init();
|
||||
}
|
||||
|
||||
lime.app.Application.current.onExit.add(function(exitCode) {
|
||||
lime.app.Application.current.onExit.add(function(exitCode)
|
||||
{
|
||||
DiscordClient.instance.shutdown();
|
||||
});
|
||||
#end
|
||||
@@ -230,7 +244,9 @@ class InitState extends FlxState
|
||||
// ANDROID SETUP
|
||||
//
|
||||
#if android
|
||||
FlxG.android.preventDefaultKeys = [flixel.input.android.FlxAndroidKey.BACK];
|
||||
FlxG.android.preventDefaultKeys = [
|
||||
flixel.input.android.FlxAndroidKey.BACK
|
||||
];
|
||||
#end
|
||||
|
||||
//
|
||||
@@ -302,22 +318,38 @@ class InitState extends FlxState
|
||||
}
|
||||
|
||||
#if FEATURE_LOST_FOCUS_VOLUME
|
||||
@:noCompletion var _lastFocusVolume:Null<Float>;
|
||||
@:noCompletion
|
||||
var _lastFocusVolume:Null<Float>;
|
||||
|
||||
function onLostFocus()
|
||||
function onLostFocus():Void
|
||||
{
|
||||
if (FlxG.sound.muted || FlxG.sound.volume == 0 || FlxG.autoPause) return;
|
||||
_lastFocusVolume = FlxG.sound.volume;
|
||||
FlxG.sound.volume *= Constants.LOST_FOCUS_VOLUME_MULTIPLIER;
|
||||
}
|
||||
|
||||
function onGainFocus()
|
||||
{
|
||||
if (FlxG.sound.muted || FlxG.autoPause) return;
|
||||
if (_lastFocusVolume != null) FlxG.sound.volume = _lastFocusVolume;
|
||||
}
|
||||
#end
|
||||
|
||||
function onGainFocus():Void
|
||||
{
|
||||
#if !mobile
|
||||
if (Preferences.unlockedFramerate)
|
||||
{
|
||||
FlxG.updateFramerate = 0;
|
||||
FlxG.drawFramerate = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.updateFramerate = Preferences.framerate;
|
||||
FlxG.drawFramerate = Preferences.framerate;
|
||||
}
|
||||
#end
|
||||
|
||||
#if FEATURE_LOST_FOCUS_VOLUME
|
||||
if (FlxG.sound.muted || FlxG.sound.volume == 0 || FlxG.autoPause) return;
|
||||
if (_lastFocusVolume != null) FlxG.sound.volume = _lastFocusVolume;
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the game.
|
||||
*
|
||||
@@ -359,37 +391,34 @@ class InitState extends FlxState
|
||||
FlxG.switchState(() -> new funkin.ui.debug.stage.StageBuilderState());
|
||||
#elseif RESULTS
|
||||
// -DRESULTS
|
||||
FlxG.switchState(() -> new funkin.play.ResultState(
|
||||
{
|
||||
storyMode: true,
|
||||
title: "Cum Song Erect by Kawai Sprite",
|
||||
songId: "cum",
|
||||
characterId: "pico",
|
||||
difficultyId: "hard",
|
||||
isNewHighscore: true,
|
||||
scoreData:
|
||||
{
|
||||
score: 1_234_567,
|
||||
tallies:
|
||||
{
|
||||
sick: 130,
|
||||
good: 60,
|
||||
bad: 69,
|
||||
shit: 69,
|
||||
missed: 69,
|
||||
combo: 69,
|
||||
maxCombo: 69,
|
||||
totalNotesHit: 140,
|
||||
totalNotes: 240
|
||||
}
|
||||
// 2400 total notes = 7% = LOSS
|
||||
// 275 total notes = 69% = NICE
|
||||
// 240 total notes = 79% = GOOD
|
||||
// 230 total notes = 82% = GREAT
|
||||
// 210 total notes = 91% = EXCELLENT
|
||||
// 190 total notes = PERFECT
|
||||
},
|
||||
}));
|
||||
FlxG.switchState(() -> new funkin.play.ResultState({
|
||||
storyMode: true,
|
||||
title: 'Cum Song Erect by Kawai Sprite',
|
||||
songId: 'cum',
|
||||
characterId: 'pico',
|
||||
difficultyId: 'hard',
|
||||
isNewHighscore: true,
|
||||
scoreData: {
|
||||
score: 1_234_567,
|
||||
tallies: {
|
||||
sick: 130,
|
||||
good: 60,
|
||||
bad: 69,
|
||||
shit: 69,
|
||||
missed: 69,
|
||||
combo: 69,
|
||||
maxCombo: 69,
|
||||
totalNotesHit: 140,
|
||||
totalNotes: 240
|
||||
}
|
||||
// 2400 total notes = 7% = LOSS
|
||||
// 275 total notes = 69% = NICE
|
||||
// 240 total notes = 79% = GOOD
|
||||
// 230 total notes = 82% = GREAT
|
||||
// 210 total notes = 91% = EXCELLENT
|
||||
// 190 total notes = PERFECT
|
||||
},
|
||||
}));
|
||||
#elseif ANIMDEBUG
|
||||
// -DANIMDEBUG
|
||||
FlxG.switchState(() -> new funkin.ui.debug.anim.DebugBoundingState());
|
||||
@@ -407,15 +436,13 @@ class InitState extends FlxState
|
||||
function startGameNormally():Void
|
||||
{
|
||||
var params:CLIParams = CLIUtil.processArgs();
|
||||
trace('Command line args: ${params}');
|
||||
|
||||
if (params.chart.shouldLoadChart)
|
||||
{
|
||||
#if FEATURE_CHART_EDITOR
|
||||
FlxG.switchState(() -> new ChartEditorState(
|
||||
{
|
||||
fnfcTargetPath: params.chart.chartPath,
|
||||
}));
|
||||
FlxG.switchState(() -> new ChartEditorState({
|
||||
fnfcTargetPath: params.chart.chartPath,
|
||||
}));
|
||||
#else
|
||||
FlxG.switchState(() -> new TitleState());
|
||||
#end
|
||||
@@ -423,10 +450,9 @@ class InitState extends FlxState
|
||||
else if (params.stage.shouldLoadStage)
|
||||
{
|
||||
#if FEATURE_STAGE_EDITOR
|
||||
FlxG.switchState(() -> new StageEditorState(
|
||||
{
|
||||
fnfsTargetPath: params.stage.stagePath,
|
||||
}));
|
||||
FlxG.switchState(() -> new StageEditorState({
|
||||
fnfsTargetPath: params.stage.stagePath,
|
||||
}));
|
||||
#else
|
||||
FlxG.switchState(() -> new TitleState());
|
||||
#end
|
||||
@@ -441,9 +467,9 @@ class InitState extends FlxState
|
||||
}
|
||||
else
|
||||
{
|
||||
// FlxG.sound.cache(Paths.music('freakyMenu/freakyMenu'));
|
||||
#if mobile
|
||||
funkin.mobile.util.FNFCUtil.onFNFCOpen.add(function(fnfcFile:String) {
|
||||
funkin.mobile.util.FNFCProvider.onFNFCOpen.add(function(fnfcFile:String)
|
||||
{
|
||||
flixel.tweens.FlxTween.globalManager.clear();
|
||||
flixel.util.FlxTimer.globalManager.clear();
|
||||
@:nullSafety(Off)
|
||||
@@ -456,7 +482,7 @@ class InitState extends FlxState
|
||||
FlxG.switchState(() -> new ChartPlaytestMenu(fnfcFile));
|
||||
});
|
||||
|
||||
final fnfcFile = funkin.mobile.util.FNFCUtil.queryFNFC();
|
||||
final fnfcFile = funkin.mobile.util.FNFCProvider.queryFNFC();
|
||||
if (fnfcFile != null)
|
||||
{
|
||||
trace('launching FNFC from $fnfcFile');
|
||||
@@ -517,11 +543,10 @@ class InitState extends FlxState
|
||||
}
|
||||
|
||||
@:nullSafety(Off) // Cannot unify?
|
||||
LoadingState.loadPlayState(
|
||||
{
|
||||
targetSong: songData,
|
||||
targetDifficulty: difficultyId,
|
||||
});
|
||||
LoadingState.loadPlayState({
|
||||
targetSong: songData,
|
||||
targetDifficulty: difficultyId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,11 +585,10 @@ class InitState extends FlxState
|
||||
}
|
||||
|
||||
@:nullSafety(Off)
|
||||
LoadingState.loadPlayState(
|
||||
{
|
||||
targetSong: targetSong,
|
||||
targetDifficulty: difficultyId,
|
||||
});
|
||||
LoadingState.loadPlayState({
|
||||
targetSong: targetSong,
|
||||
targetDifficulty: difficultyId,
|
||||
});
|
||||
}
|
||||
|
||||
@:nullSafety(Off) // Meh, remove when flixel.system.debug.log.LogStyle is null safe
|
||||
@@ -573,7 +597,7 @@ class InitState extends FlxState
|
||||
//
|
||||
// FLIXEL DEBUG SETUP
|
||||
//
|
||||
#if FEATURE_DEBUG_FUNCTIONS
|
||||
#if (FEATURE_DEBUG_FUNCTIONS && !FLX_NO_DEBUG)
|
||||
trace('Initializing Flixel debugger...');
|
||||
|
||||
#if !debug
|
||||
@@ -592,7 +616,8 @@ class InitState extends FlxState
|
||||
|
||||
// Adds a red button to the debugger.
|
||||
// This pauses the game AND the music! This ensures the Conductor stops.
|
||||
FlxG.debugger.addButton(CENTER, new BitmapData(20, 20, true, 0xFFCC2233), function() {
|
||||
FlxG.debugger.addButton(CENTER, new BitmapData(20, 20, true, 0xFFCC2233), function()
|
||||
{
|
||||
if (FlxG.vcr.paused)
|
||||
{
|
||||
FlxG.vcr.resume();
|
||||
@@ -619,7 +644,8 @@ class InitState extends FlxState
|
||||
|
||||
// Adds a blue button to the debugger.
|
||||
// This skips forward in the song.
|
||||
FlxG.debugger.addButton(CENTER, new BitmapData(20, 20, true, 0xFF2222CC), function() {
|
||||
FlxG.debugger.addButton(CENTER, new BitmapData(20, 20, true, 0xFF2222CC), function()
|
||||
{
|
||||
FlxG.game.debugger.vcr.onStep();
|
||||
|
||||
for (snd in FlxG.sound.list)
|
||||
@@ -636,7 +662,8 @@ class InitState extends FlxState
|
||||
// This big obnoxious white button is for MOBILE, so that you can press it
|
||||
// easily with your finger when debug bullshit pops up during testing lol!
|
||||
#if mobile
|
||||
FlxG.debugger.addButton(LEFT, new BitmapData(200, 200), function() {
|
||||
FlxG.debugger.addButton(LEFT, new BitmapData(200, 200), function()
|
||||
{
|
||||
FlxG.debugger.visible = false;
|
||||
|
||||
// Make errors and warnings less annoying.
|
||||
|
||||
+20
-21
@@ -107,7 +107,7 @@ class Paths implements ConsoleClass
|
||||
return getPath('data/$key.json', TEXT, library);
|
||||
}
|
||||
|
||||
public static function srt(key:String, ?library:String, ?directory:String = "data/"):String
|
||||
public static function srt(key:String, ?library:String, ?directory:String = 'data/'):String
|
||||
{
|
||||
return getPath('$directory$key.srt', TEXT, library);
|
||||
}
|
||||
@@ -181,10 +181,10 @@ class Paths implements ConsoleClass
|
||||
|
||||
public static function getAnimateAtlas(key:String, ?library:String, settings:AtlasSpriteSettings):FlxAnimateFrames
|
||||
{
|
||||
var assetLibrary:String = library ?? "";
|
||||
var graphicKey:String = "";
|
||||
var assetLibrary:String = library ?? '';
|
||||
var graphicKey:String = '';
|
||||
|
||||
if (assetLibrary != "")
|
||||
if (assetLibrary != '')
|
||||
{
|
||||
graphicKey = Paths.animateAtlas(key, assetLibrary);
|
||||
}
|
||||
@@ -193,19 +193,18 @@ class Paths implements ConsoleClass
|
||||
graphicKey = Paths.animateAtlas(key);
|
||||
}
|
||||
|
||||
var validatedSettings:AtlasSpriteSettings =
|
||||
{
|
||||
swfMode: settings?.swfMode ?? false,
|
||||
cacheOnLoad: settings?.cacheOnLoad ?? false,
|
||||
filterQuality: settings?.filterQuality ?? MEDIUM,
|
||||
spritemaps: settings?.spritemaps ?? null,
|
||||
metadataJson: settings?.metadataJson ?? null,
|
||||
cacheKey: settings?.cacheKey ?? null,
|
||||
uniqueInCache: settings?.uniqueInCache ?? false,
|
||||
onSymbolCreate: settings?.onSymbolCreate ?? null,
|
||||
applyStageMatrix: settings?.applyStageMatrix ?? false,
|
||||
useRenderTexture: settings?.useRenderTexture ?? false
|
||||
};
|
||||
var validatedSettings:AtlasSpriteSettings = {
|
||||
swfMode: settings?.swfMode ?? false,
|
||||
cacheOnLoad: settings?.cacheOnLoad ?? false,
|
||||
filterQuality: settings?.filterQuality ?? MEDIUM,
|
||||
spritemaps: settings?.spritemaps ?? null,
|
||||
metadataJson: settings?.metadataJson ?? null,
|
||||
cacheKey: settings?.cacheKey ?? null,
|
||||
uniqueInCache: settings?.uniqueInCache ?? false,
|
||||
onSymbolCreate: settings?.onSymbolCreate ?? null,
|
||||
applyStageMatrix: settings?.applyStageMatrix ?? false,
|
||||
useRenderTexture: settings?.useRenderTexture ?? false
|
||||
};
|
||||
|
||||
// Validate asset path.
|
||||
if (!Assets.exists('${graphicKey}/Animation.json'))
|
||||
@@ -230,8 +229,8 @@ class Paths implements ConsoleClass
|
||||
|
||||
enum abstract PathsFunction(String)
|
||||
{
|
||||
var MUSIC;
|
||||
var INST;
|
||||
var VOICES;
|
||||
var SOUND;
|
||||
public var MUSIC;
|
||||
public var INST;
|
||||
public var VOICES;
|
||||
public var SOUND;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ class PlayerSettings
|
||||
public static var player1(default, null):PlayerSettings;
|
||||
@:nullSafety(Off)
|
||||
public static var player2(default, null):PlayerSettings;
|
||||
|
||||
public static var onAvatarAdd(default, null) = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
public static var onAvatarRemove(default, null) = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
|
||||
@@ -45,9 +44,12 @@ class PlayerSettings
|
||||
{
|
||||
return switch (id)
|
||||
{
|
||||
case 1: player1;
|
||||
case 2: player2;
|
||||
default: null;
|
||||
case 1:
|
||||
player1;
|
||||
case 2:
|
||||
player2;
|
||||
default:
|
||||
null;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -98,7 +100,7 @@ class PlayerSettings
|
||||
*/
|
||||
function new(id:Int)
|
||||
{
|
||||
trace('loading player settings for id: $id');
|
||||
trace('Loading player settings for id: $id');
|
||||
|
||||
this.id = id;
|
||||
this.controls = new Controls('player$id', None);
|
||||
|
||||
+100
-45
@@ -8,6 +8,9 @@ import funkin.save.Save;
|
||||
import funkin.util.WindowUtil;
|
||||
import funkin.util.HapticUtil.HapticsMode;
|
||||
import funkin.ui.debug.FunkinDebugDisplay.DebugDisplayMode;
|
||||
#if FEATURE_DISCORD_RPC
|
||||
import funkin.api.discord.DiscordClient;
|
||||
#end
|
||||
|
||||
/**
|
||||
* A core class which provides a store of user-configurable, globally relevant values.
|
||||
@@ -41,12 +44,23 @@ class Preferences
|
||||
{
|
||||
#if web
|
||||
return 60;
|
||||
#elseif mobile
|
||||
var refreshRate:Int = FlxG.stage.window.displayMode.refreshRate;
|
||||
|
||||
if (refreshRate < 60) refreshRate = 60;
|
||||
|
||||
return refreshRate;
|
||||
#else
|
||||
var save:Save = Save.instance;
|
||||
save.options.framerate = value;
|
||||
Save.system.flush();
|
||||
FlxG.updateFramerate = value;
|
||||
FlxG.drawFramerate = value;
|
||||
|
||||
if (!unlockedFramerate)
|
||||
{
|
||||
FlxG.updateFramerate = value;
|
||||
FlxG.drawFramerate = value;
|
||||
}
|
||||
|
||||
return value;
|
||||
#end
|
||||
}
|
||||
@@ -69,13 +83,13 @@ class Preferences
|
||||
static function set_naughtyness(value:Bool):Bool
|
||||
{
|
||||
#if NO_FEATURE_NAUGHTYNESS
|
||||
value = false;
|
||||
#end
|
||||
|
||||
return false;
|
||||
#else
|
||||
var save:Save = Save.instance;
|
||||
save.options.naughtyness = value;
|
||||
Save.system.flush();
|
||||
return value;
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,19 +160,23 @@ class Preferences
|
||||
{
|
||||
#if NO_FEATURE_DEBUG_DISPLAY
|
||||
return DebugDisplayMode.Off;
|
||||
#end
|
||||
|
||||
#else
|
||||
return Save?.instance?.options?.debugDisplay ?? 'Off';
|
||||
#end
|
||||
}
|
||||
|
||||
static function set_debugDisplay(value:DebugDisplayMode):DebugDisplayMode
|
||||
{
|
||||
#if NO_FEATURE_DEBUG_DISPLAY
|
||||
return DebugDisplayMode.Off;
|
||||
#else
|
||||
if (value != Save.instance.options.debugDisplay) setDebugDisplayMode(value);
|
||||
|
||||
var save = Save.instance;
|
||||
save.options.debugDisplay = value;
|
||||
Save.system.flush();
|
||||
return value;
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,13 +208,13 @@ class Preferences
|
||||
|
||||
static function get_hapticsMode():HapticsMode
|
||||
{
|
||||
var value = Save?.instance?.options?.hapticsMode ?? "All";
|
||||
var value = Save?.instance?.options?.hapticsMode ?? 'All';
|
||||
|
||||
return switch (value)
|
||||
{
|
||||
case "None":
|
||||
case 'None':
|
||||
HapticsMode.NONE;
|
||||
case "Notes Only":
|
||||
case 'Notes Only':
|
||||
HapticsMode.NOTES_ONLY;
|
||||
default:
|
||||
HapticsMode.ALL;
|
||||
@@ -210,11 +228,11 @@ class Preferences
|
||||
switch (value)
|
||||
{
|
||||
case HapticsMode.NONE:
|
||||
string = "None";
|
||||
string = 'None';
|
||||
case HapticsMode.NOTES_ONLY:
|
||||
string = "Notes Only";
|
||||
string = 'Notes Only';
|
||||
default:
|
||||
string = "All";
|
||||
string = 'All';
|
||||
};
|
||||
|
||||
var save:Save = Save.instance;
|
||||
@@ -253,18 +271,23 @@ class Preferences
|
||||
{
|
||||
#if mobile
|
||||
return false;
|
||||
#end
|
||||
#else
|
||||
return Save?.instance?.options?.autoPause ?? true;
|
||||
#end
|
||||
}
|
||||
|
||||
static function set_autoPause(value:Bool):Bool
|
||||
{
|
||||
#if mobile
|
||||
return false;
|
||||
#else
|
||||
if (value != Save.instance.options.autoPause) FlxG.autoPause = value;
|
||||
|
||||
var save:Save = Save.instance;
|
||||
save.options.autoPause = value;
|
||||
Save.system.flush();
|
||||
return value;
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,35 +337,42 @@ class Preferences
|
||||
|
||||
static function get_vsyncMode():lime.ui.WindowVSyncMode
|
||||
{
|
||||
var value = Save?.instance?.options?.vsyncMode ?? "Off";
|
||||
#if (mobile || web)
|
||||
return lime.ui.WindowVSyncMode.OFF;
|
||||
#else
|
||||
var value = Save?.instance?.options?.vsyncMode ?? 'Off';
|
||||
|
||||
return switch (value)
|
||||
{
|
||||
case "Off":
|
||||
case 'Off':
|
||||
lime.ui.WindowVSyncMode.OFF;
|
||||
case "On":
|
||||
case 'On':
|
||||
lime.ui.WindowVSyncMode.ON;
|
||||
case "Adaptive":
|
||||
case 'Adaptive':
|
||||
lime.ui.WindowVSyncMode.ADAPTIVE;
|
||||
default:
|
||||
lime.ui.WindowVSyncMode.OFF;
|
||||
};
|
||||
#end
|
||||
}
|
||||
|
||||
static function set_vsyncMode(value:lime.ui.WindowVSyncMode):lime.ui.WindowVSyncMode
|
||||
{
|
||||
#if (mobile || web)
|
||||
return lime.ui.WindowVSyncMode.OFF;
|
||||
#else
|
||||
var string;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case lime.ui.WindowVSyncMode.OFF:
|
||||
string = "Off";
|
||||
string = 'Off';
|
||||
case lime.ui.WindowVSyncMode.ON:
|
||||
string = "On";
|
||||
string = 'On';
|
||||
case lime.ui.WindowVSyncMode.ADAPTIVE:
|
||||
string = "Adaptive";
|
||||
string = 'Adaptive';
|
||||
default:
|
||||
string = "Off";
|
||||
string = 'Off';
|
||||
};
|
||||
|
||||
WindowUtil.setVSyncMode(value);
|
||||
@@ -351,48 +381,75 @@ class Preferences
|
||||
save.options.vsyncMode = string;
|
||||
Save.system.flush();
|
||||
return value;
|
||||
#end
|
||||
}
|
||||
|
||||
public static var unlockedFramerate(get, set):Bool;
|
||||
|
||||
static function get_unlockedFramerate():Bool
|
||||
{
|
||||
#if (mobile || web)
|
||||
return false;
|
||||
#else
|
||||
return Save?.instance?.options?.unlockedFramerate ?? false;
|
||||
#end
|
||||
}
|
||||
|
||||
static function set_unlockedFramerate(value:Bool):Bool
|
||||
{
|
||||
#if (mobile || web)
|
||||
return false;
|
||||
#else
|
||||
if (value != Save.instance.options.unlockedFramerate)
|
||||
{
|
||||
#if web
|
||||
toggleFramerateCap(value);
|
||||
#end
|
||||
}
|
||||
|
||||
var save:Save = Save.instance;
|
||||
save.options.unlockedFramerate = value;
|
||||
Save.system.flush();
|
||||
return value;
|
||||
#end
|
||||
}
|
||||
|
||||
#if web
|
||||
// We create a haxe version of this just for readability.
|
||||
// We use these to override `window.requestAnimationFrame` in Javascript to uncap the framerate / "animation" request rate
|
||||
// Javascript is crazy since u can just do stuff like that lol
|
||||
public static var enabledDiscordRPC(get, set):Bool;
|
||||
|
||||
public static function unlockedFramerateFunction(callback, element)
|
||||
static function get_enabledDiscordRPC():Bool
|
||||
{
|
||||
var currTime = Date.now().getTime();
|
||||
var timeToCall = 0;
|
||||
var id = js.Browser.window.setTimeout(function() {
|
||||
callback(currTime + timeToCall);
|
||||
}, timeToCall);
|
||||
return id;
|
||||
return Save?.instance?.options?.enabledDiscordRPC ?? true;
|
||||
}
|
||||
|
||||
// Lime already implements their own little framerate cap, so we can just use that
|
||||
// This also gets set in the init function in Main.hx, since we need to definitely override it
|
||||
public static var lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
|
||||
static function set_enabledDiscordRPC(value:Bool):Bool
|
||||
{
|
||||
#if FEATURE_DISCORD_RPC
|
||||
toggleDiscordRPC(value);
|
||||
#end
|
||||
|
||||
var save:Save = Save.instance;
|
||||
save.options.enabledDiscordRPC = value;
|
||||
Save.system.flush();
|
||||
return value;
|
||||
}
|
||||
|
||||
#if FEATURE_DISCORD_RPC
|
||||
public static function toggleDiscordRPC(enable:Bool)
|
||||
{
|
||||
if (DiscordClient.instance == null) return;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
DiscordClient.instance.init();
|
||||
|
||||
if (DiscordClient.presenceParamsCache != null)
|
||||
{
|
||||
DiscordClient.instance.setPresence(DiscordClient.presenceParamsCache);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DiscordClient.instance.shutdown();
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
@@ -484,9 +541,7 @@ class Preferences
|
||||
setDebugDisplayMode(Preferences.debugDisplay);
|
||||
setDebugDisplayBGOpacity(Preferences.debugDisplayBGOpacity / 100);
|
||||
|
||||
#if web
|
||||
toggleFramerateCap(Preferences.unlockedFramerate);
|
||||
#end
|
||||
|
||||
#if mobile
|
||||
// Apply the allowScreenTimeout setting.
|
||||
@@ -496,21 +551,21 @@ class Preferences
|
||||
|
||||
static function toggleFramerateCap(unlocked:Bool):Void
|
||||
{
|
||||
#if web
|
||||
var framerateFunction = unlocked ? unlockedFramerateFunction : lockedFramerateFunction;
|
||||
untyped js.Syntax.code("window.requestAnimationFrame = framerateFunction;");
|
||||
#if !(mobile || web)
|
||||
FlxG.drawFramerate = unlocked ? 0 : framerate;
|
||||
FlxG.updateFramerate = unlocked ? 0 : framerate;
|
||||
#end
|
||||
}
|
||||
|
||||
public static function setDebugDisplayMode(mode:DebugDisplayMode):Void
|
||||
{
|
||||
if (FlxG.game.parent.contains(Main.debugDisplay)) FlxG.game.parent.removeChild(Main.debugDisplay);
|
||||
if (FlxG.game.contains(Main.debugDisplay)) FlxG.game.removeChild(Main.debugDisplay);
|
||||
|
||||
if (mode == DebugDisplayMode.Off) return;
|
||||
|
||||
Main.debugDisplay.isAdvanced = (mode == DebugDisplayMode.Advanced);
|
||||
|
||||
FlxG.game.parent.addChild(Main.debugDisplay);
|
||||
FlxG.game.addChild(Main.debugDisplay);
|
||||
}
|
||||
|
||||
static function setDebugDisplayBGOpacity(value:Float):Void
|
||||
|
||||
@@ -8,25 +8,36 @@ import hxdiscord_rpc.Types.DiscordRichPresence;
|
||||
import hxdiscord_rpc.Types.DiscordUser;
|
||||
import sys.thread.Thread;
|
||||
|
||||
@:build(funkin.util.macro.EnvironmentMacro.build())
|
||||
@:nullSafety
|
||||
/**
|
||||
* Handles integration with the Discord Rich Presence API.
|
||||
*/
|
||||
@:build(funkin.util.macro.EnvironmentMacro.build()) @:nullSafety
|
||||
class DiscordClient
|
||||
{
|
||||
@:envField
|
||||
static final DISCORD_CLIENT_ID:Null<String>;
|
||||
|
||||
/**
|
||||
* The current instance of the singleton Discord client.
|
||||
*/
|
||||
public static var instance(get, never):DiscordClient;
|
||||
|
||||
static var _instance:Null<DiscordClient> = null;
|
||||
|
||||
static function get_instance():DiscordClient
|
||||
{
|
||||
if (DiscordClient._instance == null) _instance = new DiscordClient();
|
||||
if (DiscordClient._instance == null) throw "Could not initialize singleton DiscordClient!";
|
||||
if (DiscordClient._instance == null) throw 'Could not initialize singleton DiscordClient!';
|
||||
return DiscordClient._instance;
|
||||
}
|
||||
|
||||
var handlers:DiscordEventHandlers;
|
||||
|
||||
/**
|
||||
* Latest passed parameters for the presence.
|
||||
*/
|
||||
public static var presenceParamsCache:Null<DiscordClientPresenceParams>;
|
||||
|
||||
private function new()
|
||||
{
|
||||
trace(' DISCORD '.bold().bg_blue() + ' Initializing event handlers...');
|
||||
@@ -44,13 +55,13 @@ class DiscordClient
|
||||
|
||||
if (!hasValidCredentials())
|
||||
{
|
||||
FlxG.log.warn("Tried to initialize Discord connection, but credentials are invalid!");
|
||||
FlxG.log.warn('Tried to initialize Discord connection, but credentials are invalid!');
|
||||
return;
|
||||
}
|
||||
|
||||
@:nullSafety(Off)
|
||||
{
|
||||
Discord.Initialize(DISCORD_CLIENT_ID, cpp.RawPointer.addressOf(handlers), false, "");
|
||||
Discord.Initialize(DISCORD_CLIENT_ID, cpp.RawPointer.addressOf(handlers), false, '');
|
||||
}
|
||||
|
||||
createDaemon();
|
||||
@@ -61,7 +72,7 @@ class DiscordClient
|
||||
*/
|
||||
static function hasValidCredentials():Bool
|
||||
{
|
||||
return !(DISCORD_CLIENT_ID == null || DISCORD_CLIENT_ID == "" || (DISCORD_CLIENT_ID != null && DISCORD_CLIENT_ID.contains(" ")));
|
||||
return !(DISCORD_CLIENT_ID == null || DISCORD_CLIENT_ID == '' || (DISCORD_CLIENT_ID != null && DISCORD_CLIENT_ID.contains(' ')));
|
||||
}
|
||||
|
||||
var daemon:Null<Thread> = null;
|
||||
@@ -93,6 +104,8 @@ class DiscordClient
|
||||
|
||||
public function setPresence(params:DiscordClientPresenceParams):Void
|
||||
{
|
||||
presenceParamsCache = params;
|
||||
|
||||
var presence:DiscordRichPresence = new DiscordRichPresence();
|
||||
|
||||
// Presence should always be playing the game.
|
||||
@@ -102,35 +115,33 @@ class DiscordClient
|
||||
presence.largeImageText = "Friday Night Funkin'";
|
||||
|
||||
// State should be generally what the person is doing, like "In the Menus" or "Pico (Pico Mix) [Freeplay Hard]"
|
||||
presence.state = cast(params.state, Null<String>) ?? "";
|
||||
presence.state = cast(params.state, Null<String>) ?? '';
|
||||
// Details should be what the person is specifically doing, including stuff like timestamps (maybe something like "03:24 elapsed").
|
||||
presence.details = cast(params.details, Null<String>) ?? "";
|
||||
presence.details = cast(params.details, Null<String>) ?? '';
|
||||
|
||||
// The large image displaying what the user is doing.
|
||||
// This should probably be album art.
|
||||
// IMPORTANT NOTE: This can be an asset key uploaded to Discord's developer panel OR any URL you like.
|
||||
presence.largeImageKey = cast(params.largeImageKey, Null<String>) ?? "album-volume1";
|
||||
presence.largeImageKey = cast(params.largeImageKey, Null<String>) ?? 'album-volume1';
|
||||
|
||||
// TODO: Make this use the song's album art.
|
||||
// presence.largeImageKey = "icon";
|
||||
// presence.largeImageKey = "https://f4.bcbits.com/img/a0746694746_16.jpg";
|
||||
|
||||
// The small inset image for what the user is doing.
|
||||
// This can be the opponent's health icon?
|
||||
// NOTE: Like largeImageKey, this can be a URL, or an asset key.
|
||||
presence.smallImageKey = cast(params.smallImageKey, Null<String>) ?? "";
|
||||
presence.smallImageKey = cast(params.smallImageKey, Null<String>) ?? '';
|
||||
|
||||
// NOTE: In previous versions, this showed as "Elapsed", but now shows as playtime and doesn't look good
|
||||
// presence.startTimestamp = time - 10;
|
||||
// presence.endTimestamp = time + 30;
|
||||
|
||||
final button1:DiscordButton = new DiscordButton();
|
||||
button1.label = "Play on Web";
|
||||
button1.label = 'Play on Web';
|
||||
button1.url = Constants.URL_NEWGROUNDS;
|
||||
presence.buttons[0] = button1;
|
||||
|
||||
final button2:DiscordButton = new DiscordButton();
|
||||
button2.label = "Download";
|
||||
button2.label = 'Download';
|
||||
button2.url = Constants.URL_ITCH;
|
||||
presence.buttons[1] = button2;
|
||||
|
||||
@@ -138,6 +149,7 @@ class DiscordClient
|
||||
}
|
||||
|
||||
// TODO: WHAT THE FUCK get this pointer bullfuckery out of here
|
||||
|
||||
private static function onReady(request:cpp.RawConstPointer<DiscordUser>):Void
|
||||
{
|
||||
trace(' DISCORD '.bold().bg_blue() + ' Client has connected!');
|
||||
@@ -166,17 +178,6 @@ class DiscordClient
|
||||
trace(' DISCORD '.bold().bg_blue() + ' Client has received an error! ($errorCode) "${cast (message, String)}"');
|
||||
}
|
||||
|
||||
// public var type(get, set):DiscordActivityType;
|
||||
// public var state(get, set):String;
|
||||
// public var details(get, set):String;
|
||||
// public var startTimestamp(get, set):Int;
|
||||
// public var endTimestamp(get, set):Int;
|
||||
// public var largeImageKey(get, set):String;
|
||||
// public var largeImageText(get, set):String;
|
||||
// public var smallImageKey(get, set):String;
|
||||
// public var smallImageText(get, set):String;
|
||||
//
|
||||
//
|
||||
// public var partyId(get, set)
|
||||
// public var partySize(get, set)
|
||||
// public var partyMax(get, set)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user