mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
Compare commits
1102 commits
4.5-stable
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7864ac8019 | ||
![]() |
816ec99355 | ||
![]() |
acdb8667b5 | ||
![]() |
540ea0b96c | ||
![]() |
6ae1caecaf | ||
![]() |
8aebfb7776 | ||
![]() |
4a7ca086a3 | ||
![]() |
fd8ddca49a | ||
![]() |
fc985d7769 | ||
![]() |
d5942cf5fd | ||
![]() |
6733345f73 | ||
![]() |
7613123048 | ||
![]() |
8f1b411556 | ||
![]() |
60710df3b6 | ||
![]() |
769505fef3 | ||
![]() |
94818a5313 | ||
![]() |
026efbb0f5 | ||
![]() |
f3ebee1f79 | ||
![]() |
9e96c7d9b8 | ||
![]() |
2edad6860a | ||
![]() |
13404515fb | ||
![]() |
af584b1ba8 | ||
![]() |
d739700178 | ||
![]() |
73afe696d2 | ||
![]() |
20430236e7 | ||
![]() |
49219de402 | ||
![]() |
1ae616d7d8 | ||
![]() |
ca524532e6 | ||
![]() |
57e041d357 | ||
![]() |
71031e4adb | ||
![]() |
710a6e0303 | ||
![]() |
a281e91c5a | ||
![]() |
1f7e7de82b | ||
![]() |
b49aea89d0 | ||
![]() |
1e8fd575a9 | ||
![]() |
36b92128b1 | ||
![]() |
80ce18918e | ||
![]() |
1e9d0ff925 | ||
![]() |
a364d6ad75 | ||
![]() |
68b897225e | ||
![]() |
a63dd0704f | ||
![]() |
8a8bd02860 | ||
![]() |
ad74ed68c1 | ||
![]() |
0400b703e4 | ||
![]() |
9cdf3ff3ff | ||
![]() |
0b47123768 | ||
![]() |
9554c2bc56 | ||
![]() |
4d3a899c64 | ||
![]() |
920552812e | ||
![]() |
9659dc13bd | ||
![]() |
b7bbdfd31c | ||
![]() |
79e533679c | ||
![]() |
e6768b5db4 | ||
![]() |
c2720efb28 | ||
![]() |
879d4439e7 | ||
![]() |
c17e76572d | ||
![]() |
66e5bce653 | ||
![]() |
b3bb376391 | ||
![]() |
7d3c25d083 | ||
![]() |
8173f43770 | ||
![]() |
769007c707 | ||
![]() |
e825169957 | ||
![]() |
4ae535b3b9 | ||
![]() |
c0c75561d2 | ||
![]() |
8ce4f80dd9 | ||
![]() |
d3285f5468 | ||
![]() |
c6df8d3253 | ||
![]() |
988a7f7bdf | ||
![]() |
0b4cca38ea | ||
![]() |
8be090c03a | ||
![]() |
c5754ccc52 | ||
![]() |
21a6488c7f | ||
![]() |
3dbd7d36d0 | ||
![]() |
cd74a9cb12 | ||
![]() |
cd13a9df14 | ||
![]() |
58894136b7 | ||
![]() |
40dde2a9a1 | ||
![]() |
3ef37d7bf3 | ||
![]() |
2568505535 | ||
![]() |
1e0b41ab27 | ||
![]() |
cbc960c997 | ||
![]() |
bad44931a8 | ||
![]() |
914a72f8a4 | ||
![]() |
082766a990 | ||
![]() |
276e1c222c | ||
![]() |
fc7065d2b4 | ||
![]() |
599fd7344a | ||
![]() |
31f9ed087e | ||
![]() |
c9b72fcfb6 | ||
![]() |
bb4d0638c4 | ||
![]() |
e560ea47d4 | ||
![]() |
094eb99a43 | ||
![]() |
10c333a8f1 | ||
![]() |
dc05e0f907 | ||
![]() |
43438fec2a | ||
![]() |
1274facd44 | ||
![]() |
2b1fa0f10c | ||
![]() |
dcb9a0d030 | ||
![]() |
08c200e82f | ||
![]() |
5e7f7735a4 | ||
![]() |
02f48683b5 | ||
![]() |
0450686035 | ||
![]() |
7e2f6c3ebc | ||
![]() |
14f7cbd74c | ||
![]() |
d86a428994 | ||
![]() |
7a49918c89 | ||
![]() |
ac05ce5226 | ||
![]() |
ba268416d5 | ||
![]() |
7cee91f05b | ||
![]() |
4219ce91f2 | ||
![]() |
12ced6c83b | ||
![]() |
f835707f7a | ||
![]() |
2e00156657 | ||
![]() |
5ea0b9d60d | ||
![]() |
206d4a0fb3 | ||
![]() |
8e3499a961 | ||
![]() |
e38bbf88e5 | ||
![]() |
a5ce9c3706 | ||
![]() |
263a2bdec6 | ||
![]() |
03923c6ed7 | ||
![]() |
cb7cd815ee | ||
![]() |
8b06cdf277 | ||
![]() |
70f180975b | ||
![]() |
a872b54a3b | ||
![]() |
985e6178b4 | ||
![]() |
cafc012b05 | ||
![]() |
16a11ac88b | ||
![]() |
3e1af9a12a | ||
![]() |
e33f89fe27 | ||
![]() |
d10eca9c59 | ||
![]() |
edcbdc5706 | ||
![]() |
89ce203427 | ||
![]() |
99ab454a64 | ||
![]() |
c417769226 | ||
![]() |
4ea49aecaf | ||
![]() |
d4a87d9bb3 | ||
![]() |
8150cb9200 | ||
![]() |
d598753c1a | ||
![]() |
dd3b17de88 | ||
![]() |
cf9e2ea6da | ||
![]() |
21e5b41642 | ||
![]() |
fb01d80e88 | ||
![]() |
2dce5172e2 | ||
![]() |
b9f7f2d767 | ||
![]() |
0a584250ae | ||
![]() |
56abd0ece3 | ||
![]() |
3a003b2d96 | ||
![]() |
09ad9e535b | ||
![]() |
fdecca2f18 | ||
![]() |
dae2122388 | ||
![]() |
295e465fe4 | ||
![]() |
91a1798474 | ||
![]() |
aa88eb2a75 | ||
![]() |
3f3a8562fb | ||
![]() |
db3407370c | ||
![]() |
09ea0cf899 | ||
![]() |
092b7c6427 | ||
![]() |
c41e47034e | ||
![]() |
4ab22026b6 | ||
![]() |
894d6ba13f | ||
![]() |
5913469309 | ||
![]() |
755934f5f0 | ||
![]() |
538fd69243 | ||
![]() |
7efb51c9d3 | ||
![]() |
e33e069508 | ||
![]() |
a299004622 | ||
![]() |
845f9f73cd | ||
![]() |
3a3894e22c | ||
![]() |
cee37f0234 | ||
![]() |
9843a016f5 | ||
![]() |
e6783dbdd1 | ||
![]() |
7998b5e8d2 | ||
![]() |
bd9d1bf070 | ||
![]() |
0de3f8b21f | ||
![]() |
33cc3c125d | ||
![]() |
9a5d6d1049 | ||
![]() |
4ad9114c54 | ||
![]() |
1cf0bc2c6c | ||
![]() |
52d32cee8d | ||
![]() |
8f4d8dfd2d | ||
![]() |
e20acd3fe3 | ||
![]() |
0091d30e3e | ||
![]() |
7c033002b0 | ||
![]() |
4bb612126e | ||
![]() |
e5ee1911a9 | ||
![]() |
7093ca3dbe | ||
![]() |
d3c5141e2e | ||
![]() |
d223b0ccbc | ||
![]() |
fa57282a1e | ||
![]() |
4ad11b6af3 | ||
![]() |
24f23c5cdb | ||
![]() |
a2d0e17187 | ||
![]() |
33689d7beb | ||
![]() |
207e8c1b92 | ||
![]() |
36b7e77f03 | ||
![]() |
71443372fa | ||
![]() |
4ba09aceb9 | ||
![]() |
f2d0ea6d40 | ||
![]() |
bca701f0eb | ||
![]() |
f9fc0a243c | ||
![]() |
e9a5208c8b | ||
![]() |
7fe3a661b4 | ||
![]() |
d61cd9149a | ||
![]() |
f457855148 | ||
![]() |
194d76e571 | ||
![]() |
ef853bbc06 | ||
![]() |
0f7bf2913f | ||
![]() |
5626f0bf0b | ||
![]() |
8276e512d6 | ||
![]() |
72cf639020 | ||
![]() |
91ad968557 | ||
![]() |
e878d5a2fb | ||
![]() |
6ef2c7b34b | ||
![]() |
b3ec2edc04 | ||
![]() |
c7276273d8 | ||
![]() |
1fa332cad4 | ||
![]() |
5df5c2212a | ||
![]() |
ec7d25d355 | ||
![]() |
ccccb9d3cb | ||
![]() |
cb164a38f2 | ||
![]() |
9c63619f20 | ||
![]() |
651d278e1d | ||
![]() |
9efb50bad7 | ||
![]() |
4bfe73ccd9 | ||
![]() |
a75c738ece | ||
![]() |
9f6088dafa | ||
![]() |
89e3587cd8 | ||
![]() |
916bfee528 | ||
![]() |
1c643549f3 | ||
![]() |
e3c64cff24 | ||
![]() |
a1974604fe | ||
![]() |
faf1ab126d | ||
![]() |
f81f08e5bf | ||
![]() |
fdaf00af0e | ||
![]() |
b95024752a | ||
![]() |
56d5624e88 | ||
![]() |
fda0e83bd5 | ||
![]() |
7abe27ba09 | ||
![]() |
e1a6334b56 | ||
![]() |
bb01fa25bf | ||
![]() |
d4c0fcba3b | ||
![]() |
f678729f89 | ||
![]() |
d2ee378d1c | ||
![]() |
cf75064c71 | ||
![]() |
9052d31c68 | ||
![]() |
9a25d56b1f | ||
![]() |
30398802f8 | ||
![]() |
1cab5e1b1c | ||
![]() |
a177d33ca7 | ||
![]() |
546ead2abd | ||
![]() |
a6e44be2dc | ||
![]() |
fda161f976 | ||
![]() |
6c44c80c62 | ||
![]() |
91c48b3151 | ||
![]() |
839e0358b3 | ||
![]() |
35999a16dd | ||
![]() |
7b2e148687 | ||
![]() |
c01c7b800d | ||
![]() |
9fc656d2bf | ||
![]() |
62abe9e6e7 | ||
![]() |
48ebbc438e | ||
![]() |
f1f9f54ac3 | ||
![]() |
e437cfa280 | ||
![]() |
5ee1384cbd | ||
![]() |
ce98fae6e8 | ||
![]() |
fdc235f496 | ||
![]() |
36b76fc84c | ||
![]() |
aae2def236 | ||
![]() |
8d6426ef1a | ||
![]() |
b17aa3343a | ||
![]() |
9894256e3a | ||
![]() |
093d191909 | ||
![]() |
d6036462b1 | ||
![]() |
2adecffbc3 | ||
![]() |
dc5e615a1d | ||
![]() |
5935a32e32 | ||
![]() |
d413181b8a | ||
![]() |
d1d28c0bcf | ||
![]() |
93a5f4fab2 | ||
![]() |
fa1c53bb8e | ||
![]() |
788745e5b8 | ||
![]() |
12aa435bbb | ||
![]() |
6ece891ae6 | ||
![]() |
6febc2bf96 | ||
![]() |
d8df20a2e6 | ||
![]() |
9f4f16c588 | ||
![]() |
f85dc0720d | ||
![]() |
686b56fae9 | ||
![]() |
dd6ffaabdc | ||
![]() |
e8535bc27e | ||
![]() |
d364dacac1 | ||
![]() |
30a0a41982 | ||
![]() |
5b2d91ef31 | ||
![]() |
43a9999852 | ||
![]() |
ef5ecd95d7 | ||
![]() |
925d7003f8 | ||
![]() |
dac4704447 | ||
![]() |
f9a2ecd184 | ||
![]() |
3b04c8464c | ||
![]() |
660bf91360 | ||
![]() |
b568b06970 | ||
![]() |
984b52a972 | ||
![]() |
ef5cd99604 | ||
![]() |
e277b3f0ce | ||
![]() |
1043c3fd64 | ||
![]() |
bc0342b3ef | ||
![]() |
900bd07d10 | ||
![]() |
6f0f5a9bd0 | ||
![]() |
480f3d1119 | ||
![]() |
cb321840a1 | ||
![]() |
faddd60c40 | ||
![]() |
40b9d003af | ||
![]() |
91fc0c3756 | ||
![]() |
0d056cf294 | ||
![]() |
60b7b8b16e | ||
![]() |
3fa500d2f3 | ||
![]() |
e2a8e93005 | ||
![]() |
5d492e1aed | ||
![]() |
9d44b68867 | ||
![]() |
ac8491ae72 | ||
![]() |
7f77565b66 | ||
![]() |
a9d361f88f | ||
![]() |
94c7c2b780 | ||
![]() |
47d757d3dc | ||
![]() |
c5183d21db | ||
![]() |
1211cd827e | ||
![]() |
abeb9c654e | ||
![]() |
5a8c3bb0de | ||
![]() |
400c77f170 | ||
![]() |
db9a0d82d9 | ||
![]() |
ead282ff13 | ||
![]() |
7ddce8ab26 | ||
![]() |
19c47c5d99 | ||
![]() |
af404ff584 | ||
![]() |
ad600125df | ||
![]() |
79b1a6defc | ||
![]() |
1db0a60dc0 | ||
![]() |
5c3eb8b227 | ||
![]() |
a88c54a5c7 | ||
![]() |
39c449fc60 | ||
![]() |
4211499248 | ||
![]() |
636763276e | ||
![]() |
0fc8aacc64 | ||
![]() |
8657d8a090 | ||
![]() |
91167c3c23 | ||
![]() |
96ca7a205d | ||
![]() |
3d0daf15e1 | ||
![]() |
e1f19d14dd | ||
![]() |
c20ab940aa | ||
![]() |
8ad335eae0 | ||
![]() |
d779c98ee1 | ||
![]() |
79b45ac162 | ||
![]() |
c24d6afd64 | ||
![]() |
d616da4498 | ||
![]() |
f394656844 | ||
![]() |
4986e28bef | ||
![]() |
36c7bbb47a | ||
![]() |
e1a7a18747 | ||
![]() |
00129b2199 | ||
![]() |
06827c91c6 | ||
![]() |
f6aa5ba23c | ||
![]() |
6dfe5de9a8 | ||
![]() |
d9ba9ba3da | ||
![]() |
cf3c00056c | ||
![]() |
b35a75e429 | ||
![]() |
fb572aff53 | ||
![]() |
554e16fac2 | ||
![]() |
71a485a1af | ||
![]() |
1566eec9cf | ||
![]() |
00f8f62be7 | ||
![]() |
38af23a654 | ||
![]() |
c3caa263bf | ||
![]() |
eecb957610 | ||
![]() |
1c50f8660a | ||
![]() |
2cb1c51038 | ||
![]() |
8973c91293 | ||
![]() |
6d33ad2917 | ||
![]() |
4b519317cd | ||
![]() |
3316609ddd | ||
![]() |
8d91f83244 | ||
![]() |
4a3bf069a6 | ||
![]() |
e5ecc392c9 | ||
![]() |
ab287991cf | ||
![]() |
8df06279c6 | ||
![]() |
749d9b95b9 | ||
![]() |
9af58c1133 | ||
![]() |
e2dd60b5f8 | ||
![]() |
7fbc3a5307 | ||
![]() |
b67b765a10 | ||
![]() |
7bdec67718 | ||
![]() |
f44aa13a9f | ||
![]() |
96c0d7c90d | ||
![]() |
c6a850634f | ||
![]() |
9281613e76 | ||
![]() |
c82387b384 | ||
![]() |
51ba8c1c12 | ||
![]() |
1e3754c1d1 | ||
![]() |
fdc79f5286 | ||
![]() |
0f3e975aac | ||
![]() |
9ff5325642 | ||
![]() |
d9af8e0acc | ||
![]() |
5f0ecf4c8c | ||
![]() |
2182dedcc6 | ||
![]() |
03eb42642c | ||
![]() |
3ffcae66a8 | ||
![]() |
abbe792575 | ||
![]() |
8f386fd9c4 | ||
![]() |
33bfd1fac4 | ||
![]() |
c92430e84a | ||
![]() |
1a504af2ee | ||
![]() |
1c4760878b | ||
![]() |
be9f6b480c | ||
![]() |
ef496a4289 | ||
![]() |
127c2a347e | ||
![]() |
bf926c2000 | ||
![]() |
4594de69fd | ||
![]() |
25de1a353a | ||
![]() |
712bc99668 | ||
![]() |
b50ce590b4 | ||
![]() |
ea452f2de5 | ||
![]() |
60c45fb64c | ||
![]() |
54094b9073 | ||
![]() |
caefb0f1c1 | ||
![]() |
817974ec53 | ||
![]() |
d9078d887f | ||
![]() |
a0afcdd05a | ||
![]() |
6bfcfd1d33 | ||
![]() |
45dfd4dd23 | ||
![]() |
1df6a40aa0 | ||
![]() |
f9be832eca | ||
![]() |
486626413b | ||
![]() |
6f014135c4 | ||
![]() |
9712d6fb1f | ||
![]() |
f745685f54 | ||
![]() |
eab59f8057 | ||
![]() |
6b9acd7e9e | ||
![]() |
7eaf1ee62d | ||
![]() |
0a5f7125e4 | ||
![]() |
42263551b5 | ||
![]() |
24ed12d4a3 | ||
![]() |
ac85d24e64 | ||
![]() |
f7e052a456 | ||
![]() |
ddcb3cfcf5 | ||
![]() |
b5d0f7a5d2 | ||
![]() |
bac9a9be85 | ||
![]() |
f88b51995b | ||
![]() |
c993db9688 | ||
![]() |
61003f18ab | ||
![]() |
3d1c9fd5de | ||
![]() |
06f0c3fef6 | ||
![]() |
42b27932a8 | ||
![]() |
d705613db3 | ||
![]() |
dd09d5b7dd | ||
![]() |
ac65df58a5 | ||
![]() |
7288419939 | ||
![]() |
44f4002bf2 | ||
![]() |
09609c1320 | ||
![]() |
45502d1f04 | ||
![]() |
318e6c77b5 | ||
![]() |
a430bf6e8b | ||
![]() |
9d7663398a | ||
![]() |
131d6b14a2 | ||
![]() |
22467f3a5b | ||
![]() |
2b7f39ea28 | ||
![]() |
7b5ee98474 | ||
![]() |
1889f68007 | ||
![]() |
7aa229cc8a | ||
![]() |
b9730c0b2e | ||
![]() |
e22d442bf6 | ||
![]() |
2839d8cee5 | ||
![]() |
5f2593c9a2 | ||
![]() |
4610e1e517 | ||
![]() |
9fbf5808a0 | ||
![]() |
4d231b5bf8 | ||
![]() |
5240f1c283 | ||
![]() |
1f7bf131b0 | ||
![]() |
55ac91b887 | ||
![]() |
5a1bc65e06 | ||
![]() |
e5bf31b170 | ||
![]() |
b9010edcfa | ||
![]() |
c6189a83b9 | ||
![]() |
7ca521eda1 | ||
![]() |
4f66d53068 | ||
![]() |
a9d4900284 | ||
![]() |
6dc4272a1e | ||
![]() |
af08ab49f7 | ||
![]() |
b9513683d5 | ||
![]() |
19165b0b11 | ||
![]() |
d86123870b | ||
![]() |
93fd5c7ad0 | ||
![]() |
76c039fb09 | ||
![]() |
6b22951162 | ||
![]() |
f9a6e51e21 | ||
![]() |
70b6fa1525 | ||
![]() |
8bc1dd63f4 | ||
![]() |
4c3765d9ff | ||
![]() |
6f3c5088ae | ||
![]() |
373ff727f0 | ||
![]() |
4d13966c08 | ||
![]() |
45d064c388 | ||
![]() |
f9694033a5 | ||
![]() |
dba83ef669 | ||
![]() |
c28b6c2ced | ||
![]() |
bf940f0eab | ||
![]() |
c3fdc85d16 | ||
![]() |
3615b188d7 | ||
![]() |
2c707a911f | ||
![]() |
9bb8d12c1b | ||
![]() |
bcc0922a20 | ||
![]() |
56e62869fb | ||
![]() |
8f533897d8 | ||
![]() |
d07a72e067 | ||
![]() |
4a1c1c483b | ||
![]() |
31b25d5971 | ||
![]() |
726c4e9fba | ||
![]() |
0b2805f400 | ||
![]() |
3997e77393 | ||
![]() |
21fd4faf1b | ||
![]() |
79d0eea742 | ||
![]() |
7974cf00e7 | ||
![]() |
5089e9aef0 | ||
![]() |
62933b683e | ||
![]() |
e256771e86 | ||
![]() |
54e8c8eecc | ||
![]() |
0e7bb92b1d | ||
![]() |
fdf32d1b2a | ||
![]() |
084783e92b | ||
![]() |
8fef9a689e | ||
![]() |
618afcffa6 | ||
![]() |
be53dd3d04 | ||
![]() |
a9673e2bfc | ||
![]() |
6e33e3b7af | ||
![]() |
cf6da2a12e | ||
![]() |
c79fe58939 | ||
![]() |
d5738b5cdd | ||
![]() |
aa8bc0b56d | ||
![]() |
5021b3e6e5 | ||
![]() |
f00df0ad1e | ||
![]() |
9ad608691b | ||
![]() |
6ebef31b3c | ||
![]() |
65e8b0951b | ||
![]() |
743e0edfd7 | ||
![]() |
0534423c58 | ||
![]() |
97b398cba1 | ||
![]() |
d1246b099e | ||
![]() |
3f84820711 | ||
![]() |
90a171d278 | ||
![]() |
65a00fc60a | ||
![]() |
2914a870af | ||
![]() |
ac2e01684c | ||
![]() |
c3e6002c6e | ||
![]() |
8d8041bd4d | ||
![]() |
ef4863ab97 | ||
![]() |
781a37420f | ||
![]() |
f6fc2f4a08 | ||
![]() |
e59a55e645 | ||
![]() |
f3db297fd1 | ||
![]() |
12f8c78231 | ||
![]() |
b4472f4670 | ||
![]() |
9a1fbff651 | ||
![]() |
720dfdde7d | ||
![]() |
a285ab6bcf | ||
![]() |
14b60f2264 | ||
![]() |
eeac57075c | ||
![]() |
754d49ac81 | ||
![]() |
1a7be001d2 | ||
![]() |
835383d46b | ||
![]() |
9283328fe7 | ||
![]() |
3a16864c33 | ||
![]() |
e9cd9a9c35 | ||
![]() |
1c59038555 | ||
![]() |
c4bbf27cb5 | ||
![]() |
6a3d37ef1c | ||
![]() |
2f3eaa965c | ||
![]() |
727066fe1f | ||
![]() |
4e80190a46 | ||
![]() |
e882e42e1b | ||
![]() |
ebb96e2303 | ||
![]() |
0590c974c1 | ||
![]() |
1bf821c1e1 | ||
![]() |
1f7630f1bf | ||
![]() |
e49e73e160 | ||
![]() |
121b1b7d58 | ||
![]() |
5fda92451d | ||
![]() |
5088a93024 | ||
![]() |
7227fdd805 | ||
![]() |
3ac159094f | ||
![]() |
19df15f1dc | ||
![]() |
a078895ad2 | ||
![]() |
c32c2606f4 | ||
![]() |
5aa220efee | ||
![]() |
6af2341894 | ||
![]() |
d5848e2232 | ||
![]() |
cd198f7517 | ||
![]() |
f277add285 | ||
![]() |
71723f74b7 | ||
![]() |
d48f255074 | ||
![]() |
bc9c14da7a | ||
![]() |
ecfe34f56c | ||
![]() |
bd65cfa876 | ||
![]() |
0b7b52a1f1 | ||
![]() |
40d56c98bc | ||
![]() |
ccbece58d8 | ||
![]() |
a75e6be6fb | ||
![]() |
6e4e8072e1 | ||
![]() |
da9a77ce42 | ||
![]() |
d93fe9038d | ||
![]() |
c64ff4b069 | ||
![]() |
e366471fdc | ||
![]() |
c07966583f | ||
![]() |
f64ccadceb | ||
![]() |
020cdd0f73 | ||
![]() |
a238af4d20 | ||
![]() |
1ce3101fbc | ||
![]() |
de27f3a435 | ||
![]() |
daa1fc97dd | ||
![]() |
7e5c6890b2 | ||
![]() |
6f57447710 | ||
![]() |
5db618a2db | ||
![]() |
7b8073d122 | ||
![]() |
cf82b71c7a | ||
![]() |
78b743cf4a | ||
![]() |
a7b2cd66ad | ||
![]() |
22355f2114 | ||
![]() |
f987cf8a8a | ||
![]() |
6547174ccf | ||
![]() |
3d1d4bf934 | ||
![]() |
8c956babeb | ||
![]() |
54e74142af | ||
![]() |
89fea8ec34 | ||
![]() |
e90a337fa3 | ||
![]() |
1a77567029 | ||
![]() |
58ecb8ade5 | ||
![]() |
3101d75634 | ||
![]() |
5fa4e3dee1 | ||
![]() |
e40436d527 | ||
![]() |
b7c5fcaf1e | ||
![]() |
0ef1c07838 | ||
![]() |
13dcb1f8b3 | ||
![]() |
2b79cb613b | ||
![]() |
2569d4088f | ||
![]() |
8d27c00038 | ||
![]() |
329acc038d | ||
![]() |
96d9303b76 | ||
![]() |
b1b9a42517 | ||
![]() |
e6d25c0f73 | ||
![]() |
44c847c1a5 | ||
![]() |
c21e977e66 | ||
![]() |
eae9ef2292 | ||
![]() |
c6f57c7a55 | ||
![]() |
8ef4a43ada | ||
![]() |
d283e4cb2a | ||
![]() |
aa2c4fe654 | ||
![]() |
6010f0f2b0 | ||
![]() |
c62356fcaa | ||
![]() |
75f0f3dc55 | ||
![]() |
1f5d8a39cb | ||
![]() |
685c7e92e5 | ||
![]() |
4b8cd07408 | ||
![]() |
cd3a6c88fd | ||
![]() |
5a8a3ed8e2 | ||
![]() |
2cc0f68c56 | ||
![]() |
9708b088f9 | ||
![]() |
fc9a775f56 | ||
![]() |
35fda7f857 | ||
![]() |
8b68b55d16 | ||
![]() |
1036bfd7ad | ||
![]() |
0dcf28104d | ||
![]() |
a57fef9558 | ||
![]() |
f5432271b9 | ||
![]() |
f8d72ba783 | ||
![]() |
666ed1b51c | ||
![]() |
7595a9061d | ||
![]() |
34be83851e | ||
![]() |
3d91a48298 | ||
![]() |
cbbc2eae0e | ||
![]() |
7521044465 | ||
![]() |
491ecff31e | ||
![]() |
cede7c8aa7 | ||
![]() |
71f61d959d | ||
![]() |
6dddb6e6d6 | ||
![]() |
3d63c6b602 | ||
![]() |
2455635238 | ||
![]() |
709226ad1c | ||
![]() |
800bce8a7e | ||
![]() |
cee30225e9 | ||
![]() |
38188881ce | ||
![]() |
c178b063c6 | ||
![]() |
038f5934e7 | ||
![]() |
72a9d2128f | ||
![]() |
91befbbc52 | ||
![]() |
3bf0f771ee | ||
![]() |
a20ca7bbfe | ||
![]() |
228808142b | ||
![]() |
2db6704576 | ||
![]() |
f553875728 | ||
![]() |
7ec4bd74ff | ||
![]() |
2d94ad1f3a | ||
![]() |
89c51cb183 | ||
![]() |
035f5d3055 | ||
![]() |
be421bcdd4 | ||
![]() |
50ba0149e4 | ||
![]() |
d069699940 | ||
![]() |
f16ff829f0 | ||
![]() |
bc7c05bfbd | ||
![]() |
ba0da90ba6 | ||
![]() |
d7565ffbe5 | ||
![]() |
ce157a446f | ||
![]() |
b56e83a041 | ||
![]() |
999b94cc39 | ||
![]() |
b4a99e775d | ||
![]() |
d8b057d06d | ||
![]() |
b059849bf8 | ||
![]() |
9b7a723aac | ||
![]() |
5e8c2f9a0e | ||
![]() |
3ce6402d25 | ||
![]() |
c852872cb2 | ||
![]() |
94dbc42a56 | ||
![]() |
3ef19961cc | ||
![]() |
60c33a222c | ||
![]() |
0e2b54e1da | ||
![]() |
d719fc74f5 | ||
![]() |
d9c0183bd7 | ||
![]() |
96619d46a1 | ||
![]() |
a3e0f8dee2 | ||
![]() |
0622cee189 | ||
![]() |
172c80df67 | ||
![]() |
89503e387a | ||
![]() |
cd61d6f748 | ||
![]() |
12e97610a8 | ||
![]() |
7fcc8c0831 | ||
![]() |
52df1aeb59 | ||
![]() |
6e6a9cf26b | ||
![]() |
7685cb6f48 | ||
![]() |
b25e35cf58 | ||
![]() |
53231879b3 | ||
![]() |
98a4b46b6a | ||
![]() |
149a4b4ca1 | ||
![]() |
326b22124a | ||
![]() |
4588542dfc | ||
![]() |
7738626d25 | ||
![]() |
25981beebd | ||
![]() |
40bd86819b | ||
![]() |
ebbd5a7ff5 | ||
![]() |
00574d4ba5 | ||
![]() |
96185c7d8c | ||
![]() |
8159c45834 | ||
![]() |
ab01179d6c | ||
![]() |
fc0cbb3171 | ||
![]() |
b18beb2cc2 | ||
![]() |
d7382aa058 | ||
![]() |
74e869c777 | ||
![]() |
e15210b466 | ||
![]() |
72785c54ed | ||
![]() |
b33e988aef | ||
![]() |
1e5b4a1aae | ||
![]() |
34609db10b | ||
![]() |
647546bcac | ||
![]() |
8eeef165d4 | ||
![]() |
597c5d413f | ||
![]() |
daa89d5292 | ||
![]() |
075d99fc11 | ||
![]() |
90b771ce3a | ||
![]() |
0108e2f82f | ||
![]() |
ad09677532 | ||
![]() |
bb06ffd944 | ||
![]() |
e3ce74dc7e | ||
![]() |
0668944255 | ||
![]() |
3c9d03b875 | ||
![]() |
d8a909d99c | ||
![]() |
9ef1ec5870 | ||
![]() |
9cb6411740 | ||
![]() |
191efe2e91 | ||
![]() |
8265bb8b6a | ||
![]() |
8900a5e045 | ||
![]() |
14bdf39806 | ||
![]() |
2a7e01e4fc | ||
![]() |
4fa2409c78 | ||
![]() |
cf65c18817 | ||
![]() |
8a741f10f8 | ||
![]() |
9a76f55518 | ||
![]() |
aeb3a45c97 | ||
![]() |
e4763e6329 | ||
![]() |
92596e3f17 | ||
![]() |
c652119812 | ||
![]() |
b9837e4ada | ||
![]() |
d61a337a70 | ||
![]() |
2753d333f6 | ||
![]() |
3632e6f463 | ||
![]() |
747722d639 | ||
![]() |
9b96eaaf80 | ||
![]() |
78d1539709 | ||
![]() |
f27f917d32 | ||
![]() |
5365372b3d | ||
![]() |
dd8ae6cc66 | ||
![]() |
b2e75e5322 | ||
![]() |
335fe5c5dc | ||
![]() |
2c1ad5b07a | ||
![]() |
988721cda3 | ||
![]() |
a4b5b0ec68 | ||
![]() |
2fd881c40f | ||
![]() |
cc22932fc9 | ||
![]() |
9f7c3d00dd | ||
![]() |
05dae23f18 | ||
![]() |
da8f647fa1 | ||
![]() |
9dde5688a5 | ||
![]() |
835a709303 | ||
![]() |
f84123d20e | ||
![]() |
42fbaba8ad | ||
![]() |
be11bf1d6b | ||
![]() |
f30859d7f3 | ||
![]() |
3315dd3c60 | ||
![]() |
f8dedf68e2 | ||
![]() |
3dbb193ece | ||
![]() |
01c4038559 | ||
![]() |
7a82648b2b | ||
![]() |
62273fa10b | ||
![]() |
0f614cd63f | ||
![]() |
406b22d2d5 | ||
![]() |
f81287d765 | ||
![]() |
c4559c02de | ||
![]() |
b0080500bd | ||
![]() |
e5cd234ef7 | ||
![]() |
f320274ca3 | ||
![]() |
0be2a77156 | ||
![]() |
4fcd85551c | ||
![]() |
369ed5113e | ||
![]() |
1c056c7c86 | ||
![]() |
3fa7c65914 | ||
![]() |
d5512dfe71 | ||
![]() |
d90d8afa5a | ||
![]() |
ff111e395d | ||
![]() |
6e75c28a5e | ||
![]() |
468ad87a37 | ||
![]() |
3ad1642b2e | ||
![]() |
aad046edba | ||
![]() |
1e84bc4d9c | ||
![]() |
a916325e6a | ||
![]() |
d1fd42bf3c | ||
![]() |
3335708ce0 | ||
![]() |
d824e79fc0 | ||
![]() |
3f03260a21 | ||
![]() |
b23b0dde9a | ||
![]() |
b9cdc74b2b | ||
![]() |
bee392fcd2 | ||
![]() |
1b697aff38 | ||
![]() |
7b5c53d996 | ||
![]() |
3892fa4a0b | ||
![]() |
fc951855ed | ||
![]() |
46b88dcbda | ||
![]() |
8b4b93a82e | ||
![]() |
cc7397ceb7 | ||
![]() |
e5f9f4d1cb | ||
![]() |
38d80598f5 | ||
![]() |
aa294bb3c8 | ||
![]() |
b73ba6c58d | ||
![]() |
8c7c96e2c4 | ||
![]() |
e721af5775 | ||
![]() |
e504943212 | ||
![]() |
4676d73a1a | ||
![]() |
4eaa0ef1e7 | ||
![]() |
2ee5a18917 | ||
![]() |
d66cbe0114 | ||
![]() |
c93f55533d | ||
![]() |
6bc6110a90 | ||
![]() |
09b8ac41bb | ||
![]() |
7dc6df3051 | ||
![]() |
ff3eee7df6 | ||
![]() |
adb2ec043e | ||
![]() |
1a89648c61 | ||
![]() |
d51c13fdd4 | ||
![]() |
153bd70c8a | ||
![]() |
138e21e6ff | ||
![]() |
00699ec29e | ||
![]() |
31f0eda63b | ||
![]() |
f279257883 | ||
![]() |
da212c74c2 | ||
![]() |
5f82f131d4 | ||
![]() |
2557b0da9f | ||
![]() |
6f4be6c1f9 | ||
![]() |
a97dbc3ad2 | ||
![]() |
606284e14b | ||
![]() |
02d8cf84b0 | ||
![]() |
abe3b481ae | ||
![]() |
03d32c68a9 | ||
![]() |
081cebb2f7 | ||
![]() |
6efa557e9b | ||
![]() |
fb23f7d175 | ||
![]() |
7ce05be884 | ||
![]() |
490af72c99 | ||
![]() |
853884ba05 | ||
![]() |
f73d3db412 | ||
![]() |
c39edeca6d | ||
![]() |
27a3f0eb8d | ||
![]() |
fe327c217e | ||
![]() |
f69fe1e453 | ||
![]() |
4dec6af2c8 | ||
![]() |
697474baad | ||
![]() |
155c594f02 | ||
![]() |
54dff9228c | ||
![]() |
570577a4d6 | ||
![]() |
aedc706b34 | ||
![]() |
5f5b21481d | ||
![]() |
de572675e0 | ||
![]() |
ebb51d1f7d | ||
![]() |
fe5b8fc3f6 | ||
![]() |
1a6d3c2192 | ||
![]() |
94b5658cd2 | ||
![]() |
58e056894d | ||
![]() |
a298979866 | ||
![]() |
5316d12588 | ||
![]() |
ee404c657e | ||
![]() |
e9131550b1 | ||
![]() |
0d700e53f3 | ||
![]() |
5d66b0b41a | ||
![]() |
8f36c97a49 | ||
![]() |
a50fc5acd8 | ||
![]() |
a3cb0bd2a3 | ||
![]() |
ebdf57fbf1 | ||
![]() |
46e40969a2 | ||
![]() |
6d8aa8582f | ||
![]() |
99a39ce6ea | ||
![]() |
2967267fba | ||
![]() |
76dfc53dee | ||
![]() |
c2141e0aa5 | ||
![]() |
d0a0d8b798 | ||
![]() |
4c3f2be16d | ||
![]() |
af5a81faf8 | ||
![]() |
7d09e4a428 | ||
![]() |
06b155a18c | ||
![]() |
476b901247 | ||
![]() |
1daf9893ec | ||
![]() |
204e310914 | ||
![]() |
e3a6abd871 | ||
![]() |
77dd83efbf | ||
![]() |
906aff5331 | ||
![]() |
35c87ae0ca | ||
![]() |
13c2b28cd6 | ||
![]() |
aa8acd1a04 | ||
![]() |
6379874180 | ||
![]() |
9317c8eb23 | ||
![]() |
1c62ba40b7 | ||
![]() |
8d137bcd29 | ||
![]() |
d61d70e8b9 | ||
![]() |
4e3a39a2e8 | ||
![]() |
748f35ccb8 | ||
![]() |
cadd08da9e | ||
![]() |
75bbe3a0bc | ||
![]() |
47756c9689 | ||
![]() |
e5ab5acd95 | ||
![]() |
0576b12699 | ||
![]() |
320ff6bc75 | ||
![]() |
d8cdc53ec0 | ||
![]() |
7b923609c2 | ||
![]() |
793228f171 | ||
![]() |
bc0eba5296 | ||
![]() |
45f089a143 | ||
![]() |
139c406558 | ||
![]() |
502f49d7f9 | ||
![]() |
c7d0cb8072 | ||
![]() |
252329ce40 | ||
![]() |
a86cd83593 | ||
![]() |
d3fadcb5fb | ||
![]() |
6aae7d7345 | ||
![]() |
565e1aaeb9 | ||
![]() |
f7fd65923a | ||
![]() |
d9d796618d | ||
![]() |
5f737952fd | ||
![]() |
7b850260bf | ||
![]() |
dd8bab9f89 | ||
![]() |
9504b0ff7a | ||
![]() |
8798387770 | ||
![]() |
fb7d2829f3 | ||
![]() |
feb3e904cb | ||
![]() |
c6be28af7a | ||
![]() |
1ce55b946c | ||
![]() |
cfde73ac17 | ||
![]() |
ddde1c07a6 | ||
![]() |
dcefe95ae4 | ||
![]() |
60a7bed19c | ||
![]() |
bac7253fcf | ||
![]() |
be443e41bb | ||
![]() |
dd11265c4c | ||
![]() |
d80b9887dd | ||
![]() |
1c8e3f9037 | ||
![]() |
e73e978d65 | ||
![]() |
67723a9572 | ||
![]() |
02e1919514 | ||
![]() |
7fc11f8999 | ||
![]() |
2b855d831d | ||
![]() |
ea17bf712a | ||
![]() |
bf7422e2c7 | ||
![]() |
12d74872a5 | ||
![]() |
90370a08ec | ||
![]() |
611fc62fe4 | ||
![]() |
a38256c19e | ||
![]() |
90ff46c292 | ||
![]() |
555e7ad073 | ||
![]() |
1b087104e5 | ||
![]() |
f9c76d026d | ||
![]() |
6d9983e958 | ||
![]() |
a001026dbb | ||
![]() |
0cace15d72 | ||
![]() |
c75a33aa5d | ||
![]() |
4c9bd858c7 | ||
![]() |
e90cea9250 | ||
![]() |
977ffe200e | ||
![]() |
a2b9fc08e3 | ||
![]() |
464bd50ae9 | ||
![]() |
13a643d78a | ||
![]() |
4a24de208f | ||
![]() |
188b47a29b | ||
![]() |
22e67735f1 | ||
![]() |
be68ff8cea | ||
![]() |
6e76a9467f | ||
![]() |
d6aca93c1a | ||
![]() |
b9bff1fba5 | ||
![]() |
84c0ec04f3 | ||
![]() |
d481a23c5a | ||
![]() |
0c4a00bf2a | ||
![]() |
4c4d8b39f1 | ||
![]() |
1a864595cf | ||
![]() |
56e04635a7 | ||
![]() |
bc55744121 | ||
![]() |
f260c5db8a | ||
![]() |
e0bf7ff072 | ||
![]() |
097ccbc5cd | ||
![]() |
199161f023 | ||
![]() |
459cb33abc | ||
![]() |
0ad232423d | ||
![]() |
8937c6880f | ||
![]() |
517b42e7dd | ||
![]() |
0f870fd286 | ||
![]() |
05fd79af7c | ||
![]() |
fbf27dbfc6 | ||
![]() |
9f8626ccaa | ||
![]() |
11a4961081 | ||
![]() |
adfb0d8c1d | ||
![]() |
356b1ab2a6 | ||
![]() |
8ec31b7b3d | ||
![]() |
6a288c9275 | ||
![]() |
7f5933c0f3 | ||
![]() |
e09cb44a94 | ||
![]() |
b625b40d92 | ||
![]() |
fbe2710843 | ||
![]() |
ab178719d9 | ||
![]() |
f6602d40bd | ||
![]() |
ecfb96239c | ||
![]() |
838cb0eefc | ||
![]() |
2409956297 | ||
![]() |
b56b776ab2 | ||
![]() |
31b5375a1c | ||
![]() |
cbc7dac0d5 | ||
![]() |
3d6b4f9038 | ||
![]() |
0f1e8809f7 | ||
![]() |
269ee1204d | ||
![]() |
02da380903 | ||
![]() |
37ae7d4420 | ||
![]() |
6daaea4780 | ||
![]() |
91a4a28aab | ||
![]() |
a8efa55bed | ||
![]() |
819c80428d | ||
![]() |
f20e5152ad | ||
![]() |
61956f2e06 | ||
![]() |
c5490f7284 | ||
![]() |
728934f43e | ||
![]() |
8950744921 | ||
![]() |
047edb8933 | ||
![]() |
a8f8f84af6 | ||
![]() |
3528e83ff3 | ||
![]() |
fc7b7571a0 | ||
![]() |
11adf408ab | ||
![]() |
0adf0898eb | ||
![]() |
78f1543e35 | ||
![]() |
78045df591 | ||
![]() |
00f5b230be | ||
![]() |
a760a7656c | ||
![]() |
a805b0c658 | ||
![]() |
f1c941d460 | ||
![]() |
16b9ee6f50 | ||
![]() |
a3e58a385f | ||
![]() |
c03a7b7893 | ||
![]() |
14a814586a | ||
![]() |
d956bcf749 | ||
![]() |
28fd557c58 | ||
![]() |
ae74c0c9a4 | ||
![]() |
1964918e46 | ||
![]() |
a9ac00f8f7 | ||
![]() |
af2b9be356 | ||
![]() |
175c38d0dc | ||
![]() |
b6dcb111d2 | ||
![]() |
4774b57e4d | ||
![]() |
c3476b8205 | ||
![]() |
6842a5861b | ||
![]() |
14783cd8b8 | ||
![]() |
2e41412ee4 | ||
![]() |
857f47e238 | ||
![]() |
ae980c6bfb | ||
![]() |
d1f11b2b28 | ||
![]() |
4d80777ce7 | ||
![]() |
54995d9850 | ||
![]() |
c0e36dc493 |
2086 changed files with 114460 additions and 32252 deletions
24
.github/CODEOWNERS
vendored
24
.github/CODEOWNERS
vendored
|
@ -45,8 +45,6 @@
|
||||||
# Editor
|
# Editor
|
||||||
|
|
||||||
/editor/ @godotengine/docks
|
/editor/ @godotengine/docks
|
||||||
/editor/script/ @godotengine/script-editor
|
|
||||||
/editor/shader/ @godotengine/script-editor @godotengine/shaders
|
|
||||||
/editor/animation/ @godotengine/animation
|
/editor/animation/ @godotengine/animation
|
||||||
/editor/audio/ @godotengine/audio
|
/editor/audio/ @godotengine/audio
|
||||||
/editor/debugger/ @godotengine/debugger
|
/editor/debugger/ @godotengine/debugger
|
||||||
|
@ -57,10 +55,12 @@
|
||||||
/editor/import/ @godotengine/import
|
/editor/import/ @godotengine/import
|
||||||
/editor/inspector/ @godotengine/docks
|
/editor/inspector/ @godotengine/docks
|
||||||
/editor/scene/2d/ @godotengine/2d-editor
|
/editor/scene/2d/ @godotengine/2d-editor
|
||||||
/editor/scene/2d/physics @godotengine/2d-editor @godotengine/physics
|
/editor/scene/2d/physics/ @godotengine/2d-editor @godotengine/physics
|
||||||
/editor/scene/3d/ @godotengine/3d-editor
|
/editor/scene/3d/ @godotengine/3d-editor
|
||||||
/editor/scene/3d/physics @godotengine/3d-editor @godotengine/physics
|
/editor/scene/3d/physics/ @godotengine/3d-editor @godotengine/physics
|
||||||
/editor/scene/gui/ @godotengine/gui-nodes
|
/editor/scene/gui/ @godotengine/gui-nodes
|
||||||
|
/editor/script/ @godotengine/script-editor
|
||||||
|
/editor/shader/ @godotengine/script-editor @godotengine/shaders
|
||||||
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
|
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
|
||||||
/editor/translations/ @godotengine/usability
|
/editor/translations/ @godotengine/usability
|
||||||
|
|
||||||
|
@ -205,9 +205,12 @@
|
||||||
# Scene
|
# Scene
|
||||||
|
|
||||||
/scene/2d/ @godotengine/2d-nodes
|
/scene/2d/ @godotengine/2d-nodes
|
||||||
|
/scene/2d/navigation/ @godotengine/2d-nodes @godotengine/navigation
|
||||||
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
|
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
|
||||||
/scene/3d/ @godotengine/3d-nodes
|
/scene/3d/ @godotengine/3d-nodes
|
||||||
|
/scene/3d/navigation/ @godotengine/3d-nodes @godotengine/navigation
|
||||||
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
|
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
|
||||||
|
/scene/3d/xr/ @godotengine/3d-nodes @godotengine/xr
|
||||||
/scene/animation/ @godotengine/animation
|
/scene/animation/ @godotengine/animation
|
||||||
/scene/audio/ @godotengine/audio
|
/scene/audio/ @godotengine/audio
|
||||||
/scene/debugger/ @godotengine/debugger
|
/scene/debugger/ @godotengine/debugger
|
||||||
|
@ -227,18 +230,13 @@
|
||||||
|
|
||||||
# Servers
|
# Servers
|
||||||
|
|
||||||
/servers/**/audio_* @godotengine/audio
|
|
||||||
/servers/**/camera_* @godotengine/xr
|
|
||||||
/servers/**/debugger_* @godotengine/debugger
|
|
||||||
/servers/**/navigation_* @godotengine/navigation
|
|
||||||
/servers/**/physics_* @godotengine/physics
|
|
||||||
/servers/**/rendering_* @godotengine/rendering
|
|
||||||
/servers/**/text_* @godotengine/gui-nodes
|
|
||||||
/servers/**/xr_* @godotengine/xr
|
|
||||||
/servers/audio/ @godotengine/audio
|
/servers/audio/ @godotengine/audio
|
||||||
/servers/camera/ @godotengine/xr
|
/servers/camera/ @godotengine/xr
|
||||||
/servers/debugger/ @godotengine/debugger
|
/servers/debugger/ @godotengine/debugger
|
||||||
/servers/navigation/ @godotengine/navigation
|
/servers/navigation_2d/ @godotengine/navigation
|
||||||
|
/servers/navigation_3d/ @godotengine/navigation
|
||||||
|
/servers/physics_2d/ @godotengine/physics
|
||||||
|
/servers/physics_3d/ @godotengine/physics
|
||||||
/servers/rendering/ @godotengine/rendering
|
/servers/rendering/ @godotengine/rendering
|
||||||
/servers/text/ @godotengine/gui-nodes
|
/servers/text/ @godotengine/gui-nodes
|
||||||
/servers/xr/ @godotengine/xr
|
/servers/xr/ @godotengine/xr
|
||||||
|
|
2
.github/actions/godot-deps/action.yml
vendored
2
.github/actions/godot-deps/action.yml
vendored
|
@ -10,7 +10,7 @@ inputs:
|
||||||
default: x64
|
default: x64
|
||||||
scons-version:
|
scons-version:
|
||||||
description: The SCons version to use.
|
description: The SCons version to use.
|
||||||
default: 4.9.0
|
default: 4.10.0
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
|
|
10
.github/workflows/android_builds.yml
vendored
10
.github/workflows/android_builds.yml
vendored
|
@ -26,14 +26,14 @@ jobs:
|
||||||
arch=arm64
|
arch=arm64
|
||||||
production=yes
|
production=yes
|
||||||
|
|
||||||
- name: Template arm32 (target=template_release, arch=arm32)
|
- name: Template arm32 (target=template_debug, arch=arm32)
|
||||||
cache-name: android-template-arm32
|
cache-name: android-template-arm32
|
||||||
target: template_release
|
target: template_debug
|
||||||
scons-flags: arch=arm32
|
scons-flags: arch=arm32
|
||||||
|
|
||||||
- name: Template arm64 (target=template_release, arch=arm64)
|
- name: Template arm64 (target=template_debug, arch=arm64)
|
||||||
cache-name: android-template-arm64
|
cache-name: android-template-arm64
|
||||||
target: template_release
|
target: template_debug
|
||||||
scons-flags: arch=arm64
|
scons-flags: arch=arm64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -82,7 +82,7 @@ jobs:
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Generate Godot templates
|
- name: Generate Godot templates
|
||||||
if: matrix.target == 'template_release'
|
if: matrix.target == 'template_debug'
|
||||||
run: |
|
run: |
|
||||||
cd platform/android/java
|
cd platform/android/java
|
||||||
./gradlew generateGodotTemplates
|
./gradlew generateGodotTemplates
|
||||||
|
|
2
.github/workflows/linux_builds.yml
vendored
2
.github/workflows/linux_builds.yml
vendored
|
@ -8,7 +8,7 @@ env:
|
||||||
dev_mode=yes
|
dev_mode=yes
|
||||||
module_text_server_fb_enabled=yes
|
module_text_server_fb_enabled=yes
|
||||||
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.17.0/"
|
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.17.0/"
|
||||||
GODOT_CPP_BRANCH: 4.4
|
GODOT_CPP_BRANCH: 4.5
|
||||||
DOTNET_NOLOGO: true
|
DOTNET_NOLOGO: true
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||||
ASAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/asan.txt
|
ASAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/asan.txt
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -217,7 +217,7 @@ xcuserdata/
|
||||||
*.xcscmblueprint
|
*.xcscmblueprint
|
||||||
*.xccheckout
|
*.xccheckout
|
||||||
*.xcodeproj/*
|
*.xcodeproj/*
|
||||||
!misc/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
|
!misc/misc/dist/apple_embedded_xcode/godot.xcodeproj/project.pbxproj
|
||||||
|
|
||||||
# Zed
|
# Zed
|
||||||
.zed/
|
.zed/
|
||||||
|
|
|
@ -34,9 +34,9 @@ repos:
|
||||||
stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy`
|
stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy`
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.12.0
|
rev: v0.13.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff-check
|
||||||
args: [--fix]
|
args: [--fix]
|
||||||
files: (\.py|SConstruct|SCsub)$
|
files: (\.py|SConstruct|SCsub)$
|
||||||
types_or: [text]
|
types_or: [text]
|
||||||
|
|
|
@ -214,7 +214,7 @@ License: Apache-2.0
|
||||||
|
|
||||||
Files: thirdparty/basis_universal/*
|
Files: thirdparty/basis_universal/*
|
||||||
Comment: Basis Universal
|
Comment: Basis Universal
|
||||||
Copyright: 2019-2024, Binomial LLC.
|
Copyright: 2019-2025, Binomial LLC.
|
||||||
License: Apache-2.0
|
License: Apache-2.0
|
||||||
|
|
||||||
Files: thirdparty/brotli/*
|
Files: thirdparty/brotli/*
|
||||||
|
@ -555,7 +555,7 @@ License: Zlib
|
||||||
Files: thirdparty/sdl/hidapi/*
|
Files: thirdparty/sdl/hidapi/*
|
||||||
Comment: hidapi
|
Comment: hidapi
|
||||||
Copyright: 2010, Alan Ott, Signal 11 Software
|
Copyright: 2010, Alan Ott, Signal 11 Software
|
||||||
License: BSD-3-Clause
|
License: BSD-3-clause
|
||||||
|
|
||||||
Files: thirdparty/spirv-cross/*
|
Files: thirdparty/spirv-cross/*
|
||||||
Comment: SPIRV-Cross
|
Comment: SPIRV-Cross
|
||||||
|
|
51
SConstruct
51
SConstruct
|
@ -210,7 +210,7 @@ opts.Add(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
opts.Add(BoolVariable("tests", "Build the unit tests", False))
|
opts.Add(BoolVariable("tests", "Build the unit tests", False))
|
||||||
opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster rebuilds", False))
|
opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster incremental builds", False))
|
||||||
opts.Add(BoolVariable("ninja", "Use the ninja backend for faster rebuilds", False))
|
opts.Add(BoolVariable("ninja", "Use the ninja backend for faster rebuilds", False))
|
||||||
opts.Add(BoolVariable("ninja_auto_run", "Run ninja automatically after generating the ninja file", True))
|
opts.Add(BoolVariable("ninja_auto_run", "Run ninja automatically after generating the ninja file", True))
|
||||||
opts.Add("ninja_file", "Path to the generated ninja file", "build.ninja")
|
opts.Add("ninja_file", "Path to the generated ninja file", "build.ninja")
|
||||||
|
@ -239,6 +239,7 @@ opts.Add(BoolVariable("disable_physics_3d", "Disable 3D physics nodes and server
|
||||||
opts.Add(BoolVariable("disable_navigation_2d", "Disable 2D navigation features", False))
|
opts.Add(BoolVariable("disable_navigation_2d", "Disable 2D navigation features", False))
|
||||||
opts.Add(BoolVariable("disable_navigation_3d", "Disable 3D navigation features", False))
|
opts.Add(BoolVariable("disable_navigation_3d", "Disable 3D navigation features", False))
|
||||||
opts.Add(BoolVariable("disable_xr", "Disable XR nodes and server", False))
|
opts.Add(BoolVariable("disable_xr", "Disable XR nodes and server", False))
|
||||||
|
opts.Add(BoolVariable("disable_overrides", "Disable project settings overrides and related CLI arguments", False))
|
||||||
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
|
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
|
||||||
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
|
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
|
||||||
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
|
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
|
||||||
|
@ -264,6 +265,14 @@ opts.Add(
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
opts.Add(
|
||||||
|
EnumVariable(
|
||||||
|
"library_type",
|
||||||
|
"Build library type",
|
||||||
|
"executable",
|
||||||
|
("executable", "static_library", "shared_library"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Thirdparty libraries
|
# Thirdparty libraries
|
||||||
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
|
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
|
||||||
|
@ -469,16 +478,6 @@ for tool in custom_tools:
|
||||||
# Add default include paths.
|
# Add default include paths.
|
||||||
env.Prepend(CPPPATH=["#"])
|
env.Prepend(CPPPATH=["#"])
|
||||||
|
|
||||||
# Allow marking includes as external/system to avoid raising warnings.
|
|
||||||
env["_CCCOMCOM"] += " $_CPPEXTINCFLAGS"
|
|
||||||
env["CPPEXTPATH"] = []
|
|
||||||
if env.scons_version < (4, 2):
|
|
||||||
env["_CPPEXTINCFLAGS"] = "${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}"
|
|
||||||
else:
|
|
||||||
env["_CPPEXTINCFLAGS"] = (
|
|
||||||
"${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE, affect_signature=False)}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# configure ENV for platform
|
# configure ENV for platform
|
||||||
env.platform_exporters = platform_exporters
|
env.platform_exporters = platform_exporters
|
||||||
env.platform_apis = platform_apis
|
env.platform_apis = platform_apis
|
||||||
|
@ -530,10 +529,10 @@ env.Decider("MD5-timestamp")
|
||||||
|
|
||||||
# SCons speed optimization controlled by the `fast_unsafe` option, which provide
|
# SCons speed optimization controlled by the `fast_unsafe` option, which provide
|
||||||
# more than 10 s speed up for incremental rebuilds.
|
# more than 10 s speed up for incremental rebuilds.
|
||||||
# Unsafe as they reduce the certainty of rebuilding all changed files, so it's
|
# Unsafe as they reduce the certainty of rebuilding all changed files.
|
||||||
# enabled by default for `debug` builds, and can be overridden from command line.
|
# If you use it and run into corrupted incremental builds, try to turn it off.
|
||||||
# Ref: https://github.com/SCons/scons/wiki/GoFastButton
|
# Ref: https://github.com/SCons/scons/wiki/GoFastButton
|
||||||
if methods.get_cmdline_bool("fast_unsafe", env.dev_build):
|
if env["fast_unsafe"]:
|
||||||
env.SetOption("implicit_cache", 1)
|
env.SetOption("implicit_cache", 1)
|
||||||
env.SetOption("max_drift", 60)
|
env.SetOption("max_drift", 60)
|
||||||
|
|
||||||
|
@ -556,6 +555,13 @@ if not env["deprecated"]:
|
||||||
if env["precision"] == "double":
|
if env["precision"] == "double":
|
||||||
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
||||||
|
|
||||||
|
# Library Support
|
||||||
|
if env["library_type"] != "executable":
|
||||||
|
if "library" not in env.get("supported", []):
|
||||||
|
print_error(f"Library builds unsupported for {env['platform']}")
|
||||||
|
Exit(255)
|
||||||
|
env.Append(CPPDEFINES=["LIBGODOT_ENABLED"])
|
||||||
|
|
||||||
# Default num_jobs to local cpu count if not user specified.
|
# Default num_jobs to local cpu count if not user specified.
|
||||||
# SCons has a peculiarity where user-specified options won't be overridden
|
# SCons has a peculiarity where user-specified options won't be overridden
|
||||||
# by SetOption, so we can rely on this to know if we should use our default.
|
# by SetOption, so we can rely on this to know if we should use our default.
|
||||||
|
@ -634,6 +640,7 @@ if env["strict_checks"]:
|
||||||
|
|
||||||
# Run SCU file generation script if in a SCU build.
|
# Run SCU file generation script if in a SCU build.
|
||||||
if env["scu_build"]:
|
if env["scu_build"]:
|
||||||
|
env.Append(CPPDEFINES=["SCU_BUILD_ENABLED"])
|
||||||
max_includes_per_scu = 8
|
max_includes_per_scu = 8
|
||||||
if env.dev_build:
|
if env.dev_build:
|
||||||
max_includes_per_scu = 1024
|
max_includes_per_scu = 1024
|
||||||
|
@ -965,19 +972,6 @@ else: # GCC, Clang
|
||||||
if env["werror"]:
|
if env["werror"]:
|
||||||
env.AppendUnique(CCFLAGS=["-Werror"])
|
env.AppendUnique(CCFLAGS=["-Werror"])
|
||||||
|
|
||||||
# Configure external includes.
|
|
||||||
if env.msvc:
|
|
||||||
if not methods.using_clang(env):
|
|
||||||
if cc_version_major < 16 or (cc_version_major == 16 and cc_version_minor < 10):
|
|
||||||
env.AppendUnique(CCFLAGS=["/experimental:external"])
|
|
||||||
env.AppendUnique(CCFLAGS=["/external:anglebrackets"])
|
|
||||||
env.AppendUnique(CCFLAGS=["/external:W0"])
|
|
||||||
env["EXTINCPREFIX"] = "/external:I"
|
|
||||||
env["EXTINCSUFFIX"] = ""
|
|
||||||
else:
|
|
||||||
env["EXTINCPREFIX"] = "-isystem "
|
|
||||||
env["EXTINCSUFFIX"] = ""
|
|
||||||
|
|
||||||
if hasattr(detect, "get_program_suffix"):
|
if hasattr(detect, "get_program_suffix"):
|
||||||
suffix = "." + detect.get_program_suffix()
|
suffix = "." + detect.get_program_suffix()
|
||||||
else:
|
else:
|
||||||
|
@ -1042,6 +1036,9 @@ if env["minizip"]:
|
||||||
if env["brotli"]:
|
if env["brotli"]:
|
||||||
env.Append(CPPDEFINES=["BROTLI_ENABLED"])
|
env.Append(CPPDEFINES=["BROTLI_ENABLED"])
|
||||||
|
|
||||||
|
if not env["disable_overrides"]:
|
||||||
|
env.Append(CPPDEFINES=["OVERRIDE_ENABLED"])
|
||||||
|
|
||||||
if not env["verbose"]:
|
if not env["verbose"]:
|
||||||
methods.no_verbose(env)
|
methods.no_verbose(env)
|
||||||
|
|
||||||
|
|
16
core/SCsub
16
core/SCsub
|
@ -51,8 +51,8 @@ if env["brotli"] and env["builtin_brotli"]:
|
||||||
]
|
]
|
||||||
thirdparty_brotli_sources = [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
|
thirdparty_brotli_sources = [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
|
||||||
|
|
||||||
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_brotli_dir + "include"])
|
env_thirdparty.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
|
||||||
env.Prepend(CPPEXTPATH=[thirdparty_brotli_dir + "include"])
|
env.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
|
||||||
|
|
||||||
if env.get("use_ubsan") or env.get("use_asan") or env.get("use_tsan") or env.get("use_lsan") or env.get("use_msan"):
|
if env.get("use_ubsan") or env.get("use_asan") or env.get("use_tsan") or env.get("use_lsan") or env.get("use_msan"):
|
||||||
env_thirdparty.Append(CPPDEFINES=["BROTLI_BUILD_PORTABLE"])
|
env_thirdparty.Append(CPPDEFINES=["BROTLI_BUILD_PORTABLE"])
|
||||||
|
@ -69,8 +69,8 @@ if env["builtin_clipper2"]:
|
||||||
]
|
]
|
||||||
thirdparty_clipper_sources = [thirdparty_clipper_dir + file for file in thirdparty_clipper_sources]
|
thirdparty_clipper_sources = [thirdparty_clipper_dir + file for file in thirdparty_clipper_sources]
|
||||||
|
|
||||||
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_clipper_dir + "include"])
|
env_thirdparty.Prepend(CPPPATH=[thirdparty_clipper_dir + "include"])
|
||||||
env.Prepend(CPPEXTPATH=[thirdparty_clipper_dir + "include"])
|
env.Prepend(CPPPATH=[thirdparty_clipper_dir + "include"])
|
||||||
|
|
||||||
env_thirdparty.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
|
env_thirdparty.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
|
||||||
env.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
|
env.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
|
||||||
|
@ -94,9 +94,9 @@ if env["builtin_zlib"]:
|
||||||
]
|
]
|
||||||
thirdparty_zlib_sources = [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]
|
thirdparty_zlib_sources = [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]
|
||||||
|
|
||||||
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_zlib_dir])
|
env_thirdparty.Prepend(CPPPATH=[thirdparty_zlib_dir])
|
||||||
# Needs to be available in main env too
|
# Needs to be available in main env too
|
||||||
env.Prepend(CPPEXTPATH=[thirdparty_zlib_dir])
|
env.Prepend(CPPPATH=[thirdparty_zlib_dir])
|
||||||
if env.dev_build:
|
if env.dev_build:
|
||||||
env_thirdparty.Append(CPPDEFINES=["ZLIB_DEBUG"])
|
env_thirdparty.Append(CPPDEFINES=["ZLIB_DEBUG"])
|
||||||
# Affects headers so it should also be defined for Godot code
|
# Affects headers so it should also be defined for Godot code
|
||||||
|
@ -151,9 +151,9 @@ if env["builtin_zstd"]:
|
||||||
thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S")
|
thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S")
|
||||||
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
|
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
|
||||||
|
|
||||||
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
|
env_thirdparty.Prepend(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
|
||||||
env_thirdparty.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
|
env_thirdparty.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
|
||||||
env.Prepend(CPPEXTPATH=thirdparty_zstd_dir)
|
env.Prepend(CPPPATH=thirdparty_zstd_dir)
|
||||||
# Also needed in main env includes will trigger warnings
|
# Also needed in main env includes will trigger warnings
|
||||||
env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
|
env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
|
||||||
|
|
||||||
|
|
|
@ -38,24 +38,40 @@
|
||||||
#include "core/version.h"
|
#include "core/version.h"
|
||||||
#include "servers/rendering/rendering_device.h"
|
#include "servers/rendering/rendering_device.h"
|
||||||
|
|
||||||
|
void Engine::_update_time_scale() {
|
||||||
|
_time_scale = _user_time_scale * _game_time_scale;
|
||||||
|
user_ips = MAX(1, ips * _user_time_scale);
|
||||||
|
max_user_physics_steps_per_frame = MAX(max_physics_steps_per_frame, max_physics_steps_per_frame * _user_time_scale);
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::set_physics_ticks_per_second(int p_ips) {
|
void Engine::set_physics_ticks_per_second(int p_ips) {
|
||||||
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
|
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
|
||||||
ips = p_ips;
|
ips = p_ips;
|
||||||
|
_update_time_scale();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Engine::get_physics_ticks_per_second() const {
|
int Engine::get_physics_ticks_per_second() const {
|
||||||
return ips;
|
return ips;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Engine::get_user_physics_ticks_per_second() const {
|
||||||
|
return user_ips;
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
|
void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
|
||||||
ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
|
ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
|
||||||
max_physics_steps_per_frame = p_max_physics_steps;
|
max_physics_steps_per_frame = p_max_physics_steps;
|
||||||
|
_update_time_scale();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Engine::get_max_physics_steps_per_frame() const {
|
int Engine::get_max_physics_steps_per_frame() const {
|
||||||
return max_physics_steps_per_frame;
|
return max_physics_steps_per_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Engine::get_user_max_physics_steps_per_frame() const {
|
||||||
|
return max_user_physics_steps_per_frame;
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::set_physics_jitter_fix(double p_threshold) {
|
void Engine::set_physics_jitter_fix(double p_threshold) {
|
||||||
if (p_threshold < 0) {
|
if (p_threshold < 0) {
|
||||||
p_threshold = 0;
|
p_threshold = 0;
|
||||||
|
@ -112,11 +128,21 @@ uint32_t Engine::get_frame_delay() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::set_time_scale(double p_scale) {
|
void Engine::set_time_scale(double p_scale) {
|
||||||
_time_scale = p_scale;
|
_game_time_scale = p_scale;
|
||||||
|
_update_time_scale();
|
||||||
}
|
}
|
||||||
|
|
||||||
double Engine::get_time_scale() const {
|
double Engine::get_time_scale() const {
|
||||||
return freeze_time_scale ? 0 : _time_scale;
|
return freeze_time_scale ? 0.0 : _game_time_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::set_user_time_scale(double p_scale) {
|
||||||
|
_user_time_scale = p_scale;
|
||||||
|
_update_time_scale();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Engine::get_effective_time_scale() const {
|
||||||
|
return freeze_time_scale ? 0.0 : _time_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Engine::get_unfrozen_time_scale() const {
|
double Engine::get_unfrozen_time_scale() const {
|
||||||
|
|
|
@ -30,10 +30,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/os/main_loop.h"
|
#include "core/string/string_name.h"
|
||||||
#include "core/string/ustring.h"
|
#include "core/templates/hash_map.h"
|
||||||
#include "core/templates/list.h"
|
#include "core/templates/list.h"
|
||||||
|
|
||||||
|
class Object;
|
||||||
|
class Dictionary;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedArray;
|
class TypedArray;
|
||||||
|
|
||||||
|
@ -59,13 +62,17 @@ private:
|
||||||
double _process_step = 0;
|
double _process_step = 0;
|
||||||
|
|
||||||
int ips = 60;
|
int ips = 60;
|
||||||
|
int user_ips = 60;
|
||||||
double physics_jitter_fix = 0.5;
|
double physics_jitter_fix = 0.5;
|
||||||
double _fps = 1;
|
double _fps = 1;
|
||||||
int _max_fps = 0;
|
int _max_fps = 0;
|
||||||
int _audio_output_latency = 0;
|
int _audio_output_latency = 0;
|
||||||
double _time_scale = 1.0;
|
double _time_scale = 1.0;
|
||||||
|
double _game_time_scale = 1.0;
|
||||||
|
double _user_time_scale = 1.0;
|
||||||
uint64_t _physics_frames = 0;
|
uint64_t _physics_frames = 0;
|
||||||
int max_physics_steps_per_frame = 8;
|
int max_physics_steps_per_frame = 8;
|
||||||
|
int max_user_physics_steps_per_frame = 8;
|
||||||
double _physics_interpolation_fraction = 0.0f;
|
double _physics_interpolation_fraction = 0.0f;
|
||||||
bool abort_on_gpu_errors = false;
|
bool abort_on_gpu_errors = false;
|
||||||
bool use_validation_layers = false;
|
bool use_validation_layers = false;
|
||||||
|
@ -101,14 +108,19 @@ private:
|
||||||
|
|
||||||
bool freeze_time_scale = false;
|
bool freeze_time_scale = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _update_time_scale();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Engine *get_singleton();
|
static Engine *get_singleton();
|
||||||
|
|
||||||
virtual void set_physics_ticks_per_second(int p_ips);
|
virtual void set_physics_ticks_per_second(int p_ips);
|
||||||
virtual int get_physics_ticks_per_second() const;
|
virtual int get_physics_ticks_per_second() const;
|
||||||
|
virtual int get_user_physics_ticks_per_second() const;
|
||||||
|
|
||||||
virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
|
virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
|
||||||
virtual int get_max_physics_steps_per_frame() const;
|
virtual int get_max_physics_steps_per_frame() const;
|
||||||
|
virtual int get_user_max_physics_steps_per_frame() const;
|
||||||
|
|
||||||
void set_physics_jitter_fix(double p_threshold);
|
void set_physics_jitter_fix(double p_threshold);
|
||||||
double get_physics_jitter_fix() const;
|
double get_physics_jitter_fix() const;
|
||||||
|
@ -132,6 +144,8 @@ public:
|
||||||
|
|
||||||
void set_time_scale(double p_scale);
|
void set_time_scale(double p_scale);
|
||||||
double get_time_scale() const;
|
double get_time_scale() const;
|
||||||
|
void set_user_time_scale(double p_scale);
|
||||||
|
double get_effective_time_scale() const;
|
||||||
double get_unfrozen_time_scale() const;
|
double get_unfrozen_time_scale() const;
|
||||||
|
|
||||||
void set_print_to_stdout(bool p_enabled);
|
void set_print_to_stdout(bool p_enabled);
|
||||||
|
|
|
@ -83,6 +83,11 @@ const PackedStringArray ProjectSettings::get_required_features() {
|
||||||
// Returns the features supported by this build of Godot. Includes all required features.
|
// Returns the features supported by this build of Godot. Includes all required features.
|
||||||
const PackedStringArray ProjectSettings::_get_supported_features() {
|
const PackedStringArray ProjectSettings::_get_supported_features() {
|
||||||
PackedStringArray features = get_required_features();
|
PackedStringArray features = get_required_features();
|
||||||
|
|
||||||
|
#ifdef LIBGODOT_ENABLED
|
||||||
|
features.append("LibGodot");
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE_MONO_ENABLED
|
#ifdef MODULE_MONO_ENABLED
|
||||||
features.append("C#");
|
features.append("C#");
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,7 +285,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
if (p_value.get_type() == Variant::NIL) {
|
if (p_value.get_type() == Variant::NIL) {
|
||||||
props.erase(p_name);
|
props.erase(p_name);
|
||||||
if (p_name.operator String().begins_with("autoload/")) {
|
if (p_name.operator String().begins_with("autoload/")) {
|
||||||
String node_name = p_name.operator String().split("/")[1];
|
String node_name = p_name.operator String().get_slicec('/', 1);
|
||||||
if (autoloads.has(node_name)) {
|
if (autoloads.has(node_name)) {
|
||||||
remove_autoload(node_name);
|
remove_autoload(node_name);
|
||||||
}
|
}
|
||||||
|
@ -326,7 +331,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
props[p_name] = VariantContainer(p_value, last_order++);
|
props[p_name] = VariantContainer(p_value, last_order++);
|
||||||
}
|
}
|
||||||
if (p_name.operator String().begins_with("autoload/")) {
|
if (p_name.operator String().begins_with("autoload/")) {
|
||||||
String node_name = p_name.operator String().split("/")[1];
|
String node_name = p_name.operator String().get_slicec('/', 1);
|
||||||
AutoloadInfo autoload;
|
AutoloadInfo autoload;
|
||||||
autoload.name = node_name;
|
autoload.name = node_name;
|
||||||
String path = p_value;
|
String path = p_value;
|
||||||
|
@ -643,11 +648,16 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, vformat("Cannot open resource pack '%s'.", p_main_pack));
|
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, vformat("Cannot open resource pack '%s'.", p_main_pack));
|
||||||
|
|
||||||
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
||||||
|
#ifdef OVERRIDE_ENABLED
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Load override from location of the main pack
|
// Load override from location of the main pack
|
||||||
// Optional, we don't mind if it fails
|
// Optional, we don't mind if it fails
|
||||||
_load_settings_text(p_main_pack.get_base_dir().path_join("override.cfg"));
|
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
||||||
|
if (!disable_override) {
|
||||||
|
_load_settings_text(p_main_pack.get_base_dir().path_join("override.cfg"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif // OVERRIDE_ENABLED
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,12 +703,17 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
// If we opened our package, try and load our project.
|
// If we opened our package, try and load our project.
|
||||||
if (found) {
|
if (found) {
|
||||||
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
||||||
|
#ifdef OVERRIDE_ENABLED
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Load overrides from the PCK and the executable location.
|
// Load overrides from the PCK and the executable location.
|
||||||
// Optional, we don't mind if either fails.
|
// Optional, we don't mind if either fails.
|
||||||
_load_settings_text("res://override.cfg");
|
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
||||||
_load_settings_text(exec_path.get_base_dir().path_join("override.cfg"));
|
if (!disable_override) {
|
||||||
|
_load_settings_text("res://override.cfg");
|
||||||
|
_load_settings_text(exec_path.get_base_dir().path_join("override.cfg"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif // OVERRIDE_ENABLED
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,10 +728,15 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
|
|
||||||
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
|
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
|
||||||
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
||||||
|
#ifdef OVERRIDE_ENABLED
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Optional, we don't mind if it fails.
|
// Optional, we don't mind if it fails.
|
||||||
_load_settings_text("res://override.cfg");
|
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
||||||
|
if (!disable_override) {
|
||||||
|
_load_settings_text("res://override.cfg");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif // OVERRIDE_ENABLED
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,11 +756,16 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
err = _load_settings_text_or_binary(resource_path.path_join("project.godot"), resource_path.path_join("project.binary"));
|
err = _load_settings_text_or_binary(resource_path.path_join("project.godot"), resource_path.path_join("project.binary"));
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Optional, we don't mind if it fails.
|
// Optional, we don't mind if it fails.
|
||||||
_load_settings_text(resource_path.path_join("override.cfg"));
|
#ifdef OVERRIDE_ENABLED
|
||||||
|
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
||||||
|
if (!disable_override) {
|
||||||
|
_load_settings_text(resource_path.path_join("override.cfg"));
|
||||||
|
}
|
||||||
|
#endif // OVERRIDE_ENABLED
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // MACOS_ENABLED
|
||||||
|
|
||||||
// Nothing was found, try to find a project file in provided path (`p_path`)
|
// Nothing was found, try to find a project file in provided path (`p_path`)
|
||||||
// or, if requested (`p_upwards`) in parent directories.
|
// or, if requested (`p_upwards`) in parent directories.
|
||||||
|
@ -760,7 +785,12 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
|
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Optional, we don't mind if it fails.
|
// Optional, we don't mind if it fails.
|
||||||
_load_settings_text(current_dir.path_join("override.cfg"));
|
#ifdef OVERRIDE_ENABLED
|
||||||
|
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
||||||
|
if (!disable_override) {
|
||||||
|
_load_settings_text(current_dir.path_join("override.cfg"));
|
||||||
|
}
|
||||||
|
#endif // OVERRIDE_ENABLED
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1569,6 +1599,7 @@ ProjectSettings::ProjectSettings() {
|
||||||
GLOBAL_DEF("application/config/use_custom_user_dir", false);
|
GLOBAL_DEF("application/config/use_custom_user_dir", false);
|
||||||
GLOBAL_DEF("application/config/custom_user_dir_name", "");
|
GLOBAL_DEF("application/config/custom_user_dir_name", "");
|
||||||
GLOBAL_DEF("application/config/project_settings_override", "");
|
GLOBAL_DEF("application/config/project_settings_override", "");
|
||||||
|
GLOBAL_DEF("application/config/disable_project_settings_override", false);
|
||||||
|
|
||||||
GLOBAL_DEF("application/run/main_loop_type", "SceneTree");
|
GLOBAL_DEF("application/run/main_loop_type", "SceneTree");
|
||||||
GLOBAL_DEF("application/config/auto_accept_quit", true);
|
GLOBAL_DEF("application/config/auto_accept_quit", true);
|
||||||
|
@ -1675,6 +1706,7 @@ ProjectSettings::ProjectSettings() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
|
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
|
||||||
|
GLOBAL_DEF("gui/common/always_show_focus_state", false);
|
||||||
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
|
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
|
||||||
|
|
||||||
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
|
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
|
||||||
|
@ -1698,7 +1730,7 @@ ProjectSettings::ProjectSettings() {
|
||||||
// installed by the scripts provided in the repository
|
// installed by the scripts provided in the repository
|
||||||
// (check `misc/scripts/install_d3d12_sdk_windows.py`).
|
// (check `misc/scripts/install_d3d12_sdk_windows.py`).
|
||||||
// For example, if the script installs 1.613.3, the default value must be 613.
|
// For example, if the script installs 1.613.3, the default value must be 613.
|
||||||
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_slider"), 613);
|
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_control"), 613);
|
||||||
|
|
||||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1);
|
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1);
|
||||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0);
|
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0);
|
||||||
|
@ -1732,6 +1764,14 @@ ProjectSettings::ProjectSettings() {
|
||||||
GLOBAL_DEF("navigation/baking/thread_model/baking_use_multiple_threads", true);
|
GLOBAL_DEF("navigation/baking/thread_model/baking_use_multiple_threads", true);
|
||||||
GLOBAL_DEF("navigation/baking/thread_model/baking_use_high_priority_threads", true);
|
GLOBAL_DEF("navigation/baking/thread_model/baking_use_high_priority_threads", true);
|
||||||
#endif // !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
|
#endif // !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
|
||||||
|
#ifndef NAVIGATION_2D_DISABLED
|
||||||
|
GLOBAL_DEF("navigation/2d/warnings/navmesh_edge_merge_errors", true);
|
||||||
|
GLOBAL_DEF("navigation/2d/warnings/navmesh_cell_size_mismatch", true);
|
||||||
|
#endif // NAVIGATION_2D_DISABLED
|
||||||
|
#ifndef NAVIGATION_3D_DISABLED
|
||||||
|
GLOBAL_DEF("navigation/3d/warnings/navmesh_edge_merge_errors", true);
|
||||||
|
GLOBAL_DEF("navigation/3d/warnings/navmesh_cell_size_mismatch", true);
|
||||||
|
#endif // NAVIGATION_3D_DISABLED
|
||||||
|
|
||||||
ProjectSettings::get_singleton()->add_hidden_prefix("input/");
|
ProjectSettings::get_singleton()->add_hidden_prefix("input/");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/object.h"
|
||||||
|
#include "core/templates/rb_map.h"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedArray;
|
class TypedArray;
|
||||||
|
@ -49,7 +50,7 @@ class ProjectSettings : public Object {
|
||||||
public:
|
public:
|
||||||
typedef HashMap<String, Variant> CustomMap;
|
typedef HashMap<String, Variant> CustomMap;
|
||||||
static inline const String PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
|
static inline const String PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
|
||||||
static inline const String EDITOR_SETTING_OVERRIDE_PREFIX = "editor_overrides/";
|
static inline const String EDITOR_SETTING_OVERRIDE_PREFIX = PNAME("editor_overrides") + String("/");
|
||||||
|
|
||||||
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
|
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
|
||||||
constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16;
|
constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16;
|
||||||
|
|
|
@ -35,10 +35,12 @@
|
||||||
#include "core/crypto/crypto_core.h"
|
#include "core/crypto/crypto_core.h"
|
||||||
#include "core/debugger/engine_debugger.h"
|
#include "core/debugger/engine_debugger.h"
|
||||||
#include "core/debugger/script_debugger.h"
|
#include "core/debugger/script_debugger.h"
|
||||||
|
#include "core/io/file_access.h"
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/math/geometry_2d.h"
|
#include "core/math/geometry_2d.h"
|
||||||
#include "core/math/geometry_3d.h"
|
#include "core/math/geometry_3d.h"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
|
#include "core/os/main_loop.h"
|
||||||
#include "core/os/thread_safe.h"
|
#include "core/os/thread_safe.h"
|
||||||
#include "core/variant/typed_array.h"
|
#include "core/variant/typed_array.h"
|
||||||
|
|
||||||
|
@ -1526,6 +1528,10 @@ void Thread::set_thread_safety_checks_enabled(bool p_enabled) {
|
||||||
set_current_thread_safe_for_nodes(!p_enabled);
|
set_current_thread_safe_for_nodes(!p_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thread::is_main_thread() {
|
||||||
|
return ::Thread::is_main_thread();
|
||||||
|
}
|
||||||
|
|
||||||
void Thread::_bind_methods() {
|
void Thread::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("start", "callable", "priority"), &Thread::start, DEFVAL(PRIORITY_NORMAL));
|
ClassDB::bind_method(D_METHOD("start", "callable", "priority"), &Thread::start, DEFVAL(PRIORITY_NORMAL));
|
||||||
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
|
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
|
||||||
|
@ -1534,6 +1540,7 @@ void Thread::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
|
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
|
||||||
|
|
||||||
ClassDB::bind_static_method("Thread", D_METHOD("set_thread_safety_checks_enabled", "enabled"), &Thread::set_thread_safety_checks_enabled);
|
ClassDB::bind_static_method("Thread", D_METHOD("set_thread_safety_checks_enabled", "enabled"), &Thread::set_thread_safety_checks_enabled);
|
||||||
|
ClassDB::bind_static_method("Thread", D_METHOD("is_main_thread"), &Thread::is_main_thread);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(PRIORITY_LOW);
|
BIND_ENUM_CONSTANT(PRIORITY_LOW);
|
||||||
BIND_ENUM_CONSTANT(PRIORITY_NORMAL);
|
BIND_ENUM_CONSTANT(PRIORITY_NORMAL);
|
||||||
|
@ -1545,14 +1552,16 @@ namespace Special {
|
||||||
////// ClassDB //////
|
////// ClassDB //////
|
||||||
|
|
||||||
PackedStringArray ClassDB::get_class_list() const {
|
PackedStringArray ClassDB::get_class_list() const {
|
||||||
List<StringName> classes;
|
LocalVector<StringName> classes;
|
||||||
::ClassDB::get_class_list(&classes);
|
::ClassDB::get_class_list(classes);
|
||||||
|
|
||||||
PackedStringArray ret;
|
PackedStringArray ret;
|
||||||
ret.resize(classes.size());
|
ret.resize(classes.size());
|
||||||
|
String *ptrw = ret.ptrw();
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (const StringName &E : classes) {
|
for (const StringName &cls : classes) {
|
||||||
ret.set(idx++, E);
|
ptrw[idx] = cls;
|
||||||
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1806,8 +1815,12 @@ void ClassDB::get_argument_options(const StringName &p_function, int p_idx, List
|
||||||
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
|
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
|
||||||
}
|
}
|
||||||
if (first_argument_is_class || pf == "is_parent_class") {
|
if (first_argument_is_class || pf == "is_parent_class") {
|
||||||
for (const String &E : get_class_list()) {
|
LocalVector<StringName> classes;
|
||||||
r_options->push_back(E.quote());
|
::ClassDB::get_class_list(classes);
|
||||||
|
for (const StringName &E : classes) {
|
||||||
|
if (::ClassDB::is_class_exposed(E)) {
|
||||||
|
r_options->push_back(E.operator String().quote());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -495,6 +495,7 @@ public:
|
||||||
Variant wait_to_finish();
|
Variant wait_to_finish();
|
||||||
|
|
||||||
static void set_thread_safety_checks_enabled(bool p_enabled);
|
static void set_thread_safety_checks_enabled(bool p_enabled);
|
||||||
|
static bool is_main_thread();
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Special {
|
namespace Special {
|
||||||
|
|
|
@ -11,7 +11,7 @@ def disabled_class_builder(target, source, env):
|
||||||
with methods.generated_wrapper(str(target[0])) as file:
|
with methods.generated_wrapper(str(target[0])) as file:
|
||||||
for c in source[0].read():
|
for c in source[0].read():
|
||||||
if cs := c.strip():
|
if cs := c.strip():
|
||||||
file.write(f"#define ClassDB_Disable_{cs} 1\n")
|
file.write(f"class {cs}; template <> struct is_class_enabled<{cs}> : std::false_type {{}};\n")
|
||||||
|
|
||||||
|
|
||||||
# Generate version info
|
# Generate version info
|
||||||
|
|
|
@ -75,7 +75,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -83,7 +83,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_bitfield_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -92,7 +92,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
// This just binds enum classes as if they were regular enum constants.
|
// This just binds enum classes as if they were regular enum constants.
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -100,7 +100,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -108,7 +108,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -116,7 +116,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member, false, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member, false, true)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -124,7 +124,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -132,7 +132,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -144,7 +144,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -152,7 +152,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -166,7 +166,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -174,7 +174,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_bitfield_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -183,7 +183,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
// This just binds enum classes as if they were regular enum constants.
|
// This just binds enum classes as if they were regular enum constants.
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -191,7 +191,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -199,7 +199,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -207,7 +207,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -215,7 +215,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -223,7 +223,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -235,7 +235,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -243,7 +243,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
|
|
@ -13,7 +13,7 @@ if is_builtin or not has_module:
|
||||||
# Use our headers for builtin or if the module is not going to be compiled.
|
# Use our headers for builtin or if the module is not going to be compiled.
|
||||||
# We decided not to depend on system mbedtls just for these few files that can
|
# We decided not to depend on system mbedtls just for these few files that can
|
||||||
# be easily extracted.
|
# be easily extracted.
|
||||||
env_crypto.Prepend(CPPEXTPATH=["#thirdparty/mbedtls/include"])
|
env_crypto.Prepend(CPPPATH=["#thirdparty/mbedtls/include"])
|
||||||
|
|
||||||
# MbedTLS core functions (for CryptoCore).
|
# MbedTLS core functions (for CryptoCore).
|
||||||
# If the mbedtls module is compiled we don't need to add the .c files with our
|
# If the mbedtls module is compiled we don't need to add the .c files with our
|
||||||
|
|
|
@ -149,6 +149,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
|
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
|
||||||
|
GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
||||||
|
@ -161,6 +163,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
|
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
|
||||||
|
GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
||||||
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
||||||
|
|
|
@ -121,7 +121,10 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
|
||||||
}
|
}
|
||||||
|
|
||||||
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
|
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
|
||||||
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more.
|
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create_tcp); // TCP is the default protocol. Platforms/modules can add more.
|
||||||
|
#ifdef UNIX_ENABLED
|
||||||
|
register_uri_handler("unix://", RemoteDebuggerPeerTCP::create_unix);
|
||||||
|
#endif
|
||||||
if (p_uri.is_empty()) {
|
if (p_uri.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -132,10 +135,10 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bo
|
||||||
OS::get_singleton()->initialize_debugging();
|
OS::get_singleton()->initialize_debugging();
|
||||||
} else if (p_uri.contains("://")) {
|
} else if (p_uri.contains("://")) {
|
||||||
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
|
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
|
||||||
if (!protocols.has(proto)) {
|
CreatePeerFunc *create_fn = protocols.getptr(proto);
|
||||||
return;
|
ERR_FAIL_NULL_MSG(create_fn, vformat("Invalid protocol: %s.", proto));
|
||||||
}
|
|
||||||
RemoteDebuggerPeer *peer = protocols[proto](p_uri);
|
RemoteDebuggerPeer *peer = (*create_fn)(p_uri);
|
||||||
if (!peer) {
|
if (!peer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "local_debugger.h"
|
#include "local_debugger.h"
|
||||||
|
|
||||||
#include "core/debugger/script_debugger.h"
|
#include "core/debugger/script_debugger.h"
|
||||||
|
#include "core/os/main_loop.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
|
||||||
struct LocalDebugger::ScriptsProfiler {
|
struct LocalDebugger::ScriptsProfiler {
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
#include "core/math/expression.h"
|
#include "core/math/expression.h"
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "servers/display_server.h"
|
#include "servers/display/display_server.h"
|
||||||
|
|
||||||
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
|
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
|
||||||
Object *performance = nullptr;
|
Object *performance = nullptr;
|
||||||
|
@ -48,9 +48,9 @@ class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
|
||||||
uint64_t last_monitor_modification_time = 0;
|
uint64_t last_monitor_modification_time = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void toggle(bool p_enable, const Array &p_opts) {}
|
void toggle(bool p_enable, const Array &p_opts) override {}
|
||||||
void add(const Array &p_data) {}
|
void add(const Array &p_data) override {}
|
||||||
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
|
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) override {
|
||||||
if (!performance) {
|
if (!performance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -566,25 +566,25 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
|
||||||
input_vals.append(V);
|
input_vals.append(V);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<StringName> native_types;
|
LocalVector<StringName> native_types;
|
||||||
ClassDB::get_class_list(&native_types);
|
ClassDB::get_class_list(native_types);
|
||||||
for (const StringName &E : native_types) {
|
for (const StringName &class_name : native_types) {
|
||||||
if (!ClassDB::is_class_exposed(E) || !Engine::get_singleton()->has_singleton(E) || Engine::get_singleton()->is_singleton_editor_only(E)) {
|
if (!ClassDB::is_class_exposed(class_name) || !Engine::get_singleton()->has_singleton(class_name) || Engine::get_singleton()->is_singleton_editor_only(class_name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_names.append(E);
|
input_names.append(class_name);
|
||||||
input_vals.append(Engine::get_singleton()->get_singleton_object(E));
|
input_vals.append(Engine::get_singleton()->get_singleton_object(class_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<StringName> user_types;
|
LocalVector<StringName> user_types;
|
||||||
ScriptServer::get_global_class_list(&user_types);
|
ScriptServer::get_global_class_list(user_types);
|
||||||
for (const StringName &S : user_types) {
|
for (const StringName &class_name : user_types) {
|
||||||
String scr_path = ScriptServer::get_global_class_path(S);
|
String scr_path = ScriptServer::get_global_class_path(class_name);
|
||||||
Ref<Script> scr = ResourceLoader::load(scr_path, "Script");
|
Ref<Script> scr = ResourceLoader::load(scr_path, "Script");
|
||||||
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", S, scr_path));
|
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", class_name, scr_path));
|
||||||
|
|
||||||
input_names.append(S);
|
input_names.append(class_name);
|
||||||
input_vals.append(scr);
|
input_vals.append(scr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,18 +76,19 @@ void RemoteDebuggerPeerTCP::close() {
|
||||||
in_buf.clear();
|
in_buf.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp) {
|
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP() {
|
||||||
// This means remote debugger takes 16 MiB just because it exists...
|
// This means remote debugger takes 16 MiB just because it exists...
|
||||||
in_buf.resize((8 << 20) + 4); // 8 MiB should be way more than enough (need 4 extra bytes for encoding packet size).
|
in_buf.resize((8 << 20) + 4); // 8 MiB should be way more than enough (need 4 extra bytes for encoding packet size).
|
||||||
out_buf.resize(8 << 20); // 8 MiB should be way more than enough
|
out_buf.resize(8 << 20); // 8 MiB should be way more than enough
|
||||||
tcp_client = p_tcp;
|
}
|
||||||
if (tcp_client.is_valid()) { // Attaching to an already connected stream.
|
|
||||||
connected = true;
|
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream) :
|
||||||
running = true;
|
RemoteDebuggerPeerTCP() {
|
||||||
thread.start(_thread_func, this);
|
DEV_ASSERT(p_stream.is_valid());
|
||||||
} else {
|
tcp_client = p_stream;
|
||||||
tcp_client.instantiate();
|
connected = true;
|
||||||
}
|
running = true;
|
||||||
|
thread.start(_thread_func, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
|
RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
|
||||||
|
@ -154,22 +155,10 @@ void RemoteDebuggerPeerTCP::_read_in() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) {
|
Error RemoteDebuggerPeerTCP::_try_connect(Ref<StreamPeerSocket> tcp_client) {
|
||||||
IPAddress ip;
|
|
||||||
if (p_host.is_valid_ip_address()) {
|
|
||||||
ip = p_host;
|
|
||||||
} else {
|
|
||||||
ip = IP::get_singleton()->resolve_hostname(p_host);
|
|
||||||
}
|
|
||||||
|
|
||||||
int port = p_port;
|
|
||||||
|
|
||||||
const int tries = 6;
|
const int tries = 6;
|
||||||
const int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
|
const int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
|
||||||
|
|
||||||
Error err = tcp_client->connect_to_host(ip, port);
|
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Remote Debugger: Unable to connect to host '%s:%d'.", p_host, port));
|
|
||||||
|
|
||||||
for (int i = 0; i < tries; i++) {
|
for (int i = 0; i < tries; i++) {
|
||||||
tcp_client->poll();
|
tcp_client->poll();
|
||||||
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
|
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
|
||||||
|
@ -186,9 +175,6 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
|
||||||
ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num_int64(tcp_client->get_status())));
|
ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num_int64(tcp_client->get_status())));
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
connected = true;
|
|
||||||
running = true;
|
|
||||||
thread.start(_thread_func, this);
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +208,7 @@ void RemoteDebuggerPeerTCP::_poll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
|
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
|
||||||
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
|
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
|
||||||
|
|
||||||
String debug_host = p_uri.replace("tcp://", "");
|
String debug_host = p_uri.replace("tcp://", "");
|
||||||
|
@ -234,13 +220,30 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
|
||||||
debug_host = debug_host.substr(0, sep_pos);
|
debug_host = debug_host.substr(0, sep_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP);
|
IPAddress ip;
|
||||||
Error err = peer->connect_to_host(debug_host, debug_port);
|
if (debug_host.is_valid_ip_address()) {
|
||||||
if (err != OK) {
|
ip = debug_host;
|
||||||
memdelete(peer);
|
} else {
|
||||||
return nullptr;
|
ip = IP::get_singleton()->resolve_hostname(debug_host);
|
||||||
}
|
}
|
||||||
return peer;
|
|
||||||
|
Ref<StreamPeerTCP> stream;
|
||||||
|
stream.instantiate();
|
||||||
|
ERR_FAIL_COND_V_MSG(stream->connect_to_host(ip, debug_port) != OK, nullptr, vformat("Remote Debugger: Unable to connect to host '%s:%d'.", debug_host, debug_port));
|
||||||
|
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
|
||||||
|
return memnew(RemoteDebuggerPeerTCP(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_unix(const String &p_uri) {
|
||||||
|
ERR_FAIL_COND_V(!p_uri.begins_with("unix://"), nullptr);
|
||||||
|
|
||||||
|
String debug_path = p_uri.replace("unix://", "");
|
||||||
|
Ref<StreamPeerUDS> stream;
|
||||||
|
stream.instantiate();
|
||||||
|
Error err = stream->connect_to_host(debug_path);
|
||||||
|
ERR_FAIL_COND_V_MSG(err != OK && err != ERR_BUSY, nullptr, vformat("Remote Debugger: Unable to connect to socket path '%s'.", debug_path));
|
||||||
|
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
|
||||||
|
return memnew(RemoteDebuggerPeerTCP(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeer::RemoteDebuggerPeer() {
|
RemoteDebuggerPeer::RemoteDebuggerPeer() {
|
||||||
|
|
|
@ -31,12 +31,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/io/stream_peer_tcp.h"
|
#include "core/io/stream_peer_tcp.h"
|
||||||
|
#include "core/io/stream_peer_uds.h"
|
||||||
#include "core/object/ref_counted.h"
|
#include "core/object/ref_counted.h"
|
||||||
#include "core/os/mutex.h"
|
#include "core/os/mutex.h"
|
||||||
#include "core/os/thread.h"
|
#include "core/os/thread.h"
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
|
|
||||||
class RemoteDebuggerPeer : public RefCounted {
|
class RemoteDebuggerPeer : public RefCounted {
|
||||||
|
GDSOFTCLASS(RemoteDebuggerPeer, RefCounted);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int max_queued_messages = 4096;
|
int max_queued_messages = 4096;
|
||||||
|
|
||||||
|
@ -54,8 +57,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
|
class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
|
||||||
|
GDSOFTCLASS(RemoteDebuggerPeerTCP, RemoteDebuggerPeer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<StreamPeerTCP> tcp_client;
|
Ref<StreamPeerSocket> tcp_client;
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
Thread thread;
|
Thread thread;
|
||||||
List<Array> in_queue;
|
List<Array> in_queue;
|
||||||
|
@ -74,11 +79,11 @@ private:
|
||||||
void _poll();
|
void _poll();
|
||||||
void _write_out();
|
void _write_out();
|
||||||
void _read_in();
|
void _read_in();
|
||||||
|
static Error _try_connect(Ref<StreamPeerSocket> p_stream);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static RemoteDebuggerPeer *create(const String &p_uri);
|
static RemoteDebuggerPeer *create_tcp(const String &p_uri);
|
||||||
|
static RemoteDebuggerPeer *create_unix(const String &p_uri);
|
||||||
Error connect_to_host(const String &p_host, uint16_t p_port);
|
|
||||||
|
|
||||||
bool is_peer_connected() override;
|
bool is_peer_connected() override;
|
||||||
int get_max_message_size() const override;
|
int get_max_message_size() const override;
|
||||||
|
@ -88,6 +93,7 @@ public:
|
||||||
void poll() override;
|
void poll() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
|
RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream);
|
||||||
|
RemoteDebuggerPeerTCP();
|
||||||
~RemoteDebuggerPeerTCP();
|
~RemoteDebuggerPeerTCP();
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include "error_list.h"
|
#include "error_list.h"
|
||||||
|
|
||||||
#include <iterator>
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
const char *error_names[] = {
|
const char *error_names[] = {
|
||||||
"OK", // OK
|
"OK", // OK
|
||||||
|
@ -84,4 +84,4 @@ const char *error_names[] = {
|
||||||
"Printer on fire", // ERR_PRINTER_ON_FIRE
|
"Printer on fire", // ERR_PRINTER_ON_FIRE
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(std::size(error_names) == ERR_MAX);
|
static_assert(std_size(error_names) == ERR_MAX);
|
||||||
|
|
|
@ -96,7 +96,7 @@ static String fix_doc_description(const String &p_bbcode) {
|
||||||
// Based on what EditorHelp does.
|
// Based on what EditorHelp does.
|
||||||
|
|
||||||
return p_bbcode.dedent()
|
return p_bbcode.dedent()
|
||||||
.remove_chars("\t\r")
|
.remove_chars("\r")
|
||||||
.strip_edges();
|
.strip_edges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,11 +900,9 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
|
||||||
// classes
|
// classes
|
||||||
Array classes;
|
Array classes;
|
||||||
|
|
||||||
List<StringName> class_list;
|
LocalVector<StringName> class_list;
|
||||||
|
|
||||||
ClassDB::get_class_list(&class_list);
|
ClassDB::get_class_list(class_list);
|
||||||
|
|
||||||
class_list.sort_custom<StringName::AlphCompare>();
|
|
||||||
|
|
||||||
for (const StringName &class_name : class_list) {
|
for (const StringName &class_name : class_list) {
|
||||||
if (!ClassDB::is_class_exposed(class_name)) {
|
if (!ClassDB::is_class_exposed(class_name)) {
|
||||||
|
|
|
@ -267,6 +267,7 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClassCreationDeprecatedInfo legacy = {
|
const ClassCreationDeprecatedInfo legacy = {
|
||||||
|
false,
|
||||||
p_extension_funcs->notification_func, // GDExtensionClassNotification notification_func;
|
p_extension_funcs->notification_func, // GDExtensionClassNotification notification_func;
|
||||||
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
|
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
|
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
|
||||||
|
@ -281,7 +282,7 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
|
||||||
const GDExtensionClassCreationInfo5 class_info5 = {
|
const GDExtensionClassCreationInfo5 class_info5 = {
|
||||||
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
|
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
|
||||||
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
|
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
|
||||||
true, // GDExtensionBool is_exposed;
|
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
|
||||||
false, // GDExtensionBool is_runtime;
|
false, // GDExtensionBool is_runtime;
|
||||||
nullptr, // GDExtensionConstStringPtr icon_path;
|
nullptr, // GDExtensionConstStringPtr icon_path;
|
||||||
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
|
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
|
||||||
|
@ -305,6 +306,7 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClassCreationDeprecatedInfo legacy = {
|
const ClassCreationDeprecatedInfo legacy = {
|
||||||
|
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
|
||||||
nullptr, // GDExtensionClassNotification notification_func;
|
nullptr, // GDExtensionClassNotification notification_func;
|
||||||
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
|
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
|
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
|
||||||
|
@ -319,7 +321,7 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
|
||||||
const GDExtensionClassCreationInfo5 class_info5 = {
|
const GDExtensionClassCreationInfo5 class_info5 = {
|
||||||
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
|
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
|
||||||
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
|
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
|
||||||
true, // GDExtensionBool is_exposed;
|
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
|
||||||
p_extension_funcs->is_runtime, // GDExtensionBool is_runtime;
|
p_extension_funcs->is_runtime, // GDExtensionBool is_runtime;
|
||||||
nullptr, // GDExtensionConstStringPtr icon_path;
|
nullptr, // GDExtensionConstStringPtr icon_path;
|
||||||
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
|
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
|
||||||
|
@ -343,6 +345,7 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClassCreationDeprecatedInfo legacy = {
|
const ClassCreationDeprecatedInfo legacy = {
|
||||||
|
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
|
||||||
nullptr, // GDExtensionClassNotification notification_func;
|
nullptr, // GDExtensionClassNotification notification_func;
|
||||||
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
|
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance2 create_instance_func;
|
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance2 create_instance_func;
|
||||||
|
@ -355,9 +358,16 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
|
||||||
|
|
||||||
void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs) {
|
void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs) {
|
||||||
GDExtensionClassCreationInfo5 class_info5 = *p_extension_funcs;
|
GDExtensionClassCreationInfo5 class_info5 = *p_extension_funcs;
|
||||||
// Force classes to be exposed, because the behavior of unexposed classes changed in an incompatible (albeit, minor) way.
|
const ClassCreationDeprecatedInfo legacy = {
|
||||||
class_info5.is_exposed = true;
|
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
|
||||||
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5);
|
nullptr, // GDExtensionClassNotification notification_func;
|
||||||
|
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||||
|
nullptr, // GDExtensionClassCreateInstance2 create_instance_func;
|
||||||
|
nullptr, // GDExtensionClassGetRID get_rid;
|
||||||
|
nullptr, // GDExtensionClassGetVirtual get_virtual_func;
|
||||||
|
nullptr, // GDExtensionClassGetVirtual get_virtual_func;
|
||||||
|
};
|
||||||
|
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5, &legacy);
|
||||||
}
|
}
|
||||||
#endif // DISABLE_DEPRECATED
|
#endif // DISABLE_DEPRECATED
|
||||||
|
|
||||||
|
@ -447,6 +457,7 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
|
||||||
extension->gdextension.validate_property = p_extension_funcs->validate_property_func;
|
extension->gdextension.validate_property = p_extension_funcs->validate_property_func;
|
||||||
#ifndef DISABLE_DEPRECATED
|
#ifndef DISABLE_DEPRECATED
|
||||||
if (p_deprecated_funcs) {
|
if (p_deprecated_funcs) {
|
||||||
|
extension->gdextension.legacy_unexposed_class = p_deprecated_funcs->legacy_unexposed_class;
|
||||||
extension->gdextension.notification = p_deprecated_funcs->notification_func;
|
extension->gdextension.notification = p_deprecated_funcs->notification_func;
|
||||||
extension->gdextension.free_property_list = p_deprecated_funcs->free_property_list_func;
|
extension->gdextension.free_property_list = p_deprecated_funcs->free_property_list_func;
|
||||||
extension->gdextension.create_instance = p_deprecated_funcs->create_instance_func;
|
extension->gdextension.create_instance = p_deprecated_funcs->create_instance_func;
|
||||||
|
|
|
@ -67,6 +67,7 @@ class GDExtension : public Resource {
|
||||||
|
|
||||||
struct ClassCreationDeprecatedInfo {
|
struct ClassCreationDeprecatedInfo {
|
||||||
#ifndef DISABLE_DEPRECATED
|
#ifndef DISABLE_DEPRECATED
|
||||||
|
bool legacy_unexposed_class = false;
|
||||||
GDExtensionClassNotification notification_func = nullptr;
|
GDExtensionClassNotification notification_func = nullptr;
|
||||||
GDExtensionClassFreePropertyList free_property_list_func = nullptr;
|
GDExtensionClassFreePropertyList free_property_list_func = nullptr;
|
||||||
GDExtensionClassCreateInstance create_instance_func = nullptr;
|
GDExtensionClassCreateInstance create_instance_func = nullptr;
|
||||||
|
@ -183,6 +184,8 @@ public:
|
||||||
VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
|
VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
|
||||||
|
|
||||||
class GDExtensionResourceLoader : public ResourceFormatLoader {
|
class GDExtensionResourceLoader : public ResourceFormatLoader {
|
||||||
|
GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);
|
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);
|
||||||
|
|
||||||
|
|
74
core/extension/gdextension_function_loader.cpp
Normal file
74
core/extension/gdextension_function_loader.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* gdextension_function_loader.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "gdextension_function_loader.h"
|
||||||
|
|
||||||
|
#include "gdextension.h"
|
||||||
|
|
||||||
|
Error GDExtensionFunctionLoader::open_library(const String &p_path) {
|
||||||
|
ERR_FAIL_COND_V_MSG(!p_path.begins_with("libgodot://"), ERR_FILE_NOT_FOUND, "Function based GDExtensions should have a path starting with libgodot://");
|
||||||
|
ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions.");
|
||||||
|
|
||||||
|
library_path = p_path;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error GDExtensionFunctionLoader::initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) {
|
||||||
|
ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions.");
|
||||||
|
GDExtensionBool ret = initialization_function(p_get_proc_address, p_extension.ptr(), r_initialization);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
return OK;
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_V_MSG(FAILED, "GDExtension initialization function for '" + library_path + "' returned an error.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionFunctionLoader::close_library() {
|
||||||
|
initialization_function = nullptr;
|
||||||
|
library_path.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GDExtensionFunctionLoader::is_library_open() const {
|
||||||
|
return !library_path.is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GDExtensionFunctionLoader::has_library_changed() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GDExtensionFunctionLoader::library_exists() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDExtensionFunctionLoader::set_initialization_function(GDExtensionInitializationFunction p_initialization_function) {
|
||||||
|
initialization_function = p_initialization_function;
|
||||||
|
}
|
54
core/extension/gdextension_function_loader.h
Normal file
54
core/extension/gdextension_function_loader.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* gdextension_function_loader.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/extension/gdextension_loader.h"
|
||||||
|
#include "core/os/shared_object.h"
|
||||||
|
|
||||||
|
class GDExtension;
|
||||||
|
|
||||||
|
class GDExtensionFunctionLoader : public GDExtensionLoader {
|
||||||
|
friend class GDExtensionManager;
|
||||||
|
friend class GDExtension;
|
||||||
|
|
||||||
|
String library_path;
|
||||||
|
GDExtensionInitializationFunction initialization_function = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Error open_library(const String &p_path) override;
|
||||||
|
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) override;
|
||||||
|
virtual void close_library() override;
|
||||||
|
virtual bool is_library_open() const override;
|
||||||
|
virtual bool has_library_changed() const override;
|
||||||
|
virtual bool library_exists() const override;
|
||||||
|
|
||||||
|
void set_initialization_function(GDExtensionInitializationFunction p_initialization_function);
|
||||||
|
};
|
|
@ -261,6 +261,7 @@ static void gdextension_get_godot_version2(GDExtensionGodotVersion2 *r_godot_ver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memory Functions
|
// Memory Functions
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
static void *gdextension_mem_alloc(size_t p_size) {
|
static void *gdextension_mem_alloc(size_t p_size) {
|
||||||
return memalloc(p_size);
|
return memalloc(p_size);
|
||||||
}
|
}
|
||||||
|
@ -272,6 +273,19 @@ static void *gdextension_mem_realloc(void *p_mem, size_t p_size) {
|
||||||
static void gdextension_mem_free(void *p_mem) {
|
static void gdextension_mem_free(void *p_mem) {
|
||||||
memfree(p_mem);
|
memfree(p_mem);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void *gdextension_mem_alloc2(size_t p_size, GDExtensionBool p_prepad_align) {
|
||||||
|
return Memory::alloc_static(p_size, p_prepad_align);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *gdextension_mem_realloc2(void *p_mem, size_t p_size, GDExtensionBool p_prepad_align) {
|
||||||
|
return Memory::realloc_static(p_mem, p_size, p_prepad_align);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gdextension_mem_free2(void *p_mem, GDExtensionBool p_prepad_align) {
|
||||||
|
Memory::free_static(p_mem, p_prepad_align);
|
||||||
|
}
|
||||||
|
|
||||||
// Helper print functions.
|
// Helper print functions.
|
||||||
static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) {
|
static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) {
|
||||||
|
@ -1687,9 +1701,14 @@ void gdextension_setup_interface() {
|
||||||
REGISTER_INTERFACE_FUNC(get_godot_version);
|
REGISTER_INTERFACE_FUNC(get_godot_version);
|
||||||
#endif // DISABLE_DEPRECATED
|
#endif // DISABLE_DEPRECATED
|
||||||
REGISTER_INTERFACE_FUNC(get_godot_version2);
|
REGISTER_INTERFACE_FUNC(get_godot_version2);
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
REGISTER_INTERFACE_FUNC(mem_alloc);
|
REGISTER_INTERFACE_FUNC(mem_alloc);
|
||||||
REGISTER_INTERFACE_FUNC(mem_realloc);
|
REGISTER_INTERFACE_FUNC(mem_realloc);
|
||||||
REGISTER_INTERFACE_FUNC(mem_free);
|
REGISTER_INTERFACE_FUNC(mem_free);
|
||||||
|
#endif // DISABLE_DEPRECATED
|
||||||
|
REGISTER_INTERFACE_FUNC(mem_alloc2);
|
||||||
|
REGISTER_INTERFACE_FUNC(mem_realloc2);
|
||||||
|
REGISTER_INTERFACE_FUNC(mem_free2);
|
||||||
REGISTER_INTERFACE_FUNC(print_error);
|
REGISTER_INTERFACE_FUNC(print_error);
|
||||||
REGISTER_INTERFACE_FUNC(print_error_with_message);
|
REGISTER_INTERFACE_FUNC(print_error_with_message);
|
||||||
REGISTER_INTERFACE_FUNC(print_warning);
|
REGISTER_INTERFACE_FUNC(print_warning);
|
||||||
|
|
|
@ -858,6 +858,7 @@ typedef void (*GDExtensionInterfaceGetGodotVersion2)(GDExtensionGodotVersion2 *r
|
||||||
/**
|
/**
|
||||||
* @name mem_alloc
|
* @name mem_alloc
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
* @deprecated in Godot 4.6. Use `mem_alloc2` instead.
|
||||||
*
|
*
|
||||||
* Allocates memory.
|
* Allocates memory.
|
||||||
*
|
*
|
||||||
|
@ -870,6 +871,7 @@ typedef void *(*GDExtensionInterfaceMemAlloc)(size_t p_bytes);
|
||||||
/**
|
/**
|
||||||
* @name mem_realloc
|
* @name mem_realloc
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
* @deprecated in Godot 4.6. Use `mem_realloc2` instead.
|
||||||
*
|
*
|
||||||
* Reallocates memory.
|
* Reallocates memory.
|
||||||
*
|
*
|
||||||
|
@ -883,6 +885,7 @@ typedef void *(*GDExtensionInterfaceMemRealloc)(void *p_ptr, size_t p_bytes);
|
||||||
/**
|
/**
|
||||||
* @name mem_free
|
* @name mem_free
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
* @deprecated in Godot 4.6. Use `mem_free2` instead.
|
||||||
*
|
*
|
||||||
* Frees memory.
|
* Frees memory.
|
||||||
*
|
*
|
||||||
|
@ -890,7 +893,45 @@ typedef void *(*GDExtensionInterfaceMemRealloc)(void *p_ptr, size_t p_bytes);
|
||||||
*/
|
*/
|
||||||
typedef void (*GDExtensionInterfaceMemFree)(void *p_ptr);
|
typedef void (*GDExtensionInterfaceMemFree)(void *p_ptr);
|
||||||
|
|
||||||
/* INTERFACE: Godot Core */
|
/**
|
||||||
|
* @name mem_alloc2
|
||||||
|
* @since 4.6
|
||||||
|
*
|
||||||
|
* Allocates memory.
|
||||||
|
*
|
||||||
|
* @param p_bytes The amount of memory to allocate in bytes.
|
||||||
|
* @param p_pad_align If true, the returned memory will have prepadding of at least 8 bytes.
|
||||||
|
*
|
||||||
|
* @return A pointer to the allocated memory, or NULL if unsuccessful.
|
||||||
|
*/
|
||||||
|
typedef void *(*GDExtensionInterfaceMemAlloc2)(size_t p_bytes, GDExtensionBool p_pad_align);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name mem_realloc2
|
||||||
|
* @since 4.6
|
||||||
|
*
|
||||||
|
* Reallocates memory.
|
||||||
|
*
|
||||||
|
* @param p_ptr A pointer to the previously allocated memory.
|
||||||
|
* @param p_bytes The number of bytes to resize the memory block to.
|
||||||
|
* @param p_pad_align If true, the returned memory will have prepadding of at least 8 bytes.
|
||||||
|
*
|
||||||
|
* @return A pointer to the allocated memory, or NULL if unsuccessful.
|
||||||
|
*/
|
||||||
|
typedef void *(*GDExtensionInterfaceMemRealloc2)(void *p_ptr, size_t p_bytes, GDExtensionBool p_pad_align);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name mem_free2
|
||||||
|
* @since 4.6
|
||||||
|
*
|
||||||
|
* Frees memory.
|
||||||
|
*
|
||||||
|
* @param p_ptr A pointer to the previously allocated memory.
|
||||||
|
* @param p_pad_align If true, the given memory was allocated with prepadding.
|
||||||
|
*/
|
||||||
|
typedef void (*GDExtensionInterfaceMemFree2)(void *p_ptr, GDExtensionBool p_pad_align);
|
||||||
|
|
||||||
|
//* INTERFACE: Godot Core */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name print_error
|
* @name print_error
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "gdextension_manager.h"
|
#include "gdextension_manager.h"
|
||||||
|
|
||||||
|
#include "core/extension/gdextension_function_loader.h"
|
||||||
#include "core/extension/gdextension_library_loader.h"
|
#include "core/extension/gdextension_library_loader.h"
|
||||||
#include "core/extension/gdextension_special_compat_hashes.h"
|
#include "core/extension/gdextension_special_compat_hashes.h"
|
||||||
#include "core/io/dir_access.h"
|
#include "core/io/dir_access.h"
|
||||||
|
@ -114,7 +115,14 @@ GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &
|
||||||
|
|
||||||
Ref<GDExtensionLibraryLoader> loader;
|
Ref<GDExtensionLibraryLoader> loader;
|
||||||
loader.instantiate();
|
loader.instantiate();
|
||||||
return GDExtensionManager::get_singleton()->load_extension_with_loader(p_path, loader);
|
return load_extension_with_loader(p_path, loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_from_function(const String &p_path, GDExtensionConstPtr<const GDExtensionInitializationFunction> p_init_func) {
|
||||||
|
Ref<GDExtensionFunctionLoader> func_loader;
|
||||||
|
func_loader.instantiate();
|
||||||
|
func_loader->set_initialization_function((GDExtensionInitializationFunction)*p_init_func.data);
|
||||||
|
return load_extension_with_loader(p_path, func_loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
|
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
|
||||||
|
@ -454,6 +462,7 @@ GDExtensionManager *GDExtensionManager::get_singleton() {
|
||||||
|
|
||||||
void GDExtensionManager::_bind_methods() {
|
void GDExtensionManager::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension);
|
ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension);
|
||||||
|
ClassDB::bind_method(D_METHOD("load_extension_from_function", "path", "init_func"), &GDExtensionManager::load_extension_from_function);
|
||||||
ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension);
|
ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension);
|
||||||
ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension);
|
ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension);
|
||||||
ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded);
|
ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded);
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/extension/gdextension.h"
|
#include "core/extension/gdextension.h"
|
||||||
|
#include "core/variant/native_ptr.h"
|
||||||
|
|
||||||
|
GDVIRTUAL_NATIVE_PTR(GDExtensionInitializationFunction)
|
||||||
|
|
||||||
class GDExtensionManager : public Object {
|
class GDExtensionManager : public Object {
|
||||||
GDCLASS(GDExtensionManager, Object);
|
GDCLASS(GDExtensionManager, Object);
|
||||||
|
@ -66,6 +69,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LoadStatus load_extension(const String &p_path);
|
LoadStatus load_extension(const String &p_path);
|
||||||
|
LoadStatus load_extension_from_function(const String &p_path, GDExtensionConstPtr<const GDExtensionInitializationFunction> p_init_func);
|
||||||
LoadStatus load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
|
LoadStatus load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
|
||||||
LoadStatus reload_extension(const String &p_path);
|
LoadStatus reload_extension(const String &p_path);
|
||||||
LoadStatus unload_extension(const String &p_path);
|
LoadStatus unload_extension(const String &p_path);
|
||||||
|
|
|
@ -63,7 +63,7 @@ bool GDExtensionSpecialCompatHashes::get_legacy_hashes(const StringName &p_class
|
||||||
if (p_check_valid) {
|
if (p_check_valid) {
|
||||||
MethodBind *mb = ClassDB::get_method_with_compatibility(p_class, p_method, mapping.current_hash);
|
MethodBind *mb = ClassDB::get_method_with_compatibility(p_class, p_method, mapping.current_hash);
|
||||||
if (!mb) {
|
if (!mb) {
|
||||||
WARN_PRINT(vformat("Compatibility hash %d for %s::%s() mapped to non-existent hash %d. Please update gdextension_special_compat_hashes.cpp.", mapping.legacy_hash, p_class, p_method, mapping.current_hash));
|
WARN_PRINT(vformat("Compatibility hash %d for %s::%s() mapped to non-existent hash %d in gdextension_special_compat_hashes.cpp.", mapping.legacy_hash, p_class, p_method, mapping.current_hash));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
#include "core/templates/hash_map.h"
|
#include "core/templates/hash_map.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
|
|
||||||
|
class Array;
|
||||||
|
|
||||||
// Note: In most situations, compatibility methods should be registered via ClassDB::bind_compatibility_method().
|
// Note: In most situations, compatibility methods should be registered via ClassDB::bind_compatibility_method().
|
||||||
// This class is only meant to be used in exceptional circumstances, for example, when Godot's hashing
|
// This class is only meant to be used in exceptional circumstances, for example, when Godot's hashing
|
||||||
// algorithm changes and registering compatibility methods for all affect methods would be onerous.
|
// algorithm changes and registering compatibility methods for all affect methods would be onerous.
|
||||||
|
|
126
core/extension/godot_instance.cpp
Normal file
126
core/extension/godot_instance.cpp
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* godot_instance.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "godot_instance.h"
|
||||||
|
|
||||||
|
#include "core/extension/gdextension_manager.h"
|
||||||
|
#include "core/os/main_loop.h"
|
||||||
|
#include "main/main.h"
|
||||||
|
#include "servers/display/display_server.h"
|
||||||
|
|
||||||
|
void GodotInstance::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("start"), &GodotInstance::start);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_started"), &GodotInstance::is_started);
|
||||||
|
ClassDB::bind_method(D_METHOD("iteration"), &GodotInstance::iteration);
|
||||||
|
ClassDB::bind_method(D_METHOD("focus_in"), &GodotInstance::focus_in);
|
||||||
|
ClassDB::bind_method(D_METHOD("focus_out"), &GodotInstance::focus_out);
|
||||||
|
ClassDB::bind_method(D_METHOD("pause"), &GodotInstance::pause);
|
||||||
|
ClassDB::bind_method(D_METHOD("resume"), &GodotInstance::resume);
|
||||||
|
}
|
||||||
|
|
||||||
|
GodotInstance::GodotInstance() {
|
||||||
|
}
|
||||||
|
|
||||||
|
GodotInstance::~GodotInstance() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GodotInstance::initialize(GDExtensionInitializationFunction p_init_func) {
|
||||||
|
print_verbose("Godot Instance initialization");
|
||||||
|
GDExtensionManager *gdextension_manager = GDExtensionManager::get_singleton();
|
||||||
|
GDExtensionConstPtr<const GDExtensionInitializationFunction> ptr((const GDExtensionInitializationFunction *)&p_init_func);
|
||||||
|
GDExtensionManager::LoadStatus status = gdextension_manager->load_extension_from_function("libgodot://main", ptr);
|
||||||
|
return status == GDExtensionManager::LoadStatus::LOAD_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GodotInstance::start() {
|
||||||
|
print_verbose("GodotInstance::start()");
|
||||||
|
Error err = Main::setup2();
|
||||||
|
if (err != OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
started = Main::start() == EXIT_SUCCESS;
|
||||||
|
if (started) {
|
||||||
|
OS::get_singleton()->get_main_loop()->initialize();
|
||||||
|
}
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GodotInstance::is_started() {
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GodotInstance::iteration() {
|
||||||
|
DisplayServer::get_singleton()->process_events();
|
||||||
|
return Main::iteration();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GodotInstance::stop() {
|
||||||
|
print_verbose("GodotInstance::stop()");
|
||||||
|
if (started) {
|
||||||
|
OS::get_singleton()->get_main_loop()->finalize();
|
||||||
|
}
|
||||||
|
started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GodotInstance::focus_out() {
|
||||||
|
print_verbose("GodotInstance::focus_out()");
|
||||||
|
if (started) {
|
||||||
|
if (OS::get_singleton()->get_main_loop()) {
|
||||||
|
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GodotInstance::focus_in() {
|
||||||
|
print_verbose("GodotInstance::focus_in()");
|
||||||
|
if (started) {
|
||||||
|
if (OS::get_singleton()->get_main_loop()) {
|
||||||
|
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GodotInstance::pause() {
|
||||||
|
print_verbose("GodotInstance::pause()");
|
||||||
|
if (started) {
|
||||||
|
if (OS::get_singleton()->get_main_loop()) {
|
||||||
|
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_PAUSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GodotInstance::resume() {
|
||||||
|
print_verbose("GodotInstance::resume()");
|
||||||
|
if (started) {
|
||||||
|
if (OS::get_singleton()->get_main_loop()) {
|
||||||
|
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
core/extension/godot_instance.h
Normal file
59
core/extension/godot_instance.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* godot_instance.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/extension/gdextension_interface.h"
|
||||||
|
#include "core/object/class_db.h"
|
||||||
|
|
||||||
|
class GodotInstance : public Object {
|
||||||
|
GDCLASS(GodotInstance, Object);
|
||||||
|
|
||||||
|
bool started = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
GodotInstance();
|
||||||
|
~GodotInstance();
|
||||||
|
|
||||||
|
bool initialize(GDExtensionInitializationFunction p_init_func);
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
bool is_started();
|
||||||
|
bool iteration();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
void focus_out();
|
||||||
|
void focus_in();
|
||||||
|
void pause();
|
||||||
|
void resume();
|
||||||
|
};
|
73
core/extension/libgodot.h
Normal file
73
core/extension/libgodot.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* libgodot.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gdextension_interface.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Export macros for DLL visibility
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define LIBGODOT_API __declspec(dllexport)
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define LIBGODOT_API __attribute__((visibility("default")))
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name libgodot_create_godot_instance
|
||||||
|
* @since 4.6
|
||||||
|
*
|
||||||
|
* Creates a new Godot instance.
|
||||||
|
*
|
||||||
|
* @param p_argc The number of command line arguments.
|
||||||
|
* @param p_argv The C-style array of command line arguments.
|
||||||
|
* @param p_init_func GDExtension initialization function of the host application.
|
||||||
|
*
|
||||||
|
* @return A pointer to created \ref GodotInstance GDExtension object or nullptr if there was an error.
|
||||||
|
*/
|
||||||
|
LIBGODOT_API GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name libgodot_destroy_godot_instance
|
||||||
|
* @since 4.6
|
||||||
|
*
|
||||||
|
* Destroys an existing Godot instance.
|
||||||
|
*
|
||||||
|
* @param p_godot_instance The reference to the GodotInstance object to destroy.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LIBGODOT_API void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1756,8 +1756,7 @@ void Input::parse_mapping(const String &p_mapping) {
|
||||||
void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
|
void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
|
||||||
parse_mapping(p_mapping);
|
parse_mapping(p_mapping);
|
||||||
if (p_update_existing) {
|
if (p_update_existing) {
|
||||||
Vector<String> entry = p_mapping.split(",");
|
const String uid = p_mapping.get_slicec(',', 0);
|
||||||
const String &uid = entry[0];
|
|
||||||
for (KeyValue<int, Joypad> &E : joy_names) {
|
for (KeyValue<int, Joypad> &E : joy_names) {
|
||||||
Joypad &joy = E.value;
|
Joypad &joy = E.value;
|
||||||
if (joy.uid == uid) {
|
if (joy.uid == uid) {
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "core/object/object.h"
|
#include "core/object/object.h"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
#include "core/os/thread_safe.h"
|
#include "core/os/thread_safe.h"
|
||||||
|
#include "core/templates/rb_map.h"
|
||||||
#include "core/templates/rb_set.h"
|
#include "core/templates/rb_set.h"
|
||||||
#include "core/variant/typed_array.h"
|
#include "core/variant/typed_array.h"
|
||||||
|
|
||||||
|
|
|
@ -260,12 +260,12 @@ String InputEventWithModifiers::as_text() const {
|
||||||
if (is_ctrl_pressed()) {
|
if (is_ctrl_pressed()) {
|
||||||
mod_names.push_back(find_keycode_name(Key::CTRL));
|
mod_names.push_back(find_keycode_name(Key::CTRL));
|
||||||
}
|
}
|
||||||
if (is_shift_pressed()) {
|
|
||||||
mod_names.push_back(find_keycode_name(Key::SHIFT));
|
|
||||||
}
|
|
||||||
if (is_alt_pressed()) {
|
if (is_alt_pressed()) {
|
||||||
mod_names.push_back(find_keycode_name(Key::ALT));
|
mod_names.push_back(find_keycode_name(Key::ALT));
|
||||||
}
|
}
|
||||||
|
if (is_shift_pressed()) {
|
||||||
|
mod_names.push_back(find_keycode_name(Key::SHIFT));
|
||||||
|
}
|
||||||
if (is_meta_pressed()) {
|
if (is_meta_pressed()) {
|
||||||
mod_names.push_back(find_keycode_name(Key::META));
|
mod_names.push_back(find_keycode_name(Key::META));
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ String InputEventWithModifiers::as_text() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventWithModifiers::to_string() {
|
String InputEventWithModifiers::_to_string() {
|
||||||
return as_text();
|
return as_text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +488,7 @@ String InputEventKey::as_text() const {
|
||||||
return mods_text.is_empty() ? kc : mods_text + "+" + kc;
|
return mods_text.is_empty() ? kc : mods_text + "+" + kc;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventKey::to_string() {
|
String InputEventKey::_to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
String e = is_echo() ? "true" : "false";
|
String e = is_echo() ? "true" : "false";
|
||||||
|
|
||||||
|
@ -848,7 +848,7 @@ String InputEventMouseButton::as_text() const {
|
||||||
return full_string;
|
return full_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMouseButton::to_string() {
|
String InputEventMouseButton::_to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
String canceled_state = is_canceled() ? "true" : "false";
|
String canceled_state = is_canceled() ? "true" : "false";
|
||||||
String d = double_click ? "true" : "false";
|
String d = double_click ? "true" : "false";
|
||||||
|
@ -988,7 +988,7 @@ String InputEventMouseMotion::as_text() const {
|
||||||
return vformat(RTR("Mouse motion at position (%s) with velocity (%s)"), String(get_position()), String(get_velocity()));
|
return vformat(RTR("Mouse motion at position (%s) with velocity (%s)"), String(get_position()), String(get_velocity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMouseMotion::to_string() {
|
String InputEventMouseMotion::_to_string() {
|
||||||
BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
|
BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
|
||||||
String button_mask_string = itos((int64_t)mouse_button_mask);
|
String button_mask_string = itos((int64_t)mouse_button_mask);
|
||||||
|
|
||||||
|
@ -1184,15 +1184,16 @@ String InputEventJoypadMotion::as_text() const {
|
||||||
return vformat(RTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
|
return vformat(RTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventJoypadMotion::to_string() {
|
String InputEventJoypadMotion::_to_string() {
|
||||||
return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value);
|
return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventJoypadMotion> InputEventJoypadMotion::create_reference(JoyAxis p_axis, float p_value) {
|
Ref<InputEventJoypadMotion> InputEventJoypadMotion::create_reference(JoyAxis p_axis, float p_value, int p_device) {
|
||||||
Ref<InputEventJoypadMotion> ie;
|
Ref<InputEventJoypadMotion> ie;
|
||||||
ie.instantiate();
|
ie.instantiate();
|
||||||
ie->set_axis(p_axis);
|
ie->set_axis(p_axis);
|
||||||
ie->set_axis_value(p_value);
|
ie->set_axis_value(p_value);
|
||||||
|
ie->set_device(p_device);
|
||||||
|
|
||||||
return ie;
|
return ie;
|
||||||
}
|
}
|
||||||
|
@ -1302,15 +1303,16 @@ String InputEventJoypadButton::as_text() const {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventJoypadButton::to_string() {
|
String InputEventJoypadButton::_to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure);
|
return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(JoyButton p_btn_index) {
|
Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(JoyButton p_btn_index, int p_device) {
|
||||||
Ref<InputEventJoypadButton> ie;
|
Ref<InputEventJoypadButton> ie;
|
||||||
ie.instantiate();
|
ie.instantiate();
|
||||||
ie->set_button_index(p_btn_index);
|
ie->set_button_index(p_btn_index);
|
||||||
|
ie->set_device(p_device);
|
||||||
|
|
||||||
return ie;
|
return ie;
|
||||||
}
|
}
|
||||||
|
@ -1384,7 +1386,7 @@ String InputEventScreenTouch::as_text() const {
|
||||||
return vformat(RTR("Screen %s at (%s) with %s touch points"), status, String(get_position()), itos(index));
|
return vformat(RTR("Screen %s at (%s) with %s touch points"), status, String(get_position()), itos(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventScreenTouch::to_string() {
|
String InputEventScreenTouch::_to_string() {
|
||||||
String p = pressed ? "true" : "false";
|
String p = pressed ? "true" : "false";
|
||||||
String canceled_state = canceled ? "true" : "false";
|
String canceled_state = canceled ? "true" : "false";
|
||||||
String double_tap_string = double_tap ? "true" : "false";
|
String double_tap_string = double_tap ? "true" : "false";
|
||||||
|
@ -1512,7 +1514,7 @@ String InputEventScreenDrag::as_text() const {
|
||||||
return vformat(RTR("Screen dragged with %s touch points at position (%s) with velocity of (%s)"), itos(index), String(get_position()), String(get_velocity()));
|
return vformat(RTR("Screen dragged with %s touch points at position (%s) with velocity of (%s)"), itos(index), String(get_position()), String(get_velocity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventScreenDrag::to_string() {
|
String InputEventScreenDrag::_to_string() {
|
||||||
return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", index, String(get_position()), String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
|
return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", index, String(get_position()), String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1654,7 +1656,7 @@ String InputEventAction::as_text() const {
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventAction::to_string() {
|
String InputEventAction::_to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p);
|
return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p);
|
||||||
}
|
}
|
||||||
|
@ -1725,7 +1727,7 @@ String InputEventMagnifyGesture::as_text() const {
|
||||||
return vformat(RTR("Magnify Gesture at (%s) with factor %s"), String(get_position()), rtos(get_factor()));
|
return vformat(RTR("Magnify Gesture at (%s) with factor %s"), String(get_position()), rtos(get_factor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMagnifyGesture::to_string() {
|
String InputEventMagnifyGesture::_to_string() {
|
||||||
return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position()));
|
return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1767,7 +1769,7 @@ String InputEventPanGesture::as_text() const {
|
||||||
return vformat(RTR("Pan Gesture at (%s) with delta (%s)"), String(get_position()), String(get_delta()));
|
return vformat(RTR("Pan Gesture at (%s) with delta (%s)"), String(get_position()), String(get_delta()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventPanGesture::to_string() {
|
String InputEventPanGesture::_to_string() {
|
||||||
return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position()));
|
return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1848,7 +1850,7 @@ String InputEventMIDI::as_text() const {
|
||||||
return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message));
|
return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMIDI::to_string() {
|
String InputEventMIDI::_to_string() {
|
||||||
String ret;
|
String ret;
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case MIDIMessage::NOTE_ON:
|
case MIDIMessage::NOTE_ON:
|
||||||
|
@ -1924,7 +1926,7 @@ String InputEventShortcut::as_text() const {
|
||||||
return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
|
return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventShortcut::to_string() {
|
String InputEventShortcut::_to_string() {
|
||||||
ERR_FAIL_COND_V(shortcut.is_null(), "None");
|
ERR_FAIL_COND_V(shortcut.is_null(), "None");
|
||||||
|
|
||||||
return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
|
return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
|
||||||
|
|
|
@ -146,7 +146,7 @@ public:
|
||||||
BitField<KeyModifierMask> get_modifiers_mask() const;
|
BitField<KeyModifierMask> get_modifiers_mask() const;
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventWithModifiers() {}
|
InputEventWithModifiers() {}
|
||||||
};
|
};
|
||||||
|
@ -200,7 +200,7 @@ public:
|
||||||
virtual String as_text_key_label() const;
|
virtual String as_text_key_label() const;
|
||||||
virtual String as_text_location() const;
|
virtual String as_text_location() const;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
static Ref<InputEventKey> create_reference(Key p_keycode_with_modifier_masks, bool p_physical = false);
|
static Ref<InputEventKey> create_reference(Key p_keycode_with_modifier_masks, bool p_physical = false);
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ public:
|
||||||
|
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::MOUSE_BUTTON; }
|
InputEventType get_type() const final override { return InputEventType::MOUSE_BUTTON; }
|
||||||
|
|
||||||
|
@ -308,7 +308,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
|
@ -337,9 +337,10 @@ public:
|
||||||
|
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
static Ref<InputEventJoypadMotion> create_reference(JoyAxis p_axis, float p_value);
|
// The default device ID is `InputMap::ALL_DEVICES`.
|
||||||
|
static Ref<InputEventJoypadMotion> create_reference(JoyAxis p_axis, float p_value, int p_device = -1);
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::JOY_MOTION; }
|
InputEventType get_type() const final override { return InputEventType::JOY_MOTION; }
|
||||||
|
|
||||||
|
@ -369,9 +370,10 @@ public:
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
static Ref<InputEventJoypadButton> create_reference(JoyButton p_btn_index);
|
// The default device ID is `InputMap::ALL_DEVICES`.
|
||||||
|
static Ref<InputEventJoypadButton> create_reference(JoyButton p_btn_index, int p_device = -1);
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::JOY_BUTTON; }
|
InputEventType get_type() const final override { return InputEventType::JOY_BUTTON; }
|
||||||
|
|
||||||
|
@ -402,7 +404,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::SCREEN_TOUCH; }
|
InputEventType get_type() const final override { return InputEventType::SCREEN_TOUCH; }
|
||||||
|
|
||||||
|
@ -454,7 +456,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
|
@ -493,7 +495,7 @@ public:
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::ACTION; }
|
InputEventType get_type() const final override { return InputEventType::ACTION; }
|
||||||
|
|
||||||
|
@ -526,7 +528,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::MAGNIFY_GESTURE; }
|
InputEventType get_type() const final override { return InputEventType::MAGNIFY_GESTURE; }
|
||||||
|
|
||||||
|
@ -546,7 +548,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::PAN_GESTURE; }
|
InputEventType get_type() const final override { return InputEventType::PAN_GESTURE; }
|
||||||
|
|
||||||
|
@ -594,7 +596,7 @@ public:
|
||||||
int get_controller_value() const;
|
int get_controller_value() const;
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::MIDI; }
|
InputEventType get_type() const final override { return InputEventType::MIDI; }
|
||||||
|
|
||||||
|
@ -614,7 +616,7 @@ public:
|
||||||
Ref<Shortcut> get_shortcut();
|
Ref<Shortcut> get_shortcut();
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String to_string() override;
|
virtual String _to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::SHORTCUT; }
|
InputEventType get_type() const final override { return InputEventType::SHORTCUT; }
|
||||||
|
|
||||||
|
|
|
@ -403,9 +403,12 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
|
||||||
{ "ui_graph_delete", TTRC("Delete Nodes") },
|
{ "ui_graph_delete", TTRC("Delete Nodes") },
|
||||||
{ "ui_graph_follow_left", TTRC("Follow Input Port Connection") },
|
{ "ui_graph_follow_left", TTRC("Follow Input Port Connection") },
|
||||||
{ "ui_graph_follow_right", TTRC("Follow Output Port Connection") },
|
{ "ui_graph_follow_right", TTRC("Follow Output Port Connection") },
|
||||||
|
{ "ui_filedialog_delete", TTRC("Delete") },
|
||||||
{ "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
|
{ "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
|
||||||
{ "ui_filedialog_refresh", TTRC("Refresh") },
|
{ "ui_filedialog_refresh", TTRC("Refresh") },
|
||||||
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
|
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
|
||||||
|
{ "ui_filedialog_find", TTRC("Find") },
|
||||||
|
{ "ui_filedialog_focus_path", TTRC("Focus Path") },
|
||||||
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
|
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
|
||||||
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
|
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
|
||||||
{ "ui_colorpicker_delete_preset", TTRC("ColorPicker: Delete Preset") },
|
{ "ui_colorpicker_delete_preset", TTRC("ColorPicker: Delete Preset") },
|
||||||
|
@ -415,7 +418,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
String InputMap::get_builtin_display_name(const String &p_name) const {
|
String InputMap::get_builtin_display_name(const String &p_name) const {
|
||||||
constexpr int len = std::size(_builtin_action_display_names);
|
constexpr int len = std_size(_builtin_action_display_names);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (_builtin_action_display_names[i].name == p_name) {
|
if (_builtin_action_display_names[i].name == p_name) {
|
||||||
|
@ -804,6 +807,10 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
|
||||||
default_builtin_cache.insert("ui_graph_follow_right.macos", inputs);
|
default_builtin_cache.insert("ui_graph_follow_right.macos", inputs);
|
||||||
|
|
||||||
// ///// UI File Dialog Shortcuts /////
|
// ///// UI File Dialog Shortcuts /////
|
||||||
|
inputs = List<Ref<InputEvent>>();
|
||||||
|
inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE));
|
||||||
|
default_builtin_cache.insert("ui_filedialog_delete", inputs);
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
inputs = List<Ref<InputEvent>>();
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
|
inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
|
||||||
default_builtin_cache.insert("ui_filedialog_up_one_level", inputs);
|
default_builtin_cache.insert("ui_filedialog_up_one_level", inputs);
|
||||||
|
@ -816,6 +823,22 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::H));
|
inputs.push_back(InputEventKey::create_reference(Key::H));
|
||||||
default_builtin_cache.insert("ui_filedialog_show_hidden", inputs);
|
default_builtin_cache.insert("ui_filedialog_show_hidden", inputs);
|
||||||
|
|
||||||
|
inputs = List<Ref<InputEvent>>();
|
||||||
|
inputs.push_back(InputEventKey::create_reference(Key::F | KeyModifierMask::CMD_OR_CTRL));
|
||||||
|
default_builtin_cache.insert("ui_filedialog_find", inputs);
|
||||||
|
|
||||||
|
inputs = List<Ref<InputEvent>>();
|
||||||
|
// Ctrl + L (matches most Windows/Linux file managers' "focus on path bar" shortcut,
|
||||||
|
// plus macOS Safari's "focus on address bar" shortcut).
|
||||||
|
inputs.push_back(InputEventKey::create_reference(Key::L | KeyModifierMask::CMD_OR_CTRL));
|
||||||
|
default_builtin_cache.insert("ui_filedialog_focus_path", inputs);
|
||||||
|
|
||||||
|
inputs = List<Ref<InputEvent>>();
|
||||||
|
// Cmd + Shift + G (matches Finder's "Go To" shortcut).
|
||||||
|
inputs.push_back(InputEventKey::create_reference(Key::G | KeyModifierMask::CMD_OR_CTRL));
|
||||||
|
inputs.push_back(InputEventKey::create_reference(Key::L | KeyModifierMask::CMD_OR_CTRL));
|
||||||
|
default_builtin_cache.insert("ui_filedialog_focus_path.macos", inputs);
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
inputs = List<Ref<InputEvent>>();
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD_OR_CTRL));
|
inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD_OR_CTRL));
|
||||||
default_builtin_cache.insert("ui_swap_input_direction", inputs);
|
default_builtin_cache.insert("ui_swap_input_direction", inputs);
|
||||||
|
@ -843,9 +866,8 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
|
||||||
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
||||||
String fullname = E.key;
|
String fullname = E.key;
|
||||||
|
|
||||||
Vector<String> split = fullname.split(".");
|
const String &name = fullname.get_slicec('.', 0);
|
||||||
const String &name = split[0];
|
String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
|
||||||
String override_for = split.size() > 1 ? split[1] : String();
|
|
||||||
|
|
||||||
if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
|
if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
|
||||||
builtins_with_overrides[name].push_back(override_for);
|
builtins_with_overrides[name].push_back(override_for);
|
||||||
|
@ -855,9 +877,8 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
|
||||||
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
||||||
String fullname = E.key;
|
String fullname = E.key;
|
||||||
|
|
||||||
Vector<String> split = fullname.split(".");
|
const String &name = fullname.get_slicec('.', 0);
|
||||||
const String &name = split[0];
|
String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
|
||||||
String override_for = split.size() > 1 ? split[1] : String();
|
|
||||||
|
|
||||||
if (builtins_with_overrides.has(name) && override_for.is_empty()) {
|
if (builtins_with_overrides.has(name) && override_for.is_empty()) {
|
||||||
// Builtin has an override but this particular one is not an override, so skip.
|
// Builtin has an override but this particular one is not an override, so skip.
|
||||||
|
|
|
@ -85,6 +85,17 @@ String Shortcut::get_as_text() const {
|
||||||
return "None";
|
return "None";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<Shortcut> Shortcut::make_from_action(const StringName &p_action) {
|
||||||
|
Ref<InputEventAction> event;
|
||||||
|
event.instantiate();
|
||||||
|
event->set_action(p_action);
|
||||||
|
|
||||||
|
Ref<Shortcut> shortcut;
|
||||||
|
shortcut.instantiate();
|
||||||
|
shortcut->set_events({ event });
|
||||||
|
return shortcut;
|
||||||
|
}
|
||||||
|
|
||||||
bool Shortcut::has_valid_event() const {
|
bool Shortcut::has_valid_event() const {
|
||||||
// Tests if there is ANY input event which is valid.
|
// Tests if there is ANY input event which is valid.
|
||||||
for (int i = 0; i < events.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
|
|
@ -52,5 +52,7 @@ public:
|
||||||
|
|
||||||
String get_as_text() const;
|
String get_as_text() const;
|
||||||
|
|
||||||
|
static Ref<Shortcut> make_from_action(const StringName &p_action);
|
||||||
|
|
||||||
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
|
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,6 +90,14 @@ void FileAccess::store_pascal_string_bind_compat_78289(const String &p_string) {
|
||||||
store_pascal_string(p_string);
|
store_pascal_string(p_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String FileAccess::get_as_text_bind_compat_110867(bool p_skip_cr) const {
|
||||||
|
String text = get_as_text();
|
||||||
|
if (unlikely(p_skip_cr)) {
|
||||||
|
text = text.remove_char('\r');
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
void FileAccess::_bind_compatibility_methods() {
|
void FileAccess::_bind_compatibility_methods() {
|
||||||
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
|
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
|
||||||
|
|
||||||
|
@ -107,6 +115,7 @@ void FileAccess::_bind_compatibility_methods() {
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("store_string", "string"), &FileAccess::store_string_bind_compat_78289);
|
ClassDB::bind_compatibility_method(D_METHOD("store_string", "string"), &FileAccess::store_string_bind_compat_78289);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var_bind_compat_78289, DEFVAL(false));
|
ClassDB::bind_compatibility_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var_bind_compat_78289, DEFVAL(false));
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string_bind_compat_78289);
|
ClassDB::bind_compatibility_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string_bind_compat_78289);
|
||||||
|
ClassDB::bind_compatibility_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text_bind_compat_110867, DEFVAL(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "core/io/file_access_encrypted.h"
|
#include "core/io/file_access_encrypted.h"
|
||||||
#include "core/io/file_access_pack.h"
|
#include "core/io/file_access_pack.h"
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
|
#include "core/io/resource_uid.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/os/time.h"
|
#include "core/os/time.h"
|
||||||
|
|
||||||
|
@ -81,12 +82,12 @@ Ref<FileAccess> FileAccess::create_for_path(const String &p_path) {
|
||||||
Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix, const String &p_extension, bool p_keep, Error *r_error) {
|
Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix, const String &p_extension, bool p_keep, Error *r_error) {
|
||||||
const String ERROR_COMMON_PREFIX = "Error while creating temporary file";
|
const String ERROR_COMMON_PREFIX = "Error while creating temporary file";
|
||||||
|
|
||||||
if (!p_prefix.is_valid_filename()) {
|
if (!p_prefix.is_empty() && !p_prefix.is_valid_filename()) {
|
||||||
*r_error = ERR_FILE_BAD_PATH;
|
*r_error = ERR_FILE_BAD_PATH;
|
||||||
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid prefix.)", ERROR_COMMON_PREFIX, p_prefix));
|
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid prefix.)", ERROR_COMMON_PREFIX, p_prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_extension.is_valid_filename()) {
|
if (!p_extension.is_empty() && !p_extension.is_valid_filename()) {
|
||||||
*r_error = ERR_FILE_BAD_PATH;
|
*r_error = ERR_FILE_BAD_PATH;
|
||||||
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid extension.)", ERROR_COMMON_PREFIX, p_extension));
|
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid extension.)", ERROR_COMMON_PREFIX, p_extension));
|
||||||
}
|
}
|
||||||
|
@ -445,7 +446,7 @@ class CharBuffer {
|
||||||
public:
|
public:
|
||||||
_FORCE_INLINE_ CharBuffer() :
|
_FORCE_INLINE_ CharBuffer() :
|
||||||
buffer(stack_buffer),
|
buffer(stack_buffer),
|
||||||
capacity(std::size(stack_buffer)) {
|
capacity(std_size(stack_buffer)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ void push_back(char c) {
|
_FORCE_INLINE_ void push_back(char c) {
|
||||||
|
@ -467,10 +468,22 @@ String FileAccess::get_line() const {
|
||||||
uint8_t c = get_8();
|
uint8_t c = get_8();
|
||||||
|
|
||||||
while (!eof_reached()) {
|
while (!eof_reached()) {
|
||||||
if (c == '\n' || c == '\0' || get_error() != OK) {
|
if (c == '\r' || c == '\n' || c == '\0' || get_error() != OK) {
|
||||||
|
if (c == '\r') {
|
||||||
|
// Check for Windows-style EOL.
|
||||||
|
const uint64_t prev_pos = get_position() - 1;
|
||||||
|
if (unlikely(get_8() != '\n')) {
|
||||||
|
// HACK: We can't simply check the next value in a vacuum, so we risk triggering
|
||||||
|
// an EOL false-positive in the unlikely event that this `\r` was the final
|
||||||
|
// value of the file. Unilaterally work around by re-reading the *previous*
|
||||||
|
// byte (the starting `\r`) to ensure `get_error()` returns `OK`.
|
||||||
|
const_cast<FileAccess *>(this)->seek(prev_pos);
|
||||||
|
get_8();
|
||||||
|
}
|
||||||
|
}
|
||||||
line.push_back(0);
|
line.push_back(0);
|
||||||
return String::utf8(line.get_data());
|
return String::utf8(line.get_data());
|
||||||
} else if (c != '\r') {
|
} else {
|
||||||
line.push_back(char(c));
|
line.push_back(char(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,11 +551,11 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
|
||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
String FileAccess::get_as_text(bool p_skip_cr) const {
|
String FileAccess::get_as_text() const {
|
||||||
uint64_t original_pos = get_position();
|
uint64_t original_pos = get_position();
|
||||||
const_cast<FileAccess *>(this)->seek(0);
|
const_cast<FileAccess *>(this)->seek(0);
|
||||||
|
|
||||||
String text = get_as_utf8_string(p_skip_cr);
|
String text = get_as_utf8_string();
|
||||||
|
|
||||||
const_cast<FileAccess *>(this)->seek(original_pos);
|
const_cast<FileAccess *>(this)->seek(original_pos);
|
||||||
|
|
||||||
|
@ -557,6 +570,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.reserve_exact(p_length);
|
||||||
Error err = data.resize(p_length);
|
Error err = data.resize(p_length);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length));
|
ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length));
|
||||||
|
|
||||||
|
@ -570,7 +584,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
|
String FileAccess::get_as_utf8_string() const {
|
||||||
Vector<uint8_t> sourcef;
|
Vector<uint8_t> sourcef;
|
||||||
uint64_t len = get_length();
|
uint64_t len = get_length();
|
||||||
sourcef.resize(len + 1);
|
sourcef.resize(len + 1);
|
||||||
|
@ -581,7 +595,7 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
|
||||||
w[len] = 0;
|
w[len] = 0;
|
||||||
|
|
||||||
String s;
|
String s;
|
||||||
s.append_utf8((const char *)w, len, p_skip_cr);
|
s.append_utf8((const char *)w, len);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,6 +865,7 @@ Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_err
|
||||||
ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path)));
|
ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path)));
|
||||||
}
|
}
|
||||||
Vector<uint8_t> data;
|
Vector<uint8_t> data;
|
||||||
|
data.reserve_exact(f->get_length());
|
||||||
data.resize(f->get_length());
|
data.resize(f->get_length());
|
||||||
f->get_buffer(data.ptrw(), data.size());
|
f->get_buffer(data.ptrw(), data.size());
|
||||||
return data;
|
return data;
|
||||||
|
@ -987,7 +1002,7 @@ void FileAccess::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
|
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
|
||||||
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
|
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
|
||||||
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
|
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
|
||||||
ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("get_as_text"), &FileAccess::get_as_text);
|
||||||
ClassDB::bind_static_method("FileAccess", D_METHOD("get_md5", "path"), &FileAccess::get_md5);
|
ClassDB::bind_static_method("FileAccess", D_METHOD("get_md5", "path"), &FileAccess::get_md5);
|
||||||
ClassDB::bind_static_method("FileAccess", D_METHOD("get_sha256", "path"), &FileAccess::get_sha256);
|
ClassDB::bind_static_method("FileAccess", D_METHOD("get_sha256", "path"), &FileAccess::get_sha256);
|
||||||
ClassDB::bind_method(D_METHOD("is_big_endian"), &FileAccess::is_big_endian);
|
ClassDB::bind_method(D_METHOD("is_big_endian"), &FileAccess::is_big_endian);
|
||||||
|
|
|
@ -132,6 +132,7 @@ protected:
|
||||||
void store_line_bind_compat_78289(const String &p_line);
|
void store_line_bind_compat_78289(const String &p_line);
|
||||||
void store_csv_line_bind_compat_78289(const Vector<String> &p_values, const String &p_delim = ",");
|
void store_csv_line_bind_compat_78289(const Vector<String> &p_values, const String &p_delim = ",");
|
||||||
void store_pascal_string_bind_compat_78289(const String &p_string);
|
void store_pascal_string_bind_compat_78289(const String &p_string);
|
||||||
|
String get_as_text_bind_compat_110867(bool p_skip_cr) const;
|
||||||
|
|
||||||
static void _bind_compatibility_methods();
|
static void _bind_compatibility_methods();
|
||||||
#endif
|
#endif
|
||||||
|
@ -188,8 +189,8 @@ public:
|
||||||
virtual String get_line() const;
|
virtual String get_line() const;
|
||||||
virtual String get_token() const;
|
virtual String get_token() const;
|
||||||
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
|
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
|
||||||
String get_as_text(bool p_skip_cr = false) const;
|
String get_as_text() const;
|
||||||
virtual String get_as_utf8_string(bool p_skip_cr = false) const;
|
virtual String get_as_utf8_string() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
|
|
|
@ -130,34 +130,37 @@ void FileAccessCompressed::_close() {
|
||||||
f->store_32(0); //compressed sizes, will update later
|
f->store_32(0); //compressed sizes, will update later
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<int> block_sizes;
|
uint32_t last_block_size = write_max % block_size;
|
||||||
|
|
||||||
|
// Temporary buffer for compressed data blocks.
|
||||||
|
LocalVector<uint8_t> temp_cblock;
|
||||||
|
temp_cblock.resize(Compression::get_max_compressed_buffer_size(bc == 1 ? last_block_size : block_size, cmode));
|
||||||
|
uint8_t *temp_cblock_ptr = temp_cblock.ptr();
|
||||||
|
|
||||||
|
// Compress and store the blocks.
|
||||||
|
LocalVector<uint32_t> block_sizes;
|
||||||
for (uint32_t i = 0; i < bc; i++) {
|
for (uint32_t i = 0; i < bc; i++) {
|
||||||
uint32_t bl = i == (bc - 1) ? write_max % block_size : block_size;
|
uint32_t bl = i == (bc - 1) ? last_block_size : block_size;
|
||||||
uint8_t *bp = &write_ptr[i * block_size];
|
uint8_t *bp = &write_ptr[i * block_size];
|
||||||
|
|
||||||
Vector<uint8_t> cblock;
|
const int64_t compressed_size = Compression::compress(temp_cblock_ptr, bp, bl, cmode);
|
||||||
cblock.resize(Compression::get_max_compressed_buffer_size(bl, cmode));
|
|
||||||
const int64_t compressed_size = Compression::compress(cblock.ptrw(), bp, bl, cmode);
|
|
||||||
ERR_FAIL_COND_MSG(compressed_size < 0, "FileAccessCompressed: Error compressing data.");
|
ERR_FAIL_COND_MSG(compressed_size < 0, "FileAccessCompressed: Error compressing data.");
|
||||||
|
|
||||||
f->store_buffer(cblock.ptr(), (uint64_t)compressed_size);
|
f->store_buffer(temp_cblock_ptr, (uint64_t)compressed_size);
|
||||||
block_sizes.push_back(compressed_size);
|
block_sizes.push_back(compressed_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
f->seek(16); //ok write block sizes
|
f->seek(16); //ok write block sizes
|
||||||
for (uint32_t i = 0; i < bc; i++) {
|
for (uint32_t i = 0; i < bc; i++) {
|
||||||
f->store_32(uint32_t(block_sizes[i]));
|
f->store_32(block_sizes[i]);
|
||||||
}
|
}
|
||||||
f->seek_end();
|
f->seek_end();
|
||||||
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
|
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
|
||||||
|
|
||||||
buffer.clear();
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
comp_buffer.clear();
|
comp_buffer.clear();
|
||||||
buffer.clear();
|
|
||||||
read_blocks.clear();
|
read_blocks.clear();
|
||||||
}
|
}
|
||||||
|
buffer.clear();
|
||||||
f.unref();
|
f.unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ void FileAccessEncrypted::_close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writing) {
|
if (writing) {
|
||||||
Vector<uint8_t> compressed;
|
LocalVector<uint8_t> compressed;
|
||||||
uint64_t len = data.size();
|
uint64_t len = data.size();
|
||||||
if (len % 16) {
|
if (len % 16) {
|
||||||
len += 16 - (len % 16);
|
len += 16 - (len % 16);
|
||||||
|
@ -150,10 +150,8 @@ void FileAccessEncrypted::_close() {
|
||||||
ERR_FAIL_COND(CryptoCore::md5(data.ptr(), data.size(), hash) != OK); // Bug?
|
ERR_FAIL_COND(CryptoCore::md5(data.ptr(), data.size(), hash) != OK); // Bug?
|
||||||
|
|
||||||
compressed.resize(len);
|
compressed.resize(len);
|
||||||
memset(compressed.ptrw(), 0, len);
|
memcpy(compressed.ptr(), data.ptr(), data.size());
|
||||||
for (int i = 0; i < data.size(); i++) {
|
memset(compressed.ptr() + data.size(), 0, len - data.size());
|
||||||
compressed.write[i] = data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoCore::AESContext ctx;
|
CryptoCore::AESContext ctx;
|
||||||
ctx.set_encode_key(key.ptrw(), 256);
|
ctx.set_encode_key(key.ptrw(), 256);
|
||||||
|
@ -166,7 +164,7 @@ void FileAccessEncrypted::_close() {
|
||||||
file->store_64(data.size());
|
file->store_64(data.size());
|
||||||
file->store_buffer(iv.ptr(), 16);
|
file->store_buffer(iv.ptr(), 16);
|
||||||
|
|
||||||
ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptrw(), compressed.ptrw());
|
ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptr(), compressed.ptr());
|
||||||
|
|
||||||
file->store_buffer(compressed.ptr(), compressed.size());
|
file->store_buffer(compressed.ptr(), compressed.size());
|
||||||
data.clear();
|
data.clear();
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include "core/crypto/crypto.h"
|
#include "core/crypto/crypto.h"
|
||||||
|
|
||||||
class HTTPClientTCP : public HTTPClient {
|
class HTTPClientTCP : public HTTPClient {
|
||||||
|
GDSOFTCLASS(HTTPClientTCP, HTTPClient);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Status status = STATUS_DISCONNECTED;
|
Status status = STATUS_DISCONNECTED;
|
||||||
IP::ResolverID resolving = IP::RESOLVER_INVALID_ID;
|
IP::ResolverID resolving = IP::RESOLVER_INVALID_ID;
|
||||||
|
|
|
@ -78,6 +78,14 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
|
||||||
"ASTC_4x4_HDR",
|
"ASTC_4x4_HDR",
|
||||||
"ASTC_8x8",
|
"ASTC_8x8",
|
||||||
"ASTC_8x8_HDR",
|
"ASTC_8x8_HDR",
|
||||||
|
"R16",
|
||||||
|
"RG16",
|
||||||
|
"RGB16",
|
||||||
|
"RGBA16",
|
||||||
|
"R16Int",
|
||||||
|
"RG16Int",
|
||||||
|
"RGB16Int",
|
||||||
|
"RGBA16Int",
|
||||||
};
|
};
|
||||||
|
|
||||||
// External VRAM compression function pointers.
|
// External VRAM compression function pointers.
|
||||||
|
@ -201,6 +209,22 @@ int Image::get_format_pixel_size(Format p_format) {
|
||||||
return 1;
|
return 1;
|
||||||
case FORMAT_ASTC_8x8_HDR:
|
case FORMAT_ASTC_8x8_HDR:
|
||||||
return 1;
|
return 1;
|
||||||
|
case FORMAT_R16:
|
||||||
|
return 2;
|
||||||
|
case FORMAT_RG16:
|
||||||
|
return 4;
|
||||||
|
case FORMAT_RGB16:
|
||||||
|
return 6;
|
||||||
|
case FORMAT_RGBA16:
|
||||||
|
return 8;
|
||||||
|
case FORMAT_R16I:
|
||||||
|
return 2;
|
||||||
|
case FORMAT_RG16I:
|
||||||
|
return 4;
|
||||||
|
case FORMAT_RGB16I:
|
||||||
|
return 6;
|
||||||
|
case FORMAT_RGBA16I:
|
||||||
|
return 8;
|
||||||
case FORMAT_MAX: {
|
case FORMAT_MAX: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -759,6 +783,78 @@ void Image::convert(Format p_new_format) {
|
||||||
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
|
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
|
||||||
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||||
break;
|
break;
|
||||||
|
case FORMAT_R16 | (FORMAT_RG16 << 8):
|
||||||
|
_convert_fast<uint16_t, 1, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_R16 | (FORMAT_RGB16 << 8):
|
||||||
|
_convert_fast<uint16_t, 1, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_R16 | (FORMAT_RGBA16 << 8):
|
||||||
|
_convert_fast<uint16_t, 1, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RG16 | (FORMAT_R16 << 8):
|
||||||
|
_convert_fast<uint16_t, 2, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RG16 | (FORMAT_RGB16 << 8):
|
||||||
|
_convert_fast<uint16_t, 2, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RG16 | (FORMAT_RGBA16 << 8):
|
||||||
|
_convert_fast<uint16_t, 2, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGB16 | (FORMAT_R16 << 8):
|
||||||
|
_convert_fast<uint16_t, 3, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGB16 | (FORMAT_RG16 << 8):
|
||||||
|
_convert_fast<uint16_t, 3, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGB16 | (FORMAT_RGBA16 << 8):
|
||||||
|
_convert_fast<uint16_t, 3, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGBA16 | (FORMAT_R16 << 8):
|
||||||
|
_convert_fast<uint16_t, 4, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGBA16 | (FORMAT_RG16 << 8):
|
||||||
|
_convert_fast<uint16_t, 4, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGBA16 | (FORMAT_RGB16 << 8):
|
||||||
|
_convert_fast<uint16_t, 4, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_R16I | (FORMAT_RG16I << 8):
|
||||||
|
_convert_fast<uint16_t, 1, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_R16I | (FORMAT_RGB16I << 8):
|
||||||
|
_convert_fast<uint16_t, 1, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_R16I | (FORMAT_RGBA16I << 8):
|
||||||
|
_convert_fast<uint16_t, 1, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RG16I | (FORMAT_R16I << 8):
|
||||||
|
_convert_fast<uint16_t, 2, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RG16I | (FORMAT_RGB16I << 8):
|
||||||
|
_convert_fast<uint16_t, 2, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RG16I | (FORMAT_RGBA16I << 8):
|
||||||
|
_convert_fast<uint16_t, 2, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGB16I | (FORMAT_R16I << 8):
|
||||||
|
_convert_fast<uint16_t, 3, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGB16I | (FORMAT_RG16I << 8):
|
||||||
|
_convert_fast<uint16_t, 3, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGB16I | (FORMAT_RGBA16I << 8):
|
||||||
|
_convert_fast<uint16_t, 3, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGBA16I | (FORMAT_R16I << 8):
|
||||||
|
_convert_fast<uint16_t, 4, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGBA16I | (FORMAT_RG16I << 8):
|
||||||
|
_convert_fast<uint16_t, 4, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
|
case FORMAT_RGBA16I | (FORMAT_RGB16I << 8):
|
||||||
|
_convert_fast<uint16_t, 4, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,6 +865,11 @@ Image::Format Image::get_format() const {
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ImageScaleType {
|
||||||
|
IMAGE_SCALING_INT,
|
||||||
|
IMAGE_SCALING_FLOAT,
|
||||||
|
};
|
||||||
|
|
||||||
static double _bicubic_interp_kernel(double x) {
|
static double _bicubic_interp_kernel(double x) {
|
||||||
x = Math::abs(x);
|
x = Math::abs(x);
|
||||||
|
|
||||||
|
@ -783,7 +884,7 @@ static double _bicubic_interp_kernel(double x) {
|
||||||
return bc;
|
return bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int CC, typename T>
|
template <int CC, typename T, ImageScaleType TYPE>
|
||||||
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||||
// get source image size
|
// get source image size
|
||||||
int width = p_src_width;
|
int width = p_src_width;
|
||||||
|
@ -845,7 +946,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
||||||
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
|
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
|
||||||
|
|
||||||
for (int i = 0; i < CC; i++) {
|
for (int i = 0; i < CC; i++) {
|
||||||
if constexpr (sizeof(T) == 2) { //half float
|
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||||
color[i] = Math::half_to_float(p[i]);
|
color[i] = Math::half_to_float(p[i]);
|
||||||
} else {
|
} else {
|
||||||
color[i] += p[i] * k2;
|
color[i] += p[i] * k2;
|
||||||
|
@ -857,8 +958,12 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
||||||
for (int i = 0; i < CC; i++) {
|
for (int i = 0; i < CC; i++) {
|
||||||
if constexpr (sizeof(T) == 1) { //byte
|
if constexpr (sizeof(T) == 1) { //byte
|
||||||
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
|
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
|
||||||
} else if constexpr (sizeof(T) == 2) { //half float
|
} else if constexpr (sizeof(T) == 2) {
|
||||||
dst[i] = Math::make_half_float(color[i]);
|
if constexpr (TYPE == IMAGE_SCALING_FLOAT) {
|
||||||
|
dst[i] = Math::make_half_float(color[i]); //half float
|
||||||
|
} else {
|
||||||
|
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 65535); // uint16
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dst[i] = color[i];
|
dst[i] = color[i];
|
||||||
}
|
}
|
||||||
|
@ -867,7 +972,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int CC, typename T>
|
template <int CC, typename T, ImageScaleType TYPE>
|
||||||
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||||
constexpr uint32_t FRAC_BITS = 8;
|
constexpr uint32_t FRAC_BITS = 8;
|
||||||
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
|
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
|
||||||
|
@ -915,23 +1020,40 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
|
||||||
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
|
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
|
||||||
interp >>= FRAC_BITS;
|
interp >>= FRAC_BITS;
|
||||||
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
|
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
|
||||||
} else if constexpr (sizeof(T) == 2) { //half float
|
} else if constexpr (sizeof(T) == 2) {
|
||||||
|
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||||
|
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||||
|
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
||||||
|
const T *src = ((const T *)p_src);
|
||||||
|
T *dst = ((T *)p_dst);
|
||||||
|
|
||||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
||||||
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
||||||
const T *src = ((const T *)p_src);
|
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
||||||
T *dst = ((T *)p_dst);
|
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
||||||
|
|
||||||
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
||||||
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
||||||
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
||||||
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
|
||||||
|
|
||||||
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
||||||
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
} else { //uint16
|
||||||
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||||
|
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
||||||
|
const T *src = ((const T *)p_src);
|
||||||
|
T *dst = ((T *)p_dst);
|
||||||
|
|
||||||
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
float p00 = src[y_ofs_up + src_xofs_left + l];
|
||||||
|
float p10 = src[y_ofs_up + src_xofs_right + l];
|
||||||
|
float p01 = src[y_ofs_down + src_xofs_left + l];
|
||||||
|
float p11 = src[y_ofs_down + src_xofs_right + l];
|
||||||
|
|
||||||
|
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
||||||
|
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
||||||
|
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
||||||
|
|
||||||
|
dst[i * p_dst_width * CC + j * CC + l] = uint16_t(interp);
|
||||||
|
}
|
||||||
} else if constexpr (sizeof(T) == 4) { //float
|
} else if constexpr (sizeof(T) == 4) { //float
|
||||||
|
|
||||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||||
|
@ -982,7 +1104,7 @@ static float _lanczos(float p_x) {
|
||||||
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
|
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int CC, typename T>
|
template <int CC, typename T, ImageScaleType TYPE>
|
||||||
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||||
int32_t src_width = p_src_width;
|
int32_t src_width = p_src_width;
|
||||||
int32_t src_height = p_src_height;
|
int32_t src_height = p_src_height;
|
||||||
|
@ -1023,7 +1145,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
||||||
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
|
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < CC; i++) {
|
for (uint32_t i = 0; i < CC; i++) {
|
||||||
if constexpr (sizeof(T) == 2) { //half float
|
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||||
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
|
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
|
||||||
} else {
|
} else {
|
||||||
pixel[i] += src_data[i] * lanczos_val;
|
pixel[i] += src_data[i] * lanczos_val;
|
||||||
|
@ -1082,8 +1204,13 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
||||||
|
|
||||||
if constexpr (sizeof(T) == 1) { //byte
|
if constexpr (sizeof(T) == 1) { //byte
|
||||||
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
|
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
|
||||||
} else if constexpr (sizeof(T) == 2) { //half float
|
} else if constexpr (sizeof(T) == 2) {
|
||||||
dst_data[i] = Math::make_half_float(pixel[i]);
|
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
||||||
|
dst_data[i] = Math::make_half_float(pixel[i]);
|
||||||
|
} else { //uint16
|
||||||
|
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 65535);
|
||||||
|
}
|
||||||
|
|
||||||
} else { // float
|
} else { // float
|
||||||
dst_data[i] = pixel[i];
|
dst_data[i] = pixel[i];
|
||||||
}
|
}
|
||||||
|
@ -1226,6 +1353,21 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||||
|
switch (get_format_pixel_size(format)) {
|
||||||
|
case 2:
|
||||||
|
_scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
_scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1270,46 +1412,61 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 1:
|
case 1:
|
||||||
_scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<1, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<2, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<3, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<4, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 4:
|
case 4:
|
||||||
_scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<1, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<2, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
_scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<3, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
_scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<4, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 2:
|
case 2:
|
||||||
_scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<1, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<2, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
_scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<3, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<4, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||||
|
switch (get_format_pixel_size(format)) {
|
||||||
|
case 2:
|
||||||
|
_scale_bilinear<1, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_scale_bilinear<2, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
_scale_bilinear<3, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
_scale_bilinear<4, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1326,46 +1483,61 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 1:
|
case 1:
|
||||||
_scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 4:
|
case 4:
|
||||||
_scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
_scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
_scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 2:
|
case 2:
|
||||||
_scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
_scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||||
|
switch (get_format_pixel_size(format)) {
|
||||||
|
case 2:
|
||||||
|
_scale_cubic<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_scale_cubic<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
_scale_cubic<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
_scale_cubic<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1374,46 +1546,61 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 1:
|
case 1:
|
||||||
_scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 4:
|
case 4:
|
||||||
_scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
_scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
_scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 2:
|
case 2:
|
||||||
_scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
_scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
||||||
|
switch (get_format_pixel_size(format)) {
|
||||||
|
case 2:
|
||||||
|
_scale_lanczos<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_scale_lanczos<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
_scale_lanczos<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
_scale_lanczos<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1782,7 +1969,7 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
|
||||||
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + right_step], rdown_ptr[j], rdown_ptr[j + right_step]);
|
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + right_step], rdown_ptr[j], rdown_ptr[j + right_step]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renormalize) {
|
if constexpr (renormalize) {
|
||||||
renormalize_func(dst_ptr);
|
renormalize_func(dst_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1828,6 +2015,12 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
|
||||||
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case Image::FORMAT_RGBA4444: {
|
||||||
|
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgba4444, nullptr>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
} break;
|
||||||
|
case Image::FORMAT_RGB565: {
|
||||||
|
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgb565, nullptr>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
} break;
|
||||||
case Image::FORMAT_RF:
|
case Image::FORMAT_RF:
|
||||||
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
|
@ -1869,8 +2062,32 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Image::FORMAT_RGBE9995:
|
case Image::FORMAT_RGBE9995:
|
||||||
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(src_u32, dst_u32, p_width, p_height);
|
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, nullptr>(src_u32, dst_u32, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
|
case Image::FORMAT_R16:
|
||||||
|
case Image::FORMAT_R16I:
|
||||||
|
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case Image::FORMAT_RG16:
|
||||||
|
case Image::FORMAT_RG16I:
|
||||||
|
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
break;
|
||||||
|
case Image::FORMAT_RGB16:
|
||||||
|
case Image::FORMAT_RGB16I: {
|
||||||
|
if (p_renormalize) {
|
||||||
|
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
} else {
|
||||||
|
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Image::FORMAT_RGBA16:
|
||||||
|
case Image::FORMAT_RGBA16I: {
|
||||||
|
if (p_renormalize) {
|
||||||
|
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
} else {
|
||||||
|
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
@ -1930,7 +2147,6 @@ void Image::normalize() {
|
||||||
|
|
||||||
Error Image::generate_mipmaps(bool p_renormalize) {
|
Error Image::generate_mipmaps(bool p_renormalize) {
|
||||||
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
|
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
|
||||||
ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format.");
|
|
||||||
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
|
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
|
||||||
|
|
||||||
int gen_mipmap_count;
|
int gen_mipmap_count;
|
||||||
|
@ -2468,6 +2684,17 @@ bool Image::is_invisible() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case FORMAT_RGBA16:
|
||||||
|
case FORMAT_RGBA16I: {
|
||||||
|
const int pixel_count = len / 8;
|
||||||
|
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
|
||||||
|
|
||||||
|
for (int i = 0; i < pixel_count; i++) {
|
||||||
|
if (pixeldata[i * 4 + 3] != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
// Formats that are compressed or don't support alpha channels are presumed to be visible.
|
// Formats that are compressed or don't support alpha channels are presumed to be visible.
|
||||||
return false;
|
return false;
|
||||||
|
@ -2671,7 +2898,7 @@ bool Image::is_compressed() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Image::is_format_compressed(Format p_format) {
|
bool Image::is_format_compressed(Format p_format) {
|
||||||
return p_format > FORMAT_RGBE9995;
|
return p_format > FORMAT_RGBE9995 && p_format < FORMAT_R16;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error Image::decompress() {
|
Error Image::decompress() {
|
||||||
|
@ -2902,20 +3129,17 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const P
|
||||||
|
|
||||||
int pixel_size = get_format_pixel_size(format);
|
int pixel_size = get_format_pixel_size(format);
|
||||||
|
|
||||||
for (int i = 0; i < dest_rect.size.y; i++) {
|
// If the rect width is equivalent for both src and dst and the x offset is 0, we can blit in a single memcpy.
|
||||||
for (int j = 0; j < dest_rect.size.x; j++) {
|
// Else, we do a per-line copy.
|
||||||
int src_x = src_rect.position.x + j;
|
if ((dest_rect.size.x == p_src->width) && (p_src->width == width) && (dest_rect.position.x == 0) && (src_rect.position.x == 0)) {
|
||||||
int src_y = src_rect.position.y + i;
|
const uint8_t *src = &src_data_ptr[(src_rect.position.y * p_src->width) * pixel_size];
|
||||||
|
uint8_t *dst = &dst_data_ptr[(dest_rect.position.y * width) * pixel_size];
|
||||||
int dst_x = dest_rect.position.x + j;
|
memcpy(dst, src, width * dest_rect.size.y * pixel_size);
|
||||||
int dst_y = dest_rect.position.y + i;
|
} else {
|
||||||
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
||||||
const uint8_t *src = &src_data_ptr[(src_y * p_src->width + src_x) * pixel_size];
|
const uint8_t *src = &src_data_ptr[((src_rect.position.y + i) * p_src->width + src_rect.position.x) * pixel_size];
|
||||||
uint8_t *dst = &dst_data_ptr[(dst_y * width + dst_x) * pixel_size];
|
uint8_t *dst = &dst_data_ptr[((dest_rect.position.y + i) * width + dest_rect.position.x) * pixel_size];
|
||||||
|
memcpy(dst, src, pixel_size * dest_rect.size.x);
|
||||||
for (int k = 0; k < pixel_size; k++) {
|
|
||||||
dst[k] = src[k];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3071,13 +3295,13 @@ void Image::fill(const Color &p_color) {
|
||||||
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
|
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
|
||||||
|
|
||||||
uint8_t *dst_data_ptr = data.ptrw();
|
uint8_t *dst_data_ptr = data.ptrw();
|
||||||
|
|
||||||
int pixel_size = get_format_pixel_size(format);
|
int pixel_size = get_format_pixel_size(format);
|
||||||
|
int64_t pixel_count = data.size() / pixel_size;
|
||||||
|
|
||||||
// Put first pixel with the format-aware API.
|
// Put first pixel with the format-aware API.
|
||||||
_set_color_at_ofs(dst_data_ptr, 0, p_color);
|
_set_color_at_ofs(dst_data_ptr, 0, p_color);
|
||||||
|
|
||||||
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height);
|
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, pixel_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
|
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
|
||||||
|
@ -3157,6 +3381,42 @@ void Image::_copy_internals_from(const Image &p_image) {
|
||||||
data = p_image.data;
|
data = p_image.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color color_from_rgba4444(uint16_t p_col) {
|
||||||
|
float r = ((p_col >> 12) & 0xF) / 15.0;
|
||||||
|
float g = ((p_col >> 8) & 0xF) / 15.0;
|
||||||
|
float b = ((p_col >> 4) & 0xF) / 15.0;
|
||||||
|
float a = (p_col & 0xF) / 15.0;
|
||||||
|
return Color(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ uint16_t color_to_rgba4444(Color p_col) {
|
||||||
|
uint16_t rgba = 0;
|
||||||
|
|
||||||
|
rgba = uint16_t(CLAMP(p_col.r * 15.0, 0, 15)) << 12;
|
||||||
|
rgba |= uint16_t(CLAMP(p_col.g * 15.0, 0, 15)) << 8;
|
||||||
|
rgba |= uint16_t(CLAMP(p_col.b * 15.0, 0, 15)) << 4;
|
||||||
|
rgba |= uint16_t(CLAMP(p_col.a * 15.0, 0, 15));
|
||||||
|
|
||||||
|
return rgba;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ Color color_from_rgb565(uint16_t p_col) {
|
||||||
|
float r = ((p_col >> 11) & 0x1F) / 31.0;
|
||||||
|
float g = ((p_col >> 5) & 0x3F) / 63.0;
|
||||||
|
float b = (p_col & 0x1F) / 31.0;
|
||||||
|
return Color(r, g, b, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ uint16_t color_to_rgb565(Color p_col) {
|
||||||
|
uint16_t rgba = 0;
|
||||||
|
|
||||||
|
rgba = uint16_t(CLAMP(p_col.r * 31.0, 0, 31)) << 11;
|
||||||
|
rgba |= uint16_t(CLAMP(p_col.g * 63.0, 0, 63)) << 5;
|
||||||
|
rgba |= uint16_t(CLAMP(p_col.b * 31.0, 0, 31));
|
||||||
|
|
||||||
|
return rgba;
|
||||||
|
}
|
||||||
|
|
||||||
Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case FORMAT_L8: {
|
case FORMAT_L8: {
|
||||||
|
@ -3191,19 +3451,10 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
||||||
return Color(r, g, b, a);
|
return Color(r, g, b, a);
|
||||||
}
|
}
|
||||||
case FORMAT_RGBA4444: {
|
case FORMAT_RGBA4444: {
|
||||||
uint16_t u = ((uint16_t *)ptr)[ofs];
|
return color_from_rgba4444(((uint16_t *)ptr)[ofs]);
|
||||||
float r = ((u >> 12) & 0xF) / 15.0;
|
|
||||||
float g = ((u >> 8) & 0xF) / 15.0;
|
|
||||||
float b = ((u >> 4) & 0xF) / 15.0;
|
|
||||||
float a = (u & 0xF) / 15.0;
|
|
||||||
return Color(r, g, b, a);
|
|
||||||
}
|
}
|
||||||
case FORMAT_RGB565: {
|
case FORMAT_RGB565: {
|
||||||
uint16_t u = ((uint16_t *)ptr)[ofs];
|
return color_from_rgb565(((uint16_t *)ptr)[ofs]);
|
||||||
float r = ((u >> 11) & 0x1F) / 31.0;
|
|
||||||
float g = ((u >> 5) & 0x3F) / 63.0;
|
|
||||||
float b = (u & 0x1F) / 31.0;
|
|
||||||
return Color(r, g, b, 1.0);
|
|
||||||
}
|
}
|
||||||
case FORMAT_RF: {
|
case FORMAT_RF: {
|
||||||
float r = ((float *)ptr)[ofs];
|
float r = ((float *)ptr)[ofs];
|
||||||
|
@ -3252,6 +3503,50 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
||||||
case FORMAT_RGBE9995: {
|
case FORMAT_RGBE9995: {
|
||||||
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
|
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
|
||||||
}
|
}
|
||||||
|
case FORMAT_R16: {
|
||||||
|
float r = ((uint16_t *)ptr)[ofs] / 65535.0f;
|
||||||
|
return Color(r, 0, 0, 1);
|
||||||
|
}
|
||||||
|
case FORMAT_RG16: {
|
||||||
|
float r = ((uint16_t *)ptr)[ofs * 2 + 0] / 65535.0f;
|
||||||
|
float g = ((uint16_t *)ptr)[ofs * 2 + 1] / 65535.0f;
|
||||||
|
return Color(r, g, 0, 1);
|
||||||
|
}
|
||||||
|
case FORMAT_RGB16: {
|
||||||
|
float r = ((uint16_t *)ptr)[ofs * 3 + 0] / 65535.0f;
|
||||||
|
float g = ((uint16_t *)ptr)[ofs * 3 + 1] / 65535.0f;
|
||||||
|
float b = ((uint16_t *)ptr)[ofs * 3 + 2] / 65535.0f;
|
||||||
|
return Color(r, g, b, 1);
|
||||||
|
}
|
||||||
|
case FORMAT_RGBA16: {
|
||||||
|
float r = ((uint16_t *)ptr)[ofs * 4 + 0] / 65535.0f;
|
||||||
|
float g = ((uint16_t *)ptr)[ofs * 4 + 1] / 65535.0f;
|
||||||
|
float b = ((uint16_t *)ptr)[ofs * 4 + 2] / 65535.0f;
|
||||||
|
float a = ((uint16_t *)ptr)[ofs * 4 + 3] / 65535.0f;
|
||||||
|
return Color(r, g, b, a);
|
||||||
|
}
|
||||||
|
case FORMAT_R16I: {
|
||||||
|
uint16_t r = ((uint16_t *)ptr)[ofs];
|
||||||
|
return Color(r, 0, 0, 1);
|
||||||
|
}
|
||||||
|
case FORMAT_RG16I: {
|
||||||
|
uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
|
||||||
|
uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
|
||||||
|
return Color(r, g, 0, 1);
|
||||||
|
}
|
||||||
|
case FORMAT_RGB16I: {
|
||||||
|
uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0];
|
||||||
|
uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1];
|
||||||
|
uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2];
|
||||||
|
return Color(r, g, b, 1);
|
||||||
|
}
|
||||||
|
case FORMAT_RGBA16I: {
|
||||||
|
uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0];
|
||||||
|
uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1];
|
||||||
|
uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2];
|
||||||
|
uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3];
|
||||||
|
return Color(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
|
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
|
||||||
|
@ -3287,23 +3582,10 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||||
ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
|
ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_RGBA4444: {
|
case FORMAT_RGBA4444: {
|
||||||
uint16_t rgba = 0;
|
((uint16_t *)ptr)[ofs] = color_to_rgba4444(p_color);
|
||||||
|
|
||||||
rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15)) << 12;
|
|
||||||
rgba |= uint16_t(CLAMP(p_color.g * 15.0, 0, 15)) << 8;
|
|
||||||
rgba |= uint16_t(CLAMP(p_color.b * 15.0, 0, 15)) << 4;
|
|
||||||
rgba |= uint16_t(CLAMP(p_color.a * 15.0, 0, 15));
|
|
||||||
|
|
||||||
((uint16_t *)ptr)[ofs] = rgba;
|
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_RGB565: {
|
case FORMAT_RGB565: {
|
||||||
uint16_t rgba = 0;
|
((uint16_t *)ptr)[ofs] = color_to_rgb565(p_color);
|
||||||
|
|
||||||
rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)) << 11;
|
|
||||||
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 63)) << 5;
|
|
||||||
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31));
|
|
||||||
|
|
||||||
((uint16_t *)ptr)[ofs] = rgba;
|
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_RF: {
|
case FORMAT_RF: {
|
||||||
((float *)ptr)[ofs] = p_color.r;
|
((float *)ptr)[ofs] = p_color.r;
|
||||||
|
@ -3344,6 +3626,42 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||||
case FORMAT_RGBE9995: {
|
case FORMAT_RGBE9995: {
|
||||||
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
|
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
|
||||||
} break;
|
} break;
|
||||||
|
case FORMAT_R16: {
|
||||||
|
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||||
|
} break;
|
||||||
|
case FORMAT_RG16: {
|
||||||
|
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
||||||
|
} break;
|
||||||
|
case FORMAT_RGB16: {
|
||||||
|
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
||||||
|
} break;
|
||||||
|
case FORMAT_RGBA16: {
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a * 65535.0, 0, 65535));
|
||||||
|
} break;
|
||||||
|
case FORMAT_R16I: {
|
||||||
|
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||||
|
} break;
|
||||||
|
case FORMAT_RG16I: {
|
||||||
|
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
||||||
|
} break;
|
||||||
|
case FORMAT_RGB16I: {
|
||||||
|
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
||||||
|
} break;
|
||||||
|
case FORMAT_RGBA16I: {
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
||||||
|
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a, 0, 65535));
|
||||||
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
|
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
|
||||||
|
@ -3419,11 +3737,11 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
|
||||||
|
|
||||||
if (format == FORMAT_L8) {
|
if (format == FORMAT_L8) {
|
||||||
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
|
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
|
||||||
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF) {
|
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF || format == FORMAT_R16 || format == FORMAT_R16I) {
|
||||||
return USED_CHANNELS_R; // Red only cannot have any channel less.
|
return USED_CHANNELS_R; // Red only cannot have any channel less.
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF;
|
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF || format == FORMAT_RGBA16 || format == FORMAT_RGBA16I;
|
||||||
bool r = false, g = false, b = false, a = false, c = false;
|
bool r = false, g = false, b = false, a = false, c = false;
|
||||||
|
|
||||||
const uint8_t *data_ptr = data.ptr();
|
const uint8_t *data_ptr = data.ptr();
|
||||||
|
@ -3657,6 +3975,14 @@ void Image::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
|
||||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
|
||||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_R16);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_RG16);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_RGB16);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_RGBA16);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_R16I);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_RG16I);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_RGB16I);
|
||||||
|
BIND_ENUM_CONSTANT(FORMAT_RGBA16I);
|
||||||
BIND_ENUM_CONSTANT(FORMAT_MAX);
|
BIND_ENUM_CONSTANT(FORMAT_MAX);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
|
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
|
||||||
|
@ -4070,6 +4396,22 @@ uint32_t Image::get_format_component_mask(Format p_format) {
|
||||||
return rgba;
|
return rgba;
|
||||||
case FORMAT_ASTC_8x8_HDR:
|
case FORMAT_ASTC_8x8_HDR:
|
||||||
return rgba;
|
return rgba;
|
||||||
|
case FORMAT_R16:
|
||||||
|
return r;
|
||||||
|
case FORMAT_RG16:
|
||||||
|
return rg;
|
||||||
|
case FORMAT_RGB16:
|
||||||
|
return rgb;
|
||||||
|
case FORMAT_RGBA16:
|
||||||
|
return rgba;
|
||||||
|
case FORMAT_R16I:
|
||||||
|
return r;
|
||||||
|
case FORMAT_RG16I:
|
||||||
|
return rg;
|
||||||
|
case FORMAT_RGB16I:
|
||||||
|
return rgb;
|
||||||
|
case FORMAT_RGBA16I:
|
||||||
|
return rgba;
|
||||||
default:
|
default:
|
||||||
ERR_PRINT("Unhandled format.");
|
ERR_PRINT("Unhandled format.");
|
||||||
return rgba;
|
return rgba;
|
||||||
|
@ -4213,6 +4555,18 @@ void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint3
|
||||||
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
|
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Image::average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
||||||
|
p_out = static_cast<uint16_t>((p_a + p_b + p_c + p_d + 2) >> 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
||||||
|
p_out = color_to_rgba4444((color_from_rgba4444(p_a) + color_from_rgba4444(p_b) + color_from_rgba4444(p_c) + color_from_rgba4444(p_d)) * 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
||||||
|
p_out = color_to_rgb565((color_from_rgb565(p_a) + color_from_rgb565(p_b) + color_from_rgb565(p_c) + color_from_rgb565(p_d)) * 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
void Image::renormalize_uint8(uint8_t *p_rgb) {
|
void Image::renormalize_uint8(uint8_t *p_rgb) {
|
||||||
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
|
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
|
||||||
n *= 2.0;
|
n *= 2.0;
|
||||||
|
@ -4242,8 +4596,17 @@ void Image::renormalize_half(uint16_t *p_rgb) {
|
||||||
p_rgb[2] = Math::make_half_float(n.z);
|
p_rgb[2] = Math::make_half_float(n.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
|
void Image::renormalize_uint16(uint16_t *p_rgb) {
|
||||||
// Never used.
|
Vector3 n(p_rgb[0] / 65535.0, p_rgb[1] / 65535.0, p_rgb[2] / 65535.0);
|
||||||
|
n *= 2.0;
|
||||||
|
n -= Vector3(1, 1, 1);
|
||||||
|
n.normalize();
|
||||||
|
n += Vector3(1, 1, 1);
|
||||||
|
n *= 0.5;
|
||||||
|
n *= 65535;
|
||||||
|
p_rgb[0] = CLAMP(int(n.x), 0, 65535);
|
||||||
|
p_rgb[1] = CLAMP(int(n.y), 0, 65535);
|
||||||
|
p_rgb[2] = CLAMP(int(n.z), 0, 65535);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
|
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
|
||||||
|
|
|
@ -111,6 +111,14 @@ public:
|
||||||
FORMAT_ASTC_4x4_HDR,
|
FORMAT_ASTC_4x4_HDR,
|
||||||
FORMAT_ASTC_8x8,
|
FORMAT_ASTC_8x8,
|
||||||
FORMAT_ASTC_8x8_HDR,
|
FORMAT_ASTC_8x8_HDR,
|
||||||
|
FORMAT_R16,
|
||||||
|
FORMAT_RG16,
|
||||||
|
FORMAT_RGB16,
|
||||||
|
FORMAT_RGBA16,
|
||||||
|
FORMAT_R16I,
|
||||||
|
FORMAT_RG16I,
|
||||||
|
FORMAT_RGB16I,
|
||||||
|
FORMAT_RGBA16I,
|
||||||
FORMAT_MAX
|
FORMAT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -282,10 +290,14 @@ private:
|
||||||
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
|
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
|
||||||
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||||
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
|
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
|
||||||
|
static void average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||||
|
static void average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||||
|
static void average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||||
|
|
||||||
static void renormalize_uint8(uint8_t *p_rgb);
|
static void renormalize_uint8(uint8_t *p_rgb);
|
||||||
static void renormalize_float(float *p_rgb);
|
static void renormalize_float(float *p_rgb);
|
||||||
static void renormalize_half(uint16_t *p_rgb);
|
static void renormalize_half(uint16_t *p_rgb);
|
||||||
static void renormalize_rgbe9995(uint32_t *p_rgb);
|
static void renormalize_uint16(uint16_t *p_rgb);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int get_width() const;
|
int get_width() const;
|
||||||
|
|
|
@ -101,6 +101,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderImage : public ResourceFormatLoader {
|
class ResourceFormatLoaderImage : public ResourceFormatLoader {
|
||||||
|
GDSOFTCLASS(ResourceFormatLoaderImage, ResourceFormatLoader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
|
||||||
#include "core/config/engine.h"
|
#include "core/config/engine.h"
|
||||||
|
#include "core/io/file_access.h"
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
#include "core/variant/container_type_validate.h"
|
#include "core/variant/container_type_validate.h"
|
||||||
|
|
||||||
|
@ -82,11 +83,18 @@ void JSON::_stringify(String &r_result, const Variant &p_var, const String &p_in
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const double magnitude = std::log10(Math::abs(num));
|
if (p_full_precision) {
|
||||||
const int total_digits = p_full_precision ? 17 : 14;
|
const String num_sci = String::num_scientific(num);
|
||||||
const int precision = MAX(1, total_digits - (int)Math::floor(magnitude));
|
if (num_sci.contains_char('.') || num_sci.contains_char('e')) {
|
||||||
|
r_result += num_sci;
|
||||||
r_result += String::num(num, precision);
|
} else {
|
||||||
|
r_result += num_sci + ".0";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const double magnitude = std::log10(Math::abs(num));
|
||||||
|
const int precision = MAX(1, 14 - (int)Math::floor(magnitude));
|
||||||
|
r_result += String::num(num, precision);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Variant::PACKED_INT32_ARRAY:
|
case Variant::PACKED_INT32_ARRAY:
|
||||||
|
|
|
@ -107,6 +107,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderJSON : public ResourceFormatLoader {
|
class ResourceFormatLoaderJSON : public ResourceFormatLoader {
|
||||||
|
GDSOFTCLASS(ResourceFormatLoaderJSON, ResourceFormatLoader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
||||||
|
@ -119,6 +121,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverJSON : public ResourceFormatSaver {
|
class ResourceFormatSaverJSON : public ResourceFormatSaver {
|
||||||
|
GDSOFTCLASS(ResourceFormatSaverJSON, ResourceFormatSaver);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
||||||
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
#include "core/core_globals.h"
|
#include "core/core_globals.h"
|
||||||
#include "core/io/dir_access.h"
|
#include "core/io/dir_access.h"
|
||||||
|
#include "core/io/file_access.h"
|
||||||
|
#include "core/object/script_backtrace.h"
|
||||||
#include "core/os/time.h"
|
#include "core/os/time.h"
|
||||||
#include "core/templates/rb_set.h"
|
#include "core/templates/rb_set.h"
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/io/file_access.h"
|
#include "core/object/ref_counted.h"
|
||||||
#include "core/object/script_backtrace.h"
|
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
|
class FileAccess;
|
||||||
class RegEx;
|
class RegEx;
|
||||||
|
class ScriptBacktrace;
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "core/object/ref_counted.h"
|
#include "core/object/ref_counted.h"
|
||||||
|
|
||||||
class NetSocket : public RefCounted {
|
class NetSocket : public RefCounted {
|
||||||
|
GDSOFTCLASS(NetSocket, RefCounted);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static NetSocket *(*_create)();
|
static NetSocket *(*_create)();
|
||||||
|
|
||||||
|
@ -52,21 +54,61 @@ public:
|
||||||
TYPE_UDP,
|
TYPE_UDP,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual Error open(Type p_type, IP::Type &ip_type) = 0;
|
enum class Family {
|
||||||
|
NONE,
|
||||||
|
INET,
|
||||||
|
UNIX,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Address {
|
||||||
|
Family _family = Family::NONE;
|
||||||
|
CharString _path;
|
||||||
|
IPAddress _ip;
|
||||||
|
uint16_t _port = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_FORCE_INLINE_ Family get_family() const { return _family; }
|
||||||
|
_FORCE_INLINE_ bool is_inet() const { return _family == Family::INET; }
|
||||||
|
_FORCE_INLINE_ bool is_unix() const { return _family == Family::UNIX; }
|
||||||
|
_FORCE_INLINE_ bool is_valid() const { return is_inet() || is_unix(); }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ const IPAddress &ip() const { return _ip; }
|
||||||
|
_FORCE_INLINE_ const uint16_t &port() const { return _port; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ const CharString &get_path() const { return _path; }
|
||||||
|
|
||||||
|
Address() {}
|
||||||
|
|
||||||
|
Address(const IPAddress &p_addr, uint16_t p_port) :
|
||||||
|
_family(Family::INET) {
|
||||||
|
_ip = p_addr;
|
||||||
|
_port = p_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
Address(const String &p_path) :
|
||||||
|
_family(Family::UNIX), _path(p_path.utf8()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Address(const CharString &p_path) :
|
||||||
|
_family(Family::UNIX), _path(p_path) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual Error open(Family p_family, Type p_type, IP::Type &r_ip_type) = 0;
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
virtual Error bind(IPAddress p_addr, uint16_t p_port) = 0;
|
virtual Error bind(Address p_addr) = 0;
|
||||||
virtual Error listen(int p_max_pending) = 0;
|
virtual Error listen(int p_max_pending) = 0;
|
||||||
virtual Error connect_to_host(IPAddress p_addr, uint16_t p_port) = 0;
|
virtual Error connect_to_host(Address p_addr) = 0;
|
||||||
virtual Error poll(PollType p_type, int timeout) const = 0;
|
virtual Error poll(PollType p_type, int timeout) const = 0;
|
||||||
virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0;
|
virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0;
|
||||||
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) = 0;
|
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) = 0;
|
||||||
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0;
|
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0;
|
||||||
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0;
|
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0;
|
||||||
virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port) = 0;
|
virtual Ref<NetSocket> accept(Address &r_addr) = 0;
|
||||||
|
|
||||||
virtual bool is_open() const = 0;
|
virtual bool is_open() const = 0;
|
||||||
virtual int get_available_bytes() const = 0;
|
virtual int get_available_bytes() const = 0;
|
||||||
virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const = 0;
|
virtual Error get_socket_address(Address *r_addr) const = 0;
|
||||||
|
|
||||||
virtual Error set_broadcasting_enabled(bool p_enabled) = 0; // Returns OK if the socket option has been set successfully.
|
virtual Error set_broadcasting_enabled(bool p_enabled) = 0; // Returns OK if the socket option has been set successfully.
|
||||||
virtual void set_blocking_enabled(bool p_enabled) = 0;
|
virtual void set_blocking_enabled(bool p_enabled) = 0;
|
||||||
|
|
|
@ -52,7 +52,7 @@ Error PacketPeerUDP::join_multicast_group(IPAddress p_multi_address, const Strin
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = p_multi_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = p_multi_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
Error err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
||||||
ERR_FAIL_COND_V(err != OK, err);
|
ERR_FAIL_COND_V(err != OK, err);
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_broadcasting_enabled(broadcast);
|
_sock->set_broadcasting_enabled(broadcast);
|
||||||
|
@ -141,7 +141,7 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
||||||
ERR_FAIL_COND_V(err != OK, err);
|
ERR_FAIL_COND_V(err != OK, err);
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_broadcasting_enabled(broadcast);
|
_sock->set_broadcasting_enabled(broadcast);
|
||||||
|
@ -186,7 +186,7 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec
|
||||||
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return ERR_CANT_CREATE;
|
return ERR_CANT_CREATE;
|
||||||
|
@ -194,7 +194,8 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec
|
||||||
|
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_broadcasting_enabled(broadcast);
|
_sock->set_broadcasting_enabled(broadcast);
|
||||||
err = _sock->bind(p_bind_address, p_port);
|
NetSocket::Address addr(p_bind_address, p_port);
|
||||||
|
err = _sock->bind(addr);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
_sock->close();
|
_sock->close();
|
||||||
|
@ -231,12 +232,13 @@ Error PacketPeerUDP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _sock->connect_to_host(p_host, p_port);
|
NetSocket::Address addr(p_host, p_port);
|
||||||
|
err = _sock->connect_to_host(addr);
|
||||||
|
|
||||||
// I see no reason why we should get ERR_BUSY (wouldblock/eagain) here.
|
// I see no reason why we should get ERR_BUSY (wouldblock/eagain) here.
|
||||||
// This is UDP, so connect is only used to tell the OS to which socket
|
// This is UDP, so connect is only used to tell the OS to which socket
|
||||||
|
@ -345,9 +347,9 @@ int PacketPeerUDP::get_packet_port() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PacketPeerUDP::get_local_port() const {
|
int PacketPeerUDP::get_local_port() const {
|
||||||
uint16_t local_port;
|
NetSocket::Address addr;
|
||||||
_sock->get_socket_address(nullptr, &local_port);
|
_sock->get_socket_address(&addr);
|
||||||
return local_port;
|
return addr.port();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketPeerUDP::set_dest_address(const IPAddress &p_address, int p_port) {
|
void PacketPeerUDP::set_dest_address(const IPAddress &p_address, int p_port) {
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
class PListNode;
|
class PListNode;
|
||||||
|
|
||||||
class PList : public RefCounted {
|
class PList : public RefCounted {
|
||||||
|
GDSOFTCLASS(PList, RefCounted);
|
||||||
|
|
||||||
friend class PListNode;
|
friend class PListNode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -660,6 +660,10 @@ void Resource::reset_local_to_scene() {
|
||||||
// Restores the state as if setup_local_to_scene() hadn't been called.
|
// Restores the state as if setup_local_to_scene() hadn't been called.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String Resource::_to_string() {
|
||||||
|
return (name.is_empty() ? "" : String(name) + " ") + "(" + path_cache + "):" + Object::_to_string();
|
||||||
|
}
|
||||||
|
|
||||||
Node *(*Resource::_get_local_scene_func)() = nullptr;
|
Node *(*Resource::_get_local_scene_func)() = nullptr;
|
||||||
void (*Resource::_update_configuration_warning)() = nullptr;
|
void (*Resource::_update_configuration_warning)() = nullptr;
|
||||||
|
|
||||||
|
@ -758,7 +762,9 @@ void Resource::_bind_methods() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::Resource() :
|
Resource::Resource() :
|
||||||
remapped_list(this) {}
|
remapped_list(this) {
|
||||||
|
_define_ancestry(AncestralClass::RESOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
Resource::~Resource() {
|
Resource::~Resource() {
|
||||||
if (unlikely(path_cache.is_empty())) {
|
if (unlikely(path_cache.is_empty())) {
|
||||||
|
|
|
@ -54,6 +54,8 @@ class Resource : public RefCounted {
|
||||||
GDCLASS(Resource, RefCounted);
|
GDCLASS(Resource, RefCounted);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static constexpr AncestralClass static_ancestral_class = AncestralClass::RESOURCE;
|
||||||
|
|
||||||
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension("res", get_class_static()); }
|
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension("res", get_class_static()); }
|
||||||
virtual String get_base_extension() const { return "res"; }
|
virtual String get_base_extension() const { return "res"; }
|
||||||
|
|
||||||
|
@ -120,6 +122,7 @@ protected:
|
||||||
GDVIRTUAL0(_reset_state);
|
GDVIRTUAL0(_reset_state);
|
||||||
|
|
||||||
virtual Ref<Resource> _duplicate(const DuplicateParams &p_params) const;
|
virtual Ref<Resource> _duplicate(const DuplicateParams &p_params) const;
|
||||||
|
virtual String _to_string() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Node *(*_get_local_scene_func)(); // Used by the editor.
|
static Node *(*_get_local_scene_func)(); // Used by the editor.
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "core/io/file_access.h"
|
#include "core/io/file_access.h"
|
||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/io/resource_saver.h"
|
#include "core/io/resource_saver.h"
|
||||||
|
#include "core/templates/rb_map.h"
|
||||||
|
|
||||||
class ResourceLoaderBinary {
|
class ResourceLoaderBinary {
|
||||||
bool translation_remapped = false;
|
bool translation_remapped = false;
|
||||||
|
@ -108,6 +109,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
|
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
|
||||||
|
GDSOFTCLASS(ResourceFormatLoaderBinary, ResourceFormatLoader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const override;
|
||||||
|
@ -179,6 +182,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverBinary : public ResourceFormatSaver {
|
class ResourceFormatSaverBinary : public ResourceFormatSaver {
|
||||||
|
GDSOFTCLASS(ResourceFormatSaverBinary, ResourceFormatSaver);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static inline ResourceFormatSaverBinary *singleton = nullptr;
|
static inline ResourceFormatSaverBinary *singleton = nullptr;
|
||||||
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
||||||
|
|
|
@ -39,6 +39,8 @@ class ResourceFormatImporter;
|
||||||
typedef Ref<Resource> (*ResourceFormatImporterLoadOnStartup)(ResourceFormatImporter *p_importer, const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, ResourceFormatLoader::CacheMode p_cache_mode);
|
typedef Ref<Resource> (*ResourceFormatImporterLoadOnStartup)(ResourceFormatImporter *p_importer, const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, ResourceFormatLoader::CacheMode p_cache_mode);
|
||||||
|
|
||||||
class ResourceFormatImporter : public ResourceFormatLoader {
|
class ResourceFormatImporter : public ResourceFormatLoader {
|
||||||
|
GDSOFTCLASS(ResourceFormatImporter, ResourceFormatLoader);
|
||||||
|
|
||||||
struct PathAndType {
|
struct PathAndType {
|
||||||
String path;
|
String path;
|
||||||
String type;
|
String type;
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#include "core/string/translation_server.h"
|
#include "core/string/translation_server.h"
|
||||||
#include "core/templates/rb_set.h"
|
#include "core/templates/rb_set.h"
|
||||||
#include "core/variant/variant_parser.h"
|
#include "core/variant/variant_parser.h"
|
||||||
#include "servers/rendering_server.h"
|
#include "servers/rendering/rendering_server.h"
|
||||||
|
|
||||||
#ifdef DEBUG_LOAD_THREADED
|
#ifdef DEBUG_LOAD_THREADED
|
||||||
#define print_lt(m_text) print_line(m_text)
|
#define print_lt(m_text) print_line(m_text)
|
||||||
|
@ -174,7 +174,7 @@ Ref<Resource> ResourceFormatLoader::load(const String &p_path, const String &p_o
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Failed to load resource '%s'. ResourceFormatLoader::load was not implemented for this resource type.", p_path));
|
return Ref<Resource>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
|
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
|
||||||
|
@ -1465,8 +1465,8 @@ void ResourceLoader::add_custom_loaders() {
|
||||||
|
|
||||||
String custom_loader_base_class = ResourceFormatLoader::get_class_static();
|
String custom_loader_base_class = ResourceFormatLoader::get_class_static();
|
||||||
|
|
||||||
List<StringName> global_classes;
|
LocalVector<StringName> global_classes;
|
||||||
ScriptServer::get_global_class_list(&global_classes);
|
ScriptServer::get_global_class_list(global_classes);
|
||||||
|
|
||||||
for (const StringName &class_name : global_classes) {
|
for (const StringName &class_name : global_classes) {
|
||||||
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
||||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
||||||
GDVIRTUAL2RC(Error, _rename_dependencies, String, Dictionary)
|
GDVIRTUAL2RC(Error, _rename_dependencies, String, Dictionary)
|
||||||
GDVIRTUAL1RC(bool, _exists, String)
|
GDVIRTUAL1RC(bool, _exists, String)
|
||||||
|
|
||||||
GDVIRTUAL4RC(Variant, _load, String, String, bool, int)
|
GDVIRTUAL4RC_REQUIRED(Variant, _load, String, String, bool, int)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
||||||
|
|
|
@ -255,8 +255,8 @@ void ResourceSaver::add_custom_savers() {
|
||||||
|
|
||||||
String custom_saver_base_class = ResourceFormatSaver::get_class_static();
|
String custom_saver_base_class = ResourceFormatSaver::get_class_static();
|
||||||
|
|
||||||
List<StringName> global_classes;
|
LocalVector<StringName> global_classes;
|
||||||
ScriptServer::get_global_class_list(&global_classes);
|
ScriptServer::get_global_class_list(global_classes);
|
||||||
|
|
||||||
for (const StringName &class_name : global_classes) {
|
for (const StringName &class_name : global_classes) {
|
||||||
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
||||||
|
|
|
@ -47,7 +47,7 @@ String ResourceUID::get_cache_file() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr uint8_t uuid_characters[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8' };
|
static constexpr uint8_t uuid_characters[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8' };
|
||||||
static constexpr uint32_t uuid_characters_element_count = std::size(uuid_characters);
|
static constexpr uint32_t uuid_characters_element_count = std_size(uuid_characters);
|
||||||
static constexpr uint8_t max_uuid_number_length = 13; // Max 0x7FFFFFFFFFFFFFFF (uid://d4n4ub6itg400) size is 13 characters.
|
static constexpr uint8_t max_uuid_number_length = 13; // Max 0x7FFFFFFFFFFFFFFF (uid://d4n4ub6itg400) size is 13 characters.
|
||||||
|
|
||||||
String ResourceUID::id_to_text(ID p_id) const {
|
String ResourceUID::id_to_text(ID p_id) const {
|
||||||
|
@ -351,6 +351,7 @@ void ResourceUID::clear() {
|
||||||
unique_ids.clear();
|
unique_ids.clear();
|
||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceUID::_bind_methods() {
|
void ResourceUID::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("id_to_text", "id"), &ResourceUID::id_to_text);
|
ClassDB::bind_method(D_METHOD("id_to_text", "id"), &ResourceUID::id_to_text);
|
||||||
ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
|
ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
|
||||||
|
|
90
core/io/socket_server.cpp
Normal file
90
core/io/socket_server.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* socket_server.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "socket_server.h"
|
||||||
|
|
||||||
|
void SocketServer::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("is_connection_available"), &SocketServer::is_connection_available);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_listening"), &SocketServer::is_listening);
|
||||||
|
ClassDB::bind_method(D_METHOD("stop"), &SocketServer::stop);
|
||||||
|
ClassDB::bind_method(D_METHOD("take_socket_connection"), &SocketServer::take_socket_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error SocketServer::_listen(const NetSocket::Address &p_addr) {
|
||||||
|
DEV_ASSERT(_sock.is_valid());
|
||||||
|
DEV_ASSERT(_sock->is_open());
|
||||||
|
|
||||||
|
_sock->set_blocking_enabled(false);
|
||||||
|
Error err = _sock->bind(p_addr);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
_sock->close();
|
||||||
|
return ERR_ALREADY_IN_USE;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _sock->listen(MAX_PENDING_CONNECTIONS);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
_sock->close();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SocketServer::is_listening() const {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), false);
|
||||||
|
|
||||||
|
return _sock->is_open();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SocketServer::is_connection_available() const {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), false);
|
||||||
|
|
||||||
|
if (!_sock->is_open()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
||||||
|
return (err == OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketServer::stop() {
|
||||||
|
if (_sock.is_valid()) {
|
||||||
|
_sock->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketServer::SocketServer() :
|
||||||
|
_sock(NetSocket::create()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketServer::~SocketServer() {
|
||||||
|
stop();
|
||||||
|
}
|
77
core/io/socket_server.h
Normal file
77
core/io/socket_server.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* socket_server.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/io/net_socket.h"
|
||||||
|
#include "core/io/stream_peer_socket.h"
|
||||||
|
|
||||||
|
class SocketServer : public RefCounted {
|
||||||
|
GDCLASS(SocketServer, RefCounted);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum {
|
||||||
|
MAX_PENDING_CONNECTIONS = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ref<NetSocket> _sock;
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
Error _listen(const NetSocket::Address &p_addr);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Ref<T> _take_connection() {
|
||||||
|
Ref<T> conn;
|
||||||
|
if (!is_connection_available()) {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<NetSocket> ns;
|
||||||
|
NetSocket::Address addr;
|
||||||
|
ns = _sock->accept(addr);
|
||||||
|
if (ns.is_null()) {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.instantiate();
|
||||||
|
conn->accept_socket(ns, addr);
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool is_listening() const;
|
||||||
|
bool is_connection_available() const;
|
||||||
|
virtual Ref<StreamPeerSocket> take_socket_connection() = 0;
|
||||||
|
|
||||||
|
void stop(); // Stop listening
|
||||||
|
|
||||||
|
SocketServer();
|
||||||
|
~SocketServer();
|
||||||
|
};
|
52
core/io/stream_peer_socket.compat.inc
Normal file
52
core/io/stream_peer_socket.compat.inc
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* stream_peer_socket.compat.inc */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
|
|
||||||
|
namespace compat::StreamPeerTCP {
|
||||||
|
enum class Status {
|
||||||
|
STATUS_NONE = StreamPeerSocket::STATUS_NONE,
|
||||||
|
STATUS_CONNECTING = StreamPeerSocket::STATUS_CONNECTING,
|
||||||
|
STATUS_CONNECTED = StreamPeerSocket::STATUS_CONNECTED,
|
||||||
|
STATUS_ERROR = StreamPeerSocket::STATUS_ERROR,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
VARIANT_ENUM_CAST(compat::StreamPeerTCP::Status);
|
||||||
|
|
||||||
|
compat::StreamPeerTCP::Status StreamPeerSocket::_get_status_compat_107954() const {
|
||||||
|
return (compat::StreamPeerTCP::Status)get_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPeerSocket::_bind_compatibility_methods() {
|
||||||
|
ClassDB::bind_compatibility_method(D_METHOD("get_status"), &StreamPeerSocket::_get_status_compat_107954);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
236
core/io/stream_peer_socket.cpp
Normal file
236
core/io/stream_peer_socket.cpp
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* stream_peer_socket.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "stream_peer_socket.h"
|
||||||
|
#include "stream_peer_socket.compat.inc"
|
||||||
|
|
||||||
|
Error StreamPeerSocket::poll() {
|
||||||
|
if (status == STATUS_CONNECTED) {
|
||||||
|
Error err;
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
||||||
|
if (err == OK) {
|
||||||
|
// FIN received
|
||||||
|
if (_sock->get_available_bytes() == 0) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Also poll write
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
|
||||||
|
if (err != OK && err != ERR_BUSY) {
|
||||||
|
// Got an error
|
||||||
|
disconnect_from_host();
|
||||||
|
status = STATUS_ERROR;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
} else if (status != STATUS_CONNECTING) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err = _sock->connect_to_host(peer_address);
|
||||||
|
|
||||||
|
if (err == OK) {
|
||||||
|
status = STATUS_CONNECTED;
|
||||||
|
return OK;
|
||||||
|
} else if (err == ERR_BUSY) {
|
||||||
|
// Check for connect timeout
|
||||||
|
if (OS::get_singleton()->get_ticks_msec() > timeout) {
|
||||||
|
disconnect_from_host();
|
||||||
|
status = STATUS_ERROR;
|
||||||
|
return ERR_CONNECTION_ERROR;
|
||||||
|
}
|
||||||
|
// Still trying to connect
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect_from_host();
|
||||||
|
status = STATUS_ERROR;
|
||||||
|
return ERR_CONNECTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerSocket::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
||||||
|
|
||||||
|
if (status != STATUS_CONNECTED) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err;
|
||||||
|
int data_to_send = p_bytes;
|
||||||
|
const uint8_t *offset = p_data;
|
||||||
|
int total_sent = 0;
|
||||||
|
|
||||||
|
while (data_to_send) {
|
||||||
|
int sent_amount = 0;
|
||||||
|
err = _sock->send(offset, data_to_send, sent_amount);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
if (err != ERR_BUSY) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_block) {
|
||||||
|
r_sent = total_sent;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block and wait for the socket to accept more data
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
|
||||||
|
if (err != OK) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data_to_send -= sent_amount;
|
||||||
|
offset += sent_amount;
|
||||||
|
total_sent += sent_amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r_sent = total_sent;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerSocket::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
|
||||||
|
if (status != STATUS_CONNECTED) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err;
|
||||||
|
int to_read = p_bytes;
|
||||||
|
int total_read = 0;
|
||||||
|
r_received = 0;
|
||||||
|
|
||||||
|
while (to_read) {
|
||||||
|
int read = 0;
|
||||||
|
err = _sock->recv(p_buffer + total_read, to_read, read);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
if (err != ERR_BUSY) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_block) {
|
||||||
|
r_received = total_read;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (read == 0) {
|
||||||
|
disconnect_from_host();
|
||||||
|
r_received = total_read;
|
||||||
|
return ERR_FILE_EOF;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
to_read -= read;
|
||||||
|
total_read += read;
|
||||||
|
|
||||||
|
if (!p_block) {
|
||||||
|
r_received = total_read;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r_received = total_read;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamPeerSocket::Status StreamPeerSocket::get_status() const {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPeerSocket::disconnect_from_host() {
|
||||||
|
if (_sock.is_valid() && _sock->is_open()) {
|
||||||
|
_sock->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout = 0;
|
||||||
|
status = STATUS_NONE;
|
||||||
|
peer_address = NetSocket::Address();
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerSocket::wait(NetSocket::PollType p_type, int p_timeout) {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
|
||||||
|
return _sock->poll(p_type, p_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerSocket::put_data(const uint8_t *p_data, int p_bytes) {
|
||||||
|
int total;
|
||||||
|
return write(p_data, p_bytes, total, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerSocket::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
|
||||||
|
return write(p_data, p_bytes, r_sent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerSocket::get_data(uint8_t *p_buffer, int p_bytes) {
|
||||||
|
int total;
|
||||||
|
return read(p_buffer, p_bytes, total, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerSocket::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
|
||||||
|
return read(p_buffer, p_bytes, r_received, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StreamPeerSocket::get_available_bytes() const {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), -1);
|
||||||
|
return _sock->get_available_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPeerSocket::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerSocket::poll);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerSocket::get_status);
|
||||||
|
ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerSocket::disconnect_from_host);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_NONE);
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_CONNECTING);
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_CONNECTED);
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamPeerSocket::StreamPeerSocket() :
|
||||||
|
_sock(NetSocket::create()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamPeerSocket::~StreamPeerSocket() {
|
||||||
|
disconnect_from_host();
|
||||||
|
}
|
93
core/io/stream_peer_socket.h
Normal file
93
core/io/stream_peer_socket.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* stream_peer_socket.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/io/net_socket.h"
|
||||||
|
#include "core/io/stream_peer.h"
|
||||||
|
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
|
namespace compat::StreamPeerTCP {
|
||||||
|
enum class Status;
|
||||||
|
} //namespace compat::StreamPeerTCP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class StreamPeerSocket : public StreamPeer {
|
||||||
|
GDCLASS(StreamPeerSocket, StreamPeer);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Status {
|
||||||
|
STATUS_NONE,
|
||||||
|
STATUS_CONNECTING,
|
||||||
|
STATUS_CONNECTED,
|
||||||
|
STATUS_ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
|
compat::StreamPeerTCP::Status _get_status_compat_107954() const;
|
||||||
|
static void _bind_compatibility_methods();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Ref<NetSocket> _sock;
|
||||||
|
uint64_t timeout = 0;
|
||||||
|
Status status = STATUS_NONE;
|
||||||
|
NetSocket::Address peer_address;
|
||||||
|
|
||||||
|
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
|
||||||
|
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
|
||||||
|
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) = 0;
|
||||||
|
|
||||||
|
void disconnect_from_host();
|
||||||
|
|
||||||
|
int get_available_bytes() const override;
|
||||||
|
Status get_status() const;
|
||||||
|
|
||||||
|
// Poll socket updating its state.
|
||||||
|
Error poll();
|
||||||
|
|
||||||
|
// Wait or check for writable, readable.
|
||||||
|
Error wait(NetSocket::PollType p_type, int p_timeout = 0);
|
||||||
|
|
||||||
|
// Read/Write from StreamPeer
|
||||||
|
Error put_data(const uint8_t *p_data, int p_bytes) override;
|
||||||
|
Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
|
||||||
|
Error get_data(uint8_t *p_buffer, int p_bytes) override;
|
||||||
|
Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
|
||||||
|
|
||||||
|
StreamPeerSocket();
|
||||||
|
virtual ~StreamPeerSocket();
|
||||||
|
};
|
||||||
|
|
||||||
|
VARIANT_ENUM_CAST(StreamPeerSocket::Status);
|
|
@ -32,60 +32,14 @@
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
|
|
||||||
Error StreamPeerTCP::poll() {
|
void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) {
|
||||||
if (status == STATUS_CONNECTED) {
|
|
||||||
Error err;
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
|
||||||
if (err == OK) {
|
|
||||||
// FIN received
|
|
||||||
if (_sock->get_available_bytes() == 0) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Also poll write
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
|
|
||||||
if (err != OK && err != ERR_BUSY) {
|
|
||||||
// Got an error
|
|
||||||
disconnect_from_host();
|
|
||||||
status = STATUS_ERROR;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
} else if (status != STATUS_CONNECTING) {
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err = _sock->connect_to_host(peer_host, peer_port);
|
|
||||||
|
|
||||||
if (err == OK) {
|
|
||||||
status = STATUS_CONNECTED;
|
|
||||||
return OK;
|
|
||||||
} else if (err == ERR_BUSY) {
|
|
||||||
// Check for connect timeout
|
|
||||||
if (OS::get_singleton()->get_ticks_msec() > timeout) {
|
|
||||||
disconnect_from_host();
|
|
||||||
status = STATUS_ERROR;
|
|
||||||
return ERR_CONNECTION_ERROR;
|
|
||||||
}
|
|
||||||
// Still trying to connect
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnect_from_host();
|
|
||||||
status = STATUS_ERROR;
|
|
||||||
return ERR_CONNECTION_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port) {
|
|
||||||
_sock = p_sock;
|
_sock = p_sock;
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
|
|
||||||
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
||||||
status = STATUS_CONNECTED;
|
status = STATUS_CONNECTED;
|
||||||
|
|
||||||
peer_host = p_host;
|
peer_address = p_addr;
|
||||||
peer_port = p_port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
|
Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
|
||||||
|
@ -97,12 +51,13 @@ Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
|
||||||
if (p_host.is_wildcard()) {
|
if (p_host.is_wildcard()) {
|
||||||
ip_type = IP::TYPE_ANY;
|
ip_type = IP::TYPE_ANY;
|
||||||
}
|
}
|
||||||
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
|
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
return _sock->bind(p_host, p_port);
|
NetSocket::Address addr(p_host, p_port);
|
||||||
|
return _sock->bind(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
|
@ -113,7 +68,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
|
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +76,9 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
||||||
Error err = _sock->connect_to_host(p_host, p_port);
|
|
||||||
|
NetSocket::Address addr(p_host, p_port);
|
||||||
|
Error err = _sock->connect_to_host(addr);
|
||||||
|
|
||||||
if (err == OK) {
|
if (err == OK) {
|
||||||
status = STATUS_CONNECTED;
|
status = STATUS_CONNECTED;
|
||||||
|
@ -133,106 +90,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer_host = p_host;
|
peer_address = addr;
|
||||||
peer_port = p_port;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
|
||||||
|
|
||||||
if (status != STATUS_CONNECTED) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err;
|
|
||||||
int data_to_send = p_bytes;
|
|
||||||
const uint8_t *offset = p_data;
|
|
||||||
int total_sent = 0;
|
|
||||||
|
|
||||||
while (data_to_send) {
|
|
||||||
int sent_amount = 0;
|
|
||||||
err = _sock->send(offset, data_to_send, sent_amount);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
if (err != ERR_BUSY) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p_block) {
|
|
||||||
r_sent = total_sent;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block and wait for the socket to accept more data
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
|
|
||||||
if (err != OK) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data_to_send -= sent_amount;
|
|
||||||
offset += sent_amount;
|
|
||||||
total_sent += sent_amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r_sent = total_sent;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
|
|
||||||
if (status != STATUS_CONNECTED) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err;
|
|
||||||
int to_read = p_bytes;
|
|
||||||
int total_read = 0;
|
|
||||||
r_received = 0;
|
|
||||||
|
|
||||||
while (to_read) {
|
|
||||||
int read = 0;
|
|
||||||
err = _sock->recv(p_buffer + total_read, to_read, read);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
if (err != ERR_BUSY) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p_block) {
|
|
||||||
r_received = total_read;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (read == 0) {
|
|
||||||
disconnect_from_host();
|
|
||||||
r_received = total_read;
|
|
||||||
return ERR_FILE_EOF;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
to_read -= read;
|
|
||||||
total_read += read;
|
|
||||||
|
|
||||||
if (!p_block) {
|
|
||||||
r_received = total_read;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r_received = total_read;
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -242,61 +100,18 @@ void StreamPeerTCP::set_no_delay(bool p_enabled) {
|
||||||
_sock->set_tcp_no_delay_enabled(p_enabled);
|
_sock->set_tcp_no_delay_enabled(p_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamPeerTCP::Status StreamPeerTCP::get_status() const {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamPeerTCP::disconnect_from_host() {
|
|
||||||
if (_sock.is_valid() && _sock->is_open()) {
|
|
||||||
_sock->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = 0;
|
|
||||||
status = STATUS_NONE;
|
|
||||||
peer_host = IPAddress();
|
|
||||||
peer_port = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerTCP::wait(NetSocket::PollType p_type, int p_timeout) {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
|
|
||||||
return _sock->poll(p_type, p_timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerTCP::put_data(const uint8_t *p_data, int p_bytes) {
|
|
||||||
int total;
|
|
||||||
return write(p_data, p_bytes, total, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerTCP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
|
|
||||||
return write(p_data, p_bytes, r_sent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerTCP::get_data(uint8_t *p_buffer, int p_bytes) {
|
|
||||||
int total;
|
|
||||||
return read(p_buffer, p_bytes, total, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerTCP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
|
|
||||||
return read(p_buffer, p_bytes, r_received, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int StreamPeerTCP::get_available_bytes() const {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), -1);
|
|
||||||
return _sock->get_available_bytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress StreamPeerTCP::get_connected_host() const {
|
IPAddress StreamPeerTCP::get_connected_host() const {
|
||||||
return peer_host;
|
return peer_address.ip();
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamPeerTCP::get_connected_port() const {
|
int StreamPeerTCP::get_connected_port() const {
|
||||||
return peer_port;
|
return peer_address.port();
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamPeerTCP::get_local_port() const {
|
int StreamPeerTCP::get_local_port() const {
|
||||||
uint16_t local_port;
|
NetSocket::Address addr;
|
||||||
_sock->get_socket_address(nullptr, &local_port);
|
_sock->get_socket_address(&addr);
|
||||||
return local_port;
|
return addr.port();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
|
Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
|
||||||
|
@ -316,24 +131,8 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
|
||||||
void StreamPeerTCP::_bind_methods() {
|
void StreamPeerTCP::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*"));
|
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*"));
|
||||||
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
|
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
|
||||||
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerTCP::poll);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
|
ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
|
||||||
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
|
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
|
||||||
ClassDB::bind_method(D_METHOD("get_local_port"), &StreamPeerTCP::get_local_port);
|
ClassDB::bind_method(D_METHOD("get_local_port"), &StreamPeerTCP::get_local_port);
|
||||||
ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host);
|
|
||||||
ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);
|
ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_NONE);
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_CONNECTING);
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_CONNECTED);
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamPeerTCP::StreamPeerTCP() :
|
|
||||||
_sock(Ref<NetSocket>(NetSocket::create())) {
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamPeerTCP::~StreamPeerTCP() {
|
|
||||||
disconnect_from_host();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,62 +32,24 @@
|
||||||
|
|
||||||
#include "core/io/ip.h"
|
#include "core/io/ip.h"
|
||||||
#include "core/io/ip_address.h"
|
#include "core/io/ip_address.h"
|
||||||
#include "core/io/net_socket.h"
|
#include "core/io/stream_peer_socket.h"
|
||||||
#include "core/io/stream_peer.h"
|
|
||||||
|
|
||||||
class StreamPeerTCP : public StreamPeer {
|
class StreamPeerTCP : public StreamPeerSocket {
|
||||||
GDCLASS(StreamPeerTCP, StreamPeer);
|
GDCLASS(StreamPeerTCP, StreamPeerSocket);
|
||||||
|
|
||||||
public:
|
|
||||||
enum Status {
|
|
||||||
STATUS_NONE,
|
|
||||||
STATUS_CONNECTING,
|
|
||||||
STATUS_CONNECTED,
|
|
||||||
STATUS_ERROR,
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Ref<NetSocket> _sock;
|
|
||||||
uint64_t timeout = 0;
|
|
||||||
Status status = STATUS_NONE;
|
|
||||||
IPAddress peer_host;
|
|
||||||
uint16_t peer_port = 0;
|
|
||||||
|
|
||||||
Error _connect(const String &p_address, int p_port);
|
Error _connect(const String &p_address, int p_port);
|
||||||
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
|
|
||||||
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
|
|
||||||
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port);
|
void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) override;
|
||||||
|
|
||||||
Error bind(int p_port, const IPAddress &p_host);
|
Error bind(int p_port, const IPAddress &p_host);
|
||||||
Error connect_to_host(const IPAddress &p_host, int p_port);
|
Error connect_to_host(const IPAddress &p_host, int p_port);
|
||||||
IPAddress get_connected_host() const;
|
IPAddress get_connected_host() const;
|
||||||
int get_connected_port() const;
|
int get_connected_port() const;
|
||||||
int get_local_port() const;
|
int get_local_port() const;
|
||||||
void disconnect_from_host();
|
|
||||||
|
|
||||||
int get_available_bytes() const override;
|
|
||||||
Status get_status() const;
|
|
||||||
|
|
||||||
void set_no_delay(bool p_enabled);
|
void set_no_delay(bool p_enabled);
|
||||||
|
|
||||||
// Poll socket updating its state.
|
|
||||||
Error poll();
|
|
||||||
|
|
||||||
// Wait or check for writable, readable.
|
|
||||||
Error wait(NetSocket::PollType p_type, int p_timeout = 0);
|
|
||||||
|
|
||||||
// Read/Write from StreamPeer
|
|
||||||
Error put_data(const uint8_t *p_data, int p_bytes) override;
|
|
||||||
Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
|
|
||||||
Error get_data(uint8_t *p_buffer, int p_bytes) override;
|
|
||||||
Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
|
|
||||||
|
|
||||||
StreamPeerTCP();
|
|
||||||
~StreamPeerTCP();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(StreamPeerTCP::Status);
|
|
||||||
|
|
99
core/io/stream_peer_uds.cpp
Normal file
99
core/io/stream_peer_uds.cpp
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* stream_peer_uds.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "stream_peer_uds.h"
|
||||||
|
|
||||||
|
#include "core/config/project_settings.h"
|
||||||
|
|
||||||
|
void StreamPeerUDS::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("bind", "path"), &StreamPeerUDS::bind);
|
||||||
|
ClassDB::bind_method(D_METHOD("connect_to_host", "path"), &StreamPeerUDS::connect_to_host);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_connected_path"), &StreamPeerUDS::get_connected_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPeerUDS::accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) {
|
||||||
|
_sock = p_sock;
|
||||||
|
_sock->set_blocking_enabled(false);
|
||||||
|
|
||||||
|
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/unix/connect_timeout_seconds")) * 1000);
|
||||||
|
status = STATUS_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerUDS::bind(const String &p_path) {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
||||||
|
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
|
||||||
|
|
||||||
|
IP::Type ip_type = IP::TYPE_NONE;
|
||||||
|
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
|
||||||
|
if (err != OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
_sock->set_blocking_enabled(false);
|
||||||
|
NetSocket::Address addr(p_path);
|
||||||
|
return _sock->bind(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerUDS::connect_to_host(const String &p_path) {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
||||||
|
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
|
||||||
|
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
if (!_sock->is_open()) {
|
||||||
|
IP::Type ip_type = IP::TYPE_NONE;
|
||||||
|
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
|
||||||
|
if (err != OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
_sock->set_blocking_enabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/unix/connect_timeout_seconds")) * 1000);
|
||||||
|
NetSocket::Address addr(p_path);
|
||||||
|
Error err = _sock->connect_to_host(addr);
|
||||||
|
|
||||||
|
if (err == OK) {
|
||||||
|
status = STATUS_CONNECTED;
|
||||||
|
} else if (err == ERR_BUSY) {
|
||||||
|
status = STATUS_CONNECTING;
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Connection to remote host failed!");
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer_address = addr;
|
||||||
|
peer_path = p_path;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String StreamPeerUDS::get_connected_path() const {
|
||||||
|
return String(peer_address.get_path().get_data());
|
||||||
|
}
|
48
core/io/stream_peer_uds.h
Normal file
48
core/io/stream_peer_uds.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* stream_peer_uds.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/io/stream_peer_socket.h"
|
||||||
|
|
||||||
|
class StreamPeerUDS : public StreamPeerSocket {
|
||||||
|
GDCLASS(StreamPeerUDS, StreamPeerSocket);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
String peer_path;
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) override;
|
||||||
|
|
||||||
|
Error bind(const String &p_path);
|
||||||
|
Error connect_to_host(const String &p_path);
|
||||||
|
const String get_connected_path() const;
|
||||||
|
};
|
|
@ -32,11 +32,8 @@
|
||||||
|
|
||||||
void TCPServer::_bind_methods() {
|
void TCPServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCPServer::listen, DEFVAL("*"));
|
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCPServer::listen, DEFVAL("*"));
|
||||||
ClassDB::bind_method(D_METHOD("is_connection_available"), &TCPServer::is_connection_available);
|
|
||||||
ClassDB::bind_method(D_METHOD("is_listening"), &TCPServer::is_listening);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_local_port"), &TCPServer::get_local_port);
|
ClassDB::bind_method(D_METHOD("get_local_port"), &TCPServer::get_local_port);
|
||||||
ClassDB::bind_method(D_METHOD("take_connection"), &TCPServer::take_connection);
|
ClassDB::bind_method(D_METHOD("take_connection"), &TCPServer::take_connection);
|
||||||
ClassDB::bind_method(D_METHOD("stop"), &TCPServer::stop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
|
@ -52,81 +49,21 @@ Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _sock->open(NetSocket::TYPE_TCP, ip_type);
|
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
|
||||||
|
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
|
|
||||||
_sock->set_blocking_enabled(false);
|
|
||||||
_sock->set_reuse_address_enabled(true);
|
_sock->set_reuse_address_enabled(true);
|
||||||
|
|
||||||
err = _sock->bind(p_bind_address, p_port);
|
return _listen(NetSocket::Address(p_bind_address, p_port));
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
_sock->close();
|
|
||||||
return ERR_ALREADY_IN_USE;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _sock->listen(MAX_PENDING_CONNECTIONS);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
_sock->close();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TCPServer::get_local_port() const {
|
int TCPServer::get_local_port() const {
|
||||||
uint16_t local_port;
|
NetSocket::Address addr;
|
||||||
_sock->get_socket_address(nullptr, &local_port);
|
_sock->get_socket_address(&addr);
|
||||||
return local_port;
|
return addr.port();
|
||||||
}
|
|
||||||
|
|
||||||
bool TCPServer::is_listening() const {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), false);
|
|
||||||
|
|
||||||
return _sock->is_open();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCPServer::is_connection_available() const {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), false);
|
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
|
||||||
return (err == OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<StreamPeerTCP> TCPServer::take_connection() {
|
Ref<StreamPeerTCP> TCPServer::take_connection() {
|
||||||
Ref<StreamPeerTCP> conn;
|
return _take_connection<StreamPeerTCP>();
|
||||||
if (!is_connection_available()) {
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<NetSocket> ns;
|
|
||||||
IPAddress ip;
|
|
||||||
uint16_t port = 0;
|
|
||||||
ns = _sock->accept(ip, port);
|
|
||||||
if (ns.is_null()) {
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.instantiate();
|
|
||||||
conn->accept_socket(ns, ip, port);
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPServer::stop() {
|
|
||||||
if (_sock.is_valid()) {
|
|
||||||
_sock->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPServer::TCPServer() :
|
|
||||||
_sock(Ref<NetSocket>(NetSocket::create())) {
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPServer::~TCPServer() {
|
|
||||||
stop();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,30 +31,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/io/ip.h"
|
#include "core/io/ip.h"
|
||||||
#include "core/io/net_socket.h"
|
#include "core/io/socket_server.h"
|
||||||
#include "core/io/stream_peer.h"
|
|
||||||
#include "core/io/stream_peer_tcp.h"
|
#include "core/io/stream_peer_tcp.h"
|
||||||
|
|
||||||
class TCPServer : public RefCounted {
|
class TCPServer : public SocketServer {
|
||||||
GDCLASS(TCPServer, RefCounted);
|
GDCLASS(TCPServer, SocketServer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum {
|
|
||||||
MAX_PENDING_CONNECTIONS = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
Ref<NetSocket> _sock;
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Error listen(uint16_t p_port, const IPAddress &p_bind_address = IPAddress("*"));
|
Error listen(uint16_t p_port, const IPAddress &p_bind_address = IPAddress("*"));
|
||||||
int get_local_port() const;
|
int get_local_port() const;
|
||||||
bool is_listening() const;
|
|
||||||
bool is_connection_available() const;
|
|
||||||
Ref<StreamPeerTCP> take_connection();
|
Ref<StreamPeerTCP> take_connection();
|
||||||
|
Ref<StreamPeerSocket> take_socket_connection() override { return take_connection(); }
|
||||||
void stop(); // Stop listening
|
|
||||||
|
|
||||||
TCPServer();
|
|
||||||
~TCPServer();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include "translation_loader_po.h"
|
#include "translation_loader_po.h"
|
||||||
|
|
||||||
#include "core/io/file_access.h"
|
#include "core/io/file_access.h"
|
||||||
#include "core/string/translation_po.h"
|
#include "core/string/translation.h"
|
||||||
|
|
||||||
Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
|
Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
|
||||||
if (r_error) {
|
if (r_error) {
|
||||||
|
@ -39,7 +39,8 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
|
||||||
}
|
}
|
||||||
|
|
||||||
const String path = f->get_path();
|
const String path = f->get_path();
|
||||||
Ref<TranslationPO> translation = Ref<TranslationPO>(memnew(TranslationPO));
|
Ref<Translation> translation;
|
||||||
|
translation.instantiate();
|
||||||
String config;
|
String config;
|
||||||
|
|
||||||
uint32_t magic = f->get_32();
|
uint32_t magic = f->get_32();
|
||||||
|
@ -112,7 +113,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
|
||||||
int p_start = config.find("Plural-Forms");
|
int p_start = config.find("Plural-Forms");
|
||||||
if (p_start != -1) {
|
if (p_start != -1) {
|
||||||
int p_end = config.find_char('\n', p_start);
|
int p_end = config.find_char('\n', p_start);
|
||||||
translation->set_plural_rule(config.substr(p_start, p_end - p_start));
|
translation->set_plural_rules_override(config.substr(p_start, p_end - p_start));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint32_t str_start = 0;
|
uint32_t str_start = 0;
|
||||||
|
@ -228,8 +229,8 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
|
||||||
int p_start = config.find("Plural-Forms");
|
int p_start = config.find("Plural-Forms");
|
||||||
if (p_start != -1) {
|
if (p_start != -1) {
|
||||||
int p_end = config.find_char('\n', p_start);
|
int p_end = config.find_char('\n', p_start);
|
||||||
translation->set_plural_rule(config.substr(p_start, p_end - p_start));
|
translation->set_plural_rules_override(config.substr(p_start, p_end - p_start));
|
||||||
plural_forms = translation->get_plural_forms();
|
plural_forms = translation->get_nplurals();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,10 @@
|
||||||
|
|
||||||
#include "core/io/file_access.h"
|
#include "core/io/file_access.h"
|
||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/string/translation.h"
|
|
||||||
|
|
||||||
class TranslationLoaderPO : public ResourceFormatLoader {
|
class TranslationLoaderPO : public ResourceFormatLoader {
|
||||||
|
GDSOFTCLASS(TranslationLoaderPO, ResourceFormatLoader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Ref<Resource> load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
|
static Ref<Resource> load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
|
|
|
@ -99,7 +99,7 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return ERR_CANT_CREATE;
|
return ERR_CANT_CREATE;
|
||||||
|
@ -107,7 +107,8 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
|
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_reuse_address_enabled(true);
|
_sock->set_reuse_address_enabled(true);
|
||||||
err = _sock->bind(p_bind_address, p_port);
|
NetSocket::Address addr(p_bind_address, p_port);
|
||||||
|
err = _sock->bind(addr);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
stop();
|
stop();
|
||||||
|
@ -117,9 +118,9 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int UDPServer::get_local_port() const {
|
int UDPServer::get_local_port() const {
|
||||||
uint16_t local_port;
|
NetSocket::Address addr;
|
||||||
_sock->get_socket_address(nullptr, &local_port);
|
_sock->get_socket_address(&addr);
|
||||||
return local_port;
|
return addr.port();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UDPServer::is_listening() const {
|
bool UDPServer::is_listening() const {
|
||||||
|
|
52
core/io/uds_server.cpp
Normal file
52
core/io/uds_server.cpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* uds_server.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "uds_server.h"
|
||||||
|
|
||||||
|
void UDSServer::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("listen", "path"), &UDSServer::listen);
|
||||||
|
ClassDB::bind_method(D_METHOD("take_connection"), &UDSServer::take_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error UDSServer::listen(const String &p_path) {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
||||||
|
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
|
||||||
|
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
IP::Type ip_type = IP::TYPE_NONE;
|
||||||
|
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
|
||||||
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
|
|
||||||
|
return _listen(p_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<StreamPeerUDS> UDSServer::take_connection() {
|
||||||
|
return _take_connection<StreamPeerUDS>();
|
||||||
|
}
|
46
core/io/uds_server.h
Normal file
46
core/io/uds_server.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* uds_server.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/io/socket_server.h"
|
||||||
|
#include "core/io/stream_peer_uds.h"
|
||||||
|
|
||||||
|
class UDSServer : public SocketServer {
|
||||||
|
GDCLASS(UDSServer, SocketServer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Error listen(const String &p_path);
|
||||||
|
Ref<StreamPeerUDS> take_connection();
|
||||||
|
Ref<StreamPeerSocket> take_socket_connection() override { return take_connection(); }
|
||||||
|
};
|
|
@ -783,7 +783,7 @@ void AStarGrid2D::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "jumping_enabled"), "set_jumping_enabled", "is_jumping_enabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "jumping_enabled"), "set_jumping_enabled", "is_jumping_enabled");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "default_compute_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_compute_heuristic", "get_default_compute_heuristic");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "default_compute_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_compute_heuristic", "get_default_compute_heuristic");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "default_estimate_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_estimate_heuristic", "get_default_estimate_heuristic");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "default_estimate_heuristic", PROPERTY_HINT_ENUM, "Euclidean,Manhattan,Octile,Chebyshev"), "set_default_estimate_heuristic", "get_default_estimate_heuristic");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "diagonal_mode", PROPERTY_HINT_ENUM, "Never,Always,At Least One Walkable,Only If No Obstacles"), "set_diagonal_mode", "get_diagonal_mode");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "diagonal_mode", PROPERTY_HINT_ENUM, "Always,Never,At Least One Walkable,Only If No Obstacles"), "set_diagonal_mode", "get_diagonal_mode");
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(HEURISTIC_EUCLIDEAN);
|
BIND_ENUM_CONSTANT(HEURISTIC_EUCLIDEAN);
|
||||||
BIND_ENUM_CONSTANT(HEURISTIC_MANHATTAN);
|
BIND_ENUM_CONSTANT(HEURISTIC_MANHATTAN);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "core/math/plane.h"
|
#include "core/math/plane.h"
|
||||||
#include "core/math/vector3.h"
|
#include "core/math/vector3.h"
|
||||||
|
#include "core/templates/hashfuncs.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AABB (Axis Aligned Bounding Box)
|
* AABB (Axis Aligned Bounding Box)
|
||||||
|
@ -131,6 +132,16 @@ struct [[nodiscard]] AABB {
|
||||||
return position + (size * 0.5f);
|
return position + (size * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t hash() const {
|
||||||
|
uint32_t h = hash_murmur3_one_real(position.x);
|
||||||
|
h = hash_murmur3_one_real(position.y, h);
|
||||||
|
h = hash_murmur3_one_real(position.z, h);
|
||||||
|
h = hash_murmur3_one_real(size.x, h);
|
||||||
|
h = hash_murmur3_one_real(size.y, h);
|
||||||
|
h = hash_murmur3_one_real(size.z, h);
|
||||||
|
return hash_fmix32(h);
|
||||||
|
}
|
||||||
|
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
|
|
||||||
AABB() = default;
|
AABB() = default;
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
#include "core/math/vector3.h"
|
#include "core/math/vector3.h"
|
||||||
|
|
||||||
struct [[nodiscard]] Basis {
|
struct [[nodiscard]] Basis {
|
||||||
|
static const Basis FLIP_X;
|
||||||
|
static const Basis FLIP_Y;
|
||||||
|
static const Basis FLIP_Z;
|
||||||
|
|
||||||
Vector3 rows[3] = {
|
Vector3 rows[3] = {
|
||||||
Vector3(1, 0, 0),
|
Vector3(1, 0, 0),
|
||||||
Vector3(0, 1, 0),
|
Vector3(0, 1, 0),
|
||||||
|
@ -224,7 +228,7 @@ struct [[nodiscard]] Basis {
|
||||||
|
|
||||||
operator Quaternion() const { return get_quaternion(); }
|
operator Quaternion() const { return get_quaternion(); }
|
||||||
|
|
||||||
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false);
|
||||||
|
|
||||||
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }
|
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }
|
||||||
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
|
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
|
||||||
|
@ -247,6 +251,10 @@ private:
|
||||||
void _set_diagonal(const Vector3 &p_diag);
|
void _set_diagonal(const Vector3 &p_diag);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline constexpr Basis Basis::FLIP_X = { { -1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
|
||||||
|
inline constexpr Basis Basis::FLIP_Y = { { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } };
|
||||||
|
inline constexpr Basis Basis::FLIP_Z = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, -1 } };
|
||||||
|
|
||||||
constexpr bool Basis::operator==(const Basis &p_matrix) const {
|
constexpr bool Basis::operator==(const Basis &p_matrix) const {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
|
|
|
@ -432,7 +432,7 @@ int Color::find_named_color(const String &p_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Color::get_named_color_count() {
|
int Color::get_named_color_count() {
|
||||||
return std::size(named_colors);
|
return std_size(named_colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
String Color::get_named_color_name(int p_idx) {
|
String Color::get_named_color_name(int p_idx) {
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/math/math_funcs.h"
|
#include "core/math/math_funcs.h"
|
||||||
|
#include "core/templates/hashfuncs.h"
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
|
|
||||||
|
@ -239,6 +240,14 @@ struct [[nodiscard]] Color {
|
||||||
_FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
|
_FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
|
||||||
_FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
|
_FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
|
||||||
|
|
||||||
|
uint32_t hash() const {
|
||||||
|
uint32_t h = hash_murmur3_one_float(r);
|
||||||
|
h = hash_murmur3_one_float(r, h);
|
||||||
|
h = hash_murmur3_one_float(b, h);
|
||||||
|
h = hash_murmur3_one_float(a, h);
|
||||||
|
return hash_fmix32(h);
|
||||||
|
}
|
||||||
|
|
||||||
constexpr Color() :
|
constexpr Color() :
|
||||||
r(0), g(0), b(0), a(1) {}
|
r(0), g(0), b(0), a(1) {}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "core/math/aabb.h"
|
#include "core/math/aabb.h"
|
||||||
#include "core/math/projection.h"
|
#include "core/math/projection.h"
|
||||||
#include "core/math/vector3.h"
|
#include "core/math/vector3.h"
|
||||||
|
#include "core/math/vector3i.h"
|
||||||
#include "core/templates/a_hash_map.h"
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/list.h"
|
#include "core/templates/list.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
|
|
|
@ -30,7 +30,9 @@
|
||||||
|
|
||||||
#include "geometry_2d.h"
|
#include "geometry_2d.h"
|
||||||
|
|
||||||
|
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Walloc-zero")
|
||||||
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
||||||
|
GODOT_GCC_WARNING_POP
|
||||||
#include "thirdparty/misc/polypartition.h"
|
#include "thirdparty/misc/polypartition.h"
|
||||||
#define STB_RECT_PACK_IMPLEMENTATION
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
#include "thirdparty/misc/stb_rect_pack.h"
|
#include "thirdparty/misc/stb_rect_pack.h"
|
||||||
|
@ -292,14 +294,16 @@ Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Vector<Point2>> polypaths;
|
Vector<Vector<Point2>> polypaths;
|
||||||
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
|
polypaths.resize(paths.size());
|
||||||
|
for (PathsD::size_type i = 0; i < paths.size(); i++) {
|
||||||
const PathD &path = paths[i];
|
const PathD &path = paths[i];
|
||||||
|
|
||||||
Vector<Vector2> polypath;
|
Vector<Vector2> polypath;
|
||||||
|
polypath.resize(path.size());
|
||||||
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
||||||
polypath.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
polypath.set(j, Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
||||||
}
|
}
|
||||||
polypaths.push_back(polypath);
|
polypaths.set(i, polypath);
|
||||||
}
|
}
|
||||||
return polypaths;
|
return polypaths;
|
||||||
}
|
}
|
||||||
|
@ -353,14 +357,16 @@ Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_poly
|
||||||
// to attain the desired precision.
|
// to attain the desired precision.
|
||||||
|
|
||||||
Vector<Vector<Point2>> polypaths;
|
Vector<Vector<Point2>> polypaths;
|
||||||
|
polypaths.resize(paths.size());
|
||||||
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
|
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
|
||||||
const PathD &path = paths[i];
|
const PathD &path = paths[i];
|
||||||
|
|
||||||
Vector<Vector2> polypath2;
|
Vector<Vector2> polypath2;
|
||||||
|
polypath2.resize(path.size());
|
||||||
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
||||||
polypath2.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
polypath2.set(j, Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
||||||
}
|
}
|
||||||
polypaths.push_back(polypath2);
|
polypaths.set(i, polypath2);
|
||||||
}
|
}
|
||||||
return polypaths;
|
return polypaths;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/math/color.h"
|
||||||
#include "core/math/delaunay_3d.h"
|
#include "core/math/delaunay_3d.h"
|
||||||
#include "core/math/face3.h"
|
#include "core/math/face3.h"
|
||||||
|
#include "core/math/vector2.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
|
@ -292,6 +294,10 @@ public:
|
||||||
real_t den = p.normal.dot(dir);
|
real_t den = p.normal.dot(dir);
|
||||||
|
|
||||||
if (Math::abs(den) <= (real_t)CMP_EPSILON) {
|
if (Math::abs(den) <= (real_t)CMP_EPSILON) {
|
||||||
|
if (p.is_point_over(p_from)) {
|
||||||
|
// Separating plane.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
continue; // Ignore parallel plane.
|
continue; // Ignore parallel plane.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,10 @@
|
||||||
class Variant;
|
class Variant;
|
||||||
|
|
||||||
struct [[nodiscard]] Plane {
|
struct [[nodiscard]] Plane {
|
||||||
|
static const Plane PLANE_YZ;
|
||||||
|
static const Plane PLANE_XZ;
|
||||||
|
static const Plane PLANE_XY;
|
||||||
|
|
||||||
Vector3 normal;
|
Vector3 normal;
|
||||||
real_t d = 0;
|
real_t d = 0;
|
||||||
|
|
||||||
|
@ -90,6 +94,10 @@ struct [[nodiscard]] Plane {
|
||||||
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
|
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline constexpr Plane Plane::PLANE_YZ = { 1, 0, 0, 0 };
|
||||||
|
inline constexpr Plane Plane::PLANE_XZ = { 0, 1, 0, 0 };
|
||||||
|
inline constexpr Plane Plane::PLANE_XY = { 0, 0, 1, 0 };
|
||||||
|
|
||||||
bool Plane::is_point_over(const Vector3 &p_point) const {
|
bool Plane::is_point_over(const Vector3 &p_point) const {
|
||||||
return (normal.dot(p_point) > d);
|
return (normal.dot(p_point) > d);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/vector2.h"
|
#include "core/math/vector2.h"
|
||||||
|
#include "core/templates/hashfuncs.h"
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
struct Rect2i;
|
struct Rect2i;
|
||||||
|
@ -361,6 +362,14 @@ struct [[nodiscard]] Rect2 {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Rect2i() const;
|
operator Rect2i() const;
|
||||||
|
|
||||||
|
uint32_t hash() const {
|
||||||
|
uint32_t h = hash_murmur3_one_real(position.x);
|
||||||
|
h = hash_murmur3_one_real(position.y, h);
|
||||||
|
h = hash_murmur3_one_real(size.x, h);
|
||||||
|
h = hash_murmur3_one_real(size.y, h);
|
||||||
|
return hash_fmix32(h);
|
||||||
|
}
|
||||||
|
|
||||||
Rect2() = default;
|
Rect2() = default;
|
||||||
constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
|
constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
|
||||||
position(Point2(p_x, p_y)),
|
position(Point2(p_x, p_y)),
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/vector2i.h"
|
#include "core/math/vector2i.h"
|
||||||
|
#include "core/templates/hashfuncs.h"
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
struct Rect2;
|
struct Rect2;
|
||||||
|
@ -226,6 +227,14 @@ struct [[nodiscard]] Rect2i {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Rect2() const;
|
operator Rect2() const;
|
||||||
|
|
||||||
|
uint32_t hash() const {
|
||||||
|
uint32_t h = hash_murmur3_one_32(uint32_t(position.x));
|
||||||
|
h = hash_murmur3_one_32(uint32_t(position.y), h);
|
||||||
|
h = hash_murmur3_one_32(uint32_t(size.x), h);
|
||||||
|
h = hash_murmur3_one_32(uint32_t(size.y), h);
|
||||||
|
return hash_fmix32(h);
|
||||||
|
}
|
||||||
|
|
||||||
Rect2i() = default;
|
Rect2i() = default;
|
||||||
constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) :
|
constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) :
|
||||||
position(Point2i(p_x, p_y)),
|
position(Point2i(p_x, p_y)),
|
||||||
|
|
|
@ -52,6 +52,9 @@ struct [[nodiscard]] Transform2D {
|
||||||
// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
|
// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
|
||||||
// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
|
// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
|
||||||
|
|
||||||
|
static const Transform2D FLIP_X;
|
||||||
|
static const Transform2D FLIP_Y;
|
||||||
|
|
||||||
Vector2 columns[3] = {
|
Vector2 columns[3] = {
|
||||||
{ 1, 0 },
|
{ 1, 0 },
|
||||||
{ 0, 1 },
|
{ 0, 1 },
|
||||||
|
@ -149,6 +152,9 @@ struct [[nodiscard]] Transform2D {
|
||||||
Transform2D() = default;
|
Transform2D() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline constexpr Transform2D Transform2D::FLIP_X = { { -1, 0 }, { 0, 1 }, { 0, 0 } };
|
||||||
|
inline constexpr Transform2D Transform2D::FLIP_Y = { { 1, 0 }, { 0, -1 }, { 0, 0 } };
|
||||||
|
|
||||||
constexpr bool Transform2D::operator==(const Transform2D &p_transform) const {
|
constexpr bool Transform2D::operator==(const Transform2D &p_transform) const {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (columns[i] != p_transform.columns[i]) {
|
if (columns[i] != p_transform.columns[i]) {
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
struct [[nodiscard]] Transform3D {
|
struct [[nodiscard]] Transform3D {
|
||||||
|
static const Transform3D FLIP_X;
|
||||||
|
static const Transform3D FLIP_Y;
|
||||||
|
static const Transform3D FLIP_Z;
|
||||||
|
|
||||||
Basis basis;
|
Basis basis;
|
||||||
Vector3 origin;
|
Vector3 origin;
|
||||||
|
|
||||||
|
@ -51,8 +55,8 @@ struct [[nodiscard]] Transform3D {
|
||||||
void rotate(const Vector3 &p_axis, real_t p_angle);
|
void rotate(const Vector3 &p_axis, real_t p_angle);
|
||||||
void rotate_basis(const Vector3 &p_axis, real_t p_angle);
|
void rotate_basis(const Vector3 &p_axis, real_t p_angle);
|
||||||
|
|
||||||
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false);
|
||||||
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false) const;
|
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false) const;
|
||||||
|
|
||||||
void scale(const Vector3 &p_scale);
|
void scale(const Vector3 &p_scale);
|
||||||
Transform3D scaled(const Vector3 &p_scale) const;
|
Transform3D scaled(const Vector3 &p_scale) const;
|
||||||
|
@ -136,6 +140,10 @@ struct [[nodiscard]] Transform3D {
|
||||||
origin(p_ox, p_oy, p_oz) {}
|
origin(p_ox, p_oy, p_oz) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline constexpr Transform3D Transform3D::FLIP_X = { Basis::FLIP_X };
|
||||||
|
inline constexpr Transform3D Transform3D::FLIP_Y = { Basis::FLIP_Y };
|
||||||
|
inline constexpr Transform3D Transform3D::FLIP_Z = { Basis::FLIP_Z };
|
||||||
|
|
||||||
constexpr bool Transform3D::operator==(const Transform3D &p_transform) const {
|
constexpr bool Transform3D::operator==(const Transform3D &p_transform) const {
|
||||||
return (basis == p_transform.basis && origin == p_transform.origin);
|
return (basis == p_transform.basis && origin == p_transform.origin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,18 @@
|
||||||
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/math_funcs.h"
|
#include "core/math/math_funcs.h"
|
||||||
|
#include "core/templates/hashfuncs.h"
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
struct Vector2i;
|
struct Vector2i;
|
||||||
|
|
||||||
struct [[nodiscard]] Vector2 {
|
struct [[nodiscard]] Vector2 {
|
||||||
static const int AXIS_COUNT = 2;
|
static const Vector2 LEFT;
|
||||||
|
static const Vector2 RIGHT;
|
||||||
|
static const Vector2 UP;
|
||||||
|
static const Vector2 DOWN;
|
||||||
|
|
||||||
|
static constexpr int AXIS_COUNT = 2;
|
||||||
|
|
||||||
enum Axis {
|
enum Axis {
|
||||||
AXIS_X,
|
AXIS_X,
|
||||||
|
@ -185,6 +191,12 @@ struct [[nodiscard]] Vector2 {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Vector2i() const;
|
operator Vector2i() const;
|
||||||
|
|
||||||
|
uint32_t hash() const {
|
||||||
|
uint32_t h = hash_murmur3_one_real(x);
|
||||||
|
h = hash_murmur3_one_real(y, h);
|
||||||
|
return hash_fmix32(h);
|
||||||
|
}
|
||||||
|
|
||||||
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
|
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
|
||||||
constexpr Vector2() :
|
constexpr Vector2() :
|
||||||
x(0), y(0) {}
|
x(0), y(0) {}
|
||||||
|
@ -193,6 +205,11 @@ struct [[nodiscard]] Vector2 {
|
||||||
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
|
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline constexpr Vector2 Vector2::LEFT = { -1, 0 };
|
||||||
|
inline constexpr Vector2 Vector2::RIGHT = { 1, 0 };
|
||||||
|
inline constexpr Vector2 Vector2::UP = { 0, -1 };
|
||||||
|
inline constexpr Vector2 Vector2::DOWN = { 0, 1 };
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
|
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
|
||||||
return p_vec - *this * (dot(p_vec) - p_d);
|
return p_vec - *this * (dot(p_vec) - p_d);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue