Compare commits
699 Commits
4.0.2-stab
...
2.1.3-stab
| Author | SHA1 | Date | |
|---|---|---|---|
| d8ae244d51 | |||
| 8df5b7151f | |||
| 3b687c5474 | |||
| c449df86f7 | |||
| 45bf6d9f20 | |||
| 37d9a7bee4 | |||
| 2515ff5577 | |||
| b46d7f986d | |||
| b7e3ef5f6f | |||
| 2bc0208b2c | |||
| 20d1a28341 | |||
| a27876d5ac | |||
| a7a5ac596e | |||
| fb4e9962ea | |||
| 9b6b713d61 | |||
| c9eb0f5f45 | |||
| 86966940ff | |||
| 4b561e3e04 | |||
| f90eb87193 | |||
| c3c0cfd207 | |||
| 7f32db5ac9 | |||
| 33ea9fc4a7 | |||
| 2491754de7 | |||
| e9b045d9e5 | |||
| b55b66d74e | |||
| 63ddee793e | |||
| 6f489fbb2e | |||
| 64d8eeb4a1 | |||
| 6d722f2622 | |||
| 593149b1a0 | |||
| 990e8e00c7 | |||
| 1b15c53479 | |||
| 4087e61900 | |||
| 2ee9e033ec | |||
| f7c3ecb38c | |||
| 9f8f8efa67 | |||
| 3916d964de | |||
| 6ff1436fde | |||
| 0501f3a901 | |||
| dad8e04139 | |||
| ed80f4563a | |||
| f71da5c8c5 | |||
| 212fca0c50 | |||
| 9a9bd12913 | |||
| 323041a476 | |||
| a67400aee7 | |||
| 1620f46f03 | |||
| 1a1e25bfca | |||
| 89b201b466 | |||
| e5d63aaece | |||
| 1c17e5b38d | |||
| e10e732bf0 | |||
| 6222821535 | |||
| d047e67977 | |||
| 7d642e218e | |||
| 73f53a7918 | |||
| 12749dd67a | |||
| ddd01332ef | |||
| d0b0a3241f | |||
| 5889169bbd | |||
| 603f83ba91 | |||
| 33f9873b70 | |||
| 6438823037 | |||
| 6392381c16 | |||
| fd5215bffb | |||
| 2798a85ba7 | |||
| ca96d7940e | |||
| d90809151f | |||
| 1307ff7eb1 | |||
| facacb886c | |||
| 5d8d51719a | |||
| 95f747ec93 | |||
| 225b1d2d76 | |||
| 391f6c5536 | |||
| bba31fbad7 | |||
| e3d6d863af | |||
| b3d1113ae3 | |||
| 93107f4245 | |||
| 3bdb29b077 | |||
| 62d8f96720 | |||
| d3e6f58c25 | |||
| 8c06da0d49 | |||
| 31107daa1a | |||
| 5d691350c4 | |||
| ed3134088b | |||
| f263274a25 | |||
| 0c650c2511 | |||
| 0afb9b579f | |||
| 8f5b15754c | |||
| a9d63bcf6f | |||
| 2c95976ef7 | |||
| 492f6e06c0 | |||
| 15b6eadba7 | |||
| d2e8a21cb1 | |||
| adf36faee8 | |||
| a531051a61 | |||
| fd17d301d0 | |||
| aaf4e3ab9f | |||
| 2c2c48ffb3 | |||
| 15ecdb5f00 | |||
| 994df5df5c | |||
| 7dbccc9a57 | |||
| cab9ad7657 | |||
| 9f41c0a356 | |||
| 86de0bd081 | |||
| d9525082fe | |||
| 0b9684a085 | |||
| 43d992fc34 | |||
| 90a747a52d | |||
| 603105df18 | |||
| aeffe74a27 | |||
| ccf37c4ca2 | |||
| 4b7d1d8c15 | |||
| e1d18e6481 | |||
| cc6810c030 | |||
| a14ad02d15 | |||
| 48da11372e | |||
| 9c75b9dddf | |||
| 98ba3db502 | |||
| ea987256f6 | |||
| 51c5a12f43 | |||
| 3251e93cee | |||
| 4230b22558 | |||
| f4f0a6c609 | |||
| 2f1a0448a7 | |||
| c5c546fb7f | |||
| f2f2369db8 | |||
| 3c16e7842f | |||
| 82ad45024f | |||
| e3e86567ba | |||
| 10119f7b04 | |||
| a9d8da91b7 | |||
| cf7ba8e390 | |||
| 94653f0e88 | |||
| f8db8a3faa | |||
| 1d418afe86 | |||
| d4e0be7632 | |||
| 2664549916 | |||
| 1b0e2b0c39 | |||
| 9d2c0f6c6e | |||
| 19f90b59d5 | |||
| 6e5246e312 | |||
| 16b78da941 | |||
| 2d479aa0c6 | |||
| dbf0137576 | |||
| 75bf6a9978 | |||
| 4bfecab813 | |||
| 9992509b0d | |||
| 9b26e9c9ac | |||
| 5ac097a035 | |||
| cb2cdce6b8 | |||
| db6d9cdc22 | |||
| 96e0fd5570 | |||
| ecb4d41d20 | |||
| 7bf7fe854f | |||
| 77cb8f058d | |||
| dffdf28349 | |||
| 02d711eb61 | |||
| 4cf49bb6f4 | |||
| 674a090e59 | |||
| 38e86c8c24 | |||
| 616850b3c0 | |||
| 12a1b517ca | |||
| 919c1d627f | |||
| fb2173174d | |||
| c67b08300a | |||
| 9f536e3962 | |||
| ca2277f3f1 | |||
| 31260bb720 | |||
| 97fef612fb | |||
| c01c5fce59 | |||
| 6fb2abc7d8 | |||
| 5e90183ba4 | |||
| 3f8ce209b7 | |||
| 8015ab0db3 | |||
| ca3881ccb8 | |||
| b9451ce58d | |||
| 507bb0e1cb | |||
| ab7faa1281 | |||
| 1eb9925f58 | |||
| 98f01f9143 | |||
| e5f0183b0a | |||
| 618ac3842e | |||
| 5cc184d732 | |||
| b5be9d6115 | |||
| 58455f03f7 | |||
| 7b27cc91b1 | |||
| 148566b31b | |||
| 6289997724 | |||
| 8ea4413a2c | |||
| c185fe1095 | |||
| ce09a094ab | |||
| 3c566fc552 | |||
| e869a8a279 | |||
| 91cf3c1321 | |||
| 204a7481e0 | |||
| 3be30efe8e | |||
| 8436a34305 | |||
| 6aef1c48c4 | |||
| 50c6a6d9b1 | |||
| 9518401100 | |||
| d34c530a7f | |||
| 1e79f80b90 | |||
| 95a5d9e617 | |||
| cc265d5506 | |||
| bfa3d70169 | |||
| 0f5b85f85a | |||
| eeca4a3aa3 | |||
| 886f150b4a | |||
| e0170625ef | |||
| bc56fa8d91 | |||
| e5a458d8d0 | |||
| c58c490d45 | |||
| 9cf5058610 | |||
| 25aedb896a | |||
| c8edf071da | |||
| 5b556cab25 | |||
| 4a8d2b676e | |||
| e46e12906a | |||
| 43574f65da | |||
| b6721caa13 | |||
| d79f44da62 | |||
| ee9f31a5cc | |||
| e9e5affda1 | |||
| 7e90b98db2 | |||
| f67881bada | |||
| 6490e9ae5b | |||
| 902288cc8c | |||
| 02a3d08d93 | |||
| 3d817ac73a | |||
| 71a5b0885b | |||
| 5b8d5766f4 | |||
| bbbc3a91c9 | |||
| f7ef78c998 | |||
| d5c2a6b76b | |||
| a7ec7dcd12 | |||
| ebb7d2cdb7 | |||
| 6abe141579 | |||
| f50b4f5cb2 | |||
| eff8fc4dfb | |||
| 11b95cda45 | |||
| 331ff9db77 | |||
| 3b09d77208 | |||
| 4e9f88b649 | |||
| c0f7b80b89 | |||
| 7496b2f862 | |||
| 9e3f063e99 | |||
| 7ebb356a31 | |||
| e0f00a549c | |||
| 9fa3713d76 | |||
| be0350704f | |||
| 1f08d17a98 | |||
| 85793ccc4a | |||
| 0dbfb864ad | |||
| 58a700e43e | |||
| 0c1c34ef22 | |||
| f3bc5d443c | |||
| 34b6caa433 | |||
| 6a01cf96b2 | |||
| 1d0997b01e | |||
| bd71020354 | |||
| 6b1d33ec71 | |||
| 4a73e74ccb | |||
| 43a2599801 | |||
| 936f2e3b4e | |||
| b6468db118 | |||
| e9316a009e | |||
| f3b32746de | |||
| cdb0be8eed | |||
| ad899a0dd9 | |||
| 888f8b31e7 | |||
| 67a0da34a2 | |||
| 5b2c31a18a | |||
| 9038a96e49 | |||
| e4efab04bb | |||
| 2ac89f6540 | |||
| 8f11304dfc | |||
| 6549733aa7 | |||
| fec41c528c | |||
| c508b5b2e1 | |||
| b65e553440 | |||
| 7c47769aa2 | |||
| 6a62831195 | |||
| 0669c9816e | |||
| 23789f49dd | |||
| 8e380677cb | |||
| e4bbc1067a | |||
| 5aac8eeb0f | |||
| b351d4cbc1 | |||
| 1f2293d5cc | |||
| 8322c1aa64 | |||
| 8fca6870c4 | |||
| 9f3c594f9e | |||
| b3d0596c4b | |||
| 6b5a852bd8 | |||
| 25a62a3e32 | |||
| b61d7e6261 | |||
| 9c8ecb45f8 | |||
| 8a5596322d | |||
| 93a83c81f0 | |||
| af7fd899f4 | |||
| d66740175e | |||
| 5672852351 | |||
| 349e62835b | |||
| ff490e42da | |||
| b1fc41a301 | |||
| 3cd976366e | |||
| 6e9584e0c5 | |||
| c24c2ca17b | |||
| d2240404e3 | |||
| 01b8beb023 | |||
| 4f35fdd1e3 | |||
| 0b6d4e92b5 | |||
| d8223ffa75 | |||
| b5bdc60f58 | |||
| ba50bb9cb1 | |||
| 2a60bf1cd9 | |||
| 1bb1b6986c | |||
| 4c9c43735a | |||
| 6940830627 | |||
| 27a801df99 | |||
| f520e7788e | |||
| 580031e6f5 | |||
| d5e4011bc3 | |||
| 1397019424 | |||
| eea6c43676 | |||
| 3a4c412153 | |||
| 9b0be3753b | |||
| 5698571235 | |||
| 0701e7c2d8 | |||
| 2fbae72d14 | |||
| dbeb1ca114 | |||
| 0aebdb346a | |||
| 71b35c527f | |||
| a282579f5c | |||
| f08aa02688 | |||
| a8bc2f64ad | |||
| 85585c7fc5 | |||
| c5bff5073e | |||
| f10a78e5c0 | |||
| 5354d7ddcc | |||
| ff3891f88e | |||
| 5bfd0bbe5e | |||
| fa816730c0 | |||
| 01f3399ed0 | |||
| 1e34e8d5e1 | |||
| f184455187 | |||
| c07fe5e8de | |||
| 5b27f05e7e | |||
| 2e74bdab35 | |||
| 916e79a5bf | |||
| f95694ee86 | |||
| 6227e8f343 | |||
| 608e3f3097 | |||
| ef009a8b91 | |||
| 1a41d3351a | |||
| 17399de0e1 | |||
| fe81402257 | |||
| b56c00cc56 | |||
| 13cdc2a6f5 | |||
| fd5e01d1cd | |||
| b328d2eb00 | |||
| fde651ebf8 | |||
| 39ce4a49fa | |||
| 6ad84850ab | |||
| c0743f898a | |||
| 8589a1b117 | |||
| 40de567297 | |||
| 1e646e2797 | |||
| 4a7d5f7b0e | |||
| a86dae5761 | |||
| 7a77fd1cd5 | |||
| ac9f0aea1a | |||
| 3bb1709fd7 | |||
| 00fdcf3cd0 | |||
| 7ef71b9013 | |||
| e8a6cbc897 | |||
| 47ae6c6507 | |||
| 5e79ac72b7 | |||
| a46a643f90 | |||
| c030e602e5 | |||
| 19b31297ec | |||
| 4635671de5 | |||
| 8f23be8752 | |||
| 490f51a202 | |||
| 1a7f14b206 | |||
| e1dfaaf786 | |||
| 3f6fe2f3f1 | |||
| 2fff8e8cde | |||
| 754e9aa60a | |||
| a2048efd72 | |||
| 70a6791150 | |||
| 6e0de0cce8 | |||
| 04def2161e | |||
| b3443fd848 | |||
| 5546929712 | |||
| d8b0070b8c | |||
| 904285f4b4 | |||
| 53fea7f196 | |||
| fd1022fd29 | |||
| 24a440a34f | |||
| 5ede1a1226 | |||
| 17422f1f86 | |||
| 49e22aa83f | |||
| 6d86a63648 | |||
| a3582fa3cb | |||
| 326978dcce | |||
| 76233a3022 | |||
| ed2c369785 | |||
| 220bcbf7c0 | |||
| 3e2247ca53 | |||
| bf3cf5505e | |||
| bcc887bbe5 | |||
| 9b32df9cab | |||
| 601f056b6f | |||
| 14b46c4263 | |||
| 8a813e2a1e | |||
| 679e9f413c | |||
| 19ce11b908 | |||
| 28944e95e7 | |||
| 2d6dabc68e | |||
| 9219ac7e44 | |||
| e3dc319f78 | |||
| 221346521c | |||
| f1c2d70f1a | |||
| 3e127ce3fd | |||
| 0413d85add | |||
| 7d09222b37 | |||
| dd8b87f58e | |||
| 36a4c54593 | |||
| 51fe9fc132 | |||
| 9e1e5daddf | |||
| bc8dabf3d2 | |||
| fada9d7a8e | |||
| 82b458f160 | |||
| 64f38490df | |||
| c282ac8ec7 | |||
| 210618c5e2 | |||
| 2b00fdc679 | |||
| d7ec768805 | |||
| 86c6aabf27 | |||
| e5f210693c | |||
| 7e3360ae01 | |||
| 67f65f6639 | |||
| dbca4ee3fe | |||
| cd828bd5fc | |||
| da4a870bc4 | |||
| ce54b6ea8b | |||
| 5ee9a9962f | |||
| f629b1fd3e | |||
| eaf803f71e | |||
| a7389217f8 | |||
| e259bf8bbb | |||
| 561c1f17a1 | |||
| 7c92b401f1 | |||
| d44e6ea268 | |||
| 1185da656f | |||
| c78aef5812 | |||
| 91af714d39 | |||
| 5033fc92f4 | |||
| 1038c1f856 | |||
| 8087be05c7 | |||
| a20da0c048 | |||
| d67bbd183e | |||
| 647b287a1e | |||
| 91df1ebff6 | |||
| 62d1e39113 | |||
| b492dd78bd | |||
| a27aee241c | |||
| e3be51f87c | |||
| 68b6b50d28 | |||
| 06c47e6f8a | |||
| e56961f58b | |||
| b0013f32bf | |||
| 58daf901f9 | |||
| 887b1de1db | |||
| caf42f77d2 | |||
| 9f9d1eed7b | |||
| 0af331d1c0 | |||
| 7a17d72e84 | |||
| 52bf8bd168 | |||
| f3b42e049d | |||
| a130520a7c | |||
| 85a7105345 | |||
| dcd4b80c13 | |||
| 5a49e45d21 | |||
| 7143401e25 | |||
| f4414e3e03 | |||
| aa1367595e | |||
| d96842b80e | |||
| 8bf3bc3449 | |||
| f1bd2f6f56 | |||
| e04ec9565b | |||
| 8263fca121 | |||
| 1022705707 | |||
| 4ff4177acc | |||
| c8a97c3678 | |||
| 82e8721715 | |||
| bfea3f1d9a | |||
| 4cd640f684 | |||
| 995dcb610c | |||
| 55414bc573 | |||
| 819ccdd340 | |||
| ea1e180e4a | |||
| 575e986bde | |||
| 846db09038 | |||
| fae2863a5e | |||
| 56b03e7208 | |||
| c9d7f77c6f | |||
| 14e45a55d4 | |||
| 7d25d20861 | |||
| e88a540b91 | |||
| 2287bac8f7 | |||
| 00b0f3dfde | |||
| 64b083b496 | |||
| 9b71cae50f | |||
| 8a8ace8fa0 | |||
| 2261c65f19 | |||
| a418304def | |||
| ea48675ffa | |||
| d5ee98bb2c | |||
| 728ac94313 | |||
| a8502ae6f6 | |||
| 04255541a0 | |||
| 17edff2f84 | |||
| b4edaa892d | |||
| 81bc271619 | |||
| 5f540a17cc | |||
| 4b6809a2b3 | |||
| 280728c0c7 | |||
| 35cdb1a49b | |||
| 3df8f79c9f | |||
| 99d82f3033 | |||
| f250c0cf50 | |||
| 55a5631986 | |||
| 8cb09bf9d0 | |||
| 58e2652f94 | |||
| 3f941faf4d | |||
| b3bf3c392a | |||
| c757787fed | |||
| 1ae1deabfa | |||
| 22680a30f1 | |||
| ce1138cb02 | |||
| a139c7afe6 | |||
| e51cd3d454 | |||
| a7d6894a9f | |||
| 6775cce469 | |||
| 9e20b39b3d | |||
| 0462bf01a2 | |||
| cf427eeb7a | |||
| cd03f8cce2 | |||
| d0ff75c91c | |||
| 82dfaf7af6 | |||
| c0ba08b8d5 | |||
| ba095b8dcc | |||
| 9593863a92 | |||
| 97ebfddaaf | |||
| 342b1408d5 | |||
| 359b5f3b25 | |||
| 5b942f056a | |||
| 44ba542de6 | |||
| f63b338e0f | |||
| 13108317ae | |||
| 12d4d65668 | |||
| 56dc7aa568 | |||
| f315d352ec | |||
| ef0bcc7e20 | |||
| b2a58da321 | |||
| de13e52b9b | |||
| 73e7ccabf5 | |||
| 721599c797 | |||
| ab231cd3fb | |||
| 268b3446c6 | |||
| d7925ca09d | |||
| d613952300 | |||
| a3c58999e2 | |||
| 4b2243f82e | |||
| 6fc894d652 | |||
| 5adb75c2e7 | |||
| a827734e03 | |||
| f4f5855168 | |||
| f4da1e9ed2 | |||
| a5fe7ffbcd | |||
| 02487a4be1 | |||
| 228ee4363e | |||
| 36b1521cdc | |||
| d1ad94acf0 | |||
| 63b5a80088 | |||
| 45a5769162 | |||
| b9399e93ad | |||
| 33223e7a8a | |||
| 12edde80f2 | |||
| c8299249e4 | |||
| 1d175be921 | |||
| 94e5c48004 | |||
| 4084ec4869 | |||
| d3b549f2a3 | |||
| 4ca83c635f | |||
| e788ffff65 | |||
| 6a0d47f34c | |||
| e6d49fb54c | |||
| eed5d878e8 | |||
| 521b5bd90f | |||
| 8dca3f3f42 | |||
| d2aa006ddb | |||
| ec32c33799 | |||
| 9b9870ed9f | |||
| a72945f4e3 | |||
| 3ff8dea5f9 | |||
| 2b43d0a028 | |||
| ee23649813 | |||
| 75f51aece9 | |||
| 5653ac41f9 | |||
| 6c22cab856 | |||
| 71dc733ad2 | |||
| 04ade4d639 | |||
| 20c3b35dd5 | |||
| 323dec7dd5 | |||
| 3b691907e9 | |||
| 85eca7bc93 | |||
| 2e6ce4b362 | |||
| a1df4f138c | |||
| 0aad82e921 | |||
| aae720e488 | |||
| 772a590261 | |||
| f90370886f | |||
| c44757c2b7 | |||
| ffe5ecd67d | |||
| e0ddef3164 | |||
| 7178399548 | |||
| c007d31e52 | |||
| 3f30a22cb0 | |||
| d6dc8f4644 | |||
| c4f79716d3 | |||
| 4a9461fded | |||
| 49dd7b38bc | |||
| bfcfb58efc | |||
| ed96689d8c | |||
| 125a9f0b06 | |||
| fd58f8dce8 | |||
| adcf45b627 | |||
| 48d1e8bd4e | |||
| 73b40d1457 | |||
| e7772e43d3 | |||
| de5f49aac5 | |||
| 2ab7e6daab | |||
| 68c7da5a35 | |||
| a3a065b458 | |||
| 9ea76ff46d | |||
| cd6afd5f1d | |||
| 265715f5b2 | |||
| cd8beea3bf | |||
| 0657d43960 | |||
| a21b9caa2a | |||
| 83864514f9 | |||
| b1ea299edf | |||
| 103b04e529 | |||
| 07caf4438d | |||
| 6df46803a7 | |||
| cccc35e427 | |||
| fa1f5e55de | |||
| 6a563949c7 | |||
| f9aeb91850 | |||
| 71a9efe604 | |||
| 5f9e6d2b48 | |||
| 6327fc47c8 | |||
| 3cbd6b8701 | |||
| 4890db7fef | |||
| df3d2b25d8 | |||
| 743c63670e | |||
| e26acc39da | |||
| 1a53c4d3c2 | |||
| 37fc61f986 | |||
| 16fc229e5d | |||
| 4f07998552 | |||
| 3b7ab73cab | |||
| bbb543735c | |||
| ed931d3b59 | |||
| 720305d98e | |||
| 676b60a8b5 | |||
| 0c76ba32cc | |||
| c5e2c83dcd | |||
| 9cc700a0ab | |||
| 569966f3bb | |||
| 58556f5f95 | |||
| 229b172977 | |||
| c56ea7cf91 | |||
| 1913e4a040 | |||
| 2b35ba4815 | |||
| d853eb2fb7 | |||
| 36eeedb357 | |||
| 5f18c5cb46 | |||
| f25e9a08e1 | |||
| 4f8f9a4dbf | |||
| dd97502788 | |||
| d55304c56f | |||
| 03a4b8cbc8 | |||
| 2f0df52fe7 | |||
| fd6f62fd9a |
159
.clang-format
159
.clang-format
@ -1,88 +1,57 @@
|
||||
# Commented out parameters are those with the same value as base LLVM style.
|
||||
# We can uncomment them if we want to change their value, or enforce the
|
||||
# chosen value in case the base style changes (last sync: Clang 14.0).
|
||||
---
|
||||
### General config, applies to all languages ###
|
||||
BasedOnStyle: LLVM
|
||||
# Commented out parameters are those with the same value as base LLVM style
|
||||
# We can uncomment them if we want to change their value, or enforce the
|
||||
# chosen value in case the base style changes (initial sync: Clang 3.9.1).
|
||||
...
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
# AlignArrayOfStructures: None
|
||||
# AlignConsecutiveMacros: None
|
||||
# AlignConsecutiveAssignments: None
|
||||
# AlignConsecutiveBitFields: None
|
||||
# AlignConsecutiveDeclarations: None
|
||||
# AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
# AlignConsecutiveAssignments: false
|
||||
# AlignConsecutiveDeclarations: false
|
||||
# AlignEscapedNewlinesLeft: false
|
||||
# AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
# AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
# AllowShortEnumsOnASingleLine: true
|
||||
# AllowShortBlocksOnASingleLine: Never
|
||||
# AllowShortCaseLabelsOnASingleLine: false
|
||||
# AllowShortFunctionsOnASingleLine: All
|
||||
# AllowShortLambdasOnASingleLine: All
|
||||
# AllowShortIfStatementsOnASingleLine: Never
|
||||
# AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
# AllowShortLoopsOnASingleLine: false
|
||||
# AlwaysBreakAfterDefinitionReturnType: None
|
||||
# AlwaysBreakAfterReturnType: None
|
||||
# AlwaysBreakBeforeMultilineStrings: false
|
||||
# AlwaysBreakTemplateDeclarations: MultiLine
|
||||
# AttributeMacros:
|
||||
# - __capability
|
||||
# AlwaysBreakTemplateDeclarations: false
|
||||
# BinPackArguments: true
|
||||
# BinPackParameters: true
|
||||
# BraceWrapping:
|
||||
# AfterCaseLabel: false
|
||||
# AfterClass: false
|
||||
# AfterControlStatement: Never
|
||||
# AfterControlStatement: false
|
||||
# AfterEnum: false
|
||||
# AfterFunction: false
|
||||
# AfterNamespace: false
|
||||
# AfterObjCDeclaration: false
|
||||
# AfterStruct: false
|
||||
# AfterUnion: false
|
||||
# AfterExternBlock: false
|
||||
# BeforeCatch: false
|
||||
# BeforeElse: false
|
||||
# BeforeLambdaBody: false
|
||||
# BeforeWhile: false
|
||||
# IndentBraces: false
|
||||
# SplitEmptyFunction: true
|
||||
# SplitEmptyRecord: true
|
||||
# SplitEmptyNamespace: true
|
||||
# BreakBeforeBinaryOperators: None
|
||||
# BreakBeforeConceptDeclarations: true
|
||||
# BreakBeforeBraces: Attach
|
||||
# BreakBeforeInheritanceComma: false
|
||||
# BreakInheritanceList: BeforeColon
|
||||
# BreakBeforeTernaryOperators: true
|
||||
BreakBeforeTernaryOperators: false
|
||||
# BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: AfterColon
|
||||
# BreakAfterJavaFieldAnnotations: false
|
||||
# BreakStringLiterals: true
|
||||
ColumnLimit: 0
|
||||
# CommentPragmas: '^ IWYU pragma:'
|
||||
# QualifierAlignment: Leave
|
||||
# CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
# ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
# ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
# DeriveLineEnding: true
|
||||
# DerivePointerAlignment: false
|
||||
# DisableFormat: false
|
||||
# EmptyLineAfterAccessModifier: Never
|
||||
# EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
# ExperimentalAutoDetectBinPacking: false
|
||||
# PackConstructorInitializers: BinPack
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
# AllowAllConstructorInitializersOnNextLine: true
|
||||
# FixNamespaceComments: true
|
||||
# ForEachMacros:
|
||||
# - foreach
|
||||
# - Q_FOREACH
|
||||
# - BOOST_FOREACH
|
||||
# IfMacros:
|
||||
# - KJ_IF_MAYBE
|
||||
# IncludeBlocks: Preserve
|
||||
# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeCategories:
|
||||
- Regex: '".*"'
|
||||
Priority: 1
|
||||
@ -90,110 +59,40 @@ IncludeCategories:
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
# IncludeIsMainSourceRegex: ''
|
||||
# IndentAccessModifiers: false
|
||||
# IncludeIsMainRegex: '$'
|
||||
IndentCaseLabels: true
|
||||
# IndentCaseBlocks: false
|
||||
# IndentGotoLabels: true
|
||||
# IndentPPDirectives: None
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentRequires: false
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# InsertTrailingCommas: None
|
||||
# JavaScriptQuotes: Leave
|
||||
# JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
# LambdaBodyIndentation: Signature
|
||||
# KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
# MacroBlockBegin: ''
|
||||
# MacroBlockEnd: ''
|
||||
# MaxEmptyLinesToKeep: 1
|
||||
# NamespaceIndentation: None
|
||||
# PenaltyBreakAssignment: 2
|
||||
ObjCBlockIndentWidth: 4
|
||||
# ObjCSpaceAfterProperty: false
|
||||
# ObjCSpaceBeforeProtocolList: true
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakOpenParenthesis: 0
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyBreakTemplateDeclaration: 10
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PenaltyIndentedWhitespace: 0
|
||||
# PointerAlignment: Right
|
||||
# PPIndentWidth: -1
|
||||
# ReferenceAlignment: Pointer
|
||||
PointerAlignment: Right
|
||||
# ReflowComments: true
|
||||
# RemoveBracesLLVM: false
|
||||
# SeparateDefinitionBlocks: Leave
|
||||
# ShortNamespaceLines: 1
|
||||
# SortIncludes: CaseSensitive
|
||||
# SortJavaStaticImport: Before
|
||||
# SortUsingDeclarations: true
|
||||
SortIncludes: true
|
||||
# SpaceAfterCStyleCast: false
|
||||
# SpaceAfterLogicalNot: false
|
||||
# SpaceAfterTemplateKeyword: true
|
||||
# SpaceBeforeAssignmentOperators: true
|
||||
# SpaceBeforeCaseColon: false
|
||||
# SpaceBeforeCpp11BracedList: false
|
||||
# SpaceBeforeCtorInitializerColon: true
|
||||
# SpaceBeforeInheritanceColon: true
|
||||
# SpaceBeforeParens: ControlStatements
|
||||
# SpaceBeforeParensOptions:
|
||||
# AfterControlStatements: true
|
||||
# AfterForeachMacros: true
|
||||
# AfterFunctionDefinitionName: false
|
||||
# AfterFunctionDeclarationName: false
|
||||
# AfterIfMacros: true
|
||||
# AfterOverloadedOperator: false
|
||||
# BeforeNonEmptyParentheses: false
|
||||
# SpaceAroundPointerQualifiers: Default
|
||||
# SpaceBeforeRangeBasedForLoopColon: true
|
||||
# SpaceInEmptyBlock: false
|
||||
# SpaceInEmptyParentheses: false
|
||||
# SpacesBeforeTrailingComments: 1
|
||||
# SpacesInAngles: Never
|
||||
# SpacesInConditionalStatement: false
|
||||
# SpacesInAngles: false
|
||||
# SpacesInContainerLiterals: true
|
||||
# SpacesInCStyleCastParentheses: false
|
||||
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
|
||||
## our comment capitalization at the same time.
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 0
|
||||
Maximum: -1
|
||||
# SpacesInParentheses: false
|
||||
# SpacesInSquareBrackets: false
|
||||
# SpaceBeforeSquareBrackets: false
|
||||
# BitFieldColonSpacing: Both
|
||||
# StatementAttributeLikeMacros:
|
||||
# - Q_EMIT
|
||||
# StatementMacros:
|
||||
# - Q_UNUSED
|
||||
# - QT_REQUIRE_VERSION
|
||||
Standard: Cpp03
|
||||
TabWidth: 4
|
||||
# UseCRLF: false
|
||||
UseTab: Always
|
||||
# WhitespaceSensitiveMacros:
|
||||
# - STRINGIZE
|
||||
# - PP_STRINGIZE
|
||||
# - BOOST_PP_STRINGIZE
|
||||
# - NS_SWIFT_NAME
|
||||
# - CF_SWIFT_NAME
|
||||
---
|
||||
### C++ specific config ###
|
||||
Language: Cpp
|
||||
Standard: c++17
|
||||
---
|
||||
### ObjC specific config ###
|
||||
Language: ObjC
|
||||
# ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
# ObjCBreakBeforeNestedBlockParam: true
|
||||
# ObjCSpaceAfterProperty: false
|
||||
# ObjCSpaceBeforeProtocolList: true
|
||||
---
|
||||
### Java specific config ###
|
||||
Language: Java
|
||||
# BreakAfterJavaFieldAnnotations: false
|
||||
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
|
||||
...
|
||||
|
||||
47
.clang-tidy
47
.clang-tidy
@ -1,47 +0,0 @@
|
||||
---
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,cppcoreguidelines-pro-type-member-init,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-use-default-member-init,modernize-use-nullptr,readability-braces-around-statements,readability-redundant-member-init'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
AnalyzeTemporaryDtors: false
|
||||
FormatStyle: none
|
||||
CheckOptions:
|
||||
- key: cert-dcl16-c.NewSuffixes
|
||||
value: 'L;LL;LU;LLU'
|
||||
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
|
||||
value: '0'
|
||||
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-pro-type-member-init.UseAssignment
|
||||
value: '1'
|
||||
- key: google-readability-function-size.StatementThreshold
|
||||
value: '800'
|
||||
- key: google-readability-namespace-comments.ShortNamespaceLines
|
||||
value: '10'
|
||||
- key: google-readability-namespace-comments.SpacesBeforeComments
|
||||
value: '2'
|
||||
- key: modernize-loop-convert.MaxCopySize
|
||||
value: '16'
|
||||
- key: modernize-loop-convert.MinConfidence
|
||||
value: reasonable
|
||||
- key: modernize-loop-convert.NamingStyle
|
||||
value: CamelCase
|
||||
- key: modernize-pass-by-value.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-use-bool-literals.IgnoreMacros
|
||||
value: '0'
|
||||
- key: modernize-use-default-member-init.IgnoreMacros
|
||||
value: '0'
|
||||
- key: modernize-use-default-member-init.UseAssignment
|
||||
value: '1'
|
||||
- key: modernize-use-nullptr.NullMacros
|
||||
value: 'NULL'
|
||||
- key: readability-braces-around-statements.ShortStatementLines
|
||||
value: '0'
|
||||
...
|
||||
|
||||
@ -4,30 +4,7 @@ root = true
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = tab
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{cpp,hpp,c,h,mm}]
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.gradle,AndroidManifest.xml}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[{*.py,SConstruct,SCsub}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# YAML requires indentation with spaces instead of tabs.
|
||||
[*.{yml,yaml}]
|
||||
[.travis.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# GDScript unit test files
|
||||
[*.gd]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.out]
|
||||
insert_final_newline = true
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
# This file contains a list of Git commit hashes that should be hidden from the
|
||||
# regular Git history. Typically, this includes commits involving mass auto-formatting
|
||||
# or other normalizations. Commit hashes *must* use the full 40-character notation.
|
||||
# To apply the ignore list in your local Git client, you must run:
|
||||
#
|
||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
#
|
||||
# This file is automatically used by GitHub.com's blame view.
|
||||
|
||||
# A Whole New World (clang-format edition)
|
||||
5dbf1809c6e3e905b94b8764e99491e608122261
|
||||
|
||||
# Style: clang-format: Disable KeepEmptyLinesAtTheStartOfBlocks
|
||||
0be6d925dc3c6413bce7a3ccb49631b8e4a6e67a
|
||||
|
||||
# Style: clang-format: Disable AllowShortIfStatementsOnASingleLine
|
||||
e956e80c1fa1cc8aefcb1533e5acf5cf3c8ffdd9
|
||||
22
.gitattributes
vendored
22
.gitattributes
vendored
@ -1,20 +1,10 @@
|
||||
# Properly detect languages on Github
|
||||
*.h linguist-language=cpp
|
||||
*.inc linguist-language=cpp
|
||||
thirdparty/* linguist-vendored
|
||||
drivers/* linguist-vendored
|
||||
|
||||
# Normalize EOL for all files that Git considers text files
|
||||
* text=auto eol=lf
|
||||
# Except for bat files, which are Windows only files
|
||||
*.bat eol=crlf
|
||||
# And some test files where the EOL matters
|
||||
*.test.txt -text
|
||||
|
||||
# The above only works properly for Git 2.10+, so for older versions
|
||||
# we need to manually list the binary files we don't want modified.
|
||||
*.icns binary
|
||||
*.ico binary
|
||||
*.jar binary
|
||||
*.png binary
|
||||
*.ttf binary
|
||||
*.tza binary
|
||||
*.cpp eol=lf
|
||||
*.h eol=lf
|
||||
*.mm eol=lf
|
||||
*.py eol=lf
|
||||
*.hpp eol=lf
|
||||
|
||||
180
.github/CODEOWNERS
vendored
180
.github/CODEOWNERS
vendored
@ -1,180 +0,0 @@
|
||||
# Lines starting with '#' are comments.
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
# Owners can be @users, @org/teams or emails
|
||||
|
||||
# Buildsystem
|
||||
|
||||
.* @godotengine/buildsystem
|
||||
.github/ @godotengine/buildsystem
|
||||
*.py @godotengine/buildsystem
|
||||
SConstruct @godotengine/buildsystem
|
||||
SCsub @godotengine/buildsystem
|
||||
|
||||
# Core
|
||||
|
||||
/core/ @godotengine/core
|
||||
/core/crypto/ @godotengine/network
|
||||
/core/debugger/ @godotengine/debugger
|
||||
/core/extension/ @godotengine/gdextension
|
||||
/core/input/ @godotengine/input
|
||||
|
||||
# Doc
|
||||
|
||||
/doc/ @godotengine/documentation
|
||||
doc_classes/* @godotengine/documentation
|
||||
|
||||
# Drivers
|
||||
|
||||
## Audio
|
||||
/drivers/alsa/ @godotengine/audio
|
||||
/drivers/alsamidi/ @godotengine/audio
|
||||
/drivers/coreaudio/ @godotengine/audio
|
||||
/drivers/coremidi/ @godotengine/audio
|
||||
/drivers/pulseaudio/ @godotengine/audio
|
||||
/drivers/wasapi/ @godotengine/audio
|
||||
/drivers/winmidi/ @godotengine/audio
|
||||
/drivers/xaudio2/ @godotengine/audio
|
||||
|
||||
## Rendering
|
||||
/drivers/dummy/ @godotengine/rendering
|
||||
/drivers/gles3/ @godotengine/rendering
|
||||
/drivers/spirv-reflect/ @godotengine/rendering
|
||||
/drivers/vulkan/ @godotengine/rendering
|
||||
|
||||
## OS
|
||||
/drivers/unix/ @godotengine/_platforms
|
||||
/drivers/windows/ @godotengine/windows
|
||||
|
||||
## Misc
|
||||
/drivers/png/ @godotengine/import
|
||||
|
||||
# Editor
|
||||
|
||||
/editor/*debugger* @godotengine/debugger
|
||||
/editor/icons/ @godotengine/usability
|
||||
/editor/import/ @godotengine/import
|
||||
/editor/plugins/*2d_*.* @godotengine/2d-editor
|
||||
/editor/plugins/*3d_*.* @godotengine/3d-editor
|
||||
/editor/plugins/script_*.* @godotengine/script-editor
|
||||
/editor/plugins/*shader*.* @godotengine/shaders
|
||||
/editor/code_editor.* @godotengine/script-editor
|
||||
/editor/*dock*.* @godotengine/docks
|
||||
/editor/*shader*.* @godotengine/shaders
|
||||
|
||||
# Main
|
||||
|
||||
/main/ @godotengine/core
|
||||
|
||||
# Misc
|
||||
|
||||
/misc/ @godotengine/buildsystem
|
||||
|
||||
# Modules
|
||||
|
||||
## Audio (+ video)
|
||||
/modules/minimp3/ @godotengine/audio
|
||||
/modules/ogg/ @godotengine/audio
|
||||
/modules/opus/ @godotengine/audio
|
||||
/modules/theora/ @godotengine/audio
|
||||
/modules/vorbis/ @godotengine/audio
|
||||
/modules/webm/ @godotengine/audio
|
||||
|
||||
## Import
|
||||
/modules/basis_universal/ @godotengine/import
|
||||
/modules/bmp/ @godotengine/import
|
||||
/modules/cvtt/ @godotengine/import
|
||||
/modules/dds/ @godotengine/import
|
||||
/modules/etc/ @godotengine/import
|
||||
/modules/fbx/ @godotengine/import
|
||||
/modules/gltf/ @godotengine/import
|
||||
/modules/hdr/ @godotengine/import
|
||||
/modules/jpg/ @godotengine/import
|
||||
/modules/pvr/ @godotengine/import
|
||||
/modules/squish/ @godotengine/import
|
||||
/modules/svg/ @godotengine/import
|
||||
/modules/tga/ @godotengine/import
|
||||
/modules/tinyexr/ @godotengine/import
|
||||
/modules/webp/ @godotengine/import
|
||||
|
||||
## Network
|
||||
/modules/enet/ @godotengine/network
|
||||
/modules/mbedtls/ @godotengine/network
|
||||
/modules/upnp/ @godotengine/network
|
||||
/modules/webrtc/ @godotengine/network
|
||||
/modules/websocket/ @godotengine/network
|
||||
|
||||
## Rendering
|
||||
/modules/denoise/ @godotengine/rendering
|
||||
/modules/glslang/ @godotengine/rendering
|
||||
/modules/lightmapper_rd/ @godotengine/rendering
|
||||
/modules/meshoptimizer/ @godotengine/rendering
|
||||
/modules/vhacd/ @godotengine/rendering
|
||||
/modules/xatlas_unwrap/ @godotengine/rendering
|
||||
|
||||
## Scripting
|
||||
/modules/gdscript/ @godotengine/gdscript
|
||||
/modules/jsonrpc/ @godotengine/gdscript
|
||||
/modules/mono/ @godotengine/dotnet
|
||||
|
||||
## Text
|
||||
/modules/freetype/ @godotengine/buildsystem
|
||||
/modules/text_server_adv/ @godotengine/gui-nodes
|
||||
/modules/text_server_fb/ @godotengine/gui-nodes
|
||||
|
||||
## XR
|
||||
/modules/camera/ @godotengine/xr
|
||||
/modules/gdextension/xr/ @godotengine/xr
|
||||
/modules/mobile_vr/ @godotengine/xr
|
||||
/modules/webxr/ @godotengine/xr
|
||||
|
||||
## Misc
|
||||
/modules/bullet/ @godotengine/physics
|
||||
/modules/csg/ @godotengine/3d-nodes
|
||||
/modules/gdnavigation/ @godotengine/navigation
|
||||
/modules/gridmap/ @godotengine/3d-nodes
|
||||
/modules/opensimplex/ @godotengine/3d-nodes
|
||||
/modules/regex/ @godotengine/core
|
||||
|
||||
# Platform
|
||||
|
||||
/platform/android/ @godotengine/android
|
||||
/platform/ios/ @godotengine/ios
|
||||
/platform/javascript/ @godotengine/html5
|
||||
/platform/linuxbsd/ @godotengine/linux-bsd
|
||||
/platform/macos/ @godotengine/macos
|
||||
/platform/uwp/ @godotengine/uwp
|
||||
/platform/windows/ @godotengine/windows
|
||||
|
||||
# Scene
|
||||
|
||||
/scene/2d/ @godotengine/2d-nodes
|
||||
/scene/3d/ @godotengine/3d-nodes
|
||||
/scene/animation/ @godotengine/animation
|
||||
/scene/audio/ @godotengine/audio
|
||||
/scene/debugger/ @godotengine/debugger
|
||||
/scene/gui/ @godotengine/gui-nodes
|
||||
/scene/main/ @godotengine/core
|
||||
/scene/resources/default_theme/ @godotengine/gui-nodes
|
||||
/scene/resources/font.* @godotengine/gui-nodes
|
||||
/scene/resources/text_line.* @godotengine/gui-nodes
|
||||
/scene/resources/text_paragraph.* @godotengine/gui-nodes
|
||||
/scene/resources/visual_shader*.* @godotengine/shaders
|
||||
|
||||
# Servers
|
||||
|
||||
/servers/audio* @godotengine/audio
|
||||
/servers/camera* @godotengine/xr
|
||||
/servers/display_server.* @godotengine/_platforms
|
||||
/servers/navigation_server*.* @godotengine/navigation
|
||||
/servers/physics* @godotengine/physics
|
||||
/servers/rendering* @godotengine/rendering
|
||||
/servers/text_server.* @godotengine/gui-nodes
|
||||
/servers/xr* @godotengine/xr
|
||||
|
||||
# Tests
|
||||
|
||||
/tests/ @godotengine/tests
|
||||
|
||||
# Thirdparty
|
||||
|
||||
/thirdparty/ @godotengine/buildsystem
|
||||
59
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
59
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,59 +0,0 @@
|
||||
name: Bug report
|
||||
description: Report a bug in Godot
|
||||
body:
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
- Read our [CONTRIBUTING.md guide](https://github.com/godotengine/godot/blob/master/CONTRIBUTING.md#reporting-bugs) on reporting bugs.
|
||||
- Write a descriptive issue title above.
|
||||
- Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
|
||||
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html).
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Godot version
|
||||
description: >
|
||||
Specify the Git commit hash if using a development or non-official build.
|
||||
If you use a custom build, please test if your issue is reproducible in official builds too.
|
||||
placeholder: 3.3.stable, 4.0.dev (3041becc6)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: System information
|
||||
description: |
|
||||
Specify the OS version, and when relevant hardware information.
|
||||
For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
|
||||
placeholder: Windows 10, GLES3, Intel HD Graphics 620 (27.20.100.9616)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue description
|
||||
description: |
|
||||
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
|
||||
You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: |
|
||||
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
|
||||
If you include a minimal reproduction project below, you can detail how to use it here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Minimal reproduction project
|
||||
description: |
|
||||
A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
|
||||
Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field.
|
||||
Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.**
|
||||
validations:
|
||||
required: true
|
||||
14
.github/ISSUE_TEMPLATE/config.yml
vendored
14
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,14 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
|
||||
contact_links:
|
||||
- name: Godot proposals
|
||||
url: https://github.com/godotengine/godot-proposals
|
||||
about: Please submit feature proposals on the Godot proposals repository, not here.
|
||||
|
||||
- name: Godot documentation repository
|
||||
url: https://github.com/godotengine/godot-docs
|
||||
about: Please report issues with documentation on the Godot documentation repository, not here.
|
||||
|
||||
- name: Godot community channels
|
||||
url: https://godotengine.org/community
|
||||
about: Please ask for technical support on one of the other community channels, not here.
|
||||
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,7 +0,0 @@
|
||||
<!--
|
||||
Please target the `master` branch in priority.
|
||||
PRs can target `3.x` if the same change was done in `master`, or is not relevant there.
|
||||
|
||||
Relevant fixes are cherry-picked for stable branches as needed by maintainers.
|
||||
You can mention in the description if the change is compatible with `3.x`.
|
||||
-->
|
||||
36
.github/actions/godot-build/action.yml
vendored
36
.github/actions/godot-build/action.yml
vendored
@ -1,36 +0,0 @@
|
||||
name: Build Godot
|
||||
description: Build Godot with the provided options.
|
||||
inputs:
|
||||
target:
|
||||
description: Build target (editor, template_release, template_debug).
|
||||
default: "editor"
|
||||
tests:
|
||||
description: Unit tests.
|
||||
default: false
|
||||
platform:
|
||||
description: Target platform.
|
||||
required: false
|
||||
sconsflags:
|
||||
default: ""
|
||||
scons-cache:
|
||||
description: The scons cache path.
|
||||
default: "${{ github.workspace }}/.scons-cache/"
|
||||
scons-cache-limit:
|
||||
description: The scons cache size limit.
|
||||
# actions/cache has 10 GiB limit, and GitHub runners have a 14 GiB disk.
|
||||
# Limit to 7 GiB to avoid having the extracted cache fill the disk.
|
||||
default: 7168
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Scons Build
|
||||
shell: sh
|
||||
env:
|
||||
SCONSFLAGS: ${{ inputs.sconsflags }}
|
||||
SCONS_CACHE: ${{ inputs.scons-cache }}
|
||||
SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }}
|
||||
run: |
|
||||
echo "Building with flags:" platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }}
|
||||
if [ "${{ inputs.target }}" != "editor" ]; then rm -rf editor; fi # Ensure we don't include editor code.
|
||||
scons platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }}
|
||||
ls -l bin/
|
||||
22
.github/actions/godot-cache/action.yml
vendored
22
.github/actions/godot-cache/action.yml
vendored
@ -1,22 +0,0 @@
|
||||
name: Setup Godot build cache
|
||||
description: Setup Godot build cache.
|
||||
inputs:
|
||||
cache-name:
|
||||
description: The cache base name (job name by default).
|
||||
default: "${{github.job}}"
|
||||
scons-cache:
|
||||
description: The scons cache path.
|
||||
default: "${{github.workspace}}/.scons-cache/"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# Upload cache on completion and check it out now
|
||||
- name: Load .scons_cache directory
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{inputs.scons-cache}}
|
||||
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
restore-keys: |
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}
|
||||
27
.github/actions/godot-deps/action.yml
vendored
27
.github/actions/godot-deps/action.yml
vendored
@ -1,27 +0,0 @@
|
||||
name: Setup python and scons
|
||||
description: Setup python, install the pip version of scons.
|
||||
inputs:
|
||||
python-version:
|
||||
description: The python version to use.
|
||||
default: "3.x"
|
||||
python-arch:
|
||||
description: The python architecture.
|
||||
default: "x64"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# Use python 3.x release (works cross platform)
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
# Semantic version range syntax or exact version of a Python version
|
||||
python-version: ${{ inputs.python-version }}
|
||||
# Optional - x64 or x86 architecture, defaults to x64
|
||||
architecture: ${{ inputs.python-arch }}
|
||||
|
||||
- name: Setup scons
|
||||
shell: bash
|
||||
run: |
|
||||
python -c "import sys; print(sys.version)"
|
||||
python -m pip install scons==4.4.0
|
||||
scons --version
|
||||
19
.github/actions/upload-artifact/action.yml
vendored
19
.github/actions/upload-artifact/action.yml
vendored
@ -1,19 +0,0 @@
|
||||
name: Upload Godot artifact
|
||||
description: Upload the Godot artifact.
|
||||
inputs:
|
||||
name:
|
||||
description: The artifact name.
|
||||
default: "${{ github.job }}"
|
||||
path:
|
||||
description: The path to upload.
|
||||
required: true
|
||||
default: "bin/*"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Upload Godot Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.name }}
|
||||
path: ${{ inputs.path }}
|
||||
retention-days: 14
|
||||
59
.github/workflows/android_builds.yml
vendored
59
.github/workflows/android_builds.yml
vendored
@ -1,59 +0,0 @@
|
||||
name: 🤖 Android Builds
|
||||
on: [push, pull_request]
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Only used for the cache key. Increment version to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-android
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
android-template:
|
||||
runs-on: "ubuntu-20.04"
|
||||
name: Template (target=template_release)
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Java 11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
continue-on-error: true
|
||||
|
||||
- name: Setup python and scons
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
- name: Compilation (arm32)
|
||||
uses: ./.github/actions/godot-build
|
||||
with:
|
||||
sconsflags: ${{ env.SCONSFLAGS }} arch=arm32
|
||||
platform: android
|
||||
target: template_release
|
||||
tests: false
|
||||
|
||||
- name: Compilation (arm64)
|
||||
uses: ./.github/actions/godot-build
|
||||
with:
|
||||
sconsflags: ${{ env.SCONSFLAGS }} arch=arm64
|
||||
platform: android
|
||||
target: template_release
|
||||
tests: false
|
||||
|
||||
- name: Generate Godot templates
|
||||
run: |
|
||||
cd platform/android/java
|
||||
./gradlew generateGodotTemplates
|
||||
cd ../../..
|
||||
ls -l bin/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
38
.github/workflows/ios_builds.yml
vendored
38
.github/workflows/ios_builds.yml
vendored
@ -1,38 +0,0 @@
|
||||
name: 🍏 iOS Builds
|
||||
on: [push, pull_request]
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Only used for the cache key. Increment version to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-ios
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
ios-template:
|
||||
runs-on: "macos-latest"
|
||||
name: Template (target=template_release)
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
continue-on-error: true
|
||||
|
||||
- name: Setup python and scons
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
- name: Compilation (arm64)
|
||||
uses: ./.github/actions/godot-build
|
||||
with:
|
||||
sconsflags: ${{ env.SCONSFLAGS }}
|
||||
platform: ios
|
||||
target: template_release
|
||||
tests: false
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
213
.github/workflows/linux_builds.yml
vendored
213
.github/workflows/linux_builds.yml
vendored
@ -1,213 +0,0 @@
|
||||
name: 🐧 Linux Builds
|
||||
on: [push, pull_request]
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Only used for the cache key. Increment version to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-linux
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: "ubuntu-20.04"
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Editor w/ Mono (target=editor)
|
||||
cache-name: linux-editor-mono
|
||||
target: editor
|
||||
tests: false # Disabled due freeze caused by mix Mono build and CI
|
||||
sconsflags: module_mono_enabled=yes
|
||||
doc-test: true
|
||||
bin: "./bin/godot.linuxbsd.editor.x86_64.mono"
|
||||
build-mono: true
|
||||
proj-conv: true
|
||||
artifact: true
|
||||
|
||||
- name: Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)
|
||||
cache-name: linux-editor-double-sanitizers
|
||||
target: editor
|
||||
tests: true
|
||||
# Debug symbols disabled as they're huge on this build and we hit the 14 GB limit for runners.
|
||||
sconsflags: dev_build=yes debug_symbols=no precision=double use_asan=yes use_ubsan=yes linker=gold
|
||||
proj-test: true
|
||||
# Can be turned off for PRs that intentionally break compat with godot-cpp,
|
||||
# until both the upstream PR and the matching godot-cpp changes are merged.
|
||||
godot-cpp-test: true
|
||||
bin: "./bin/godot.linuxbsd.editor.dev.double.x86_64.san"
|
||||
build-mono: false
|
||||
# Skip 2GiB artifact speeding up action.
|
||||
artifact: false
|
||||
|
||||
- name: Editor with clang sanitizers (target=editor, tests=yes, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)
|
||||
cache-name: linux-editor-llvm-sanitizers
|
||||
target: editor
|
||||
tests: true
|
||||
sconsflags: dev_build=yes use_asan=yes use_ubsan=yes use_llvm=yes linker=lld
|
||||
bin: "./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san"
|
||||
build-mono: false
|
||||
# Skip 2GiB artifact speeding up action.
|
||||
artifact: false
|
||||
|
||||
- name: Template w/ Mono (target=template_release)
|
||||
cache-name: linux-template-mono
|
||||
target: template_release
|
||||
tests: false
|
||||
sconsflags: module_mono_enabled=yes
|
||||
build-mono: false
|
||||
artifact: true
|
||||
|
||||
- name: Minimal template (target=template_release, everything disabled)
|
||||
cache-name: linux-template-minimal
|
||||
target: template_release
|
||||
tests: false
|
||||
sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no minizip=no
|
||||
artifact: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Need newer mesa for lavapipe to work properly.
|
||||
- name: Linux dependencies for tests
|
||||
if: ${{ matrix.proj-test }}
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
|
||||
sudo add-apt-repository ppa:kisak/kisak-mesa
|
||||
sudo apt-get install -qq mesa-vulkan-drivers
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
with:
|
||||
cache-name: ${{ matrix.cache-name }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Setup python and scons
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
- name: Set up .NET Sdk
|
||||
uses: actions/setup-dotnet@v2
|
||||
if: ${{ matrix.build-mono }}
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Setup GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
- name: Compilation
|
||||
uses: ./.github/actions/godot-build
|
||||
with:
|
||||
sconsflags: ${{ env.SCONSFLAGS }} ${{ matrix.sconsflags }}
|
||||
platform: linuxbsd
|
||||
target: ${{ matrix.target }}
|
||||
tests: ${{ matrix.tests }}
|
||||
|
||||
- name: Generate C# glue
|
||||
if: ${{ matrix.build-mono }}
|
||||
run: |
|
||||
${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue || true
|
||||
|
||||
- name: Build .NET solutions
|
||||
if: ${{ matrix.build-mono }}
|
||||
run: |
|
||||
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=linuxbsd
|
||||
|
||||
# Execute unit tests for the editor
|
||||
- name: Unit tests
|
||||
if: ${{ matrix.tests }}
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
${{ matrix.bin }} --test --headless
|
||||
|
||||
# Check class reference
|
||||
- name: Check for class reference updates
|
||||
if: ${{ matrix.doc-test }}
|
||||
run: |
|
||||
echo "Running --doctool to see if this changes the public API without updating the documentation."
|
||||
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
|
||||
${{ matrix.bin }} --doctool --headless 2>&1 > /dev/null || true
|
||||
git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
|
||||
|
||||
# Test 3.x -> 4.x project converter
|
||||
- name: Test project converter
|
||||
if: ${{ matrix.proj-conv }}
|
||||
run: |
|
||||
mkdir converter_test
|
||||
cd converter_test
|
||||
touch project.godot
|
||||
../${{ matrix.bin }} --headless --validate-conversion-3to4
|
||||
cd ..
|
||||
rm converter_test -rf
|
||||
|
||||
# Download and extract zip archive with project, folder is renamed to be able to easy change used project
|
||||
- name: Download test project
|
||||
if: ${{ matrix.proj-test }}
|
||||
run: |
|
||||
wget https://github.com/godotengine/regression-test-project/archive/4.0.zip
|
||||
unzip 4.0.zip
|
||||
mv "regression-test-project-4.0" "test_project"
|
||||
|
||||
# Editor is quite complicated piece of software, so it is easy to introduce bug here
|
||||
- name: Open and close editor (Vulkan)
|
||||
if: ${{ matrix.proj-test }}
|
||||
run: |
|
||||
xvfb-run ${{ matrix.bin }} --audio-driver Dummy --editor --quit --path test_project 2>&1 | tee sanitizers_log.txt || true
|
||||
misc/scripts/check_ci_log.py sanitizers_log.txt
|
||||
|
||||
- name: Open and close editor (GLES3)
|
||||
if: ${{ matrix.proj-test }}
|
||||
run: |
|
||||
DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --rendering-driver opengl3 --editor --quit --path test_project 2>&1 | tee sanitizers_log.txt || true
|
||||
misc/scripts/check_ci_log.py sanitizers_log.txt
|
||||
|
||||
# Run test project
|
||||
- name: Run project
|
||||
if: ${{ matrix.proj-test }}
|
||||
run: |
|
||||
xvfb-run ${{ matrix.bin }} 40 --audio-driver Dummy --path test_project 2>&1 | tee sanitizers_log.txt || true
|
||||
misc/scripts/check_ci_log.py sanitizers_log.txt
|
||||
|
||||
# Checkout godot-cpp
|
||||
- name: Checkout godot-cpp
|
||||
if: ${{ matrix.godot-cpp-test }}
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: godotengine/godot-cpp
|
||||
submodules: 'recursive'
|
||||
path: 'godot-cpp'
|
||||
|
||||
# Dump GDExtension interface and API
|
||||
- name: Dump GDExtension interface and API for godot-cpp build
|
||||
if: ${{ matrix.godot-cpp-test }}
|
||||
run: |
|
||||
${{ matrix.bin }} --headless --dump-gdextension-interface --dump-extension-api
|
||||
cp -f gdextension_interface.h godot-cpp/gdextension/
|
||||
cp -f extension_api.json godot-cpp/gdextension/
|
||||
|
||||
# Build godot-cpp test extension
|
||||
- name: Build godot-cpp test extension
|
||||
if: ${{ matrix.godot-cpp-test }}
|
||||
run: |
|
||||
cd godot-cpp/test
|
||||
scons target=template_debug dev_build=yes
|
||||
cd ../..
|
||||
|
||||
- name: Prepare artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
run: |
|
||||
strip bin/godot.*
|
||||
chmod +x bin/godot.*
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
74
.github/workflows/macos_builds.yml
vendored
74
.github/workflows/macos_builds.yml
vendored
@ -1,74 +0,0 @@
|
||||
name: 🍎 macOS Builds
|
||||
on: [push, pull_request]
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Only used for the cache key. Increment version to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-macos
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-macos:
|
||||
runs-on: "macos-latest"
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Editor (target=editor, tests=yes)
|
||||
cache-name: macos-editor
|
||||
target: editor
|
||||
tests: true
|
||||
bin: "./bin/godot.macos.editor.x86_64"
|
||||
|
||||
- name: Template (target=template_release)
|
||||
cache-name: macos-template
|
||||
target: template_release
|
||||
tests: false
|
||||
sconsflags: debug_symbols=no
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
with:
|
||||
cache-name: ${{ matrix.cache-name }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Setup python and scons
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
- name: Setup Vulkan SDK
|
||||
run: |
|
||||
sh misc/scripts/install_vulkan_sdk_macos.sh
|
||||
|
||||
- name: Compilation
|
||||
uses: ./.github/actions/godot-build
|
||||
with:
|
||||
sconsflags: ${{ env.SCONSFLAGS }}
|
||||
platform: macos
|
||||
target: ${{ matrix.target }}
|
||||
tests: ${{ matrix.tests }}
|
||||
|
||||
# Execute unit tests for the editor
|
||||
- name: Unit tests
|
||||
if: ${{ matrix.tests }}
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
${{ matrix.bin }} --test
|
||||
|
||||
- name: Prepare artifact
|
||||
run: |
|
||||
strip bin/godot.*
|
||||
chmod +x bin/godot.*
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
75
.github/workflows/static_checks.yml
vendored
75
.github/workflows/static_checks.yml
vendored
@ -1,75 +0,0 @@
|
||||
name: 📊 Static Checks
|
||||
on: [push, pull_request]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
static-checks:
|
||||
name: Static Checks (clang-format, black format, file format, documentation checks)
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main"
|
||||
sudo apt-get install -qq dos2unix clang-format-15 libxml2-utils python3-pip moreutils
|
||||
sudo update-alternatives --remove-all clang-format || true
|
||||
sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-15 100
|
||||
sudo pip3 install black==22.3.0 pygments pytest==7.1.2 mypy==0.971
|
||||
|
||||
- name: File formatting checks (file_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/file_format.sh
|
||||
|
||||
- name: Header guards formatting checks (header_guards.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/header_guards.sh
|
||||
|
||||
- name: Python style checks via black (black_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/black_format.sh
|
||||
|
||||
- name: Python scripts static analysis (mypy_check.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/mypy_check.sh
|
||||
|
||||
- name: Python builders checks via pytest (pytest_builders.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/pytest_builders.sh
|
||||
|
||||
- name: JavaScript style and documentation checks via ESLint and JSDoc
|
||||
run: |
|
||||
cd platform/web
|
||||
npm ci
|
||||
npm run lint
|
||||
npm run docs -- -d dry-run
|
||||
|
||||
- name: Class reference schema checks
|
||||
run: |
|
||||
xmllint --noout --schema doc/class.xsd doc/classes/*.xml modules/*/doc_classes/*.xml
|
||||
|
||||
- name: Documentation checks
|
||||
run: |
|
||||
doc/tools/make_rst.py --dry-run --color doc/classes modules
|
||||
|
||||
- name: Style checks via clang-format (clang_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/clang_format.sh
|
||||
|
||||
- name: Style checks via dotnet format (dotnet_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/dotnet_format.sh
|
||||
|
||||
- name: Spell checks via codespell
|
||||
uses: codespell-project/actions-codespell@v1
|
||||
with:
|
||||
skip: ./.*,./**/.*,./bin,./thirdparty,*.desktop,*.gen.*,*.po,*.pot,*.rc,./AUTHORS.md,./COPYRIGHT.txt,./DONORS.md,./core/input/gamecontrollerdb.txt,./core/string/locales.h,./editor/project_converter_3_to_4.cpp,./misc/scripts/codespell.sh,./platform/android/java/lib/src/com,./platform/web/node_modules,./platform/web/package-lock.json
|
||||
check_hidden: false
|
||||
ignore_words_list: curvelinear,doubleclick,expct,findn,gird,hel,inout,lod,nd,numer,ot,te
|
||||
only_warn: true
|
||||
50
.github/workflows/web_builds.yml
vendored
50
.github/workflows/web_builds.yml
vendored
@ -1,50 +0,0 @@
|
||||
name: 🌐 Web Builds
|
||||
on: [push, pull_request]
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Only used for the cache key. Increment version to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no
|
||||
EM_VERSION: 3.1.18
|
||||
EM_CACHE_FOLDER: "emsdk-cache"
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-web
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
web-template:
|
||||
runs-on: "ubuntu-20.04"
|
||||
name: Template (target=template_release)
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Emscripten latest
|
||||
uses: mymindstorm/setup-emsdk@v12
|
||||
with:
|
||||
version: ${{env.EM_VERSION}}
|
||||
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
||||
|
||||
- name: Verify Emscripten setup
|
||||
run: |
|
||||
emcc -v
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
continue-on-error: true
|
||||
|
||||
- name: Setup python and scons
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
- name: Compilation
|
||||
uses: ./.github/actions/godot-build
|
||||
with:
|
||||
sconsflags: ${{ env.SCONSFLAGS }}
|
||||
platform: web
|
||||
target: template_release
|
||||
tests: false
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
77
.github/workflows/windows_builds.yml
vendored
77
.github/workflows/windows_builds.yml
vendored
@ -1,77 +0,0 @@
|
||||
name: 🏁 Windows Builds
|
||||
on: [push, pull_request]
|
||||
|
||||
# Global Settings
|
||||
# SCONS_CACHE for windows must be set in the build environment
|
||||
env:
|
||||
# Only used for the cache key. Increment version to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes
|
||||
SCONS_CACHE_MSVC_CONFIG: true
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-windows
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
# Windows 10 with latest image
|
||||
runs-on: "windows-latest"
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Editor (target=editor, tests=yes)
|
||||
cache-name: windows-editor
|
||||
target: editor
|
||||
tests: true
|
||||
# Skip debug symbols, they're way too big with MSVC.
|
||||
sconsflags: debug_symbols=no vsproj=yes
|
||||
bin: "./bin/godot.windows.editor.x86_64.exe"
|
||||
|
||||
- name: Template (target=template_release, tools=no)
|
||||
cache-name: windows-template
|
||||
target: template_release
|
||||
tests: false
|
||||
sconsflags: debug_symbols=no
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
with:
|
||||
cache-name: ${{ matrix.cache-name }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Setup python and scons
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
- name: Setup MSVC problem matcher
|
||||
uses: ammaraskar/msvc-problem-matcher@master
|
||||
|
||||
- name: Compilation
|
||||
uses: ./.github/actions/godot-build
|
||||
with:
|
||||
sconsflags: ${{ env.SCONSFLAGS }} ${{ matrix.sconsflags }}
|
||||
platform: windows
|
||||
target: ${{ matrix.target }}
|
||||
tests: ${{ matrix.tests }}
|
||||
|
||||
# Execute unit tests for the editor
|
||||
- name: Unit tests
|
||||
if: ${{ matrix.tests }}
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
${{ matrix.bin }} --test
|
||||
|
||||
- name: Prepare artifact
|
||||
run: |
|
||||
Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
480
.gitignore
vendored
480
.gitignore
vendored
@ -1,280 +1,121 @@
|
||||
# Godot .gitignore config
|
||||
#
|
||||
# Aims to encompass the most commonly found files that we don't want committed
|
||||
# to Git, such as compilation output, IDE specific files, etc.
|
||||
#
|
||||
# It doesn't cover *all* thirdparty IDE extensions under the sun so if you have
|
||||
# specific needs covered here, you can add them to:
|
||||
# .git/info/exclude
|
||||
#
|
||||
# Or contribute them to this file if they're common enough that a good number of
|
||||
# users would benefit from the shared rules.
|
||||
#
|
||||
# This file is organized by sections, with subsections ordered alphabetically.
|
||||
# - Build configuration
|
||||
# - Godot generated files
|
||||
# - General build output
|
||||
# - IDE and tool specific
|
||||
# - Visual Studio specific
|
||||
# - OS specific
|
||||
# Godot auto generated files
|
||||
core/global_defaults.cpp
|
||||
core/method_bind_ext.inc
|
||||
core/method_bind.inc
|
||||
core/script_encryption_key.cpp
|
||||
core/version_generated.h
|
||||
drivers/gles2/shaders/*.h
|
||||
drivers/unix/os_unix_global_settings_path.cpp
|
||||
editor/builtin_fonts.h
|
||||
editor/certs_compressed.h
|
||||
editor/doc_data_compressed.h
|
||||
editor/editor_icons.cpp
|
||||
editor/register_exporters.cpp
|
||||
editor/translations.h
|
||||
log.txt
|
||||
main/app_icon.h
|
||||
main/splash.h
|
||||
make.bat
|
||||
modules/register_module_types.cpp
|
||||
platform/android/logo.h
|
||||
platform/bb10/logo.h
|
||||
platform/iphone/logo.h
|
||||
platform/javascript/logo.h
|
||||
platform/osx/logo.h
|
||||
platform/server/logo.h
|
||||
platform/windows/logo.h
|
||||
platform/x11/logo.h
|
||||
|
||||
###########################
|
||||
### Build configuration ###
|
||||
###########################
|
||||
# Documentation generated by doxygen or from classes.xml
|
||||
doc/_build/
|
||||
|
||||
/custom.py
|
||||
misc/hooks/pre-commit-custom-*
|
||||
# Javascript specific
|
||||
*.bc
|
||||
|
||||
#############################
|
||||
### Godot generated files ###
|
||||
#############################
|
||||
# Android specific
|
||||
platform/android/java/build.gradle
|
||||
platform/android/java/.gradle
|
||||
platform/android/java/.gradletasknamecache
|
||||
platform/android/java/local.properties
|
||||
platform/android/java/project.properties
|
||||
platform/android/java/build.gradle
|
||||
platform/android/java/AndroidManifest.xml
|
||||
platform/android/java/libs/*
|
||||
platform/android/java/assets
|
||||
|
||||
# Buildsystem
|
||||
bin
|
||||
*.gen.*
|
||||
compile_commands.json
|
||||
platform/windows/godot_res.res
|
||||
|
||||
# Generated by Godot binary
|
||||
.import/
|
||||
/gdextension_interface.h
|
||||
extension_api.json
|
||||
logs/
|
||||
|
||||
# Generated by unit tests
|
||||
tests/data/*.translation
|
||||
|
||||
############################
|
||||
### General build output ###
|
||||
############################
|
||||
|
||||
# C/C++ generated
|
||||
# General c++ generated files
|
||||
*.lib
|
||||
*.o
|
||||
*.ox
|
||||
*.a
|
||||
*.ax
|
||||
*.d
|
||||
*.dll
|
||||
*.lib
|
||||
*.lo
|
||||
*.o
|
||||
*.os
|
||||
*.ox
|
||||
*.Plo
|
||||
*.so
|
||||
# Binutils tmp linker output of the form "stXXXXXX" where "X" is alphanumeric
|
||||
st[A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9][A-Za-z0-9]
|
||||
*.os
|
||||
*.Plo
|
||||
*.lo
|
||||
|
||||
# Python generated
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Documentation
|
||||
doc/_build/
|
||||
|
||||
# Android
|
||||
.gradle/
|
||||
local.properties
|
||||
*.iml
|
||||
.gradletasknamecache
|
||||
project.properties
|
||||
platform/android/java/*/.cxx/
|
||||
platform/android/java/*/build/
|
||||
platform/android/java/*/libs/
|
||||
|
||||
# iOS
|
||||
*.dSYM
|
||||
|
||||
# Web platform
|
||||
*.bc
|
||||
platform/web/node_modules/
|
||||
|
||||
# Misc
|
||||
*.debug
|
||||
|
||||
#############################
|
||||
### IDE and tool specific ###
|
||||
#############################
|
||||
|
||||
# Automake
|
||||
# Libs generated files
|
||||
.deps/*
|
||||
.dirstamp
|
||||
|
||||
# ccls
|
||||
.ccls-cache/
|
||||
|
||||
# clangd
|
||||
.clangd/
|
||||
.cache/
|
||||
|
||||
# CLion
|
||||
cmake-build-debug
|
||||
|
||||
# Code::Blocks
|
||||
*.cbp
|
||||
*.layout
|
||||
*.depend
|
||||
|
||||
# CodeLite
|
||||
*.project
|
||||
*.workspace
|
||||
.codelite/
|
||||
|
||||
# Cppcheck
|
||||
*.cppcheck
|
||||
cppcheck-cppcheck-build-dir/
|
||||
|
||||
# Eclipse CDT
|
||||
.cproject
|
||||
.settings/
|
||||
*.pydevproject
|
||||
*.launch
|
||||
|
||||
# Gcov and Lcov code coverage
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.gcov.html
|
||||
*.func.html
|
||||
*.func-sort-c.html
|
||||
*index-sort-f.html
|
||||
*index-sort-l.html
|
||||
*index.html
|
||||
godot.info
|
||||
amber.png
|
||||
emerald.png
|
||||
glass.png
|
||||
ruby.png
|
||||
snow.png
|
||||
updown.png
|
||||
gcov.css
|
||||
|
||||
# Geany
|
||||
*.geany
|
||||
.geanyprj
|
||||
|
||||
# Gprof
|
||||
gmon.out
|
||||
|
||||
# Jetbrains IDEs
|
||||
.idea/
|
||||
.fleet/
|
||||
|
||||
# Kate
|
||||
*.kate-swp
|
||||
|
||||
# Kdevelop
|
||||
*.kdev4
|
||||
|
||||
# Qt Creator
|
||||
*.config
|
||||
*.creator
|
||||
*.creator.*
|
||||
*.files
|
||||
*.includes
|
||||
*.cflags
|
||||
*.cxxflags
|
||||
|
||||
# SCons
|
||||
.sconf_temp
|
||||
.sconsign*.dblite
|
||||
.scons_env.json
|
||||
.scons_node_count
|
||||
|
||||
# Sourcetrail
|
||||
*.srctrl*
|
||||
|
||||
# Tags
|
||||
# https://github.com/github/gitignore/blob/master/Global/Tags.gitignore
|
||||
# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
|
||||
TAGS
|
||||
!TAGS/
|
||||
tags
|
||||
*.tags
|
||||
!tags/
|
||||
gtags.files
|
||||
GTAGS
|
||||
GRTAGS
|
||||
GPATH
|
||||
cscope.files
|
||||
cscope.out
|
||||
cscope.in.out
|
||||
cscope.po.out
|
||||
|
||||
# Vim
|
||||
# Vim temp files
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
.history/
|
||||
# QT project files
|
||||
*.config
|
||||
*.creator
|
||||
*.files
|
||||
*.includes
|
||||
|
||||
# Xcode
|
||||
xcuserdata/
|
||||
*.xcscmblueprint
|
||||
*.xccheckout
|
||||
*.xcodeproj/*
|
||||
# Misc
|
||||
.DS_Store
|
||||
|
||||
# for projects that use SCons for building: http://http://www.scons.org/
|
||||
.sconsign.dblite
|
||||
*.pyc
|
||||
|
||||
##############################
|
||||
### Visual Studio specific ###
|
||||
##############################
|
||||
|
||||
# https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
# Ignore Visual Studio temporary files, build results, and
|
||||
# files generated by popular Visual Studio add-ons.
|
||||
|
||||
# Actual VS project files we don't use
|
||||
*.sln
|
||||
*.vcxproj*
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
*.sln
|
||||
*.vcxproj*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Do not ignore arch-specific folders anywhere under thirdparty libraries
|
||||
!thirdparty/**/x64/
|
||||
!thirdparty/**/x86/
|
||||
!thirdparty/**/arm/
|
||||
!thirdparty/**/arm64/
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# Files built by Visual Studio
|
||||
*.o
|
||||
*.a
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
@ -284,9 +125,7 @@ Generated\ Files/
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
@ -294,11 +133,13 @@ Generated\ Files/
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
@ -309,68 +150,157 @@ ipch/
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
# CodeLite project files
|
||||
*.project
|
||||
*.workspace
|
||||
.codelite/
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
|
||||
# NuGet Packages Directory
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||
#packages/*
|
||||
## TODO: If the tool you use requires repositories.config, also uncomment the next line
|
||||
#!packages/repositories.config
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
|
||||
!packages/build/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
enc_temp_folder/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
node_modules/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
# KDE
|
||||
.directory
|
||||
|
||||
#Kdevelop project files
|
||||
*.kdev4
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# Hint file for IntelliSense
|
||||
cpp.hint
|
||||
# SQL Server files
|
||||
App_Data/*.mdf
|
||||
App_Data/*.ldf
|
||||
|
||||
###################
|
||||
### OS specific ###
|
||||
###################
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Linux
|
||||
*~
|
||||
.directory
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
__MACOSX
|
||||
# =========================
|
||||
# Windows detritus
|
||||
# =========================
|
||||
|
||||
# Windows
|
||||
# https://github.com/github/gitignore/blob/main/Global/Windows.gitignore
|
||||
[Tt]humbs.db
|
||||
[Tt]humbs.db:encryptable
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
*.stackdump
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
*.lnk
|
||||
logo.h
|
||||
*.autosave
|
||||
|
||||
# https://github.com/github/gitignore/blob/master/Global/Tags.gitignore
|
||||
# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
|
||||
TAGS
|
||||
!TAGS/
|
||||
tags
|
||||
!tags/
|
||||
gtags.files
|
||||
GTAGS
|
||||
GRTAGS
|
||||
GPATH
|
||||
cscope.files
|
||||
cscope.out
|
||||
cscope.in.out
|
||||
cscope.po.out
|
||||
godot.creator.*
|
||||
|
||||
projects/
|
||||
platform/windows/godot_res.res
|
||||
|
||||
# Visual Studio Code folder (and files) that are created
|
||||
# when the C/C++ extension (https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) is used
|
||||
/.vscode
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
extraction:
|
||||
cpp:
|
||||
after_prepare:
|
||||
- pip3 install scons
|
||||
- PATH="/opt/work/.local/bin:$PATH"
|
||||
index:
|
||||
build_command: scons -j2
|
||||
165
.mailmap
165
.mailmap
@ -1,165 +0,0 @@
|
||||
Aaron Record <aaronjrecord@gmail.com>
|
||||
Alexander Holland <alexander.holland@live.de>
|
||||
Alexander Holland <alexander.holland@live.de> <alexander.holland@haw-hamburg.de>
|
||||
Alexander Holland <alexander.holland@live.de> <AlexHolly>
|
||||
Alfred Reinold Baudisch <alfred@alfredbaudisch.com>
|
||||
Andrea Catania <info@andreacatania.com>
|
||||
Anish Bhobe <anishbhobe@hotmail.com>
|
||||
Anutrix <numaanzaheerahmed@yahoo.com>
|
||||
Aren Villanueva <arenvillanueva@yomogi-soft.com> <aren@displaysweet.com>
|
||||
Ariel Manzur <ariel@godotengine.org>
|
||||
Ariel Manzur <ariel@godotengine.org> <puntob@gmail.com>
|
||||
Ariel Manzur <ariel@godotengine.org> <punto@godotengine.org>
|
||||
Ariel Manzur <ariel@godotengine.org> <ariel@okamstudio.com>
|
||||
Ariel Manzur <ariel@godotengine.org> <punto@Ariels-Mac-mini.local>
|
||||
Ariel Manzur <ariel@godotengine.org> <punto@Ariels-Mac-mini-2.local>
|
||||
Bastiaan Olij <mux213@gmail.com>
|
||||
Benjamin <mafortion.benjamin@gmail.com>
|
||||
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.de>
|
||||
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.org>
|
||||
Bruno Lourenço <madequa@users.noreply.github.com> <bmlourenco@gmail.com>
|
||||
Chaosus <chaosus89@gmail.com>
|
||||
Chris Bradfield <chris@kidscancode.org> <cb@scribe.net>
|
||||
Clay John <claynjohn@gmail.com>
|
||||
Clay John <claynjohn@gmail.com> <clayjohn@shaw.ca>
|
||||
Dana Olson <dana@shineuponthee.com> <adolson@gmail.com>
|
||||
dankan1890 <mewuidev2@gmail.com>
|
||||
Daniel J. Ramirez <djrmuv@gmail.com>
|
||||
David Cambré <david.cambre@gmail.com> <David.Cambre@gmail.com>
|
||||
Dominik 'dreamsComeTrue' Jasiński <dominikjasinski@o2.pl>
|
||||
DeeJayLSP <djlsplays@gmail.com> <60024671+DeeJayLSP@users.noreply.github.com>
|
||||
Emmanuel Barroga <emmanuelbarroga@gmail.com>
|
||||
Eric M <itsjusteza@gmail.com>
|
||||
Eric Rybicki <info@ericrybicki.com> <stratos695@googlemail.com>
|
||||
Erik Selecký <35656626+rxlecky@users.noreply.github.com>
|
||||
Erik Selecký <35656626+rxlecky@users.noreply.github.com> <35656626+SeleckyErik@users.noreply.github.com>
|
||||
Eveline Jarosz <marqin.pl@gmail.com>
|
||||
Eveline Jarosz <marqin.pl@gmail.com> <marqin.pl+git@gmail.com>
|
||||
Fabian <supagu@gmail.com>
|
||||
Ferenc Arn <tagcup@yahoo.com>
|
||||
Ferenc Arn <tagcup@yahoo.com> <tagcup@users.noreply.github.com>
|
||||
FireForge <67974470+fire-forge@users.noreply.github.com> <isaacr.7.2005@gmail.com>
|
||||
foxydevloper <12120644+foxydevloper@users.noreply.github.com>
|
||||
Fredia Huya-Kouadio <fhuyakou@gmail.com>
|
||||
Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@google.com>
|
||||
Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@fb.com>
|
||||
Fredia Huya-Kouadio <fhuyakou@gmail.com> <fhuya@meta.com>
|
||||
Geequlim <geequlim@gmail.com>
|
||||
Gilles Roudiere <gilles.roudiere@gmail.com>
|
||||
Gilles Roudiere <gilles.roudiere@gmail.com> <gilles.roudiere@laas.fr>
|
||||
Gordon MacPherson <gordon@gordonite.tech>
|
||||
Guilherme Felipe <guilhermefelipecgs@gmail.com>
|
||||
Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
|
||||
HaSa1002 <johawitt@outlook.de>
|
||||
Hein-Pieter van Braam-Stewart <hp@tmm.cx>
|
||||
Hugo Locurcio <hugo.locurcio@hugo.pro> <hugo.l@openmailbox.org>
|
||||
Hugo Locurcio <hugo.locurcio@hugo.pro> <Calinou@users.noreply.github.com>
|
||||
Hugo Locurcio <hugo.locurcio@hugo.pro> Calinou <calinou@opmbx.org>
|
||||
Ian Bishop <ianb96@gmail.com>
|
||||
Ignacio Etcheverry <ignalfonsore@gmail.com>
|
||||
Ignacio Etcheverry <ignalfonsore@gmail.com> <neikeq@users.noreply.github.com>
|
||||
Ilaria Cislaghi <cislaghi.ilaria@gmail.com>
|
||||
Ilaria Cislaghi <cislaghi.ilaria@gmail.com> <ilaria.cislaghi@simedis.com>
|
||||
Indah Sylvia <ISylvox@yahoo.com>
|
||||
iwek <miwanczuk7@gmail.com>
|
||||
J08nY <johny@neuromancer.sk> <jancar.jj@gmail.com>
|
||||
J08nY <johny@neuromancer.sk> <J08nY@users.noreply.github.com>
|
||||
Jake Young <young9003@gmail.com>
|
||||
Jakub Grzesik <kubecz3k@gmail.com>
|
||||
janglee <merupatel123@gmail.com>
|
||||
Jason Knight <00jknight@gmail.com> <jason@winterpixel.com>
|
||||
Jean-Michel Bernard <jmb462@gmail.com>
|
||||
Jérôme Gully <jerome.gully0@gmail.com>
|
||||
JFonS <joan.fonssanchez@gmail.com>
|
||||
Juan Linietsky <reduzio@gmail.com>
|
||||
Juan Linietsky <reduzio@gmail.com> <juan@godotengine.org>
|
||||
Juan Linietsky <reduzio@gmail.com> <juan@okamstudio.com>
|
||||
Juan Linietsky <reduzio@gmail.com> <reduz@Juans-MBP.fibertel.com.ar>
|
||||
Juan Linietsky <reduzio@gmail.com> <red@kyoko>
|
||||
Julian Murgia <the.straton@gmail.com>
|
||||
Kanabenki <lucien.menassol@gmail.com> <18357657+Kanabenki@users.noreply.github.com>
|
||||
karroffel <therzog@mail.de>
|
||||
karroffel <therzog@mail.de> <thomas.herzog@mail.com>
|
||||
karroffel <therzog@mail.de> <thomas.herzog@simedis.com>
|
||||
Kelly Thomas <kelly.thomas@hotmail.com.au>
|
||||
Kongfa Waroros <gongpha@hotmail.com>
|
||||
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>
|
||||
kleonc <9283098+kleonc@users.noreply.github.com> <kleonc@users.noreply.github.com>
|
||||
Leon Krause <lk@leonkrause.com> <eska@eska.me>
|
||||
Leon Krause <lk@leonkrause.com> <eska014@users.noreply.github.com>
|
||||
Liz Haas <27thLiz@gmail.com>
|
||||
Liz Haas <27thLiz@gmail.com> <liu.gam3@gmail.com>
|
||||
Liz Haas <27thLiz@gmail.com> <hinsbart@gmail.com>
|
||||
Liz Haas <27thLiz@gmail.com> <hinsbart@users.noreply.github.com>
|
||||
Liz Haas <27thLiz@gmail.com> <entenflugstuhl@gmail.com>
|
||||
Manuele Finocchiaro <m4nu3lf@gmail.com>
|
||||
Manuel Strey <manuel.strey@gmx.de>
|
||||
Marcel Admiraal <madmiraal@users.noreply.github.com>
|
||||
Marcelo Fernandez <marcelofg55@gmail.com>
|
||||
Marcin Zawiejski <dragmz@gmail.com>
|
||||
Marcus Elg <marcusaccounts@yahoo.se>
|
||||
Mariano Javier Suligoy <marianognu.easyrpg@gmail.com>
|
||||
Mario Schlack <m4r10.5ch14ck@gmail.com>
|
||||
marxin <mliska@suse.cz>
|
||||
marynate <mary.w.nate@gmail.com> <marynate@github.com>
|
||||
Mateo Kuruk Miccino <mateomiccino@gmail.com>
|
||||
Max Hilbrunner <m.hilbrunner@gmail.com>
|
||||
Max Hilbrunner <m.hilbrunner@gmail.com> <mhilbrunner@users.noreply.github.com>
|
||||
Michael Alexsander <michaelalexsander@protonmail.com>
|
||||
Micky <micheledevita2@gmail.com> <66727710+Mickeon@users.noreply.github.com>
|
||||
Nathan Franke <natfra@pm.me> <nathanwfranke@gmail.com>
|
||||
Nathan Lovato <nathan@gdquest.com>
|
||||
Nathan Warden <nathan@nathanwarden.com> <nathanwardenlee@icloud.com>
|
||||
Nicholas Huelin <62965063+SirQuartz@users.noreply.github.com>
|
||||
Nils ANDRÉ-CHANG <nils@nilsand.re>
|
||||
Nils ANDRÉ-CHANG <nils@nilsand.re> <nils.andre.chang@gmail.com>
|
||||
Nuno Donato <nunodonato@gmail.com> <n.donato@estrelasustentavel.pt>
|
||||
ocean (they/them) <anvilfolk@gmail.com>
|
||||
Pawel Kowal <pkowal1982@gmail.com>
|
||||
Pedro J. Estébanez <pedrojrulez@gmail.com> <RandomShaper@users.noreply.github.com>
|
||||
Patrick <firefly2442@gmail.com>
|
||||
Paul Batty <p_batty@hotmail.co.uk>
|
||||
Paul Batty <p_batty@hotmail.co.uk> <Paulb23@users.noreply.github.com>
|
||||
Pawel Kowal <pkowal1982@gmail.com> <pawel.kowal@javart.eu>
|
||||
Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
|
||||
Pieter-Jan Briers <pieterjan.briers+git@gmail.com> <pieterjan.briers@gmail.com>
|
||||
Poommetee Ketson <poommetee@protonmail.com>
|
||||
Przemysław Gołąb (n-pigeon) <golab.przemyslaw@gmail.com>
|
||||
Rafał Mikrut <mikrutrafal@protonmail.com>
|
||||
Rafał Mikrut <mikrutrafal@protonmail.com> <mikrutrafal54@gmail.com>
|
||||
Ralf Hölzemer <r.hoelzemer@posteo.de> <rollenrolm@posteo.de>
|
||||
Ralf Hölzemer <r.hoelzemer@posteo.de> <rollenrolm@users.noreply.github.com>
|
||||
Ramesh Ravone <ramesh.maran443@gmail.com>
|
||||
RaphaelHunter <raphael10241024@gmail.com>
|
||||
RaphaelHunter <raphael10241024@gmail.com> <Raphael10241024@gmail.com>
|
||||
RaphaelHunter <raphael10241024@gmail.com> <raphael20141024@gmail.com>
|
||||
Rémi Verschelde <rverschelde@gmail.com> <remi@verschelde.fr>
|
||||
Rhody Lugo <rhodylugo@gmail.com> <rhodylugo@me.com>
|
||||
Ricardo Subtil <ricasubtil@gmail.com>
|
||||
Rindbee <idleman@yeah.net>
|
||||
Riteo Siuga <riteo@posteo.net>
|
||||
Robin Hübner <profan@prfn.se> <robinhubner@gmail.com>
|
||||
romulox_x <romulox_x@yahoo.com>
|
||||
rune-scape <allie.smith.epic@gmail.com>
|
||||
rune-scape <allie.smith.epic@gmail.com> <spartacrafter@gmail.com>
|
||||
Ruslan Mustakov <r.mustakov@gmail.com> <ruslan.mustakov@xored.com>
|
||||
Saracen <SaracenOne@gmail.com>
|
||||
sheepandshepherd <sheepandshepherd@hotmail.com> <sheepandshepherd@users.noreply.github.com>
|
||||
Silc 'Tokage' Renew <tokage.it.lab@gmail.com>
|
||||
Silc 'Tokage' Renew <tokage.it.lab@gmail.com> <61938263+TokageItLab@users.noreply.github.com>
|
||||
Swarnim Arun <swarnimarun11@gmail.com>
|
||||
TechnoPorg <jonah.janzen@gmail.com> <69441745+TechnoPorg@users.noreply.github.com>
|
||||
Theo Hallenius <redsymbzone@hotmail.com>
|
||||
Tomasz Chabora <kobewi4e@gmail.com>
|
||||
Twarit <wtwarit@gmail.com>
|
||||
Vitika9 <vitika.program@gmail.com>
|
||||
V.VamsiKrishna <vk@bsb.in> <vamsikrishna.v@gmail.com>
|
||||
Wilhem Barbier <nounoursheureux@openmailbox.org> <wilhem.b@free.fr>
|
||||
Wilhem Barbier <nounoursheureux@openmailbox.org> <schtroumps31@gmail.com>
|
||||
Will Nations <willnationsdev@gmail.com>
|
||||
yg2f <yoann@terminajones.com>
|
||||
Yuri Sizov <yuris@humnom.net> <pycbouh@users.noreply.github.com>
|
||||
Yuri Sizov <yuris@humnom.net> <yaschik4ilicha@gmail.com>
|
||||
Zae <zaevi@live.com>
|
||||
Zak Stam <zakscomputers@hotmail.com>
|
||||
Zher Huei Lee <lee.zh.92@gmail.com>
|
||||
90
.travis.yml
Normal file
90
.travis.yml
Normal file
@ -0,0 +1,90 @@
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
env:
|
||||
- GODOT_TARGET=iphone
|
||||
- GODOT_TARGET=osx
|
||||
- GODOT_TARGET=x11
|
||||
#- GODOT_TARGET=android
|
||||
- GODOT_TARGET=windows
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: STATIC_CHECKS=yes
|
||||
exclude:
|
||||
- os: linux
|
||||
env: GODOT_TARGET=iphone
|
||||
- os: linux
|
||||
env: GODOT_TARGET=osx
|
||||
- os: linux
|
||||
env: GODOT_TARGET=android
|
||||
- os: osx
|
||||
env: GODOT_TARGET=x11
|
||||
- os: osx
|
||||
env: GODOT_TARGET=windows
|
||||
- compiler: gcc
|
||||
env: GODOT_TARGET=iphone
|
||||
- compiler: gcc
|
||||
env: GODOT_TARGET=osx
|
||||
- compiler: clang
|
||||
env: GODOT_TARGET=android
|
||||
- compiler: clang
|
||||
env: GODOT_TARGET=windows
|
||||
- compiler: clang
|
||||
env: GODOT_TARGET=x11
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-3.9
|
||||
packages:
|
||||
- build-essential
|
||||
- scons
|
||||
- pkg-config
|
||||
- libx11-dev
|
||||
- libxcursor-dev
|
||||
- libasound2-dev
|
||||
- libfreetype6-dev
|
||||
- libgl1-mesa-dev
|
||||
- libglu1-mesa-dev
|
||||
- libssl-dev
|
||||
- libxinerama-dev
|
||||
- libxrandr-dev
|
||||
|
||||
# For cross-compiling to Windows.
|
||||
- binutils-mingw-w64-i686
|
||||
- binutils-mingw-w64-x86-64
|
||||
- gcc-mingw-w64-i686
|
||||
- gcc-mingw-w64-x86-64
|
||||
- g++-mingw-w64-i686
|
||||
- g++-mingw-w64-x86-64
|
||||
- mingw-w64
|
||||
|
||||
# For style checks.
|
||||
- clang-format-3.9
|
||||
|
||||
|
||||
before_script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew install scons; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
|
||||
brew update; brew install -v android-sdk;
|
||||
brew install -v android-ndk | grep -v "inflating:" | grep -v "creating:";
|
||||
export ANDROID_HOME=/usr/local/opt/android-sdk; export ANDROID_NDK_ROOT=/usr/local/opt/android-ndk;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [ "$STATIC_CHECKS" = "yes" ]; then
|
||||
sh ./misc/travis/clang-format.sh;
|
||||
else
|
||||
scons platform=$GODOT_TARGET CXX=$CXX openssl=builtin;
|
||||
fi
|
||||
236
AUTHORS.md
236
AUTHORS.md
@ -10,263 +10,67 @@ source code. "Significant" is arbitrarily decided, but should be fair :)
|
||||
GitHub usernames are indicated in parentheses, or as sole entry when no other
|
||||
name is available.
|
||||
|
||||
## Project Founders
|
||||
## Original authors
|
||||
|
||||
Juan Linietsky (reduz)
|
||||
Ariel Manzur (punto-)
|
||||
|
||||
## Lead Developer
|
||||
|
||||
Juan Linietsky (reduz)
|
||||
|
||||
## Project Manager
|
||||
|
||||
Rémi Verschelde (akien-mga)
|
||||
|
||||
## Developers
|
||||
|
||||
(in alphabetical order, with over 10 commits excluding merges)
|
||||
(in alphabetical order, with 10 commits or more excluding merges)
|
||||
|
||||
Aaron Franke (aaronfranke)
|
||||
Aaron Record (LightningAA)
|
||||
Adam Scott (adamscott)
|
||||
Alexander Holland (AlexHolly)
|
||||
Alexey Khoroshavin (allkhor)
|
||||
Alfred Reinold Baudisch (alfredbaudisch)
|
||||
Alket Rexhepi (alketii)
|
||||
Andrea Catania (AndreaCatania)
|
||||
Andrii Doroshenko (Xrayez)
|
||||
Andy Maloney (asmaloney)
|
||||
Andy Moss (MillionOstrich)
|
||||
Angad Kambli (angad-k)
|
||||
Anilforextra (AnilBK)
|
||||
Anish Bhobe (KidRigger)
|
||||
Alexey Velikiy (jonyrock)
|
||||
Andreas Haas (Hinsbart)
|
||||
Anton Yabchinskiy (a12n)
|
||||
Anutrix
|
||||
Aren Villanueva (kurikaesu)
|
||||
Ariel Manzur (punto-)
|
||||
Bartłomiej T. Listwon (Listwon)
|
||||
Bastiaan Olij (BastiaanOlij)
|
||||
Ben Brookshire (sheepandshepherd)
|
||||
Benjamin Larsson (Nallebeorn)
|
||||
Bernhard Liebl (poke1024)
|
||||
Bhuvan Vemula (Bhu1-V)
|
||||
Błażej Szczygieł (zaps166)
|
||||
Bojidar Marinov (bojidar-bg)
|
||||
Brian Semrau (briansemrau)
|
||||
Bruno Lourenço (MadEqua)
|
||||
Cameron Reikes (creikey)
|
||||
Camille Mohr-Daurat (pouleyKetchoupp)
|
||||
Caner Demirer (cdemirer)
|
||||
Błażej Szczygieł (zaps166)
|
||||
Carl Olsson (not-surt)
|
||||
Carter Anderson (cart)
|
||||
Chris Bradfield (cbscribe)
|
||||
Clay John (clayjohn)
|
||||
ConteZero
|
||||
Dana Olson (adolson)
|
||||
Daniel J. Ramirez (djrm)
|
||||
Daniel Rakos (aqnuep)
|
||||
Daniel Zilberleyb (dzil123)
|
||||
Danil Alexeev (dalexeev)
|
||||
dankan1890
|
||||
David Cambré (Gallilus)
|
||||
David Sichma (DavidSichma)
|
||||
David Snopek (dsnopek)
|
||||
Dharkael (lupoDharkael)
|
||||
Dmitry Koteroff (Krakean)
|
||||
Dmitry Maganov (vonagam)
|
||||
Dominik Jasiński (dreamsComeTrue)
|
||||
Douglas Leão (DeeJayLSP)
|
||||
DualMatrix
|
||||
Ellen Poe (ellenhp)
|
||||
Emmanuel Barroga (codecustard)
|
||||
Emmanuel Leblond (touilleMan)
|
||||
Eoin O'Neill (Eoin-ONeill-Yokai)
|
||||
Eric Lasota (elasota)
|
||||
Eric M (EricEzaM)
|
||||
Eric Rybicki (ericrybick)
|
||||
Erik Selecký (rxlecky)
|
||||
est31
|
||||
Eveline Jarosz (Marqin)
|
||||
Fabian Mathews (supagu)
|
||||
Fabio Alessandrelli (Faless)
|
||||
Fabrice Cipolla (fabriceci)
|
||||
Ferenc Arn (tagcup)
|
||||
FireForge (fire-forge)
|
||||
follower
|
||||
foxydevloper
|
||||
François Belair (Razoric480)
|
||||
Franklin Sobrinho (TheHX)
|
||||
Fredia Huya-Kouadio (m4gr3d)
|
||||
Geequlim
|
||||
Gen (dbsGen)
|
||||
George Marques (vnen)
|
||||
Gerrit Großkopf (Grosskopf)
|
||||
Gilles Roudiere (groud)
|
||||
Gordon MacPherson (RevoluPowered)
|
||||
Guilherme Felipe de C. G. da Silva (guilhermefelipecgs)
|
||||
Hanif Bin Ariffin (hbina)
|
||||
Haoyu Qiu (timothyqiu)
|
||||
Hein-Pieter van Braam-Stewart (hpvb)
|
||||
Hendrik Brucker (Geometror)
|
||||
hilfazer
|
||||
Hiroshi Ogawa (hi-ogawa)
|
||||
homer666
|
||||
hoontee
|
||||
Hugo Locurcio (Calinou)
|
||||
Ian Bishop (ianb96)
|
||||
Ibrahn Sahir (ibrahn)
|
||||
Guilherme Felipe (guilhermefelipecgs)
|
||||
Hein-Pieter van Braam (hpvb)
|
||||
Hubert Jarosz (Marqin)
|
||||
Ignacio Etcheverry (neikeq)
|
||||
Igor Kordiukiewicz (IgorKordiukiewicz)
|
||||
Ilaria Cislaghi (QbieShay)
|
||||
Indah Sylvia (ISylvox)
|
||||
J08nY
|
||||
Jake Young (Duroxxigar)
|
||||
Jakub Grzesik (kubecz3k)
|
||||
James Buck (jbuck3)
|
||||
Jan Haller (Bromeon)
|
||||
Jason Knight (jasonwinterpixel)
|
||||
Jean-Michel Bernard (jmb462)
|
||||
Jérôme Gully (Nutriz)
|
||||
Jia Jun Chai (SkyLucilfer)
|
||||
Joan Fons Sanchez (JFonS)
|
||||
Johan Manuel (29jm)
|
||||
Johannes Witt (HaSa1002)
|
||||
Jonathan Nicholl (jtnicholl)
|
||||
Jordan Schidlowsky (winterpixelgames)
|
||||
Josh Jones (DarkKilauea)
|
||||
Joshua Grams (JoshuaGrams)
|
||||
Juan Linietsky (reduz)
|
||||
Julian Murgia (StraToN)
|
||||
Julien Nguyen (Blackiris)
|
||||
Jummit
|
||||
Justo Delgado (mrcdk)
|
||||
karroffel
|
||||
Kelly Thomas (KellyThomas)
|
||||
kleonc
|
||||
Kongfa Waroros (gongpha)
|
||||
Kostadin Damyanov (Max-Might)
|
||||
K. S. Ernest (iFire) Lee (fire)
|
||||
lawnjelly
|
||||
Leon Krause (leonkrause)
|
||||
Liz Haas (27thLiz)
|
||||
Lucien Menassol (Kanabenki)
|
||||
Lyuma
|
||||
Maganty Rushyendra (mrushyendra)
|
||||
Manuele Finocchiaro (m4nu3lf)
|
||||
Marcel Admiraal (madmiraal)
|
||||
L. Krause (eska014)
|
||||
Marcelo Fernandez (marcelofg55)
|
||||
Marc Gilleron (Zylann)
|
||||
Marcin Zawiejski (dragmz)
|
||||
Marcus Brummer (mbrlabs)
|
||||
Marcus Elg (MCrafterzz)
|
||||
Mariano Javier Suligoy (MarianoGnu)
|
||||
Mario Schlack (hurikhan)
|
||||
Marios Staikopoulos (marstaik)
|
||||
Marius Hanl (Maran23)
|
||||
Mark Riedesel (klowner)
|
||||
Markus Sauermann (Sauermann)
|
||||
Martin Capitanio (capnm)
|
||||
Martin Liška (marxin)
|
||||
Martin Sjursen (binbitten)
|
||||
marynate
|
||||
Masoud BH (masoudbh3)
|
||||
Mateo Kuruk Miccino (kuruk-mm)
|
||||
Matthew (skyace65)
|
||||
Matthias Hölzl (hoelzl)
|
||||
Max Hilbrunner (mhilbrunner)
|
||||
merumelu
|
||||
Meru Patel (Janglee123)
|
||||
MewPurPur
|
||||
Michael Alexsander (YeldhamDev)
|
||||
Michał Iwańczuk (iwek7)
|
||||
MichiRecRoom (LikeLakers2)
|
||||
Micky (Mickeon)
|
||||
MinusKube
|
||||
Morris "Tabor" Arroad (mortarroad)
|
||||
mrezai
|
||||
Muhammad Huri (CakHuri)
|
||||
muiroc
|
||||
Nathan Franke (nathanfranke)
|
||||
Nathan Lovato (NathanLovato)
|
||||
Nathan Warden (NathanWarden)
|
||||
Nicholas Huelin (SirQuartz)
|
||||
Nikita Lita (nikitalita)
|
||||
Nils André-Chang (NilsIrl)
|
||||
Noah Beard (TwistedTwigleg)
|
||||
Nuno Donato (nunodonato)
|
||||
ocean (they/them) (anvilfolk)
|
||||
Omar El Sheikh (The-O-King)
|
||||
Ovnuniarchos
|
||||
Pascal Richter (ShyRed)
|
||||
Patrick (firefly2442)
|
||||
Paul Batty (Paulb23)
|
||||
Paul Joannon (paulloz)
|
||||
Paul Trojahn (ptrojahn)
|
||||
Pāvels Nadtočajevs (bruvzg)
|
||||
Paweł Fertyk (pfertyk)
|
||||
Pawel Kowal (pkowal1982)
|
||||
Pawel Lampe (Scony)
|
||||
Pedro J. Estébanez (RandomShaper)
|
||||
Pieter-Jan Briers (PJB3005)
|
||||
Poommetee Ketson (Noshyaar)
|
||||
Przemysław Gołąb (n-pigeon)
|
||||
Rafael M. G. (rafallus)
|
||||
Rafał Mikrut (qarmin)
|
||||
Ralf Hölzemer (rollenrolm)
|
||||
Ramesh Ravone (RameshRavone)
|
||||
Raphael2048
|
||||
Raul Santos (raulsntos)
|
||||
Ray Koopa (RayKoopa)
|
||||
RedMser
|
||||
RedworkDE
|
||||
RayKoopa
|
||||
Rémi Verschelde (akien-mga)
|
||||
Rhody Lugo (rraallvv)
|
||||
Ricardo Buring (rburing)
|
||||
Ricardo Subtil (Ev1lbl0w)
|
||||
Riteo Siuga (Riteo)
|
||||
Roberto F. Arroyo (robfram)
|
||||
Robin Hübner (profan)
|
||||
romulox-x
|
||||
Rune Smith (rune-scape)
|
||||
Ruslan Mustakov (endragor)
|
||||
Ryan Roden-Corrent (rrcore)
|
||||
Saniko (sanikoyes)
|
||||
santouits
|
||||
SaracenOne
|
||||
Sergey Minakov (naithar)
|
||||
sersoong
|
||||
Shiqing (kawa-yoiko)
|
||||
Silc 'Tokage' Renew (TokageItLab)
|
||||
Simon Wenner (swenner)
|
||||
smix8
|
||||
snailrhymer
|
||||
Stijn Hinlopen (hinlopen)
|
||||
Swarnim Arun (minraws)
|
||||
TC (floppyhammer)
|
||||
TechnoPorg
|
||||
Thakee Nathees (ThakeeNathees)
|
||||
thebestnom
|
||||
Theo Hallenius (TheoXD)
|
||||
Timo Schwarzer (timoschwarzer)
|
||||
Timo (toger5)
|
||||
Tomasz Chabora (KoBeWi)
|
||||
trollodel
|
||||
Twarit Waikar (IronicallySerious)
|
||||
Umang Kalra (theoway)
|
||||
Vinzenz Feenstra (vinzenz)
|
||||
Vitika Soni (Vitika9)
|
||||
박한얼 (volzhs)
|
||||
Thomas Herzog (karroffel)
|
||||
V. Vamsi Krishna (vkbsb)
|
||||
Wilhem Barbier (nounoursheureux)
|
||||
William Deurwaarder (williamd67)
|
||||
Will Nations (willnationsdev)
|
||||
Wilson E. Alvarez (Rubonnek)
|
||||
Xavier Cho (mysticfall)
|
||||
yg2f (SuperUserNameMan)
|
||||
Yuri Rubinsky (Chaosus)
|
||||
Yuri Sizov (YuriSizov)
|
||||
Zae Chao (zaevi)
|
||||
Zak Stam (zaksnet)
|
||||
Vinzenz Feenstra (vinzenz)
|
||||
Zher Huei Lee (leezh)
|
||||
ZuBsPaCe
|
||||
风青山 (Rindbee)
|
||||
박한얼 (volzhs)
|
||||
est31
|
||||
marynate
|
||||
mrezai
|
||||
romulox-x
|
||||
sanikoyes
|
||||
yg2f (SuperUserNameMan)
|
||||
|
||||
2828
CHANGELOG.md
2828
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
272
CONTRIBUTING.md
272
CONTRIBUTING.md
@ -1,267 +1,59 @@
|
||||
# How to contribute efficiently
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Reporting bugs](#reporting-bugs)
|
||||
- [Proposing features or improvements](#proposing-features-or-improvements)
|
||||
- [Contributing pull requests](#contributing-pull-requests)
|
||||
- [Contributing to Godot's translation](#contributing-to-godots-translation)
|
||||
- [Communicating with developers](#communicating-with-developers)
|
||||
|
||||
**Please read the first section before reporting a bug!**
|
||||
|
||||
## Reporting bugs
|
||||
## Reporting bugs or proposing features
|
||||
|
||||
The golden rule is to **always open *one* issue for *one* bug**. If you notice
|
||||
several bugs and want to report them, make sure to create one new issue for
|
||||
each of them.
|
||||
The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
|
||||
|
||||
If you're reporting a new bug, you'll make our life simpler (and the
|
||||
fix will come sooner) by following these guidelines:
|
||||
Everything refered to hereafter as "bug" also applies for feature requests.
|
||||
|
||||
### Search first in the existing database
|
||||
If you are reporting a new issue, you will make our life much simpler (and the fix come much sooner) by following those guidelines:
|
||||
|
||||
Issues are often reported several times by various users. It's good practice to
|
||||
**search first in the [issue tracker](https://github.com/godotengine/godot/issues)
|
||||
before reporting your issue**. If you don't find a relevant match or if you're
|
||||
unsure, don't hesitate to **open a new issue**. The bugsquad will handle it
|
||||
from there if it's a duplicate.
|
||||
#### Search first in the existing database
|
||||
|
||||
### Specify the platform
|
||||
Issues are often reported several times by various users. It's a good practice to **search first** in the issues database before reporting your issue. If you don't find a relevant match or if you are unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
|
||||
|
||||
Godot runs on a large variety of platforms and operating systems and devices.
|
||||
**In your bug reports, please always specify:**
|
||||
#### Specify the platform
|
||||
|
||||
Godot runs on a large variety of platforms and operating systems and devices. If you believe your issue is device/platform dependent (for example if it is related to the rendering, crashes or compilation errors), please specify:
|
||||
* Operating system
|
||||
* Device (including architecture, e.g. x86, x86_64, arm, etc.)
|
||||
* GPU model (and driver in use if you know it)
|
||||
|
||||
- Operating system and version (e.g. Windows 10, macOS 10.15, Ubuntu 19.10)
|
||||
- Godot version (e.g. 3.2, 3.1.2, or the Git commit hash if you're using a development branch)
|
||||
#### Specify steps to reproduce
|
||||
|
||||
For bugs that are likely OS-specific and/or graphics-related, please also specify:
|
||||
Many bugs can't be reproduced unless specific steps are taken. Please **specify the exact steps** that must be taken to reproduce the condition, and try to keep them as minimal as possible.
|
||||
|
||||
- Device (CPU model including architecture, e.g. x86_64, arm64, etc.)
|
||||
- GPU model (and the driver version in use if you know it)
|
||||
#### Provide a simple, example project
|
||||
|
||||
**Bug reports not including the required information may be closed at the
|
||||
maintainers' discretion.** If in doubt, always include all the requested
|
||||
information; it's better to include too much information than not enough
|
||||
information.
|
||||
Sometimes an unexpected behavior happens in your project. In such case, understand that:
|
||||
|
||||
### Specify steps to reproduce
|
||||
|
||||
Many bugs can't be reproduced unless specific steps are taken. Please **specify
|
||||
the exact steps** that must be taken to reproduce the condition, and try to
|
||||
keep them as minimal as possible. If you're describing a procedure to follow
|
||||
in the editor, don't hesitate to include screenshots.
|
||||
|
||||
Making your bug report easy to reproduce will make it easier for contributors
|
||||
to fix the bug.
|
||||
|
||||
### Provide a simple example project
|
||||
|
||||
Sometimes, unexpected behavior can happen in your project. In such case,
|
||||
understand that:
|
||||
|
||||
- What happens to you may not happen to other users.
|
||||
- We can't take the time to look at your project, understand how it is set up
|
||||
and then figure out why it's failing.
|
||||
- On the contributors' end, recreating a test project from scratch takes valuable
|
||||
time that can be saved by uploading a *minimal* project.
|
||||
|
||||
To speed up our work, **please upload a minimal project** that isolates
|
||||
and reproduces the issue. This is always the **best way for us to fix it**.
|
||||
We recommend attaching a ZIP file with the minimal project directly to the bug report,
|
||||
by drag and dropping the file in the GitHub edition field. This ensures the file
|
||||
can remain available for a long period of time. Only use third-party file hosts
|
||||
if your ZIP file isn't accepted by GitHub because it's too large.
|
||||
|
||||
We recommend always attaching a minimal reproduction project, even if the issue
|
||||
may seem simple to reproduce manually.
|
||||
|
||||
**Note for C# users:** If your issue is *not* .NET-specific, please upload a
|
||||
minimal reproduction project written in GDScript.
|
||||
This will make it easier for contributors to reproduce the issue
|
||||
locally as not everyone has a .NET setup available.
|
||||
|
||||
**If you've been asked by a maintainer to upload a minimal reproduction project,
|
||||
you *must* do so within 7 days.** Otherwise, your bug report will be closed as
|
||||
it'll be considered too difficult to diagnose.
|
||||
|
||||
Now that you've read the guidelines, click the link below to create a
|
||||
bug report:
|
||||
|
||||
- **[Report a bug](https://github.com/godotengine/godot/issues/new?assignees=&labels=&template=bug_report.yml)**
|
||||
|
||||
## Proposing features or improvements
|
||||
|
||||
**Since August 2019, the main issue tracker no longer accepts feature proposals.**
|
||||
Instead, head to the [Godot Proposals repository](https://github.com/godotengine/godot-proposals)
|
||||
and follow the instructions in the README file. High-quality feature proposals
|
||||
are more likely to be well-received by the maintainers and community, so do
|
||||
your best :)
|
||||
|
||||
See [this article](https://godotengine.org/article/introducing-godot-proposals-repository)
|
||||
for detailed rationale on this change.
|
||||
* What happens to you may not happen to other users.
|
||||
* We can't take the time to look at your project, understand how it is set up and then figure out why it's failing.
|
||||
|
||||
To speed up our work, please prepare for us **a simple project** that isolates and reproduces the issue. This is always the **the best way for us to fix it**. You can attach a zip file with the minimal project directly to the bug report, by drag and dropping the file in the GitHub edition field.
|
||||
|
||||
## Contributing pull requests
|
||||
|
||||
If you want to add new engine features, please make sure that:
|
||||
If you want to add new engine functionalities, please make sure that:
|
||||
|
||||
- This functionality is desired, which means that it solves a common use case
|
||||
that several users will need in their real-life projects.
|
||||
- You talked to other developers on how to implement it best. See also
|
||||
[Proposing features or improvements](#proposing-features-or-improvements).
|
||||
- Even if it doesn't get merged, your PR is useful for future work by another
|
||||
developer.
|
||||
* This functionality is desired.
|
||||
* You talked to other developers on how to implement it best (on either communication channel, and maybe in a GitHub issue first before making your PR).
|
||||
* Even if it does not get merged, your PR is useful for future work by another developer.
|
||||
|
||||
Similar rules can be applied when contributing bug fixes - it's always best to
|
||||
discuss the implementation in the bug report first if you are not 100% about
|
||||
what would be the best fix.
|
||||
Similar rules can be applied when contributing bug fixes - it's always best to discuss the implementation in the bug report first if you are not 100% about what would be the best fix.
|
||||
|
||||
[This blog post](https://godotengine.org/article/will-your-contribution-be-merged-heres-how-tell)
|
||||
outlines the process used by core developers when assessing PRs. We strongly
|
||||
recommend that you have a look at it to know what's important to take into
|
||||
account for a PR to be considered for merging.
|
||||
#### Be nice to the git history
|
||||
|
||||
In addition to the following tips, also take a look at the
|
||||
[Engine development guide](https://docs.godotengine.org/en/latest/contributing/development/index.html)
|
||||
for an introduction to developing on Godot.
|
||||
Try to make simple PRs with that handle one specific topic. Just like for reporting issues, it's better to open 3 different PRs that each address a different issue than one big PR with three commits.
|
||||
|
||||
The [Contributing docs](https://docs.godotengine.org/en/latest/contributing/ways_to_contribute.html)
|
||||
also have important information on the [PR workflow](https://docs.godotengine.org/en/latest/contributing/workflow/pr_workflow.html)
|
||||
and the [code style](https://docs.godotengine.org/en/latest/contributing/development/code_style_guidelines.html) we use.
|
||||
When updating your fork with upstream changes, please use ``git pull --rebase`` to avoid creating "merge commits". Those commits unnecessarily pollute the git history when coming from PRs.
|
||||
|
||||
### Document your changes
|
||||
Also try to make commits that bring the engine from one stable state to another stable state, i.e. if your first commit has a bug that you fixed in the second commit, try to merge them together before making your pull request (see ``git rebase -i`` and relevant help about rebasing or ammending commits on the Internet).
|
||||
|
||||
If your pull request adds methods, properties or signals that are exposed to
|
||||
scripting APIs, you **must** update the class reference to document those.
|
||||
This is to ensure the documentation coverage doesn't decrease as contributions
|
||||
are merged.
|
||||
This git style guide has some good practices to have in mind: https://github.com/agis-/git-style-guide
|
||||
|
||||
[Update documentation XML files](https://docs.godotengine.org/en/latest/contributing/documentation/updating_the_class_reference.html#updating-class-reference-when-working-on-the-engine)
|
||||
using your compiled binary, then fill in the descriptions.
|
||||
Follow the style guide described in the
|
||||
[Writing guidelines](https://docs.godotengine.org/en/latest/contributing/documentation/docs_writing_guidelines.html).
|
||||
Thanks!
|
||||
|
||||
If your pull request modifies parts of the code in a non-obvious way, make sure
|
||||
to add comments in the code as well. This helps other people understand the
|
||||
change without having to look at `git blame`.
|
||||
|
||||
### Write unit tests
|
||||
|
||||
When fixing a bug or contributing a new feature, we recommend including unit
|
||||
tests in the same commit as the rest of the pull request. Unit tests are pieces
|
||||
of code that compare the output to a predetermined *expected result* to detect
|
||||
regressions. Tests are compiled and run on GitHub Actions for every commit and
|
||||
pull request.
|
||||
|
||||
Pull requests that include tests are more likely to be merged, since we can have
|
||||
greater confidence in them not being the target of regressions in the future.
|
||||
|
||||
For bugs, the unit tests should cover the functionality that was previously
|
||||
broken. If done well, this ensures regressions won't appear in the future
|
||||
again. For new features, the unit tests should cover the newly added
|
||||
functionality, testing both the "success" and "expected failure" cases if
|
||||
applicable.
|
||||
|
||||
Feel free to contribute standalone pull requests to add new tests or improve
|
||||
existing tests as well.
|
||||
|
||||
See [Unit testing](https://docs.godotengine.org/en/latest/contributing/development/core_and_modules/unit_testing.html)
|
||||
for information on writing tests in Godot's C++ codebase.
|
||||
|
||||
### Be nice to the Git history
|
||||
|
||||
Try to make simple PRs that handle one specific topic. Just like for reporting
|
||||
issues, it's better to open 3 different PRs that each address a different issue
|
||||
than one big PR with three commits.
|
||||
|
||||
When updating your fork with upstream changes, please use ``git pull --rebase``
|
||||
to avoid creating "merge commits". Those commits unnecessarily pollute the git
|
||||
history when coming from PRs.
|
||||
|
||||
Also try to make commits that bring the engine from one stable state to another
|
||||
stable state, i.e. if your first commit has a bug that you fixed in the second
|
||||
commit, try to merge them together before making your pull request (see ``git
|
||||
rebase -i`` and relevant help about rebasing or amending commits on the
|
||||
Internet).
|
||||
|
||||
This [Git style guide](https://github.com/agis-/git-style-guide) has some
|
||||
good practices to have in mind.
|
||||
|
||||
See our [PR workflow](https://docs.godotengine.org/en/latest/contributing/workflow/pr_workflow.html)
|
||||
documentation for tips on using Git, amending commits and rebasing branches.
|
||||
|
||||
### Format your commit messages with readability in mind
|
||||
|
||||
The way you format your commit messages is quite important to ensure that the
|
||||
commit history and changelog will be easy to read and understand. A Git commit
|
||||
message is formatted as a short title (first line) and an extended description
|
||||
(everything after the first line and an empty separation line).
|
||||
|
||||
The short title is the most important part, as it is what will appear in the
|
||||
`shortlog` changelog (one line per commit, so no description shown) or in the
|
||||
GitHub interface unless you click the "expand" button. As the name says, try to
|
||||
keep that first line under 72 characters. It should describe what the commit
|
||||
does globally, while details would go in the description. Typically, if you
|
||||
can't keep the title short because you have too much stuff to mention, it means
|
||||
you should probably split your changes in several commits :)
|
||||
|
||||
Here's an example of a well-formatted commit message (note how the extended
|
||||
description is also manually wrapped at 80 chars for readability):
|
||||
|
||||
```text
|
||||
Prevent French fries carbonization by fixing heat regulation
|
||||
|
||||
When using the French fries frying module, Godot would not regulate the heat
|
||||
and thus bring the oil bath to supercritical liquid conditions, thus causing
|
||||
unwanted side effects in the physics engine.
|
||||
|
||||
By fixing the regulation system via an added binding to the internal feature,
|
||||
this commit now ensures that Godot will not go past the ebullition temperature
|
||||
of cooking oil under normal atmospheric conditions.
|
||||
|
||||
Fixes #1789, long live the Realm!
|
||||
```
|
||||
|
||||
**Note:** When using the GitHub online editor or its drag-and-drop
|
||||
feature, *please* edit the commit title to something meaningful. Commits named
|
||||
"Update my_file.cpp" won't be accepted.
|
||||
|
||||
## Contributing to Godot's translation
|
||||
|
||||
You can contribute to Godot's translation from the [Hosted
|
||||
Weblate](https://hosted.weblate.org/projects/godot-engine/godot), an open
|
||||
source and web-based translation platform. Please refer to the [translation
|
||||
readme](editor/translations/README.md) for more information.
|
||||
|
||||
You can also help translate [Godot's
|
||||
documentation](https://hosted.weblate.org/projects/godot-engine/godot-docs/)
|
||||
on Weblate.
|
||||
|
||||
## Communicating with developers
|
||||
|
||||
The Godot Engine community has [many communication
|
||||
channels](https://godotengine.org/community), some used more for user-level
|
||||
discussions and support, others more for development discussions.
|
||||
|
||||
To communicate with developers (e.g. to discuss a feature you want to implement
|
||||
or a bug you want to fix), the following channels can be used:
|
||||
|
||||
- [Godot Contributors Chat](https://chat.godotengine.org): You will
|
||||
find most core developers there, so it's the go-to platform for direct chat
|
||||
about Godot Engine development. Feel free to start discussing something there
|
||||
to get some early feedback before writing up a detailed proposal in a GitHub
|
||||
issue.
|
||||
- [Bug tracker](https://github.com/godotengine/godot/issues): If there is an
|
||||
existing issue about a topic you want to discuss, just add a comment to it -
|
||||
many developers watch the repository and will get a notification. You can
|
||||
also create a new issue - please keep in mind to create issues only to
|
||||
discuss quite specific points about the development, and not general user
|
||||
feedback or support requests.
|
||||
- [Feature proposals](https://github.com/godotengine/godot-proposals/issues):
|
||||
To propose a new feature, we have a dedicated issue tracker for that. Don't
|
||||
hesitate to start by talking about your idea on the Godot Contributors Chat
|
||||
to make sure that it makes sense in Godot's context.
|
||||
|
||||
Thanks for your interest in contributing!
|
||||
|
||||
—The Godot development team
|
||||
The Godot development team
|
||||
|
||||
1946
COPYRIGHT.txt
1946
COPYRIGHT.txt
File diff suppressed because it is too large
Load Diff
783
DONORS.md
783
DONORS.md
@ -1,783 +0,0 @@
|
||||
# Donors to the Godot Engine project
|
||||
|
||||
Godot Engine is a non-profit project developed by a community of voluntary
|
||||
contributors, as well as occasional paid contributors thanks to the financial
|
||||
support of generous donors.
|
||||
|
||||
The ways to donate to the project, as well as details on how the funds are
|
||||
used, are described on [Godot's website](https://godotengine.org/donate).
|
||||
|
||||
The following is a list of the current monthly donors, who will have their
|
||||
generous deed immortalized in the next stable release of Godot Engine.
|
||||
|
||||
## Platinum sponsors
|
||||
|
||||
Gamblify <https://www.gamblify.com>
|
||||
Heroic Labs <https://heroiclabs.com>
|
||||
Spiffcode <http://spiffcode.com>
|
||||
|
||||
## Gold sponsors
|
||||
|
||||
None currently, become one! <https://godotengine.org/donate>
|
||||
|
||||
## Silver sponsors
|
||||
|
||||
Affray Interactive <https://scp.games/pandemic>
|
||||
Playful Studios <https://playfulstudios.com>
|
||||
Robot Gentleman <http://robotgentleman.com>
|
||||
Striked <https://striked.gg>
|
||||
|
||||
## Bronze sponsors
|
||||
|
||||
ASIFA-Hollywood <https://www.asifa-hollywood.org>
|
||||
Basically Games
|
||||
Bippinbits <https://bippinbits.com>
|
||||
Brandon Lamb
|
||||
Bri
|
||||
Garry Newman
|
||||
Gordon MacPherson
|
||||
Hunter Dickson
|
||||
Isaiah smith
|
||||
Jb Evain
|
||||
Keepsake Games <https://keepsake.games>
|
||||
Kenney <https://kenney.nl>
|
||||
Kitcat490
|
||||
Kyle Szklenski
|
||||
Matthew Campbell
|
||||
Maxim Karsten
|
||||
Moonwards <https://www.moonwards.com>
|
||||
Nik Rudenko
|
||||
TrampolineTales <https://trampolinetales.com>
|
||||
|
||||
## Mini sponsors
|
||||
|
||||
AD Ford
|
||||
Albin Lundahl
|
||||
Andres Hernandez
|
||||
Andrew Dunai
|
||||
anti666
|
||||
Christian Baune
|
||||
Christopher Montesano
|
||||
Christopher Shifflett
|
||||
Christoph Woinke
|
||||
Daniel Edwards
|
||||
Darrin Massena
|
||||
David Mydlarz
|
||||
Digital Grows
|
||||
Edward Flick
|
||||
Florian Neumann
|
||||
GameDev.net
|
||||
Hein-Pieter van Braam
|
||||
Jonah Stich
|
||||
Justin Arnold
|
||||
Justin McGettigan
|
||||
Justo Delgado Baudí
|
||||
Kossi Selom Banybah
|
||||
Lloyd Bond
|
||||
Marcel Kräml
|
||||
Marek Belski
|
||||
Markus Ort
|
||||
Matthieu Huvé
|
||||
Michael
|
||||
Mike King
|
||||
Nassor Paulino da Silva
|
||||
nate-wilkins
|
||||
Nathan Warden
|
||||
Neal Gompa (Conan Kudo)
|
||||
Ninja_5tyl3
|
||||
Patrick Horn
|
||||
Patrick Schmidt
|
||||
Rami
|
||||
Ronnie Cheng
|
||||
Ryan Heath
|
||||
Samantha
|
||||
ShikadiGum
|
||||
Slobodan Milnovic
|
||||
Stephan Lanfermann
|
||||
Steve
|
||||
Tim Yuen
|
||||
Violin Iliev
|
||||
Vladimír Chvátil
|
||||
|
||||
## Gold donors
|
||||
|
||||
Acheron
|
||||
Adam Brown
|
||||
albinaask
|
||||
Allen Pestaluky
|
||||
Arisaka Mayuki
|
||||
Asher Glick
|
||||
Barugon
|
||||
Benito
|
||||
Carlo Cabanilla
|
||||
Daniel James
|
||||
David Fedorchak
|
||||
David Gehrig
|
||||
David Hubber
|
||||
David Snopek
|
||||
Ed Morley
|
||||
Frank Kurka
|
||||
Guy Kay Jay
|
||||
Javier Roman
|
||||
Joan Fons
|
||||
Jonathan Wright
|
||||
Jon Woodward
|
||||
Karl Werf
|
||||
Klavdij Voncina
|
||||
Maciej Pendolski
|
||||
Manuele Finocchiaro
|
||||
Markus Wiesner
|
||||
Mateo Navarrete
|
||||
Matthew Hillier
|
||||
Officine Pixel S.n.c.
|
||||
Pedro Silva
|
||||
Retro Village
|
||||
Rob Messick
|
||||
Roland Fredenhagen
|
||||
Ronan Zeegers
|
||||
Sarksus
|
||||
Sean
|
||||
Sergey
|
||||
Sofox
|
||||
Taylor Ritenour
|
||||
Tom Langwaldt
|
||||
tukon
|
||||
Vagabond Arcade
|
||||
Victor
|
||||
Xeno Coliseum
|
||||
|
||||
␣
|
||||
23BLUENINJA
|
||||
AdamRatai
|
||||
Alexander Erlemann
|
||||
Alexandre VALIN
|
||||
Alexej Kowalew
|
||||
Alex Khayrullin
|
||||
Algebrute
|
||||
alice gambrell
|
||||
Alo Mis
|
||||
Andrew Cunningham
|
||||
Andrew Farr
|
||||
Andriy
|
||||
Antanas Paskauskas
|
||||
Antoni Batchelli
|
||||
Ari
|
||||
Arthur S. Muszynski
|
||||
BasicIncomePlz
|
||||
Brandon Hawkinson
|
||||
BrizzleBrip
|
||||
c64cosmin
|
||||
Cameron Connolly
|
||||
Carlo del Mundo
|
||||
Charlie Whitfield
|
||||
Chris Petrich
|
||||
Chris Serino
|
||||
Collin Rapp
|
||||
Craig Scarborough
|
||||
Craig Smith
|
||||
CT
|
||||
CzechBlueBear
|
||||
CzłowiekImadło
|
||||
Daniel Grice
|
||||
Daniel Reed
|
||||
Daniel Tebbutt
|
||||
Darrian Little
|
||||
Dennis Belfrage
|
||||
Donn Eddy
|
||||
Emily A. Bellows
|
||||
Eric Brand
|
||||
Eugenio Hugo Salgüero Jáñez
|
||||
Felix Winterhalter
|
||||
flesk
|
||||
Florencio Olsen
|
||||
foxydevloper
|
||||
Fransiska
|
||||
Gabrielius Vaiškūnas
|
||||
Gary Hulst
|
||||
Geoffroy Warin
|
||||
George Venizelos
|
||||
GlassBrick
|
||||
GrayDwarf
|
||||
Guilherme Felipe de C. G. da Silva
|
||||
Guillaume Pham Ngoc
|
||||
Harry Tumber
|
||||
Harvey Fong
|
||||
Heath Hayes
|
||||
Horváth-Lázár Péter
|
||||
Hu Hund
|
||||
illuxxium
|
||||
Jaap Marsman
|
||||
Jamal Bencharki
|
||||
James Couzens
|
||||
Jared White
|
||||
Jason Yundt
|
||||
Jennifer Wilcox
|
||||
Jesús Chicharro
|
||||
Jihun Moon
|
||||
Joel Fivat
|
||||
Johnathan Kupferer
|
||||
John Stinson
|
||||
Josef Stumpfegger
|
||||
Joshie Sparks
|
||||
Joshua Flores
|
||||
Joshua Lesperance
|
||||
Juan Velandia
|
||||
Judd
|
||||
Julian Todd
|
||||
JUSTIN CARROLL
|
||||
Kelson Ball
|
||||
Kelteseth
|
||||
Khora
|
||||
kickmaniac
|
||||
kinfox
|
||||
Laszlo Kiss
|
||||
leetNightshade
|
||||
Leo Fidel R Liban
|
||||
Liam Smyth
|
||||
LoparPanda
|
||||
Luca Junge
|
||||
Luca Vazzano
|
||||
LyaaaaaGames
|
||||
MadScientistCarl
|
||||
Marcus Dobler
|
||||
Marcus Richter
|
||||
Mark Barrett
|
||||
Martin Eigel
|
||||
Martin Gulliksson
|
||||
Martin Kotz
|
||||
Martin Soucek
|
||||
matt
|
||||
Matt Greene
|
||||
Matthew Dana
|
||||
Max Kryschi
|
||||
Michael Dürwald
|
||||
Michael Policastro
|
||||
MikadoSC
|
||||
nate etan
|
||||
Nicola Cocchiaro
|
||||
Nikita Blizniuk
|
||||
Nikola Whallon
|
||||
Oliver Dick
|
||||
Otis Clark
|
||||
Patrick Wuttke
|
||||
Patryk Pluta (vrid)
|
||||
Paul Hocker
|
||||
Paul Von Zimmerman
|
||||
Pete Goodwin
|
||||
Petr Malac
|
||||
Petrus Prinsloo
|
||||
Philip Woods
|
||||
RAMupgrade
|
||||
red1939
|
||||
Reilt
|
||||
Rene Tailleur
|
||||
Rhodochrone
|
||||
Rickard Hermanson
|
||||
Rob
|
||||
Rob McInroy
|
||||
RodZilla
|
||||
Romeo Disca
|
||||
Ronnie Ashlock
|
||||
Ronny Mühle
|
||||
Russ
|
||||
Ryan Breaker
|
||||
Ryan Miller
|
||||
Ryan Scott
|
||||
"Sage Automatic Systems, LLC"
|
||||
Samuel Hummerstone
|
||||
Samuel Judd
|
||||
schroedinger's possum
|
||||
Shishir Tandale
|
||||
Sing Chun Lee
|
||||
SKison
|
||||
Song Junwoo
|
||||
spacechase0
|
||||
SpicyCactuar
|
||||
Stephan Hennion
|
||||
Steven Landow
|
||||
Stoned Xander
|
||||
Talii
|
||||
Teslatech
|
||||
Thomas Bjarnelöf
|
||||
Thomas Kurz
|
||||
Tobias Bocanegra
|
||||
Tobias Raggl
|
||||
Tom Glenn
|
||||
Torbulous
|
||||
toto bibi
|
||||
Troy Kinsella
|
||||
Turntsnaco
|
||||
UltyX
|
||||
Valryia
|
||||
VeryProfessionalDodo
|
||||
VoidPointer
|
||||
whatever
|
||||
Winston
|
||||
Yifan Lai
|
||||
Yuancheng Zhang
|
||||
zkip lan
|
||||
|
||||
## Silver donors
|
||||
|
||||
Aaron Mayfield
|
||||
Aaron Oldenburg
|
||||
Adam Brunnmeier
|
||||
Adam Carr
|
||||
Adam Long
|
||||
Adam McCurdy
|
||||
Adam N Webber
|
||||
Adam Smeltzer
|
||||
Adinimys
|
||||
Adisibio
|
||||
Adriano Orioli
|
||||
Adrien de Pierres
|
||||
Agustinus Arya
|
||||
Aidan O'Flannagain
|
||||
ajaxcc
|
||||
Aki Mimoto
|
||||
Akio Yamazaki
|
||||
Alan Beauchamp
|
||||
Albert Gyulgazyan
|
||||
Alberto Salazar Muñoz
|
||||
Alberto Vilches
|
||||
Alder Stefano
|
||||
Alejandro Saucedo
|
||||
AleMax
|
||||
Alessandro Senese
|
||||
Alex Clavelle
|
||||
Alex de la Mare
|
||||
alex raeside
|
||||
Allan Davis
|
||||
Andre Altmueller
|
||||
Andrei Pufu
|
||||
Andre Stackhouse
|
||||
Andrew
|
||||
Andrew Groot
|
||||
andrew james morris
|
||||
Ano Nim
|
||||
Anthony Avina
|
||||
Anton Bouwer
|
||||
Arch Toasty
|
||||
Arda Erol
|
||||
Arthur Brainville
|
||||
Arturo Rosales
|
||||
Aubrey Falconer
|
||||
Auré Franky
|
||||
aurelien condomines
|
||||
Austin Miller
|
||||
Azar Gurbanov
|
||||
AzulCrescent
|
||||
Balázs Batári
|
||||
Beau Seymour
|
||||
Benedikt
|
||||
Ben Vercammen
|
||||
Ben Visness
|
||||
Bernhard Werner
|
||||
Bill Thibault
|
||||
bitbrain
|
||||
Bjarne Voigtländer
|
||||
Black Block
|
||||
Brady Goldsworthy
|
||||
Bram
|
||||
Brian
|
||||
Brian Ford
|
||||
Brigham Keys
|
||||
Burney Waring
|
||||
Caleb Makela
|
||||
Caliburn
|
||||
Cameron Meyer
|
||||
Carlos Rios
|
||||
Carl van der Geest
|
||||
Casey
|
||||
Cesar Ruiz
|
||||
Chad Steadman
|
||||
Checkpoint Charlie
|
||||
chendrak
|
||||
Chris Cavalluzzi
|
||||
Chris Jagusch
|
||||
Chris Langford
|
||||
Chris Ridenour
|
||||
Christian Kaltenecker
|
||||
Christian Mauduit
|
||||
Christian Scholz
|
||||
Christian Winter
|
||||
Christoffer Dahlblom
|
||||
Christoph Czurda
|
||||
Christophe Gagnier
|
||||
Codex404
|
||||
Cody Parker
|
||||
Conall O
|
||||
Corchari
|
||||
Corey W
|
||||
Craig Post
|
||||
CrispyPin
|
||||
cynwav
|
||||
Dakota Watkins
|
||||
Daniel H. Bahr
|
||||
Daniel Hoffmann
|
||||
Danielle
|
||||
Dare Looks
|
||||
Daren Scot Wilson
|
||||
Davesnothere
|
||||
David Baker
|
||||
David Bôle
|
||||
David May
|
||||
David Maziarka
|
||||
Devin Carraway
|
||||
Devin R
|
||||
Dimitri Roche
|
||||
Dominik Wetzel
|
||||
Donovan Hutcheon
|
||||
Douglas Plumley
|
||||
Dragontrapper
|
||||
dragoon
|
||||
Dr Ewan Murray
|
||||
Ducky
|
||||
Duobix
|
||||
Duodecimal
|
||||
edisonlee55
|
||||
Eduardo Teixeira
|
||||
Edward Herbert
|
||||
Edward Swartz
|
||||
Egon Elbre
|
||||
Elias Nykrem
|
||||
Elijah Anderson
|
||||
Emerson MX
|
||||
Ends
|
||||
Ephemeral
|
||||
Eric Stokes
|
||||
Eric Walkingshaw
|
||||
Eric Williams
|
||||
Erkki Seppälä
|
||||
Ewan Holmes
|
||||
Faisal Alkubaisi
|
||||
Fault Boy
|
||||
fby
|
||||
Felix Adam
|
||||
Fer DC
|
||||
Filip Lundby
|
||||
Frank
|
||||
fumangy
|
||||
Game Endeavor
|
||||
Garrett Steffen
|
||||
Gary Thomas
|
||||
gebba
|
||||
George Marques
|
||||
Green Fox
|
||||
Greg Burkland
|
||||
Gregory Campbell
|
||||
Greyson Richey
|
||||
Grid
|
||||
Grominet
|
||||
Guldoman
|
||||
Guo Hongci
|
||||
Hans Jorgensen
|
||||
Haplo
|
||||
Heribert Hirth
|
||||
Ian Richard Kunert
|
||||
Ian Williams
|
||||
Interstice
|
||||
iveks
|
||||
Jacob D
|
||||
Jaguar
|
||||
Jake D
|
||||
Jako Danar
|
||||
James
|
||||
James A F Manley
|
||||
James Duran
|
||||
James Gary
|
||||
James Thomas
|
||||
Jamie Massey
|
||||
Janis Skuja
|
||||
Jan Vetulani
|
||||
JARKKO PARVIAINEN
|
||||
Jason Evans
|
||||
Jason Uechi
|
||||
Jeff Hungerford
|
||||
Jeffrey Berube
|
||||
Jennifer Graves
|
||||
Jesse Dubay
|
||||
João Pedro Braz
|
||||
Joe Hurdle
|
||||
Joe Klemmer
|
||||
John Barlex
|
||||
John Bruce
|
||||
John Palgut
|
||||
Jonas
|
||||
Jonas Arndt
|
||||
Jonas Bernemann
|
||||
Jonas LHOSTE
|
||||
Jonas Rudlang
|
||||
Jonas Yamazaki
|
||||
Jonathan Bieber
|
||||
Jonathan Ellis
|
||||
Jonathan G
|
||||
Jon Sully
|
||||
Jordy Goodridge
|
||||
Jose Francisco 'Yiro' Vera Girona
|
||||
Joseph Catrambone
|
||||
Josh Segall
|
||||
Josh Taylor
|
||||
Joshua Heidrich
|
||||
Juanfran
|
||||
Juan Maggi
|
||||
Juan Uys
|
||||
Jueast
|
||||
Julian le Roux
|
||||
Julian Murgia
|
||||
Justin Hamilton
|
||||
Justin Spedding
|
||||
Justin Zander
|
||||
Kalydi Balázs
|
||||
Katsuomi Kobayashi
|
||||
Keedong Park
|
||||
Keegan Scott
|
||||
Keinan Powers
|
||||
Keith Bradner
|
||||
Kenji Kawabata
|
||||
Ken Minardo
|
||||
Kent Jofur
|
||||
Kerotasma
|
||||
Ketafuki
|
||||
killaQueen
|
||||
kimbring2
|
||||
Kodera Software
|
||||
KsyTek Games
|
||||
kycho
|
||||
Kyle Burnett
|
||||
Kyle Jacobs
|
||||
Lasse le Dous
|
||||
Laurent CHEA
|
||||
Laurent Dethoor
|
||||
Laxman Pradhan
|
||||
Lech Rozanski
|
||||
Leland Vakarian
|
||||
Leonardo Baumle
|
||||
Levi Lindsey
|
||||
LF
|
||||
Linus Lind Lundgren
|
||||
Logan Apple
|
||||
Lucas Coelho
|
||||
Ludovic DELVAL
|
||||
Luigi Renna
|
||||
Luis Ernesto Del Toro Peña
|
||||
Luis Gaemperle
|
||||
Luis Morao
|
||||
Lukas Komischke
|
||||
Luke Kasz
|
||||
Major Haul
|
||||
Malcolm
|
||||
Mara Huldra
|
||||
Marcos Heitor Carvalho
|
||||
Markie Music
|
||||
Mark Tyler
|
||||
Markus Martin
|
||||
Markus Michael Egger
|
||||
Markus Strompen
|
||||
Martin Holas
|
||||
Martin Liška
|
||||
Martin Trbola
|
||||
Martin Zabinski
|
||||
Matěj Drábek
|
||||
Matt Edwards
|
||||
Matthew
|
||||
Matthew Booe
|
||||
Maverick
|
||||
Maxime Blade
|
||||
Maxwell
|
||||
McStuffings
|
||||
Melchor
|
||||
Melissa Mears
|
||||
Metal Demon 2000
|
||||
Michael
|
||||
Michael Morrison
|
||||
Michal Skwarek
|
||||
Mikael Nordenberg
|
||||
Mikail Freitas
|
||||
Mikayla
|
||||
Mike Birkhead
|
||||
Mike Copley
|
||||
Mike McRoberts
|
||||
Miss
|
||||
Mitchell J. Wagner
|
||||
MJacred
|
||||
ModularMind
|
||||
Molinghu
|
||||
Molly Jameson
|
||||
MoltenGears
|
||||
Moowool
|
||||
Moritz Weissenberger
|
||||
moulefrite
|
||||
MrAZIE
|
||||
Mrjemandem
|
||||
Nathaniel
|
||||
neguse
|
||||
neighty
|
||||
Neil Blakey-Milner
|
||||
Neil Wang
|
||||
Neofytos Chimonas
|
||||
Nerdforge
|
||||
Nerdyninja
|
||||
Nicholas La Roux
|
||||
Nick Eldrenkamp
|
||||
Nick Macholl
|
||||
Nico Greve
|
||||
Nicolas Rosset
|
||||
Nicolò Brigadoi Calamari
|
||||
Nils Nordmark
|
||||
Nobbele
|
||||
Noel Billig
|
||||
Noesis
|
||||
obscuresteel
|
||||
Okatima
|
||||
Oleg Reva
|
||||
Olexa Tourko
|
||||
Oliver Ambrose
|
||||
oscar1000108
|
||||
Oscar Domingo
|
||||
Parth Patel
|
||||
Patrick Indermühle
|
||||
Patrickm
|
||||
Patrick Nafarrete
|
||||
Paul Gieske
|
||||
Paul Hankins
|
||||
Paul Mozet
|
||||
Paweł Kowal
|
||||
Paweł Łyczkowski
|
||||
Pedro Henrique Martins Garcia
|
||||
Peter Höglund
|
||||
Philip Ludington (MrPhil)
|
||||
Phoenix Jauregui
|
||||
Pierre Caye
|
||||
Pille
|
||||
Pixel Archipel
|
||||
pj
|
||||
Point08
|
||||
Portponky
|
||||
Preethi Vaidyanathan
|
||||
PsycHead
|
||||
Puntigames
|
||||
pwab
|
||||
Quincy Quincy
|
||||
Quinn Morrison
|
||||
Rafa Laguna
|
||||
RagingRoosevelt
|
||||
Ragnar Pettersson
|
||||
Rainer Amler
|
||||
Rammeow
|
||||
Relintai
|
||||
Remi Rampin
|
||||
Reneator
|
||||
Richard Ivánek
|
||||
Riley
|
||||
Robin Ward
|
||||
RobotCritter
|
||||
Rob Ruana
|
||||
Rodrigo Loli
|
||||
Roger Smith
|
||||
Roglozor
|
||||
Roka
|
||||
Roland Rząsa
|
||||
Roman Papush
|
||||
Roy Scayged
|
||||
Rudi
|
||||
Ryan Groom
|
||||
Ryan Mueller
|
||||
Rykk
|
||||
Sammy Fischer
|
||||
Sangeeth Pavithran
|
||||
Sasha Schwartz
|
||||
Sean Dee
|
||||
Sebastian Michailidis
|
||||
SeongWan Kim
|
||||
Sessamekesh
|
||||
SeungJong k
|
||||
Shaidak
|
||||
Shane Lillie
|
||||
Shane Spoor
|
||||
simdee
|
||||
Simon Jonas Larsen
|
||||
Simon Schoenenberger
|
||||
Sina Yeganeh
|
||||
sirn
|
||||
Skalli
|
||||
slavfox
|
||||
SleepDepJoel1
|
||||
smbe19
|
||||
smo1704
|
||||
Soheib El-Harrache
|
||||
Solene Waked
|
||||
Sophie Winter
|
||||
Squidgy
|
||||
Squirrel
|
||||
SSebigo
|
||||
Stephen Rice
|
||||
Stephen Schlie
|
||||
summerblind
|
||||
Sung soo Choi
|
||||
SxP
|
||||
tadashi endo
|
||||
Tarch
|
||||
Techwizz
|
||||
Terry
|
||||
TheVoiceInMyHead
|
||||
Thibaut DECROMBECQUE
|
||||
thomas
|
||||
Thomas Bechtold
|
||||
Thomas Detoy
|
||||
Thomas Pickett
|
||||
thommy
|
||||
Till1805
|
||||
Tim Drumheller
|
||||
Tim Erskine
|
||||
Tim Gleason
|
||||
Tim Klein
|
||||
Tim Nedvyga
|
||||
Timothy B. MacDonald
|
||||
Tim Raveling
|
||||
Tim Riley
|
||||
Toadile
|
||||
Tom Coxon
|
||||
Tom Webster
|
||||
Torsten Crass
|
||||
travis f w
|
||||
Trent Skinner
|
||||
tril zerobyte
|
||||
Tryggve Sollid
|
||||
Turgut Temucin
|
||||
Tycho
|
||||
Tyler Stafos
|
||||
Tyler Stepke
|
||||
Ukko K.
|
||||
Uther
|
||||
v01tech
|
||||
Vaida
|
||||
Vaughan Ling
|
||||
Vavin.X
|
||||
Vincent Barkmann
|
||||
Vincent Cloutier
|
||||
Vincent Foulon
|
||||
Vitaliy Sapronenko
|
||||
Vladimir Savin
|
||||
Vulinux
|
||||
Wapiti .
|
||||
Wiley Thompson
|
||||
William Bodin
|
||||
William Edwards
|
||||
William F Siqueira
|
||||
Woonki Moon
|
||||
Wyatt Goodin
|
||||
Xananax
|
||||
Yan Shi
|
||||
yin
|
||||
Zekim
|
||||
Zher Huei Lee
|
||||
Zoee Silcock
|
||||
ケルベロス
|
||||
貴宏 小松
|
||||
郝晨煜
|
||||
|
||||
## Bronze donors
|
||||
|
||||
There are even more donors that support the project with a small monthly donation.
|
||||
Every bit counts and we thank every one of them for their amazing support!
|
||||
10
ISSUE_TEMPLATE
Normal file
10
ISSUE_TEMPLATE
Normal file
@ -0,0 +1,10 @@
|
||||
**Operating system or device - Godot version:**
|
||||
|
||||
|
||||
**Issue description** (what happened, and what was expected):
|
||||
|
||||
|
||||
**Steps to reproduce:**
|
||||
|
||||
|
||||
**Link to minimal example project** (optional but very welcome):
|
||||
28
LICENSE.md
Normal file
28
LICENSE.md
Normal file
@ -0,0 +1,28 @@
|
||||
GODOT ENGINE
|
||||
http://www.godotengine.org
|
||||
|
||||
************************************************************************
|
||||
|
||||
Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.
|
||||
Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)
|
||||
|
||||
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.
|
||||
|
||||
************************************************************************
|
||||
20
LICENSE.txt
20
LICENSE.txt
@ -1,20 +0,0 @@
|
||||
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.
|
||||
@ -1,5 +1,2 @@
|
||||
Godot Engine Logo
|
||||
Copyright (c) 2017 Andrea Calabró
|
||||
|
||||
This work is licensed under a Creative Commons Attribution 4.0 International
|
||||
License (CC-BY-4.0 International) <https://creativecommons.org/licenses/by/4.0/>.
|
||||
Godot Logo (c) Andrea Calabró, distributed under the terms of the CC By License:
|
||||
https://creativecommons.org/licenses/by/3.0/legalcode
|
||||
80
README.md
80
README.md
@ -1,76 +1,66 @@
|
||||
# Godot Engine
|
||||
[](https://godotengine.org)
|
||||
|
||||
<p align="center">
|
||||
<a href="https://godotengine.org">
|
||||
<img src="logo_outlined.svg" width="400" alt="Godot Engine logo">
|
||||
</a>
|
||||
</p>
|
||||
## Godot Engine
|
||||
|
||||
## 2D and 3D cross-platform game engine
|
||||
Homepage: https://godotengine.org
|
||||
|
||||
**[Godot Engine](https://godotengine.org) is a feature-packed, cross-platform
|
||||
game engine to create 2D and 3D games from a unified interface.** It provides a
|
||||
comprehensive set of [common tools](https://godotengine.org/features), so that users can focus on making games
|
||||
without having to reinvent the wheel. Games can be exported with one click to a
|
||||
number of platforms, including the major desktop platforms (Linux, macOS,
|
||||
Windows), mobile platforms (Android, iOS), as well as Web-based platforms
|
||||
and [consoles](https://docs.godotengine.org/en/latest/tutorials/platform/consoles.html).
|
||||
#### 2D and 3D cross-platform game engine
|
||||
|
||||
## Free, open source and community-driven
|
||||
Godot Engine is a feature-packed, cross-platform game engine to create 2D and
|
||||
3D games from a unified interface. It provides a comprehensive set of common
|
||||
tools, so that users can focus on making games without having to reinvent the
|
||||
wheel. Games can be exported in one click to a number of platforms, including
|
||||
the major desktop platforms (Linux, Mac OSX, Windows) as well as mobile
|
||||
(Android, iOS) and web-based (HTML5) platforms.
|
||||
|
||||
Godot is completely free and open source under the very permissive [MIT license](https://godotengine.org/license).
|
||||
#### Free, open source and community-driven
|
||||
|
||||
Godot is completely free and open source under the very permissive MIT license.
|
||||
No strings attached, no royalties, nothing. The users' games are theirs, down
|
||||
to the last line of engine code. Godot's development is fully independent and
|
||||
community-driven, empowering users to help shape their engine to match their
|
||||
expectations. It is supported by the [Software Freedom Conservancy](https://sfconservancy.org/)
|
||||
expectations. It is supported by the Software Freedom Conservancy
|
||||
not-for-profit.
|
||||
|
||||
Before being open sourced in [February 2014](https://github.com/godotengine/godot/commit/0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac),
|
||||
Godot had been developed by [Juan Linietsky](https://github.com/reduz) and
|
||||
[Ariel Manzur](https://github.com/punto-) (both still maintaining the project) for several
|
||||
Before being open sourced in February 2014, Godot had been developed by Juan
|
||||
Linietsky and Ariel Manzur (both still maintaining the project) for several
|
||||
years as an in-house engine, used to publish several work-for-hire titles.
|
||||
|
||||

|
||||
### Getting the engine
|
||||
|
||||
## Getting the engine
|
||||
|
||||
### Binary downloads
|
||||
#### Binary downloads
|
||||
|
||||
Official binaries for the Godot editor and the export templates can be found
|
||||
[on the homepage](https://godotengine.org/download).
|
||||
|
||||
### Compiling from source
|
||||
#### Compiling from source
|
||||
|
||||
[See the official docs](https://docs.godotengine.org/en/latest/contributing/development/compiling)
|
||||
[See the official docs](http://docs.godotengine.org/en/latest/reference/_compiling.html)
|
||||
for compilation instructions for every supported platform.
|
||||
|
||||
## Community and contributing
|
||||
### Community
|
||||
|
||||
Godot is not only an engine but an ever-growing community of users and engine
|
||||
developers. The main community channels are listed [on the homepage](https://godotengine.org/community).
|
||||
|
||||
The best way to get in touch with the core engine developers is to join the
|
||||
[Godot Contributors Chat](https://chat.godotengine.org).
|
||||
To get in touch with the developers, the best way is to join the
|
||||
[#godotengine IRC channel](https://webchat.freenode.net/?channels=godotengine)
|
||||
on Freenode.
|
||||
|
||||
To get started contributing to the project, see the [contributing guide](CONTRIBUTING.md).
|
||||
### Documentation and demos
|
||||
|
||||
## Documentation and demos
|
||||
|
||||
The official documentation is hosted on [Read the Docs](https://docs.godotengine.org).
|
||||
The official documentation is hosted on [ReadTheDocs](http://docs.godotengine.org).
|
||||
It is maintained by the Godot community in its own [GitHub repository](https://github.com/godotengine/godot-docs).
|
||||
|
||||
The [class reference](https://docs.godotengine.org/en/latest/classes/)
|
||||
is also accessible from the Godot editor.
|
||||
The [class reference](http://docs.godotengine.org/en/latest/classes/_classes.html)
|
||||
is also accessible from within the engine.
|
||||
|
||||
We also maintain official demos in their own [GitHub repository](https://github.com/godotengine/godot-demo-projects)
|
||||
as well as a list of [awesome Godot community resources](https://github.com/godotengine/awesome-godot).
|
||||
The official demos are maintained in their own [GitHub repository](https://github.com/godotengine/godot-demo-projects)
|
||||
as well.
|
||||
|
||||
There are also a number of other
|
||||
[learning resources](https://docs.godotengine.org/en/latest/community/tutorials.html)
|
||||
provided by the community, such as text and video tutorials, demos, etc.
|
||||
Consult the [community channels](https://godotengine.org/community)
|
||||
for more information.
|
||||
There are also a number of other learning resources provided by the community,
|
||||
such as text and video tutorials, demos, etc. Consult the [community channels](https://godotengine.org/community)
|
||||
for more info.
|
||||
|
||||
[](https://www.codetriage.com/godotengine/godot)
|
||||
[](https://hosted.weblate.org/engage/godot-engine/?utm_source=widget)
|
||||
[](https://www.tickgit.com/browse?repo=github.com/godotengine/godot)
|
||||
[](https://travis-ci.org/godotengine/godot)
|
||||
[](http://www.codetriage.com/godotengine/godot)
|
||||
|
||||
1165
SConstruct
1165
SConstruct
File diff suppressed because it is too large
Load Diff
229
core/SCsub
229
core/SCsub
@ -1,207 +1,68 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
import core_builders
|
||||
Import('env')
|
||||
|
||||
env.core_sources = []
|
||||
|
||||
|
||||
# Generate AES256 script encryption key
|
||||
import os
|
||||
gd_call = ""
|
||||
gd_inc = ""
|
||||
|
||||
for x in env.global_defaults:
|
||||
env.core_sources.append("#platform/" + x + "/globals/global_defaults.cpp")
|
||||
gd_inc += '#include "platform/' + x + '/globals/global_defaults.h"\n'
|
||||
gd_call += "\tregister_" + x + "_global_defaults();\n"
|
||||
|
||||
gd_cpp = '#include "globals.h"\n'
|
||||
gd_cpp += gd_inc
|
||||
gd_cpp += "void Globals::register_global_defaults() {\n" + gd_call + "\n}\n"
|
||||
|
||||
f = open("global_defaults.cpp", "wb")
|
||||
f.write(gd_cpp)
|
||||
f.close()
|
||||
|
||||
import os
|
||||
txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0"
|
||||
if "SCRIPT_AES256_ENCRYPTION_KEY" in os.environ:
|
||||
key = os.environ["SCRIPT_AES256_ENCRYPTION_KEY"]
|
||||
if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ):
|
||||
e = os.environ["SCRIPT_AES256_ENCRYPTION_KEY"]
|
||||
txt = ""
|
||||
ec_valid = True
|
||||
if len(key) != 64:
|
||||
if (len(e) != 64):
|
||||
ec_valid = False
|
||||
else:
|
||||
txt = ""
|
||||
for i in range(len(key) >> 1):
|
||||
if i > 0:
|
||||
|
||||
for i in range(len(e) >> 1):
|
||||
if (i > 0):
|
||||
txt += ","
|
||||
txts = "0x" + key[i * 2 : i * 2 + 2]
|
||||
txts = "0x" + e[i * 2:i * 2 + 2]
|
||||
try:
|
||||
int(txts, 16)
|
||||
except Exception:
|
||||
except:
|
||||
ec_valid = False
|
||||
txt += txts
|
||||
if not ec_valid:
|
||||
print("Error: Invalid AES256 encryption key, not 64 hexadecimal characters: '" + key + "'.")
|
||||
print(
|
||||
"Unset 'SCRIPT_AES256_ENCRYPTION_KEY' in your environment "
|
||||
"or make sure that it contains exactly 64 hexadecimal characters."
|
||||
)
|
||||
Exit(255)
|
||||
if (not ec_valid):
|
||||
txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0"
|
||||
print("Invalid AES256 encryption key, not 64 bits hex: " + e)
|
||||
|
||||
# NOTE: It is safe to generate this file here, since this is still executed serially
|
||||
with open("script_encryption_key.gen.cpp", "w") as f:
|
||||
f.write('#include "core/config/project_settings.h"\nuint8_t script_encryption_key[32]={' + txt + "};\n")
|
||||
f = open("script_encryption_key.cpp", "wb")
|
||||
f.write("#include \"globals.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
|
||||
f.close()
|
||||
|
||||
|
||||
# Add required thirdparty code.
|
||||
|
||||
thirdparty_obj = []
|
||||
|
||||
env_thirdparty = env.Clone()
|
||||
env_thirdparty.disable_warnings()
|
||||
|
||||
# Misc thirdparty code: header paths are hardcoded, we don't need to append
|
||||
# to the include path (saves a few chars on the compiler invocation for touchy MSVC...)
|
||||
thirdparty_misc_dir = "#thirdparty/misc/"
|
||||
thirdparty_misc_sources = [
|
||||
# C sources
|
||||
"fastlz.c",
|
||||
"r128.c",
|
||||
"smaz.c",
|
||||
# C++ sources
|
||||
"pcg.cpp",
|
||||
"polypartition.cpp",
|
||||
"clipper.cpp",
|
||||
"smolv.cpp",
|
||||
]
|
||||
thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_misc_sources]
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_misc_sources)
|
||||
|
||||
# Zlib library, can be unbundled
|
||||
if env["builtin_zlib"]:
|
||||
thirdparty_zlib_dir = "#thirdparty/zlib/"
|
||||
thirdparty_zlib_sources = [
|
||||
"adler32.c",
|
||||
"compress.c",
|
||||
"crc32.c",
|
||||
"deflate.c",
|
||||
"infback.c",
|
||||
"inffast.c",
|
||||
"inflate.c",
|
||||
"inftrees.c",
|
||||
"trees.c",
|
||||
"uncompr.c",
|
||||
"zutil.c",
|
||||
]
|
||||
thirdparty_zlib_sources = [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]
|
||||
|
||||
env_thirdparty.Prepend(CPPPATH=[thirdparty_zlib_dir])
|
||||
# Needs to be available in main env too
|
||||
env.Prepend(CPPPATH=[thirdparty_zlib_dir])
|
||||
if env.dev_build:
|
||||
env_thirdparty.Append(CPPDEFINES=["ZLIB_DEBUG"])
|
||||
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_zlib_sources)
|
||||
|
||||
# Minizip library, could be unbundled in theory
|
||||
# However, our version has some custom modifications, so it won't compile with the system one
|
||||
thirdparty_minizip_dir = "#thirdparty/minizip/"
|
||||
thirdparty_minizip_sources = ["ioapi.c", "unzip.c", "zip.c"]
|
||||
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_minizip_sources)
|
||||
|
||||
# Zstd library, can be unbundled in theory
|
||||
# though we currently use some private symbols
|
||||
# https://github.com/godotengine/godot/issues/17374
|
||||
if env["builtin_zstd"]:
|
||||
thirdparty_zstd_dir = "#thirdparty/zstd/"
|
||||
thirdparty_zstd_sources = [
|
||||
"common/debug.c",
|
||||
"common/entropy_common.c",
|
||||
"common/error_private.c",
|
||||
"common/fse_decompress.c",
|
||||
"common/pool.c",
|
||||
"common/threading.c",
|
||||
"common/xxhash.c",
|
||||
"common/zstd_common.c",
|
||||
"compress/fse_compress.c",
|
||||
"compress/hist.c",
|
||||
"compress/huf_compress.c",
|
||||
"compress/zstd_compress.c",
|
||||
"compress/zstd_double_fast.c",
|
||||
"compress/zstd_fast.c",
|
||||
"compress/zstd_lazy.c",
|
||||
"compress/zstd_ldm.c",
|
||||
"compress/zstd_opt.c",
|
||||
"compress/zstdmt_compress.c",
|
||||
"compress/zstd_compress_literals.c",
|
||||
"compress/zstd_compress_sequences.c",
|
||||
"compress/zstd_compress_superblock.c",
|
||||
"decompress/huf_decompress.c",
|
||||
"decompress/zstd_ddict.c",
|
||||
"decompress/zstd_decompress_block.c",
|
||||
"decompress/zstd_decompress.c",
|
||||
]
|
||||
if env["platform"] in ["android", "ios", "linuxbsd", "macos"]:
|
||||
# Match platforms with ZSTD_ASM_SUPPORTED in common/portability_macros.h
|
||||
thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S")
|
||||
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
|
||||
|
||||
env_thirdparty.Prepend(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
|
||||
env_thirdparty.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
|
||||
env.Prepend(CPPPATH=thirdparty_zstd_dir)
|
||||
# Also needed in main env includes will trigger warnings
|
||||
env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
|
||||
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_zstd_sources)
|
||||
|
||||
|
||||
env.core_sources += thirdparty_obj
|
||||
|
||||
|
||||
# Godot source files
|
||||
|
||||
env.add_source_files(env.core_sources, "*.cpp")
|
||||
env.add_source_files(env.core_sources, "script_encryption_key.gen.cpp")
|
||||
env.add_source_files(env.core_sources, "version_hash.gen.cpp")
|
||||
|
||||
# Certificates
|
||||
env.Depends(
|
||||
"#core/io/certs_compressed.gen.h",
|
||||
["#thirdparty/certs/ca-certificates.crt", env.Value(env["builtin_certs"]), env.Value(env["system_certs_path"])],
|
||||
)
|
||||
env.CommandNoCache(
|
||||
"#core/io/certs_compressed.gen.h",
|
||||
"#thirdparty/certs/ca-certificates.crt",
|
||||
env.Run(core_builders.make_certs_header, "Building ca-certificates header."),
|
||||
)
|
||||
|
||||
# Authors
|
||||
env.Depends("#core/authors.gen.h", "../AUTHORS.md")
|
||||
env.CommandNoCache(
|
||||
"#core/authors.gen.h", "../AUTHORS.md", env.Run(core_builders.make_authors_header, "Generating authors header.")
|
||||
)
|
||||
|
||||
# Donors
|
||||
env.Depends("#core/donors.gen.h", "../DONORS.md")
|
||||
env.CommandNoCache(
|
||||
"#core/donors.gen.h", "../DONORS.md", env.Run(core_builders.make_donors_header, "Generating donors header.")
|
||||
)
|
||||
|
||||
# License
|
||||
env.Depends("#core/license.gen.h", ["../COPYRIGHT.txt", "../LICENSE.txt"])
|
||||
env.CommandNoCache(
|
||||
"#core/license.gen.h",
|
||||
["../COPYRIGHT.txt", "../LICENSE.txt"],
|
||||
env.Run(core_builders.make_license_header, "Generating license header."),
|
||||
)
|
||||
|
||||
# Chain load SCsubs
|
||||
SConscript("os/SCsub")
|
||||
SConscript("math/SCsub")
|
||||
SConscript("crypto/SCsub")
|
||||
SConscript("io/SCsub")
|
||||
SConscript("debugger/SCsub")
|
||||
SConscript("input/SCsub")
|
||||
SConscript("variant/SCsub")
|
||||
SConscript("extension/SCsub")
|
||||
SConscript("object/SCsub")
|
||||
SConscript("templates/SCsub")
|
||||
SConscript("string/SCsub")
|
||||
SConscript("config/SCsub")
|
||||
SConscript("error/SCsub")
|
||||
|
||||
|
||||
# Build it all as a library
|
||||
lib = env.add_library("core", env.core_sources)
|
||||
Export('env')
|
||||
|
||||
import make_binders
|
||||
env.Command(['method_bind.inc', 'method_bind_ext.inc'], 'make_binders.py', make_binders.run)
|
||||
|
||||
SConscript('os/SCsub')
|
||||
SConscript('math/SCsub')
|
||||
SConscript('io/SCsub')
|
||||
SConscript('bind/SCsub')
|
||||
SConscript('helper/SCsub')
|
||||
|
||||
lib = env.Library("core", env.core_sources)
|
||||
|
||||
env.Prepend(LIBS=[lib])
|
||||
|
||||
# Needed to force rebuilding the core files when the thirdparty code is updated.
|
||||
env.Depends(lib, thirdparty_obj)
|
||||
|
||||
193
core/allocators.h
Normal file
193
core/allocators.h
Normal file
@ -0,0 +1,193 @@
|
||||
/*************************************************************************/
|
||||
/* allocators.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 ALLOCATORS_H
|
||||
#define ALLOCATORS_H
|
||||
|
||||
#include "os/memory.h"
|
||||
template <int PREALLOC_COUNT = 64, int MAX_HANDS = 8>
|
||||
class BalloonAllocator {
|
||||
|
||||
enum {
|
||||
|
||||
USED_FLAG = (1 << 30),
|
||||
USED_MASK = USED_FLAG - 1
|
||||
};
|
||||
|
||||
struct Balloon {
|
||||
|
||||
Balloon *next;
|
||||
Balloon *prev;
|
||||
uint32_t hand;
|
||||
};
|
||||
|
||||
struct Hand {
|
||||
|
||||
int used;
|
||||
int allocated;
|
||||
Balloon *first;
|
||||
Balloon *last;
|
||||
};
|
||||
|
||||
Hand hands[MAX_HANDS];
|
||||
|
||||
public:
|
||||
void *alloc(size_t p_size) {
|
||||
|
||||
size_t max = (1 << MAX_HANDS);
|
||||
ERR_FAIL_COND_V(p_size > max, NULL);
|
||||
|
||||
unsigned int hand = 0;
|
||||
|
||||
while (p_size > (size_t)(1 << hand))
|
||||
++hand;
|
||||
|
||||
Hand &h = hands[hand];
|
||||
|
||||
if (h.used == h.allocated) {
|
||||
|
||||
for (int i = 0; i < PREALLOC_COUNT; i++) {
|
||||
|
||||
Balloon *b = (Balloon *)memalloc(sizeof(Balloon) + (1 << hand));
|
||||
b->hand = hand;
|
||||
if (h.last) {
|
||||
|
||||
b->prev = h.last;
|
||||
h.last->next = b;
|
||||
h.last = b;
|
||||
} else {
|
||||
|
||||
b->prev = NULL;
|
||||
h.last = b;
|
||||
h.first = b;
|
||||
}
|
||||
}
|
||||
|
||||
h.last->next = NULL;
|
||||
h.allocated += PREALLOC_COUNT;
|
||||
}
|
||||
|
||||
Balloon *pick = h.last;
|
||||
|
||||
ERR_FAIL_COND_V((pick->hand & USED_FLAG), NULL);
|
||||
|
||||
// remove last
|
||||
h.last = h.last->prev;
|
||||
h.last->next = NULL;
|
||||
|
||||
pick->next = h.first;
|
||||
h.first->prev = pick;
|
||||
pick->prev = NULL;
|
||||
h.first = pick;
|
||||
h.used++;
|
||||
pick->hand |= USED_FLAG;
|
||||
|
||||
return (void *)(pick + 1);
|
||||
}
|
||||
|
||||
void free(void *p_ptr) {
|
||||
|
||||
Balloon *b = (Balloon *)p_ptr;
|
||||
b -= 1;
|
||||
|
||||
ERR_FAIL_COND(!(b->hand & USED_FLAG));
|
||||
|
||||
b->hand = b->hand & USED_MASK; // not used
|
||||
int hand = b->hand;
|
||||
|
||||
Hand &h = hands[hand];
|
||||
|
||||
if (b == h.first)
|
||||
h.first = b->next;
|
||||
|
||||
if (b->prev)
|
||||
b->prev->next = b->next;
|
||||
if (b->next)
|
||||
b->next->prev = b->prev;
|
||||
|
||||
if (h.last != b) {
|
||||
h.last->next = b;
|
||||
b->prev = h.last;
|
||||
b->next = NULL;
|
||||
h.last = b;
|
||||
}
|
||||
|
||||
h.used--;
|
||||
|
||||
if (h.used <= (h.allocated - (PREALLOC_COUNT * 2))) { // this is done to ensure no alloc/free is done constantly
|
||||
|
||||
for (int i = 0; i < PREALLOC_COUNT; i++) {
|
||||
ERR_CONTINUE(h.last->hand & USED_FLAG);
|
||||
|
||||
Balloon *new_last = h.last->prev;
|
||||
if (new_last)
|
||||
new_last->next = NULL;
|
||||
memfree(h.last);
|
||||
h.last = new_last;
|
||||
}
|
||||
h.allocated -= PREALLOC_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
BalloonAllocator() {
|
||||
|
||||
for (int i = 0; i < MAX_HANDS; i++) {
|
||||
|
||||
hands[i].allocated = 0;
|
||||
hands[i].used = 0;
|
||||
hands[i].first = NULL;
|
||||
hands[i].last = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
|
||||
for (int i = 0; i < MAX_HANDS; i++) {
|
||||
|
||||
while (hands[i].first) {
|
||||
|
||||
Balloon *b = hands[i].first;
|
||||
hands[i].first = b->next;
|
||||
memfree(b);
|
||||
}
|
||||
|
||||
hands[i].allocated = 0;
|
||||
hands[i].used = 0;
|
||||
hands[i].first = NULL;
|
||||
hands[i].last = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
~BalloonAllocator() {
|
||||
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ALLOCATORS_H
|
||||
308
core/array.cpp
Normal file
308
core/array.cpp
Normal file
@ -0,0 +1,308 @@
|
||||
/*************************************************************************/
|
||||
/* array.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "array.h"
|
||||
#include "hashfuncs.h"
|
||||
#include "object.h"
|
||||
#include "variant.h"
|
||||
#include "vector.h"
|
||||
|
||||
struct ArrayPrivate {
|
||||
|
||||
SafeRefCount refcount;
|
||||
Vector<Variant> array;
|
||||
bool shared;
|
||||
};
|
||||
|
||||
void Array::_ref(const Array &p_from) const {
|
||||
|
||||
ArrayPrivate *_fp = p_from._p;
|
||||
|
||||
ERR_FAIL_COND(!_fp); // should NOT happen.
|
||||
|
||||
if (_fp == _p)
|
||||
return; //wathever it is, nothing to do here move along
|
||||
|
||||
bool success = _fp->refcount.ref();
|
||||
|
||||
ERR_FAIL_COND(!success); //should really not happen either
|
||||
|
||||
_unref();
|
||||
|
||||
if (_fp->shared) {
|
||||
|
||||
_p = p_from._p;
|
||||
|
||||
} else {
|
||||
|
||||
_p = memnew(ArrayPrivate);
|
||||
_p->shared = false;
|
||||
_p->refcount.init();
|
||||
_p->array = _fp->array;
|
||||
|
||||
if (_fp->refcount.unref())
|
||||
memdelete(_fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Array::_unref() const {
|
||||
|
||||
if (!_p)
|
||||
return;
|
||||
|
||||
if (_p->refcount.unref()) {
|
||||
memdelete(_p);
|
||||
}
|
||||
_p = NULL;
|
||||
}
|
||||
|
||||
Variant &Array::operator[](int p_idx) {
|
||||
|
||||
return _p->array[p_idx];
|
||||
}
|
||||
|
||||
const Variant &Array::operator[](int p_idx) const {
|
||||
|
||||
return _p->array[p_idx];
|
||||
}
|
||||
|
||||
int Array::size() const {
|
||||
|
||||
return _p->array.size();
|
||||
}
|
||||
bool Array::empty() const {
|
||||
|
||||
return _p->array.empty();
|
||||
}
|
||||
void Array::clear() {
|
||||
|
||||
_p->array.clear();
|
||||
}
|
||||
|
||||
bool Array::is_shared() const {
|
||||
|
||||
return _p->shared;
|
||||
}
|
||||
|
||||
bool Array::operator==(const Array &p_array) const {
|
||||
|
||||
return _p == p_array._p;
|
||||
}
|
||||
|
||||
uint32_t Array::hash() const {
|
||||
|
||||
uint32_t h = hash_djb2_one_32(0);
|
||||
|
||||
for (int i = 0; i < _p->array.size(); i++) {
|
||||
|
||||
h = hash_djb2_one_32(_p->array[i].hash(), h);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
void Array::operator=(const Array &p_array) {
|
||||
|
||||
_ref(p_array);
|
||||
}
|
||||
void Array::push_back(const Variant &p_value) {
|
||||
|
||||
_p->array.push_back(p_value);
|
||||
}
|
||||
|
||||
Error Array::resize(int p_new_size) {
|
||||
|
||||
return _p->array.resize(p_new_size);
|
||||
}
|
||||
|
||||
void Array::insert(int p_pos, const Variant &p_value) {
|
||||
|
||||
_p->array.insert(p_pos, p_value);
|
||||
}
|
||||
|
||||
void Array::erase(const Variant &p_value) {
|
||||
|
||||
_p->array.erase(p_value);
|
||||
}
|
||||
|
||||
Variant Array::front() const {
|
||||
ERR_FAIL_COND_V(_p->array.size() == 0, Variant());
|
||||
return operator[](0);
|
||||
}
|
||||
|
||||
Variant Array::back() const {
|
||||
ERR_FAIL_COND_V(_p->array.size() == 0, Variant());
|
||||
return operator[](_p->array.size() - 1);
|
||||
}
|
||||
|
||||
int Array::find(const Variant &p_value, int p_from) const {
|
||||
|
||||
return _p->array.find(p_value, p_from);
|
||||
}
|
||||
|
||||
int Array::rfind(const Variant &p_value, int p_from) const {
|
||||
|
||||
if (_p->array.size() == 0)
|
||||
return -1;
|
||||
|
||||
if (p_from < 0) {
|
||||
// Relative offset from the end
|
||||
p_from = _p->array.size() + p_from;
|
||||
}
|
||||
if (p_from < 0 || p_from >= _p->array.size()) {
|
||||
// Limit to array boundaries
|
||||
p_from = _p->array.size() - 1;
|
||||
}
|
||||
|
||||
for (int i = p_from; i >= 0; i--) {
|
||||
|
||||
if (_p->array[i] == p_value) {
|
||||
return i;
|
||||
};
|
||||
};
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Array::find_last(const Variant &p_value) const {
|
||||
|
||||
return rfind(p_value);
|
||||
}
|
||||
|
||||
int Array::count(const Variant &p_value) const {
|
||||
|
||||
if (_p->array.size() == 0)
|
||||
return 0;
|
||||
|
||||
int amount = 0;
|
||||
for (int i = 0; i < _p->array.size(); i++) {
|
||||
|
||||
if (_p->array[i] == p_value) {
|
||||
amount++;
|
||||
};
|
||||
};
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
bool Array::has(const Variant &p_value) const {
|
||||
return _p->array.find(p_value, 0) != -1;
|
||||
}
|
||||
|
||||
void Array::remove(int p_pos) {
|
||||
|
||||
_p->array.remove(p_pos);
|
||||
}
|
||||
|
||||
void Array::set(int p_idx, const Variant &p_value) {
|
||||
|
||||
operator[](p_idx) = p_value;
|
||||
}
|
||||
|
||||
const Variant &Array::get(int p_idx) const {
|
||||
|
||||
return operator[](p_idx);
|
||||
}
|
||||
|
||||
struct _ArrayVariantSort {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
|
||||
bool valid = false;
|
||||
Variant res;
|
||||
Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
|
||||
if (!valid)
|
||||
res = false;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
void Array::sort() {
|
||||
|
||||
_p->array.sort_custom<_ArrayVariantSort>();
|
||||
}
|
||||
|
||||
struct _ArrayVariantSortCustom {
|
||||
|
||||
Object *obj;
|
||||
StringName func;
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
|
||||
|
||||
const Variant *args[2] = { &p_l, &p_r };
|
||||
Variant::CallError err;
|
||||
bool res = obj->call(func, args, 2, err);
|
||||
if (err.error != Variant::CallError::CALL_OK)
|
||||
res = false;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
void Array::sort_custom(Object *p_obj, const StringName &p_function) {
|
||||
|
||||
ERR_FAIL_NULL(p_obj);
|
||||
|
||||
SortArray<Variant, _ArrayVariantSortCustom> avs;
|
||||
avs.compare.obj = p_obj;
|
||||
avs.compare.func = p_function;
|
||||
avs.sort(_p->array.ptr(), _p->array.size());
|
||||
}
|
||||
|
||||
void Array::invert() {
|
||||
|
||||
_p->array.invert();
|
||||
}
|
||||
|
||||
void Array::push_front(const Variant &p_value) {
|
||||
|
||||
_p->array.insert(0, p_value);
|
||||
}
|
||||
|
||||
void Array::pop_back() {
|
||||
|
||||
if (!_p->array.empty())
|
||||
_p->array.resize(_p->array.size() - 1);
|
||||
}
|
||||
void Array::pop_front() {
|
||||
|
||||
if (!_p->array.empty())
|
||||
_p->array.remove(0);
|
||||
}
|
||||
|
||||
Array::Array(const Array &p_from) {
|
||||
|
||||
_p = NULL;
|
||||
_ref(p_from);
|
||||
}
|
||||
Array::Array(bool p_shared) {
|
||||
|
||||
_p = memnew(ArrayPrivate);
|
||||
_p->refcount.init();
|
||||
_p->shared = p_shared;
|
||||
}
|
||||
Array::~Array() {
|
||||
|
||||
_unref();
|
||||
}
|
||||
94
core/array.h
Normal file
94
core/array.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*************************************************************************/
|
||||
/* array.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 ARRAY_H
|
||||
#define ARRAY_H
|
||||
|
||||
#include "typedefs.h"
|
||||
class Variant;
|
||||
class ArrayPrivate;
|
||||
class Object;
|
||||
class StringName;
|
||||
|
||||
class Array {
|
||||
|
||||
mutable ArrayPrivate *_p;
|
||||
void _ref(const Array &p_from) const;
|
||||
void _unref() const;
|
||||
|
||||
public:
|
||||
Variant &operator[](int p_idx);
|
||||
const Variant &operator[](int p_idx) const;
|
||||
|
||||
void set(int p_idx, const Variant &p_value);
|
||||
const Variant &get(int p_idx) const;
|
||||
|
||||
int size() const;
|
||||
bool empty() const;
|
||||
void clear();
|
||||
|
||||
bool is_shared() const;
|
||||
|
||||
bool operator==(const Array &p_array) const;
|
||||
|
||||
uint32_t hash() const;
|
||||
void operator=(const Array &p_array);
|
||||
|
||||
void push_back(const Variant &p_value);
|
||||
_FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility
|
||||
Error resize(int p_new_size);
|
||||
|
||||
void insert(int p_pos, const Variant &p_value);
|
||||
void remove(int p_pos);
|
||||
|
||||
Variant front() const;
|
||||
Variant back() const;
|
||||
|
||||
void sort();
|
||||
void sort_custom(Object *p_obj, const StringName &p_function);
|
||||
void invert();
|
||||
|
||||
int find(const Variant &p_value, int p_from = 0) const;
|
||||
int rfind(const Variant &p_value, int p_from = -1) const;
|
||||
int find_last(const Variant &p_value) const;
|
||||
int count(const Variant &p_value) const;
|
||||
bool has(const Variant &p_value) const;
|
||||
|
||||
void erase(const Variant &p_value);
|
||||
|
||||
void push_front(const Variant &p_value);
|
||||
void pop_back();
|
||||
void pop_front();
|
||||
|
||||
Array(const Array &p_from);
|
||||
Array(bool p_shared = false);
|
||||
~Array();
|
||||
};
|
||||
|
||||
#endif // ARRAY_H
|
||||
7
core/bind/SCsub
Normal file
7
core/bind/SCsub
Normal file
@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.core_sources, "*.cpp")
|
||||
|
||||
Export('env')
|
||||
2300
core/bind/core_bind.cpp
Normal file
2300
core/bind/core_bind.cpp
Normal file
File diff suppressed because it is too large
Load Diff
573
core/bind/core_bind.h
Normal file
573
core/bind/core_bind.h
Normal file
@ -0,0 +1,573 @@
|
||||
/*************************************************************************/
|
||||
/* core_bind.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 CORE_BIND_H
|
||||
#define CORE_BIND_H
|
||||
|
||||
#include "io/resource_loader.h"
|
||||
#include "io/resource_saver.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/file_access.h"
|
||||
#include "os/semaphore.h"
|
||||
#include "os/thread.h"
|
||||
|
||||
class _ResourceLoader : public Object {
|
||||
OBJ_TYPE(_ResourceLoader, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _ResourceLoader *singleton;
|
||||
|
||||
public:
|
||||
static _ResourceLoader *get_singleton() { return singleton; }
|
||||
Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "");
|
||||
RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false);
|
||||
DVector<String> get_recognized_extensions_for_type(const String &p_type);
|
||||
void set_abort_on_missing_resources(bool p_abort);
|
||||
StringArray get_dependencies(const String &p_path);
|
||||
bool has(const String &p_path);
|
||||
Ref<ResourceImportMetadata> load_import_metadata(const String &p_path);
|
||||
|
||||
_ResourceLoader();
|
||||
};
|
||||
|
||||
class _ResourceSaver : public Object {
|
||||
OBJ_TYPE(_ResourceSaver, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _ResourceSaver *singleton;
|
||||
|
||||
public:
|
||||
enum SaverFlags {
|
||||
|
||||
FLAG_RELATIVE_PATHS = 1,
|
||||
FLAG_BUNDLE_RESOURCES = 2,
|
||||
FLAG_CHANGE_PATH = 4,
|
||||
FLAG_OMIT_EDITOR_PROPERTIES = 8,
|
||||
FLAG_SAVE_BIG_ENDIAN = 16,
|
||||
FLAG_COMPRESS = 32,
|
||||
};
|
||||
|
||||
static _ResourceSaver *get_singleton() { return singleton; }
|
||||
|
||||
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags);
|
||||
DVector<String> get_recognized_extensions(const RES &p_resource);
|
||||
|
||||
_ResourceSaver();
|
||||
};
|
||||
|
||||
class MainLoop;
|
||||
|
||||
class _OS : public Object {
|
||||
OBJ_TYPE(_OS, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _OS *singleton;
|
||||
|
||||
public:
|
||||
enum Weekday {
|
||||
DAY_SUNDAY,
|
||||
DAY_MONDAY,
|
||||
DAY_TUESDAY,
|
||||
DAY_WEDNESDAY,
|
||||
DAY_THURSDAY,
|
||||
DAY_FRIDAY,
|
||||
DAY_SATURDAY
|
||||
};
|
||||
|
||||
enum Month {
|
||||
/// Start at 1 to follow Windows SYSTEMTIME structure
|
||||
/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
|
||||
MONTH_JANUARY = 1,
|
||||
MONTH_FEBRUARY,
|
||||
MONTH_MARCH,
|
||||
MONTH_APRIL,
|
||||
MONTH_MAY,
|
||||
MONTH_JUNE,
|
||||
MONTH_JULY,
|
||||
MONTH_AUGUST,
|
||||
MONTH_SEPTEMBER,
|
||||
MONTH_OCTOBER,
|
||||
MONTH_NOVEMBER,
|
||||
MONTH_DECEMBER
|
||||
};
|
||||
|
||||
Point2 get_mouse_pos() const;
|
||||
void set_window_title(const String &p_title);
|
||||
int get_mouse_button_state() const;
|
||||
|
||||
void set_clipboard(const String &p_text);
|
||||
String get_clipboard() const;
|
||||
|
||||
void set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen = 0);
|
||||
Size2 get_video_mode(int p_screen = 0) const;
|
||||
bool is_video_mode_fullscreen(int p_screen = 0) const;
|
||||
bool is_video_mode_resizable(int p_screen = 0) const;
|
||||
Array get_fullscreen_mode_list(int p_screen = 0) const;
|
||||
|
||||
virtual int get_screen_count() const;
|
||||
virtual int get_current_screen() const;
|
||||
virtual void set_current_screen(int p_screen);
|
||||
virtual Point2 get_screen_position(int p_screen = 0) const;
|
||||
virtual Size2 get_screen_size(int p_screen = 0) const;
|
||||
virtual int get_screen_dpi(int p_screen = 0) const;
|
||||
virtual Point2 get_window_position() const;
|
||||
virtual void set_window_position(const Point2 &p_position);
|
||||
virtual Size2 get_window_size() const;
|
||||
virtual void set_window_size(const Size2 &p_size);
|
||||
virtual void set_window_fullscreen(bool p_enabled);
|
||||
virtual bool is_window_fullscreen() const;
|
||||
virtual void set_window_resizable(bool p_enabled);
|
||||
virtual bool is_window_resizable() const;
|
||||
virtual void set_window_minimized(bool p_enabled);
|
||||
virtual bool is_window_minimized() const;
|
||||
virtual void set_window_maximized(bool p_enabled);
|
||||
virtual bool is_window_maximized() const;
|
||||
virtual void request_attention();
|
||||
|
||||
virtual void set_borderless_window(bool p_borderless);
|
||||
virtual bool get_borderless_window() const;
|
||||
|
||||
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
|
||||
bool native_video_is_playing();
|
||||
void native_video_pause();
|
||||
void native_video_unpause();
|
||||
void native_video_stop();
|
||||
|
||||
void set_iterations_per_second(int p_ips);
|
||||
int get_iterations_per_second() const;
|
||||
|
||||
void set_target_fps(int p_fps);
|
||||
float get_target_fps() const;
|
||||
|
||||
void set_low_processor_usage_mode(bool p_enabled);
|
||||
bool is_in_low_processor_usage_mode() const;
|
||||
|
||||
String get_executable_path() const;
|
||||
int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output = Array());
|
||||
|
||||
Error kill(int p_pid);
|
||||
Error shell_open(String p_uri);
|
||||
|
||||
int get_process_ID() const;
|
||||
|
||||
bool has_environment(const String &p_var) const;
|
||||
String get_environment(const String &p_var) const;
|
||||
|
||||
String get_name() const;
|
||||
Vector<String> get_cmdline_args();
|
||||
|
||||
String get_locale() const;
|
||||
String get_latin_keyboard_variant() const;
|
||||
|
||||
String get_model_name() const;
|
||||
MainLoop *get_main_loop() const;
|
||||
|
||||
String get_custom_level() const;
|
||||
|
||||
float get_frames_per_second() const;
|
||||
|
||||
void dump_memory_to_file(const String &p_file);
|
||||
void dump_resources_to_file(const String &p_file);
|
||||
|
||||
bool has_virtual_keyboard() const;
|
||||
void show_virtual_keyboard(const String &p_existing_text = "");
|
||||
void hide_virtual_keyboard();
|
||||
|
||||
void print_resources_in_use(bool p_short = false);
|
||||
void print_all_resources(const String &p_to_file);
|
||||
void print_all_textures_by_size();
|
||||
void print_resources_by_type(const Vector<String> &p_types);
|
||||
|
||||
bool has_touchscreen_ui_hint() const;
|
||||
|
||||
bool is_debug_build() const;
|
||||
|
||||
String get_unique_ID() const;
|
||||
|
||||
String get_scancode_string(uint32_t p_code) const;
|
||||
bool is_scancode_unicode(uint32_t p_unicode) const;
|
||||
int find_scancode_from_string(const String &p_code) const;
|
||||
|
||||
/*
|
||||
struct Date {
|
||||
|
||||
int year;
|
||||
Month month;
|
||||
int day;
|
||||
Weekday weekday;
|
||||
bool dst;
|
||||
};
|
||||
|
||||
struct Time {
|
||||
|
||||
int hour;
|
||||
int min;
|
||||
int sec;
|
||||
};
|
||||
*/
|
||||
|
||||
void set_use_file_access_save_and_swap(bool p_enable);
|
||||
|
||||
void set_icon(const Image &p_icon);
|
||||
|
||||
int get_exit_code() const;
|
||||
void set_exit_code(int p_code);
|
||||
Dictionary get_date(bool utc) const;
|
||||
Dictionary get_time(bool utc) const;
|
||||
Dictionary get_datetime(bool utc) const;
|
||||
Dictionary get_datetime_from_unix_time(uint64_t unix_time_val) const;
|
||||
uint64_t get_unix_time_from_datetime(Dictionary datetime) const;
|
||||
Dictionary get_time_zone_info() const;
|
||||
uint64_t get_unix_time() const;
|
||||
uint64_t get_system_time_secs() const;
|
||||
|
||||
int get_static_memory_usage() const;
|
||||
int get_static_memory_peak_usage() const;
|
||||
int get_dynamic_memory_usage() const;
|
||||
|
||||
void delay_usec(uint32_t p_usec) const;
|
||||
void delay_msec(uint32_t p_msec) const;
|
||||
uint32_t get_ticks_msec() const;
|
||||
uint32_t get_splash_tick_msec() const;
|
||||
|
||||
bool can_use_threads() const;
|
||||
|
||||
bool can_draw() const;
|
||||
|
||||
int get_frames_drawn();
|
||||
|
||||
bool is_stdout_verbose() const;
|
||||
|
||||
int get_processor_count() const;
|
||||
|
||||
enum SystemDir {
|
||||
SYSTEM_DIR_DESKTOP,
|
||||
SYSTEM_DIR_DCIM,
|
||||
SYSTEM_DIR_DOCUMENTS,
|
||||
SYSTEM_DIR_DOWNLOADS,
|
||||
SYSTEM_DIR_MOVIES,
|
||||
SYSTEM_DIR_MUSIC,
|
||||
SYSTEM_DIR_PICTURES,
|
||||
SYSTEM_DIR_RINGTONES,
|
||||
};
|
||||
|
||||
enum ScreenOrientation {
|
||||
|
||||
SCREEN_ORIENTATION_LANDSCAPE,
|
||||
SCREEN_ORIENTATION_PORTRAIT,
|
||||
SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
|
||||
SCREEN_ORIENTATION_REVERSE_PORTRAIT,
|
||||
SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
|
||||
SCREEN_ORIENTATION_SENSOR_PORTRAIT,
|
||||
SCREEN_ORIENTATION_SENSOR,
|
||||
};
|
||||
|
||||
String get_system_dir(SystemDir p_dir) const;
|
||||
|
||||
String get_data_dir() const;
|
||||
|
||||
void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
|
||||
void set_screen_orientation(ScreenOrientation p_orientation);
|
||||
ScreenOrientation get_screen_orientation() const;
|
||||
|
||||
void set_keep_screen_on(bool p_enabled);
|
||||
bool is_keep_screen_on() const;
|
||||
|
||||
void set_time_scale(float p_scale);
|
||||
float get_time_scale();
|
||||
|
||||
bool is_ok_left_and_cancel_right() const;
|
||||
|
||||
Error set_thread_name(const String &p_name);
|
||||
|
||||
void set_use_vsync(bool p_enable);
|
||||
bool is_vsync_enabled() const;
|
||||
|
||||
Dictionary get_engine_version() const;
|
||||
|
||||
static _OS *get_singleton() { return singleton; }
|
||||
|
||||
_OS();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_OS::SystemDir);
|
||||
VARIANT_ENUM_CAST(_OS::ScreenOrientation);
|
||||
|
||||
class _Geometry : public Object {
|
||||
|
||||
OBJ_TYPE(_Geometry, Object);
|
||||
|
||||
static _Geometry *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static _Geometry *get_singleton();
|
||||
DVector<Plane> build_box_planes(const Vector3 &p_extents);
|
||||
DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
|
||||
DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
|
||||
Variant segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
|
||||
DVector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
|
||||
DVector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
|
||||
Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
|
||||
Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
|
||||
Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
|
||||
Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
|
||||
Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
|
||||
Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
|
||||
bool point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const;
|
||||
|
||||
DVector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius);
|
||||
DVector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius);
|
||||
DVector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes);
|
||||
real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius);
|
||||
int get_uv84_normal_bit(const Vector3 &p_vector);
|
||||
|
||||
Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
|
||||
|
||||
Dictionary make_atlas(const Vector<Size2> &p_rects);
|
||||
|
||||
_Geometry();
|
||||
};
|
||||
|
||||
class _File : public Reference {
|
||||
|
||||
OBJ_TYPE(_File, Reference);
|
||||
FileAccess *f;
|
||||
bool eswap;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum ModeFlags {
|
||||
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
READ_WRITE = 3,
|
||||
WRITE_READ = 7,
|
||||
};
|
||||
|
||||
Error open_encrypted(const String &p_path, int p_mode_flags, const Vector<uint8_t> &p_key);
|
||||
Error open_encrypted_pass(const String &p_path, int p_mode_flags, const String &p_pass);
|
||||
|
||||
Error open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
void close(); ///< close a file
|
||||
bool is_open() const; ///< true when file is open
|
||||
|
||||
void seek(int64_t p_position); ///< seek to a given position
|
||||
void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
int64_t get_pos() const; ///< get position in the file
|
||||
int64_t get_len() const; ///< get size of the file
|
||||
|
||||
bool eof_reached() const; ///< reading passed EOF
|
||||
|
||||
uint8_t get_8() const; ///< get a byte
|
||||
uint16_t get_16() const; ///< get 16 bits uint
|
||||
uint32_t get_32() const; ///< get 32 bits uint
|
||||
uint64_t get_64() const; ///< get 64 bits uint
|
||||
|
||||
float get_float() const;
|
||||
double get_double() const;
|
||||
real_t get_real() const;
|
||||
|
||||
Variant get_var() const;
|
||||
|
||||
DVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
|
||||
String get_line() const;
|
||||
String get_as_text() const;
|
||||
String get_md5(const String &p_path) const;
|
||||
String get_sha256(const String &p_path) const;
|
||||
|
||||
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
|
||||
* It's not about the current CPU type but file formats.
|
||||
* this flags get reset to false (little endian) on each open
|
||||
*/
|
||||
|
||||
void set_endian_swap(bool p_swap);
|
||||
bool get_endian_swap();
|
||||
|
||||
Error get_error() const; ///< get last error
|
||||
|
||||
void store_8(uint8_t p_dest); ///< store a byte
|
||||
void store_16(uint16_t p_dest); ///< store 16 bits uint
|
||||
void store_32(uint32_t p_dest); ///< store 32 bits uint
|
||||
void store_64(uint64_t p_dest); ///< store 64 bits uint
|
||||
|
||||
void store_float(float p_dest);
|
||||
void store_double(double p_dest);
|
||||
void store_real(real_t p_real);
|
||||
|
||||
void store_string(const String &p_string);
|
||||
void store_line(const String &p_string);
|
||||
|
||||
virtual void store_pascal_string(const String &p_string);
|
||||
virtual String get_pascal_string();
|
||||
|
||||
Vector<String> get_csv_line(String delim = ",") const;
|
||||
|
||||
void store_buffer(const DVector<uint8_t> &p_buffer); ///< store an array of bytes
|
||||
|
||||
void store_var(const Variant &p_var);
|
||||
|
||||
bool file_exists(const String &p_name) const; ///< return true if a file exists
|
||||
|
||||
uint64_t get_modified_time(const String &p_file) const;
|
||||
|
||||
_File();
|
||||
virtual ~_File();
|
||||
};
|
||||
|
||||
class _Directory : public Reference {
|
||||
|
||||
OBJ_TYPE(_Directory, Reference);
|
||||
DirAccess *d;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Error open(const String &p_path);
|
||||
|
||||
bool list_dir_begin(); ///< This starts dir listing
|
||||
String get_next();
|
||||
bool current_is_dir() const;
|
||||
|
||||
void list_dir_end(); ///<
|
||||
|
||||
int get_drive_count();
|
||||
String get_drive(int p_drive);
|
||||
|
||||
Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
|
||||
String get_current_dir(); ///< return current dir location
|
||||
|
||||
Error make_dir(String p_dir);
|
||||
Error make_dir_recursive(String p_dir);
|
||||
|
||||
bool file_exists(String p_file);
|
||||
bool dir_exists(String p_dir);
|
||||
|
||||
int get_space_left();
|
||||
|
||||
Error copy(String p_from, String p_to);
|
||||
Error rename(String p_from, String p_to);
|
||||
Error remove(String p_name);
|
||||
|
||||
_Directory();
|
||||
virtual ~_Directory();
|
||||
};
|
||||
|
||||
class _Marshalls : public Reference {
|
||||
|
||||
OBJ_TYPE(_Marshalls, Reference);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
String variant_to_base64(const Variant &p_var);
|
||||
Variant base64_to_variant(const String &p_str);
|
||||
|
||||
String raw_to_base64(const DVector<uint8_t> &p_arr);
|
||||
DVector<uint8_t> base64_to_raw(const String &p_str);
|
||||
|
||||
String utf8_to_base64(const String &p_str);
|
||||
String base64_to_utf8(const String &p_str);
|
||||
|
||||
_Marshalls(){};
|
||||
};
|
||||
|
||||
class _Mutex : public Reference {
|
||||
|
||||
OBJ_TYPE(_Mutex, Reference);
|
||||
Mutex *mutex;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void lock();
|
||||
Error try_lock();
|
||||
void unlock();
|
||||
|
||||
_Mutex();
|
||||
~_Mutex();
|
||||
};
|
||||
|
||||
class _Semaphore : public Reference {
|
||||
|
||||
OBJ_TYPE(_Semaphore, Reference);
|
||||
Semaphore *semaphore;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Error wait();
|
||||
Error post();
|
||||
|
||||
_Semaphore();
|
||||
~_Semaphore();
|
||||
};
|
||||
|
||||
class _Thread : public Reference {
|
||||
|
||||
OBJ_TYPE(_Thread, Reference);
|
||||
|
||||
protected:
|
||||
Variant ret;
|
||||
Variant userdata;
|
||||
volatile bool active;
|
||||
Object *target_instance;
|
||||
StringName target_method;
|
||||
Thread *thread;
|
||||
static void _bind_methods();
|
||||
static void _start_func(void *ud);
|
||||
|
||||
public:
|
||||
enum Priority {
|
||||
|
||||
PRIORITY_LOW,
|
||||
PRIORITY_NORMAL,
|
||||
PRIORITY_HIGH
|
||||
};
|
||||
|
||||
Error start(Object *p_instance, const StringName &p_method, const Variant &p_userdata = Variant(), int p_priority = PRIORITY_NORMAL);
|
||||
String get_id() const;
|
||||
bool is_active() const;
|
||||
Variant wait_to_finish();
|
||||
|
||||
_Thread();
|
||||
~_Thread();
|
||||
};
|
||||
|
||||
#endif // CORE_BIND_H
|
||||
389
core/color.cpp
Normal file
389
core/color.cpp
Normal file
@ -0,0 +1,389 @@
|
||||
/*************************************************************************/
|
||||
/* color.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "color.h"
|
||||
#include "color_names.inc"
|
||||
#include "map.h"
|
||||
#include "math_funcs.h"
|
||||
#include "print_string.h"
|
||||
|
||||
uint32_t Color::to_ARGB32() const {
|
||||
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_32() const {
|
||||
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
float Color::get_h() const {
|
||||
|
||||
float min = MIN(r, g);
|
||||
min = MIN(min, b);
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
|
||||
float delta = max - min;
|
||||
|
||||
if (delta == 0)
|
||||
return 0;
|
||||
|
||||
float h;
|
||||
if (r == max)
|
||||
h = (g - b) / delta; // between yellow & magenta
|
||||
else if (g == max)
|
||||
h = 2 + (b - r) / delta; // between cyan & yellow
|
||||
else
|
||||
h = 4 + (r - g) / delta; // between magenta & cyan
|
||||
|
||||
h /= 6.0;
|
||||
if (h < 0)
|
||||
h += 1.0;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
float Color::get_s() const {
|
||||
|
||||
float min = MIN(r, g);
|
||||
min = MIN(min, b);
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
|
||||
float delta = max - min;
|
||||
|
||||
return (max != 0) ? (delta / max) : 0;
|
||||
}
|
||||
|
||||
float Color::get_v() const {
|
||||
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
return max;
|
||||
}
|
||||
|
||||
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||
|
||||
int i;
|
||||
float f, p, q, t;
|
||||
a = p_alpha;
|
||||
|
||||
if (p_s == 0) {
|
||||
// acp_hromatic (grey)
|
||||
r = g = b = p_v;
|
||||
return;
|
||||
}
|
||||
|
||||
p_h *= 6.0;
|
||||
p_h = Math::fmod(p_h, 6);
|
||||
i = Math::floor(p_h);
|
||||
|
||||
f = p_h - i;
|
||||
p = p_v * (1 - p_s);
|
||||
q = p_v * (1 - p_s * f);
|
||||
t = p_v * (1 - p_s * (1 - f));
|
||||
|
||||
switch (i) {
|
||||
case 0: // Red is the dominant color
|
||||
r = p_v;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
case 1: // Green is the dominant color
|
||||
r = q;
|
||||
g = p_v;
|
||||
b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p;
|
||||
g = p_v;
|
||||
b = t;
|
||||
break;
|
||||
case 3: // Blue is the dominant color
|
||||
r = p;
|
||||
g = q;
|
||||
b = p_v;
|
||||
break;
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = p_v;
|
||||
break;
|
||||
default: // (5) Red is the dominant color
|
||||
r = p_v;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Color::invert() {
|
||||
|
||||
r = 1.0 - r;
|
||||
g = 1.0 - g;
|
||||
b = 1.0 - b;
|
||||
}
|
||||
void Color::contrast() {
|
||||
|
||||
r = Math::fmod(r + 0.5, 1.0);
|
||||
g = Math::fmod(g + 0.5, 1.0);
|
||||
b = Math::fmod(b + 0.5, 1.0);
|
||||
}
|
||||
|
||||
Color Color::hex(uint32_t p_hex) {
|
||||
|
||||
float a = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float b = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float g = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float r = (p_hex & 0xFF) / 255.0;
|
||||
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
|
||||
static float _parse_col(const String &p_str, int p_ofs) {
|
||||
|
||||
int ig = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
||||
int c = p_str[i + p_ofs];
|
||||
int v = 0;
|
||||
|
||||
if (c >= '0' && c <= '9') {
|
||||
v = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
v = c - 'a';
|
||||
v += 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
v = c - 'A';
|
||||
v += 10;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
ig += v * 16;
|
||||
else
|
||||
ig += v;
|
||||
}
|
||||
|
||||
return ig;
|
||||
}
|
||||
|
||||
Color Color::inverted() const {
|
||||
|
||||
Color c = *this;
|
||||
c.invert();
|
||||
return c;
|
||||
}
|
||||
|
||||
Color Color::contrasted() const {
|
||||
|
||||
Color c = *this;
|
||||
c.contrast();
|
||||
return c;
|
||||
}
|
||||
|
||||
Color Color::html(const String &p_color) {
|
||||
|
||||
String color = p_color;
|
||||
if (color.length() == 0)
|
||||
return Color();
|
||||
if (color[0] == '#')
|
||||
color = color.substr(1, color.length() - 1);
|
||||
|
||||
bool alpha = false;
|
||||
|
||||
if (color.length() == 8) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 6) {
|
||||
alpha = false;
|
||||
} else {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
int a = 255;
|
||||
if (alpha) {
|
||||
a = _parse_col(color, 0);
|
||||
if (a < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
}
|
||||
|
||||
int from = alpha ? 2 : 0;
|
||||
|
||||
int r = _parse_col(color, from + 0);
|
||||
if (r < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int g = _parse_col(color, from + 2);
|
||||
if (g < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int b = _parse_col(color, from + 4);
|
||||
if (b < 0) {
|
||||
ERR_EXPLAIN("Invalid Color Code: " + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
|
||||
}
|
||||
|
||||
bool Color::html_is_valid(const String &p_color) {
|
||||
|
||||
String color = p_color;
|
||||
|
||||
if (color.length() == 0)
|
||||
return false;
|
||||
if (color[0] == '#')
|
||||
color = color.substr(1, color.length() - 1);
|
||||
|
||||
bool alpha = false;
|
||||
|
||||
if (color.length() == 8) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 6) {
|
||||
alpha = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
int a = 255;
|
||||
if (alpha) {
|
||||
a = _parse_col(color, 0);
|
||||
if (a < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int from = alpha ? 2 : 0;
|
||||
|
||||
int r = _parse_col(color, from + 0);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
}
|
||||
int g = _parse_col(color, from + 2);
|
||||
if (g < 0) {
|
||||
return false;
|
||||
}
|
||||
int b = _parse_col(color, from + 4);
|
||||
if (b < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Color Color::named(const String &p_name) {
|
||||
if (_named_colors.empty()) _populate_named_colors(); // from color_names.inc
|
||||
String name = p_name;
|
||||
// Normalize name
|
||||
name = name.replace(" ", "");
|
||||
name = name.replace("-", "");
|
||||
name = name.replace("_", "");
|
||||
name = name.replace("'", "");
|
||||
name = name.replace(".", "");
|
||||
name = name.to_lower();
|
||||
|
||||
const Map<String, Color>::Element *color = _named_colors.find(name);
|
||||
if (color) {
|
||||
return color->value();
|
||||
} else {
|
||||
ERR_EXPLAIN("Invalid Color Name: " + p_name);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
}
|
||||
|
||||
String _to_hex(float p_val) {
|
||||
|
||||
int v = p_val * 255;
|
||||
v = CLAMP(v, 0, 255);
|
||||
String ret;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
||||
CharType c[2] = { 0, 0 };
|
||||
int lv = v & 0xF;
|
||||
if (lv < 10)
|
||||
c[0] = '0' + lv;
|
||||
else
|
||||
c[0] = 'a' + lv - 10;
|
||||
|
||||
v >>= 4;
|
||||
String cs = (const CharType *)c;
|
||||
ret = cs + ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Color::to_html(bool p_alpha) const {
|
||||
|
||||
String txt;
|
||||
txt += _to_hex(r);
|
||||
txt += _to_hex(g);
|
||||
txt += _to_hex(b);
|
||||
if (p_alpha)
|
||||
txt = _to_hex(a) + txt;
|
||||
return txt;
|
||||
}
|
||||
|
||||
float Color::gray() const {
|
||||
|
||||
return (r + g + b) / 3.0;
|
||||
}
|
||||
|
||||
Color::operator String() const {
|
||||
|
||||
return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a);
|
||||
}
|
||||
154
core/color.h
Normal file
154
core/color.h
Normal file
@ -0,0 +1,154 @@
|
||||
/*************************************************************************/
|
||||
/* color.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#include "math_funcs.h"
|
||||
#include "ustring.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
struct Color {
|
||||
|
||||
union {
|
||||
|
||||
struct {
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
};
|
||||
float components[4];
|
||||
};
|
||||
|
||||
bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
|
||||
bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
|
||||
|
||||
uint32_t to_32() const;
|
||||
uint32_t to_ARGB32() const;
|
||||
float gray() const;
|
||||
float get_h() const;
|
||||
float get_s() const;
|
||||
float get_v() const;
|
||||
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
|
||||
|
||||
_FORCE_INLINE_ float &operator[](int idx) {
|
||||
return components[idx];
|
||||
}
|
||||
_FORCE_INLINE_ const float &operator[](int idx) const {
|
||||
return components[idx];
|
||||
}
|
||||
|
||||
void invert();
|
||||
void contrast();
|
||||
Color inverted() const;
|
||||
Color contrasted() const;
|
||||
|
||||
_FORCE_INLINE_ Color linear_interpolate(const Color &p_b, float p_t) const {
|
||||
|
||||
Color res = *this;
|
||||
|
||||
res.r += (p_t * (p_b.r - r));
|
||||
res.g += (p_t * (p_b.g - g));
|
||||
res.b += (p_t * (p_b.b - b));
|
||||
res.a += (p_t * (p_b.a - a));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Color blend(const Color &p_over) const {
|
||||
|
||||
Color res;
|
||||
float sa = 1.0 - p_over.a;
|
||||
res.a = a * sa + p_over.a;
|
||||
if (res.a == 0) {
|
||||
return Color(0, 0, 0, 0);
|
||||
} else {
|
||||
res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
|
||||
res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
|
||||
res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Color to_linear() const {
|
||||
|
||||
return Color(
|
||||
r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
a);
|
||||
}
|
||||
|
||||
static Color hex(uint32_t p_hex);
|
||||
static Color html(const String &p_color);
|
||||
static bool html_is_valid(const String &p_color);
|
||||
static Color named(const String &p_name);
|
||||
String to_html(bool p_alpha = true) const;
|
||||
|
||||
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
|
||||
operator String() const;
|
||||
|
||||
/**
|
||||
* No construct parameters, r=0, g=0, b=0. a=255
|
||||
*/
|
||||
_FORCE_INLINE_ Color() {
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
a = 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
|
||||
*/
|
||||
_FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
|
||||
r = p_r;
|
||||
g = p_g;
|
||||
b = p_b;
|
||||
a = p_a;
|
||||
}
|
||||
};
|
||||
|
||||
bool Color::operator<(const Color &p_color) const {
|
||||
|
||||
if (r == p_color.r) {
|
||||
if (g == p_color.g) {
|
||||
if (b == p_color.b) {
|
||||
return (a < p_color.a);
|
||||
} else
|
||||
return (b < p_color.b);
|
||||
} else
|
||||
return g < p_color.g;
|
||||
} else
|
||||
return r < p_color.r;
|
||||
}
|
||||
|
||||
#endif
|
||||
152
core/color_names.inc
Normal file
152
core/color_names.inc
Normal file
@ -0,0 +1,152 @@
|
||||
// Names from https://en.wikipedia.org/wiki/List_of_colors (through https://raw.githubusercontent.com/SuperUserNameMan/color_to_name/616a7cddafefda91478b7bc26167de97fb5badb1/godot_version.gd), slightly edited and normalized
|
||||
#include "map.h"
|
||||
|
||||
static Map<String, Color> _named_colors;
|
||||
static void _populate_named_colors() {
|
||||
if(!_named_colors.empty()) return;
|
||||
_named_colors.insert("aliceblue", Color(0.94, 0.97, 1.00));
|
||||
_named_colors.insert("antiquewhite", Color(0.98, 0.92, 0.84));
|
||||
_named_colors.insert("aqua", Color(0.00, 1.00, 1.00));
|
||||
_named_colors.insert("aquamarine", Color(0.50, 1.00, 0.83));
|
||||
_named_colors.insert("azure", Color(0.94, 1.00, 1.00));
|
||||
_named_colors.insert("beige", Color(0.96, 0.96, 0.86));
|
||||
_named_colors.insert("bisque", Color(1.00, 0.89, 0.77));
|
||||
_named_colors.insert("black", Color(0.00, 0.00, 0.00));
|
||||
_named_colors.insert("blanchedalmond", Color(1.00, 0.92, 0.80));
|
||||
_named_colors.insert("blue", Color(0.00, 0.00, 1.00));
|
||||
_named_colors.insert("blueviolet", Color(0.54, 0.17, 0.89));
|
||||
_named_colors.insert("brown", Color(0.65, 0.16, 0.16));
|
||||
_named_colors.insert("burlywood", Color(0.87, 0.72, 0.53));
|
||||
_named_colors.insert("cadetblue", Color(0.37, 0.62, 0.63));
|
||||
_named_colors.insert("chartreuse", Color(0.50, 1.00, 0.00));
|
||||
_named_colors.insert("chocolate", Color(0.82, 0.41, 0.12));
|
||||
_named_colors.insert("coral", Color(1.00, 0.50, 0.31));
|
||||
_named_colors.insert("cornflower", Color(0.39, 0.58, 0.93));
|
||||
_named_colors.insert("cornsilk", Color(1.00, 0.97, 0.86));
|
||||
_named_colors.insert("crimson", Color(0.86, 0.08, 0.24));
|
||||
_named_colors.insert("cyan", Color(0.00, 1.00, 1.00));
|
||||
_named_colors.insert("darkblue", Color(0.00, 0.00, 0.55));
|
||||
_named_colors.insert("darkcyan", Color(0.00, 0.55, 0.55));
|
||||
_named_colors.insert("darkgoldenrod", Color(0.72, 0.53, 0.04));
|
||||
_named_colors.insert("darkgray", Color(0.66, 0.66, 0.66));
|
||||
_named_colors.insert("darkgreen", Color(0.00, 0.39, 0.00));
|
||||
_named_colors.insert("darkkhaki", Color(0.74, 0.72, 0.42));
|
||||
_named_colors.insert("darkmagenta", Color(0.55, 0.00, 0.55));
|
||||
_named_colors.insert("darkolivegreen", Color(0.33, 0.42, 0.18));
|
||||
_named_colors.insert("darkorange", Color(1.00, 0.55, 0.00));
|
||||
_named_colors.insert("darkorchid", Color(0.60, 0.20, 0.80));
|
||||
_named_colors.insert("darkred", Color(0.55, 0.00, 0.00));
|
||||
_named_colors.insert("darksalmon", Color(0.91, 0.59, 0.48));
|
||||
_named_colors.insert("darkseagreen", Color(0.56, 0.74, 0.56));
|
||||
_named_colors.insert("darkslateblue", Color(0.28, 0.24, 0.55));
|
||||
_named_colors.insert("darkslategray", Color(0.18, 0.31, 0.31));
|
||||
_named_colors.insert("darkturquoise", Color(0.00, 0.81, 0.82));
|
||||
_named_colors.insert("darkviolet", Color(0.58, 0.00, 0.83));
|
||||
_named_colors.insert("deeppink", Color(1.00, 0.08, 0.58));
|
||||
_named_colors.insert("deepskyblue", Color(0.00, 0.75, 1.00));
|
||||
_named_colors.insert("dimgray", Color(0.41, 0.41, 0.41));
|
||||
_named_colors.insert("dodgerblue", Color(0.12, 0.56, 1.00));
|
||||
_named_colors.insert("firebrick", Color(0.70, 0.13, 0.13));
|
||||
_named_colors.insert("floralwhite", Color(1.00, 0.98, 0.94));
|
||||
_named_colors.insert("forestgreen", Color(0.13, 0.55, 0.13));
|
||||
_named_colors.insert("fuchsia", Color(1.00, 0.00, 1.00));
|
||||
_named_colors.insert("gainsboro", Color(0.86, 0.86, 0.86));
|
||||
_named_colors.insert("ghostwhite", Color(0.97, 0.97, 1.00));
|
||||
_named_colors.insert("gold", Color(1.00, 0.84, 0.00));
|
||||
_named_colors.insert("goldenrod", Color(0.85, 0.65, 0.13));
|
||||
_named_colors.insert("gray", Color(0.75, 0.75, 0.75));
|
||||
_named_colors.insert("webgray", Color(0.50, 0.50, 0.50));
|
||||
_named_colors.insert("green", Color(0.00, 1.00, 0.00));
|
||||
_named_colors.insert("webgreen", Color(0.00, 0.50, 0.00));
|
||||
_named_colors.insert("greenyellow", Color(0.68, 1.00, 0.18));
|
||||
_named_colors.insert("honeydew", Color(0.94, 1.00, 0.94));
|
||||
_named_colors.insert("hotpink", Color(1.00, 0.41, 0.71));
|
||||
_named_colors.insert("indianred", Color(0.80, 0.36, 0.36));
|
||||
_named_colors.insert("indigo", Color(0.29, 0.00, 0.51));
|
||||
_named_colors.insert("ivory", Color(1.00, 1.00, 0.94));
|
||||
_named_colors.insert("khaki", Color(0.94, 0.90, 0.55));
|
||||
_named_colors.insert("lavender", Color(0.90, 0.90, 0.98));
|
||||
_named_colors.insert("lavenderblush", Color(1.00, 0.94, 0.96));
|
||||
_named_colors.insert("lawngreen", Color(0.49, 0.99, 0.00));
|
||||
_named_colors.insert("lemonchiffon", Color(1.00, 0.98, 0.80));
|
||||
_named_colors.insert("lightblue", Color(0.68, 0.85, 0.90));
|
||||
_named_colors.insert("lightcoral", Color(0.94, 0.50, 0.50));
|
||||
_named_colors.insert("lightcyan", Color(0.88, 1.00, 1.00));
|
||||
_named_colors.insert("lightgoldenrod", Color(0.98, 0.98, 0.82));
|
||||
_named_colors.insert("lightgray", Color(0.83, 0.83, 0.83));
|
||||
_named_colors.insert("lightgreen", Color(0.56, 0.93, 0.56));
|
||||
_named_colors.insert("lightpink", Color(1.00, 0.71, 0.76));
|
||||
_named_colors.insert("lightsalmon", Color(1.00, 0.63, 0.48));
|
||||
_named_colors.insert("lightseagreen", Color(0.13, 0.70, 0.67));
|
||||
_named_colors.insert("lightskyblue", Color(0.53, 0.81, 0.98));
|
||||
_named_colors.insert("lightslategray", Color(0.47, 0.53, 0.60));
|
||||
_named_colors.insert("lightsteelblue", Color(0.69, 0.77, 0.87));
|
||||
_named_colors.insert("lightyellow", Color(1.00, 1.00, 0.88));
|
||||
_named_colors.insert("lime", Color(0.00, 1.00, 0.00));
|
||||
_named_colors.insert("limegreen", Color(0.20, 0.80, 0.20));
|
||||
_named_colors.insert("linen", Color(0.98, 0.94, 0.90));
|
||||
_named_colors.insert("magenta", Color(1.00, 0.00, 1.00));
|
||||
_named_colors.insert("maroon", Color(0.69, 0.19, 0.38));
|
||||
_named_colors.insert("webmaroon", Color(0.50, 0.00, 0.00));
|
||||
_named_colors.insert("mediumaquamarine", Color(0.40, 0.80, 0.67));
|
||||
_named_colors.insert("mediumblue", Color(0.00, 0.00, 0.80));
|
||||
_named_colors.insert("mediumorchid", Color(0.73, 0.33, 0.83));
|
||||
_named_colors.insert("mediumpurple", Color(0.58, 0.44, 0.86));
|
||||
_named_colors.insert("mediumseagreen", Color(0.24, 0.70, 0.44));
|
||||
_named_colors.insert("mediumslateblue", Color(0.48, 0.41, 0.93));
|
||||
_named_colors.insert("mediumspringgreen", Color(0.00, 0.98, 0.60));
|
||||
_named_colors.insert("mediumturquoise", Color(0.28, 0.82, 0.80));
|
||||
_named_colors.insert("mediumvioletred", Color(0.78, 0.08, 0.52));
|
||||
_named_colors.insert("midnightblue", Color(0.10, 0.10, 0.44));
|
||||
_named_colors.insert("mintcream", Color(0.96, 1.00, 0.98));
|
||||
_named_colors.insert("mistyrose", Color(1.00, 0.89, 0.88));
|
||||
_named_colors.insert("moccasin", Color(1.00, 0.89, 0.71));
|
||||
_named_colors.insert("navajowhite", Color(1.00, 0.87, 0.68));
|
||||
_named_colors.insert("navyblue", Color(0.00, 0.00, 0.50));
|
||||
_named_colors.insert("oldlace", Color(0.99, 0.96, 0.90));
|
||||
_named_colors.insert("olive", Color(0.50, 0.50, 0.00));
|
||||
_named_colors.insert("olivedrab", Color(0.42, 0.56, 0.14));
|
||||
_named_colors.insert("orange", Color(1.00, 0.65, 0.00));
|
||||
_named_colors.insert("orangered", Color(1.00, 0.27, 0.00));
|
||||
_named_colors.insert("orchid", Color(0.85, 0.44, 0.84));
|
||||
_named_colors.insert("palegoldenrod", Color(0.93, 0.91, 0.67));
|
||||
_named_colors.insert("palegreen", Color(0.60, 0.98, 0.60));
|
||||
_named_colors.insert("paleturquoise", Color(0.69, 0.93, 0.93));
|
||||
_named_colors.insert("palevioletred", Color(0.86, 0.44, 0.58));
|
||||
_named_colors.insert("papayawhip", Color(1.00, 0.94, 0.84));
|
||||
_named_colors.insert("peachpuff", Color(1.00, 0.85, 0.73));
|
||||
_named_colors.insert("peru", Color(0.80, 0.52, 0.25));
|
||||
_named_colors.insert("pink", Color(1.00, 0.75, 0.80));
|
||||
_named_colors.insert("plum", Color(0.87, 0.63, 0.87));
|
||||
_named_colors.insert("powderblue", Color(0.69, 0.88, 0.90));
|
||||
_named_colors.insert("purple", Color(0.63, 0.13, 0.94));
|
||||
_named_colors.insert("webpurple", Color(0.50, 0.00, 0.50));
|
||||
_named_colors.insert("rebeccapurple", Color(0.40, 0.20, 0.60));
|
||||
_named_colors.insert("red", Color(1.00, 0.00, 0.00));
|
||||
_named_colors.insert("rosybrown", Color(0.74, 0.56, 0.56));
|
||||
_named_colors.insert("royalblue", Color(0.25, 0.41, 0.88));
|
||||
_named_colors.insert("saddlebrown", Color(0.55, 0.27, 0.07));
|
||||
_named_colors.insert("salmon", Color(0.98, 0.50, 0.45));
|
||||
_named_colors.insert("sandybrown", Color(0.96, 0.64, 0.38));
|
||||
_named_colors.insert("seagreen", Color(0.18, 0.55, 0.34));
|
||||
_named_colors.insert("seashell", Color(1.00, 0.96, 0.93));
|
||||
_named_colors.insert("sienna", Color(0.63, 0.32, 0.18));
|
||||
_named_colors.insert("silver", Color(0.75, 0.75, 0.75));
|
||||
_named_colors.insert("skyblue", Color(0.53, 0.81, 0.92));
|
||||
_named_colors.insert("slateblue", Color(0.42, 0.35, 0.80));
|
||||
_named_colors.insert("slategray", Color(0.44, 0.50, 0.56));
|
||||
_named_colors.insert("snow", Color(1.00, 0.98, 0.98));
|
||||
_named_colors.insert("springgreen", Color(0.00, 1.00, 0.50));
|
||||
_named_colors.insert("steelblue", Color(0.27, 0.51, 0.71));
|
||||
_named_colors.insert("tan", Color(0.82, 0.71, 0.55));
|
||||
_named_colors.insert("teal", Color(0.00, 0.50, 0.50));
|
||||
_named_colors.insert("thistle", Color(0.85, 0.75, 0.85));
|
||||
_named_colors.insert("tomato", Color(1.00, 0.39, 0.28));
|
||||
_named_colors.insert("turquoise", Color(0.25, 0.88, 0.82));
|
||||
_named_colors.insert("violet", Color(0.93, 0.51, 0.93));
|
||||
_named_colors.insert("wheat", Color(0.96, 0.87, 0.70));
|
||||
_named_colors.insert("white", Color(1.00, 1.00, 1.00));
|
||||
_named_colors.insert("whitesmoke", Color(0.96, 0.96, 0.96));
|
||||
_named_colors.insert("yellow", Color(1.00, 1.00, 0.00));
|
||||
_named_colors.insert("yellowgreen", Color(0.60, 0.80, 0.20));
|
||||
}
|
||||
102
core/command_queue_mt.cpp
Normal file
102
core/command_queue_mt.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*************************************************************************/
|
||||
/* command_queue_mt.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "command_queue_mt.h"
|
||||
#include "os/os.h"
|
||||
|
||||
void CommandQueueMT::lock() {
|
||||
|
||||
if (mutex)
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
void CommandQueueMT::unlock() {
|
||||
|
||||
if (mutex)
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
void CommandQueueMT::wait_for_flush() {
|
||||
|
||||
// wait one millisecond for a flush to happen
|
||||
OS::get_singleton()->delay_usec(1000);
|
||||
}
|
||||
|
||||
CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
|
||||
|
||||
int idx = -1;
|
||||
|
||||
while (true) {
|
||||
|
||||
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
|
||||
|
||||
if (!sync_sems[i].in_use) {
|
||||
sync_sems[i].in_use = true;
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
wait_for_flush();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return &sync_sems[idx];
|
||||
}
|
||||
|
||||
CommandQueueMT::CommandQueueMT(bool p_sync) {
|
||||
|
||||
read_ptr = 0;
|
||||
write_ptr = 0;
|
||||
mutex = Mutex::create();
|
||||
|
||||
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
|
||||
|
||||
sync_sems[i].sem = Semaphore::create();
|
||||
sync_sems[i].in_use = false;
|
||||
}
|
||||
if (p_sync)
|
||||
sync = Semaphore::create();
|
||||
else
|
||||
sync = NULL;
|
||||
}
|
||||
|
||||
CommandQueueMT::~CommandQueueMT() {
|
||||
|
||||
if (sync)
|
||||
memdelete(sync);
|
||||
memdelete(mutex);
|
||||
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
|
||||
|
||||
memdelete(sync_sems[i].sem);
|
||||
}
|
||||
}
|
||||
1203
core/command_queue_mt.h
Normal file
1203
core/command_queue_mt.h
Normal file
File diff suppressed because it is too large
Load Diff
519
core/compressed_translation.cpp
Normal file
519
core/compressed_translation.cpp
Normal file
@ -0,0 +1,519 @@
|
||||
/*************************************************************************/
|
||||
/* compressed_translation.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "compressed_translation.h"
|
||||
#include "pair.h"
|
||||
#include <string.h>
|
||||
|
||||
/////////// SMAZ /////////////
|
||||
|
||||
/*
|
||||
Copyright (c) 2006-2009, Salvatore Sanfilippo
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Smaz nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Our compression codebook, used for compression */
|
||||
static const char *Smaz_cb[241] = {
|
||||
"\002s,\266", "\003had\232\002leW", "\003on \216", "", "\001yS",
|
||||
"\002ma\255\002li\227", "\003or \260", "", "\002ll\230\003s t\277",
|
||||
"\004fromg\002mel", "", "\003its\332", "\001z\333", "\003ingF", "\001>\336",
|
||||
"\001 \000\003 (\002nc\344", "\002nd=\003 on\312",
|
||||
"\002ne\213\003hat\276\003re q", "", "\002ngT\003herz\004have\306\003s o\225",
|
||||
"", "\003ionk\003s a\254\002ly\352", "\003hisL\003 inN\003 be\252", "",
|
||||
"\003 fo\325\003 of \003 ha\311", "", "\002of\005",
|
||||
"\003 co\241\002no\267\003 ma\370", "", "", "\003 cl\356\003enta\003 an7",
|
||||
"\002ns\300\001\"e", "\003n t\217\002ntP\003s, \205",
|
||||
"\002pe\320\003 we\351\002om\223", "\002on\037", "", "\002y G", "\003 wa\271",
|
||||
"\003 re\321\002or*", "", "\002=\"\251\002ot\337", "\003forD\002ou[",
|
||||
"\003 toR", "\003 th\r", "\003 it\366",
|
||||
"\003but\261\002ra\202\003 wi\363\002</\361", "\003 wh\237", "\002 4",
|
||||
"\003nd ?", "\002re!", "", "\003ng c", "",
|
||||
"\003ly \307\003ass\323\001a\004\002rir", "", "", "", "\002se_", "\003of \"",
|
||||
"\003div\364\002ros\003ere\240", "", "\002ta\310\001bZ\002si\324", "",
|
||||
"\003and\a\002rs\335", "\002rt\362", "\002teE", "\003ati\316", "\002so\263",
|
||||
"\002th\021", "\002tiJ\001c\034\003allp", "\003ate\345", "\002ss\246",
|
||||
"\002stM", "", "\002><\346", "\002to\024", "\003arew", "\001d\030",
|
||||
"\002tr\303", "", "\001\n1\003 a \222", "\003f tv\002veo", "\002un\340", "",
|
||||
"\003e o\242", "\002a \243\002wa\326\001e\002", "\002ur\226\003e a\274",
|
||||
"\002us\244\003\n\r\n\247", "\002ut\304\003e c\373", "\002we\221", "", "",
|
||||
"\002wh\302", "\001f,", "", "", "", "\003d t\206", "", "", "\003th \343",
|
||||
"\001g;", "", "", "\001\r9\003e s\265", "\003e t\234", "", "\003to Y",
|
||||
"\003e\r\n\236", "\002d \036\001h\022", "", "\001,Q", "\002 a\031", "\002 b^",
|
||||
"\002\r\n\025\002 cI", "\002 d\245", "\002 e\253", "\002 fh\001i\b\002e \v",
|
||||
"", "\002 hU\001-\314", "\002 i8", "", "", "\002 l\315", "\002 m{",
|
||||
"\002f :\002 n\354", "\002 o\035", "\002 p}\001.n\003\r\n\r\250", "",
|
||||
"\002 r\275", "\002 s>", "\002 t\016", "", "\002g \235\005which+\003whi\367",
|
||||
"\002 w5", "\001/\305", "\003as \214", "\003at \207", "", "\003who\331", "",
|
||||
"\001l\026\002h \212", "", "\002, $", "", "\004withV", "", "", "", "\001m-", "",
|
||||
"", "\002ac\357", "\002ad\350", "\003TheH", "", "", "\004this\233\001n\t",
|
||||
"", "\002. y", "", "\002alX\003e, \365", "\003tio\215\002be\\",
|
||||
"\002an\032\003ver\347", "", "\004that0\003tha\313\001o\006", "\003was2",
|
||||
"\002arO", "\002as.", "\002at'\003the\001\004they\200\005there\322\005theird",
|
||||
"\002ce\210", "\004were]", "", "\002ch\231\002l \264\001p<", "", "",
|
||||
"\003one\256", "", "\003he \023\002dej", "\003ter\270", "\002cou", "",
|
||||
"\002by\177\002di\201\002eax", "", "\002ec\327", "\002edB", "\002ee\353", "",
|
||||
"", "\001r\f\002n )", "", "", "", "\002el\262", "", "\003in i\002en3", "",
|
||||
"\002o `\001s\n", "", "\002er\033", "\003is t\002es6", "", "\002ge\371",
|
||||
"\004.com\375", "\002fo\334\003our\330", "\003ch \301\001t\003", "\002hab", "",
|
||||
"\003men\374", "", "\002he\020", "", "", "\001u&", "\002hif", "",
|
||||
"\003not\204\002ic\203", "\003ed @\002id\355", "", "", "\002ho\273",
|
||||
"\002r K\001vm", "", "", "", "\003t t\257\002il\360", "\002im\342",
|
||||
"\003en \317\002in\017", "\002io\220", "\002s \027\001wA", "", "\003er |",
|
||||
"\003es ~\002is%", "\002it/", "", "\002iv\272", "",
|
||||
"\002t #\ahttp://C\001x\372", "\002la\211", "\001<\341", "\003, a\224"
|
||||
};
|
||||
|
||||
/* Reverse compression codebook, used for decompression */
|
||||
static const char *Smaz_rcb[254] = {
|
||||
" ", "the", "e", "t", "a", "of", "o", "and", "i", "n", "s", "e ", "r", " th",
|
||||
" t", "in", "he", "th", "h", "he ", "to", "\r\n", "l", "s ", "d", " a", "an",
|
||||
"er", "c", " o", "d ", "on", " of", "re", "of ", "t ", ", ", "is", "u", "at",
|
||||
" ", "n ", "or", "which", "f", "m", "as", "it", "that", "\n", "was", "en",
|
||||
" ", " w", "es", " an", " i", "\r", "f ", "g", "p", "nd", " s", "nd ", "ed ",
|
||||
"w", "ed", "http://", "for", "te", "ing", "y ", "The", " c", "ti", "r ", "his",
|
||||
"st", " in", "ar", "nt", ",", " to", "y", "ng", " h", "with", "le", "al", "to ",
|
||||
"b", "ou", "be", "were", " b", "se", "o ", "ent", "ha", "ng ", "their", "\"",
|
||||
"hi", "from", " f", "in ", "de", "ion", "me", "v", ".", "ve", "all", "re ",
|
||||
"ri", "ro", "is ", "co", "f t", "are", "ea", ". ", "her", " m", "er ", " p",
|
||||
"es ", "by", "they", "di", "ra", "ic", "not", "s, ", "d t", "at ", "ce", "la",
|
||||
"h ", "ne", "as ", "tio", "on ", "n t", "io", "we", " a ", "om", ", a", "s o",
|
||||
"ur", "li", "ll", "ch", "had", "this", "e t", "g ", "e\r\n", " wh", "ere",
|
||||
" co", "e o", "a ", "us", " d", "ss", "\n\r\n", "\r\n\r", "=\"", " be", " e",
|
||||
"s a", "ma", "one", "t t", "or ", "but", "el", "so", "l ", "e s", "s,", "no",
|
||||
"ter", " wa", "iv", "ho", "e a", " r", "hat", "s t", "ns", "ch ", "wh", "tr",
|
||||
"ut", "/", "have", "ly ", "ta", " ha", " on", "tha", "-", " l", "ati", "en ",
|
||||
"pe", " re", "there", "ass", "si", " fo", "wa", "ec", "our", "who", "its", "z",
|
||||
"fo", "rs", ">", "ot", "un", "<", "im", "th ", "nc", "ate", "><", "ver", "ad",
|
||||
" we", "ly", "ee", " n", "id", " cl", "ac", "il", "</", "rt", " wi", "div",
|
||||
"e, ", " it", "whi", " ma", "ge", "x", "e c", "men", ".com"
|
||||
};
|
||||
|
||||
static int smaz_compress(const char *in, int inlen, char *out, int outlen) {
|
||||
unsigned int h1, h2, h3 = 0;
|
||||
int verblen = 0, _outlen = outlen;
|
||||
char verb[256], *_out = out;
|
||||
|
||||
while (inlen) {
|
||||
int j = 7, needed;
|
||||
char *flush = NULL;
|
||||
const char *slot;
|
||||
|
||||
h1 = h2 = in[0] << 3;
|
||||
if (inlen > 1) h2 += in[1];
|
||||
if (inlen > 2) h3 = h2 ^ in[2];
|
||||
if (j > inlen) j = inlen;
|
||||
|
||||
/* Try to lookup substrings into the hash table, starting from the
|
||||
* longer to the shorter substrings */
|
||||
for (; j > 0; j--) {
|
||||
switch (j) {
|
||||
case 1: slot = Smaz_cb[h1 % 241]; break;
|
||||
case 2: slot = Smaz_cb[h2 % 241]; break;
|
||||
default: slot = Smaz_cb[h3 % 241]; break;
|
||||
}
|
||||
while (slot[0]) {
|
||||
if (slot[0] == j && memcmp(slot + 1, in, j) == 0) {
|
||||
/* Match found in the hash table,
|
||||
* prepare a verbatim bytes flush if needed */
|
||||
if (verblen) {
|
||||
needed = (verblen == 1) ? 2 : 2 + verblen;
|
||||
flush = out;
|
||||
out += needed;
|
||||
outlen -= needed;
|
||||
}
|
||||
/* Emit the byte */
|
||||
if (outlen <= 0) return _outlen + 1;
|
||||
out[0] = slot[slot[0] + 1];
|
||||
out++;
|
||||
outlen--;
|
||||
inlen -= j;
|
||||
in += j;
|
||||
goto out;
|
||||
} else {
|
||||
slot += slot[0] + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Match not found - add the byte to the verbatim buffer */
|
||||
verb[verblen] = in[0];
|
||||
verblen++;
|
||||
inlen--;
|
||||
in++;
|
||||
out:
|
||||
/* Prepare a flush if we reached the flush length limit, and there
|
||||
* is not already a pending flush operation. */
|
||||
if (!flush && (verblen == 256 || (verblen > 0 && inlen == 0))) {
|
||||
needed = (verblen == 1) ? 2 : 2 + verblen;
|
||||
flush = out;
|
||||
out += needed;
|
||||
outlen -= needed;
|
||||
if (outlen < 0) return _outlen + 1;
|
||||
}
|
||||
/* Perform a verbatim flush if needed */
|
||||
if (flush) {
|
||||
if (verblen == 1) {
|
||||
flush[0] = (signed char)254;
|
||||
flush[1] = verb[0];
|
||||
} else {
|
||||
flush[0] = (signed char)255;
|
||||
flush[1] = (signed char)(verblen - 1);
|
||||
memcpy(flush + 2, verb, verblen);
|
||||
}
|
||||
flush = NULL;
|
||||
verblen = 0;
|
||||
}
|
||||
}
|
||||
return out - _out;
|
||||
}
|
||||
|
||||
static int smaz_decompress(const char *in, int inlen, char *out, int outlen) {
|
||||
unsigned char *c = (unsigned char *)in;
|
||||
char *_out = out;
|
||||
int _outlen = outlen;
|
||||
|
||||
while (inlen) {
|
||||
if (*c == 254) {
|
||||
/* Verbatim byte */
|
||||
if (outlen < 1) return _outlen + 1;
|
||||
*out = *(c + 1);
|
||||
out++;
|
||||
outlen--;
|
||||
c += 2;
|
||||
inlen -= 2;
|
||||
} else if (*c == 255) {
|
||||
/* Verbatim string */
|
||||
int len = (*(c + 1)) + 1;
|
||||
if (outlen < len) return _outlen + 1;
|
||||
memcpy(out, c + 2, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
c += 2 + len;
|
||||
inlen -= 2 + len;
|
||||
} else {
|
||||
/* Codebook entry */
|
||||
const char *s = Smaz_rcb[*c];
|
||||
int len = strlen(s);
|
||||
|
||||
if (outlen < len) return _outlen + 1;
|
||||
memcpy(out, s, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
c++;
|
||||
inlen--;
|
||||
}
|
||||
}
|
||||
return out - _out;
|
||||
}
|
||||
|
||||
/////////// END OF SMAZ /////////////
|
||||
|
||||
struct _PHashTranslationCmp {
|
||||
|
||||
int orig_len;
|
||||
CharString compressed;
|
||||
int offset;
|
||||
};
|
||||
|
||||
void PHashTranslation::generate(const Ref<Translation> &p_from) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
List<StringName> keys;
|
||||
p_from->get_message_list(&keys);
|
||||
|
||||
int size = Math::larger_prime(keys.size());
|
||||
|
||||
print_line("compressing keys: " + itos(keys.size()));
|
||||
Vector<Vector<Pair<int, CharString> > > buckets;
|
||||
Vector<Map<uint32_t, int> > table;
|
||||
Vector<uint32_t> hfunc_table;
|
||||
Vector<_PHashTranslationCmp> compressed;
|
||||
|
||||
table.resize(size);
|
||||
hfunc_table.resize(size);
|
||||
buckets.resize(size);
|
||||
compressed.resize(keys.size());
|
||||
|
||||
int idx = 0;
|
||||
int total_compression_size = 0;
|
||||
int total_string_size = 0;
|
||||
|
||||
for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
|
||||
|
||||
//hash string
|
||||
CharString cs = E->get().operator String().utf8();
|
||||
uint32_t h = hash(0, cs.get_data());
|
||||
Pair<int, CharString> p;
|
||||
p.first = idx;
|
||||
p.second = cs;
|
||||
buckets[h % size].push_back(p);
|
||||
|
||||
//compress string
|
||||
CharString src_s = p_from->get_message(E->get()).operator String().utf8();
|
||||
_PHashTranslationCmp ps;
|
||||
ps.orig_len = src_s.size();
|
||||
ps.offset = total_compression_size;
|
||||
|
||||
if (ps.orig_len != 0) {
|
||||
CharString dst_s;
|
||||
dst_s.resize(src_s.size());
|
||||
int ret = smaz_compress(src_s.get_data(), src_s.size(), &dst_s[0], src_s.size());
|
||||
if (ret >= src_s.size()) {
|
||||
//if compressed is larger than original, just use original
|
||||
ps.orig_len = src_s.size();
|
||||
ps.compressed = src_s;
|
||||
} else {
|
||||
dst_s.resize(ret);
|
||||
//ps.orig_len=;
|
||||
ps.compressed = dst_s;
|
||||
}
|
||||
} else {
|
||||
ps.orig_len = 1;
|
||||
ps.compressed.resize(1);
|
||||
ps.compressed[0] = 0;
|
||||
}
|
||||
|
||||
compressed[idx] = ps;
|
||||
total_compression_size += ps.compressed.size();
|
||||
total_string_size += src_s.size();
|
||||
idx++;
|
||||
}
|
||||
|
||||
int bucket_table_size = 0;
|
||||
print_line("total compressed string size: " + itos(total_compression_size) + " (" + itos(total_string_size) + " uncompressed).");
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
||||
Vector<Pair<int, CharString> > &b = buckets[i];
|
||||
Map<uint32_t, int> &t = table[i];
|
||||
|
||||
if (b.size() == 0)
|
||||
continue;
|
||||
|
||||
//print_line("bucket: "+itos(i)+" - elements: "+itos(b.size()));
|
||||
|
||||
int d = 1;
|
||||
int item = 0;
|
||||
|
||||
while (item < b.size()) {
|
||||
|
||||
uint32_t slot = hash(d, b[item].second.get_data());
|
||||
if (t.has(slot)) {
|
||||
|
||||
item = 0;
|
||||
d++;
|
||||
t.clear();
|
||||
} else {
|
||||
t[slot] = b[item].first;
|
||||
item++;
|
||||
}
|
||||
}
|
||||
|
||||
hfunc_table[i] = d;
|
||||
bucket_table_size += 2 + b.size() * 4;
|
||||
}
|
||||
|
||||
print_line("bucket table size: " + itos(bucket_table_size * 4));
|
||||
print_line("hash table size: " + itos(size * 4));
|
||||
|
||||
hash_table.resize(size);
|
||||
bucket_table.resize(bucket_table_size);
|
||||
|
||||
DVector<int>::Write htwb = hash_table.write();
|
||||
DVector<int>::Write btwb = bucket_table.write();
|
||||
|
||||
uint32_t *htw = (uint32_t *)&htwb[0];
|
||||
uint32_t *btw = (uint32_t *)&btwb[0];
|
||||
|
||||
int btindex = 0;
|
||||
int collisions = 0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
||||
Map<uint32_t, int> &t = table[i];
|
||||
if (t.size() == 0) {
|
||||
htw[i] = 0xFFFFFFFF; //nothing
|
||||
continue;
|
||||
} else if (t.size() > 1) {
|
||||
collisions += t.size() - 1;
|
||||
}
|
||||
|
||||
htw[i] = btindex;
|
||||
btw[btindex++] = t.size();
|
||||
btw[btindex++] = hfunc_table[i];
|
||||
|
||||
for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) {
|
||||
|
||||
btw[btindex++] = E->key();
|
||||
btw[btindex++] = compressed[E->get()].offset;
|
||||
btw[btindex++] = compressed[E->get()].compressed.size();
|
||||
btw[btindex++] = compressed[E->get()].orig_len;
|
||||
}
|
||||
}
|
||||
|
||||
print_line("total collisions: " + itos(collisions));
|
||||
|
||||
strings.resize(total_compression_size);
|
||||
DVector<uint8_t>::Write cw = strings.write();
|
||||
|
||||
for (int i = 0; i < compressed.size(); i++) {
|
||||
memcpy(&cw[compressed[i].offset], compressed[i].compressed.get_data(), compressed[i].compressed.size());
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(btindex != bucket_table_size);
|
||||
set_locale(p_from->get_locale());
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) {
|
||||
|
||||
String name = p_name.operator String();
|
||||
if (name == "hash_table") {
|
||||
hash_table = p_value;
|
||||
//print_line("translation: loaded hash table of size: "+itos(hash_table.size()));
|
||||
} else if (name == "bucket_table") {
|
||||
bucket_table = p_value;
|
||||
//print_line("translation: loaded bucket table of size: "+itos(bucket_table.size()));
|
||||
} else if (name == "strings") {
|
||||
strings = p_value;
|
||||
//print_line("translation: loaded string table of size: "+itos(strings.size()));
|
||||
} else if (name == "load_from") {
|
||||
//print_line("generating");
|
||||
generate(p_value);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
|
||||
String name = p_name.operator String();
|
||||
if (name == "hash_table")
|
||||
r_ret = hash_table;
|
||||
else if (name == "bucket_table")
|
||||
r_ret = bucket_table;
|
||||
else if (name == "strings")
|
||||
r_ret = strings;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
StringName PHashTranslation::get_message(const StringName &p_src_text) const {
|
||||
|
||||
int htsize = hash_table.size();
|
||||
|
||||
if (htsize == 0)
|
||||
return StringName();
|
||||
|
||||
CharString str = p_src_text.operator String().utf8();
|
||||
uint32_t h = hash(0, str.get_data());
|
||||
|
||||
DVector<int>::Read htr = hash_table.read();
|
||||
const uint32_t *htptr = (const uint32_t *)&htr[0];
|
||||
DVector<int>::Read btr = bucket_table.read();
|
||||
const uint32_t *btptr = (const uint32_t *)&btr[0];
|
||||
DVector<uint8_t>::Read sr = strings.read();
|
||||
const char *sptr = (const char *)&sr[0];
|
||||
|
||||
uint32_t p = htptr[h % htsize];
|
||||
|
||||
//print_line("String: "+p_src_text.operator String());
|
||||
//print_line("Hash: "+itos(p));
|
||||
|
||||
if (p == 0xFFFFFFFF) {
|
||||
// print_line("GETMSG: Nothing!");
|
||||
return StringName(); //nothing
|
||||
}
|
||||
|
||||
const Bucket &bucket = *(const Bucket *)&btptr[p];
|
||||
|
||||
h = hash(bucket.func, str.get_data());
|
||||
|
||||
int idx = -1;
|
||||
|
||||
for (int i = 0; i < bucket.size; i++) {
|
||||
|
||||
if (bucket.elem[i].key == h) {
|
||||
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//print_line("bucket pos: "+itos(idx));
|
||||
if (idx == -1) {
|
||||
// print_line("GETMSG: Not in Bucket!");
|
||||
return StringName();
|
||||
}
|
||||
|
||||
if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) {
|
||||
|
||||
String rstr;
|
||||
rstr.parse_utf8(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].uncomp_size);
|
||||
// print_line("Uncompressed, size: "+itos(bucket.elem[idx].comp_size));
|
||||
// print_line("Return: "+rstr);
|
||||
|
||||
return rstr;
|
||||
} else {
|
||||
|
||||
CharString uncomp;
|
||||
uncomp.resize(bucket.elem[idx].uncomp_size + 1);
|
||||
smaz_decompress(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].comp_size, uncomp.ptr(), bucket.elem[idx].uncomp_size);
|
||||
String rstr;
|
||||
rstr.parse_utf8(uncomp.get_data());
|
||||
// print_line("Compressed, size: "+itos(bucket.elem[idx].comp_size));
|
||||
// print_line("Return: "+rstr);
|
||||
return rstr;
|
||||
}
|
||||
}
|
||||
|
||||
void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::INT_ARRAY, "hash_table"));
|
||||
p_list->push_back(PropertyInfo(Variant::INT_ARRAY, "bucket_table"));
|
||||
p_list->push_back(PropertyInfo(Variant::RAW_ARRAY, "strings"));
|
||||
p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR));
|
||||
}
|
||||
void PHashTranslation::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("generate", "from:Translation"), &PHashTranslation::generate);
|
||||
}
|
||||
|
||||
PHashTranslation::PHashTranslation() {
|
||||
}
|
||||
91
core/compressed_translation.h
Normal file
91
core/compressed_translation.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*************************************************************************/
|
||||
/* compressed_translation.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 COMPRESSED_TRANSLATION_H
|
||||
#define COMPRESSED_TRANSLATION_H
|
||||
|
||||
#include "translation.h"
|
||||
|
||||
class PHashTranslation : public Translation {
|
||||
|
||||
OBJ_TYPE(PHashTranslation, Translation);
|
||||
|
||||
//this translation uses a sort of modified perfect hash algorithm
|
||||
//it requieres hashing strings twice and then does a binary search,
|
||||
//so it's slower, but at the same time it has an extreemly high chance
|
||||
//of catching untranslated strings
|
||||
|
||||
//load/store friendly types
|
||||
DVector<int> hash_table;
|
||||
DVector<int> bucket_table;
|
||||
DVector<uint8_t> strings;
|
||||
|
||||
struct Bucket {
|
||||
|
||||
int size;
|
||||
uint32_t func;
|
||||
|
||||
struct Elem {
|
||||
|
||||
uint32_t key;
|
||||
uint32_t str_offset;
|
||||
uint32_t comp_size;
|
||||
uint32_t uncomp_size;
|
||||
};
|
||||
|
||||
Elem elem[1];
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ uint32_t hash(uint32_t d, const char *p_str) const {
|
||||
|
||||
if (d == 0)
|
||||
d = 0x1000193;
|
||||
while (*p_str) {
|
||||
|
||||
d = (d * 0x1000193) ^ uint32_t(*p_str);
|
||||
p_str++;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual StringName get_message(const StringName &p_src_text) const; //overridable for other implementations
|
||||
void generate(const Ref<Translation> &p_from);
|
||||
|
||||
PHashTranslation();
|
||||
};
|
||||
|
||||
#endif // COMPRESSED_TRANSLATION_H
|
||||
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env_config = env.Clone()
|
||||
|
||||
env_config.add_source_files(env.core_sources, "*.cpp")
|
||||
@ -1,369 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* engine.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 "engine.h"
|
||||
|
||||
#include "core/authors.gen.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/donors.gen.h"
|
||||
#include "core/io/json.h"
|
||||
#include "core/license.gen.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/variant/typed_array.h"
|
||||
#include "core/version.h"
|
||||
|
||||
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.");
|
||||
ips = p_ips;
|
||||
}
|
||||
|
||||
int Engine::get_physics_ticks_per_second() const {
|
||||
return ips;
|
||||
}
|
||||
|
||||
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.");
|
||||
max_physics_steps_per_frame = p_max_physics_steps;
|
||||
}
|
||||
|
||||
int Engine::get_max_physics_steps_per_frame() const {
|
||||
return max_physics_steps_per_frame;
|
||||
}
|
||||
|
||||
void Engine::set_physics_jitter_fix(double p_threshold) {
|
||||
if (p_threshold < 0) {
|
||||
p_threshold = 0;
|
||||
}
|
||||
physics_jitter_fix = p_threshold;
|
||||
}
|
||||
|
||||
double Engine::get_physics_jitter_fix() const {
|
||||
return physics_jitter_fix;
|
||||
}
|
||||
|
||||
void Engine::set_max_fps(int p_fps) {
|
||||
_max_fps = p_fps > 0 ? p_fps : 0;
|
||||
}
|
||||
|
||||
int Engine::get_max_fps() const {
|
||||
return _max_fps;
|
||||
}
|
||||
|
||||
uint64_t Engine::get_frames_drawn() {
|
||||
return frames_drawn;
|
||||
}
|
||||
|
||||
void Engine::set_frame_delay(uint32_t p_msec) {
|
||||
_frame_delay = p_msec;
|
||||
}
|
||||
|
||||
uint32_t Engine::get_frame_delay() const {
|
||||
return _frame_delay;
|
||||
}
|
||||
|
||||
void Engine::set_time_scale(double p_scale) {
|
||||
_time_scale = p_scale;
|
||||
}
|
||||
|
||||
double Engine::get_time_scale() const {
|
||||
return _time_scale;
|
||||
}
|
||||
|
||||
Dictionary Engine::get_version_info() const {
|
||||
Dictionary dict;
|
||||
dict["major"] = VERSION_MAJOR;
|
||||
dict["minor"] = VERSION_MINOR;
|
||||
dict["patch"] = VERSION_PATCH;
|
||||
dict["hex"] = VERSION_HEX;
|
||||
dict["status"] = VERSION_STATUS;
|
||||
dict["build"] = VERSION_BUILD;
|
||||
dict["year"] = VERSION_YEAR;
|
||||
|
||||
String hash = String(VERSION_HASH);
|
||||
dict["hash"] = hash.is_empty() ? String("unknown") : hash;
|
||||
|
||||
String stringver = String(dict["major"]) + "." + String(dict["minor"]);
|
||||
if ((int)dict["patch"] != 0) {
|
||||
stringver += "." + String(dict["patch"]);
|
||||
}
|
||||
stringver += "-" + String(dict["status"]) + " (" + String(dict["build"]) + ")";
|
||||
dict["string"] = stringver;
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
static Array array_from_info(const char *const *info_list) {
|
||||
Array arr;
|
||||
for (int i = 0; info_list[i] != nullptr; i++) {
|
||||
arr.push_back(String::utf8(info_list[i]));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
static Array array_from_info_count(const char *const *info_list, int info_count) {
|
||||
Array arr;
|
||||
for (int i = 0; i < info_count; i++) {
|
||||
arr.push_back(String::utf8(info_list[i]));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
Dictionary Engine::get_author_info() const {
|
||||
Dictionary dict;
|
||||
|
||||
dict["lead_developers"] = array_from_info(AUTHORS_LEAD_DEVELOPERS);
|
||||
dict["project_managers"] = array_from_info(AUTHORS_PROJECT_MANAGERS);
|
||||
dict["founders"] = array_from_info(AUTHORS_FOUNDERS);
|
||||
dict["developers"] = array_from_info(AUTHORS_DEVELOPERS);
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
TypedArray<Dictionary> Engine::get_copyright_info() const {
|
||||
TypedArray<Dictionary> components;
|
||||
for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) {
|
||||
const ComponentCopyright &cp_info = COPYRIGHT_INFO[component_index];
|
||||
Dictionary component_dict;
|
||||
component_dict["name"] = String::utf8(cp_info.name);
|
||||
Array parts;
|
||||
for (int i = 0; i < cp_info.part_count; i++) {
|
||||
const ComponentCopyrightPart &cp_part = cp_info.parts[i];
|
||||
Dictionary part_dict;
|
||||
part_dict["files"] = array_from_info_count(cp_part.files, cp_part.file_count);
|
||||
part_dict["copyright"] = array_from_info_count(cp_part.copyright_statements, cp_part.copyright_count);
|
||||
part_dict["license"] = String::utf8(cp_part.license);
|
||||
parts.push_back(part_dict);
|
||||
}
|
||||
component_dict["parts"] = parts;
|
||||
|
||||
components.push_back(component_dict);
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
Dictionary Engine::get_donor_info() const {
|
||||
Dictionary donors;
|
||||
donors["platinum_sponsors"] = array_from_info(DONORS_SPONSOR_PLATINUM);
|
||||
donors["gold_sponsors"] = array_from_info(DONORS_SPONSOR_GOLD);
|
||||
donors["silver_sponsors"] = array_from_info(DONORS_SPONSOR_SILVER);
|
||||
donors["bronze_sponsors"] = array_from_info(DONORS_SPONSOR_BRONZE);
|
||||
donors["mini_sponsors"] = array_from_info(DONORS_SPONSOR_MINI);
|
||||
donors["gold_donors"] = array_from_info(DONORS_GOLD);
|
||||
donors["silver_donors"] = array_from_info(DONORS_SILVER);
|
||||
donors["bronze_donors"] = array_from_info(DONORS_BRONZE);
|
||||
return donors;
|
||||
}
|
||||
|
||||
Dictionary Engine::get_license_info() const {
|
||||
Dictionary licenses;
|
||||
for (int i = 0; i < LICENSE_COUNT; i++) {
|
||||
licenses[LICENSE_NAMES[i]] = LICENSE_BODIES[i];
|
||||
}
|
||||
return licenses;
|
||||
}
|
||||
|
||||
String Engine::get_license_text() const {
|
||||
return String(GODOT_LICENSE_TEXT);
|
||||
}
|
||||
|
||||
String Engine::get_architecture_name() const {
|
||||
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
|
||||
return "x86_64";
|
||||
|
||||
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
||||
return "x86_32";
|
||||
|
||||
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
|
||||
return "arm64";
|
||||
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
return "arm32";
|
||||
|
||||
#elif defined(__riscv)
|
||||
#if __riscv_xlen == 8
|
||||
return "rv64";
|
||||
#else
|
||||
return "riscv";
|
||||
#endif
|
||||
|
||||
#elif defined(__powerpc__)
|
||||
#if defined(__powerpc64__)
|
||||
return "ppc64";
|
||||
#else
|
||||
return "ppc";
|
||||
#endif
|
||||
|
||||
#elif defined(__wasm__)
|
||||
#if defined(__wasm64__)
|
||||
return "wasm64";
|
||||
#elif defined(__wasm32__)
|
||||
return "wasm32";
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Engine::is_abort_on_gpu_errors_enabled() const {
|
||||
return abort_on_gpu_errors;
|
||||
}
|
||||
|
||||
int32_t Engine::get_gpu_index() const {
|
||||
return gpu_idx;
|
||||
}
|
||||
|
||||
bool Engine::is_validation_layers_enabled() const {
|
||||
return use_validation_layers;
|
||||
}
|
||||
|
||||
void Engine::set_print_error_messages(bool p_enabled) {
|
||||
CoreGlobals::print_error_enabled = p_enabled;
|
||||
}
|
||||
|
||||
bool Engine::is_printing_error_messages() const {
|
||||
return CoreGlobals::print_error_enabled;
|
||||
}
|
||||
|
||||
void Engine::add_singleton(const Singleton &p_singleton) {
|
||||
ERR_FAIL_COND_MSG(singleton_ptrs.has(p_singleton.name), "Can't register singleton that already exists: " + String(p_singleton.name));
|
||||
singletons.push_back(p_singleton);
|
||||
singleton_ptrs[p_singleton.name] = p_singleton.ptr;
|
||||
}
|
||||
|
||||
Object *Engine::get_singleton_object(const StringName &p_name) const {
|
||||
HashMap<StringName, Object *>::ConstIterator E = singleton_ptrs.find(p_name);
|
||||
ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + String(p_name) + "'.");
|
||||
return E->value;
|
||||
}
|
||||
|
||||
bool Engine::is_singleton_user_created(const StringName &p_name) const {
|
||||
ERR_FAIL_COND_V(!singleton_ptrs.has(p_name), false);
|
||||
|
||||
for (const Singleton &E : singletons) {
|
||||
if (E.name == p_name && E.user_created) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void Engine::remove_singleton(const StringName &p_name) {
|
||||
ERR_FAIL_COND(!singleton_ptrs.has(p_name));
|
||||
|
||||
for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) {
|
||||
if (E->get().name == p_name) {
|
||||
singletons.erase(E);
|
||||
singleton_ptrs.erase(p_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Engine::has_singleton(const StringName &p_name) const {
|
||||
return singleton_ptrs.has(p_name);
|
||||
}
|
||||
|
||||
void Engine::get_singletons(List<Singleton> *p_singletons) {
|
||||
for (const Singleton &E : singletons) {
|
||||
p_singletons->push_back(E);
|
||||
}
|
||||
}
|
||||
|
||||
String Engine::get_write_movie_path() const {
|
||||
return write_movie_path;
|
||||
}
|
||||
|
||||
void Engine::set_write_movie_path(const String &p_path) {
|
||||
write_movie_path = p_path;
|
||||
}
|
||||
|
||||
void Engine::set_shader_cache_path(const String &p_path) {
|
||||
shader_cache_path = p_path;
|
||||
}
|
||||
String Engine::get_shader_cache_path() const {
|
||||
return shader_cache_path;
|
||||
}
|
||||
|
||||
Engine *Engine::singleton = nullptr;
|
||||
|
||||
Engine *Engine::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
Engine::Engine() {
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
void Engine::startup_begin() {
|
||||
startup_benchmark_total_from = OS::get_singleton()->get_ticks_usec();
|
||||
}
|
||||
|
||||
void Engine::startup_benchmark_begin_measure(const String &p_what) {
|
||||
startup_benchmark_section = p_what;
|
||||
startup_benchmark_from = OS::get_singleton()->get_ticks_usec();
|
||||
}
|
||||
void Engine::startup_benchmark_end_measure() {
|
||||
uint64_t total = OS::get_singleton()->get_ticks_usec() - startup_benchmark_from;
|
||||
double total_f = double(total) / double(1000000);
|
||||
|
||||
startup_benchmark_json[startup_benchmark_section] = total_f;
|
||||
}
|
||||
|
||||
void Engine::startup_dump(const String &p_to_file) {
|
||||
uint64_t total = OS::get_singleton()->get_ticks_usec() - startup_benchmark_total_from;
|
||||
double total_f = double(total) / double(1000000);
|
||||
startup_benchmark_json["total_time"] = total_f;
|
||||
|
||||
if (!p_to_file.is_empty()) {
|
||||
Ref<FileAccess> f = FileAccess::open(p_to_file, FileAccess::WRITE);
|
||||
if (f.is_valid()) {
|
||||
Ref<JSON> json;
|
||||
json.instantiate();
|
||||
f->store_string(json->stringify(startup_benchmark_json, "\t", false, true));
|
||||
}
|
||||
} else {
|
||||
List<Variant> keys;
|
||||
startup_benchmark_json.get_key_list(&keys);
|
||||
print_line("STARTUP BENCHMARK:");
|
||||
for (const Variant &K : keys) {
|
||||
print_line("\t-", K, ": ", startup_benchmark_json[K], +" sec.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr, const StringName &p_class_name) :
|
||||
name(p_name),
|
||||
ptr(p_ptr),
|
||||
class_name(p_class_name) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
|
||||
if (rc && !rc->is_referenced()) {
|
||||
WARN_PRINT("You must use Ref<> to ensure the lifetime of a RefCounted object intended to be used as a singleton.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1,175 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* engine.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "core/os/main_loop.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/templates/list.h"
|
||||
#include "core/templates/vector.h"
|
||||
|
||||
template <typename T>
|
||||
class TypedArray;
|
||||
|
||||
class Engine {
|
||||
public:
|
||||
struct Singleton {
|
||||
StringName name;
|
||||
Object *ptr = nullptr;
|
||||
StringName class_name; //used for binding generation hinting
|
||||
bool user_created = false;
|
||||
Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr, const StringName &p_class_name = StringName());
|
||||
};
|
||||
|
||||
private:
|
||||
friend class Main;
|
||||
|
||||
uint64_t frames_drawn = 0;
|
||||
uint32_t _frame_delay = 0;
|
||||
uint64_t _frame_ticks = 0;
|
||||
double _process_step = 0;
|
||||
|
||||
int ips = 60;
|
||||
double physics_jitter_fix = 0.5;
|
||||
double _fps = 1;
|
||||
int _max_fps = 0;
|
||||
double _time_scale = 1.0;
|
||||
uint64_t _physics_frames = 0;
|
||||
int max_physics_steps_per_frame = 8;
|
||||
double _physics_interpolation_fraction = 0.0f;
|
||||
bool abort_on_gpu_errors = false;
|
||||
bool use_validation_layers = false;
|
||||
int32_t gpu_idx = -1;
|
||||
|
||||
uint64_t _process_frames = 0;
|
||||
bool _in_physics = false;
|
||||
|
||||
List<Singleton> singletons;
|
||||
HashMap<StringName, Object *> singleton_ptrs;
|
||||
|
||||
bool editor_hint = false;
|
||||
bool project_manager_hint = false;
|
||||
|
||||
static Engine *singleton;
|
||||
|
||||
String write_movie_path;
|
||||
String shader_cache_path;
|
||||
|
||||
Dictionary startup_benchmark_json;
|
||||
String startup_benchmark_section;
|
||||
uint64_t startup_benchmark_from = 0;
|
||||
uint64_t startup_benchmark_total_from = 0;
|
||||
|
||||
public:
|
||||
static Engine *get_singleton();
|
||||
|
||||
virtual void set_physics_ticks_per_second(int p_ips);
|
||||
virtual int get_physics_ticks_per_second() const;
|
||||
|
||||
virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
|
||||
virtual int get_max_physics_steps_per_frame() const;
|
||||
|
||||
void set_physics_jitter_fix(double p_threshold);
|
||||
double get_physics_jitter_fix() const;
|
||||
|
||||
virtual void set_max_fps(int p_fps);
|
||||
virtual int get_max_fps() const;
|
||||
|
||||
virtual double get_frames_per_second() const { return _fps; }
|
||||
|
||||
uint64_t get_frames_drawn();
|
||||
|
||||
uint64_t get_physics_frames() const { return _physics_frames; }
|
||||
uint64_t get_process_frames() const { return _process_frames; }
|
||||
bool is_in_physics_frame() const { return _in_physics; }
|
||||
uint64_t get_frame_ticks() const { return _frame_ticks; }
|
||||
double get_process_step() const { return _process_step; }
|
||||
double get_physics_interpolation_fraction() const { return _physics_interpolation_fraction; }
|
||||
|
||||
void set_time_scale(double p_scale);
|
||||
double get_time_scale() const;
|
||||
|
||||
void set_print_error_messages(bool p_enabled);
|
||||
bool is_printing_error_messages() const;
|
||||
|
||||
void set_frame_delay(uint32_t p_msec);
|
||||
uint32_t get_frame_delay() const;
|
||||
|
||||
void add_singleton(const Singleton &p_singleton);
|
||||
void get_singletons(List<Singleton> *p_singletons);
|
||||
bool has_singleton(const StringName &p_name) const;
|
||||
Object *get_singleton_object(const StringName &p_name) const;
|
||||
void remove_singleton(const StringName &p_name);
|
||||
bool is_singleton_user_created(const StringName &p_name) const;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) { editor_hint = p_enabled; }
|
||||
_FORCE_INLINE_ bool is_editor_hint() const { return editor_hint; }
|
||||
|
||||
_FORCE_INLINE_ void set_project_manager_hint(bool p_enabled) { project_manager_hint = p_enabled; }
|
||||
_FORCE_INLINE_ bool is_project_manager_hint() const { return project_manager_hint; }
|
||||
#else
|
||||
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) {}
|
||||
_FORCE_INLINE_ bool is_editor_hint() const { return false; }
|
||||
|
||||
_FORCE_INLINE_ void set_project_manager_hint(bool p_enabled) {}
|
||||
_FORCE_INLINE_ bool is_project_manager_hint() const { return false; }
|
||||
#endif
|
||||
|
||||
Dictionary get_version_info() const;
|
||||
Dictionary get_author_info() const;
|
||||
TypedArray<Dictionary> get_copyright_info() const;
|
||||
Dictionary get_donor_info() const;
|
||||
Dictionary get_license_info() const;
|
||||
String get_license_text() const;
|
||||
|
||||
void set_write_movie_path(const String &p_path);
|
||||
String get_write_movie_path() const;
|
||||
|
||||
String get_architecture_name() const;
|
||||
|
||||
void set_shader_cache_path(const String &p_path);
|
||||
String get_shader_cache_path() const;
|
||||
|
||||
bool is_abort_on_gpu_errors_enabled() const;
|
||||
bool is_validation_layers_enabled() const;
|
||||
int32_t get_gpu_index() const;
|
||||
|
||||
void startup_begin();
|
||||
void startup_benchmark_begin_measure(const String &p_what);
|
||||
void startup_benchmark_end_measure();
|
||||
void startup_dump(const String &p_to_file);
|
||||
|
||||
Engine();
|
||||
virtual ~Engine() {}
|
||||
};
|
||||
|
||||
#endif // ENGINE_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,225 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* project_settings.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef PROJECT_SETTINGS_H
|
||||
#define PROJECT_SETTINGS_H
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/os/thread_safe.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rb_set.h"
|
||||
|
||||
template <typename T>
|
||||
class TypedArray;
|
||||
|
||||
class ProjectSettings : public Object {
|
||||
GDCLASS(ProjectSettings, Object);
|
||||
_THREAD_SAFE_CLASS_
|
||||
|
||||
public:
|
||||
typedef HashMap<String, Variant> CustomMap;
|
||||
static const String PROJECT_DATA_DIR_NAME_SUFFIX;
|
||||
|
||||
enum {
|
||||
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
|
||||
NO_BUILTIN_ORDER_BASE = 1 << 16
|
||||
};
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
const static PackedStringArray get_required_features();
|
||||
const static PackedStringArray get_unsupported_features(const PackedStringArray &p_project_features);
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
struct AutoloadInfo {
|
||||
StringName name;
|
||||
String path;
|
||||
bool is_singleton = false;
|
||||
};
|
||||
|
||||
protected:
|
||||
struct VariantContainer {
|
||||
int order = 0;
|
||||
bool persist = false;
|
||||
bool basic = false;
|
||||
bool internal = false;
|
||||
Variant variant;
|
||||
Variant initial;
|
||||
bool hide_from_editor = false;
|
||||
bool restart_if_changed = false;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
bool ignore_value_in_docs = false;
|
||||
#endif
|
||||
|
||||
VariantContainer() {}
|
||||
|
||||
VariantContainer(const Variant &p_variant, int p_order, bool p_persist = false) :
|
||||
order(p_order),
|
||||
persist(p_persist),
|
||||
variant(p_variant) {
|
||||
}
|
||||
};
|
||||
|
||||
int last_order = NO_BUILTIN_ORDER_BASE;
|
||||
int last_builtin_order = 0;
|
||||
uint64_t last_save_time = 0;
|
||||
|
||||
RBMap<StringName, VariantContainer> props; // NOTE: Key order is used e.g. in the save_custom method.
|
||||
String resource_path;
|
||||
HashMap<StringName, PropertyInfo> custom_prop_info;
|
||||
bool using_datapack = false;
|
||||
bool project_loaded = false;
|
||||
List<String> input_presets;
|
||||
|
||||
HashSet<String> custom_features;
|
||||
HashMap<StringName, LocalVector<Pair<StringName, StringName>>> feature_overrides;
|
||||
|
||||
HashMap<StringName, AutoloadInfo> autoloads;
|
||||
|
||||
Array global_class_list;
|
||||
bool is_global_class_list_loaded = false;
|
||||
|
||||
String project_data_dir_name;
|
||||
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
bool _property_can_revert(const StringName &p_name) const;
|
||||
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
|
||||
|
||||
static ProjectSettings *singleton;
|
||||
|
||||
Error _load_settings_text(const String &p_path);
|
||||
Error _load_settings_binary(const String &p_path);
|
||||
Error _load_settings_text_or_binary(const String &p_text_path, const String &p_bin_path);
|
||||
|
||||
Error _save_settings_text(const String &p_file, const RBMap<String, List<String>> &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String());
|
||||
Error _save_settings_binary(const String &p_file, const RBMap<String, List<String>> &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String());
|
||||
|
||||
Error _save_custom_bnd(const String &p_file);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
const static PackedStringArray _get_supported_features();
|
||||
const static PackedStringArray _trim_to_supported_features(const PackedStringArray &p_project_features);
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
void _convert_to_last_version(int p_from_version);
|
||||
|
||||
bool _load_resource_pack(const String &p_pack, bool p_replace_files = true, int p_offset = 0);
|
||||
|
||||
void _add_property_info_bind(const Dictionary &p_info);
|
||||
|
||||
Error _setup(const String &p_path, const String &p_main_pack, bool p_upwards = false, bool p_ignore_override = false);
|
||||
|
||||
void _add_builtin_input_map();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static const int CONFIG_VERSION = 5;
|
||||
|
||||
void set_setting(const String &p_setting, const Variant &p_value);
|
||||
Variant get_setting(const String &p_setting, const Variant &p_default_value = Variant()) const;
|
||||
TypedArray<Dictionary> get_global_class_list();
|
||||
void store_global_class_list(const Array &p_classes);
|
||||
String get_global_class_list_path() const;
|
||||
|
||||
bool has_setting(String p_var) const;
|
||||
String localize_path(const String &p_path) const;
|
||||
String globalize_path(const String &p_path) const;
|
||||
|
||||
void set_initial_value(const String &p_name, const Variant &p_value);
|
||||
void set_as_basic(const String &p_name, bool p_basic);
|
||||
void set_as_internal(const String &p_name, bool p_internal);
|
||||
void set_restart_if_changed(const String &p_name, bool p_restart);
|
||||
void set_ignore_value_in_docs(const String &p_name, bool p_ignore);
|
||||
bool get_ignore_value_in_docs(const String &p_name) const;
|
||||
|
||||
String get_project_data_dir_name() const;
|
||||
String get_project_data_path() const;
|
||||
String get_resource_path() const;
|
||||
String get_safe_project_name() const;
|
||||
String get_imported_files_path() const;
|
||||
|
||||
static ProjectSettings *get_singleton();
|
||||
|
||||
void clear(const String &p_name);
|
||||
int get_order(const String &p_name) const;
|
||||
void set_order(const String &p_name, int p_order);
|
||||
void set_builtin_order(const String &p_name);
|
||||
bool is_builtin_setting(const String &p_name) const;
|
||||
|
||||
Error setup(const String &p_path, const String &p_main_pack, bool p_upwards = false, bool p_ignore_override = false);
|
||||
|
||||
Error load_custom(const String &p_path);
|
||||
Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>(), bool p_merge_with_current = true);
|
||||
Error save();
|
||||
void set_custom_property_info(const PropertyInfo &p_info);
|
||||
const HashMap<StringName, PropertyInfo> &get_custom_property_info() const;
|
||||
uint64_t get_last_saved_time() { return last_save_time; }
|
||||
|
||||
List<String> get_input_presets() const { return input_presets; }
|
||||
|
||||
Variant get_setting_with_override(const StringName &p_name) const;
|
||||
|
||||
bool is_using_datapack() const;
|
||||
bool is_project_loaded() const;
|
||||
|
||||
bool has_custom_feature(const String &p_feature) const;
|
||||
|
||||
const HashMap<StringName, AutoloadInfo> &get_autoload_list() const;
|
||||
void add_autoload(const AutoloadInfo &p_autoload);
|
||||
void remove_autoload(const StringName &p_autoload);
|
||||
bool has_autoload(const StringName &p_autoload) const;
|
||||
AutoloadInfo get_autoload(const StringName &p_name) const;
|
||||
|
||||
ProjectSettings();
|
||||
~ProjectSettings();
|
||||
};
|
||||
|
||||
// Not a macro any longer.
|
||||
Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed = false, bool p_ignore_value_in_docs = false, bool p_basic = false, bool p_internal = false);
|
||||
Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p_restart_if_changed = false, bool p_ignore_value_in_docs = false, bool p_basic = false, bool p_internal = false);
|
||||
|
||||
#define GLOBAL_DEF(m_var, m_value) _GLOBAL_DEF(m_var, m_value)
|
||||
#define GLOBAL_DEF_RST(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true)
|
||||
#define GLOBAL_DEF_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true)
|
||||
#define GLOBAL_DEF_RST_NOVAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true)
|
||||
#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get_setting_with_override(m_var)
|
||||
|
||||
#define GLOBAL_DEF_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, true)
|
||||
#define GLOBAL_DEF_RST_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, false, true)
|
||||
#define GLOBAL_DEF_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, true, true)
|
||||
#define GLOBAL_DEF_RST_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true, true)
|
||||
|
||||
#define GLOBAL_DEF_INTERNAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, false, true)
|
||||
|
||||
#endif // PROJECT_SETTINGS_H
|
||||
1796
core/core_bind.cpp
1796
core/core_bind.cpp
File diff suppressed because it is too large
Load Diff
569
core/core_bind.h
569
core/core_bind.h
@ -1,569 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* core_bind.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CORE_BIND_H
|
||||
#define CORE_BIND_H
|
||||
|
||||
#include "core/debugger/engine_profiler.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/os/semaphore.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "core/templates/safe_refcount.h"
|
||||
|
||||
class MainLoop;
|
||||
template <typename T>
|
||||
class TypedArray;
|
||||
|
||||
namespace core_bind {
|
||||
|
||||
class ResourceLoader : public Object {
|
||||
GDCLASS(ResourceLoader, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static ResourceLoader *singleton;
|
||||
|
||||
public:
|
||||
enum ThreadLoadStatus {
|
||||
THREAD_LOAD_INVALID_RESOURCE,
|
||||
THREAD_LOAD_IN_PROGRESS,
|
||||
THREAD_LOAD_FAILED,
|
||||
THREAD_LOAD_LOADED
|
||||
};
|
||||
|
||||
enum CacheMode {
|
||||
CACHE_MODE_IGNORE, // Resource and subresources do not use path cache, no path is set into resource.
|
||||
CACHE_MODE_REUSE, // Resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available.
|
||||
CACHE_MODE_REPLACE, // Resource and subresource use path cache, but replace existing loaded resources when available with information from disk.
|
||||
};
|
||||
|
||||
static ResourceLoader *get_singleton() { return singleton; }
|
||||
|
||||
Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
||||
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array());
|
||||
Ref<Resource> load_threaded_get(const String &p_path);
|
||||
|
||||
Ref<Resource> load(const String &p_path, const String &p_type_hint = "", CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
||||
Vector<String> get_recognized_extensions_for_type(const String &p_type);
|
||||
void add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front);
|
||||
void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader);
|
||||
void set_abort_on_missing_resources(bool p_abort);
|
||||
PackedStringArray get_dependencies(const String &p_path);
|
||||
bool has_cached(const String &p_path);
|
||||
bool exists(const String &p_path, const String &p_type_hint = "");
|
||||
ResourceUID::ID get_resource_uid(const String &p_path);
|
||||
|
||||
ResourceLoader() { singleton = this; }
|
||||
};
|
||||
|
||||
class ResourceSaver : public Object {
|
||||
GDCLASS(ResourceSaver, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static ResourceSaver *singleton;
|
||||
|
||||
public:
|
||||
enum SaverFlags {
|
||||
FLAG_NONE = 0,
|
||||
FLAG_RELATIVE_PATHS = 1,
|
||||
FLAG_BUNDLE_RESOURCES = 2,
|
||||
FLAG_CHANGE_PATH = 4,
|
||||
FLAG_OMIT_EDITOR_PROPERTIES = 8,
|
||||
FLAG_SAVE_BIG_ENDIAN = 16,
|
||||
FLAG_COMPRESS = 32,
|
||||
FLAG_REPLACE_SUBRESOURCE_PATHS = 64,
|
||||
};
|
||||
|
||||
static ResourceSaver *get_singleton() { return singleton; }
|
||||
|
||||
Error save(const Ref<Resource> &p_resource, const String &p_path, BitField<SaverFlags> p_flags);
|
||||
Vector<String> get_recognized_extensions(const Ref<Resource> &p_resource);
|
||||
void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front);
|
||||
void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
|
||||
|
||||
ResourceSaver() { singleton = this; }
|
||||
};
|
||||
|
||||
class OS : public Object {
|
||||
GDCLASS(OS, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static OS *singleton;
|
||||
|
||||
public:
|
||||
enum RenderingDriver {
|
||||
RENDERING_DRIVER_VULKAN,
|
||||
RENDERING_DRIVER_OPENGL3,
|
||||
};
|
||||
|
||||
virtual PackedStringArray get_connected_midi_inputs();
|
||||
virtual void open_midi_inputs();
|
||||
virtual void close_midi_inputs();
|
||||
|
||||
void set_low_processor_usage_mode(bool p_enabled);
|
||||
bool is_in_low_processor_usage_mode() const;
|
||||
|
||||
void set_low_processor_usage_mode_sleep_usec(int p_usec);
|
||||
int get_low_processor_usage_mode_sleep_usec() const;
|
||||
|
||||
void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||
void crash(const String &p_message);
|
||||
|
||||
Vector<String> get_system_fonts() const;
|
||||
String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
|
||||
Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
|
||||
String get_executable_path() const;
|
||||
String read_string_from_stdin();
|
||||
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
|
||||
int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false);
|
||||
int create_instance(const Vector<String> &p_arguments);
|
||||
Error kill(int p_pid);
|
||||
Error shell_open(String p_uri);
|
||||
|
||||
bool is_process_running(int p_pid) const;
|
||||
int get_process_id() const;
|
||||
|
||||
void set_restart_on_exit(bool p_restart, const Vector<String> &p_restart_arguments = Vector<String>());
|
||||
bool is_restart_on_exit_set() const;
|
||||
Vector<String> get_restart_on_exit_arguments() const;
|
||||
|
||||
bool has_environment(const String &p_var) const;
|
||||
String get_environment(const String &p_var) const;
|
||||
void set_environment(const String &p_var, const String &p_value) const;
|
||||
void unset_environment(const String &p_var) const;
|
||||
|
||||
String get_name() const;
|
||||
String get_distribution_name() const;
|
||||
String get_version() const;
|
||||
Vector<String> get_cmdline_args();
|
||||
Vector<String> get_cmdline_user_args();
|
||||
|
||||
Vector<String> get_video_adapter_driver_info() const;
|
||||
|
||||
String get_locale() const;
|
||||
String get_locale_language() const;
|
||||
|
||||
String get_model_name() const;
|
||||
|
||||
bool is_debug_build() const;
|
||||
|
||||
String get_unique_id() const;
|
||||
|
||||
String get_keycode_string(Key p_code) const;
|
||||
bool is_keycode_unicode(char32_t p_unicode) const;
|
||||
Key find_keycode_from_string(const String &p_code) const;
|
||||
|
||||
void set_use_file_access_save_and_swap(bool p_enable);
|
||||
|
||||
uint64_t get_static_memory_usage() const;
|
||||
uint64_t get_static_memory_peak_usage() const;
|
||||
|
||||
void delay_usec(int p_usec) const;
|
||||
void delay_msec(int p_msec) const;
|
||||
uint64_t get_ticks_msec() const;
|
||||
uint64_t get_ticks_usec() const;
|
||||
|
||||
bool is_userfs_persistent() const;
|
||||
|
||||
bool is_stdout_verbose() const;
|
||||
|
||||
int get_processor_count() const;
|
||||
String get_processor_name() const;
|
||||
|
||||
enum SystemDir {
|
||||
SYSTEM_DIR_DESKTOP,
|
||||
SYSTEM_DIR_DCIM,
|
||||
SYSTEM_DIR_DOCUMENTS,
|
||||
SYSTEM_DIR_DOWNLOADS,
|
||||
SYSTEM_DIR_MOVIES,
|
||||
SYSTEM_DIR_MUSIC,
|
||||
SYSTEM_DIR_PICTURES,
|
||||
SYSTEM_DIR_RINGTONES,
|
||||
};
|
||||
|
||||
String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const;
|
||||
|
||||
Error move_to_trash(const String &p_path) const;
|
||||
String get_user_data_dir() const;
|
||||
String get_config_dir() const;
|
||||
String get_data_dir() const;
|
||||
String get_cache_dir() const;
|
||||
|
||||
Error set_thread_name(const String &p_name);
|
||||
Thread::ID get_thread_caller_id() const;
|
||||
Thread::ID get_main_thread_id() const;
|
||||
|
||||
bool has_feature(const String &p_feature) const;
|
||||
|
||||
bool request_permission(const String &p_name);
|
||||
bool request_permissions();
|
||||
Vector<String> get_granted_permissions() const;
|
||||
|
||||
static OS *get_singleton() { return singleton; }
|
||||
|
||||
OS() { singleton = this; }
|
||||
};
|
||||
|
||||
class Geometry2D : public Object {
|
||||
GDCLASS(Geometry2D, Object);
|
||||
|
||||
static Geometry2D *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static Geometry2D *get_singleton();
|
||||
Variant segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
|
||||
Variant line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b);
|
||||
Vector<Vector2> get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
|
||||
Vector2 get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
|
||||
Vector2 get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b);
|
||||
bool point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const;
|
||||
|
||||
bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius);
|
||||
real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius);
|
||||
|
||||
bool is_polygon_clockwise(const Vector<Vector2> &p_polygon);
|
||||
bool is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon);
|
||||
Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
|
||||
Vector<int> triangulate_delaunay(const Vector<Vector2> &p_points);
|
||||
Vector<Point2> convex_hull(const Vector<Point2> &p_points);
|
||||
TypedArray<PackedVector2Array> decompose_polygon_in_convex(const Vector<Vector2> &p_polygon);
|
||||
|
||||
enum PolyBooleanOperation {
|
||||
OPERATION_UNION,
|
||||
OPERATION_DIFFERENCE,
|
||||
OPERATION_INTERSECTION,
|
||||
OPERATION_XOR
|
||||
};
|
||||
// 2D polygon boolean operations.
|
||||
TypedArray<PackedVector2Array> merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Union (add).
|
||||
TypedArray<PackedVector2Array> clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Difference (subtract).
|
||||
TypedArray<PackedVector2Array> intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Common area (multiply).
|
||||
TypedArray<PackedVector2Array> exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // All but common area (xor).
|
||||
|
||||
// 2D polyline vs polygon operations.
|
||||
TypedArray<PackedVector2Array> clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Cut.
|
||||
TypedArray<PackedVector2Array> intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Chop.
|
||||
|
||||
// 2D offset polygons/polylines.
|
||||
enum PolyJoinType {
|
||||
JOIN_SQUARE,
|
||||
JOIN_ROUND,
|
||||
JOIN_MITER
|
||||
};
|
||||
enum PolyEndType {
|
||||
END_POLYGON,
|
||||
END_JOINED,
|
||||
END_BUTT,
|
||||
END_SQUARE,
|
||||
END_ROUND
|
||||
};
|
||||
TypedArray<PackedVector2Array> offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE);
|
||||
TypedArray<PackedVector2Array> offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE, PolyEndType p_end_type = END_SQUARE);
|
||||
|
||||
Dictionary make_atlas(const Vector<Size2> &p_rects);
|
||||
|
||||
Geometry2D() { singleton = this; }
|
||||
};
|
||||
|
||||
class Geometry3D : public Object {
|
||||
GDCLASS(Geometry3D, Object);
|
||||
|
||||
static Geometry3D *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static Geometry3D *get_singleton();
|
||||
TypedArray<Plane> build_box_planes(const Vector3 &p_extents);
|
||||
TypedArray<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
|
||||
TypedArray<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z);
|
||||
Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
|
||||
Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
|
||||
Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
|
||||
Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
|
||||
Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
|
||||
|
||||
Vector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius);
|
||||
Vector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius);
|
||||
Vector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes);
|
||||
|
||||
Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane);
|
||||
|
||||
Geometry3D() { singleton = this; }
|
||||
};
|
||||
|
||||
class Marshalls : public Object {
|
||||
GDCLASS(Marshalls, Object);
|
||||
|
||||
static Marshalls *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static Marshalls *get_singleton();
|
||||
|
||||
String variant_to_base64(const Variant &p_var, bool p_full_objects = false);
|
||||
Variant base64_to_variant(const String &p_str, bool p_allow_objects = false);
|
||||
|
||||
String raw_to_base64(const Vector<uint8_t> &p_arr);
|
||||
Vector<uint8_t> base64_to_raw(const String &p_str);
|
||||
|
||||
String utf8_to_base64(const String &p_str);
|
||||
String base64_to_utf8(const String &p_str);
|
||||
|
||||
Marshalls() { singleton = this; }
|
||||
~Marshalls() { singleton = nullptr; }
|
||||
};
|
||||
|
||||
class Mutex : public RefCounted {
|
||||
GDCLASS(Mutex, RefCounted);
|
||||
::Mutex mutex;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void lock();
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
class Semaphore : public RefCounted {
|
||||
GDCLASS(Semaphore, RefCounted);
|
||||
::Semaphore semaphore;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void wait();
|
||||
bool try_wait();
|
||||
void post();
|
||||
};
|
||||
|
||||
class Thread : public RefCounted {
|
||||
GDCLASS(Thread, RefCounted);
|
||||
|
||||
protected:
|
||||
Variant ret;
|
||||
SafeFlag running;
|
||||
Callable target_callable;
|
||||
::Thread thread;
|
||||
static void _bind_methods();
|
||||
static void _start_func(void *ud);
|
||||
|
||||
public:
|
||||
enum Priority {
|
||||
PRIORITY_LOW,
|
||||
PRIORITY_NORMAL,
|
||||
PRIORITY_HIGH,
|
||||
PRIORITY_MAX
|
||||
};
|
||||
|
||||
Error start(const Callable &p_callable, Priority p_priority = PRIORITY_NORMAL);
|
||||
String get_id() const;
|
||||
bool is_started() const;
|
||||
bool is_alive() const;
|
||||
Variant wait_to_finish();
|
||||
};
|
||||
|
||||
namespace special {
|
||||
|
||||
class ClassDB : public Object {
|
||||
GDCLASS(ClassDB, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
PackedStringArray get_class_list() const;
|
||||
PackedStringArray get_inheriters_from_class(const StringName &p_class) const;
|
||||
StringName get_parent_class(const StringName &p_class) const;
|
||||
bool class_exists(const StringName &p_class) const;
|
||||
bool is_parent_class(const StringName &p_class, const StringName &p_inherits) const;
|
||||
bool can_instantiate(const StringName &p_class) const;
|
||||
Variant instantiate(const StringName &p_class) const;
|
||||
|
||||
bool has_signal(StringName p_class, StringName p_signal) const;
|
||||
Dictionary get_signal(StringName p_class, StringName p_signal) const;
|
||||
TypedArray<Dictionary> get_signal_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
|
||||
TypedArray<Dictionary> get_property_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
Variant get_property(Object *p_object, const StringName &p_property) const;
|
||||
Error set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const;
|
||||
|
||||
bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false) const;
|
||||
|
||||
TypedArray<Dictionary> get_method_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
|
||||
PackedStringArray get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||
bool has_integer_constant(const StringName &p_class, const StringName &p_name) const;
|
||||
int64_t get_integer_constant(const StringName &p_class, const StringName &p_name) const;
|
||||
|
||||
bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false) const;
|
||||
PackedStringArray get_enum_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||
PackedStringArray get_enum_constants(const StringName &p_class, const StringName &p_enum, bool p_no_inheritance = false) const;
|
||||
StringName get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false) const;
|
||||
|
||||
bool is_class_enabled(StringName p_class) const;
|
||||
|
||||
ClassDB() {}
|
||||
~ClassDB() {}
|
||||
};
|
||||
|
||||
} // namespace special
|
||||
|
||||
class Engine : public Object {
|
||||
GDCLASS(Engine, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static Engine *singleton;
|
||||
|
||||
public:
|
||||
static Engine *get_singleton() { return singleton; }
|
||||
void set_physics_ticks_per_second(int p_ips);
|
||||
int get_physics_ticks_per_second() const;
|
||||
|
||||
void set_max_physics_steps_per_frame(int p_max_physics_steps);
|
||||
int get_max_physics_steps_per_frame() const;
|
||||
|
||||
void set_physics_jitter_fix(double p_threshold);
|
||||
double get_physics_jitter_fix() const;
|
||||
double get_physics_interpolation_fraction() const;
|
||||
|
||||
void set_max_fps(int p_fps);
|
||||
int get_max_fps() const;
|
||||
|
||||
double get_frames_per_second() const;
|
||||
uint64_t get_physics_frames() const;
|
||||
uint64_t get_process_frames() const;
|
||||
|
||||
int get_frames_drawn();
|
||||
|
||||
void set_time_scale(double p_scale);
|
||||
double get_time_scale();
|
||||
|
||||
MainLoop *get_main_loop() const;
|
||||
|
||||
Dictionary get_version_info() const;
|
||||
Dictionary get_author_info() const;
|
||||
TypedArray<Dictionary> get_copyright_info() const;
|
||||
Dictionary get_donor_info() const;
|
||||
Dictionary get_license_info() const;
|
||||
String get_license_text() const;
|
||||
|
||||
String get_architecture_name() const;
|
||||
|
||||
bool is_in_physics_frame() const;
|
||||
|
||||
bool has_singleton(const StringName &p_name) const;
|
||||
Object *get_singleton_object(const StringName &p_name) const;
|
||||
void register_singleton(const StringName &p_name, Object *p_object);
|
||||
void unregister_singleton(const StringName &p_name);
|
||||
Vector<String> get_singleton_list() const;
|
||||
|
||||
Error register_script_language(ScriptLanguage *p_language);
|
||||
Error unregister_script_language(const ScriptLanguage *p_language);
|
||||
int get_script_language_count();
|
||||
ScriptLanguage *get_script_language(int p_index) const;
|
||||
|
||||
void set_editor_hint(bool p_enabled);
|
||||
bool is_editor_hint() const;
|
||||
|
||||
// `set_write_movie_path()` is not exposed to the scripting API as changing it at run-time has no effect.
|
||||
String get_write_movie_path() const;
|
||||
|
||||
void set_print_error_messages(bool p_enabled);
|
||||
bool is_printing_error_messages() const;
|
||||
|
||||
Engine() { singleton = this; }
|
||||
};
|
||||
|
||||
class EngineDebugger : public Object {
|
||||
GDCLASS(EngineDebugger, Object);
|
||||
|
||||
HashMap<StringName, Callable> captures;
|
||||
HashMap<StringName, Ref<EngineProfiler>> profilers;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static EngineDebugger *singleton;
|
||||
|
||||
public:
|
||||
static EngineDebugger *get_singleton() { return singleton; }
|
||||
|
||||
bool is_active();
|
||||
|
||||
void register_profiler(const StringName &p_name, Ref<EngineProfiler> p_profiler);
|
||||
void unregister_profiler(const StringName &p_name);
|
||||
bool is_profiling(const StringName &p_name);
|
||||
bool has_profiler(const StringName &p_name);
|
||||
void profiler_add_frame_data(const StringName &p_name, const Array &p_data);
|
||||
void profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts = Array());
|
||||
|
||||
void register_message_capture(const StringName &p_name, const Callable &p_callable);
|
||||
void unregister_message_capture(const StringName &p_name);
|
||||
bool has_capture(const StringName &p_name);
|
||||
|
||||
void send_message(const String &p_msg, const Array &p_data);
|
||||
|
||||
static Error call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured);
|
||||
|
||||
EngineDebugger() { singleton = this; }
|
||||
~EngineDebugger();
|
||||
};
|
||||
|
||||
} // namespace core_bind
|
||||
|
||||
VARIANT_ENUM_CAST(core_bind::ResourceLoader::ThreadLoadStatus);
|
||||
VARIANT_ENUM_CAST(core_bind::ResourceLoader::CacheMode);
|
||||
|
||||
VARIANT_BITFIELD_CAST(core_bind::ResourceSaver::SaverFlags);
|
||||
|
||||
VARIANT_ENUM_CAST(core_bind::OS::RenderingDriver);
|
||||
VARIANT_ENUM_CAST(core_bind::OS::SystemDir);
|
||||
|
||||
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyBooleanOperation);
|
||||
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyJoinType);
|
||||
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
|
||||
|
||||
VARIANT_ENUM_CAST(core_bind::Thread::Priority);
|
||||
|
||||
#endif // CORE_BIND_H
|
||||
@ -1,338 +0,0 @@
|
||||
"""Functions used to generate source files during build time
|
||||
|
||||
All such functions are invoked in a subprocess on Windows to prevent build flakiness.
|
||||
"""
|
||||
import zlib
|
||||
|
||||
from platform_methods import subprocess_main
|
||||
|
||||
|
||||
def escape_string(s):
|
||||
def charcode_to_c_escapes(c):
|
||||
rev_result = []
|
||||
while c >= 256:
|
||||
c, low = (c // 256, c % 256)
|
||||
rev_result.append("\\%03o" % low)
|
||||
rev_result.append("\\%03o" % c)
|
||||
return "".join(reversed(rev_result))
|
||||
|
||||
result = ""
|
||||
if isinstance(s, str):
|
||||
s = s.encode("utf-8")
|
||||
for c in s:
|
||||
if not (32 <= c < 127) or c in (ord("\\"), ord('"')):
|
||||
result += charcode_to_c_escapes(c)
|
||||
else:
|
||||
result += chr(c)
|
||||
return result
|
||||
|
||||
|
||||
def make_certs_header(target, source, env):
|
||||
src = source[0]
|
||||
dst = target[0]
|
||||
f = open(src, "rb")
|
||||
g = open(dst, "w", encoding="utf-8")
|
||||
buf = f.read()
|
||||
decomp_size = len(buf)
|
||||
|
||||
# Use maximum zlib compression level to further reduce file size
|
||||
# (at the cost of initial build times).
|
||||
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
|
||||
|
||||
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
g.write("#ifndef CERTS_COMPRESSED_GEN_H\n")
|
||||
g.write("#define CERTS_COMPRESSED_GEN_H\n")
|
||||
|
||||
# System certs path. Editor will use them if defined. (for package maintainers)
|
||||
path = env["system_certs_path"]
|
||||
g.write('#define _SYSTEM_CERTS_PATH "%s"\n' % str(path))
|
||||
if env["builtin_certs"]:
|
||||
# Defined here and not in env so changing it does not trigger a full rebuild.
|
||||
g.write("#define BUILTIN_CERTS_ENABLED\n")
|
||||
g.write("static const int _certs_compressed_size = " + str(len(buf)) + ";\n")
|
||||
g.write("static const int _certs_uncompressed_size = " + str(decomp_size) + ";\n")
|
||||
g.write("static const unsigned char _certs_compressed[] = {\n")
|
||||
for i in range(len(buf)):
|
||||
g.write("\t" + str(buf[i]) + ",\n")
|
||||
g.write("};\n")
|
||||
g.write("#endif // CERTS_COMPRESSED_GEN_H")
|
||||
|
||||
g.close()
|
||||
f.close()
|
||||
|
||||
|
||||
def make_authors_header(target, source, env):
|
||||
sections = [
|
||||
"Project Founders",
|
||||
"Lead Developer",
|
||||
"Project Manager",
|
||||
"Developers",
|
||||
]
|
||||
sections_id = [
|
||||
"AUTHORS_FOUNDERS",
|
||||
"AUTHORS_LEAD_DEVELOPERS",
|
||||
"AUTHORS_PROJECT_MANAGERS",
|
||||
"AUTHORS_DEVELOPERS",
|
||||
]
|
||||
|
||||
src = source[0]
|
||||
dst = target[0]
|
||||
f = open(src, "r", encoding="utf-8")
|
||||
g = open(dst, "w", encoding="utf-8")
|
||||
|
||||
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
g.write("#ifndef AUTHORS_GEN_H\n")
|
||||
g.write("#define AUTHORS_GEN_H\n")
|
||||
|
||||
reading = False
|
||||
|
||||
def close_section():
|
||||
g.write("\t0\n")
|
||||
g.write("};\n")
|
||||
|
||||
for line in f:
|
||||
if reading:
|
||||
if line.startswith(" "):
|
||||
g.write('\t"' + escape_string(line.strip()) + '",\n')
|
||||
continue
|
||||
if line.startswith("## "):
|
||||
if reading:
|
||||
close_section()
|
||||
reading = False
|
||||
for section, section_id in zip(sections, sections_id):
|
||||
if line.strip().endswith(section):
|
||||
current_section = escape_string(section_id)
|
||||
reading = True
|
||||
g.write("const char *const " + current_section + "[] = {\n")
|
||||
break
|
||||
|
||||
if reading:
|
||||
close_section()
|
||||
|
||||
g.write("#endif // AUTHORS_GEN_H\n")
|
||||
|
||||
g.close()
|
||||
f.close()
|
||||
|
||||
|
||||
def make_donors_header(target, source, env):
|
||||
sections = [
|
||||
"Platinum sponsors",
|
||||
"Gold sponsors",
|
||||
"Silver sponsors",
|
||||
"Bronze sponsors",
|
||||
"Mini sponsors",
|
||||
"Gold donors",
|
||||
"Silver donors",
|
||||
"Bronze donors",
|
||||
]
|
||||
sections_id = [
|
||||
"DONORS_SPONSOR_PLATINUM",
|
||||
"DONORS_SPONSOR_GOLD",
|
||||
"DONORS_SPONSOR_SILVER",
|
||||
"DONORS_SPONSOR_BRONZE",
|
||||
"DONORS_SPONSOR_MINI",
|
||||
"DONORS_GOLD",
|
||||
"DONORS_SILVER",
|
||||
"DONORS_BRONZE",
|
||||
]
|
||||
|
||||
src = source[0]
|
||||
dst = target[0]
|
||||
f = open(src, "r", encoding="utf-8")
|
||||
g = open(dst, "w", encoding="utf-8")
|
||||
|
||||
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
g.write("#ifndef DONORS_GEN_H\n")
|
||||
g.write("#define DONORS_GEN_H\n")
|
||||
|
||||
reading = False
|
||||
|
||||
def close_section():
|
||||
g.write("\t0\n")
|
||||
g.write("};\n")
|
||||
|
||||
for line in f:
|
||||
if reading >= 0:
|
||||
if line.startswith(" "):
|
||||
g.write('\t"' + escape_string(line.strip()) + '",\n')
|
||||
continue
|
||||
if line.startswith("## "):
|
||||
if reading:
|
||||
close_section()
|
||||
reading = False
|
||||
for section, section_id in zip(sections, sections_id):
|
||||
if line.strip().endswith(section):
|
||||
current_section = escape_string(section_id)
|
||||
reading = True
|
||||
g.write("const char *const " + current_section + "[] = {\n")
|
||||
break
|
||||
|
||||
if reading:
|
||||
close_section()
|
||||
|
||||
g.write("#endif // DONORS_GEN_H\n")
|
||||
|
||||
g.close()
|
||||
f.close()
|
||||
|
||||
|
||||
def make_license_header(target, source, env):
|
||||
src_copyright = source[0]
|
||||
src_license = source[1]
|
||||
dst = target[0]
|
||||
|
||||
class LicenseReader:
|
||||
def __init__(self, license_file):
|
||||
self._license_file = license_file
|
||||
self.line_num = 0
|
||||
self.current = self.next_line()
|
||||
|
||||
def next_line(self):
|
||||
line = self._license_file.readline()
|
||||
self.line_num += 1
|
||||
while line.startswith("#"):
|
||||
line = self._license_file.readline()
|
||||
self.line_num += 1
|
||||
self.current = line
|
||||
return line
|
||||
|
||||
def next_tag(self):
|
||||
if not ":" in self.current:
|
||||
return ("", [])
|
||||
tag, line = self.current.split(":", 1)
|
||||
lines = [line.strip()]
|
||||
while self.next_line() and self.current.startswith(" "):
|
||||
lines.append(self.current.strip())
|
||||
return (tag, lines)
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
projects: dict = OrderedDict()
|
||||
license_list = []
|
||||
|
||||
with open(src_copyright, "r", encoding="utf-8") as copyright_file:
|
||||
reader = LicenseReader(copyright_file)
|
||||
part = {}
|
||||
while reader.current:
|
||||
tag, content = reader.next_tag()
|
||||
if tag in ("Files", "Copyright", "License"):
|
||||
part[tag] = content[:]
|
||||
elif tag == "Comment":
|
||||
# attach part to named project
|
||||
projects[content[0]] = projects.get(content[0], []) + [part]
|
||||
|
||||
if not tag or not reader.current:
|
||||
# end of a paragraph start a new part
|
||||
if "License" in part and not "Files" in part:
|
||||
# no Files tag in this one, so assume standalone license
|
||||
license_list.append(part["License"])
|
||||
part = {}
|
||||
reader.next_line()
|
||||
|
||||
data_list: list = []
|
||||
for project in iter(projects.values()):
|
||||
for part in project:
|
||||
part["file_index"] = len(data_list)
|
||||
data_list += part["Files"]
|
||||
part["copyright_index"] = len(data_list)
|
||||
data_list += part["Copyright"]
|
||||
|
||||
with open(dst, "w", encoding="utf-8") as f:
|
||||
|
||||
f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
f.write("#ifndef LICENSE_GEN_H\n")
|
||||
f.write("#define LICENSE_GEN_H\n")
|
||||
f.write("const char *const GODOT_LICENSE_TEXT =")
|
||||
|
||||
with open(src_license, "r", encoding="utf-8") as license_file:
|
||||
for line in license_file:
|
||||
escaped_string = escape_string(line.strip())
|
||||
f.write('\n\t\t"' + escaped_string + '\\n"')
|
||||
f.write(";\n\n")
|
||||
|
||||
f.write(
|
||||
"struct ComponentCopyrightPart {\n"
|
||||
"\tconst char *license;\n"
|
||||
"\tconst char *const *files;\n"
|
||||
"\tconst char *const *copyright_statements;\n"
|
||||
"\tint file_count;\n"
|
||||
"\tint copyright_count;\n"
|
||||
"};\n\n"
|
||||
)
|
||||
|
||||
f.write(
|
||||
"struct ComponentCopyright {\n"
|
||||
"\tconst char *name;\n"
|
||||
"\tconst ComponentCopyrightPart *parts;\n"
|
||||
"\tint part_count;\n"
|
||||
"};\n\n"
|
||||
)
|
||||
|
||||
f.write("const char *const COPYRIGHT_INFO_DATA[] = {\n")
|
||||
for line in data_list:
|
||||
f.write('\t"' + escape_string(line) + '",\n')
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("const ComponentCopyrightPart COPYRIGHT_PROJECT_PARTS[] = {\n")
|
||||
part_index = 0
|
||||
part_indexes = {}
|
||||
for project_name, project in iter(projects.items()):
|
||||
part_indexes[project_name] = part_index
|
||||
for part in project:
|
||||
f.write(
|
||||
'\t{ "'
|
||||
+ escape_string(part["License"][0])
|
||||
+ '", '
|
||||
+ "©RIGHT_INFO_DATA["
|
||||
+ str(part["file_index"])
|
||||
+ "], "
|
||||
+ "©RIGHT_INFO_DATA["
|
||||
+ str(part["copyright_index"])
|
||||
+ "], "
|
||||
+ str(len(part["Files"]))
|
||||
+ ", "
|
||||
+ str(len(part["Copyright"]))
|
||||
+ " },\n"
|
||||
)
|
||||
part_index += 1
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("const int COPYRIGHT_INFO_COUNT = " + str(len(projects)) + ";\n")
|
||||
|
||||
f.write("const ComponentCopyright COPYRIGHT_INFO[] = {\n")
|
||||
for project_name, project in iter(projects.items()):
|
||||
f.write(
|
||||
'\t{ "'
|
||||
+ escape_string(project_name)
|
||||
+ '", '
|
||||
+ "©RIGHT_PROJECT_PARTS["
|
||||
+ str(part_indexes[project_name])
|
||||
+ "], "
|
||||
+ str(len(project))
|
||||
+ " },\n"
|
||||
)
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("const int LICENSE_COUNT = " + str(len(license_list)) + ";\n")
|
||||
|
||||
f.write("const char *const LICENSE_NAMES[] = {\n")
|
||||
for l in license_list:
|
||||
f.write('\t"' + escape_string(l[0]) + '",\n')
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("const char *const LICENSE_BODIES[] = {\n\n")
|
||||
for l in license_list:
|
||||
for line in l[1:]:
|
||||
if line == ".":
|
||||
f.write('\t"\\n"\n')
|
||||
else:
|
||||
f.write('\t"' + escape_string(line) + '\\n"\n')
|
||||
f.write('\t"",\n\n')
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("#endif // LICENSE_GEN_H\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
subprocess_main(globals())
|
||||
@ -1,850 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* core_constants.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 "core_constants.h"
|
||||
|
||||
#include "core/input/input_event.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "core/templates/hash_set.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
struct _CoreConstant {
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
bool ignore_value_in_docs = false;
|
||||
bool is_bitfield = false;
|
||||
#endif
|
||||
StringName enum_name;
|
||||
const char *name = nullptr;
|
||||
int64_t value = 0;
|
||||
|
||||
_CoreConstant() {}
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
_CoreConstant(const StringName &p_enum_name, const char *p_name, int64_t p_value, bool p_ignore_value_in_docs = false, bool p_is_bitfield = false) :
|
||||
ignore_value_in_docs(p_ignore_value_in_docs),
|
||||
is_bitfield(p_is_bitfield),
|
||||
enum_name(p_enum_name),
|
||||
name(p_name),
|
||||
value(p_value) {
|
||||
}
|
||||
#else
|
||||
_CoreConstant(const StringName &p_enum_name, const char *p_name, int64_t p_value) :
|
||||
enum_name(p_enum_name),
|
||||
name(p_name),
|
||||
value(p_value) {
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
static Vector<_CoreConstant> _global_constants;
|
||||
static HashMap<StringName, int> _global_constants_map;
|
||||
static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
||||
#define BIND_CORE_CONSTANT(m_constant) \
|
||||
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); \
|
||||
_global_constants_map[#m_constant] = _global_constants.size() - 1;
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
|
||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
|
||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
// This just binds enum classes as if they were regular enum constants.
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_enum_name(m_constant, #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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \
|
||||
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant, true)); \
|
||||
_global_constants_map[#m_constant] = _global_constants.size() - 1;
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
|
||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
|
||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BIND_CORE_CONSTANT(m_constant) \
|
||||
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); \
|
||||
_global_constants_map[#m_constant] = _global_constants.size() - 1;
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_bitfield_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
// This just binds enum classes as if they were regular enum constants.
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#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); \
|
||||
_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_enum_name(m_constant, #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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \
|
||||
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); \
|
||||
_global_constants_map[#m_constant] = _global_constants.size() - 1;
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
||||
{ \
|
||||
StringName enum_name = __constant_get_enum_name(m_constant, #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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void register_global_constants() {
|
||||
BIND_CORE_ENUM_CONSTANT(SIDE_LEFT);
|
||||
BIND_CORE_ENUM_CONSTANT(SIDE_TOP);
|
||||
BIND_CORE_ENUM_CONSTANT(SIDE_RIGHT);
|
||||
BIND_CORE_ENUM_CONSTANT(SIDE_BOTTOM);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(CORNER_TOP_LEFT);
|
||||
BIND_CORE_ENUM_CONSTANT(CORNER_TOP_RIGHT);
|
||||
BIND_CORE_ENUM_CONSTANT(CORNER_BOTTOM_RIGHT);
|
||||
BIND_CORE_ENUM_CONSTANT(CORNER_BOTTOM_LEFT);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(VERTICAL);
|
||||
BIND_CORE_ENUM_CONSTANT(HORIZONTAL);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(CLOCKWISE);
|
||||
BIND_CORE_ENUM_CONSTANT(COUNTERCLOCKWISE);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_LEFT);
|
||||
BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_CENTER);
|
||||
BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_RIGHT);
|
||||
BIND_CORE_ENUM_CONSTANT(HORIZONTAL_ALIGNMENT_FILL);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_TOP);
|
||||
BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_CENTER);
|
||||
BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_BOTTOM);
|
||||
BIND_CORE_ENUM_CONSTANT(VERTICAL_ALIGNMENT_FILL);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TOP_TO);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_CENTER_TO);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BASELINE_TO);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BOTTOM_TO);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_TOP);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_CENTER);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_BASELINE);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TO_BOTTOM);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TOP);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_CENTER);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_BOTTOM);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_IMAGE_MASK);
|
||||
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TEXT_MASK);
|
||||
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(EulerOrder, EULER_ORDER, XYZ);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(EulerOrder, EULER_ORDER, XZY);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(EulerOrder, EULER_ORDER, YXZ);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(EulerOrder, EULER_ORDER, YZX);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(EulerOrder, EULER_ORDER, ZXY);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(EulerOrder, EULER_ORDER, ZYX);
|
||||
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NONE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SPECIAL);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ESCAPE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TAB);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKTAB);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKSPACE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ENTER);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_ENTER);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, INSERT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_DELETE, KEY_DELETE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAUSE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PRINT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SYSREQ);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CLEAR);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HOME);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, END);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, RIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DOWN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAGEUP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PAGEDOWN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SHIFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CTRL);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, META);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ALT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, CAPSLOCK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NUMLOCK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SCROLLLOCK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F1);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F2);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F3);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F4);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F5);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F6);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F7);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F8);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F9);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F10);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F11);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F12);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F13);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F14);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F15);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F16);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F17);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F18);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F19);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F20);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F21);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F22);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F23);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F24);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F25);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F26);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F27);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F28);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F29);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F30);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F31);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F32);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F33);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F34);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F35);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_MULTIPLY);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_DIVIDE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_SUBTRACT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_PERIOD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_ADD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_0);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_1);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_2);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_3);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_4);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_5);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_6);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_7);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_8);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KP_9);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MENU);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HYPER);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HELP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, FORWARD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STOP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, REFRESH);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEDOWN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEMUTE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, VOLUMEUP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIAPLAY);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIASTOP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIAPREVIOUS);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIANEXT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MEDIARECORD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, HOMEPAGE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, FAVORITES);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SEARCH);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, STANDBY);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, OPENURL);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHMAIL);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHMEDIA);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH0);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH1);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH2);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH3);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH4);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH5);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH6);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH7);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH8);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCH9);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHA);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHB);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHC);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LAUNCHF);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UNKNOWN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SPACE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EXCLAM);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUOTEDBL);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NUMBERSIGN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, DOLLAR);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERCENT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AMPERSAND);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, APOSTROPHE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARENLEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PARENRIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASTERISK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PLUS);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COMMA);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, MINUS);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, PERIOD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SLASH);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_0, KEY_0);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_1, KEY_1);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_2, KEY_2);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_3, KEY_3);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_4, KEY_4);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_5, KEY_5);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_6, KEY_6);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_7, KEY_7);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_8, KEY_8);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(Key, KEY_9, KEY_9);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, COLON);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SEMICOLON);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, LESS);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, EQUAL);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GREATER);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUESTION);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, AT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, A);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, B);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, C);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, D);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, E);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, F);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, G);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, H);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, I);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, J);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, K);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, L);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, M);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, N);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, O);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, P);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Q);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, R);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, S);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, T);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, U);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, V);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, W);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, X);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Y);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, Z);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACKETLEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BACKSLASH);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACKETRIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASCIICIRCUM);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, UNDERSCORE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, QUOTELEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACELEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BAR);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, BRACERIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ASCIITILDE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, YEN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SECTION);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, GLOBE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, KEYBOARD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, JIS_EISU);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, JIS_KANA);
|
||||
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(KeyModifierMask, KEY_CODE_MASK, CODE_MASK);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(KeyModifierMask, KEY_MODIFIER_MASK, MODIFIER_MASK);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, CMD_OR_CTRL);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, SHIFT);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, ALT);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, META);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, CTRL);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, KPAD);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
|
||||
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, NONE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, LEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, RIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MIDDLE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_UP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_DOWN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_LEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, WHEEL_RIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON1, MB_XBUTTON1);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(MouseButton, MOUSE_BUTTON_XBUTTON2, MB_XBUTTON2);
|
||||
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, LEFT);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, RIGHT);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MIDDLE);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MB_XBUTTON1);
|
||||
BIND_CORE_BITFIELD_CLASS_FLAG(MouseButtonMask, MOUSE_BUTTON_MASK, MB_XBUTTON2);
|
||||
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, INVALID);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, A);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, B);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, X);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, Y);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, BACK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, GUIDE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, START);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, LEFT_STICK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, RIGHT_STICK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, LEFT_SHOULDER);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, RIGHT_SHOULDER);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_UP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_DOWN);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_LEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, DPAD_RIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC1);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE1);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE2);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE3);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE4);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, TOUCHPAD);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, SDL_MAX);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MAX);
|
||||
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, INVALID);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, LEFT_X);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, LEFT_Y);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, RIGHT_X);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, RIGHT_Y);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, TRIGGER_LEFT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, TRIGGER_RIGHT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, SDL_MAX);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, MAX);
|
||||
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NONE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_OFF);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_ON);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, AFTERTOUCH);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CONTROL_CHANGE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PROGRAM_CHANGE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CHANNEL_PRESSURE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, PITCH_BEND);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SYSTEM_EXCLUSIVE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, QUARTER_FRAME);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SONG_POSITION_POINTER);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SONG_SELECT);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, TUNE_REQUEST);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, TIMING_CLOCK);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, START);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, CONTINUE);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, STOP);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, ACTIVE_SENSING);
|
||||
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, SYSTEM_RESET);
|
||||
|
||||
// error list
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(OK); // (0)
|
||||
BIND_CORE_ENUM_CONSTANT(FAILED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_UNAVAILABLE);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_UNCONFIGURED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_UNAUTHORIZED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_PARAMETER_RANGE_ERROR); // (5)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_OUT_OF_MEMORY);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_NOT_FOUND);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_BAD_DRIVE);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_BAD_PATH);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_NO_PERMISSION); // (10)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_ALREADY_IN_USE);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_CANT_OPEN);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_CANT_WRITE);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_CANT_READ);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_UNRECOGNIZED); // (15)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_CORRUPT);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_MISSING_DEPENDENCIES);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_FILE_EOF);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CANT_OPEN);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CANT_CREATE); // (20)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_QUERY_FAILED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_ALREADY_IN_USE);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_LOCKED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_TIMEOUT);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CANT_CONNECT); // (25)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CANT_RESOLVE);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CONNECTION_ERROR);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CANT_ACQUIRE_RESOURCE);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CANT_FORK);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_INVALID_DATA); // (30)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_INVALID_PARAMETER);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_ALREADY_EXISTS);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_DOES_NOT_EXIST);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_DATABASE_CANT_READ);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_DATABASE_CANT_WRITE); // (35)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_COMPILATION_FAILED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_METHOD_NOT_FOUND);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_LINK_FAILED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_SCRIPT_FAILED);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_CYCLIC_LINK); // (40)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_INVALID_DECLARATION);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_DUPLICATE_SYMBOL);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_PARSE_ERROR);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_BUSY);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_SKIP); // (45)
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_HELP);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_BUG);
|
||||
BIND_CORE_ENUM_CONSTANT(ERR_PRINTER_ON_FIRE);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NONE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_RANGE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM_SUGGESTION);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LINK);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FLAGS);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_PHYSICS);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_NAVIGATION);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_RENDER);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_PHYSICS);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_NAVIGATION);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FILE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_DIR);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_FILE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_DIR);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_RESOURCE_TYPE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MULTILINE_TEXT);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXPRESSION);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_ID);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TYPE_STRING);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_TOO_BIG);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_PATH_VALID_TYPES);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_SAVE_FILE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_SAVE_FILE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_OBJECTID);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_TYPE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_HIDE_QUATERNION_EDIT);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
|
||||
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NONE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_STORAGE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_INTERNAL);
|
||||
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CHECKABLE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CHECKED);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_GROUP);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CATEGORY);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SUBGROUP);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CLASS_IS_BITFIELD);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NO_INSTANCE_STATE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_RESTART_IF_CHANGED);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SCRIPT_VARIABLE);
|
||||
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_STORE_IF_NULL);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_CLASS_IS_ENUM);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NIL_IS_VARIANT);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_ARRAY);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_ALWAYS_DUPLICATE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NEVER_DUPLICATE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_HIGH_END_GFX);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_KEYING_INCREMENTS);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFERRED_SET_RESOURCE);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_EDITOR_BASIC_SETTING);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_READ_ONLY);
|
||||
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_DEFAULT);
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NO_EDITOR);
|
||||
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_NORMAL);
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_EDITOR);
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_CONST);
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VIRTUAL);
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VARARG);
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_STATIC);
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_OBJECT_CORE);
|
||||
BIND_CORE_BITFIELD_FLAG(METHOD_FLAGS_DEFAULT);
|
||||
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT", Variant::FLOAT);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING", Variant::STRING);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2", Variant::VECTOR2);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2I", Variant::VECTOR2I);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RECT2", Variant::RECT2);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RECT2I", Variant::RECT2I);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3", Variant::VECTOR3);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3I", Variant::VECTOR3I);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM2D", Variant::TRANSFORM2D);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR4", Variant::VECTOR4);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR4I", Variant::VECTOR4I);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PLANE", Variant::PLANE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_QUATERNION", Variant::QUATERNION);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_AABB", Variant::AABB);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM3D", Variant::TRANSFORM3D);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PROJECTION", Variant::PROJECTION);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RID", Variant::RID);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_OBJECT", Variant::OBJECT);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_CALLABLE", Variant::CALLABLE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_SIGNAL", Variant::SIGNAL);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_DICTIONARY", Variant::DICTIONARY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_ARRAY", Variant::ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_BYTE_ARRAY", Variant::PACKED_BYTE_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_INT32_ARRAY", Variant::PACKED_INT32_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_INT64_ARRAY", Variant::PACKED_INT64_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_FLOAT32_ARRAY", Variant::PACKED_FLOAT32_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_FLOAT64_ARRAY", Variant::PACKED_FLOAT64_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_STRING_ARRAY", Variant::PACKED_STRING_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_VECTOR2_ARRAY", Variant::PACKED_VECTOR2_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_VECTOR3_ARRAY", Variant::PACKED_VECTOR3_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PACKED_COLOR_ARRAY", Variant::PACKED_COLOR_ARRAY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX);
|
||||
|
||||
//comparison
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_EQUAL", Variant::OP_EQUAL);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NOT_EQUAL", Variant::OP_NOT_EQUAL);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_LESS", Variant::OP_LESS);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_LESS_EQUAL", Variant::OP_LESS_EQUAL);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_GREATER", Variant::OP_GREATER);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_GREATER_EQUAL", Variant::OP_GREATER_EQUAL);
|
||||
//mathematic
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_ADD", Variant::OP_ADD);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SUBTRACT", Variant::OP_SUBTRACT);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MULTIPLY", Variant::OP_MULTIPLY);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_DIVIDE", Variant::OP_DIVIDE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NEGATE", Variant::OP_NEGATE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_POSITIVE", Variant::OP_POSITIVE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MODULE", Variant::OP_MODULE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_POWER", Variant::OP_POWER);
|
||||
//bitwise
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_LEFT", Variant::OP_SHIFT_LEFT);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_RIGHT", Variant::OP_SHIFT_RIGHT);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_AND", Variant::OP_BIT_AND);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_OR", Variant::OP_BIT_OR);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_XOR", Variant::OP_BIT_XOR);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_NEGATE", Variant::OP_BIT_NEGATE);
|
||||
//logic
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_AND", Variant::OP_AND);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_OR", Variant::OP_OR);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_XOR", Variant::OP_XOR);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NOT", Variant::OP_NOT);
|
||||
//containment
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_IN", Variant::OP_IN);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MAX", Variant::OP_MAX);
|
||||
}
|
||||
|
||||
void unregister_global_constants() {
|
||||
_global_constants.clear();
|
||||
}
|
||||
|
||||
int CoreConstants::get_global_constant_count() {
|
||||
return _global_constants.size();
|
||||
}
|
||||
|
||||
StringName CoreConstants::get_global_constant_enum(int p_idx) {
|
||||
return _global_constants[p_idx].enum_name;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
bool CoreConstants::is_global_constant_bitfield(int p_idx) {
|
||||
return _global_constants[p_idx].is_bitfield;
|
||||
}
|
||||
|
||||
bool CoreConstants::get_ignore_value_in_docs(int p_idx) {
|
||||
return _global_constants[p_idx].ignore_value_in_docs;
|
||||
}
|
||||
#else
|
||||
bool CoreConstants::is_global_constant_bitfield(int p_idx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CoreConstants::get_ignore_value_in_docs(int p_idx) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *CoreConstants::get_global_constant_name(int p_idx) {
|
||||
return _global_constants[p_idx].name;
|
||||
}
|
||||
|
||||
int64_t CoreConstants::get_global_constant_value(int p_idx) {
|
||||
return _global_constants[p_idx].value;
|
||||
}
|
||||
|
||||
bool CoreConstants::is_global_constant(const StringName &p_name) {
|
||||
return _global_constants_map.has(p_name);
|
||||
}
|
||||
|
||||
int CoreConstants::get_global_constant_index(const StringName &p_name) {
|
||||
ERR_FAIL_COND_V_MSG(!_global_constants_map.has(p_name), -1, "Trying to get index of non-existing constant.");
|
||||
return _global_constants_map[p_name];
|
||||
}
|
||||
|
||||
bool CoreConstants::is_global_enum(const StringName &p_enum) {
|
||||
return _global_enums.has(p_enum);
|
||||
}
|
||||
|
||||
void CoreConstants::get_enum_values(StringName p_enum, HashMap<StringName, int64_t> *p_values) {
|
||||
ERR_FAIL_NULL_MSG(p_values, "Trying to get enum values with null map.");
|
||||
ERR_FAIL_COND_MSG(!_global_enums.has(p_enum), "Trying to get values of non-existing enum.");
|
||||
for (const _CoreConstant &constant : _global_enums[p_enum]) {
|
||||
(*p_values)[constant.name] = constant.value;
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* core_constants.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CORE_CONSTANTS_H
|
||||
#define CORE_CONSTANTS_H
|
||||
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/templates/hash_set.h"
|
||||
|
||||
class CoreConstants {
|
||||
public:
|
||||
static int get_global_constant_count();
|
||||
static StringName get_global_constant_enum(int p_idx);
|
||||
static bool is_global_constant_bitfield(int p_idx);
|
||||
static bool get_ignore_value_in_docs(int p_idx);
|
||||
static const char *get_global_constant_name(int p_idx);
|
||||
static int64_t get_global_constant_value(int p_idx);
|
||||
static bool is_global_constant(const StringName &p_name);
|
||||
static int get_global_constant_index(const StringName &p_name);
|
||||
static bool is_global_enum(const StringName &p_enum);
|
||||
static void get_enum_values(StringName p_enum, HashMap<StringName, int64_t> *p_values);
|
||||
};
|
||||
|
||||
#endif // CORE_CONSTANTS_H
|
||||
@ -1,35 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* core_globals.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 "core_globals.h"
|
||||
|
||||
bool CoreGlobals::leak_reporting_enabled = true;
|
||||
bool CoreGlobals::print_line_enabled = true;
|
||||
bool CoreGlobals::print_error_enabled = true;
|
||||
@ -1,44 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* core_globals.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CORE_GLOBALS_H
|
||||
#define CORE_GLOBALS_H
|
||||
|
||||
// Home for state needed from global functions
|
||||
// that cannot be stored in Engine or OS due to e.g. circular includes
|
||||
|
||||
class CoreGlobals {
|
||||
public:
|
||||
static bool leak_reporting_enabled;
|
||||
static bool print_line_enabled;
|
||||
static bool print_error_enabled;
|
||||
};
|
||||
|
||||
#endif // CORE_GLOBALS_H
|
||||
@ -1,80 +1,47 @@
|
||||
/**************************************************************************/
|
||||
/* core_string_names.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
/*************************************************************************/
|
||||
/* core_string_names.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "core_string_names.h"
|
||||
|
||||
CoreStringNames *CoreStringNames::singleton = nullptr;
|
||||
CoreStringNames *CoreStringNames::singleton = NULL;
|
||||
|
||||
CoreStringNames::CoreStringNames() :
|
||||
_free(StaticCString::create("free")),
|
||||
changed(StaticCString::create("changed")),
|
||||
_script(StaticCString::create("script")),
|
||||
script_changed(StaticCString::create("script_changed")),
|
||||
___pdcdata(StaticCString::create("___pdcdata")),
|
||||
__getvar(StaticCString::create("__getvar")),
|
||||
_iter_init(StaticCString::create("_iter_init")),
|
||||
_iter_next(StaticCString::create("_iter_next")),
|
||||
_iter_get(StaticCString::create("_iter_get")),
|
||||
get_rid(StaticCString::create("get_rid")),
|
||||
_to_string(StaticCString::create("_to_string")),
|
||||
#ifdef TOOLS_ENABLED
|
||||
_sections_unfolded(StaticCString::create("_sections_unfolded")),
|
||||
#endif
|
||||
_custom_features(StaticCString::create("_custom_features")),
|
||||
x(StaticCString::create("x")),
|
||||
y(StaticCString::create("y")),
|
||||
z(StaticCString::create("z")),
|
||||
w(StaticCString::create("w")),
|
||||
r(StaticCString::create("r")),
|
||||
g(StaticCString::create("g")),
|
||||
b(StaticCString::create("b")),
|
||||
a(StaticCString::create("a")),
|
||||
position(StaticCString::create("position")),
|
||||
size(StaticCString::create("size")),
|
||||
end(StaticCString::create("end")),
|
||||
basis(StaticCString::create("basis")),
|
||||
origin(StaticCString::create("origin")),
|
||||
normal(StaticCString::create("normal")),
|
||||
d(StaticCString::create("d")),
|
||||
h(StaticCString::create("h")),
|
||||
s(StaticCString::create("s")),
|
||||
v(StaticCString::create("v")),
|
||||
r8(StaticCString::create("r8")),
|
||||
g8(StaticCString::create("g8")),
|
||||
b8(StaticCString::create("b8")),
|
||||
a8(StaticCString::create("a8")),
|
||||
call(StaticCString::create("call")),
|
||||
call_deferred(StaticCString::create("call_deferred")),
|
||||
bind(StaticCString::create("bind")),
|
||||
unbind(StaticCString::create("unbind")),
|
||||
emit(StaticCString::create("emit")),
|
||||
notification(StaticCString::create("notification")),
|
||||
property_list_changed(StaticCString::create("property_list_changed")) {
|
||||
CoreStringNames::CoreStringNames() {
|
||||
|
||||
_free = StaticCString::create("free");
|
||||
changed = StaticCString::create("changed");
|
||||
_meta = StaticCString::create("__meta__");
|
||||
_script = StaticCString::create("script/script");
|
||||
script_changed = StaticCString::create("script_changed");
|
||||
___pdcdata = StaticCString::create("___pdcdata");
|
||||
__getvar = StaticCString::create("__getvar");
|
||||
_iter_init = StaticCString::create("_iter_init");
|
||||
_iter_next = StaticCString::create("_iter_next");
|
||||
_iter_get = StaticCString::create("_iter_get");
|
||||
get_rid = StaticCString::create("get_rid");
|
||||
}
|
||||
|
||||
@ -1,46 +1,48 @@
|
||||
/**************************************************************************/
|
||||
/* core_string_names.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
/*************************************************************************/
|
||||
/* core_string_names.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 CORE_STRING_NAMES_H
|
||||
#define CORE_STRING_NAMES_H
|
||||
|
||||
#include "core/string/string_name.h"
|
||||
#include "string_db.h"
|
||||
|
||||
class CoreStringNames {
|
||||
|
||||
friend void register_core_types();
|
||||
friend void unregister_core_types();
|
||||
|
||||
static CoreStringNames *singleton;
|
||||
|
||||
static void create() { singleton = memnew(CoreStringNames); }
|
||||
static void free() {
|
||||
memdelete(singleton);
|
||||
singleton = nullptr;
|
||||
singleton = NULL;
|
||||
}
|
||||
|
||||
CoreStringNames();
|
||||
@ -48,10 +50,9 @@ class CoreStringNames {
|
||||
public:
|
||||
_FORCE_INLINE_ static CoreStringNames *get_singleton() { return singleton; }
|
||||
|
||||
static CoreStringNames *singleton;
|
||||
|
||||
StringName _free;
|
||||
StringName changed;
|
||||
StringName _meta;
|
||||
StringName _script;
|
||||
StringName script_changed;
|
||||
StringName ___pdcdata;
|
||||
@ -60,42 +61,6 @@ public:
|
||||
StringName _iter_next;
|
||||
StringName _iter_get;
|
||||
StringName get_rid;
|
||||
StringName _to_string;
|
||||
#ifdef TOOLS_ENABLED
|
||||
StringName _sections_unfolded;
|
||||
#endif
|
||||
StringName _custom_features;
|
||||
|
||||
StringName x;
|
||||
StringName y;
|
||||
StringName z;
|
||||
StringName w;
|
||||
StringName r;
|
||||
StringName g;
|
||||
StringName b;
|
||||
StringName a;
|
||||
StringName position;
|
||||
StringName size;
|
||||
StringName end;
|
||||
StringName basis;
|
||||
StringName origin;
|
||||
StringName normal;
|
||||
StringName d;
|
||||
StringName h;
|
||||
StringName s;
|
||||
StringName v;
|
||||
StringName r8;
|
||||
StringName g8;
|
||||
StringName b8;
|
||||
StringName a8;
|
||||
|
||||
StringName call;
|
||||
StringName call_deferred;
|
||||
StringName bind;
|
||||
StringName unbind;
|
||||
StringName emit;
|
||||
StringName notification;
|
||||
StringName property_list_changed;
|
||||
};
|
||||
|
||||
#endif // CORE_STRING_NAMES_H
|
||||
#endif // SCENE_STRING_NAMES_H
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env_crypto = env.Clone()
|
||||
|
||||
is_builtin = env["builtin_mbedtls"]
|
||||
has_module = env["module_mbedtls_enabled"]
|
||||
thirdparty_obj = []
|
||||
|
||||
if is_builtin or not has_module:
|
||||
# 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
|
||||
# be easily extracted.
|
||||
env_crypto.Prepend(CPPPATH=["#thirdparty/mbedtls/include"])
|
||||
|
||||
# MbedTLS core functions (for CryptoCore).
|
||||
# If the mbedtls module is compiled we don't need to add the .c files with our
|
||||
# custom config since they will be built by the module itself.
|
||||
# Only if the module is not enabled, we must compile here the required sources
|
||||
# to make a "light" build with only the necessary mbedtls files.
|
||||
if not has_module:
|
||||
env_thirdparty = env_crypto.Clone()
|
||||
env_thirdparty.disable_warnings()
|
||||
# Custom config file
|
||||
env_thirdparty.Append(
|
||||
CPPDEFINES=[("MBEDTLS_CONFIG_FILE", '\\"thirdparty/mbedtls/include/godot_core_mbedtls_config.h\\"')]
|
||||
)
|
||||
thirdparty_mbedtls_dir = "#thirdparty/mbedtls/library/"
|
||||
thirdparty_mbedtls_sources = [
|
||||
"aes.c",
|
||||
"base64.c",
|
||||
"constant_time.c",
|
||||
"ctr_drbg.c",
|
||||
"entropy.c",
|
||||
"md5.c",
|
||||
"sha1.c",
|
||||
"sha256.c",
|
||||
"godot_core_mbedtls_platform.c",
|
||||
]
|
||||
thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources]
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_mbedtls_sources)
|
||||
env.core_sources += thirdparty_obj
|
||||
|
||||
|
||||
# Godot source files
|
||||
|
||||
core_obj = []
|
||||
|
||||
env_crypto.add_source_files(core_obj, "*.cpp")
|
||||
env.core_sources += core_obj
|
||||
|
||||
# Needed to force rebuilding the core files when the thirdparty library is updated.
|
||||
env.Depends(core_obj, thirdparty_obj)
|
||||
@ -1,115 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* aes_context.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 "core/crypto/aes_context.h"
|
||||
|
||||
Error AESContext::start(Mode p_mode, PackedByteArray p_key, PackedByteArray p_iv) {
|
||||
ERR_FAIL_COND_V_MSG(mode != MODE_MAX, ERR_ALREADY_IN_USE, "AESContext already started. Call 'finish' before starting a new one.");
|
||||
ERR_FAIL_COND_V_MSG(p_mode < 0 || p_mode >= MODE_MAX, ERR_INVALID_PARAMETER, "Invalid mode requested.");
|
||||
// Key check.
|
||||
int key_bits = p_key.size() << 3;
|
||||
ERR_FAIL_COND_V_MSG(key_bits != 128 && key_bits != 256, ERR_INVALID_PARAMETER, "AES key must be either 16 or 32 bytes");
|
||||
// Initialization vector.
|
||||
if (p_mode == MODE_CBC_ENCRYPT || p_mode == MODE_CBC_DECRYPT) {
|
||||
ERR_FAIL_COND_V_MSG(p_iv.size() != 16, ERR_INVALID_PARAMETER, "The initialization vector (IV) must be exactly 16 bytes.");
|
||||
iv.resize(0);
|
||||
iv.append_array(p_iv);
|
||||
}
|
||||
// Encryption/decryption key.
|
||||
if (p_mode == MODE_CBC_ENCRYPT || p_mode == MODE_ECB_ENCRYPT) {
|
||||
ctx.set_encode_key(p_key.ptr(), key_bits);
|
||||
} else {
|
||||
ctx.set_decode_key(p_key.ptr(), key_bits);
|
||||
}
|
||||
mode = p_mode;
|
||||
return OK;
|
||||
}
|
||||
|
||||
PackedByteArray AESContext::update(PackedByteArray p_src) {
|
||||
ERR_FAIL_COND_V_MSG(mode < 0 || mode >= MODE_MAX, PackedByteArray(), "AESContext not started. Call 'start' before calling 'update'.");
|
||||
int len = p_src.size();
|
||||
ERR_FAIL_COND_V_MSG(len % 16, PackedByteArray(), "The number of bytes to be encrypted must be multiple of 16. Add padding if needed");
|
||||
PackedByteArray out;
|
||||
out.resize(len);
|
||||
const uint8_t *src_ptr = p_src.ptr();
|
||||
uint8_t *out_ptr = out.ptrw();
|
||||
switch (mode) {
|
||||
case MODE_ECB_ENCRYPT: {
|
||||
for (int i = 0; i < len; i += 16) {
|
||||
Error err = ctx.encrypt_ecb(src_ptr + i, out_ptr + i);
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
}
|
||||
} break;
|
||||
case MODE_ECB_DECRYPT: {
|
||||
for (int i = 0; i < len; i += 16) {
|
||||
Error err = ctx.decrypt_ecb(src_ptr + i, out_ptr + i);
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
}
|
||||
} break;
|
||||
case MODE_CBC_ENCRYPT: {
|
||||
Error err = ctx.encrypt_cbc(len, iv.ptrw(), p_src.ptr(), out.ptrw());
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
} break;
|
||||
case MODE_CBC_DECRYPT: {
|
||||
Error err = ctx.decrypt_cbc(len, iv.ptrw(), p_src.ptr(), out.ptrw());
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
} break;
|
||||
default:
|
||||
ERR_FAIL_V_MSG(PackedByteArray(), "Bug!");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
PackedByteArray AESContext::get_iv_state() {
|
||||
ERR_FAIL_COND_V_MSG(mode != MODE_CBC_ENCRYPT && mode != MODE_CBC_DECRYPT, PackedByteArray(), "Calling 'get_iv_state' only makes sense when the context is started in CBC mode.");
|
||||
PackedByteArray out;
|
||||
out.append_array(iv);
|
||||
return out;
|
||||
}
|
||||
|
||||
void AESContext::finish() {
|
||||
mode = MODE_MAX;
|
||||
iv.resize(0);
|
||||
}
|
||||
|
||||
void AESContext::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("start", "mode", "key", "iv"), &AESContext::start, DEFVAL(PackedByteArray()));
|
||||
ClassDB::bind_method(D_METHOD("update", "src"), &AESContext::update);
|
||||
ClassDB::bind_method(D_METHOD("get_iv_state"), &AESContext::get_iv_state);
|
||||
ClassDB::bind_method(D_METHOD("finish"), &AESContext::finish);
|
||||
BIND_ENUM_CONSTANT(MODE_ECB_ENCRYPT);
|
||||
BIND_ENUM_CONSTANT(MODE_ECB_DECRYPT);
|
||||
BIND_ENUM_CONSTANT(MODE_CBC_ENCRYPT);
|
||||
BIND_ENUM_CONSTANT(MODE_CBC_DECRYPT);
|
||||
BIND_ENUM_CONSTANT(MODE_MAX);
|
||||
}
|
||||
|
||||
AESContext::AESContext() {
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* aes_context.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef AES_CONTEXT_H
|
||||
#define AES_CONTEXT_H
|
||||
|
||||
#include "core/crypto/crypto_core.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class AESContext : public RefCounted {
|
||||
GDCLASS(AESContext, RefCounted);
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
MODE_ECB_ENCRYPT,
|
||||
MODE_ECB_DECRYPT,
|
||||
MODE_CBC_ENCRYPT,
|
||||
MODE_CBC_DECRYPT,
|
||||
MODE_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
Mode mode = MODE_MAX;
|
||||
CryptoCore::AESContext ctx;
|
||||
PackedByteArray iv;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Error start(Mode p_mode, PackedByteArray p_key, PackedByteArray p_iv = PackedByteArray());
|
||||
PackedByteArray update(PackedByteArray p_src);
|
||||
PackedByteArray get_iv_state();
|
||||
void finish();
|
||||
|
||||
AESContext();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(AESContext::Mode);
|
||||
|
||||
#endif // AES_CONTEXT_H
|
||||
@ -1,259 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* crypto.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 "crypto.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/io/certs_compressed.gen.h"
|
||||
#include "core/io/compression.h"
|
||||
|
||||
/// Resources
|
||||
|
||||
CryptoKey *(*CryptoKey::_create)() = nullptr;
|
||||
CryptoKey *CryptoKey::create() {
|
||||
if (_create) {
|
||||
return _create();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CryptoKey::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("save", "path", "public_only"), &CryptoKey::save, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("load", "path", "public_only"), &CryptoKey::load, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("is_public_only"), &CryptoKey::is_public_only);
|
||||
ClassDB::bind_method(D_METHOD("save_to_string", "public_only"), &CryptoKey::save_to_string, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("load_from_string", "string_key", "public_only"), &CryptoKey::load_from_string, DEFVAL(false));
|
||||
}
|
||||
|
||||
X509Certificate *(*X509Certificate::_create)() = nullptr;
|
||||
X509Certificate *X509Certificate::create() {
|
||||
if (_create) {
|
||||
return _create();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void X509Certificate::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("save", "path"), &X509Certificate::save);
|
||||
ClassDB::bind_method(D_METHOD("load", "path"), &X509Certificate::load);
|
||||
}
|
||||
|
||||
/// TLSOptions
|
||||
|
||||
Ref<TLSOptions> TLSOptions::client(Ref<X509Certificate> p_trusted_chain, const String &p_common_name_override) {
|
||||
Ref<TLSOptions> opts;
|
||||
opts.instantiate();
|
||||
opts->trusted_ca_chain = p_trusted_chain;
|
||||
opts->common_name = p_common_name_override;
|
||||
opts->verify_mode = TLS_VERIFY_FULL;
|
||||
return opts;
|
||||
}
|
||||
|
||||
Ref<TLSOptions> TLSOptions::client_unsafe(Ref<X509Certificate> p_trusted_chain) {
|
||||
Ref<TLSOptions> opts;
|
||||
opts.instantiate();
|
||||
opts->trusted_ca_chain = p_trusted_chain;
|
||||
if (p_trusted_chain.is_null()) {
|
||||
opts->verify_mode = TLS_VERIFY_NONE;
|
||||
} else {
|
||||
opts->verify_mode = TLS_VERIFY_CERT;
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
Ref<TLSOptions> TLSOptions::server(Ref<CryptoKey> p_own_key, Ref<X509Certificate> p_own_certificate) {
|
||||
Ref<TLSOptions> opts;
|
||||
opts.instantiate();
|
||||
opts->server_mode = true;
|
||||
opts->own_certificate = p_own_certificate;
|
||||
opts->private_key = p_own_key;
|
||||
opts->verify_mode = TLS_VERIFY_NONE;
|
||||
return opts;
|
||||
}
|
||||
|
||||
void TLSOptions::_bind_methods() {
|
||||
ClassDB::bind_static_method("TLSOptions", D_METHOD("client", "trusted_chain", "common_name_override"), &TLSOptions::client, DEFVAL(Ref<X509Certificate>()), DEFVAL(String()));
|
||||
ClassDB::bind_static_method("TLSOptions", D_METHOD("client_unsafe", "trusted_chain"), &TLSOptions::client_unsafe, DEFVAL(Ref<X509Certificate>()));
|
||||
ClassDB::bind_static_method("TLSOptions", D_METHOD("server", "key", "certificate"), &TLSOptions::server);
|
||||
}
|
||||
|
||||
/// HMACContext
|
||||
|
||||
void HMACContext::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("start", "hash_type", "key"), &HMACContext::start);
|
||||
ClassDB::bind_method(D_METHOD("update", "data"), &HMACContext::update);
|
||||
ClassDB::bind_method(D_METHOD("finish"), &HMACContext::finish);
|
||||
}
|
||||
|
||||
HMACContext *(*HMACContext::_create)() = nullptr;
|
||||
HMACContext *HMACContext::create() {
|
||||
if (_create) {
|
||||
return _create();
|
||||
}
|
||||
ERR_FAIL_V_MSG(nullptr, "HMACContext is not available when the mbedtls module is disabled.");
|
||||
}
|
||||
|
||||
/// Crypto
|
||||
|
||||
void (*Crypto::_load_default_certificates)(String p_path) = nullptr;
|
||||
Crypto *(*Crypto::_create)() = nullptr;
|
||||
Crypto *Crypto::create() {
|
||||
if (_create) {
|
||||
return _create();
|
||||
}
|
||||
ERR_FAIL_V_MSG(nullptr, "Crypto is not available when the mbedtls module is disabled.");
|
||||
}
|
||||
|
||||
void Crypto::load_default_certificates(String p_path) {
|
||||
if (_load_default_certificates) {
|
||||
_load_default_certificates(p_path);
|
||||
}
|
||||
}
|
||||
|
||||
PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, PackedByteArray p_key, PackedByteArray p_msg) {
|
||||
Ref<HMACContext> ctx = Ref<HMACContext>(HMACContext::create());
|
||||
ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available without mbedtls module.");
|
||||
Error err = ctx->start(p_hash_type, p_key);
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
err = ctx->update(p_msg);
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
return ctx->finish();
|
||||
}
|
||||
|
||||
// Compares two HMACS for equality without leaking timing information in order to prevent timing attacks.
|
||||
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
|
||||
bool Crypto::constant_time_compare(PackedByteArray p_trusted, PackedByteArray p_received) {
|
||||
const uint8_t *t = p_trusted.ptr();
|
||||
const uint8_t *r = p_received.ptr();
|
||||
int tlen = p_trusted.size();
|
||||
int rlen = p_received.size();
|
||||
// If the lengths are different then nothing else matters.
|
||||
if (tlen != rlen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t v = 0;
|
||||
for (int i = 0; i < tlen; i++) {
|
||||
v |= t[i] ^ r[i];
|
||||
}
|
||||
return v == 0;
|
||||
}
|
||||
|
||||
void Crypto::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes);
|
||||
ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa);
|
||||
ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000"));
|
||||
ClassDB::bind_method(D_METHOD("sign", "hash_type", "hash", "key"), &Crypto::sign);
|
||||
ClassDB::bind_method(D_METHOD("verify", "hash_type", "hash", "signature", "key"), &Crypto::verify);
|
||||
ClassDB::bind_method(D_METHOD("encrypt", "key", "plaintext"), &Crypto::encrypt);
|
||||
ClassDB::bind_method(D_METHOD("decrypt", "key", "ciphertext"), &Crypto::decrypt);
|
||||
ClassDB::bind_method(D_METHOD("hmac_digest", "hash_type", "key", "msg"), &Crypto::hmac_digest);
|
||||
ClassDB::bind_method(D_METHOD("constant_time_compare", "trusted", "received"), &Crypto::constant_time_compare);
|
||||
}
|
||||
|
||||
/// Resource loader/saver
|
||||
|
||||
Ref<Resource> ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
|
||||
String el = p_path.get_extension().to_lower();
|
||||
if (el == "crt") {
|
||||
X509Certificate *cert = X509Certificate::create();
|
||||
if (cert) {
|
||||
cert->load(p_path);
|
||||
}
|
||||
return cert;
|
||||
} else if (el == "key") {
|
||||
CryptoKey *key = CryptoKey::create();
|
||||
if (key) {
|
||||
key->load(p_path, false);
|
||||
}
|
||||
return key;
|
||||
} else if (el == "pub") {
|
||||
CryptoKey *key = CryptoKey::create();
|
||||
if (key) {
|
||||
key->load(p_path, true);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
p_extensions->push_back("crt");
|
||||
p_extensions->push_back("key");
|
||||
p_extensions->push_back("pub");
|
||||
}
|
||||
|
||||
bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const {
|
||||
return p_type == "X509Certificate" || p_type == "CryptoKey";
|
||||
}
|
||||
|
||||
String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const {
|
||||
String el = p_path.get_extension().to_lower();
|
||||
if (el == "crt") {
|
||||
return "X509Certificate";
|
||||
} else if (el == "key" || el == "pub") {
|
||||
return "CryptoKey";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
|
||||
Error err;
|
||||
Ref<X509Certificate> cert = p_resource;
|
||||
Ref<CryptoKey> key = p_resource;
|
||||
if (cert.is_valid()) {
|
||||
err = cert->save(p_path);
|
||||
} else if (key.is_valid()) {
|
||||
String el = p_path.get_extension().to_lower();
|
||||
err = key->save(p_path, el == "pub");
|
||||
} else {
|
||||
ERR_FAIL_V(ERR_INVALID_PARAMETER);
|
||||
}
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save Crypto resource to file '" + p_path + "'.");
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ResourceFormatSaverCrypto::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
|
||||
const X509Certificate *cert = Object::cast_to<X509Certificate>(*p_resource);
|
||||
const CryptoKey *key = Object::cast_to<CryptoKey>(*p_resource);
|
||||
if (cert) {
|
||||
p_extensions->push_back("crt");
|
||||
}
|
||||
if (key) {
|
||||
if (!key->is_public_only()) {
|
||||
p_extensions->push_back("key");
|
||||
}
|
||||
p_extensions->push_back("pub");
|
||||
}
|
||||
}
|
||||
|
||||
bool ResourceFormatSaverCrypto::recognize(const Ref<Resource> &p_resource) const {
|
||||
return Object::cast_to<X509Certificate>(*p_resource) || Object::cast_to<CryptoKey>(*p_resource);
|
||||
}
|
||||
@ -1,167 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* crypto.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CRYPTO_H
|
||||
#define CRYPTO_H
|
||||
|
||||
#include "core/crypto/hashing_context.h"
|
||||
#include "core/io/resource.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class CryptoKey : public Resource {
|
||||
GDCLASS(CryptoKey, Resource);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static CryptoKey *(*_create)();
|
||||
|
||||
public:
|
||||
static CryptoKey *create();
|
||||
virtual Error load(String p_path, bool p_public_only = false) = 0;
|
||||
virtual Error save(String p_path, bool p_public_only = false) = 0;
|
||||
virtual String save_to_string(bool p_public_only = false) = 0;
|
||||
virtual Error load_from_string(String p_string_key, bool p_public_only = false) = 0;
|
||||
virtual bool is_public_only() const = 0;
|
||||
};
|
||||
|
||||
class X509Certificate : public Resource {
|
||||
GDCLASS(X509Certificate, Resource);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static X509Certificate *(*_create)();
|
||||
|
||||
public:
|
||||
static X509Certificate *create();
|
||||
virtual Error load(String p_path) = 0;
|
||||
virtual Error load_from_memory(const uint8_t *p_buffer, int p_len) = 0;
|
||||
virtual Error save(String p_path) = 0;
|
||||
};
|
||||
|
||||
class TLSOptions : public RefCounted {
|
||||
GDCLASS(TLSOptions, RefCounted);
|
||||
|
||||
public:
|
||||
enum TLSVerifyMode {
|
||||
TLS_VERIFY_NONE = 0,
|
||||
TLS_VERIFY_CERT = 1,
|
||||
TLS_VERIFY_FULL = 2,
|
||||
};
|
||||
|
||||
private:
|
||||
bool server_mode = false;
|
||||
String common_name;
|
||||
TLSVerifyMode verify_mode = TLS_VERIFY_FULL;
|
||||
Ref<X509Certificate> trusted_ca_chain;
|
||||
Ref<X509Certificate> own_certificate;
|
||||
Ref<CryptoKey> private_key;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static Ref<TLSOptions> client(Ref<X509Certificate> p_trusted_chain = Ref<X509Certificate>(), const String &p_common_name_override = String());
|
||||
static Ref<TLSOptions> client_unsafe(Ref<X509Certificate> p_trusted_chain);
|
||||
static Ref<TLSOptions> server(Ref<CryptoKey> p_own_key, Ref<X509Certificate> p_own_certificate);
|
||||
|
||||
TLSVerifyMode get_verify_mode() const { return verify_mode; }
|
||||
String get_common_name() const { return common_name; }
|
||||
Ref<X509Certificate> get_trusted_ca_chain() const { return trusted_ca_chain; }
|
||||
Ref<X509Certificate> get_own_certificate() const { return own_certificate; }
|
||||
Ref<CryptoKey> get_private_key() const { return private_key; }
|
||||
bool is_server() const { return server_mode; }
|
||||
};
|
||||
|
||||
class HMACContext : public RefCounted {
|
||||
GDCLASS(HMACContext, RefCounted);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static HMACContext *(*_create)();
|
||||
|
||||
public:
|
||||
static HMACContext *create();
|
||||
|
||||
virtual Error start(HashingContext::HashType p_hash_type, PackedByteArray p_key) = 0;
|
||||
virtual Error update(PackedByteArray p_data) = 0;
|
||||
virtual PackedByteArray finish() = 0;
|
||||
|
||||
HMACContext() {}
|
||||
virtual ~HMACContext() {}
|
||||
};
|
||||
|
||||
class Crypto : public RefCounted {
|
||||
GDCLASS(Crypto, RefCounted);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static Crypto *(*_create)();
|
||||
static void (*_load_default_certificates)(String p_path);
|
||||
|
||||
public:
|
||||
static Crypto *create();
|
||||
static void load_default_certificates(String p_path);
|
||||
|
||||
virtual PackedByteArray generate_random_bytes(int p_bytes) = 0;
|
||||
virtual Ref<CryptoKey> generate_rsa(int p_bytes) = 0;
|
||||
virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) = 0;
|
||||
|
||||
virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key) = 0;
|
||||
virtual bool verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key) = 0;
|
||||
virtual Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_plaintext) = 0;
|
||||
virtual Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_ciphertext) = 0;
|
||||
|
||||
PackedByteArray hmac_digest(HashingContext::HashType p_hash_type, PackedByteArray p_key, PackedByteArray p_msg);
|
||||
|
||||
// Compares two PackedByteArrays for equality without leaking timing information in order to prevent timing attacks.
|
||||
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
|
||||
bool constant_time_compare(PackedByteArray p_trusted, PackedByteArray p_received);
|
||||
|
||||
Crypto() {}
|
||||
};
|
||||
|
||||
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
|
||||
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 void get_recognized_extensions(List<String> *p_extensions) const;
|
||||
virtual bool handles_type(const String &p_type) const;
|
||||
virtual String get_resource_type(const String &p_path) const;
|
||||
};
|
||||
|
||||
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
|
||||
public:
|
||||
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
|
||||
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
|
||||
virtual bool recognize(const Ref<Resource> &p_resource) const;
|
||||
};
|
||||
|
||||
#endif // CRYPTO_H
|
||||
@ -1,248 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* crypto_core.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 "crypto_core.h"
|
||||
|
||||
#include "core/os/os.h"
|
||||
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/base64.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/md5.h>
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
|
||||
// RandomGenerator
|
||||
CryptoCore::RandomGenerator::RandomGenerator() {
|
||||
entropy = memalloc(sizeof(mbedtls_entropy_context));
|
||||
mbedtls_entropy_init((mbedtls_entropy_context *)entropy);
|
||||
mbedtls_entropy_add_source((mbedtls_entropy_context *)entropy, &CryptoCore::RandomGenerator::_entropy_poll, nullptr, 256, MBEDTLS_ENTROPY_SOURCE_STRONG);
|
||||
ctx = memalloc(sizeof(mbedtls_ctr_drbg_context));
|
||||
mbedtls_ctr_drbg_init((mbedtls_ctr_drbg_context *)ctx);
|
||||
}
|
||||
|
||||
CryptoCore::RandomGenerator::~RandomGenerator() {
|
||||
mbedtls_ctr_drbg_free((mbedtls_ctr_drbg_context *)ctx);
|
||||
memfree(ctx);
|
||||
mbedtls_entropy_free((mbedtls_entropy_context *)entropy);
|
||||
memfree(entropy);
|
||||
}
|
||||
|
||||
int CryptoCore::RandomGenerator::_entropy_poll(void *p_data, unsigned char *r_buffer, size_t p_len, size_t *r_len) {
|
||||
*r_len = 0;
|
||||
Error err = OS::get_singleton()->get_entropy(r_buffer, p_len);
|
||||
ERR_FAIL_COND_V(err, MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
|
||||
*r_len = p_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error CryptoCore::RandomGenerator::init() {
|
||||
int ret = mbedtls_ctr_drbg_seed((mbedtls_ctr_drbg_context *)ctx, mbedtls_entropy_func, (mbedtls_entropy_context *)entropy, nullptr, 0);
|
||||
if (ret) {
|
||||
ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n ! mbedtls_ctr_drbg_seed returned an error" + itos(ret));
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::RandomGenerator::get_random_bytes(uint8_t *r_buffer, size_t p_bytes) {
|
||||
ERR_FAIL_COND_V(!ctx, ERR_UNCONFIGURED);
|
||||
int ret = mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *)ctx, r_buffer, p_bytes);
|
||||
ERR_FAIL_COND_V_MSG(ret, FAILED, " failed\n ! mbedtls_ctr_drbg_seed returned an error" + itos(ret));
|
||||
return OK;
|
||||
}
|
||||
|
||||
// MD5
|
||||
CryptoCore::MD5Context::MD5Context() {
|
||||
ctx = memalloc(sizeof(mbedtls_md5_context));
|
||||
mbedtls_md5_init((mbedtls_md5_context *)ctx);
|
||||
}
|
||||
|
||||
CryptoCore::MD5Context::~MD5Context() {
|
||||
mbedtls_md5_free((mbedtls_md5_context *)ctx);
|
||||
memfree((mbedtls_md5_context *)ctx);
|
||||
}
|
||||
|
||||
Error CryptoCore::MD5Context::start() {
|
||||
int ret = mbedtls_md5_starts_ret((mbedtls_md5_context *)ctx);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::MD5Context::update(const uint8_t *p_src, size_t p_len) {
|
||||
int ret = mbedtls_md5_update_ret((mbedtls_md5_context *)ctx, p_src, p_len);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::MD5Context::finish(unsigned char r_hash[16]) {
|
||||
int ret = mbedtls_md5_finish_ret((mbedtls_md5_context *)ctx, r_hash);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
// SHA1
|
||||
CryptoCore::SHA1Context::SHA1Context() {
|
||||
ctx = memalloc(sizeof(mbedtls_sha1_context));
|
||||
mbedtls_sha1_init((mbedtls_sha1_context *)ctx);
|
||||
}
|
||||
|
||||
CryptoCore::SHA1Context::~SHA1Context() {
|
||||
mbedtls_sha1_free((mbedtls_sha1_context *)ctx);
|
||||
memfree((mbedtls_sha1_context *)ctx);
|
||||
}
|
||||
|
||||
Error CryptoCore::SHA1Context::start() {
|
||||
int ret = mbedtls_sha1_starts_ret((mbedtls_sha1_context *)ctx);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::SHA1Context::update(const uint8_t *p_src, size_t p_len) {
|
||||
int ret = mbedtls_sha1_update_ret((mbedtls_sha1_context *)ctx, p_src, p_len);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::SHA1Context::finish(unsigned char r_hash[20]) {
|
||||
int ret = mbedtls_sha1_finish_ret((mbedtls_sha1_context *)ctx, r_hash);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
// SHA256
|
||||
CryptoCore::SHA256Context::SHA256Context() {
|
||||
ctx = memalloc(sizeof(mbedtls_sha256_context));
|
||||
mbedtls_sha256_init((mbedtls_sha256_context *)ctx);
|
||||
}
|
||||
|
||||
CryptoCore::SHA256Context::~SHA256Context() {
|
||||
mbedtls_sha256_free((mbedtls_sha256_context *)ctx);
|
||||
memfree((mbedtls_sha256_context *)ctx);
|
||||
}
|
||||
|
||||
Error CryptoCore::SHA256Context::start() {
|
||||
int ret = mbedtls_sha256_starts_ret((mbedtls_sha256_context *)ctx, 0);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::SHA256Context::update(const uint8_t *p_src, size_t p_len) {
|
||||
int ret = mbedtls_sha256_update_ret((mbedtls_sha256_context *)ctx, p_src, p_len);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::SHA256Context::finish(unsigned char r_hash[32]) {
|
||||
int ret = mbedtls_sha256_finish_ret((mbedtls_sha256_context *)ctx, r_hash);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
// AES256
|
||||
CryptoCore::AESContext::AESContext() {
|
||||
ctx = memalloc(sizeof(mbedtls_aes_context));
|
||||
mbedtls_aes_init((mbedtls_aes_context *)ctx);
|
||||
}
|
||||
|
||||
CryptoCore::AESContext::~AESContext() {
|
||||
mbedtls_aes_free((mbedtls_aes_context *)ctx);
|
||||
memfree((mbedtls_aes_context *)ctx);
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::set_encode_key(const uint8_t *p_key, size_t p_bits) {
|
||||
int ret = mbedtls_aes_setkey_enc((mbedtls_aes_context *)ctx, p_key, p_bits);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::set_decode_key(const uint8_t *p_key, size_t p_bits) {
|
||||
int ret = mbedtls_aes_setkey_dec((mbedtls_aes_context *)ctx, p_key, p_bits);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) {
|
||||
int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_src, r_dst);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::encrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst) {
|
||||
int ret = mbedtls_aes_crypt_cbc((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_length, r_iv, p_src, r_dst);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::encrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst) {
|
||||
size_t iv_off = 0; // Ignore and assume 16-byte alignment.
|
||||
int ret = mbedtls_aes_crypt_cfb128((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_length, &iv_off, p_iv, p_src, r_dst);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) {
|
||||
int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_src, r_dst);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::decrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst) {
|
||||
int ret = mbedtls_aes_crypt_cbc((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_length, r_iv, p_src, r_dst);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::AESContext::decrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst) {
|
||||
size_t iv_off = 0; // Ignore and assume 16-byte alignment.
|
||||
int ret = mbedtls_aes_crypt_cfb128((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_length, &iv_off, p_iv, p_src, r_dst);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
// CryptoCore
|
||||
String CryptoCore::b64_encode_str(const uint8_t *p_src, int p_src_len) {
|
||||
int b64len = p_src_len / 3 * 4 + 4 + 1;
|
||||
Vector<uint8_t> b64buff;
|
||||
b64buff.resize(b64len);
|
||||
uint8_t *w64 = b64buff.ptrw();
|
||||
size_t strlen = 0;
|
||||
int ret = b64_encode(&w64[0], b64len, &strlen, p_src, p_src_len);
|
||||
w64[strlen] = 0;
|
||||
return ret ? String() : (const char *)&w64[0];
|
||||
}
|
||||
|
||||
Error CryptoCore::b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) {
|
||||
int ret = mbedtls_base64_encode(r_dst, p_dst_len, r_len, p_src, p_src_len);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) {
|
||||
int ret = mbedtls_base64_decode(r_dst, p_dst_len, r_len, p_src, p_src_len);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]) {
|
||||
int ret = mbedtls_md5_ret(p_src, p_src_len, r_hash);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]) {
|
||||
int ret = mbedtls_sha1_ret(p_src, p_src_len, r_hash);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
|
||||
Error CryptoCore::sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]) {
|
||||
int ret = mbedtls_sha256_ret(p_src, p_src_len, r_hash, 0);
|
||||
return ret ? FAILED : OK;
|
||||
}
|
||||
@ -1,119 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* crypto_core.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef CRYPTO_CORE_H
|
||||
#define CRYPTO_CORE_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class CryptoCore {
|
||||
public:
|
||||
class RandomGenerator {
|
||||
private:
|
||||
void *entropy = nullptr;
|
||||
void *ctx = nullptr;
|
||||
|
||||
static int _entropy_poll(void *p_data, unsigned char *r_buffer, size_t p_len, size_t *r_len);
|
||||
|
||||
public:
|
||||
RandomGenerator();
|
||||
~RandomGenerator();
|
||||
|
||||
Error init();
|
||||
Error get_random_bytes(uint8_t *r_buffer, size_t p_bytes);
|
||||
};
|
||||
|
||||
class MD5Context {
|
||||
private:
|
||||
void *ctx = nullptr;
|
||||
|
||||
public:
|
||||
MD5Context();
|
||||
~MD5Context();
|
||||
|
||||
Error start();
|
||||
Error update(const uint8_t *p_src, size_t p_len);
|
||||
Error finish(unsigned char r_hash[16]);
|
||||
};
|
||||
|
||||
class SHA1Context {
|
||||
private:
|
||||
void *ctx = nullptr;
|
||||
|
||||
public:
|
||||
SHA1Context();
|
||||
~SHA1Context();
|
||||
|
||||
Error start();
|
||||
Error update(const uint8_t *p_src, size_t p_len);
|
||||
Error finish(unsigned char r_hash[20]);
|
||||
};
|
||||
|
||||
class SHA256Context {
|
||||
private:
|
||||
void *ctx = nullptr;
|
||||
|
||||
public:
|
||||
SHA256Context();
|
||||
~SHA256Context();
|
||||
|
||||
Error start();
|
||||
Error update(const uint8_t *p_src, size_t p_len);
|
||||
Error finish(unsigned char r_hash[32]);
|
||||
};
|
||||
|
||||
class AESContext {
|
||||
private:
|
||||
void *ctx = nullptr;
|
||||
|
||||
public:
|
||||
AESContext();
|
||||
~AESContext();
|
||||
|
||||
Error set_encode_key(const uint8_t *p_key, size_t p_bits);
|
||||
Error set_decode_key(const uint8_t *p_key, size_t p_bits);
|
||||
Error encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]);
|
||||
Error decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]);
|
||||
Error encrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst);
|
||||
Error decrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst);
|
||||
Error encrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst);
|
||||
Error decrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst);
|
||||
};
|
||||
|
||||
static String b64_encode_str(const uint8_t *p_src, int p_src_len);
|
||||
static Error b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
|
||||
static Error b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
|
||||
|
||||
static Error md5(const uint8_t *p_src, int p_src_len, unsigned char r_hash[16]);
|
||||
static Error sha1(const uint8_t *p_src, int p_src_len, unsigned char r_hash[20]);
|
||||
static Error sha256(const uint8_t *p_src, int p_src_len, unsigned char r_hash[32]);
|
||||
};
|
||||
|
||||
#endif // CRYPTO_CORE_H
|
||||
@ -1,134 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* hashing_context.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 "hashing_context.h"
|
||||
|
||||
#include "core/crypto/crypto_core.h"
|
||||
|
||||
Error HashingContext::start(HashType p_type) {
|
||||
ERR_FAIL_COND_V(ctx != nullptr, ERR_ALREADY_IN_USE);
|
||||
_create_ctx(p_type);
|
||||
ERR_FAIL_COND_V(ctx == nullptr, ERR_UNAVAILABLE);
|
||||
switch (type) {
|
||||
case HASH_MD5:
|
||||
return ((CryptoCore::MD5Context *)ctx)->start();
|
||||
case HASH_SHA1:
|
||||
return ((CryptoCore::SHA1Context *)ctx)->start();
|
||||
case HASH_SHA256:
|
||||
return ((CryptoCore::SHA256Context *)ctx)->start();
|
||||
}
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
Error HashingContext::update(PackedByteArray p_chunk) {
|
||||
ERR_FAIL_COND_V(ctx == nullptr, ERR_UNCONFIGURED);
|
||||
size_t len = p_chunk.size();
|
||||
ERR_FAIL_COND_V(len == 0, FAILED);
|
||||
const uint8_t *r = p_chunk.ptr();
|
||||
switch (type) {
|
||||
case HASH_MD5:
|
||||
return ((CryptoCore::MD5Context *)ctx)->update(&r[0], len);
|
||||
case HASH_SHA1:
|
||||
return ((CryptoCore::SHA1Context *)ctx)->update(&r[0], len);
|
||||
case HASH_SHA256:
|
||||
return ((CryptoCore::SHA256Context *)ctx)->update(&r[0], len);
|
||||
}
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
PackedByteArray HashingContext::finish() {
|
||||
ERR_FAIL_COND_V(ctx == nullptr, PackedByteArray());
|
||||
PackedByteArray out;
|
||||
Error err = FAILED;
|
||||
switch (type) {
|
||||
case HASH_MD5:
|
||||
out.resize(16);
|
||||
err = ((CryptoCore::MD5Context *)ctx)->finish(out.ptrw());
|
||||
break;
|
||||
case HASH_SHA1:
|
||||
out.resize(20);
|
||||
err = ((CryptoCore::SHA1Context *)ctx)->finish(out.ptrw());
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
out.resize(32);
|
||||
err = ((CryptoCore::SHA256Context *)ctx)->finish(out.ptrw());
|
||||
break;
|
||||
}
|
||||
_delete_ctx();
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
return out;
|
||||
}
|
||||
|
||||
void HashingContext::_create_ctx(HashType p_type) {
|
||||
type = p_type;
|
||||
switch (type) {
|
||||
case HASH_MD5:
|
||||
ctx = memnew(CryptoCore::MD5Context);
|
||||
break;
|
||||
case HASH_SHA1:
|
||||
ctx = memnew(CryptoCore::SHA1Context);
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
ctx = memnew(CryptoCore::SHA256Context);
|
||||
break;
|
||||
default:
|
||||
ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void HashingContext::_delete_ctx() {
|
||||
switch (type) {
|
||||
case HASH_MD5:
|
||||
memdelete((CryptoCore::MD5Context *)ctx);
|
||||
break;
|
||||
case HASH_SHA1:
|
||||
memdelete((CryptoCore::SHA1Context *)ctx);
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
memdelete((CryptoCore::SHA256Context *)ctx);
|
||||
break;
|
||||
}
|
||||
ctx = nullptr;
|
||||
}
|
||||
|
||||
void HashingContext::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("start", "type"), &HashingContext::start);
|
||||
ClassDB::bind_method(D_METHOD("update", "chunk"), &HashingContext::update);
|
||||
ClassDB::bind_method(D_METHOD("finish"), &HashingContext::finish);
|
||||
BIND_ENUM_CONSTANT(HASH_MD5);
|
||||
BIND_ENUM_CONSTANT(HASH_SHA1);
|
||||
BIND_ENUM_CONSTANT(HASH_SHA256);
|
||||
}
|
||||
|
||||
HashingContext::~HashingContext() {
|
||||
if (ctx != nullptr) {
|
||||
_delete_ctx();
|
||||
}
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* hashing_context.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef HASHING_CONTEXT_H
|
||||
#define HASHING_CONTEXT_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class HashingContext : public RefCounted {
|
||||
GDCLASS(HashingContext, RefCounted);
|
||||
|
||||
public:
|
||||
enum HashType {
|
||||
HASH_MD5,
|
||||
HASH_SHA1,
|
||||
HASH_SHA256
|
||||
};
|
||||
|
||||
private:
|
||||
void *ctx = nullptr;
|
||||
HashType type = HASH_MD5;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _create_ctx(HashType p_type);
|
||||
void _delete_ctx();
|
||||
|
||||
public:
|
||||
Error start(HashType p_type);
|
||||
Error update(PackedByteArray p_chunk);
|
||||
PackedByteArray finish();
|
||||
|
||||
HashingContext() {}
|
||||
~HashingContext();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(HashingContext::HashType);
|
||||
|
||||
#endif // HASHING_CONTEXT_H
|
||||
@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env.add_source_files(env.core_sources, "*.cpp")
|
||||
@ -1,147 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* debugger_marshalls.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 "debugger_marshalls.h"
|
||||
|
||||
#include "core/io/marshalls.h"
|
||||
|
||||
#define CHECK_SIZE(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() < (uint32_t)(expected), false, String("Malformed ") + what + " message from script debugger, message too short. Expected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
|
||||
#define CHECK_END(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() > (uint32_t)expected, false, String("Malformed ") + what + " message from script debugger, message too long. Expected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
|
||||
|
||||
Array DebuggerMarshalls::ScriptStackDump::serialize() {
|
||||
Array arr;
|
||||
arr.push_back(frames.size() * 3);
|
||||
for (int i = 0; i < frames.size(); i++) {
|
||||
arr.push_back(frames[i].file);
|
||||
arr.push_back(frames[i].line);
|
||||
arr.push_back(frames[i].func);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
bool DebuggerMarshalls::ScriptStackDump::deserialize(const Array &p_arr) {
|
||||
CHECK_SIZE(p_arr, 1, "ScriptStackDump");
|
||||
uint32_t size = p_arr[0];
|
||||
CHECK_SIZE(p_arr, size, "ScriptStackDump");
|
||||
int idx = 1;
|
||||
for (uint32_t i = 0; i < size / 3; i++) {
|
||||
ScriptLanguage::StackInfo sf;
|
||||
sf.file = p_arr[idx];
|
||||
sf.line = p_arr[idx + 1];
|
||||
sf.func = p_arr[idx + 2];
|
||||
frames.push_back(sf);
|
||||
idx += 3;
|
||||
}
|
||||
CHECK_END(p_arr, idx, "ScriptStackDump");
|
||||
return true;
|
||||
}
|
||||
|
||||
Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) {
|
||||
Array arr;
|
||||
arr.push_back(name);
|
||||
arr.push_back(type);
|
||||
|
||||
Variant var = value;
|
||||
if (value.get_type() == Variant::OBJECT && value.get_validated_object() == nullptr) {
|
||||
var = Variant();
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
Error err = encode_variant(var, nullptr, len, true);
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Failed to encode variant.");
|
||||
}
|
||||
|
||||
if (len > max_size) {
|
||||
arr.push_back(Variant());
|
||||
} else {
|
||||
arr.push_back(var);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
bool DebuggerMarshalls::ScriptStackVariable::deserialize(const Array &p_arr) {
|
||||
CHECK_SIZE(p_arr, 3, "ScriptStackVariable");
|
||||
name = p_arr[0];
|
||||
type = p_arr[1];
|
||||
value = p_arr[2];
|
||||
CHECK_END(p_arr, 3, "ScriptStackVariable");
|
||||
return true;
|
||||
}
|
||||
|
||||
Array DebuggerMarshalls::OutputError::serialize() {
|
||||
Array arr;
|
||||
arr.push_back(hr);
|
||||
arr.push_back(min);
|
||||
arr.push_back(sec);
|
||||
arr.push_back(msec);
|
||||
arr.push_back(source_file);
|
||||
arr.push_back(source_func);
|
||||
arr.push_back(source_line);
|
||||
arr.push_back(error);
|
||||
arr.push_back(error_descr);
|
||||
arr.push_back(warning);
|
||||
unsigned int size = callstack.size();
|
||||
const ScriptLanguage::StackInfo *r = callstack.ptr();
|
||||
arr.push_back(size * 3);
|
||||
for (int i = 0; i < callstack.size(); i++) {
|
||||
arr.push_back(r[i].file);
|
||||
arr.push_back(r[i].func);
|
||||
arr.push_back(r[i].line);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
bool DebuggerMarshalls::OutputError::deserialize(const Array &p_arr) {
|
||||
CHECK_SIZE(p_arr, 11, "OutputError");
|
||||
hr = p_arr[0];
|
||||
min = p_arr[1];
|
||||
sec = p_arr[2];
|
||||
msec = p_arr[3];
|
||||
source_file = p_arr[4];
|
||||
source_func = p_arr[5];
|
||||
source_line = p_arr[6];
|
||||
error = p_arr[7];
|
||||
error_descr = p_arr[8];
|
||||
warning = p_arr[9];
|
||||
unsigned int stack_size = p_arr[10];
|
||||
CHECK_SIZE(p_arr, stack_size, "OutputError");
|
||||
int idx = 11;
|
||||
callstack.resize(stack_size / 3);
|
||||
ScriptLanguage::StackInfo *w = callstack.ptrw();
|
||||
for (unsigned int i = 0; i < stack_size / 3; i++) {
|
||||
w[i].file = p_arr[idx];
|
||||
w[i].func = p_arr[idx + 1];
|
||||
w[i].line = p_arr[idx + 2];
|
||||
idx += 3;
|
||||
}
|
||||
CHECK_END(p_arr, idx, "OutputError");
|
||||
return true;
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* debugger_marshalls.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef DEBUGGER_MARSHALLS_H
|
||||
#define DEBUGGER_MARSHALLS_H
|
||||
|
||||
#include "core/object/script_language.h"
|
||||
|
||||
struct DebuggerMarshalls {
|
||||
struct ScriptStackVariable {
|
||||
String name;
|
||||
Variant value;
|
||||
int type = -1;
|
||||
|
||||
Array serialize(int max_size = 1 << 20); // 1 MiB default.
|
||||
bool deserialize(const Array &p_arr);
|
||||
};
|
||||
|
||||
struct ScriptStackDump {
|
||||
List<ScriptLanguage::StackInfo> frames;
|
||||
ScriptStackDump() {}
|
||||
|
||||
Array serialize();
|
||||
bool deserialize(const Array &p_arr);
|
||||
};
|
||||
|
||||
struct OutputError {
|
||||
int hr = -1;
|
||||
int min = -1;
|
||||
int sec = -1;
|
||||
int msec = -1;
|
||||
String source_file;
|
||||
String source_func;
|
||||
int source_line = -1;
|
||||
String error;
|
||||
String error_descr;
|
||||
bool warning = false;
|
||||
Vector<ScriptLanguage::StackInfo> callstack;
|
||||
|
||||
Array serialize();
|
||||
bool deserialize(const Array &p_arr);
|
||||
};
|
||||
};
|
||||
|
||||
#endif // DEBUGGER_MARSHALLS_H
|
||||
@ -1,211 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* engine_debugger.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 "engine_debugger.h"
|
||||
|
||||
#include "core/debugger/local_debugger.h"
|
||||
#include "core/debugger/remote_debugger.h"
|
||||
#include "core/debugger/remote_debugger_peer.h"
|
||||
#include "core/debugger/script_debugger.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
EngineDebugger *EngineDebugger::singleton = nullptr;
|
||||
ScriptDebugger *EngineDebugger::script_debugger = nullptr;
|
||||
|
||||
HashMap<StringName, EngineDebugger::Profiler> EngineDebugger::profilers;
|
||||
HashMap<StringName, EngineDebugger::Capture> EngineDebugger::captures;
|
||||
HashMap<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols;
|
||||
|
||||
void (*EngineDebugger::allow_focus_steal_fn)();
|
||||
|
||||
void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) {
|
||||
ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name);
|
||||
profilers.insert(p_name, p_func);
|
||||
}
|
||||
|
||||
void EngineDebugger::unregister_profiler(const StringName &p_name) {
|
||||
ERR_FAIL_COND_MSG(!profilers.has(p_name), "Profiler not registered: " + p_name);
|
||||
Profiler &p = profilers[p_name];
|
||||
if (p.active && p.toggle) {
|
||||
p.toggle(p.data, false, Array());
|
||||
p.active = false;
|
||||
}
|
||||
profilers.erase(p_name);
|
||||
}
|
||||
|
||||
void EngineDebugger::register_message_capture(const StringName &p_name, Capture p_func) {
|
||||
ERR_FAIL_COND_MSG(captures.has(p_name), "Capture already registered: " + p_name);
|
||||
captures.insert(p_name, p_func);
|
||||
}
|
||||
|
||||
void EngineDebugger::unregister_message_capture(const StringName &p_name) {
|
||||
ERR_FAIL_COND_MSG(!captures.has(p_name), "Capture not registered: " + p_name);
|
||||
captures.erase(p_name);
|
||||
}
|
||||
|
||||
void EngineDebugger::register_uri_handler(const String &p_protocol, CreatePeerFunc p_func) {
|
||||
ERR_FAIL_COND_MSG(protocols.has(p_protocol), "Protocol handler already registered: " + p_protocol);
|
||||
protocols.insert(p_protocol, p_func);
|
||||
}
|
||||
|
||||
void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) {
|
||||
ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't change profiler state, no profiler: " + p_name);
|
||||
Profiler &p = profilers[p_name];
|
||||
if (p.toggle) {
|
||||
p.toggle(p.data, p_enabled, p_opts);
|
||||
}
|
||||
p.active = p_enabled;
|
||||
}
|
||||
|
||||
void EngineDebugger::profiler_add_frame_data(const StringName &p_name, const Array &p_data) {
|
||||
ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't add frame data, no profiler: " + p_name);
|
||||
Profiler &p = profilers[p_name];
|
||||
if (p.add) {
|
||||
p.add(p.data, p_data);
|
||||
}
|
||||
}
|
||||
|
||||
bool EngineDebugger::is_profiling(const StringName &p_name) {
|
||||
return profilers.has(p_name) && profilers[p_name].active;
|
||||
}
|
||||
|
||||
bool EngineDebugger::has_profiler(const StringName &p_name) {
|
||||
return profilers.has(p_name);
|
||||
}
|
||||
|
||||
bool EngineDebugger::has_capture(const StringName &p_name) {
|
||||
return captures.has(p_name);
|
||||
}
|
||||
|
||||
Error EngineDebugger::capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured) {
|
||||
r_captured = false;
|
||||
ERR_FAIL_COND_V_MSG(!captures.has(p_name), ERR_UNCONFIGURED, "Capture not registered: " + p_name);
|
||||
const Capture &cap = captures[p_name];
|
||||
return cap.capture(cap.data, p_msg, p_args, r_captured);
|
||||
}
|
||||
|
||||
void EngineDebugger::line_poll() {
|
||||
// The purpose of this is just processing events every now and then when the script might get too busy otherwise bugs like infinite loops can't be caught
|
||||
if (poll_every % 2048 == 0) {
|
||||
poll_events(false);
|
||||
}
|
||||
poll_every++;
|
||||
}
|
||||
|
||||
void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, double p_physics_frame_time) {
|
||||
frame_time = USEC_TO_SEC(p_frame_ticks);
|
||||
process_time = USEC_TO_SEC(p_process_ticks);
|
||||
physics_time = USEC_TO_SEC(p_physics_ticks);
|
||||
physics_frame_time = p_physics_frame_time;
|
||||
// Notify tick to running profilers
|
||||
for (KeyValue<StringName, Profiler> &E : profilers) {
|
||||
Profiler &p = E.value;
|
||||
if (!p.active || !p.tick) {
|
||||
continue;
|
||||
}
|
||||
p.tick(p.data, frame_time, process_time, physics_time, physics_frame_time);
|
||||
}
|
||||
singleton->poll_events(true);
|
||||
}
|
||||
|
||||
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, 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.
|
||||
if (p_uri.is_empty()) {
|
||||
return;
|
||||
}
|
||||
if (p_uri == "local://") {
|
||||
singleton = memnew(LocalDebugger);
|
||||
script_debugger = memnew(ScriptDebugger);
|
||||
// Tell the OS that we want to handle termination signals.
|
||||
OS::get_singleton()->initialize_debugging();
|
||||
} else if (p_uri.find("://") >= 0) {
|
||||
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
|
||||
if (!protocols.has(proto)) {
|
||||
return;
|
||||
}
|
||||
RemoteDebuggerPeer *peer = protocols[proto](p_uri);
|
||||
if (!peer) {
|
||||
return;
|
||||
}
|
||||
singleton = memnew(RemoteDebugger(Ref<RemoteDebuggerPeer>(peer)));
|
||||
script_debugger = memnew(ScriptDebugger);
|
||||
// Notify editor of our pid (to allow focus stealing).
|
||||
Array msg;
|
||||
msg.push_back(OS::get_singleton()->get_process_id());
|
||||
singleton->send_message("set_pid", msg);
|
||||
}
|
||||
if (!singleton) {
|
||||
return;
|
||||
}
|
||||
|
||||
// There is a debugger, parse breakpoints.
|
||||
ScriptDebugger *singleton_script_debugger = singleton->get_script_debugger();
|
||||
singleton_script_debugger->set_skip_breakpoints(p_skip_breakpoints);
|
||||
|
||||
for (int i = 0; i < p_breakpoints.size(); i++) {
|
||||
String bp = p_breakpoints[i];
|
||||
int sp = bp.rfind(":");
|
||||
ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format.");
|
||||
|
||||
singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp));
|
||||
}
|
||||
|
||||
allow_focus_steal_fn = p_allow_focus_steal_fn;
|
||||
}
|
||||
|
||||
void EngineDebugger::deinitialize() {
|
||||
if (singleton) {
|
||||
// Stop all profilers
|
||||
for (const KeyValue<StringName, Profiler> &E : profilers) {
|
||||
if (E.value.active) {
|
||||
singleton->profiler_enable(E.key, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Flush any remaining message
|
||||
singleton->poll_events(false);
|
||||
|
||||
memdelete(singleton);
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
// Clear profilers/captures/protocol handlers.
|
||||
profilers.clear();
|
||||
captures.clear();
|
||||
protocols.clear();
|
||||
}
|
||||
|
||||
EngineDebugger::~EngineDebugger() {
|
||||
if (script_debugger) {
|
||||
memdelete(script_debugger);
|
||||
}
|
||||
script_debugger = nullptr;
|
||||
singleton = nullptr;
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* engine_debugger.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ENGINE_DEBUGGER_H
|
||||
#define ENGINE_DEBUGGER_H
|
||||
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/templates/vector.h"
|
||||
#include "core/variant/array.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
class RemoteDebuggerPeer;
|
||||
class ScriptDebugger;
|
||||
|
||||
class EngineDebugger {
|
||||
public:
|
||||
typedef void (*ProfilingToggle)(void *p_user, bool p_enable, const Array &p_opts);
|
||||
typedef void (*ProfilingTick)(void *p_user, double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
|
||||
typedef void (*ProfilingAdd)(void *p_user, const Array &p_arr);
|
||||
|
||||
typedef Error (*CaptureFunc)(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured);
|
||||
|
||||
typedef RemoteDebuggerPeer *(*CreatePeerFunc)(const String &p_uri);
|
||||
|
||||
class Profiler {
|
||||
friend class EngineDebugger;
|
||||
|
||||
ProfilingToggle toggle = nullptr;
|
||||
ProfilingAdd add = nullptr;
|
||||
ProfilingTick tick = nullptr;
|
||||
void *data = nullptr;
|
||||
bool active = false;
|
||||
|
||||
public:
|
||||
Profiler() {}
|
||||
Profiler(void *p_data, ProfilingToggle p_toggle, ProfilingAdd p_add, ProfilingTick p_tick) {
|
||||
data = p_data;
|
||||
toggle = p_toggle;
|
||||
add = p_add;
|
||||
tick = p_tick;
|
||||
}
|
||||
};
|
||||
|
||||
class Capture {
|
||||
friend class EngineDebugger;
|
||||
|
||||
CaptureFunc capture = nullptr;
|
||||
void *data = nullptr;
|
||||
|
||||
public:
|
||||
Capture() {}
|
||||
Capture(void *p_data, CaptureFunc p_capture) {
|
||||
data = p_data;
|
||||
capture = p_capture;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
double frame_time = 0.0;
|
||||
double process_time = 0.0;
|
||||
double physics_time = 0.0;
|
||||
double physics_frame_time = 0.0;
|
||||
|
||||
uint32_t poll_every = 0;
|
||||
|
||||
protected:
|
||||
static EngineDebugger *singleton;
|
||||
static ScriptDebugger *script_debugger;
|
||||
|
||||
static HashMap<StringName, Profiler> profilers;
|
||||
static HashMap<StringName, Capture> captures;
|
||||
static HashMap<String, CreatePeerFunc> protocols;
|
||||
|
||||
static void (*allow_focus_steal_fn)();
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; }
|
||||
_FORCE_INLINE_ static bool is_active() { return singleton != nullptr && script_debugger != nullptr; }
|
||||
|
||||
_FORCE_INLINE_ static ScriptDebugger *get_script_debugger() { return script_debugger; };
|
||||
|
||||
static void initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints, void (*p_allow_focus_steal_fn)());
|
||||
static void deinitialize();
|
||||
static void register_profiler(const StringName &p_name, const Profiler &p_profiler);
|
||||
static void unregister_profiler(const StringName &p_name);
|
||||
static bool is_profiling(const StringName &p_name);
|
||||
static bool has_profiler(const StringName &p_name);
|
||||
static void profiler_add_frame_data(const StringName &p_name, const Array &p_data);
|
||||
|
||||
static void register_message_capture(const StringName &p_name, Capture p_func);
|
||||
static void unregister_message_capture(const StringName &p_name);
|
||||
static bool has_capture(const StringName &p_name);
|
||||
|
||||
static void register_uri_handler(const String &p_protocol, CreatePeerFunc p_func);
|
||||
|
||||
void iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, double p_physics_frame_time);
|
||||
void profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts = Array());
|
||||
Error capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured);
|
||||
|
||||
void line_poll();
|
||||
|
||||
virtual void poll_events(bool p_is_idle) {}
|
||||
virtual void send_message(const String &p_msg, const Array &p_data) = 0;
|
||||
virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) = 0;
|
||||
virtual void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false) = 0;
|
||||
|
||||
virtual ~EngineDebugger();
|
||||
};
|
||||
|
||||
#endif // ENGINE_DEBUGGER_H
|
||||
@ -1,82 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* engine_profiler.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 "engine_profiler.h"
|
||||
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
|
||||
void EngineProfiler::_bind_methods() {
|
||||
GDVIRTUAL_BIND(_toggle, "enable", "options");
|
||||
GDVIRTUAL_BIND(_add_frame, "data");
|
||||
GDVIRTUAL_BIND(_tick, "frame_time", "process_time", "physics_time", "physics_frame_time");
|
||||
}
|
||||
|
||||
void EngineProfiler::toggle(bool p_enable, const Array &p_array) {
|
||||
GDVIRTUAL_CALL(_toggle, p_enable, p_array);
|
||||
}
|
||||
|
||||
void EngineProfiler::add(const Array &p_data) {
|
||||
GDVIRTUAL_CALL(_add_frame, p_data);
|
||||
}
|
||||
|
||||
void EngineProfiler::tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
|
||||
GDVIRTUAL_CALL(_tick, p_frame_time, p_process_time, p_physics_time, p_physics_frame_time);
|
||||
}
|
||||
|
||||
Error EngineProfiler::bind(const String &p_name) {
|
||||
ERR_FAIL_COND_V(is_bound(), ERR_ALREADY_IN_USE);
|
||||
EngineDebugger::Profiler prof(
|
||||
this,
|
||||
[](void *p_user, bool p_enable, const Array &p_opts) {
|
||||
static_cast<EngineProfiler *>(p_user)->toggle(p_enable, p_opts);
|
||||
},
|
||||
[](void *p_user, const Array &p_data) {
|
||||
static_cast<EngineProfiler *>(p_user)->add(p_data);
|
||||
},
|
||||
[](void *p_user, double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
|
||||
static_cast<EngineProfiler *>(p_user)->tick(p_frame_time, p_process_time, p_physics_time, p_physics_frame_time);
|
||||
});
|
||||
registration = p_name;
|
||||
EngineDebugger::register_profiler(p_name, prof);
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error EngineProfiler::unbind() {
|
||||
ERR_FAIL_COND_V(!is_bound(), ERR_UNCONFIGURED);
|
||||
EngineDebugger::unregister_profiler(registration);
|
||||
registration.clear();
|
||||
return OK;
|
||||
}
|
||||
|
||||
EngineProfiler::~EngineProfiler() {
|
||||
if (is_bound()) {
|
||||
unbind();
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* engine_profiler.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ENGINE_PROFILER_H
|
||||
#define ENGINE_PROFILER_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
#include "core/object/gdvirtual.gen.inc"
|
||||
#include "core/object/script_language.h"
|
||||
|
||||
class EngineProfiler : public RefCounted {
|
||||
GDCLASS(EngineProfiler, RefCounted);
|
||||
|
||||
private:
|
||||
String registration;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual void toggle(bool p_enable, const Array &p_opts);
|
||||
virtual void add(const Array &p_data);
|
||||
virtual void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
|
||||
|
||||
Error bind(const String &p_name);
|
||||
Error unbind();
|
||||
bool is_bound() const { return registration.length() > 0; }
|
||||
|
||||
GDVIRTUAL2(_toggle, bool, Array);
|
||||
GDVIRTUAL1(_add_frame, Array);
|
||||
GDVIRTUAL4(_tick, double, double, double, double);
|
||||
|
||||
EngineProfiler() {}
|
||||
virtual ~EngineProfiler();
|
||||
};
|
||||
|
||||
#endif // ENGINE_PROFILER_H
|
||||
@ -1,389 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* local_debugger.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 "local_debugger.h"
|
||||
|
||||
#include "core/debugger/script_debugger.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
struct LocalDebugger::ScriptsProfiler {
|
||||
struct ProfileInfoSort {
|
||||
bool operator()(const ScriptLanguage::ProfilingInfo &A, const ScriptLanguage::ProfilingInfo &B) const {
|
||||
return A.total_time > B.total_time;
|
||||
}
|
||||
};
|
||||
|
||||
double frame_time = 0;
|
||||
uint64_t idle_accum = 0;
|
||||
Vector<ScriptLanguage::ProfilingInfo> pinfo;
|
||||
|
||||
void toggle(bool p_enable, const Array &p_opts) {
|
||||
if (p_enable) {
|
||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||
ScriptServer::get_language(i)->profiling_start();
|
||||
}
|
||||
|
||||
print_line("BEGIN PROFILING");
|
||||
pinfo.resize(32768);
|
||||
} else {
|
||||
_print_frame_data(true);
|
||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||
ScriptServer::get_language(i)->profiling_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
|
||||
frame_time = p_frame_time;
|
||||
_print_frame_data(false);
|
||||
}
|
||||
|
||||
void _print_frame_data(bool p_accumulated) {
|
||||
uint64_t diff = OS::get_singleton()->get_ticks_usec() - idle_accum;
|
||||
|
||||
if (!p_accumulated && diff < 1000000) { //show every one second
|
||||
return;
|
||||
}
|
||||
|
||||
idle_accum = OS::get_singleton()->get_ticks_usec();
|
||||
|
||||
int ofs = 0;
|
||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||
if (p_accumulated) {
|
||||
ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&pinfo.write[ofs], pinfo.size() - ofs);
|
||||
} else {
|
||||
ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&pinfo.write[ofs], pinfo.size() - ofs);
|
||||
}
|
||||
}
|
||||
|
||||
SortArray<ScriptLanguage::ProfilingInfo, ProfileInfoSort> sort;
|
||||
sort.sort(pinfo.ptrw(), ofs);
|
||||
|
||||
// compute total script frame time
|
||||
uint64_t script_time_us = 0;
|
||||
for (int i = 0; i < ofs; i++) {
|
||||
script_time_us += pinfo[i].self_time;
|
||||
}
|
||||
double script_time = USEC_TO_SEC(script_time_us);
|
||||
double total_time = p_accumulated ? script_time : frame_time;
|
||||
|
||||
if (!p_accumulated) {
|
||||
print_line("FRAME: total: " + rtos(total_time) + " script: " + rtos(script_time) + "/" + itos(script_time * 100 / total_time) + " %");
|
||||
} else {
|
||||
print_line("ACCUMULATED: total: " + rtos(total_time));
|
||||
}
|
||||
|
||||
for (int i = 0; i < ofs; i++) {
|
||||
print_line(itos(i) + ":" + pinfo[i].signature);
|
||||
double tt = USEC_TO_SEC(pinfo[i].total_time);
|
||||
double st = USEC_TO_SEC(pinfo[i].self_time);
|
||||
print_line("\ttotal: " + rtos(tt) + "/" + itos(tt * 100 / total_time) + " % \tself: " + rtos(st) + "/" + itos(st * 100 / total_time) + " % tcalls: " + itos(pinfo[i].call_count));
|
||||
}
|
||||
}
|
||||
|
||||
ScriptsProfiler() {
|
||||
idle_accum = OS::get_singleton()->get_ticks_usec();
|
||||
}
|
||||
};
|
||||
|
||||
void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
|
||||
ScriptLanguage *script_lang = script_debugger->get_break_language();
|
||||
|
||||
if (!target_function.is_empty()) {
|
||||
String current_function = script_lang->debug_get_stack_level_function(0);
|
||||
if (current_function != target_function) {
|
||||
script_debugger->set_depth(0);
|
||||
script_debugger->set_lines_left(1);
|
||||
return;
|
||||
}
|
||||
target_function = "";
|
||||
}
|
||||
|
||||
print_line("\nDebugger Break, Reason: '" + script_lang->debug_get_error() + "'");
|
||||
print_line("*Frame " + itos(0) + " - " + script_lang->debug_get_stack_level_source(0) + ":" + itos(script_lang->debug_get_stack_level_line(0)) + " in function '" + script_lang->debug_get_stack_level_function(0) + "'");
|
||||
print_line("Enter \"help\" for assistance.");
|
||||
int current_frame = 0;
|
||||
int total_frames = script_lang->debug_get_stack_level_count();
|
||||
while (true) {
|
||||
OS::get_singleton()->print("debug> ");
|
||||
String line = OS::get_singleton()->get_stdin_string().strip_edges();
|
||||
|
||||
// Cache options
|
||||
String variable_prefix = options["variable_prefix"];
|
||||
|
||||
if (line.is_empty()) {
|
||||
print_line("\nDebugger Break, Reason: '" + script_lang->debug_get_error() + "'");
|
||||
print_line("*Frame " + itos(current_frame) + " - " + script_lang->debug_get_stack_level_source(current_frame) + ":" + itos(script_lang->debug_get_stack_level_line(current_frame)) + " in function '" + script_lang->debug_get_stack_level_function(current_frame) + "'");
|
||||
print_line("Enter \"help\" for assistance.");
|
||||
} else if (line == "c" || line == "continue") {
|
||||
break;
|
||||
} else if (line == "bt" || line == "breakpoint") {
|
||||
for (int i = 0; i < total_frames; i++) {
|
||||
String cfi = (current_frame == i) ? "*" : " "; //current frame indicator
|
||||
print_line(cfi + "Frame " + itos(i) + " - " + script_lang->debug_get_stack_level_source(i) + ":" + itos(script_lang->debug_get_stack_level_line(i)) + " in function '" + script_lang->debug_get_stack_level_function(i) + "'");
|
||||
}
|
||||
|
||||
} else if (line.begins_with("fr") || line.begins_with("frame")) {
|
||||
if (line.get_slice_count(" ") == 1) {
|
||||
print_line("*Frame " + itos(current_frame) + " - " + script_lang->debug_get_stack_level_source(current_frame) + ":" + itos(script_lang->debug_get_stack_level_line(current_frame)) + " in function '" + script_lang->debug_get_stack_level_function(current_frame) + "'");
|
||||
} else {
|
||||
int frame = line.get_slicec(' ', 1).to_int();
|
||||
if (frame < 0 || frame >= total_frames) {
|
||||
print_line("Error: Invalid frame.");
|
||||
} else {
|
||||
current_frame = frame;
|
||||
print_line("*Frame " + itos(frame) + " - " + script_lang->debug_get_stack_level_source(frame) + ":" + itos(script_lang->debug_get_stack_level_line(frame)) + " in function '" + script_lang->debug_get_stack_level_function(frame) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
} else if (line.begins_with("set")) {
|
||||
if (line.get_slice_count(" ") == 1) {
|
||||
for (const KeyValue<String, String> &E : options) {
|
||||
print_line("\t" + E.key + "=" + E.value);
|
||||
}
|
||||
|
||||
} else {
|
||||
String key_value = line.get_slicec(' ', 1);
|
||||
int value_pos = key_value.find("=");
|
||||
|
||||
if (value_pos < 0) {
|
||||
print_line("Error: Invalid set format. Use: set key=value");
|
||||
} else {
|
||||
String key = key_value.left(value_pos);
|
||||
|
||||
if (!options.has(key)) {
|
||||
print_line("Error: Unknown option " + key);
|
||||
} else {
|
||||
// Allow explicit tab character
|
||||
String value = key_value.substr(value_pos + 1).replace("\\t", "\t");
|
||||
|
||||
options[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (line == "lv" || line == "locals") {
|
||||
List<String> locals;
|
||||
List<Variant> values;
|
||||
script_lang->debug_get_stack_level_locals(current_frame, &locals, &values);
|
||||
print_variables(locals, values, variable_prefix);
|
||||
|
||||
} else if (line == "gv" || line == "globals") {
|
||||
List<String> globals;
|
||||
List<Variant> values;
|
||||
script_lang->debug_get_globals(&globals, &values);
|
||||
print_variables(globals, values, variable_prefix);
|
||||
|
||||
} else if (line == "mv" || line == "members") {
|
||||
List<String> members;
|
||||
List<Variant> values;
|
||||
script_lang->debug_get_stack_level_members(current_frame, &members, &values);
|
||||
print_variables(members, values, variable_prefix);
|
||||
|
||||
} else if (line.begins_with("p") || line.begins_with("print")) {
|
||||
if (line.get_slice_count(" ") <= 1) {
|
||||
print_line("Usage: print <expre>");
|
||||
} else {
|
||||
String expr = line.get_slicec(' ', 2);
|
||||
String res = script_lang->debug_parse_stack_level_expression(current_frame, expr);
|
||||
print_line(res);
|
||||
}
|
||||
|
||||
} else if (line == "s" || line == "step") {
|
||||
script_debugger->set_depth(-1);
|
||||
script_debugger->set_lines_left(1);
|
||||
break;
|
||||
} else if (line == "n" || line == "next") {
|
||||
script_debugger->set_depth(0);
|
||||
script_debugger->set_lines_left(1);
|
||||
break;
|
||||
} else if (line == "fin" || line == "finish") {
|
||||
String current_function = script_lang->debug_get_stack_level_function(0);
|
||||
|
||||
for (int i = 0; i < total_frames; i++) {
|
||||
target_function = script_lang->debug_get_stack_level_function(i);
|
||||
if (target_function != current_function) {
|
||||
script_debugger->set_depth(0);
|
||||
script_debugger->set_lines_left(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
print_line("Error: Reached last frame.");
|
||||
target_function = "";
|
||||
|
||||
} else if (line.begins_with("br") || line.begins_with("break")) {
|
||||
if (line.get_slice_count(" ") <= 1) {
|
||||
const HashMap<int, HashSet<StringName>> &breakpoints = script_debugger->get_breakpoints();
|
||||
if (breakpoints.size() == 0) {
|
||||
print_line("No Breakpoints.");
|
||||
continue;
|
||||
}
|
||||
|
||||
print_line("Breakpoint(s): " + itos(breakpoints.size()));
|
||||
for (const KeyValue<int, HashSet<StringName>> &E : breakpoints) {
|
||||
print_line("\t" + String(*E.value.begin()) + ":" + itos(E.key));
|
||||
}
|
||||
|
||||
} else {
|
||||
Pair<String, int> breakpoint = to_breakpoint(line);
|
||||
|
||||
String source = breakpoint.first;
|
||||
int linenr = breakpoint.second;
|
||||
|
||||
if (source.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
script_debugger->insert_breakpoint(linenr, source);
|
||||
|
||||
print_line("Added breakpoint at " + source + ":" + itos(linenr));
|
||||
}
|
||||
|
||||
} else if (line == "q" || line == "quit") {
|
||||
// Do not stop again on quit
|
||||
script_debugger->clear_breakpoints();
|
||||
script_debugger->set_depth(-1);
|
||||
script_debugger->set_lines_left(-1);
|
||||
|
||||
MainLoop *main_loop = OS::get_singleton()->get_main_loop();
|
||||
if (main_loop->get_class() == "SceneTree") {
|
||||
main_loop->call("quit");
|
||||
}
|
||||
break;
|
||||
} else if (line.begins_with("delete")) {
|
||||
if (line.get_slice_count(" ") <= 1) {
|
||||
script_debugger->clear_breakpoints();
|
||||
} else {
|
||||
Pair<String, int> breakpoint = to_breakpoint(line);
|
||||
|
||||
String source = breakpoint.first;
|
||||
int linenr = breakpoint.second;
|
||||
|
||||
if (source.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
script_debugger->remove_breakpoint(linenr, source);
|
||||
|
||||
print_line("Removed breakpoint at " + source + ":" + itos(linenr));
|
||||
}
|
||||
|
||||
} else if (line == "h" || line == "help") {
|
||||
print_line("Built-In Debugger command list:\n");
|
||||
print_line("\tc,continue\t\t Continue execution.");
|
||||
print_line("\tbt,backtrace\t\t Show stack trace (frames).");
|
||||
print_line("\tfr,frame <frame>:\t Change current frame.");
|
||||
print_line("\tlv,locals\t\t Show local variables for current frame.");
|
||||
print_line("\tmv,members\t\t Show member variables for \"this\" in frame.");
|
||||
print_line("\tgv,globals\t\t Show global variables.");
|
||||
print_line("\tp,print <expr>\t\t Execute and print variable in expression.");
|
||||
print_line("\ts,step\t\t\t Step to next line.");
|
||||
print_line("\tn,next\t\t\t Next line.");
|
||||
print_line("\tfin,finish\t\t Step out of current frame.");
|
||||
print_line("\tbr,break [source:line]\t List all breakpoints or place a breakpoint.");
|
||||
print_line("\tdelete [source:line]:\t Delete one/all breakpoints.");
|
||||
print_line("\tset [key=value]:\t List all options, or set one.");
|
||||
print_line("\tq,quit\t\t\t Quit application.");
|
||||
} else {
|
||||
print_line("Error: Invalid command, enter \"help\" for assistance.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalDebugger::print_variables(const List<String> &names, const List<Variant> &values, const String &variable_prefix) {
|
||||
String value;
|
||||
Vector<String> value_lines;
|
||||
const List<Variant>::Element *V = values.front();
|
||||
for (const String &E : names) {
|
||||
value = String(V->get());
|
||||
|
||||
if (variable_prefix.is_empty()) {
|
||||
print_line(E + ": " + String(V->get()));
|
||||
} else {
|
||||
print_line(E + ":");
|
||||
value_lines = value.split("\n");
|
||||
for (int i = 0; i < value_lines.size(); ++i) {
|
||||
print_line(variable_prefix + value_lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
V = V->next();
|
||||
}
|
||||
}
|
||||
|
||||
Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) {
|
||||
String breakpoint_part = p_line.get_slicec(' ', 1);
|
||||
Pair<String, int> breakpoint;
|
||||
|
||||
int last_colon = breakpoint_part.rfind(":");
|
||||
if (last_colon < 0) {
|
||||
print_line("Error: Invalid breakpoint format. Expected [source:line]");
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
breakpoint.first = script_debugger->breakpoint_find_source(breakpoint_part.left(last_colon).strip_edges());
|
||||
breakpoint.second = breakpoint_part.substr(last_colon).strip_edges().to_int();
|
||||
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
void LocalDebugger::send_message(const String &p_message, const Array &p_args) {
|
||||
// This needs to be cleaned up entirely.
|
||||
// print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args)));
|
||||
}
|
||||
|
||||
void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
print_line("ERROR: '" + (p_descr.is_empty() ? p_err : p_descr) + "'");
|
||||
}
|
||||
|
||||
LocalDebugger::LocalDebugger() {
|
||||
options["variable_prefix"] = "";
|
||||
|
||||
// Bind scripts profiler.
|
||||
scripts_profiler = memnew(ScriptsProfiler);
|
||||
Profiler scr_prof(
|
||||
scripts_profiler,
|
||||
[](void *p_user, bool p_enable, const Array &p_opts) {
|
||||
static_cast<ScriptsProfiler *>(p_user)->toggle(p_enable, p_opts);
|
||||
},
|
||||
nullptr,
|
||||
[](void *p_user, double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
|
||||
static_cast<ScriptsProfiler *>(p_user)->tick(p_frame_time, p_process_time, p_physics_time, p_physics_frame_time);
|
||||
});
|
||||
register_profiler("scripts", scr_prof);
|
||||
}
|
||||
|
||||
LocalDebugger::~LocalDebugger() {
|
||||
unregister_profiler("scripts");
|
||||
if (scripts_profiler) {
|
||||
memdelete(scripts_profiler);
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* local_debugger.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef LOCAL_DEBUGGER_H
|
||||
#define LOCAL_DEBUGGER_H
|
||||
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/templates/list.h"
|
||||
|
||||
class LocalDebugger : public EngineDebugger {
|
||||
private:
|
||||
struct ScriptsProfiler;
|
||||
|
||||
ScriptsProfiler *scripts_profiler = nullptr;
|
||||
|
||||
String target_function;
|
||||
HashMap<String, String> options;
|
||||
|
||||
Pair<String, int> to_breakpoint(const String &p_line);
|
||||
void print_variables(const List<String> &names, const List<Variant> &values, const String &variable_prefix);
|
||||
|
||||
public:
|
||||
void debug(bool p_can_continue, bool p_is_error_breakpoint);
|
||||
void send_message(const String &p_message, const Array &p_args);
|
||||
void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type);
|
||||
|
||||
LocalDebugger();
|
||||
~LocalDebugger();
|
||||
};
|
||||
|
||||
#endif // LOCAL_DEBUGGER_H
|
||||
@ -1,612 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* remote_debugger.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 "remote_debugger.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/debugger/debugger_marshalls.h"
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
#include "core/debugger/engine_profiler.h"
|
||||
#include "core/debugger/script_debugger.h"
|
||||
#include "core/input/input.h"
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
|
||||
Object *performance = nullptr;
|
||||
int last_perf_time = 0;
|
||||
uint64_t last_monitor_modification_time = 0;
|
||||
|
||||
public:
|
||||
void toggle(bool p_enable, const Array &p_opts) {}
|
||||
void add(const Array &p_data) {}
|
||||
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
|
||||
if (!performance) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t pt = OS::get_singleton()->get_ticks_msec();
|
||||
if (pt - last_perf_time < 1000) {
|
||||
return;
|
||||
}
|
||||
last_perf_time = pt;
|
||||
|
||||
Array custom_monitor_names = performance->call("get_custom_monitor_names");
|
||||
|
||||
uint64_t monitor_modification_time = performance->call("get_monitor_modification_time");
|
||||
if (monitor_modification_time > last_monitor_modification_time) {
|
||||
last_monitor_modification_time = monitor_modification_time;
|
||||
EngineDebugger::get_singleton()->send_message("performance:profile_names", custom_monitor_names);
|
||||
}
|
||||
|
||||
int max = performance->get("MONITOR_MAX");
|
||||
Array arr;
|
||||
arr.resize(max + custom_monitor_names.size());
|
||||
for (int i = 0; i < max; i++) {
|
||||
arr[i] = performance->call("get_monitor", i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < custom_monitor_names.size(); i++) {
|
||||
Variant monitor_value = performance->call("get_custom_monitor", custom_monitor_names[i]);
|
||||
if (!monitor_value.is_num()) {
|
||||
ERR_PRINT("Value of custom monitor '" + String(custom_monitor_names[i]) + "' is not a number");
|
||||
arr[i + max] = Variant();
|
||||
} else {
|
||||
arr[i + max] = monitor_value;
|
||||
}
|
||||
}
|
||||
|
||||
EngineDebugger::get_singleton()->send_message("performance:profile_frame", arr);
|
||||
}
|
||||
|
||||
explicit PerformanceProfiler(Object *p_performance) {
|
||||
performance = p_performance;
|
||||
}
|
||||
};
|
||||
|
||||
Error RemoteDebugger::_put_msg(String p_message, Array p_data) {
|
||||
Array msg;
|
||||
msg.push_back(p_message);
|
||||
msg.push_back(p_data);
|
||||
Error err = peer->put_message(msg);
|
||||
if (err != OK) {
|
||||
n_messages_dropped++;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
if (p_type == ERR_HANDLER_SCRIPT) {
|
||||
return; //ignore script errors, those go through debugger
|
||||
}
|
||||
|
||||
RemoteDebugger *rd = static_cast<RemoteDebugger *>(p_this);
|
||||
if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive errors during flush.
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<ScriptLanguage::StackInfo> si;
|
||||
|
||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||
si = ScriptServer::get_language(i)->debug_get_current_stack_info();
|
||||
if (si.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send_error will lock internally.
|
||||
rd->script_debugger->send_error(String::utf8(p_func), String::utf8(p_file), p_line, String::utf8(p_err), String::utf8(p_descr), p_editor_notify, p_type, si);
|
||||
}
|
||||
|
||||
void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error, bool p_rich) {
|
||||
RemoteDebugger *rd = static_cast<RemoteDebugger *>(p_this);
|
||||
|
||||
if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive prints during flush.
|
||||
return;
|
||||
}
|
||||
|
||||
String s = p_string;
|
||||
int allowed_chars = MIN(MAX(rd->max_chars_per_second - rd->char_count, 0), s.length());
|
||||
|
||||
if (allowed_chars == 0 && s.length() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowed_chars < s.length()) {
|
||||
s = s.substr(0, allowed_chars);
|
||||
}
|
||||
|
||||
MutexLock lock(rd->mutex);
|
||||
|
||||
rd->char_count += allowed_chars;
|
||||
bool overflowed = rd->char_count >= rd->max_chars_per_second;
|
||||
if (rd->is_peer_connected()) {
|
||||
if (overflowed) {
|
||||
s += "[...]";
|
||||
}
|
||||
|
||||
OutputString output_string;
|
||||
output_string.message = s;
|
||||
if (p_error) {
|
||||
output_string.type = MESSAGE_TYPE_ERROR;
|
||||
} else if (p_rich) {
|
||||
output_string.type = MESSAGE_TYPE_LOG_RICH;
|
||||
} else {
|
||||
output_string.type = MESSAGE_TYPE_LOG;
|
||||
}
|
||||
rd->output_strings.push_back(output_string);
|
||||
|
||||
if (overflowed) {
|
||||
output_string.message = "[output overflow, print less text!]";
|
||||
output_string.type = MESSAGE_TYPE_ERROR;
|
||||
rd->output_strings.push_back(output_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoteDebugger::ErrorMessage RemoteDebugger::_create_overflow_error(const String &p_what, const String &p_descr) {
|
||||
ErrorMessage oe;
|
||||
oe.error = p_what;
|
||||
oe.error_descr = p_descr;
|
||||
oe.warning = false;
|
||||
uint64_t time = OS::get_singleton()->get_ticks_msec();
|
||||
oe.hr = time / 3600000;
|
||||
oe.min = (time / 60000) % 60;
|
||||
oe.sec = (time / 1000) % 60;
|
||||
oe.msec = time % 1000;
|
||||
return oe;
|
||||
}
|
||||
|
||||
void RemoteDebugger::flush_output() {
|
||||
flush_thread = Thread::get_caller_id();
|
||||
flushing = true;
|
||||
MutexLock lock(mutex);
|
||||
if (!is_peer_connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n_messages_dropped > 0) {
|
||||
ErrorMessage err_msg = _create_overflow_error("TOO_MANY_MESSAGES", "Too many messages! " + String::num_int64(n_messages_dropped) + " messages were dropped. Profiling might misbheave, try raising 'network/limits/debugger/max_queued_messages' in project setting.");
|
||||
if (_put_msg("error", err_msg.serialize()) == OK) {
|
||||
n_messages_dropped = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (output_strings.size()) {
|
||||
// Join output strings so we generate less messages.
|
||||
Vector<String> joined_log_strings;
|
||||
Vector<String> strings;
|
||||
Vector<int> types;
|
||||
for (int i = 0; i < output_strings.size(); i++) {
|
||||
const OutputString &output_string = output_strings[i];
|
||||
if (output_string.type == MESSAGE_TYPE_ERROR) {
|
||||
if (!joined_log_strings.is_empty()) {
|
||||
strings.push_back(String("\n").join(joined_log_strings));
|
||||
types.push_back(MESSAGE_TYPE_LOG);
|
||||
joined_log_strings.clear();
|
||||
}
|
||||
strings.push_back(output_string.message);
|
||||
types.push_back(MESSAGE_TYPE_ERROR);
|
||||
} else if (output_string.type == MESSAGE_TYPE_LOG_RICH) {
|
||||
if (!joined_log_strings.is_empty()) {
|
||||
strings.push_back(String("\n").join(joined_log_strings));
|
||||
types.push_back(MESSAGE_TYPE_LOG_RICH);
|
||||
joined_log_strings.clear();
|
||||
}
|
||||
strings.push_back(output_string.message);
|
||||
types.push_back(MESSAGE_TYPE_LOG_RICH);
|
||||
} else {
|
||||
joined_log_strings.push_back(output_string.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!joined_log_strings.is_empty()) {
|
||||
strings.push_back(String("\n").join(joined_log_strings));
|
||||
types.push_back(MESSAGE_TYPE_LOG);
|
||||
}
|
||||
|
||||
Array arr;
|
||||
arr.push_back(strings);
|
||||
arr.push_back(types);
|
||||
_put_msg("output", arr);
|
||||
output_strings.clear();
|
||||
}
|
||||
|
||||
while (errors.size()) {
|
||||
ErrorMessage oe = errors.front()->get();
|
||||
_put_msg("error", oe.serialize());
|
||||
errors.pop_front();
|
||||
}
|
||||
|
||||
// Update limits
|
||||
uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000;
|
||||
|
||||
if (ticks - last_reset > 1000) {
|
||||
last_reset = ticks;
|
||||
char_count = 0;
|
||||
err_count = 0;
|
||||
n_errors_dropped = 0;
|
||||
warn_count = 0;
|
||||
n_warnings_dropped = 0;
|
||||
}
|
||||
flushing = false;
|
||||
}
|
||||
|
||||
void RemoteDebugger::send_message(const String &p_message, const Array &p_args) {
|
||||
MutexLock lock(mutex);
|
||||
if (is_peer_connected()) {
|
||||
_put_msg(p_message, p_args);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
ErrorMessage oe;
|
||||
oe.error = p_err;
|
||||
oe.error_descr = p_descr;
|
||||
oe.source_file = p_file;
|
||||
oe.source_line = p_line;
|
||||
oe.source_func = p_func;
|
||||
oe.warning = p_type == ERR_HANDLER_WARNING;
|
||||
uint64_t time = OS::get_singleton()->get_ticks_msec();
|
||||
oe.hr = time / 3600000;
|
||||
oe.min = (time / 60000) % 60;
|
||||
oe.sec = (time / 1000) % 60;
|
||||
oe.msec = time % 1000;
|
||||
oe.callstack.append_array(script_debugger->get_error_stack_info());
|
||||
|
||||
if (flushing && Thread::get_caller_id() == flush_thread) { // Can't handle recursive errors during flush.
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock lock(mutex);
|
||||
|
||||
if (oe.warning) {
|
||||
warn_count++;
|
||||
} else {
|
||||
err_count++;
|
||||
}
|
||||
|
||||
if (is_peer_connected()) {
|
||||
if (oe.warning) {
|
||||
if (warn_count > max_warnings_per_second) {
|
||||
n_warnings_dropped++;
|
||||
if (n_warnings_dropped == 1) {
|
||||
// Only print one message about dropping per second
|
||||
ErrorMessage overflow = _create_overflow_error("TOO_MANY_WARNINGS", "Too many warnings! Ignoring warnings for up to 1 second.");
|
||||
errors.push_back(overflow);
|
||||
}
|
||||
} else {
|
||||
errors.push_back(oe);
|
||||
}
|
||||
} else {
|
||||
if (err_count > max_errors_per_second) {
|
||||
n_errors_dropped++;
|
||||
if (n_errors_dropped == 1) {
|
||||
// Only print one message about dropping per second
|
||||
ErrorMessage overflow = _create_overflow_error("TOO_MANY_ERRORS", "Too many errors! Ignoring errors for up to 1 second.");
|
||||
errors.push_back(overflow);
|
||||
}
|
||||
} else {
|
||||
errors.push_back(oe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteDebugger::_send_stack_vars(List<String> &p_names, List<Variant> &p_vals, int p_type) {
|
||||
DebuggerMarshalls::ScriptStackVariable stvar;
|
||||
List<String>::Element *E = p_names.front();
|
||||
List<Variant>::Element *F = p_vals.front();
|
||||
while (E) {
|
||||
stvar.name = E->get();
|
||||
stvar.value = F->get();
|
||||
stvar.type = p_type;
|
||||
send_message("stack_frame_var", stvar.serialize());
|
||||
E = E->next();
|
||||
F = F->next();
|
||||
}
|
||||
}
|
||||
|
||||
Error RemoteDebugger::_try_capture(const String &p_msg, const Array &p_data, bool &r_captured) {
|
||||
const int idx = p_msg.find(":");
|
||||
r_captured = false;
|
||||
if (idx < 0) { // No prefix, unknown message.
|
||||
return OK;
|
||||
}
|
||||
const String cap = p_msg.substr(0, idx);
|
||||
if (!has_capture(cap)) {
|
||||
return ERR_UNAVAILABLE; // Unknown message...
|
||||
}
|
||||
const String msg = p_msg.substr(idx + 1);
|
||||
return capture_parse(cap, msg, p_data, r_captured);
|
||||
}
|
||||
|
||||
void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
|
||||
//this function is called when there is a debugger break (bug on script)
|
||||
//or when execution is paused from editor
|
||||
|
||||
if (script_debugger->is_skipping_breakpoints() && !p_is_error_breakpoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(!is_peer_connected(), "Script Debugger failed to connect, but being used anyway.");
|
||||
|
||||
if (!peer->can_block()) {
|
||||
return; // Peer does not support blocking IO. We could at least send the error though.
|
||||
}
|
||||
|
||||
ScriptLanguage *script_lang = script_debugger->get_break_language();
|
||||
const String error_str = script_lang ? script_lang->debug_get_error() : "";
|
||||
Array msg;
|
||||
msg.push_back(p_can_continue);
|
||||
msg.push_back(error_str);
|
||||
ERR_FAIL_COND(!script_lang);
|
||||
msg.push_back(script_lang->debug_get_stack_level_count() > 0);
|
||||
if (allow_focus_steal_fn) {
|
||||
allow_focus_steal_fn();
|
||||
}
|
||||
send_message("debug_enter", msg);
|
||||
|
||||
Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode();
|
||||
if (mouse_mode != Input::MOUSE_MODE_VISIBLE) {
|
||||
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
|
||||
}
|
||||
|
||||
while (is_peer_connected()) {
|
||||
flush_output();
|
||||
peer->poll();
|
||||
|
||||
if (peer->has_message()) {
|
||||
Array cmd = peer->get_message();
|
||||
|
||||
ERR_CONTINUE(cmd.size() != 2);
|
||||
ERR_CONTINUE(cmd[0].get_type() != Variant::STRING);
|
||||
ERR_CONTINUE(cmd[1].get_type() != Variant::ARRAY);
|
||||
|
||||
String command = cmd[0];
|
||||
Array data = cmd[1];
|
||||
|
||||
if (command == "step") {
|
||||
script_debugger->set_depth(-1);
|
||||
script_debugger->set_lines_left(1);
|
||||
break;
|
||||
|
||||
} else if (command == "next") {
|
||||
script_debugger->set_depth(0);
|
||||
script_debugger->set_lines_left(1);
|
||||
break;
|
||||
|
||||
} else if (command == "continue") {
|
||||
script_debugger->set_depth(-1);
|
||||
script_debugger->set_lines_left(-1);
|
||||
break;
|
||||
|
||||
} else if (command == "break") {
|
||||
ERR_PRINT("Got break when already broke!");
|
||||
break;
|
||||
|
||||
} else if (command == "get_stack_dump") {
|
||||
DebuggerMarshalls::ScriptStackDump dump;
|
||||
int slc = script_lang->debug_get_stack_level_count();
|
||||
for (int i = 0; i < slc; i++) {
|
||||
ScriptLanguage::StackInfo frame;
|
||||
frame.file = script_lang->debug_get_stack_level_source(i);
|
||||
frame.line = script_lang->debug_get_stack_level_line(i);
|
||||
frame.func = script_lang->debug_get_stack_level_function(i);
|
||||
dump.frames.push_back(frame);
|
||||
}
|
||||
send_message("stack_dump", dump.serialize());
|
||||
|
||||
} else if (command == "get_stack_frame_vars") {
|
||||
ERR_FAIL_COND(data.size() != 1);
|
||||
ERR_FAIL_COND(!script_lang);
|
||||
int lv = data[0];
|
||||
|
||||
List<String> members;
|
||||
List<Variant> member_vals;
|
||||
if (ScriptInstance *inst = script_lang->debug_get_stack_level_instance(lv)) {
|
||||
members.push_back("self");
|
||||
member_vals.push_back(inst->get_owner());
|
||||
}
|
||||
script_lang->debug_get_stack_level_members(lv, &members, &member_vals);
|
||||
ERR_FAIL_COND(members.size() != member_vals.size());
|
||||
|
||||
List<String> locals;
|
||||
List<Variant> local_vals;
|
||||
script_lang->debug_get_stack_level_locals(lv, &locals, &local_vals);
|
||||
ERR_FAIL_COND(locals.size() != local_vals.size());
|
||||
|
||||
List<String> globals;
|
||||
List<Variant> globals_vals;
|
||||
script_lang->debug_get_globals(&globals, &globals_vals);
|
||||
ERR_FAIL_COND(globals.size() != globals_vals.size());
|
||||
|
||||
Array var_size;
|
||||
var_size.push_back(local_vals.size() + member_vals.size() + globals_vals.size());
|
||||
send_message("stack_frame_vars", var_size);
|
||||
_send_stack_vars(locals, local_vals, 0);
|
||||
_send_stack_vars(members, member_vals, 1);
|
||||
_send_stack_vars(globals, globals_vals, 2);
|
||||
|
||||
} else if (command == "reload_scripts") {
|
||||
reload_all_scripts = true;
|
||||
|
||||
} else if (command == "breakpoint") {
|
||||
ERR_FAIL_COND(data.size() < 3);
|
||||
bool set = data[2];
|
||||
if (set) {
|
||||
script_debugger->insert_breakpoint(data[1], data[0]);
|
||||
} else {
|
||||
script_debugger->remove_breakpoint(data[1], data[0]);
|
||||
}
|
||||
|
||||
} else if (command == "set_skip_breakpoints") {
|
||||
ERR_FAIL_COND(data.size() < 1);
|
||||
script_debugger->set_skip_breakpoints(data[0]);
|
||||
} else {
|
||||
bool captured = false;
|
||||
ERR_CONTINUE(_try_capture(command, data, captured) != OK);
|
||||
if (!captured) {
|
||||
WARN_PRINT("Unknown message received from debugger: " + command);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
OS::get_singleton()->delay_usec(10000);
|
||||
OS::get_singleton()->process_and_drop_events();
|
||||
}
|
||||
}
|
||||
|
||||
send_message("debug_exit", Array());
|
||||
|
||||
if (mouse_mode != Input::MOUSE_MODE_VISIBLE) {
|
||||
Input::get_singleton()->set_mouse_mode(mouse_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteDebugger::poll_events(bool p_is_idle) {
|
||||
if (peer.is_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
flush_output();
|
||||
peer->poll();
|
||||
while (peer->has_message()) {
|
||||
Array arr = peer->get_message();
|
||||
|
||||
ERR_CONTINUE(arr.size() != 2);
|
||||
ERR_CONTINUE(arr[0].get_type() != Variant::STRING);
|
||||
ERR_CONTINUE(arr[1].get_type() != Variant::ARRAY);
|
||||
|
||||
const String cmd = arr[0];
|
||||
const int idx = cmd.find(":");
|
||||
bool parsed = false;
|
||||
if (idx < 0) { // Not prefix, use scripts capture.
|
||||
capture_parse("core", cmd, arr[1], parsed);
|
||||
continue;
|
||||
}
|
||||
|
||||
const String cap = cmd.substr(0, idx);
|
||||
if (!has_capture(cap)) {
|
||||
continue; // Unknown message...
|
||||
}
|
||||
|
||||
const String msg = cmd.substr(idx + 1);
|
||||
capture_parse(cap, msg, arr[1], parsed);
|
||||
}
|
||||
|
||||
// Reload scripts during idle poll only.
|
||||
if (p_is_idle && reload_all_scripts) {
|
||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||
ScriptServer::get_language(i)->reload_all_scripts();
|
||||
}
|
||||
reload_all_scripts = false;
|
||||
}
|
||||
}
|
||||
|
||||
Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bool &r_captured) {
|
||||
r_captured = true;
|
||||
if (p_cmd == "reload_scripts") {
|
||||
reload_all_scripts = true;
|
||||
|
||||
} else if (p_cmd == "breakpoint") {
|
||||
ERR_FAIL_COND_V(p_data.size() < 3, ERR_INVALID_DATA);
|
||||
bool set = p_data[2];
|
||||
if (set) {
|
||||
script_debugger->insert_breakpoint(p_data[1], p_data[0]);
|
||||
} else {
|
||||
script_debugger->remove_breakpoint(p_data[1], p_data[0]);
|
||||
}
|
||||
|
||||
} else if (p_cmd == "set_skip_breakpoints") {
|
||||
ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
|
||||
script_debugger->set_skip_breakpoints(p_data[0]);
|
||||
} else if (p_cmd == "break") {
|
||||
script_debugger->debug(script_debugger->get_break_language());
|
||||
} else {
|
||||
r_captured = false;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error RemoteDebugger::_profiler_capture(const String &p_cmd, const Array &p_data, bool &r_captured) {
|
||||
r_captured = false;
|
||||
ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(p_data[0].get_type() != Variant::BOOL, ERR_INVALID_DATA);
|
||||
ERR_FAIL_COND_V(!has_profiler(p_cmd), ERR_UNAVAILABLE);
|
||||
Array opts;
|
||||
if (p_data.size() > 1) { // Optional profiler parameters.
|
||||
ERR_FAIL_COND_V(p_data[1].get_type() != Variant::ARRAY, ERR_INVALID_DATA);
|
||||
opts = p_data[1];
|
||||
}
|
||||
r_captured = true;
|
||||
profiler_enable(p_cmd, p_data[0], opts);
|
||||
return OK;
|
||||
}
|
||||
|
||||
RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
|
||||
peer = p_peer;
|
||||
max_chars_per_second = GLOBAL_GET("network/limits/debugger/max_chars_per_second");
|
||||
max_errors_per_second = GLOBAL_GET("network/limits/debugger/max_errors_per_second");
|
||||
max_warnings_per_second = GLOBAL_GET("network/limits/debugger/max_warnings_per_second");
|
||||
|
||||
// Performance Profiler
|
||||
Object *perf = Engine::get_singleton()->get_singleton_object("Performance");
|
||||
if (perf) {
|
||||
performance_profiler = Ref<PerformanceProfiler>(memnew(PerformanceProfiler(perf)));
|
||||
performance_profiler->bind("performance");
|
||||
profiler_enable("performance", true);
|
||||
}
|
||||
|
||||
// Core and profiler captures.
|
||||
Capture core_cap(this,
|
||||
[](void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
|
||||
return static_cast<RemoteDebugger *>(p_user)->_core_capture(p_cmd, p_data, r_captured);
|
||||
});
|
||||
register_message_capture("core", core_cap);
|
||||
Capture profiler_cap(this,
|
||||
[](void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured) {
|
||||
return static_cast<RemoteDebugger *>(p_user)->_profiler_capture(p_cmd, p_data, r_captured);
|
||||
});
|
||||
register_message_capture("profiler", profiler_cap);
|
||||
|
||||
// Error handlers
|
||||
phl.printfunc = _print_handler;
|
||||
phl.userdata = this;
|
||||
add_print_handler(&phl);
|
||||
|
||||
eh.errfunc = _err_handler;
|
||||
eh.userdata = this;
|
||||
add_error_handler(&eh);
|
||||
}
|
||||
|
||||
RemoteDebugger::~RemoteDebugger() {
|
||||
remove_print_handler(&phl);
|
||||
remove_error_handler(&eh);
|
||||
}
|
||||
@ -1,114 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* remote_debugger.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef REMOTE_DEBUGGER_H
|
||||
#define REMOTE_DEBUGGER_H
|
||||
|
||||
#include "core/debugger/debugger_marshalls.h"
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
#include "core/debugger/remote_debugger_peer.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/variant/array.h"
|
||||
|
||||
class RemoteDebugger : public EngineDebugger {
|
||||
public:
|
||||
enum MessageType {
|
||||
MESSAGE_TYPE_LOG,
|
||||
MESSAGE_TYPE_ERROR,
|
||||
MESSAGE_TYPE_LOG_RICH,
|
||||
};
|
||||
|
||||
private:
|
||||
typedef DebuggerMarshalls::OutputError ErrorMessage;
|
||||
|
||||
class PerformanceProfiler;
|
||||
|
||||
Ref<PerformanceProfiler> performance_profiler;
|
||||
|
||||
Ref<RemoteDebuggerPeer> peer;
|
||||
|
||||
struct OutputString {
|
||||
String message;
|
||||
MessageType type;
|
||||
};
|
||||
List<OutputString> output_strings;
|
||||
List<ErrorMessage> errors;
|
||||
|
||||
int n_messages_dropped = 0;
|
||||
int max_errors_per_second = 0;
|
||||
int max_chars_per_second = 0;
|
||||
int max_warnings_per_second = 0;
|
||||
int n_errors_dropped = 0;
|
||||
int n_warnings_dropped = 0;
|
||||
int char_count = 0;
|
||||
int err_count = 0;
|
||||
int warn_count = 0;
|
||||
int last_reset = 0;
|
||||
bool reload_all_scripts = false;
|
||||
|
||||
// Make handlers and send_message thread safe.
|
||||
Mutex mutex;
|
||||
bool flushing = false;
|
||||
Thread::ID flush_thread = 0;
|
||||
|
||||
PrintHandlerList phl;
|
||||
static void _print_handler(void *p_this, const String &p_string, bool p_error, bool p_rich);
|
||||
ErrorHandlerList eh;
|
||||
static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type);
|
||||
|
||||
ErrorMessage _create_overflow_error(const String &p_what, const String &p_descr);
|
||||
Error _put_msg(String p_message, Array p_data);
|
||||
|
||||
bool is_peer_connected() { return peer->is_peer_connected(); }
|
||||
void flush_output();
|
||||
|
||||
void _send_stack_vars(List<String> &p_names, List<Variant> &p_vals, int p_type);
|
||||
|
||||
Error _profiler_capture(const String &p_cmd, const Array &p_data, bool &r_captured);
|
||||
Error _core_capture(const String &p_cmd, const Array &p_data, bool &r_captured);
|
||||
|
||||
template <typename T>
|
||||
void _bind_profiler(const String &p_name, T *p_prof);
|
||||
Error _try_capture(const String &p_name, const Array &p_data, bool &r_captured);
|
||||
|
||||
public:
|
||||
// Overrides
|
||||
void poll_events(bool p_is_idle);
|
||||
void send_message(const String &p_message, const Array &p_args);
|
||||
void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type);
|
||||
void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false);
|
||||
|
||||
explicit RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer);
|
||||
~RemoteDebugger();
|
||||
};
|
||||
|
||||
#endif // REMOTE_DEBUGGER_H
|
||||
@ -1,242 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* remote_debugger_peer.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 "remote_debugger_peer.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
bool RemoteDebuggerPeerTCP::is_peer_connected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
bool RemoteDebuggerPeerTCP::has_message() {
|
||||
return in_queue.size() > 0;
|
||||
}
|
||||
|
||||
Array RemoteDebuggerPeerTCP::get_message() {
|
||||
MutexLock lock(mutex);
|
||||
ERR_FAIL_COND_V(!has_message(), Array());
|
||||
Array out = in_queue[0];
|
||||
in_queue.pop_front();
|
||||
return out;
|
||||
}
|
||||
|
||||
Error RemoteDebuggerPeerTCP::put_message(const Array &p_arr) {
|
||||
MutexLock lock(mutex);
|
||||
if (out_queue.size() >= max_queued_messages) {
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
out_queue.push_back(p_arr);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int RemoteDebuggerPeerTCP::get_max_message_size() const {
|
||||
return 8 << 20; // 8 MiB
|
||||
}
|
||||
|
||||
void RemoteDebuggerPeerTCP::close() {
|
||||
running = false;
|
||||
thread.wait_to_finish();
|
||||
tcp_client->disconnect_from_host();
|
||||
out_buf.clear();
|
||||
in_buf.clear();
|
||||
}
|
||||
|
||||
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp) {
|
||||
// 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).
|
||||
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;
|
||||
running = true;
|
||||
thread.start(_thread_func, this);
|
||||
} else {
|
||||
tcp_client.instantiate();
|
||||
}
|
||||
}
|
||||
|
||||
RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
|
||||
close();
|
||||
}
|
||||
|
||||
void RemoteDebuggerPeerTCP::_write_out() {
|
||||
while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_OUT) == OK) {
|
||||
uint8_t *buf = out_buf.ptrw();
|
||||
if (out_left <= 0) {
|
||||
if (out_queue.size() == 0) {
|
||||
break; // Nothing left to send
|
||||
}
|
||||
mutex.lock();
|
||||
Variant var = out_queue[0];
|
||||
out_queue.pop_front();
|
||||
mutex.unlock();
|
||||
int size = 0;
|
||||
Error err = encode_variant(var, nullptr, size);
|
||||
ERR_CONTINUE(err != OK || size > out_buf.size() - 4); // 4 bytes separator.
|
||||
encode_uint32(size, buf);
|
||||
encode_variant(var, buf + 4, size);
|
||||
out_left = size + 4;
|
||||
out_pos = 0;
|
||||
}
|
||||
int sent = 0;
|
||||
tcp_client->put_partial_data(buf + out_pos, out_left, sent);
|
||||
out_left -= sent;
|
||||
out_pos += sent;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteDebuggerPeerTCP::_read_in() {
|
||||
while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_IN) == OK) {
|
||||
uint8_t *buf = in_buf.ptrw();
|
||||
if (in_left <= 0) {
|
||||
if (in_queue.size() > max_queued_messages) {
|
||||
break; // Too many messages already in queue.
|
||||
}
|
||||
if (tcp_client->get_available_bytes() < 4) {
|
||||
break; // Need 4 more bytes.
|
||||
}
|
||||
uint32_t size = 0;
|
||||
int read = 0;
|
||||
Error err = tcp_client->get_partial_data((uint8_t *)&size, 4, read);
|
||||
ERR_CONTINUE(read != 4 || err != OK || size > (uint32_t)in_buf.size());
|
||||
in_left = size;
|
||||
in_pos = 0;
|
||||
}
|
||||
int read = 0;
|
||||
tcp_client->get_partial_data(buf + in_pos, in_left, read);
|
||||
in_left -= read;
|
||||
in_pos += read;
|
||||
if (in_left == 0) {
|
||||
Variant var;
|
||||
Error err = decode_variant(var, buf, in_pos, &read);
|
||||
ERR_CONTINUE(read != in_pos || err != OK);
|
||||
ERR_CONTINUE_MSG(var.get_type() != Variant::ARRAY, "Malformed packet received, not an Array.");
|
||||
mutex.lock();
|
||||
in_queue.push_back(var);
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) {
|
||||
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 waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
|
||||
|
||||
tcp_client->connect_to_host(ip, port);
|
||||
|
||||
for (int i = 0; i < tries; i++) {
|
||||
tcp_client->poll();
|
||||
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
|
||||
print_verbose("Remote Debugger: Connected!");
|
||||
break;
|
||||
} else {
|
||||
const int ms = waits[i];
|
||||
OS::get_singleton()->delay_usec(ms * 1000);
|
||||
print_verbose("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec.");
|
||||
}
|
||||
}
|
||||
|
||||
if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
|
||||
ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + ".");
|
||||
return FAILED;
|
||||
}
|
||||
connected = true;
|
||||
running = true;
|
||||
thread.start(_thread_func, this);
|
||||
return OK;
|
||||
}
|
||||
|
||||
void RemoteDebuggerPeerTCP::_thread_func(void *p_ud) {
|
||||
// Update in time for 144hz monitors
|
||||
const uint64_t min_tick = 6900;
|
||||
RemoteDebuggerPeerTCP *peer = static_cast<RemoteDebuggerPeerTCP *>(p_ud);
|
||||
while (peer->running && peer->is_peer_connected()) {
|
||||
uint64_t ticks_usec = OS::get_singleton()->get_ticks_usec();
|
||||
peer->_poll();
|
||||
if (!peer->is_peer_connected()) {
|
||||
break;
|
||||
}
|
||||
ticks_usec = OS::get_singleton()->get_ticks_usec() - ticks_usec;
|
||||
if (ticks_usec < min_tick) {
|
||||
OS::get_singleton()->delay_usec(min_tick - ticks_usec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteDebuggerPeerTCP::poll() {
|
||||
// Nothing to do, polling is done in thread.
|
||||
}
|
||||
|
||||
void RemoteDebuggerPeerTCP::_poll() {
|
||||
tcp_client->poll();
|
||||
if (connected) {
|
||||
_write_out();
|
||||
_read_in();
|
||||
connected = tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
|
||||
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
|
||||
|
||||
String debug_host = p_uri.replace("tcp://", "");
|
||||
uint16_t debug_port = 6007;
|
||||
|
||||
if (debug_host.contains(":")) {
|
||||
int sep_pos = debug_host.rfind(":");
|
||||
debug_port = debug_host.substr(sep_pos + 1).to_int();
|
||||
debug_host = debug_host.substr(0, sep_pos);
|
||||
}
|
||||
|
||||
RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP);
|
||||
Error err = peer->connect_to_host(debug_host, debug_port);
|
||||
if (err != OK) {
|
||||
memdelete(peer);
|
||||
return nullptr;
|
||||
}
|
||||
return peer;
|
||||
}
|
||||
|
||||
RemoteDebuggerPeer::RemoteDebuggerPeer() {
|
||||
max_queued_messages = (int)GLOBAL_GET("network/limits/debugger/max_queued_messages");
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* remote_debugger_peer.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef REMOTE_DEBUGGER_PEER_H
|
||||
#define REMOTE_DEBUGGER_PEER_H
|
||||
|
||||
#include "core/io/stream_peer_tcp.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/os/mutex.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "core/string/ustring.h"
|
||||
|
||||
class RemoteDebuggerPeer : public RefCounted {
|
||||
protected:
|
||||
int max_queued_messages = 4096;
|
||||
|
||||
public:
|
||||
virtual bool is_peer_connected() = 0;
|
||||
virtual int get_max_message_size() const = 0;
|
||||
virtual bool has_message() = 0;
|
||||
virtual Error put_message(const Array &p_arr) = 0;
|
||||
virtual Array get_message() = 0;
|
||||
virtual void close() = 0;
|
||||
virtual void poll() = 0;
|
||||
virtual bool can_block() const { return true; } // If blocking io is allowed on main thread (debug).
|
||||
|
||||
RemoteDebuggerPeer();
|
||||
};
|
||||
|
||||
class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
|
||||
private:
|
||||
Ref<StreamPeerTCP> tcp_client;
|
||||
Mutex mutex;
|
||||
Thread thread;
|
||||
List<Array> in_queue;
|
||||
List<Array> out_queue;
|
||||
int out_left = 0;
|
||||
int out_pos = 0;
|
||||
Vector<uint8_t> out_buf;
|
||||
int in_left = 0;
|
||||
int in_pos = 0;
|
||||
Vector<uint8_t> in_buf;
|
||||
bool connected = false;
|
||||
bool running = false;
|
||||
|
||||
static void _thread_func(void *p_ud);
|
||||
|
||||
void _poll();
|
||||
void _write_out();
|
||||
void _read_in();
|
||||
|
||||
public:
|
||||
static RemoteDebuggerPeer *create(const String &p_uri);
|
||||
|
||||
Error connect_to_host(const String &p_host, uint16_t p_port);
|
||||
|
||||
bool is_peer_connected() override;
|
||||
int get_max_message_size() const override;
|
||||
bool has_message() override;
|
||||
Error put_message(const Array &p_arr) override;
|
||||
Array get_message() override;
|
||||
void poll() override;
|
||||
void close() override;
|
||||
|
||||
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
|
||||
~RemoteDebuggerPeerTCP();
|
||||
};
|
||||
|
||||
#endif // REMOTE_DEBUGGER_PEER_H
|
||||
@ -1,112 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* script_debugger.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 "script_debugger.h"
|
||||
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
|
||||
void ScriptDebugger::set_lines_left(int p_left) {
|
||||
lines_left = p_left;
|
||||
}
|
||||
|
||||
int ScriptDebugger::get_lines_left() const {
|
||||
return lines_left;
|
||||
}
|
||||
|
||||
void ScriptDebugger::set_depth(int p_depth) {
|
||||
depth = p_depth;
|
||||
}
|
||||
|
||||
int ScriptDebugger::get_depth() const {
|
||||
return depth;
|
||||
}
|
||||
|
||||
void ScriptDebugger::insert_breakpoint(int p_line, const StringName &p_source) {
|
||||
if (!breakpoints.has(p_line)) {
|
||||
breakpoints[p_line] = HashSet<StringName>();
|
||||
}
|
||||
breakpoints[p_line].insert(p_source);
|
||||
}
|
||||
|
||||
void ScriptDebugger::remove_breakpoint(int p_line, const StringName &p_source) {
|
||||
if (!breakpoints.has(p_line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
breakpoints[p_line].erase(p_source);
|
||||
if (breakpoints[p_line].size() == 0) {
|
||||
breakpoints.erase(p_line);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptDebugger::is_breakpoint(int p_line, const StringName &p_source) const {
|
||||
if (!breakpoints.has(p_line)) {
|
||||
return false;
|
||||
}
|
||||
return breakpoints[p_line].has(p_source);
|
||||
}
|
||||
|
||||
String ScriptDebugger::breakpoint_find_source(const String &p_source) const {
|
||||
return p_source;
|
||||
}
|
||||
|
||||
void ScriptDebugger::clear_breakpoints() {
|
||||
breakpoints.clear();
|
||||
}
|
||||
|
||||
void ScriptDebugger::set_skip_breakpoints(bool p_skip_breakpoints) {
|
||||
skip_breakpoints = p_skip_breakpoints;
|
||||
}
|
||||
|
||||
bool ScriptDebugger::is_skipping_breakpoints() {
|
||||
return skip_breakpoints;
|
||||
}
|
||||
|
||||
void ScriptDebugger::debug(ScriptLanguage *p_lang, bool p_can_continue, bool p_is_error_breakpoint) {
|
||||
ScriptLanguage *prev = break_lang;
|
||||
break_lang = p_lang;
|
||||
EngineDebugger::get_singleton()->debug(p_can_continue, p_is_error_breakpoint);
|
||||
break_lang = prev;
|
||||
}
|
||||
|
||||
void ScriptDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info) {
|
||||
// Store stack info, this is ugly, but allows us to separate EngineDebugger and ScriptDebugger. There might be a better way.
|
||||
error_stack_info.append_array(p_stack_info);
|
||||
EngineDebugger::get_singleton()->send_error(p_func, p_file, p_line, p_err, p_descr, p_editor_notify, p_type);
|
||||
error_stack_info.clear();
|
||||
}
|
||||
|
||||
Vector<ScriptLanguage::StackInfo> ScriptDebugger::get_error_stack_info() const {
|
||||
return error_stack_info;
|
||||
}
|
||||
|
||||
ScriptLanguage *ScriptDebugger::get_break_language() const {
|
||||
return break_lang;
|
||||
}
|
||||
@ -1,78 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* script_debugger.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SCRIPT_DEBUGGER_H
|
||||
#define SCRIPT_DEBUGGER_H
|
||||
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/templates/hash_set.h"
|
||||
#include "core/templates/rb_map.h"
|
||||
#include "core/templates/vector.h"
|
||||
|
||||
class ScriptDebugger {
|
||||
typedef ScriptLanguage::StackInfo StackInfo;
|
||||
|
||||
int lines_left = -1;
|
||||
int depth = -1;
|
||||
bool skip_breakpoints = false;
|
||||
|
||||
HashMap<int, HashSet<StringName>> breakpoints;
|
||||
|
||||
ScriptLanguage *break_lang = nullptr;
|
||||
Vector<StackInfo> error_stack_info;
|
||||
|
||||
public:
|
||||
void set_lines_left(int p_left);
|
||||
int get_lines_left() const;
|
||||
|
||||
void set_depth(int p_depth);
|
||||
int get_depth() const;
|
||||
|
||||
String breakpoint_find_source(const String &p_source) const;
|
||||
void set_break_language(ScriptLanguage *p_lang) { break_lang = p_lang; }
|
||||
ScriptLanguage *get_break_language() { return break_lang; }
|
||||
void set_skip_breakpoints(bool p_skip_breakpoints);
|
||||
bool is_skipping_breakpoints();
|
||||
void insert_breakpoint(int p_line, const StringName &p_source);
|
||||
void remove_breakpoint(int p_line, const StringName &p_source);
|
||||
bool is_breakpoint(int p_line, const StringName &p_source) const;
|
||||
void clear_breakpoints();
|
||||
const HashMap<int, HashSet<StringName>> &get_breakpoints() const { return breakpoints; }
|
||||
|
||||
void debug(ScriptLanguage *p_lang, bool p_can_continue = true, bool p_is_error_breakpoint = false);
|
||||
ScriptLanguage *get_break_language() const;
|
||||
|
||||
void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info);
|
||||
Vector<StackInfo> get_error_stack_info() const;
|
||||
ScriptDebugger() {}
|
||||
};
|
||||
|
||||
#endif // SCRIPT_DEBUGGER_H
|
||||
247
core/dictionary.cpp
Normal file
247
core/dictionary.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
/*************************************************************************/
|
||||
/* dictionary.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "dictionary.h"
|
||||
#include "io/json.h"
|
||||
#include "safe_refcount.h"
|
||||
#include "variant.h"
|
||||
|
||||
struct _DictionaryVariantHash {
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
|
||||
};
|
||||
|
||||
struct DictionaryPrivate {
|
||||
|
||||
SafeRefCount refcount;
|
||||
HashMap<Variant, Variant, _DictionaryVariantHash> variant_map;
|
||||
bool shared;
|
||||
};
|
||||
|
||||
void Dictionary::get_key_list(List<Variant> *p_keys) const {
|
||||
|
||||
_p->variant_map.get_key_list(p_keys);
|
||||
}
|
||||
|
||||
void Dictionary::_copy_on_write() const {
|
||||
|
||||
//make a copy of what we have
|
||||
if (_p->shared)
|
||||
return;
|
||||
|
||||
DictionaryPrivate *p = memnew(DictionaryPrivate);
|
||||
p->shared = _p->shared;
|
||||
p->variant_map = _p->variant_map;
|
||||
p->refcount.init();
|
||||
_unref();
|
||||
_p = p;
|
||||
}
|
||||
|
||||
Variant &Dictionary::operator[](const Variant &p_key) {
|
||||
|
||||
_copy_on_write();
|
||||
|
||||
return _p->variant_map[p_key];
|
||||
}
|
||||
|
||||
const Variant &Dictionary::operator[](const Variant &p_key) const {
|
||||
|
||||
return _p->variant_map[p_key];
|
||||
}
|
||||
const Variant *Dictionary::getptr(const Variant &p_key) const {
|
||||
|
||||
return _p->variant_map.getptr(p_key);
|
||||
}
|
||||
Variant *Dictionary::getptr(const Variant &p_key) {
|
||||
|
||||
_copy_on_write();
|
||||
return _p->variant_map.getptr(p_key);
|
||||
}
|
||||
|
||||
Variant Dictionary::get_valid(const Variant &p_key) const {
|
||||
|
||||
const Variant *v = getptr(p_key);
|
||||
if (!v)
|
||||
return Variant();
|
||||
return *v;
|
||||
}
|
||||
|
||||
int Dictionary::size() const {
|
||||
|
||||
return _p->variant_map.size();
|
||||
}
|
||||
bool Dictionary::empty() const {
|
||||
|
||||
return !_p->variant_map.size();
|
||||
}
|
||||
|
||||
bool Dictionary::has(const Variant &p_key) const {
|
||||
|
||||
return _p->variant_map.has(p_key);
|
||||
}
|
||||
|
||||
bool Dictionary::has_all(const Array &p_keys) const {
|
||||
for (int i = 0; i < p_keys.size(); i++) {
|
||||
if (!has(p_keys[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Dictionary::erase(const Variant &p_key) {
|
||||
_copy_on_write();
|
||||
_p->variant_map.erase(p_key);
|
||||
}
|
||||
|
||||
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
|
||||
|
||||
return _p == p_dictionary._p;
|
||||
}
|
||||
|
||||
void Dictionary::_ref(const Dictionary &p_from) const {
|
||||
|
||||
//make a copy first (thread safe)
|
||||
if (!p_from._p->refcount.ref())
|
||||
return; // couldn't copy
|
||||
|
||||
//if this is the same, unreference the other one
|
||||
if (p_from._p == _p) {
|
||||
_p->refcount.unref();
|
||||
return;
|
||||
}
|
||||
if (_p)
|
||||
_unref();
|
||||
_p = p_from._p;
|
||||
}
|
||||
|
||||
void Dictionary::clear() {
|
||||
|
||||
_copy_on_write();
|
||||
_p->variant_map.clear();
|
||||
}
|
||||
|
||||
bool Dictionary::is_shared() const {
|
||||
|
||||
return _p->shared;
|
||||
}
|
||||
|
||||
void Dictionary::_unref() const {
|
||||
|
||||
ERR_FAIL_COND(!_p);
|
||||
if (_p->refcount.unref()) {
|
||||
memdelete(_p);
|
||||
}
|
||||
_p = NULL;
|
||||
}
|
||||
uint32_t Dictionary::hash() const {
|
||||
|
||||
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
|
||||
|
||||
List<Variant> keys;
|
||||
get_key_list(&keys);
|
||||
|
||||
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
||||
|
||||
h = hash_djb2_one_32(E->get().hash(), h);
|
||||
h = hash_djb2_one_32(operator[](E->get()).hash(), h);
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
Array Dictionary::keys() const {
|
||||
|
||||
Array karr;
|
||||
karr.resize(size());
|
||||
const Variant *K = NULL;
|
||||
int idx = 0;
|
||||
while ((K = next(K))) {
|
||||
karr[idx++] = (*K);
|
||||
}
|
||||
return karr;
|
||||
}
|
||||
|
||||
Array Dictionary::values() const {
|
||||
|
||||
Array varr;
|
||||
varr.resize(size());
|
||||
const Variant *key = NULL;
|
||||
int i = 0;
|
||||
while ((key = next(key))) {
|
||||
varr[i++] = _p->variant_map[*key];
|
||||
}
|
||||
return varr;
|
||||
}
|
||||
|
||||
const Variant *Dictionary::next(const Variant *p_key) const {
|
||||
|
||||
return _p->variant_map.next(p_key);
|
||||
}
|
||||
|
||||
Error Dictionary::parse_json(const String &p_json) {
|
||||
|
||||
String errstr;
|
||||
int errline = 0;
|
||||
if (p_json != "") {
|
||||
Error err = JSON::parse(p_json, *this, errstr, errline);
|
||||
if (err != OK) {
|
||||
ERR_EXPLAIN("Error parsing JSON: " + errstr + " at line: " + itos(errline));
|
||||
ERR_FAIL_COND_V(err != OK, err);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
String Dictionary::to_json() const {
|
||||
|
||||
return JSON::print(*this);
|
||||
}
|
||||
|
||||
void Dictionary::operator=(const Dictionary &p_dictionary) {
|
||||
|
||||
_ref(p_dictionary);
|
||||
}
|
||||
|
||||
Dictionary::Dictionary(const Dictionary &p_from) {
|
||||
_p = NULL;
|
||||
_ref(p_from);
|
||||
}
|
||||
|
||||
Dictionary::Dictionary(bool p_shared) {
|
||||
|
||||
_p = memnew(DictionaryPrivate);
|
||||
_p->refcount.init();
|
||||
_p->shared = p_shared;
|
||||
}
|
||||
Dictionary::~Dictionary() {
|
||||
|
||||
_unref();
|
||||
}
|
||||
88
core/dictionary.h
Normal file
88
core/dictionary.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*************************************************************************/
|
||||
/* dictionary.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 DICTIONARY_H
|
||||
#define DICTIONARY_H
|
||||
|
||||
#include "array.h"
|
||||
#include "list.h"
|
||||
#include "ustring.h"
|
||||
class Variant;
|
||||
|
||||
struct DictionaryPrivate;
|
||||
|
||||
class Dictionary {
|
||||
|
||||
mutable DictionaryPrivate *_p;
|
||||
|
||||
void _copy_on_write() const;
|
||||
void _ref(const Dictionary &p_from) const;
|
||||
void _unref() const;
|
||||
|
||||
public:
|
||||
void get_key_list(List<Variant> *p_keys) const;
|
||||
|
||||
Variant &operator[](const Variant &p_key);
|
||||
const Variant &operator[](const Variant &p_key) const;
|
||||
|
||||
const Variant *getptr(const Variant &p_key) const;
|
||||
Variant *getptr(const Variant &p_key);
|
||||
|
||||
Variant get_valid(const Variant &p_key) const;
|
||||
|
||||
int size() const;
|
||||
bool empty() const;
|
||||
void clear();
|
||||
|
||||
Error parse_json(const String &p_json);
|
||||
String to_json() const;
|
||||
|
||||
bool is_shared() const;
|
||||
|
||||
bool has(const Variant &p_key) const;
|
||||
bool has_all(const Array &p_keys) const;
|
||||
|
||||
void erase(const Variant &p_key);
|
||||
|
||||
bool operator==(const Dictionary &p_dictionary) const;
|
||||
|
||||
uint32_t hash() const;
|
||||
void operator=(const Dictionary &p_dictionary);
|
||||
|
||||
const Variant *next(const Variant *p_key = NULL) const;
|
||||
|
||||
Array keys() const;
|
||||
Array values() const;
|
||||
|
||||
Dictionary(const Dictionary &p_from);
|
||||
Dictionary(bool p_shared = false);
|
||||
~Dictionary();
|
||||
};
|
||||
|
||||
#endif // DICTIONARY_H
|
||||
@ -1,173 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* doc_data.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 "doc_data.h"
|
||||
|
||||
String DocData::get_default_value_string(const Variant &p_value) {
|
||||
if (p_value.get_type() == Variant::ARRAY) {
|
||||
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
|
||||
} else {
|
||||
return p_value.get_construct_string().replace("\n", " ");
|
||||
}
|
||||
}
|
||||
|
||||
void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo) {
|
||||
if (p_retinfo.type == Variant::INT && p_retinfo.hint == PROPERTY_HINT_INT_IS_POINTER) {
|
||||
p_method.return_type = p_retinfo.hint_string;
|
||||
if (p_method.return_type.is_empty()) {
|
||||
p_method.return_type = "void*";
|
||||
} else {
|
||||
p_method.return_type += "*";
|
||||
}
|
||||
} else if (p_retinfo.type == Variant::INT && p_retinfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
|
||||
p_method.return_enum = p_retinfo.class_name;
|
||||
if (p_method.return_enum.begins_with("_")) { //proxy class
|
||||
p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length());
|
||||
}
|
||||
p_method.return_type = "int";
|
||||
} else if (p_retinfo.class_name != StringName()) {
|
||||
p_method.return_type = p_retinfo.class_name;
|
||||
} else if (p_retinfo.type == Variant::ARRAY && p_retinfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
||||
p_method.return_type = p_retinfo.hint_string + "[]";
|
||||
} else if (p_retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
p_method.return_type = p_retinfo.hint_string;
|
||||
} else if (p_retinfo.type == Variant::NIL && p_retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
|
||||
p_method.return_type = "Variant";
|
||||
} else if (p_retinfo.type == Variant::NIL) {
|
||||
p_method.return_type = "void";
|
||||
} else {
|
||||
p_method.return_type = Variant::get_type_name(p_retinfo.type);
|
||||
}
|
||||
}
|
||||
|
||||
void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo) {
|
||||
p_argument.name = p_arginfo.name;
|
||||
|
||||
if (p_arginfo.type == Variant::INT && p_arginfo.hint == PROPERTY_HINT_INT_IS_POINTER) {
|
||||
p_argument.type = p_arginfo.hint_string;
|
||||
if (p_argument.type.is_empty()) {
|
||||
p_argument.type = "void*";
|
||||
} else {
|
||||
p_argument.type += "*";
|
||||
}
|
||||
} else if (p_arginfo.type == Variant::INT && p_arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
|
||||
p_argument.enumeration = p_arginfo.class_name;
|
||||
if (p_argument.enumeration.begins_with("_")) { //proxy class
|
||||
p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length());
|
||||
}
|
||||
p_argument.type = "int";
|
||||
} else if (p_arginfo.class_name != StringName()) {
|
||||
p_argument.type = p_arginfo.class_name;
|
||||
} else if (p_arginfo.type == Variant::ARRAY && p_arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
||||
p_argument.type = p_arginfo.hint_string + "[]";
|
||||
} else if (p_arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
p_argument.type = p_arginfo.hint_string;
|
||||
} else if (p_arginfo.type == Variant::NIL) {
|
||||
// Parameters cannot be void, so PROPERTY_USAGE_NIL_IS_VARIANT is not necessary
|
||||
p_argument.type = "Variant";
|
||||
} else {
|
||||
p_argument.type = Variant::get_type_name(p_arginfo.type);
|
||||
}
|
||||
}
|
||||
|
||||
void DocData::property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo) {
|
||||
p_property.name = p_memberinfo.propinfo.name;
|
||||
p_property.description = p_memberinfo.doc_string;
|
||||
|
||||
if (p_memberinfo.propinfo.type == Variant::OBJECT) {
|
||||
p_property.type = p_memberinfo.propinfo.class_name;
|
||||
} else if (p_memberinfo.propinfo.type == Variant::NIL && p_memberinfo.propinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
|
||||
p_property.type = "Variant";
|
||||
} else {
|
||||
p_property.type = Variant::get_type_name(p_memberinfo.propinfo.type);
|
||||
}
|
||||
|
||||
p_property.setter = p_memberinfo.setter;
|
||||
p_property.getter = p_memberinfo.getter;
|
||||
|
||||
if (p_memberinfo.has_default_value && p_memberinfo.default_value.get_type() != Variant::OBJECT) {
|
||||
p_property.default_value = get_default_value_string(p_memberinfo.default_value);
|
||||
}
|
||||
|
||||
p_property.overridden = false;
|
||||
}
|
||||
|
||||
void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const MethodInfo &p_methodinfo, const String &p_desc) {
|
||||
p_method.name = p_methodinfo.name;
|
||||
p_method.description = p_desc;
|
||||
|
||||
if (p_methodinfo.flags & METHOD_FLAG_VIRTUAL) {
|
||||
p_method.qualifiers = "virtual";
|
||||
}
|
||||
|
||||
if (p_methodinfo.flags & METHOD_FLAG_CONST) {
|
||||
if (!p_method.qualifiers.is_empty()) {
|
||||
p_method.qualifiers += " ";
|
||||
}
|
||||
p_method.qualifiers += "const";
|
||||
}
|
||||
|
||||
if (p_methodinfo.flags & METHOD_FLAG_VARARG) {
|
||||
if (!p_method.qualifiers.is_empty()) {
|
||||
p_method.qualifiers += " ";
|
||||
}
|
||||
p_method.qualifiers += "vararg";
|
||||
}
|
||||
|
||||
if (p_methodinfo.flags & METHOD_FLAG_STATIC) {
|
||||
if (!p_method.qualifiers.is_empty()) {
|
||||
p_method.qualifiers += " ";
|
||||
}
|
||||
p_method.qualifiers += "static";
|
||||
}
|
||||
|
||||
return_doc_from_retinfo(p_method, p_methodinfo.return_val);
|
||||
|
||||
for (int i = 0; i < p_methodinfo.arguments.size(); i++) {
|
||||
DocData::ArgumentDoc argument;
|
||||
argument_doc_from_arginfo(argument, p_methodinfo.arguments[i]);
|
||||
int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size());
|
||||
if (default_arg_index >= 0) {
|
||||
Variant default_arg = p_methodinfo.default_arguments[default_arg_index];
|
||||
argument.default_value = get_default_value_string(default_arg);
|
||||
}
|
||||
p_method.arguments.push_back(argument);
|
||||
}
|
||||
}
|
||||
|
||||
void DocData::constant_doc_from_variant(DocData::ConstantDoc &p_const, const StringName &p_name, const Variant &p_value, const String &p_desc) {
|
||||
p_const.name = p_name;
|
||||
p_const.value = p_value;
|
||||
p_const.description = p_desc;
|
||||
}
|
||||
|
||||
void DocData::signal_doc_from_methodinfo(DocData::MethodDoc &p_signal, const MethodInfo &p_methodinfo, const String &p_desc) {
|
||||
return method_doc_from_methodinfo(p_signal, p_methodinfo, p_desc);
|
||||
}
|
||||
529
core/doc_data.h
529
core/doc_data.h
@ -1,529 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* doc_data.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef DOC_DATA_H
|
||||
#define DOC_DATA_H
|
||||
|
||||
#include "core/io/xml_parser.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
struct ScriptMemberInfo {
|
||||
PropertyInfo propinfo;
|
||||
String doc_string;
|
||||
StringName setter;
|
||||
StringName getter;
|
||||
|
||||
bool has_default_value = false;
|
||||
Variant default_value;
|
||||
};
|
||||
|
||||
class DocData {
|
||||
public:
|
||||
struct ArgumentDoc {
|
||||
String name;
|
||||
String type;
|
||||
String enumeration;
|
||||
String default_value;
|
||||
bool operator<(const ArgumentDoc &p_arg) const {
|
||||
if (name == p_arg.name) {
|
||||
return type < p_arg.type;
|
||||
}
|
||||
return name < p_arg.name;
|
||||
}
|
||||
static ArgumentDoc from_dict(const Dictionary &p_dict) {
|
||||
ArgumentDoc doc;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
doc.name = p_dict["name"];
|
||||
}
|
||||
|
||||
if (p_dict.has("type")) {
|
||||
doc.type = p_dict["type"];
|
||||
}
|
||||
|
||||
if (p_dict.has("enumeration")) {
|
||||
doc.enumeration = p_dict["enumeration"];
|
||||
}
|
||||
|
||||
if (p_dict.has("default_value")) {
|
||||
doc.default_value = p_dict["default_value"];
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
struct MethodDoc {
|
||||
String name;
|
||||
String return_type;
|
||||
String return_enum;
|
||||
String qualifiers;
|
||||
String description;
|
||||
bool is_deprecated = false;
|
||||
bool is_experimental = false;
|
||||
Vector<ArgumentDoc> arguments;
|
||||
Vector<int> errors_returned;
|
||||
bool operator<(const MethodDoc &p_method) const {
|
||||
if (name == p_method.name) {
|
||||
// Must be an operator or a constructor since there is no other overloading
|
||||
if (name.left(8) == "operator") {
|
||||
if (arguments.size() == p_method.arguments.size()) {
|
||||
if (arguments.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
return arguments[0].type < p_method.arguments[0].type;
|
||||
}
|
||||
return arguments.size() < p_method.arguments.size();
|
||||
} else {
|
||||
// Must be a constructor
|
||||
// We want this arbitrary order for a class "Foo":
|
||||
// - 1. Default constructor: Foo()
|
||||
// - 2. Copy constructor: Foo(Foo)
|
||||
// - 3+. Other constructors Foo(Bar, ...) based on first argument's name
|
||||
if (arguments.size() == 0 || p_method.arguments.size() == 0) { // 1.
|
||||
return arguments.size() < p_method.arguments.size();
|
||||
}
|
||||
if (arguments[0].type == return_type || p_method.arguments[0].type == p_method.return_type) { // 2.
|
||||
return (arguments[0].type == return_type) || (p_method.arguments[0].type != p_method.return_type);
|
||||
}
|
||||
return arguments[0] < p_method.arguments[0];
|
||||
}
|
||||
}
|
||||
return name < p_method.name;
|
||||
}
|
||||
static MethodDoc from_dict(const Dictionary &p_dict) {
|
||||
MethodDoc doc;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
doc.name = p_dict["name"];
|
||||
}
|
||||
|
||||
if (p_dict.has("return_type")) {
|
||||
doc.return_type = p_dict["return_type"];
|
||||
}
|
||||
|
||||
if (p_dict.has("return_enum")) {
|
||||
doc.return_enum = p_dict["return_enum"];
|
||||
}
|
||||
|
||||
if (p_dict.has("qualifiers")) {
|
||||
doc.qualifiers = p_dict["qualifiers"];
|
||||
}
|
||||
|
||||
if (p_dict.has("description")) {
|
||||
doc.description = p_dict["description"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_deprecated")) {
|
||||
doc.is_deprecated = p_dict["is_deprecated"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_experimental")) {
|
||||
doc.is_experimental = p_dict["is_experimental"];
|
||||
}
|
||||
|
||||
Array arguments;
|
||||
if (p_dict.has("arguments")) {
|
||||
arguments = p_dict["arguments"];
|
||||
}
|
||||
for (int i = 0; i < arguments.size(); i++) {
|
||||
doc.arguments.push_back(ArgumentDoc::from_dict(arguments[i]));
|
||||
}
|
||||
|
||||
Array errors_returned;
|
||||
if (p_dict.has("errors_returned")) {
|
||||
errors_returned = p_dict["errors_returned"];
|
||||
}
|
||||
for (int i = 0; i < errors_returned.size(); i++) {
|
||||
doc.errors_returned.push_back(errors_returned[i]);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
struct ConstantDoc {
|
||||
String name;
|
||||
String value;
|
||||
bool is_value_valid = false;
|
||||
String enumeration;
|
||||
bool is_bitfield = false;
|
||||
String description;
|
||||
bool is_deprecated = false;
|
||||
bool is_experimental = false;
|
||||
bool operator<(const ConstantDoc &p_const) const {
|
||||
return name < p_const.name;
|
||||
}
|
||||
static ConstantDoc from_dict(const Dictionary &p_dict) {
|
||||
ConstantDoc doc;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
doc.name = p_dict["name"];
|
||||
}
|
||||
|
||||
if (p_dict.has("value")) {
|
||||
doc.value = p_dict["value"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_value_valid")) {
|
||||
doc.is_value_valid = p_dict["is_value_valid"];
|
||||
}
|
||||
|
||||
if (p_dict.has("enumeration")) {
|
||||
doc.enumeration = p_dict["enumeration"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_bitfield")) {
|
||||
doc.is_bitfield = p_dict["is_bitfield"];
|
||||
}
|
||||
|
||||
if (p_dict.has("description")) {
|
||||
doc.description = p_dict["description"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_deprecated")) {
|
||||
doc.is_deprecated = p_dict["is_deprecated"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_experimental")) {
|
||||
doc.is_experimental = p_dict["is_experimental"];
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
struct EnumDoc {
|
||||
String name = "@unnamed_enum";
|
||||
bool is_bitfield = false;
|
||||
String description;
|
||||
Vector<DocData::ConstantDoc> values;
|
||||
static EnumDoc from_dict(const Dictionary &p_dict) {
|
||||
EnumDoc doc;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
doc.name = p_dict["name"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_bitfield")) {
|
||||
doc.is_bitfield = p_dict["is_bitfield"];
|
||||
}
|
||||
|
||||
if (p_dict.has("description")) {
|
||||
doc.description = p_dict["description"];
|
||||
}
|
||||
|
||||
Array values;
|
||||
if (p_dict.has("values")) {
|
||||
values = p_dict["values"];
|
||||
}
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
doc.values.push_back(ConstantDoc::from_dict(values[i]));
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
struct PropertyDoc {
|
||||
String name;
|
||||
String type;
|
||||
String enumeration;
|
||||
String description;
|
||||
String setter, getter;
|
||||
String default_value;
|
||||
bool overridden = false;
|
||||
String overrides;
|
||||
bool is_deprecated = false;
|
||||
bool is_experimental = false;
|
||||
bool operator<(const PropertyDoc &p_prop) const {
|
||||
return name < p_prop.name;
|
||||
}
|
||||
static PropertyDoc from_dict(const Dictionary &p_dict) {
|
||||
PropertyDoc doc;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
doc.name = p_dict["name"];
|
||||
}
|
||||
|
||||
if (p_dict.has("type")) {
|
||||
doc.type = p_dict["type"];
|
||||
}
|
||||
|
||||
if (p_dict.has("enumeration")) {
|
||||
doc.enumeration = p_dict["enumeration"];
|
||||
}
|
||||
|
||||
if (p_dict.has("description")) {
|
||||
doc.description = p_dict["description"];
|
||||
}
|
||||
|
||||
if (p_dict.has("setter")) {
|
||||
doc.setter = p_dict["setter"];
|
||||
}
|
||||
|
||||
if (p_dict.has("getter")) {
|
||||
doc.getter = p_dict["getter"];
|
||||
}
|
||||
|
||||
if (p_dict.has("default_value")) {
|
||||
doc.default_value = p_dict["default_value"];
|
||||
}
|
||||
|
||||
if (p_dict.has("overridden")) {
|
||||
doc.overridden = p_dict["overridden"];
|
||||
}
|
||||
|
||||
if (p_dict.has("overrides")) {
|
||||
doc.overrides = p_dict["overrides"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_deprecated")) {
|
||||
doc.is_deprecated = p_dict["is_deprecated"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_experimental")) {
|
||||
doc.is_experimental = p_dict["is_experimental"];
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
struct ThemeItemDoc {
|
||||
String name;
|
||||
String type;
|
||||
String data_type;
|
||||
String description;
|
||||
String default_value;
|
||||
bool operator<(const ThemeItemDoc &p_theme_item) const {
|
||||
// First sort by the data type, then by name.
|
||||
if (data_type == p_theme_item.data_type) {
|
||||
return name < p_theme_item.name;
|
||||
}
|
||||
return data_type < p_theme_item.data_type;
|
||||
}
|
||||
static ThemeItemDoc from_dict(const Dictionary &p_dict) {
|
||||
ThemeItemDoc doc;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
doc.name = p_dict["name"];
|
||||
}
|
||||
|
||||
if (p_dict.has("type")) {
|
||||
doc.type = p_dict["type"];
|
||||
}
|
||||
|
||||
if (p_dict.has("data_type")) {
|
||||
doc.data_type = p_dict["data_type"];
|
||||
}
|
||||
|
||||
if (p_dict.has("description")) {
|
||||
doc.description = p_dict["description"];
|
||||
}
|
||||
|
||||
if (p_dict.has("default_value")) {
|
||||
doc.default_value = p_dict["default_value"];
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
struct TutorialDoc {
|
||||
String link;
|
||||
String title;
|
||||
static TutorialDoc from_dict(const Dictionary &p_dict) {
|
||||
TutorialDoc doc;
|
||||
|
||||
if (p_dict.has("link")) {
|
||||
doc.link = p_dict["link"];
|
||||
}
|
||||
|
||||
if (p_dict.has("title")) {
|
||||
doc.title = p_dict["title"];
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
struct ClassDoc {
|
||||
String name;
|
||||
String inherits;
|
||||
String brief_description;
|
||||
String description;
|
||||
Vector<TutorialDoc> tutorials;
|
||||
Vector<MethodDoc> constructors;
|
||||
Vector<MethodDoc> methods;
|
||||
Vector<MethodDoc> operators;
|
||||
Vector<MethodDoc> signals;
|
||||
Vector<ConstantDoc> constants;
|
||||
HashMap<String, String> enums;
|
||||
Vector<PropertyDoc> properties;
|
||||
Vector<MethodDoc> annotations;
|
||||
Vector<ThemeItemDoc> theme_properties;
|
||||
bool is_deprecated = false;
|
||||
bool is_experimental = false;
|
||||
bool is_script_doc = false;
|
||||
String script_path;
|
||||
bool operator<(const ClassDoc &p_class) const {
|
||||
return name < p_class.name;
|
||||
}
|
||||
static ClassDoc from_dict(const Dictionary &p_dict) {
|
||||
ClassDoc doc;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
doc.name = p_dict["name"];
|
||||
}
|
||||
|
||||
if (p_dict.has("inherits")) {
|
||||
doc.inherits = p_dict["inherits"];
|
||||
}
|
||||
|
||||
if (p_dict.has("brief_description")) {
|
||||
doc.brief_description = p_dict["brief_description"];
|
||||
}
|
||||
|
||||
if (p_dict.has("description")) {
|
||||
doc.description = p_dict["description"];
|
||||
}
|
||||
|
||||
Array tutorials;
|
||||
if (p_dict.has("tutorials")) {
|
||||
tutorials = p_dict["tutorials"];
|
||||
}
|
||||
for (int i = 0; i < tutorials.size(); i++) {
|
||||
doc.tutorials.push_back(TutorialDoc::from_dict(tutorials[i]));
|
||||
}
|
||||
|
||||
Array constructors;
|
||||
if (p_dict.has("constructors")) {
|
||||
constructors = p_dict["constructors"];
|
||||
}
|
||||
for (int i = 0; i < constructors.size(); i++) {
|
||||
doc.constructors.push_back(MethodDoc::from_dict(constructors[i]));
|
||||
}
|
||||
|
||||
Array methods;
|
||||
if (p_dict.has("methods")) {
|
||||
methods = p_dict["methods"];
|
||||
}
|
||||
for (int i = 0; i < methods.size(); i++) {
|
||||
doc.methods.push_back(MethodDoc::from_dict(methods[i]));
|
||||
}
|
||||
|
||||
Array operators;
|
||||
if (p_dict.has("operators")) {
|
||||
operators = p_dict["operators"];
|
||||
}
|
||||
for (int i = 0; i < operators.size(); i++) {
|
||||
doc.operators.push_back(MethodDoc::from_dict(operators[i]));
|
||||
}
|
||||
|
||||
Array signals;
|
||||
if (p_dict.has("signals")) {
|
||||
signals = p_dict["signals"];
|
||||
}
|
||||
for (int i = 0; i < signals.size(); i++) {
|
||||
doc.signals.push_back(MethodDoc::from_dict(signals[i]));
|
||||
}
|
||||
|
||||
Array constants;
|
||||
if (p_dict.has("constants")) {
|
||||
constants = p_dict["constants"];
|
||||
}
|
||||
for (int i = 0; i < constants.size(); i++) {
|
||||
doc.constants.push_back(ConstantDoc::from_dict(constants[i]));
|
||||
}
|
||||
|
||||
Dictionary enums;
|
||||
if (p_dict.has("enums")) {
|
||||
enums = p_dict["enums"];
|
||||
}
|
||||
for (int i = 0; i < enums.size(); i++) {
|
||||
doc.enums[enums.get_key_at_index(i)] = enums.get_value_at_index(i);
|
||||
}
|
||||
|
||||
Array properties;
|
||||
if (p_dict.has("properties")) {
|
||||
properties = p_dict["properties"];
|
||||
}
|
||||
for (int i = 0; i < properties.size(); i++) {
|
||||
doc.properties.push_back(PropertyDoc::from_dict(properties[i]));
|
||||
}
|
||||
|
||||
Array annotations;
|
||||
if (p_dict.has("annotations")) {
|
||||
annotations = p_dict["annotations"];
|
||||
}
|
||||
for (int i = 0; i < annotations.size(); i++) {
|
||||
doc.annotations.push_back(MethodDoc::from_dict(annotations[i]));
|
||||
}
|
||||
|
||||
Array theme_properties;
|
||||
if (p_dict.has("theme_properties")) {
|
||||
theme_properties = p_dict["theme_properties"];
|
||||
}
|
||||
for (int i = 0; i < theme_properties.size(); i++) {
|
||||
doc.theme_properties.push_back(ThemeItemDoc::from_dict(theme_properties[i]));
|
||||
}
|
||||
|
||||
if (p_dict.has("is_deprecated")) {
|
||||
doc.is_deprecated = p_dict["is_deprecated"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_experimental")) {
|
||||
doc.is_experimental = p_dict["is_experimental"];
|
||||
}
|
||||
|
||||
if (p_dict.has("is_script_doc")) {
|
||||
doc.is_script_doc = p_dict["is_script_doc"];
|
||||
}
|
||||
|
||||
if (p_dict.has("script_path")) {
|
||||
doc.script_path = p_dict["script_path"];
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
};
|
||||
|
||||
static String get_default_value_string(const Variant &p_value);
|
||||
|
||||
static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo);
|
||||
static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo);
|
||||
static void property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo);
|
||||
static void method_doc_from_methodinfo(DocData::MethodDoc &p_method, const MethodInfo &p_methodinfo, const String &p_desc);
|
||||
static void constant_doc_from_variant(DocData::ConstantDoc &p_const, const StringName &p_name, const Variant &p_value, const String &p_desc);
|
||||
static void signal_doc_from_methodinfo(DocData::MethodDoc &p_signal, const MethodInfo &p_methodinfo, const String &p_desc);
|
||||
};
|
||||
|
||||
#endif // DOC_DATA_H
|
||||
32
core/dvector.cpp
Normal file
32
core/dvector.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*************************************************************************/
|
||||
/* dvector.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "dvector.h"
|
||||
|
||||
Mutex *dvector_lock = NULL;
|
||||
418
core/dvector.h
Normal file
418
core/dvector.h
Normal file
@ -0,0 +1,418 @@
|
||||
/*************************************************************************/
|
||||
/* dvector.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 DVECTOR_H
|
||||
#define DVECTOR_H
|
||||
|
||||
#include "os/memory.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
extern Mutex *dvector_lock;
|
||||
|
||||
template <class T>
|
||||
class DVector {
|
||||
|
||||
mutable MID mem;
|
||||
|
||||
void copy_on_write() {
|
||||
|
||||
if (!mem.is_valid())
|
||||
return;
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
MID_Lock lock(mem);
|
||||
|
||||
if (*(int *)lock.data() == 1) {
|
||||
// one reference, means no refcount changes
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
MID new_mem = dynalloc(mem.get_size());
|
||||
|
||||
if (!new_mem.is_valid()) {
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
ERR_FAIL_COND(new_mem.is_valid()); // out of memory
|
||||
}
|
||||
|
||||
MID_Lock dst_lock(new_mem);
|
||||
|
||||
int *rc = (int *)dst_lock.data();
|
||||
|
||||
*rc = 1;
|
||||
|
||||
T *dst = (T *)(rc + 1);
|
||||
|
||||
T *src = (T *)((int *)lock.data() + 1);
|
||||
|
||||
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
memnew_placement(&dst[i], T(src[i]));
|
||||
}
|
||||
|
||||
(*(int *)lock.data())--;
|
||||
|
||||
// unlock all
|
||||
dst_lock = MID_Lock();
|
||||
lock = MID_Lock();
|
||||
|
||||
mem = new_mem;
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
}
|
||||
|
||||
void reference(const DVector &p_dvector) {
|
||||
|
||||
unreference();
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
if (!p_dvector.mem.is_valid()) {
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
MID_Lock lock(p_dvector.mem);
|
||||
|
||||
int *rc = (int *)lock.data();
|
||||
(*rc)++;
|
||||
|
||||
lock = MID_Lock();
|
||||
mem = p_dvector.mem;
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
}
|
||||
|
||||
void unreference() {
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
if (!mem.is_valid()) {
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
MID_Lock lock(mem);
|
||||
|
||||
int *rc = (int *)lock.data();
|
||||
(*rc)--;
|
||||
|
||||
if (*rc == 0) {
|
||||
// no one else using it, destruct
|
||||
|
||||
T *t = (T *)(rc + 1);
|
||||
int count = (mem.get_size() - sizeof(int)) / sizeof(T);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
t[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
lock = MID_Lock();
|
||||
|
||||
mem = MID();
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
class Read {
|
||||
friend class DVector;
|
||||
MID_Lock lock;
|
||||
const T *mem;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ const T &operator[](int p_index) const { return mem[p_index]; }
|
||||
_FORCE_INLINE_ const T *ptr() const { return mem; }
|
||||
|
||||
Read() { mem = NULL; }
|
||||
};
|
||||
|
||||
class Write {
|
||||
friend class DVector;
|
||||
MID_Lock lock;
|
||||
T *mem;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ T &operator[](int p_index) { return mem[p_index]; }
|
||||
_FORCE_INLINE_ T *ptr() { return mem; }
|
||||
|
||||
Write() { mem = NULL; }
|
||||
};
|
||||
|
||||
Read read() const {
|
||||
|
||||
Read r;
|
||||
if (mem.is_valid()) {
|
||||
r.lock = MID_Lock(mem);
|
||||
r.mem = (const T *)((int *)r.lock.data() + 1);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
Write write() {
|
||||
|
||||
Write w;
|
||||
if (mem.is_valid()) {
|
||||
copy_on_write();
|
||||
w.lock = MID_Lock(mem);
|
||||
w.mem = (T *)((int *)w.lock.data() + 1);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
template <class MC>
|
||||
void fill_with(const MC &p_mc) {
|
||||
|
||||
int c = p_mc.size();
|
||||
resize(c);
|
||||
Write w = write();
|
||||
int idx = 0;
|
||||
for (const typename MC::Element *E = p_mc.front(); E; E = E->next()) {
|
||||
|
||||
w[idx++] = E->get();
|
||||
}
|
||||
}
|
||||
|
||||
void remove(int p_index) {
|
||||
|
||||
int s = size();
|
||||
ERR_FAIL_INDEX(p_index, s);
|
||||
Write w = write();
|
||||
for (int i = p_index; i < s - 1; i++) {
|
||||
|
||||
w[i] = w[i + 1];
|
||||
};
|
||||
w = Write();
|
||||
resize(s - 1);
|
||||
}
|
||||
|
||||
inline int size() const;
|
||||
T get(int p_index) const;
|
||||
void set(int p_index, const T &p_val);
|
||||
void push_back(const T &p_val);
|
||||
void append(const T &p_val) { push_back(p_val); }
|
||||
void append_array(const DVector<T> &p_arr) {
|
||||
int ds = p_arr.size();
|
||||
if (ds == 0)
|
||||
return;
|
||||
int bs = size();
|
||||
resize(bs + ds);
|
||||
Write w = write();
|
||||
Read r = p_arr.read();
|
||||
for (int i = 0; i < ds; i++)
|
||||
w[bs + i] = r[i];
|
||||
}
|
||||
|
||||
Error insert(int p_pos, const T &p_val) {
|
||||
|
||||
int s = size();
|
||||
ERR_FAIL_INDEX_V(p_pos, s + 1, ERR_INVALID_PARAMETER);
|
||||
resize(s + 1);
|
||||
{
|
||||
Write w = write();
|
||||
for (int i = s; i > p_pos; i--)
|
||||
w[i] = w[i - 1];
|
||||
w[p_pos] = p_val;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool is_locked() const { return mem.is_locked(); }
|
||||
|
||||
inline const T operator[](int p_index) const;
|
||||
|
||||
Error resize(int p_size);
|
||||
|
||||
void invert();
|
||||
|
||||
void operator=(const DVector &p_dvector) { reference(p_dvector); }
|
||||
DVector() {}
|
||||
DVector(const DVector &p_dvector) { reference(p_dvector); }
|
||||
~DVector() { unreference(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
int DVector<T>::size() const {
|
||||
|
||||
return mem.is_valid() ? ((mem.get_size() - sizeof(int)) / sizeof(T)) : 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T DVector<T>::get(int p_index) const {
|
||||
|
||||
return operator[](p_index);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void DVector<T>::set(int p_index, const T &p_val) {
|
||||
|
||||
if (p_index < 0 || p_index >= size()) {
|
||||
ERR_FAIL_COND(p_index < 0 || p_index >= size());
|
||||
}
|
||||
|
||||
Write w = write();
|
||||
w[p_index] = p_val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void DVector<T>::push_back(const T &p_val) {
|
||||
|
||||
resize(size() + 1);
|
||||
set(size() - 1, p_val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T DVector<T>::operator[](int p_index) const {
|
||||
|
||||
if (p_index < 0 || p_index >= size()) {
|
||||
T &aux = *((T *)0); //nullreturn
|
||||
ERR_FAIL_COND_V(p_index < 0 || p_index >= size(), aux);
|
||||
}
|
||||
|
||||
Read r = read();
|
||||
|
||||
return r[p_index];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Error DVector<T>::resize(int p_size) {
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->lock();
|
||||
|
||||
bool same = p_size == size();
|
||||
|
||||
if (dvector_lock)
|
||||
dvector_lock->unlock();
|
||||
// no further locking is necesary because we are supposed to own the only copy of this (using copy on write)
|
||||
|
||||
if (same)
|
||||
return OK;
|
||||
|
||||
if (p_size == 0) {
|
||||
|
||||
unreference();
|
||||
return OK;
|
||||
}
|
||||
|
||||
copy_on_write(); // make it unique
|
||||
|
||||
ERR_FAIL_COND_V(mem.is_locked(), ERR_LOCKED); // if after copy on write, memory is locked, fail.
|
||||
|
||||
if (p_size > size()) {
|
||||
|
||||
int oldsize = size();
|
||||
|
||||
MID_Lock lock;
|
||||
|
||||
if (oldsize == 0) {
|
||||
|
||||
mem = dynalloc(p_size * sizeof(T) + sizeof(int));
|
||||
lock = MID_Lock(mem);
|
||||
int *rc = ((int *)lock.data());
|
||||
*rc = 1;
|
||||
|
||||
} else {
|
||||
|
||||
if (dynrealloc(mem, p_size * sizeof(T) + sizeof(int)) != OK) {
|
||||
|
||||
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // out of memory
|
||||
}
|
||||
|
||||
lock = MID_Lock(mem);
|
||||
}
|
||||
|
||||
T *t = (T *)((int *)lock.data() + 1);
|
||||
|
||||
for (int i = oldsize; i < p_size; i++) {
|
||||
|
||||
memnew_placement(&t[i], T);
|
||||
}
|
||||
|
||||
lock = MID_Lock(); // clear
|
||||
} else {
|
||||
|
||||
int oldsize = size();
|
||||
|
||||
MID_Lock lock(mem);
|
||||
|
||||
T *t = (T *)((int *)lock.data() + 1);
|
||||
|
||||
for (int i = p_size; i < oldsize; i++) {
|
||||
|
||||
t[i].~T();
|
||||
}
|
||||
|
||||
lock = MID_Lock(); // clear
|
||||
|
||||
if (dynrealloc(mem, p_size * sizeof(T) + sizeof(int)) != OK) {
|
||||
|
||||
ERR_FAIL_V(ERR_OUT_OF_MEMORY); // wtf error
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void DVector<T>::invert() {
|
||||
T temp;
|
||||
Write w = write();
|
||||
int s = size();
|
||||
int half_s = s / 2;
|
||||
|
||||
for (int i = 0; i < half_s; i++) {
|
||||
temp = w[i];
|
||||
w[i] = w[s - i - 1];
|
||||
w[s - i - 1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env_error = env.Clone()
|
||||
|
||||
env_error.add_source_files(env.core_sources, "*.cpp")
|
||||
@ -1,85 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* error_list.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 "error_list.h"
|
||||
|
||||
const char *error_names[] = {
|
||||
"OK", // OK
|
||||
"Failed", // FAILED
|
||||
"Unavailable", // ERR_UNAVAILABLE
|
||||
"Unconfigured", // ERR_UNCONFIGURED
|
||||
"Unauthorized", // ERR_UNAUTHORIZED
|
||||
"Parameter out of range", // ERR_PARAMETER_RANGE_ERROR
|
||||
"Out of memory", // ERR_OUT_OF_MEMORY
|
||||
"File not found", // ERR_FILE_NOT_FOUND
|
||||
"File: Bad drive", // ERR_FILE_BAD_DRIVE
|
||||
"File: Bad path", // ERR_FILE_BAD_PATH
|
||||
"File: Permission denied", // ERR_FILE_NO_PERMISSION
|
||||
"File already in use", // ERR_FILE_ALREADY_IN_USE
|
||||
"Can't open file", // ERR_FILE_CANT_OPEN
|
||||
"Can't write file", // ERR_FILE_CANT_WRITE
|
||||
"Can't read file", // ERR_FILE_CANT_READ
|
||||
"File unrecognized", // ERR_FILE_UNRECOGNIZED
|
||||
"File corrupt", // ERR_FILE_CORRUPT
|
||||
"Missing dependencies for file", // ERR_FILE_MISSING_DEPENDENCIES
|
||||
"End of file", // ERR_FILE_EOF
|
||||
"Can't open", // ERR_CANT_OPEN
|
||||
"Can't create", // ERR_CANT_CREATE
|
||||
"Query failed", // ERR_QUERY_FAILED
|
||||
"Already in use", // ERR_ALREADY_IN_USE
|
||||
"Locked", // ERR_LOCKED
|
||||
"Timeout", // ERR_TIMEOUT
|
||||
"Can't connect", // ERR_CANT_CONNECT
|
||||
"Can't resolve", // ERR_CANT_RESOLVE
|
||||
"Connection error", // ERR_CONNECTION_ERROR
|
||||
"Can't acquire resource", // ERR_CANT_ACQUIRE_RESOURCE
|
||||
"Can't fork", // ERR_CANT_FORK
|
||||
"Invalid data", // ERR_INVALID_DATA
|
||||
"Invalid parameter", // ERR_INVALID_PARAMETER
|
||||
"Already exists", // ERR_ALREADY_EXISTS
|
||||
"Does not exist", // ERR_DOES_NOT_EXIST
|
||||
"Can't read database", // ERR_DATABASE_CANT_READ
|
||||
"Can't write database", // ERR_DATABASE_CANT_WRITE
|
||||
"Compilation failed", // ERR_COMPILATION_FAILED
|
||||
"Method not found", // ERR_METHOD_NOT_FOUND
|
||||
"Link failed", // ERR_LINK_FAILED
|
||||
"Script failed", // ERR_SCRIPT_FAILED
|
||||
"Cyclic link detected", // ERR_CYCLIC_LINK
|
||||
"Invalid declaration", // ERR_INVALID_DECLARATION
|
||||
"Duplicate symbol", // ERR_DUPLICATE_SYMBOL
|
||||
"Parse error", // ERR_PARSE_ERROR
|
||||
"Busy", // ERR_BUSY
|
||||
"Skip", // ERR_SKIP
|
||||
"Help", // ERR_HELP
|
||||
"Bug", // ERR_BUG
|
||||
"Printer on fire", // ERR_PRINTER_ON_FIRE
|
||||
};
|
||||
|
||||
static_assert(sizeof(error_names) / sizeof(*error_names) == ERR_MAX);
|
||||
@ -1,101 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* error_list.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ERROR_LIST_H
|
||||
#define ERROR_LIST_H
|
||||
|
||||
/** Error List. Please never compare an error against FAILED
|
||||
* Either do result != OK , or !result. This way, Error fail
|
||||
* values can be more detailed in the future.
|
||||
*
|
||||
* This is a generic error list, mainly for organizing a language of returning errors.
|
||||
*
|
||||
* Errors:
|
||||
* - Are added to the Error enum in core/error/error_list.h
|
||||
* - Have a description added to error_names in core/error/error_list.cpp
|
||||
* - Are bound with BIND_CORE_ENUM_CONSTANT() in core/core_constants.cpp
|
||||
*/
|
||||
|
||||
enum Error {
|
||||
OK, // (0)
|
||||
FAILED, ///< Generic fail error
|
||||
ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
|
||||
ERR_UNCONFIGURED, ///< The object being used hasn't been properly set up yet
|
||||
ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
|
||||
ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
|
||||
ERR_OUT_OF_MEMORY, ///< Out of memory
|
||||
ERR_FILE_NOT_FOUND,
|
||||
ERR_FILE_BAD_DRIVE,
|
||||
ERR_FILE_BAD_PATH,
|
||||
ERR_FILE_NO_PERMISSION, // (10)
|
||||
ERR_FILE_ALREADY_IN_USE,
|
||||
ERR_FILE_CANT_OPEN,
|
||||
ERR_FILE_CANT_WRITE,
|
||||
ERR_FILE_CANT_READ,
|
||||
ERR_FILE_UNRECOGNIZED, // (15)
|
||||
ERR_FILE_CORRUPT,
|
||||
ERR_FILE_MISSING_DEPENDENCIES,
|
||||
ERR_FILE_EOF,
|
||||
ERR_CANT_OPEN, ///< Can't open a resource/socket/file
|
||||
ERR_CANT_CREATE, // (20)
|
||||
ERR_QUERY_FAILED,
|
||||
ERR_ALREADY_IN_USE,
|
||||
ERR_LOCKED, ///< resource is locked
|
||||
ERR_TIMEOUT,
|
||||
ERR_CANT_CONNECT, // (25)
|
||||
ERR_CANT_RESOLVE,
|
||||
ERR_CONNECTION_ERROR,
|
||||
ERR_CANT_ACQUIRE_RESOURCE,
|
||||
ERR_CANT_FORK,
|
||||
ERR_INVALID_DATA, ///< Data passed is invalid (30)
|
||||
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
|
||||
ERR_ALREADY_EXISTS, ///< When adding, item already exists
|
||||
ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, if item does not exist
|
||||
ERR_DATABASE_CANT_READ, ///< database is full
|
||||
ERR_DATABASE_CANT_WRITE, ///< database is full (35)
|
||||
ERR_COMPILATION_FAILED,
|
||||
ERR_METHOD_NOT_FOUND,
|
||||
ERR_LINK_FAILED,
|
||||
ERR_SCRIPT_FAILED,
|
||||
ERR_CYCLIC_LINK, // (40)
|
||||
ERR_INVALID_DECLARATION,
|
||||
ERR_DUPLICATE_SYMBOL,
|
||||
ERR_PARSE_ERROR,
|
||||
ERR_BUSY,
|
||||
ERR_SKIP, // (45)
|
||||
ERR_HELP, ///< user requested help!!
|
||||
ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
|
||||
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
|
||||
ERR_MAX, // Not being returned, value represents the number of errors
|
||||
};
|
||||
|
||||
extern const char *error_names[];
|
||||
|
||||
#endif // ERROR_LIST_H
|
||||
@ -1,130 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* error_macros.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 "error_macros.h"
|
||||
|
||||
#include "core/io/logger.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/ustring.h"
|
||||
|
||||
static ErrorHandlerList *error_handler_list = nullptr;
|
||||
|
||||
void add_error_handler(ErrorHandlerList *p_handler) {
|
||||
// If p_handler is already in error_handler_list
|
||||
// we'd better remove it first then we can add it.
|
||||
// This prevent cyclic redundancy.
|
||||
remove_error_handler(p_handler);
|
||||
|
||||
_global_lock();
|
||||
|
||||
p_handler->next = error_handler_list;
|
||||
error_handler_list = p_handler;
|
||||
|
||||
_global_unlock();
|
||||
}
|
||||
|
||||
void remove_error_handler(const ErrorHandlerList *p_handler) {
|
||||
_global_lock();
|
||||
|
||||
ErrorHandlerList *prev = nullptr;
|
||||
ErrorHandlerList *l = error_handler_list;
|
||||
|
||||
while (l) {
|
||||
if (l == p_handler) {
|
||||
if (prev) {
|
||||
prev->next = l->next;
|
||||
} else {
|
||||
error_handler_list = l->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev = l;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
_global_unlock();
|
||||
}
|
||||
|
||||
// Errors without messages.
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error, "", p_editor_notify, p_type);
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_editor_notify, p_type);
|
||||
}
|
||||
|
||||
// Main error printing function.
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
if (OS::get_singleton()) {
|
||||
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type);
|
||||
} else {
|
||||
// Fallback if errors happen before OS init or after it's destroyed.
|
||||
const char *err_details = (p_message && *p_message) ? p_message : p_error;
|
||||
fprintf(stderr, "ERROR: %s\n at: %s (%s:%i)\n", err_details, p_function, p_file, p_line);
|
||||
}
|
||||
|
||||
_global_lock();
|
||||
ErrorHandlerList *l = error_handler_list;
|
||||
while (l) {
|
||||
l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_editor_notify, p_type);
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
_global_unlock();
|
||||
}
|
||||
|
||||
// Errors with message. (All combinations of p_error and p_message as String or char*.)
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_type);
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_editor_notify, p_type);
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_editor_notify, p_type);
|
||||
}
|
||||
|
||||
// Index errors. (All combinations of p_message as String or char*.)
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool p_editor_notify, bool p_fatal) {
|
||||
String fstr(p_fatal ? "FATAL: " : "");
|
||||
String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ").");
|
||||
_err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message, p_editor_notify, ERR_HANDLER_ERROR);
|
||||
}
|
||||
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) {
|
||||
_err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_editor_notify, p_fatal);
|
||||
}
|
||||
|
||||
void _err_flush_stdout() {
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -1,804 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* error_macros.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef ERROR_MACROS_H
|
||||
#define ERROR_MACROS_H
|
||||
|
||||
#include "core/typedefs.h"
|
||||
|
||||
#include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes.
|
||||
|
||||
class String;
|
||||
|
||||
enum ErrorHandlerType {
|
||||
ERR_HANDLER_ERROR,
|
||||
ERR_HANDLER_WARNING,
|
||||
ERR_HANDLER_SCRIPT,
|
||||
ERR_HANDLER_SHADER,
|
||||
};
|
||||
|
||||
// Pointer to the error handler printing function. Reassign to any function to have errors printed.
|
||||
// Parameters: userdata, function, file, line, error, explanation, type.
|
||||
typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, bool p_editor_notify, ErrorHandlerType p_type);
|
||||
|
||||
struct ErrorHandlerList {
|
||||
ErrorHandlerFunc errfunc = nullptr;
|
||||
void *userdata = nullptr;
|
||||
|
||||
ErrorHandlerList *next = nullptr;
|
||||
|
||||
ErrorHandlerList() {}
|
||||
};
|
||||
|
||||
void add_error_handler(ErrorHandlerList *p_handler);
|
||||
void remove_error_handler(const ErrorHandlerList *p_handler);
|
||||
|
||||
// Functions used by the error macros.
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false);
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
|
||||
void _err_flush_stdout();
|
||||
|
||||
#ifdef __GNUC__
|
||||
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
|
||||
#define FUNCTION_STR __FUNCTION__
|
||||
#else
|
||||
#define FUNCTION_STR __FUNCTION__
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/**
|
||||
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
|
||||
*/
|
||||
#define GENERATE_TRAP() __debugbreak()
|
||||
#else
|
||||
/**
|
||||
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
|
||||
*/
|
||||
#define GENERATE_TRAP() __builtin_trap()
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Error macros.
|
||||
* WARNING: These macros work in the opposite way to assert().
|
||||
*
|
||||
* Unlike exceptions and asserts, these macros try to maintain consistency and stability.
|
||||
* In most cases, bugs and/or invalid data are not fatal. They should never allow a perfectly
|
||||
* running application to fail or crash.
|
||||
* Always try to return processable data, so the engine can keep running well.
|
||||
* Use the _MSG versions to print a meaningful message to help with debugging.
|
||||
*
|
||||
* The `((void)0)` no-op statement is used as a trick to force us to put a semicolon after
|
||||
* those macros, making them look like proper statements.
|
||||
* The if wrappers are used to ensure that the macro replacement does not trigger unexpected
|
||||
* issues when expanded e.g. after an `if (cond) ERR_FAIL();` without braces.
|
||||
*/
|
||||
|
||||
// Index out of bounds error macros.
|
||||
// These macros should be used instead of `ERR_FAIL_COND` for bounds checking.
|
||||
|
||||
// Integer index out of bounds error macros.
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_INDEX_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, prints `m_msg` and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_INDEX_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, prints `m_msg` and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_INDEX_V_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
|
||||
*
|
||||
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
|
||||
* If not, prints `m_msg` and the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Unsigned integer index out of bounds error macros.
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, prints `m_msg` and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_UNSIGNED_INDEX_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, prints `m_msg` and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_UNSIGNED_INDEX_V_EDMSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
|
||||
*
|
||||
* Ensures an unsigned integer index `m_index` is less than `m_size`.
|
||||
* If not, prints `m_msg` and the application crashes.
|
||||
*/
|
||||
#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
|
||||
if (unlikely((m_index) >= (m_size))) { \
|
||||
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Null reference error macros.
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_NULL_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_NULL(m_param) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, prints `m_msg` and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_NULL_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_NULL_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_V(m_param, m_retval) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures a pointer `m_param` is not null.
|
||||
* If it is null, prints `m_msg` and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_NULL_V_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \
|
||||
if (unlikely(m_param == nullptr)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
* If checking for null use ERR_FAIL_NULL_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_COND(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current function returns.
|
||||
*
|
||||
* If checking for null use ERR_FAIL_NULL_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
|
||||
*/
|
||||
#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_COND_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg, true); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_COND_V(m_cond, m_retval) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current function returns `m_retval`.
|
||||
*
|
||||
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
|
||||
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
|
||||
*/
|
||||
#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_COND_V_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg, true); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_CONTINUE_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current loop continues.
|
||||
*/
|
||||
#define ERR_CONTINUE(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \
|
||||
continue; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current loop continues.
|
||||
*/
|
||||
#define ERR_CONTINUE_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg); \
|
||||
continue; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_CONTINUE_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_CONTINUE_EDMSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg, true); \
|
||||
continue; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_BREAK_MSG`.
|
||||
* Only use this macro if there is no sensible error message.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the current loop breaks.
|
||||
*/
|
||||
#define ERR_BREAK(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \
|
||||
break; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the current loop breaks.
|
||||
*/
|
||||
#define ERR_BREAK_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg); \
|
||||
break; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_BREAK_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_BREAK_EDMSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg, true); \
|
||||
break; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, the application crashes.
|
||||
*/
|
||||
#define CRASH_COND(m_cond) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
|
||||
*
|
||||
* Ensures `m_cond` is false.
|
||||
* If `m_cond` is true, prints `m_msg` and the application crashes.
|
||||
*/
|
||||
#define CRASH_COND_MSG(m_cond, m_msg) \
|
||||
if (unlikely(m_cond)) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", m_msg); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Generic error macros.
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* The current function returns.
|
||||
*/
|
||||
#define ERR_FAIL() \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed."); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required.
|
||||
*
|
||||
* Prints `m_msg`, and the current function returns.
|
||||
*/
|
||||
#define ERR_FAIL_MSG(m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_EDMSG(m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg, true); \
|
||||
return; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required, and
|
||||
* there is no sensible error message.
|
||||
*
|
||||
* The current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_V(m_retval) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval)); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_V_MSG`.
|
||||
* Only use this macro if more complex error detection or recovery is required.
|
||||
*
|
||||
* Prints `m_msg`, and the current function returns `m_retval`.
|
||||
*/
|
||||
#define ERR_FAIL_V_MSG(m_retval, m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_FAIL_V_MSG` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_FAIL_V_EDMSG(m_retval, m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg, true); \
|
||||
return m_retval; \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or `ERR_BREAK_MSG`.
|
||||
* Only use this macro at the start of a function that has not been implemented yet, or
|
||||
* if more complex error detection or recovery is required.
|
||||
*
|
||||
* Prints `m_msg`.
|
||||
*/
|
||||
#define ERR_PRINT(m_msg) \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
|
||||
|
||||
/**
|
||||
* Same as `ERR_PRINT` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_PRINT_ED(m_msg) \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true)
|
||||
|
||||
/**
|
||||
* Prints `m_msg` once during the application lifetime.
|
||||
*/
|
||||
#define ERR_PRINT_ONCE(m_msg) \
|
||||
if (true) { \
|
||||
static bool first_print = true; \
|
||||
if (first_print) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \
|
||||
first_print = false; \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `ERR_PRINT_ONCE` but also notifies the editor.
|
||||
*/
|
||||
#define ERR_PRINT_ONCE_ED(m_msg) \
|
||||
if (true) { \
|
||||
static bool first_print = true; \
|
||||
if (first_print) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
|
||||
first_print = false; \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Print warning message macros.
|
||||
|
||||
/**
|
||||
* Prints `m_msg`.
|
||||
*
|
||||
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
|
||||
*/
|
||||
#define WARN_PRINT(m_msg) \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING)
|
||||
|
||||
/**
|
||||
* Same as `WARN_PRINT` but also notifies the editor.
|
||||
*/
|
||||
#define WARN_PRINT_ED(m_msg) \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING)
|
||||
|
||||
/**
|
||||
* Prints `m_msg` once during the application lifetime.
|
||||
*
|
||||
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
|
||||
*/
|
||||
#define WARN_PRINT_ONCE(m_msg) \
|
||||
if (true) { \
|
||||
static bool first_print = true; \
|
||||
if (first_print) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING); \
|
||||
first_print = false; \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Same as `WARN_PRINT_ONCE` but also notifies the editor.
|
||||
*/
|
||||
#define WARN_PRINT_ONCE_ED(m_msg) \
|
||||
if (true) { \
|
||||
static bool first_print = true; \
|
||||
if (first_print) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING); \
|
||||
first_print = false; \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
// Print deprecated warning message macros.
|
||||
|
||||
/**
|
||||
* Warns that the current function is deprecated.
|
||||
*/
|
||||
#define WARN_DEPRECATED \
|
||||
if (true) { \
|
||||
static std::atomic<bool> warning_shown; \
|
||||
if (!warning_shown.load()) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \
|
||||
warning_shown.store(true); \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Warns that the current function is deprecated and prints `m_msg`.
|
||||
*/
|
||||
#define WARN_DEPRECATED_MSG(m_msg) \
|
||||
if (true) { \
|
||||
static std::atomic<bool> warning_shown; \
|
||||
if (!warning_shown.load()) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \
|
||||
warning_shown.store(true); \
|
||||
} \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Do not use.
|
||||
* If the application should never reach this point use CRASH_NOW_MSG(m_msg) to explain why.
|
||||
*
|
||||
* The application crashes.
|
||||
*/
|
||||
#define CRASH_NOW() \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* Only use if the application should never reach this point.
|
||||
*
|
||||
* Prints `m_msg`, and then the application crashes.
|
||||
*/
|
||||
#define CRASH_NOW_MSG(m_msg) \
|
||||
if (true) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", m_msg); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
|
||||
/**
|
||||
* This should be a 'free' assert for program flow and should not be needed in any releases,
|
||||
* only used in dev builds.
|
||||
*/
|
||||
#ifdef DEV_ENABLED
|
||||
#define DEV_ASSERT(m_cond) \
|
||||
if (unlikely(!(m_cond))) { \
|
||||
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: DEV_ASSERT failed \"" _STR(m_cond) "\" is false."); \
|
||||
_err_flush_stdout(); \
|
||||
GENERATE_TRAP(); \
|
||||
} else \
|
||||
((void)0)
|
||||
#else
|
||||
#define DEV_ASSERT(m_cond)
|
||||
#endif
|
||||
|
||||
#endif // ERROR_MACROS_H
|
||||
94
core/error_list.h
Normal file
94
core/error_list.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*************************************************************************/
|
||||
/* error_list.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 ERROR_LIST_H
|
||||
#define ERROR_LIST_H
|
||||
|
||||
/** Error List. Please never compare an error against FAILED
|
||||
* Either do result != OK , or !result. This way, Error fail
|
||||
* values can be more detailed in the future.
|
||||
*
|
||||
* This is a generic error list, mainly for organizing a language of returning errors.
|
||||
*/
|
||||
|
||||
enum Error {
|
||||
OK,
|
||||
FAILED, ///< Generic fail error
|
||||
ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
|
||||
ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
|
||||
ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
|
||||
ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
|
||||
ERR_OUT_OF_MEMORY, ///< Out of memory
|
||||
ERR_FILE_NOT_FOUND,
|
||||
ERR_FILE_BAD_DRIVE,
|
||||
ERR_FILE_BAD_PATH,
|
||||
ERR_FILE_NO_PERMISSION, // (10)
|
||||
ERR_FILE_ALREADY_IN_USE,
|
||||
ERR_FILE_CANT_OPEN,
|
||||
ERR_FILE_CANT_WRITE,
|
||||
ERR_FILE_CANT_READ,
|
||||
ERR_FILE_UNRECOGNIZED, // (15)
|
||||
ERR_FILE_CORRUPT,
|
||||
ERR_FILE_MISSING_DEPENDENCIES,
|
||||
ERR_FILE_EOF,
|
||||
ERR_CANT_OPEN, ///< Can't open a resource/socket/file
|
||||
ERR_CANT_CREATE, // (20)
|
||||
ERROR_QUERY_FAILED,
|
||||
ERR_ALREADY_IN_USE,
|
||||
ERR_LOCKED, ///< resource is locked
|
||||
ERR_TIMEOUT,
|
||||
ERR_CANT_CONNECT, // (25)
|
||||
ERR_CANT_RESOLVE,
|
||||
ERR_CONNECTION_ERROR,
|
||||
ERR_CANT_AQUIRE_RESOURCE,
|
||||
ERR_CANT_FORK,
|
||||
ERR_INVALID_DATA, ///< Data passed is invalid (30)
|
||||
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
|
||||
ERR_ALREADY_EXISTS, ///< When adding, item already exists
|
||||
ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist
|
||||
ERR_DATABASE_CANT_READ, ///< database is full
|
||||
ERR_DATABASE_CANT_WRITE, ///< database is full (35)
|
||||
ERR_COMPILATION_FAILED,
|
||||
ERR_METHOD_NOT_FOUND,
|
||||
ERR_LINK_FAILED,
|
||||
ERR_SCRIPT_FAILED,
|
||||
ERR_CYCLIC_LINK, // (40)
|
||||
ERR_INVALID_DECLARATION,
|
||||
ERR_DUPLICATE_SYMBOL,
|
||||
ERR_PARSE_ERROR,
|
||||
ERR_BUSY,
|
||||
ERR_SKIP, // (45)
|
||||
ERR_HELP, ///< user requested help!!
|
||||
ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
|
||||
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
|
||||
ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though
|
||||
ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
|
||||
};
|
||||
|
||||
#endif
|
||||
97
core/error_macros.cpp
Normal file
97
core/error_macros.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*************************************************************************/
|
||||
/* error_macros.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* 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 "error_macros.h"
|
||||
#include "os/os.h"
|
||||
|
||||
bool _err_error_exists = false;
|
||||
|
||||
static ErrorHandlerList *error_handler_list = NULL;
|
||||
|
||||
void _err_set_last_error(const char *p_err) {
|
||||
|
||||
OS::get_singleton()->set_last_error(p_err);
|
||||
}
|
||||
|
||||
void _err_clear_last_error() {
|
||||
|
||||
OS::get_singleton()->clear_last_error();
|
||||
}
|
||||
|
||||
void add_error_handler(ErrorHandlerList *p_handler) {
|
||||
|
||||
_global_lock();
|
||||
p_handler->next = error_handler_list;
|
||||
error_handler_list = p_handler;
|
||||
_global_unlock();
|
||||
}
|
||||
|
||||
void remove_error_handler(ErrorHandlerList *p_handler) {
|
||||
|
||||
_global_lock();
|
||||
|
||||
ErrorHandlerList *prev = NULL;
|
||||
ErrorHandlerList *l = error_handler_list;
|
||||
|
||||
while (l) {
|
||||
|
||||
if (l == p_handler) {
|
||||
|
||||
if (prev)
|
||||
prev->next = l->next;
|
||||
else
|
||||
error_handler_list = l->next;
|
||||
break;
|
||||
}
|
||||
prev = l;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
_global_unlock();
|
||||
}
|
||||
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
|
||||
|
||||
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (OS::ErrorType)p_type);
|
||||
|
||||
_global_lock();
|
||||
ErrorHandlerList *l = error_handler_list;
|
||||
while (l) {
|
||||
|
||||
l->errfunc(l->userdata, p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", p_type);
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
_global_unlock();
|
||||
|
||||
if (_err_error_exists) {
|
||||
OS::get_singleton()->clear_last_error();
|
||||
_err_error_exists = false;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user