Compare commits
636 Commits
4.0.3-stab
...
3.0.6-stab
| Author | SHA1 | Date | |
|---|---|---|---|
| 8ac39d8863 | |||
| 83140541dc | |||
| 4491151aa9 | |||
| 5262d1bbcc | |||
| 1a325e3580 | |||
| fc678567d7 | |||
| 286ff21dd1 | |||
| cf1c127c23 | |||
| e7110984f3 | |||
| 31f8d3525d | |||
| e1cf8dc2cb | |||
| 291be24742 | |||
| 3304c7620a | |||
| ba441c48b0 | |||
| e5aedf130f | |||
| 94debea0a9 | |||
| c6a48e11e9 | |||
| 327452cb09 | |||
| c751b66d38 | |||
| 5928b18cf3 | |||
| f37779ba20 | |||
| ef67ef3155 | |||
| ba3406fffe | |||
| 68bfea5aa0 | |||
| be588f9493 | |||
| c3fcb18bc6 | |||
| 4897227d04 | |||
| 11cbf850a4 | |||
| c00c3f10a4 | |||
| 00fa61f8f5 | |||
| d3a482ab65 | |||
| b64850e732 | |||
| bc2ee93758 | |||
| 2843a3f7e7 | |||
| 33a9bda1d9 | |||
| d3c4f91c9c | |||
| 5c6c88ef15 | |||
| 69cdb35820 | |||
| 4d89153e5f | |||
| c709dff1a2 | |||
| d859aa1438 | |||
| 4fcb0d036c | |||
| b5338b640f | |||
| 6a88e22423 | |||
| 861d341dff | |||
| a34daf6851 | |||
| 59a00c3cdd | |||
| e86ef017f2 | |||
| d4a226500b | |||
| 16550339ba | |||
| 84e1551c64 | |||
| af902dc042 | |||
| d99b247cc7 | |||
| 139185e543 | |||
| 64bcefb7cd | |||
| 4ac9932128 | |||
| 9190ae2be7 | |||
| a03cf8964f | |||
| 4bf441c32b | |||
| b116a45f07 | |||
| d91613592b | |||
| e6df472e8f | |||
| f6abffdb4a | |||
| a1930b1772 | |||
| 9530ce9d3f | |||
| 3d8e49d9e8 | |||
| 64419a2ea1 | |||
| 34eabc0602 | |||
| ade470352c | |||
| ae48b1b94a | |||
| 394838901d | |||
| f49fcc960b | |||
| 2f3e4c1a7a | |||
| d04cc2855a | |||
| 909eaede4c | |||
| 4d7aa0b762 | |||
| 98609279b6 | |||
| 25047050b7 | |||
| 38e6ba10b4 | |||
| e649ec71df | |||
| 711aa196af | |||
| 518a691231 | |||
| e8bfc09b81 | |||
| 74808e71d2 | |||
| 403f7dc35f | |||
| e09170dffa | |||
| f640639867 | |||
| d24f77be99 | |||
| f697b53eba | |||
| 8231b3cef8 | |||
| b95cc40640 | |||
| 9294978596 | |||
| 3d3e4e62af | |||
| d00926894e | |||
| 5d2ad1e5c7 | |||
| 9945da3efc | |||
| d1e5677fe6 | |||
| 49ddd7b0e7 | |||
| e29800ea7b | |||
| 97ad6b813a | |||
| 77542276f8 | |||
| 0a3779135d | |||
| edf423a7aa | |||
| 02b1586de2 | |||
| a2a136ea02 | |||
| 9b8388dab1 | |||
| fbad7c2dd9 | |||
| 12fe774844 | |||
| 8dc021925f | |||
| 6843ccf462 | |||
| b27352a401 | |||
| 8461d6b5f9 | |||
| 0febfa9eea | |||
| 232a3a524b | |||
| b04c9a1b66 | |||
| dd026c77e3 | |||
| 00bf66d7f2 | |||
| 6224f02c56 | |||
| 31ce9ba07f | |||
| 94b4bb2a12 | |||
| 188bfd2ac9 | |||
| 04defcca4f | |||
| 81eb60434a | |||
| 6635f2a108 | |||
| 1d3be8c453 | |||
| 4de1d0905a | |||
| c461b15720 | |||
| 5c93f887ba | |||
| 9dc5ca0e7c | |||
| c7b141d20a | |||
| 0b3b3de2cd | |||
| 5e551a584e | |||
| fd95935fef | |||
| 4fbb460a02 | |||
| 4aad40d249 | |||
| 8ccb27ce18 | |||
| 9a0a40042e | |||
| 09277c8fd8 | |||
| faceb5b75d | |||
| 9dc5ba1aaf | |||
| a187fb381e | |||
| 868c44b239 | |||
| 10c12b37ec | |||
| ae32bcf4c3 | |||
| 3491e776dd | |||
| 5f632391ca | |||
| 2e61ca6193 | |||
| 3013f4cf2b | |||
| 31c4b743cb | |||
| 78e2e48d57 | |||
| 736e574a5e | |||
| 664052824e | |||
| 0b9f61c9a6 | |||
| 41bb321962 | |||
| 0c030d6e08 | |||
| c8ce9c0080 | |||
| a519dcd576 | |||
| 66c0be642f | |||
| 2fa54c1df6 | |||
| 7f65584f28 | |||
| 7e09206e5c | |||
| ecb4c4268c | |||
| db76c54117 | |||
| c2a8eb2081 | |||
| 5917063192 | |||
| bcb38393a5 | |||
| 1905e1c8a2 | |||
| a6c9527c2f | |||
| f4c469f1b7 | |||
| 196107cd9e | |||
| 33b78c0ad6 | |||
| fa19d01c7b | |||
| f847837fb2 | |||
| 056348a8c0 | |||
| ddbe559c04 | |||
| 63e70e3cd1 | |||
| 4866733a74 | |||
| 01e64eb247 | |||
| 4fe0a8efd8 | |||
| 0551c5c2cd | |||
| e10a2e5999 | |||
| cd9b0d7cc3 | |||
| 8e301c69cb | |||
| 3ee4d6af2e | |||
| 00c55bb2eb | |||
| fe9da69f96 | |||
| c358e4c728 | |||
| 7645c539c8 | |||
| e7837828f6 | |||
| 272fb05270 | |||
| 41f360f9c2 | |||
| 4ce6a8f5f9 | |||
| dfe6d42a01 | |||
| c20776945d | |||
| 0d6c64b38a | |||
| c968c787e5 | |||
| 6e658fdcc1 | |||
| aedc4a4e80 | |||
| 7417b6adb4 | |||
| 66b36235c9 | |||
| e317ab9abe | |||
| 6a48c552e2 | |||
| a1fd60f7d2 | |||
| b5ecdd8ce8 | |||
| 20ea59332f | |||
| 57b895338b | |||
| 2f82b67071 | |||
| 56b8c4b0eb | |||
| bae5f9feb8 | |||
| e95f542204 | |||
| e7c42f132c | |||
| 1608f04851 | |||
| 93ebac318b | |||
| c4d66d087f | |||
| feee8ddd3c | |||
| 659df8cbd8 | |||
| 19a010cc3a | |||
| 307fcb2713 | |||
| ec017f4c01 | |||
| f12db4013e | |||
| e53f01a7af | |||
| 46de6afc40 | |||
| 90bf0b7aec | |||
| 6cdf6d3044 | |||
| 1da969736f | |||
| 486f4d2769 | |||
| 199a54d5ac | |||
| 57c281557a | |||
| d330bee1c2 | |||
| 72bcacf2b6 | |||
| 3876a8776e | |||
| 37ce381e3d | |||
| 939d50243b | |||
| 57f18194f5 | |||
| 58f2953ddf | |||
| 31171ea5a2 | |||
| e7b97af276 | |||
| 95004aafb2 | |||
| 3f6ea30f8d | |||
| 58918b629d | |||
| 736d8db007 | |||
| 1e8ff7460a | |||
| b5425e3d87 | |||
| 3acd6fb728 | |||
| 94ddb499df | |||
| 5a947ebc42 | |||
| 44f4c8e745 | |||
| 4eed7cb9b2 | |||
| ca00323e7f | |||
| d49fc76ab8 | |||
| d89015cfe3 | |||
| 826108efec | |||
| 739c14b07d | |||
| 7f64090401 | |||
| 3bda257163 | |||
| 02f767fe0d | |||
| 20fa30bde6 | |||
| b5b0e42b85 | |||
| a525ea128d | |||
| 3b57b95efb | |||
| 4002da9603 | |||
| e5a17617e6 | |||
| 4e756d61c8 | |||
| 0f5a3d23ea | |||
| 2e31c9fe10 | |||
| cf3c1d878d | |||
| c5dfe6824c | |||
| 640063334d | |||
| ac9e87aae3 | |||
| 5e09cf3e89 | |||
| 6989a7ac53 | |||
| 060f9f2cd7 | |||
| 4c19fc2eb1 | |||
| 5e70e4469a | |||
| 287f169f2a | |||
| 60bc0f79a7 | |||
| c8d0d38cab | |||
| d3ffc8ad0c | |||
| 393e1ef4ee | |||
| 78b44eab0a | |||
| 0f6626977b | |||
| 71885e5ae4 | |||
| 038c4d3a83 | |||
| de66976ff0 | |||
| b08aa6fb3c | |||
| ce944bc3fb | |||
| 5485939233 | |||
| 3cc2eee4e8 | |||
| 56395b03e1 | |||
| 448d281222 | |||
| c07d588e80 | |||
| 52c710f25a | |||
| 29a02a78df | |||
| 91525e3075 | |||
| 7563c17113 | |||
| 43dcf23990 | |||
| 1182637ec9 | |||
| d40f40e1c9 | |||
| fa831f0224 | |||
| 141e389c3f | |||
| 72350eebb2 | |||
| 80fbea28fb | |||
| 7ec8a6e756 | |||
| ddb31e9c5a | |||
| dc97f91a18 | |||
| 171542d96a | |||
| b855bc44ae | |||
| c39e32ae60 | |||
| 5eef26b64e | |||
| 0d2a2a9300 | |||
| 6d767b0f9a | |||
| d49579b038 | |||
| a3ba1b0280 | |||
| c2e02e2066 | |||
| 3503ee4be6 | |||
| 069b429795 | |||
| 2f7aa6c2aa | |||
| a29680c25a | |||
| 3a430e46b9 | |||
| b4733a1da9 | |||
| 8ebd4bb874 | |||
| 63a88c69ac | |||
| bfc94dd4c9 | |||
| 6472d8c7d4 | |||
| e4fadebc3b | |||
| 548ec63f76 | |||
| 9e4d34aebb | |||
| d02c891a4b | |||
| 3bd414786c | |||
| c7adcc8dca | |||
| 577f3ccaf9 | |||
| bffd4f0548 | |||
| 4c8c383876 | |||
| 125b403c0f | |||
| 5f5ec7e162 | |||
| a91d9cb918 | |||
| a7ea441504 | |||
| 4b5472b100 | |||
| 3dc4447cb8 | |||
| 9a21f964ba | |||
| 1f07f71b6c | |||
| 259b9664ef | |||
| b5a55810c5 | |||
| 4fc6256010 | |||
| ce1b62a01f | |||
| 28d4271e3e | |||
| 30b5265417 | |||
| 2f53325bed | |||
| 7ad6a9aeea | |||
| 8018dc6599 | |||
| aaed3ef5ed | |||
| 99cf2ffb19 | |||
| 3b200c55b6 | |||
| 13e9b605cf | |||
| 5d7b7f798a | |||
| 710b57d493 | |||
| ef44ed93a7 | |||
| 4f0b5f7307 | |||
| 1c25e50490 | |||
| a9ec1e3913 | |||
| 46101928bd | |||
| 74e72c995d | |||
| b6f30f1b5b | |||
| b09d06fcf7 | |||
| 9567297a66 | |||
| 607884139c | |||
| 42f351db0d | |||
| 9ab9dd73b0 | |||
| fa9e03996c | |||
| 814b610ed3 | |||
| a5ccaa919e | |||
| 5042d0c30a | |||
| 27f5e404a7 | |||
| 2e9c9f7d74 | |||
| 6063e74e06 | |||
| 449e75455b | |||
| 73cc3a96c0 | |||
| 683511310e | |||
| 12336dc253 | |||
| 8da76f3bb8 | |||
| 8289f8628d | |||
| 91bc845152 | |||
| d8a0b6ba63 | |||
| bf4d8ee69c | |||
| 2c93def09d | |||
| 9cbcff4e91 | |||
| 985b84689f | |||
| 89e4125241 | |||
| 209acbaac7 | |||
| 8a0966a8cb | |||
| 99331ca395 | |||
| ec362d54a9 | |||
| 5e8e2a8730 | |||
| df7d60a9d3 | |||
| fe20a1e35b | |||
| 55a66efa38 | |||
| 5eebe51014 | |||
| 9febb6f747 | |||
| 626525d23a | |||
| a026e2626c | |||
| cf2e30b30c | |||
| f7efa9d43a | |||
| dfb739aff0 | |||
| 89bff17cd2 | |||
| 3e1716b2c3 | |||
| e6200de73a | |||
| 593e616a48 | |||
| eeb7385f02 | |||
| 2ff3b08583 | |||
| 6ab8fb04af | |||
| 498d177cfe | |||
| 06a60bb6ef | |||
| c0132f30c4 | |||
| 649cb70ddb | |||
| 65d214d3da | |||
| 9ee98e999b | |||
| 5bcc7f88b6 | |||
| 93e99846b0 | |||
| 5c2e554853 | |||
| c4468aef5d | |||
| f967334f53 | |||
| 4132f2ea7e | |||
| 262c97098d | |||
| cee20e24bd | |||
| 87476c057a | |||
| 53693e393d | |||
| 3f7e036c4f | |||
| 0aab429453 | |||
| 61fd30c00e | |||
| 44b206a3fa | |||
| 675899a521 | |||
| 61a9ef5d81 | |||
| 9c27e4d885 | |||
| c800653c6f | |||
| 3e931e258c | |||
| 7e5a374825 | |||
| a850ebf352 | |||
| 4e1d19b20c | |||
| d7430ef077 | |||
| 17408bea9c | |||
| 2c55064708 | |||
| 42e82b9377 | |||
| a4b077a0ba | |||
| f6c65d9d15 | |||
| 990bddcf36 | |||
| c730a6ce44 | |||
| 115c0a7415 | |||
| 87242c7b92 | |||
| 4eb9ee9355 | |||
| 48ed52184d | |||
| 69274ef368 | |||
| 039fc750d5 | |||
| 58a7d78c22 | |||
| c0386f0124 | |||
| b6f958965b | |||
| dde14e15c6 | |||
| 1ea805a4aa | |||
| 3b96b3fd12 | |||
| e499b9b4b6 | |||
| 8ea709a7a9 | |||
| f2e19a26f5 | |||
| be771e7165 | |||
| cb65617897 | |||
| bcbe7a8a6f | |||
| ae540c2efe | |||
| 5f15642fde | |||
| 17d7084780 | |||
| fe38b648b0 | |||
| ad325be5a0 | |||
| d69d58deea | |||
| 34591f9451 | |||
| d79a7a2773 | |||
| 05fec82f31 | |||
| 370f84f41c | |||
| 689dfcd9ec | |||
| 46b594054c | |||
| 07e2461995 | |||
| ca5f3b9f8d | |||
| 3d804778fd | |||
| 3e8c214a19 | |||
| e9d8dfbf0e | |||
| 3687faa78f | |||
| eacd66e784 | |||
| b5f8c1a53b | |||
| f04cd405ac | |||
| f55b376d78 | |||
| fdac09a0aa | |||
| 751806b5c7 | |||
| 40018e995c | |||
| be6323d848 | |||
| 29089b715d | |||
| 7e89cc46dd | |||
| a86829211a | |||
| f01821b60a | |||
| 245c11be08 | |||
| fa98637aca | |||
| 723613dbc3 | |||
| 99efa7ce62 | |||
| c7040f3218 | |||
| 5975b44ded | |||
| 8efb9c8cdd | |||
| 75289b4017 | |||
| ccf27376a6 | |||
| 23b9f09c58 | |||
| e1fc7776f6 | |||
| c6a96fc360 | |||
| 4383fae5a4 | |||
| 9cfcf102a0 | |||
| 8dc946c89c | |||
| 327fea741a | |||
| 317cb336eb | |||
| 83b76a8171 | |||
| 70b082c0d9 | |||
| bbfec2a7cc | |||
| 8849377f6d | |||
| 149ffcb1a4 | |||
| fb4a784319 | |||
| 8f231d82bb | |||
| cc280545dc | |||
| fa02b58b46 | |||
| 000caef623 | |||
| b7faa76485 | |||
| a76dfe9c72 | |||
| a423adbee6 | |||
| c5b5fd61d4 | |||
| 5bb269d01d | |||
| d5535d9357 | |||
| 2714b851bf | |||
| 2abbdcaa20 | |||
| 9cba5ef772 | |||
| 416cd9c8b8 | |||
| 7a20495a80 | |||
| bafbd73b51 | |||
| ac6811c4fa | |||
| 8372a404bb | |||
| 5b04dcfabd | |||
| 4b581104e7 | |||
| f49601a934 | |||
| 3e6ab9f3d5 | |||
| 9f9731da3a | |||
| 18735ff6f2 | |||
| 237cf72f89 | |||
| 5c2b2ca95b | |||
| 57f707f951 | |||
| 2f87e7ffe9 | |||
| 12da8dcdeb | |||
| c5388fb0cf | |||
| 02e910275c | |||
| 285f47f037 | |||
| 9fb843db06 | |||
| 4bdcee2b9d | |||
| fd033473c7 | |||
| a39930c5b9 | |||
| c94d8e6577 | |||
| eb5e5200cc | |||
| d54ac732ae | |||
| 62fcd772be | |||
| 150423203b | |||
| ef60123938 | |||
| 0d03b5f162 | |||
| 148e059940 | |||
| 7af43c4ca3 | |||
| 5b32be4701 | |||
| 47b49200b0 | |||
| a7d7f763d0 | |||
| eda94419df | |||
| e6252bda5e | |||
| 069658f1be | |||
| a0e59a7259 | |||
| 82b9a13e0c | |||
| 79ef5f92a9 | |||
| 5d7867082d | |||
| fda35b3f42 | |||
| a0e9d751a3 | |||
| d4a70c6c08 | |||
| 65aa9063c4 | |||
| 9eb546e7ff | |||
| f031e2f665 | |||
| 4bed14f69b | |||
| 91692ce72a | |||
| 05e97db6f2 | |||
| 617bcd1b91 | |||
| 34d8625d82 | |||
| 79b931d093 | |||
| 9173819b71 | |||
| 8787850286 | |||
| 2515d42a14 | |||
| 1a9a40fe31 | |||
| eda3169cd1 | |||
| d7f73031fb | |||
| ba36ef5465 | |||
| 41f9904e71 | |||
| a206d3d2fc | |||
| a6ca62ac79 | |||
| 85dedc09a8 | |||
| 9e7c3016d1 | |||
| 906cf28dae | |||
| 801b544ee1 | |||
| 097f95993f | |||
| c04d868476 | |||
| 50674dbe15 | |||
| 71607d9198 | |||
| 3548f71cc4 | |||
| a1455f6a03 | |||
| f64b68d870 | |||
| f1d26c1c72 | |||
| 7f5fde6459 | |||
| 611caa06a5 | |||
| 3f6e8d70cf | |||
| 40c779fb70 | |||
| 532abf228c | |||
| 248fea2a79 | |||
| 7de47fbabb | |||
| 62dc7ba82f | |||
| 4a3a597377 | |||
| 501880e9ba | |||
| bd02969263 | |||
| 0fa4325153 | |||
| acf01c955f | |||
| 0a75a38db4 | |||
| 845f44b976 | |||
| 77ee4ced30 | |||
| 780a7a281b | |||
| 5481ece976 | |||
| ef49c166f6 | |||
| 77cc0a023b | |||
| 1036a76bc5 | |||
| e44bef4404 | |||
| c77047d6a3 | |||
| a34afa3820 | |||
| 77d27053c3 | |||
| 187c40d64d | |||
| e69b30b276 | |||
| 99e72894a2 | |||
| 258119a9cf | |||
| 3f6694b894 |
32
.appveyor.yml
Normal file
32
.appveyor.yml
Normal file
@ -0,0 +1,32 @@
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
HOME: "%HOMEDRIVE%%HOMEPATH%"
|
||||
PYTHON: C:\Python27
|
||||
SCONS_CACHE_ROOT: "%HOME%\\scons_cache"
|
||||
SCONS_CACHE_LIMIT: 512
|
||||
matrix:
|
||||
- VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
|
||||
GD_PLATFORM: windows
|
||||
TOOLS: yes
|
||||
TARGET: release_debug
|
||||
ARCH: amd64
|
||||
|
||||
cache:
|
||||
- "%SCONS_CACHE_ROOT%"
|
||||
|
||||
install:
|
||||
- SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
- pip install -U wheel # needed for pip install scons to work, otherwise a flag is missing
|
||||
- pip install scons
|
||||
- if defined VS call "%VS%" %ARCH% # if defined - so we can also use mingw
|
||||
|
||||
before_build:
|
||||
- echo %GD_PLATFORM%
|
||||
- python --version
|
||||
- scons --version
|
||||
- cl.exe
|
||||
- SET "SCONS_CACHE=%SCONS_CACHE_ROOT%\master"
|
||||
|
||||
build_script:
|
||||
- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% verbose=yes progress=no gdnative_wrapper=yes
|
||||
115
.clang-format
115
.clang-format
@ -1,40 +1,31 @@
|
||||
# Commented out parameters are those with the same value as base LLVM style.
|
||||
# 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).
|
||||
# chosen value in case the base style changes (last sync: Clang 6.0.1).
|
||||
---
|
||||
### General config, applies to all languages ###
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
# AlignArrayOfStructures: None
|
||||
# AlignConsecutiveMacros: None
|
||||
# AlignConsecutiveAssignments: None
|
||||
# AlignConsecutiveBitFields: None
|
||||
# AlignConsecutiveDeclarations: None
|
||||
# AlignConsecutiveAssignments: false
|
||||
# AlignConsecutiveDeclarations: false
|
||||
# AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
# 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
|
||||
@ -44,44 +35,32 @@ AllowAllParametersOfDeclarationOnNextLine: 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
|
||||
# BreakStringLiterals: true
|
||||
ColumnLimit: 0
|
||||
# CommentPragmas: '^ IWYU pragma:'
|
||||
# QualifierAlignment: Leave
|
||||
# CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
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
|
||||
IncludeCategories:
|
||||
- Regex: '".*"'
|
||||
@ -91,21 +70,13 @@ IncludeCategories:
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
# IncludeIsMainSourceRegex: ''
|
||||
# IndentAccessModifiers: false
|
||||
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
|
||||
@ -114,86 +85,42 @@ KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakOpenParenthesis: 0
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyBreakTemplateDeclaration: 10
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PenaltyIndentedWhitespace: 0
|
||||
# PointerAlignment: Right
|
||||
# PPIndentWidth: -1
|
||||
# ReferenceAlignment: Pointer
|
||||
# RawStringFormats:
|
||||
# - Delimiter: pb
|
||||
# Language: TextProto
|
||||
# BasedOnStyle: google
|
||||
# ReflowComments: true
|
||||
# RemoveBracesLLVM: false
|
||||
# SeparateDefinitionBlocks: Leave
|
||||
# ShortNamespaceLines: 1
|
||||
# SortIncludes: CaseSensitive
|
||||
# SortJavaStaticImport: Before
|
||||
# SortIncludes: true
|
||||
# SortUsingDeclarations: 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
|
||||
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
|
||||
Standard: Cpp03
|
||||
---
|
||||
### 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'
|
||||
...
|
||||
|
||||
@ -9,25 +9,10 @@ insert_final_newline = true
|
||||
[*.{cpp,hpp,c,h,mm}]
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.gradle,AndroidManifest.xml}]
|
||||
[*.py]
|
||||
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
|
||||
23
.gitattributes
vendored
23
.gitattributes
vendored
@ -1,20 +1,11 @@
|
||||
# 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
|
||||
*.mm eol=lf
|
||||
*.h eol=lf
|
||||
*.py eol=lf
|
||||
*.hpp eol=lf
|
||||
*.xml 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
|
||||
60
.github/workflows/android_builds.yml
vendored
60
.github/workflows/android_builds.yml
vendored
@ -1,60 +0,0 @@
|
||||
name: 🤖 Android Builds
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: '4.0'
|
||||
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
|
||||
39
.github/workflows/ios_builds.yml
vendored
39
.github/workflows/ios_builds.yml
vendored
@ -1,39 +0,0 @@
|
||||
name: 🍏 iOS Builds
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: '4.0'
|
||||
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
|
||||
215
.github/workflows/linux_builds.yml
vendored
215
.github/workflows/linux_builds.yml
vendored
@ -1,215 +0,0 @@
|
||||
name: 🐧 Linux Builds
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key, and godot-cpp checkout. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: '4.0'
|
||||
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
|
||||
ref: ${{ env.GODOT_BASE_BRANCH }}
|
||||
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 }}
|
||||
75
.github/workflows/macos_builds.yml
vendored
75
.github/workflows/macos_builds.yml
vendored
@ -1,75 +0,0 @@
|
||||
name: 🍎 macOS Builds
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: '4.0'
|
||||
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 }}
|
||||
41
.github/workflows/runner.yml
vendored
41
.github/workflows/runner.yml
vendored
@ -1,41 +0,0 @@
|
||||
name: 🔗 GHA
|
||||
on: [push, pull_request]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-runner
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
static-checks:
|
||||
name: 📊 Static checks
|
||||
uses: ./.github/workflows/static_checks.yml
|
||||
|
||||
android-build:
|
||||
name: 🤖 Android
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/android_builds.yml
|
||||
|
||||
ios-build:
|
||||
name: 🍏 iOS
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/ios_builds.yml
|
||||
|
||||
linux-build:
|
||||
name: 🐧 Linux
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/linux_builds.yml
|
||||
|
||||
macos-build:
|
||||
name: 🍎 macOS
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/macos_builds.yml
|
||||
|
||||
windows-build:
|
||||
name: 🏁 Windows
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/windows_builds.yml
|
||||
|
||||
web-build:
|
||||
name: 🌐 Web
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/web_builds.yml
|
||||
110
.github/workflows/static_checks.yml
vendored
110
.github/workflows/static_checks.yml
vendored
@ -1,110 +0,0 @@
|
||||
name: 📊 Static Checks
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
static-checks:
|
||||
name: Code style, file formatting, and docs
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Install APT dependencies
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: dos2unix libxml2-utils moreutils
|
||||
|
||||
- name: Install Python dependencies and general setup
|
||||
run: |
|
||||
pip3 install black==22.3.0 pytest==7.1.2 mypy==0.971
|
||||
git config diff.wsErrorHighlight all
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then
|
||||
files=$(gh pr diff ${{ github.event.pull_request.number }} --name-only)
|
||||
elif [ "${{ github.event_name }}" == "push" -a "${{ github.event.forced }}" == "false" -a "${{ github.event.created }}" == "false" ]; then
|
||||
files=$(git diff-tree --no-commit-id --name-only -r ${{ github.event.before }}..${{ github.event.after }} 2> /dev/null || true)
|
||||
fi
|
||||
echo "$files" >> changed.txt
|
||||
cat changed.txt
|
||||
files=$(echo "$files" | grep -v 'thirdparty' | xargs -I {} sh -c 'echo "./{}"' | tr '\n' ' ')
|
||||
echo "CHANGED_FILES=$files" >> $GITHUB_ENV
|
||||
|
||||
- name: File formatting checks (file_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/file_format.sh changed.txt
|
||||
|
||||
- name: Header guards formatting checks (header_guards.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/header_guards.sh changed.txt
|
||||
|
||||
- name: Python style checks via black (black_format.sh)
|
||||
run: |
|
||||
if grep -qE '\.py$|SConstruct|SCsub' changed.txt || [ -z "$(cat changed.txt)" ]; then
|
||||
bash ./misc/scripts/black_format.sh
|
||||
else
|
||||
echo "Skipping Python formatting as no Python files were changed."
|
||||
fi
|
||||
|
||||
- name: Python scripts static analysis (mypy_check.sh)
|
||||
run: |
|
||||
if grep -qE '\.py$|SConstruct|SCsub' changed.txt || [ -z "$(cat changed.txt)" ]; then
|
||||
bash ./misc/scripts/mypy_check.sh
|
||||
else
|
||||
echo "Skipping Python static analysis as no Python files were changed."
|
||||
fi
|
||||
|
||||
- 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: |
|
||||
if grep -q "platform/web" changed.txt || [ -z "$(cat changed.txt)" ]; then
|
||||
cd platform/web
|
||||
npm ci
|
||||
npm run lint
|
||||
npm run docs -- -d dry-run
|
||||
else
|
||||
echo "Skipping JavaScript formatting as no Web/JS files were changed."
|
||||
fi
|
||||
|
||||
- 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: |
|
||||
clang-format --version
|
||||
bash ./misc/scripts/clang_format.sh changed.txt
|
||||
|
||||
- name: Style checks via dotnet format (dotnet_format.sh)
|
||||
run: |
|
||||
if grep -q "modules/mono" changed.txt || [ -z "$(cat changed.txt)" ]; then
|
||||
bash ./misc/scripts/dotnet_format.sh
|
||||
else
|
||||
echo "Skipping dotnet format as no C# files were changed."
|
||||
fi
|
||||
|
||||
- name: Spell checks via codespell
|
||||
if: github.event_name == 'pull_request' && env.CHANGED_FILES != ''
|
||||
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"
|
||||
ignore_words_list: "curvelinear,doubleclick,expct,findn,gird,hel,inout,lod,nd,numer,ot,te,vai"
|
||||
path: ${{ env.CHANGED_FILES }}
|
||||
51
.github/workflows/web_builds.yml
vendored
51
.github/workflows/web_builds.yml
vendored
@ -1,51 +0,0 @@
|
||||
name: 🌐 Web Builds
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: '4.0'
|
||||
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
|
||||
78
.github/workflows/windows_builds.yml
vendored
78
.github/workflows/windows_builds.yml
vendored
@ -1,78 +0,0 @@
|
||||
name: 🏁 Windows Builds
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
# Global Settings
|
||||
# SCONS_CACHE for windows must be set in the build environment
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: '4.0'
|
||||
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)
|
||||
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 }}
|
||||
475
.gitignore
vendored
475
.gitignore
vendored
@ -1,284 +1,120 @@
|
||||
# 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
|
||||
|
||||
###########################
|
||||
### Build configuration ###
|
||||
###########################
|
||||
|
||||
/custom.py
|
||||
misc/hooks/pre-commit-custom-*
|
||||
|
||||
#############################
|
||||
### Godot generated files ###
|
||||
#############################
|
||||
|
||||
# Buildsystem
|
||||
bin
|
||||
# Godot auto generated files
|
||||
*.gen.*
|
||||
compile_commands.json
|
||||
platform/windows/godot_res.res
|
||||
|
||||
# Generated by Godot binary
|
||||
.import/
|
||||
/gdextension_interface.h
|
||||
extension_api.json
|
||||
logs/
|
||||
# Documentation generated by doxygen or from classes.xml
|
||||
doc/_build/
|
||||
|
||||
# Generated by unit tests
|
||||
tests/data/*.translation
|
||||
# Javascript specific
|
||||
*.bc
|
||||
|
||||
############################
|
||||
### General build output ###
|
||||
############################
|
||||
# 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
|
||||
platform/android/java/.idea/*
|
||||
platform/android/java/*.iml
|
||||
|
||||
# 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 development
|
||||
.venv
|
||||
venv
|
||||
|
||||
# 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
|
||||
# Gprof output
|
||||
gmon.out
|
||||
|
||||
# Jetbrains IDEs
|
||||
.idea/
|
||||
.fleet/
|
||||
# Vim temp files
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
# Kate
|
||||
*.kate-swp
|
||||
|
||||
# Kdevelop
|
||||
*.kdev4
|
||||
|
||||
# Qt Creator
|
||||
# QT project files
|
||||
*.config
|
||||
*.creator
|
||||
*.creator.*
|
||||
*.files
|
||||
*.includes
|
||||
*.cflags
|
||||
*.cxxflags
|
||||
|
||||
# SCons
|
||||
# Eclipse CDT files
|
||||
.cproject
|
||||
.settings/
|
||||
|
||||
# Geany/geany-plugins files
|
||||
*.geany
|
||||
.geanyprj
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
logs/
|
||||
|
||||
# for projects that use SCons for building: http://http://www.scons.org/
|
||||
.sconf_temp
|
||||
.sconsign*.dblite
|
||||
.scons_env.json
|
||||
.scons_node_count
|
||||
.sconsign.dblite
|
||||
*.pyc
|
||||
|
||||
# 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
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
.history/
|
||||
|
||||
# Xcode
|
||||
xcuserdata/
|
||||
*.xcscmblueprint
|
||||
*.xccheckout
|
||||
*.xcodeproj/*
|
||||
|
||||
##############################
|
||||
### 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/
|
||||
*.debug
|
||||
*.dSYM
|
||||
|
||||
# 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/
|
||||
# Hints for improving IntelliSense, created together with VS project
|
||||
cpp.hint
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
# Visualizers for the VS debugger
|
||||
*.natvis
|
||||
|
||||
# Files built by Visual Studio
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
*.o
|
||||
*.a
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
@ -288,9 +124,7 @@ Generated\ Files/
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
@ -298,83 +132,182 @@ Generated\ Files/
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
*.VC.VC.opendb
|
||||
enc_temp_folder/
|
||||
|
||||
# Visual Studio profiler
|
||||
*.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
|
||||
|
||||
# xCode
|
||||
xcuserdata
|
||||
|
||||
# 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 2017 and Visual Studio Code workspace folder
|
||||
/.vs
|
||||
/.vscode
|
||||
|
||||
# Scons progress indicator
|
||||
.scons_node_count
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
extraction:
|
||||
cpp:
|
||||
after_prepare:
|
||||
- pip3 install scons
|
||||
- PATH="/opt/work/.local/bin:$PATH"
|
||||
index:
|
||||
build_command: scons -j2
|
||||
160
.mailmap
160
.mailmap
@ -1,165 +1,29 @@
|
||||
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>
|
||||
Andreas Haas <liu.gam3@gmail.com>
|
||||
Andreas Haas <Hinsbart@users.noreply.github.com>
|
||||
Andreas Haas <entenflugstuhl@gmail.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>
|
||||
Ariel Manzur <ariel@okamstudio.com>
|
||||
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>
|
||||
Bernhard Liebl <poke1024@gmx.de>
|
||||
Bernhard Liebl <poke1024@gmx.org>
|
||||
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 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>
|
||||
Juan Linietsky <juan@okamstudio.com>
|
||||
Juan Linietsky <reduz@Juans-MBP.fibertel.com.ar>
|
||||
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>
|
||||
Leon Krause <eska@eska.me>
|
||||
Leon Krause <eska@eska.me> <eska014@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>
|
||||
Thomas Herzog <therzog@mail.de>
|
||||
Zher Huei Lee <lee.zh.92@gmail.com>
|
||||
|
||||
107
.travis.yml
Normal file
107
.travis.yml
Normal file
@ -0,0 +1,107 @@
|
||||
language: cpp
|
||||
|
||||
# OS config, depends on actual 'os' in build matrix
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- SCONS_CACHE=$HOME/.scons_cache
|
||||
- SCONS_CACHE_LIMIT=1024
|
||||
- OPTIONS="verbose=yes progress=no gdnative_wrapper=yes"
|
||||
- secure: "QLFRizqry/Y5pnEZvDlQz5S3YydQ+600u4rHEzFgUTd0heYeQaETXAQeMzp0ymuG1BkdRAl5YJoLVJgAzjwI9hrvugvoUlh2//SfpqZCHN/Q1fYbtGgNTn01R3VFEpcfYQL93I2EjrxVm0WTM4PwCvMO+hU0aWTRDvCt1Lty0kMR+RMDQOO/woqunoXh5wvFNxTJJkAmuLe0v962DJYOIwJAnqMLR0aFYjmeQJ20bc/2X5oLt+WuJDuf/lGj6WSlD6z/o/kL3YxHoUyw4A/HAZ2IX0IfNHKuay60ESWzl/NlobnePiPwHAE2pdDVu//q16fanb9VeYnBYRFse49TpFRb86Lo+Qz8nKDJqpQEIY0YKNCFqekrubqTM++Lj6QvGpykQZNxUhybmELcEsRG4PS0UMvCpebdnJD46nNB+DtO2Lgb4xXDLQwpq19z1wizq/XDQ5hz61TIIx8+i8TsgdSQKCTeWovd4HcD4CVjAD5XTLGgyRmI/zC2d+lTnKo6W9diLq/bX/Goq2QPeaTPABqv817IaJka2JyugQ7Qal/+gNTjYRRsimRCL9B2tVh+Uh8rWhTFhQL4QbP5P65HF+p8qojUzqtAhPMbZ8mxUtNukUI3liVgPgiMss96sG0nTVglFgkkAkEjIMFnqMSKnTfG812K4jIhp2jCO2Q3NeI="
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $SCONS_CACHE
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: STATIC_CHECKS=yes
|
||||
os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-trusty-5.0
|
||||
packages:
|
||||
- clang-format-5.0
|
||||
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "godotengine/godot"
|
||||
description: "Godot Engine Coverity scans"
|
||||
notification_email: coverity@godotengine.org
|
||||
build_command_prepend: ""
|
||||
build_command: "scons p=x11 -j2 $OPTIONS"
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
- env: GODOT_TARGET=x11 TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-mono-gcc EXTRA_ARGS="module_mono_enabled=yes mono_glue=no"
|
||||
os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- mono
|
||||
packages:
|
||||
- &linux_deps [libasound2-dev, libfreetype6-dev, libgl1-mesa-dev, libglu1-mesa-dev, libx11-dev, libxcursor-dev, libxi-dev, libxinerama-dev, libxrandr-dev]
|
||||
- &linux_mono_deps [mono-devel, msbuild]
|
||||
|
||||
- env: GODOT_TARGET=x11 TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
|
||||
os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *linux_deps
|
||||
|
||||
- env: GODOT_TARGET=android TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
|
||||
os: linux
|
||||
compiler: clang
|
||||
|
||||
- env: GODOT_TARGET=osx TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-clang
|
||||
os: osx
|
||||
osx_image: xcode9.3
|
||||
compiler: clang
|
||||
|
||||
- env: GODOT_TARGET=iphone TOOLS=no CACHE_NAME=${GODOT_TARGET}-clang
|
||||
os: osx
|
||||
osx_image: xcode9.3
|
||||
compiler: clang
|
||||
|
||||
- env: GODOT_TARGET=server TOOLS=yes CACHE_NAME=${GODOT_TARGET}-tools-gcc
|
||||
os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *linux_deps
|
||||
|
||||
before_install:
|
||||
- if [ "$STATIC_CHECKS" = "yes" ]; then
|
||||
unset SCONS_CACHE;
|
||||
fi
|
||||
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$GODOT_TARGET" = "android" ]; then
|
||||
misc/travis/android-tools-linux.sh;
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
misc/travis/scons-local-osx.sh;
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$GODOT_TARGET" = "android" ]; then
|
||||
misc/travis/android-tools-osx.sh;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- if [ "$GODOT_TARGET" = "android" ]; then
|
||||
export ANDROID_HOME=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-sdk;
|
||||
export ANDROID_NDK_ROOT=$TRAVIS_BUILD_DIR/godot-dev/build-tools/android-ndk;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [ "$STATIC_CHECKS" = "yes" ]; then
|
||||
sh ./misc/travis/clang-format.sh;
|
||||
else
|
||||
scons -j2 CC=$CC CXX=$CXX platform=$GODOT_TARGET TOOLS=$TOOLS $EXTRA_ARGS $OPTIONS;
|
||||
fi
|
||||
178
AUTHORS.md
178
AUTHORS.md
@ -25,248 +25,106 @@ name is available.
|
||||
|
||||
## 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)
|
||||
Alexey Velikiy (jonyrock)
|
||||
Alket Rexhepi (alketii)
|
||||
Andrea Catania (AndreaCatania)
|
||||
Andrii Doroshenko (Xrayez)
|
||||
Andy Maloney (asmaloney)
|
||||
Andreas Haas (Hinsbart)
|
||||
Andy Moss (MillionOstrich)
|
||||
Angad Kambli (angad-k)
|
||||
Anilforextra (AnilBK)
|
||||
Anish Bhobe (KidRigger)
|
||||
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)
|
||||
Benjamin (Nallebeorn)
|
||||
Bernard Liebl (poke1024)
|
||||
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)
|
||||
bruvzg
|
||||
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
|
||||
Hein-Pieter van Braam (hpvb)
|
||||
Hiroshi Ogawa (hi-ogawa)
|
||||
homer666
|
||||
hoontee
|
||||
Hubert Jarosz (Marqin)
|
||||
Hugo Locurcio (Calinou)
|
||||
Ian Bishop (ianb96)
|
||||
Ibrahn Sahir (ibrahn)
|
||||
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)
|
||||
Jérôme GULLY (Nutriz)
|
||||
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)
|
||||
Leon Krause (eska014)
|
||||
m4nu3lf
|
||||
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)
|
||||
Michael Alexsander Silva Dias (YeldhamDev)
|
||||
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
|
||||
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)
|
||||
rraallvv
|
||||
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)
|
||||
Thomas Herzog (karroffel)
|
||||
Timo (toger5)
|
||||
Tomasz Chabora (KoBeWi)
|
||||
trollodel
|
||||
Twarit Waikar (IronicallySerious)
|
||||
Umang Kalra (theoway)
|
||||
Vinzenz Feenstra (vinzenz)
|
||||
Vitika Soni (Vitika9)
|
||||
박한얼 (volzhs)
|
||||
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)
|
||||
Yuri Roubinski (Chaosus)
|
||||
Zher Huei Lee (leezh)
|
||||
ZuBsPaCe
|
||||
风青山 (Rindbee)
|
||||
Дмитрий Сальников (DmitriySalnikov)
|
||||
|
||||
3062
CHANGELOG.md
3062
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
254
CONTRIBUTING.md
254
CONTRIBUTING.md
@ -1,178 +1,80 @@
|
||||
# How to contribute efficiently
|
||||
|
||||
## Table of contents
|
||||
Sections covered in this file:
|
||||
|
||||
- [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)
|
||||
* [Reporting bugs or proposing features](#reporting-bugs-or-proposing-features)
|
||||
* [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.
|
||||
|
||||
If you're reporting a new bug, you'll make our life simpler (and the
|
||||
fix will come sooner) by following these guidelines:
|
||||
Everything referred 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.
|
||||
|
||||
#### Specify the platform
|
||||
|
||||
Godot runs on a large variety of platforms and operating systems and devices.
|
||||
**In your bug reports, please always specify:**
|
||||
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)
|
||||
|
||||
For bugs that are likely OS-specific and/or graphics-related, please also specify:
|
||||
|
||||
- Device (CPU model including architecture, e.g. x86_64, arm64, etc.)
|
||||
- GPU model (and the driver version in use if you know it)
|
||||
|
||||
**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.
|
||||
|
||||
### Specify steps to reproduce
|
||||
#### 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.
|
||||
keep them as minimal as possible.
|
||||
|
||||
Making your bug report easy to reproduce will make it easier for contributors
|
||||
to fix the bug.
|
||||
#### Provide a simple, example project
|
||||
|
||||
### Provide a simple example project
|
||||
|
||||
Sometimes, unexpected behavior can happen in your project. In such case,
|
||||
Sometimes an unexpected behavior happens 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
|
||||
* 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.
|
||||
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
|
||||
* 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.
|
||||
|
||||
[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.
|
||||
|
||||
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.
|
||||
|
||||
### Document your changes
|
||||
|
||||
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.
|
||||
|
||||
[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).
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
When updating your fork with upstream changes, please use ``git pull --rebase``
|
||||
to avoid creating "merge commits". Those commits unnecessarily pollute the git
|
||||
@ -184,31 +86,30 @@ 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.
|
||||
This git style guide has some good practices to have in mind:
|
||||
[Git Style Guide](https://github.com/agis-/git-style-guide)
|
||||
|
||||
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 logs with readability in mind
|
||||
|
||||
### 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
|
||||
The way you format your commit logs is quite important to ensure that the
|
||||
commit history and changelog will be easy to read and understand. A git commit
|
||||
log 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 :)
|
||||
GitHub interface unless you click the "expand" button. As the name tells it,
|
||||
try to keep that first line relatively short (ideally <= 50 chars, though it's
|
||||
rare to be able to tell enough in so few characters, so you can go a bit
|
||||
higher) - 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 that you should probably split your
|
||||
changes in several commits :)
|
||||
|
||||
Here's an example of a well-formatted commit message (note how the extended
|
||||
Here's an example of a well-formatted commit log (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
|
||||
@ -222,9 +123,9 @@ 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.
|
||||
*Note:* When using the GitHub online editor (or worse, the drag and drop
|
||||
feature), *please* edit the commit title to something meaningful. Commits named
|
||||
"Update my_file.cpp" will not be accepted.
|
||||
|
||||
## Contributing to Godot's translation
|
||||
|
||||
@ -233,10 +134,6 @@ 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
|
||||
@ -245,23 +142,26 @@ 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
|
||||
- [GitHub issues](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 -
|
||||
all developers watch the repository and will get an email 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.
|
||||
- [#godotengine-devel IRC channel on
|
||||
Freenode](https://webchat.freenode.net/?channels=godotengine-devel): You will
|
||||
find most core developers there, so it's the go-to channel 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.
|
||||
- [devel@godotengine.org mailing
|
||||
list](https://listengine.tuxfamily.org/godotengine.org/devel/): Mailing list
|
||||
for Godot developers, used primarily to announce developer meetings on IRC
|
||||
and other important discussions that need to reach people directly in their
|
||||
mailbox. See the [index
|
||||
page](https://listengine.tuxfamily.org/godotengine.org/devel/) for
|
||||
subscription instructions.
|
||||
|
||||
Thanks for your interest in contributing!
|
||||
Thanks!
|
||||
|
||||
—The Godot development team
|
||||
The Godot development team
|
||||
|
||||
1692
COPYRIGHT.txt
1692
COPYRIGHT.txt
File diff suppressed because it is too large
Load Diff
21
ISSUE_TEMPLATE.md
Normal file
21
ISSUE_TEMPLATE.md
Normal file
@ -0,0 +1,21 @@
|
||||
<!-- Please search existing issues for potential duplicates before filing yours:
|
||||
https://github.com/godotengine/godot/issues?q=is%3Aissue
|
||||
-->
|
||||
|
||||
**Godot version:**
|
||||
<!-- Specify commit hash if non-official. -->
|
||||
|
||||
|
||||
**OS/device including version:**
|
||||
<!-- Specify GPU model and drivers if graphics-related. -->
|
||||
|
||||
|
||||
**Issue description:**
|
||||
<!-- What happened, and what was expected. -->
|
||||
|
||||
|
||||
**Steps to reproduce:**
|
||||
|
||||
|
||||
**Minimal reproduction project:**
|
||||
<!-- Recommended as it greatly speeds up debugging. Drag and drop a zip archive to upload it. -->
|
||||
@ -1,5 +1,5 @@
|
||||
Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md).
|
||||
Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.
|
||||
Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.
|
||||
Copyright (c) 2014-2018 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
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
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 Creative Commons Attribution License
|
||||
version 3.0 (CC-BY 3.0) <https://creativecommons.org/licenses/by/3.0/legalcode>.
|
||||
|
||||
79
README.md
79
README.md
@ -1,76 +1,69 @@
|
||||
# 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/development/compiling/)
|
||||
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/)
|
||||
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://travis-ci.org/godotengine/godot)
|
||||
[](https://ci.appveyor.com/project/akien-mga/godot)
|
||||
[](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)
|
||||
|
||||
1214
SConstruct
1214
SConstruct
File diff suppressed because it is too large
Load Diff
64
compat.py
Normal file
64
compat.py
Normal file
@ -0,0 +1,64 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3,):
|
||||
def isbasestring(s):
|
||||
return isinstance(s, basestring)
|
||||
def open_utf8(filename, mode):
|
||||
return open(filename, mode)
|
||||
def byte_to_str(x):
|
||||
return str(ord(x))
|
||||
import cStringIO
|
||||
def StringIO():
|
||||
return cStringIO.StringIO()
|
||||
def encode_utf8(x):
|
||||
return x
|
||||
def decode_utf8(x):
|
||||
return x
|
||||
def iteritems(d):
|
||||
return d.iteritems()
|
||||
def escape_string(s):
|
||||
if isinstance(s, unicode):
|
||||
s = s.encode('ascii')
|
||||
result = ''
|
||||
for c in s:
|
||||
if not (32 <= ord(c) < 127) or c in ('\\', '"'):
|
||||
result += '\\%03o' % ord(c)
|
||||
else:
|
||||
result += c
|
||||
return result
|
||||
|
||||
else:
|
||||
def isbasestring(s):
|
||||
return isinstance(s, (str, bytes))
|
||||
def open_utf8(filename, mode):
|
||||
return open(filename, mode, encoding="utf-8")
|
||||
def byte_to_str(x):
|
||||
return str(x)
|
||||
import io
|
||||
def StringIO():
|
||||
return io.StringIO()
|
||||
import codecs
|
||||
def encode_utf8(x):
|
||||
return codecs.utf_8_encode(x)[0]
|
||||
def decode_utf8(x):
|
||||
return codecs.utf_8_decode(x)[0]
|
||||
def iteritems(d):
|
||||
return iter(d.items())
|
||||
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))
|
||||
def escape_string(s):
|
||||
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
|
||||
|
||||
237
core/SCsub
237
core/SCsub
@ -1,207 +1,110 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
import core_builders
|
||||
Import('env')
|
||||
|
||||
env.core_sources = []
|
||||
|
||||
|
||||
# Generate global defaults
|
||||
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 "project_settings.h"\n'
|
||||
gd_cpp += gd_inc
|
||||
gd_cpp += "void ProjectSettings::register_global_defaults() {\n" + gd_call + "\n}\n"
|
||||
|
||||
f = open("global_defaults.gen.cpp", "w")
|
||||
f.write(gd_cpp)
|
||||
f.close()
|
||||
|
||||
|
||||
# Generate AES256 script encryption key
|
||||
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.gen.cpp", "w")
|
||||
f.write("#include \"project_settings.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
|
||||
# Add required 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_dir = "#thirdparty/misc/"
|
||||
thirdparty_sources = [
|
||||
# C sources
|
||||
"base64.c",
|
||||
"fastlz.c",
|
||||
"sha256.c",
|
||||
"smaz.c",
|
||||
|
||||
# C++ sources
|
||||
"aes256.cpp",
|
||||
"hq2x.cpp",
|
||||
"md5.cpp",
|
||||
"pcg.cpp",
|
||||
"triangulator.cpp",
|
||||
]
|
||||
thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_misc_sources]
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_misc_sources)
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
env.add_source_files(env.core_sources, thirdparty_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
|
||||
# Minizip library, can 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 = [
|
||||
"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)
|
||||
env.add_source_files(env.core_sources, 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)
|
||||
if 'builtin_zstd' in env and env['builtin_zstd']:
|
||||
SConscript("#thirdparty/zstd/SCsub")
|
||||
|
||||
|
||||
env.core_sources += thirdparty_obj
|
||||
|
||||
|
||||
# Godot source files
|
||||
|
||||
# Godot's own sources
|
||||
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.")
|
||||
)
|
||||
# Make binders
|
||||
import make_binders
|
||||
env.CommandNoCache(['method_bind.gen.inc', 'method_bind_ext.gen.inc'], 'make_binders.py', make_binders.run)
|
||||
|
||||
# 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")
|
||||
SConscript('os/SCsub')
|
||||
SConscript('math/SCsub')
|
||||
SConscript('io/SCsub')
|
||||
SConscript('bind/SCsub')
|
||||
SConscript('helper/SCsub')
|
||||
|
||||
|
||||
# Build it all as a library
|
||||
lib = env.add_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)
|
||||
Export('env')
|
||||
|
||||
194
core/allocators.h
Normal file
194
core/allocators.h
Normal file
@ -0,0 +1,194 @@
|
||||
/*************************************************************************/
|
||||
/* allocators.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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
|
||||
357
core/array.cpp
Normal file
357
core/array.cpp
Normal file
@ -0,0 +1,357 @@
|
||||
/*************************************************************************/
|
||||
/* array.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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;
|
||||
};
|
||||
|
||||
void Array::_ref(const Array &p_from) const {
|
||||
|
||||
ArrayPrivate *_fp = p_from._p;
|
||||
|
||||
ERR_FAIL_COND(!_fp); // should NOT happen.
|
||||
|
||||
if (_fp == _p)
|
||||
return; // whatever it is, nothing to do here move along
|
||||
|
||||
bool success = _fp->refcount.ref();
|
||||
|
||||
ERR_FAIL_COND(!success); // should really not happen either
|
||||
|
||||
_unref();
|
||||
|
||||
_p = p_from._p;
|
||||
}
|
||||
|
||||
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::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);
|
||||
}
|
||||
|
||||
Array Array::duplicate() const {
|
||||
|
||||
Array new_arr;
|
||||
int element_count = size();
|
||||
new_arr.resize(element_count);
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
new_arr[i] = get(i);
|
||||
}
|
||||
|
||||
return new_arr;
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
Array &Array::sort() {
|
||||
|
||||
_p->array.sort_custom<_ArrayVariantSort>();
|
||||
return *this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
|
||||
|
||||
ERR_FAIL_NULL_V(p_obj, *this);
|
||||
|
||||
SortArray<Variant, _ArrayVariantSortCustom> avs;
|
||||
avs.compare.obj = p_obj;
|
||||
avs.compare.func = p_function;
|
||||
avs.sort(_p->array.ptrw(), _p->array.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Less>
|
||||
_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
|
||||
|
||||
int lo = 0;
|
||||
int hi = p_array.size();
|
||||
if (p_before) {
|
||||
while (lo < hi) {
|
||||
const int mid = (lo + hi) / 2;
|
||||
if (p_less(p_array.get(mid), p_value)) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (lo < hi) {
|
||||
const int mid = (lo + hi) / 2;
|
||||
if (p_less(p_value, p_array.get(mid))) {
|
||||
hi = mid;
|
||||
} else {
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lo;
|
||||
}
|
||||
|
||||
int Array::bsearch(const Variant &p_value, bool p_before) {
|
||||
|
||||
return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
|
||||
}
|
||||
|
||||
int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {
|
||||
|
||||
ERR_FAIL_NULL_V(p_obj, 0);
|
||||
|
||||
_ArrayVariantSortCustom less;
|
||||
less.obj = p_obj;
|
||||
less.func = p_function;
|
||||
|
||||
return bisect(_p->array, p_value, p_before, less);
|
||||
}
|
||||
|
||||
Array &Array::invert() {
|
||||
|
||||
_p->array.invert();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Array::push_front(const Variant &p_value) {
|
||||
|
||||
_p->array.insert(0, p_value);
|
||||
}
|
||||
|
||||
Variant Array::pop_back() {
|
||||
|
||||
if (!_p->array.empty()) {
|
||||
int n = _p->array.size() - 1;
|
||||
Variant ret = _p->array.get(n);
|
||||
_p->array.resize(n);
|
||||
return ret;
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
Variant Array::pop_front() {
|
||||
|
||||
if (!_p->array.empty()) {
|
||||
Variant ret = _p->array.get(0);
|
||||
_p->array.remove(0);
|
||||
return ret;
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
Array::Array(const Array &p_from) {
|
||||
|
||||
_p = NULL;
|
||||
_ref(p_from);
|
||||
}
|
||||
Array::Array() {
|
||||
|
||||
_p = memnew(ArrayPrivate);
|
||||
_p->refcount.init();
|
||||
}
|
||||
Array::~Array() {
|
||||
|
||||
_unref();
|
||||
}
|
||||
97
core/array.h
Normal file
97
core/array.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*************************************************************************/
|
||||
/* array.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 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;
|
||||
|
||||
Array &sort();
|
||||
Array &sort_custom(Object *p_obj, const StringName &p_function);
|
||||
int bsearch(const Variant &p_value, bool p_before = true);
|
||||
int bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before = true);
|
||||
Array &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);
|
||||
Variant pop_back();
|
||||
Variant pop_front();
|
||||
|
||||
Array duplicate() const;
|
||||
|
||||
Array(const Array &p_from);
|
||||
Array();
|
||||
~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')
|
||||
2793
core/bind/core_bind.cpp
Normal file
2793
core/bind/core_bind.cpp
Normal file
File diff suppressed because it is too large
Load Diff
737
core/bind/core_bind.h
Normal file
737
core/bind/core_bind.h
Normal file
@ -0,0 +1,737 @@
|
||||
/*************************************************************************/
|
||||
/* core_bind.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 "image.h"
|
||||
#include "io/compression.h"
|
||||
#include "io/resource_loader.h"
|
||||
#include "io/resource_saver.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/file_access.h"
|
||||
#include "os/os.h"
|
||||
#include "os/semaphore.h"
|
||||
#include "os/thread.h"
|
||||
|
||||
class _ResourceLoader : public Object {
|
||||
GDCLASS(_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);
|
||||
PoolVector<String> get_recognized_extensions_for_type(const String &p_type);
|
||||
void set_abort_on_missing_resources(bool p_abort);
|
||||
PoolStringArray get_dependencies(const String &p_path);
|
||||
bool has(const String &p_path);
|
||||
|
||||
_ResourceLoader();
|
||||
};
|
||||
|
||||
class _ResourceSaver : public Object {
|
||||
GDCLASS(_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);
|
||||
PoolVector<String> get_recognized_extensions(const RES &p_resource);
|
||||
|
||||
_ResourceSaver();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_ResourceSaver::SaverFlags);
|
||||
|
||||
class MainLoop;
|
||||
|
||||
class _OS : public Object {
|
||||
GDCLASS(_OS, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _OS *singleton;
|
||||
|
||||
public:
|
||||
enum PowerState {
|
||||
POWERSTATE_UNKNOWN, /**< cannot determine power status */
|
||||
POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
|
||||
POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
|
||||
POWERSTATE_CHARGING, /**< Plugged in, charging battery */
|
||||
POWERSTATE_CHARGED /**< Plugged in, battery charged */
|
||||
};
|
||||
|
||||
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_position() 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 = -1) const;
|
||||
virtual Size2 get_screen_size(int p_screen = -1) const;
|
||||
virtual int get_screen_dpi(int p_screen = -1) const;
|
||||
virtual Point2 get_window_position() const;
|
||||
virtual void set_window_position(const Point2 &p_position);
|
||||
virtual Size2 get_window_size() const;
|
||||
virtual Size2 get_real_window_size() const;
|
||||
virtual Rect2 get_window_safe_area() 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 set_window_always_on_top(bool p_enabled);
|
||||
virtual bool is_window_always_on_top() const;
|
||||
virtual void request_attention();
|
||||
virtual void center_window();
|
||||
|
||||
virtual void set_borderless_window(bool p_borderless);
|
||||
virtual bool get_borderless_window() const;
|
||||
|
||||
virtual void set_ime_position(const Point2 &p_pos);
|
||||
|
||||
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_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;
|
||||
|
||||
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();
|
||||
int get_virtual_keyboard_height();
|
||||
|
||||
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 Ref<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;
|
||||
|
||||
bool is_userfs_persistent() const;
|
||||
|
||||
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_user_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;
|
||||
|
||||
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;
|
||||
|
||||
PowerState get_power_state();
|
||||
int get_power_seconds_left();
|
||||
int get_power_percent_left();
|
||||
|
||||
bool has_feature(const String &p_feature) const;
|
||||
|
||||
static _OS *get_singleton() { return singleton; }
|
||||
|
||||
_OS();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_OS::PowerState);
|
||||
VARIANT_ENUM_CAST(_OS::Weekday);
|
||||
VARIANT_ENUM_CAST(_OS::Month);
|
||||
VARIANT_ENUM_CAST(_OS::SystemDir);
|
||||
VARIANT_ENUM_CAST(_OS::ScreenOrientation);
|
||||
|
||||
class _Geometry : public Object {
|
||||
|
||||
GDCLASS(_Geometry, Object);
|
||||
|
||||
static _Geometry *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static _Geometry *get_singleton();
|
||||
PoolVector<Plane> build_box_planes(const Vector3 &p_extents);
|
||||
PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z);
|
||||
PoolVector<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);
|
||||
PoolVector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2);
|
||||
PoolVector<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;
|
||||
|
||||
PoolVector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius);
|
||||
PoolVector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius);
|
||||
PoolVector<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);
|
||||
Vector<Point2> convex_hull_2d(const Vector<Point2> &p_points);
|
||||
Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane);
|
||||
|
||||
Dictionary make_atlas(const Vector<Size2> &p_rects);
|
||||
|
||||
_Geometry();
|
||||
};
|
||||
|
||||
class _File : public Reference {
|
||||
|
||||
GDCLASS(_File, Reference);
|
||||
FileAccess *f;
|
||||
bool eswap;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum ModeFlags {
|
||||
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
READ_WRITE = 3,
|
||||
WRITE_READ = 7,
|
||||
};
|
||||
|
||||
enum CompressionMode {
|
||||
COMPRESSION_FASTLZ = Compression::MODE_FASTLZ,
|
||||
COMPRESSION_DEFLATE = Compression::MODE_DEFLATE,
|
||||
COMPRESSION_ZSTD = Compression::MODE_ZSTD,
|
||||
COMPRESSION_GZIP = Compression::MODE_GZIP
|
||||
};
|
||||
|
||||
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_compressed(const String &p_path, int p_mode_flags, int p_compress_mode = 0);
|
||||
|
||||
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
|
||||
|
||||
String get_path() const; /// returns the path for the current open file
|
||||
String get_path_absolute() const; /// returns the absolute path for the current open file
|
||||
|
||||
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_position() 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;
|
||||
|
||||
PoolVector<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 PoolVector<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();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_File::ModeFlags);
|
||||
VARIANT_ENUM_CAST(_File::CompressionMode);
|
||||
|
||||
class _Directory : public Reference {
|
||||
|
||||
GDCLASS(_Directory, Reference);
|
||||
DirAccess *d;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Error open(const String &p_path);
|
||||
|
||||
Error list_dir_begin(bool p_skip_navigational = false, bool p_skip_hidden = false); ///< 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);
|
||||
int get_current_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();
|
||||
|
||||
private:
|
||||
bool _list_skip_navigational;
|
||||
bool _list_skip_hidden;
|
||||
};
|
||||
|
||||
class _Marshalls : public Reference {
|
||||
|
||||
GDCLASS(_Marshalls, Reference);
|
||||
|
||||
static _Marshalls *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static _Marshalls *get_singleton();
|
||||
|
||||
String variant_to_base64(const Variant &p_var);
|
||||
Variant base64_to_variant(const String &p_str);
|
||||
|
||||
String raw_to_base64(const PoolVector<uint8_t> &p_arr);
|
||||
PoolVector<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 = NULL; }
|
||||
};
|
||||
|
||||
class _Mutex : public Reference {
|
||||
|
||||
GDCLASS(_Mutex, Reference);
|
||||
Mutex *mutex;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void lock();
|
||||
Error try_lock();
|
||||
void unlock();
|
||||
|
||||
_Mutex();
|
||||
~_Mutex();
|
||||
};
|
||||
|
||||
class _Semaphore : public Reference {
|
||||
|
||||
GDCLASS(_Semaphore, Reference);
|
||||
Semaphore *semaphore;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Error wait();
|
||||
Error post();
|
||||
|
||||
_Semaphore();
|
||||
~_Semaphore();
|
||||
};
|
||||
|
||||
class _Thread : public Reference {
|
||||
|
||||
GDCLASS(_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();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(_Thread::Priority);
|
||||
|
||||
class _ClassDB : public Object {
|
||||
|
||||
GDCLASS(_ClassDB, Object)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
PoolStringArray get_class_list() const;
|
||||
PoolStringArray 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_instance(const StringName &p_class) const;
|
||||
Variant instance(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;
|
||||
Array get_signal_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
|
||||
Array 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;
|
||||
|
||||
Array get_method_list(StringName p_class, bool p_no_inheritance = false) const;
|
||||
|
||||
PoolStringArray 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;
|
||||
int get_integer_constant(const StringName &p_class, const StringName &p_name) const;
|
||||
StringName get_category(const StringName &p_node) const;
|
||||
|
||||
bool is_class_enabled(StringName p_class) const;
|
||||
|
||||
_ClassDB();
|
||||
~_ClassDB();
|
||||
};
|
||||
|
||||
class _Engine : public Object {
|
||||
GDCLASS(_Engine, Object);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _Engine *singleton;
|
||||
|
||||
public:
|
||||
static _Engine *get_singleton() { return singleton; }
|
||||
void set_iterations_per_second(int p_ips);
|
||||
int get_iterations_per_second() const;
|
||||
|
||||
void set_target_fps(int p_fps);
|
||||
int get_target_fps() const;
|
||||
|
||||
float get_frames_per_second() const;
|
||||
|
||||
int get_frames_drawn();
|
||||
|
||||
void set_time_scale(float p_scale);
|
||||
float get_time_scale();
|
||||
|
||||
MainLoop *get_main_loop() const;
|
||||
|
||||
Dictionary get_version_info() const;
|
||||
|
||||
bool is_in_physics_frame() const;
|
||||
|
||||
bool has_singleton(const String &p_name) const;
|
||||
Object *get_singleton_object(const String &p_name) const;
|
||||
|
||||
void set_editor_hint(bool p_enabled);
|
||||
bool is_editor_hint() const;
|
||||
|
||||
_Engine();
|
||||
};
|
||||
|
||||
class _JSON;
|
||||
|
||||
class JSONParseResult : public Reference {
|
||||
GDCLASS(JSONParseResult, Reference)
|
||||
|
||||
friend class _JSON;
|
||||
|
||||
Error error;
|
||||
String error_string;
|
||||
int error_line;
|
||||
|
||||
Variant result;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_error(Error p_error);
|
||||
Error get_error() const;
|
||||
|
||||
void set_error_string(const String &p_error_string);
|
||||
String get_error_string() const;
|
||||
|
||||
void set_error_line(int p_error_line);
|
||||
int get_error_line() const;
|
||||
|
||||
void set_result(const Variant &p_result);
|
||||
Variant get_result() const;
|
||||
};
|
||||
|
||||
class _JSON : public Object {
|
||||
GDCLASS(_JSON, Object)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static _JSON *singleton;
|
||||
|
||||
public:
|
||||
static _JSON *get_singleton() { return singleton; }
|
||||
|
||||
String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false);
|
||||
Ref<JSONParseResult> parse(const String &p_json);
|
||||
|
||||
_JSON();
|
||||
};
|
||||
|
||||
#endif // CORE_BIND_H
|
||||
1415
core/class_db.cpp
Normal file
1415
core/class_db.cpp
Normal file
File diff suppressed because it is too large
Load Diff
400
core/class_db.h
Normal file
400
core/class_db.h
Normal file
@ -0,0 +1,400 @@
|
||||
/*************************************************************************/
|
||||
/* class_db.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 CLASS_DB_H
|
||||
#define CLASS_DB_H
|
||||
|
||||
#include "method_bind.h"
|
||||
#include "object.h"
|
||||
#include "print_string.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
#define DEFVAL(m_defval) (m_defval)
|
||||
|
||||
//#define SIMPLE_METHODDEF
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
||||
struct MethodDefinition {
|
||||
|
||||
StringName name;
|
||||
Vector<StringName> args;
|
||||
MethodDefinition() {}
|
||||
MethodDefinition(const char *p_name) :
|
||||
name(p_name) {}
|
||||
MethodDefinition(const StringName &p_name) :
|
||||
name(p_name) {}
|
||||
};
|
||||
|
||||
MethodDefinition D_METHOD(const char *p_name);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12);
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13);
|
||||
|
||||
#else
|
||||
|
||||
//#define NO_VARIADIC_MACROS
|
||||
|
||||
#ifdef NO_VARIADIC_MACROS
|
||||
|
||||
static _FORCE_INLINE_ const char *D_METHOD(const char *m_name, ...) {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// When DEBUG_METHODS_ENABLED is set this will let the engine know
|
||||
// the argument names for easier debugging.
|
||||
#define D_METHOD(m_c, ...) m_c
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
class ClassDB {
|
||||
public:
|
||||
enum APIType {
|
||||
API_CORE,
|
||||
API_EDITOR,
|
||||
API_NONE
|
||||
};
|
||||
|
||||
public:
|
||||
struct PropertySetGet {
|
||||
|
||||
int index;
|
||||
StringName setter;
|
||||
StringName getter;
|
||||
MethodBind *_setptr;
|
||||
MethodBind *_getptr;
|
||||
Variant::Type type;
|
||||
};
|
||||
|
||||
struct ClassInfo {
|
||||
|
||||
APIType api;
|
||||
ClassInfo *inherits_ptr;
|
||||
HashMap<StringName, MethodBind *, StringNameHasher> method_map;
|
||||
HashMap<StringName, int, StringNameHasher> constant_map;
|
||||
HashMap<StringName, MethodInfo, StringNameHasher> signal_map;
|
||||
List<PropertyInfo> property_list;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
HashMap<StringName, List<StringName> > enum_map;
|
||||
List<StringName> constant_order;
|
||||
List<StringName> method_order;
|
||||
Set<StringName> methods_in_properties;
|
||||
List<MethodInfo> virtual_methods;
|
||||
StringName category;
|
||||
#endif
|
||||
HashMap<StringName, PropertySetGet, StringNameHasher> property_setget;
|
||||
|
||||
StringName inherits;
|
||||
StringName name;
|
||||
bool disabled;
|
||||
bool exposed;
|
||||
Object *(*creation_func)();
|
||||
ClassInfo();
|
||||
~ClassInfo();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
static Object *creator() {
|
||||
return memnew(T);
|
||||
}
|
||||
|
||||
static RWLock *lock;
|
||||
static HashMap<StringName, ClassInfo, StringNameHasher> classes;
|
||||
static HashMap<StringName, StringName, StringNameHasher> resource_base_extensions;
|
||||
static HashMap<StringName, StringName, StringNameHasher> compat_classes;
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount);
|
||||
#else
|
||||
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount);
|
||||
#endif
|
||||
|
||||
static APIType current_api;
|
||||
|
||||
static void _add_class2(const StringName &p_class, const StringName &p_inherits);
|
||||
|
||||
public:
|
||||
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
|
||||
template <class T>
|
||||
static void _add_class() {
|
||||
|
||||
_add_class2(T::get_class_static(), T::get_parent_class_static());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void register_class() {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
ERR_FAIL_COND(!t);
|
||||
t->creation_func = &creator<T>;
|
||||
t->exposed = true;
|
||||
T::register_custom_data_to_otdb();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void register_virtual_class() {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
ERR_FAIL_COND(!t);
|
||||
t->exposed = true;
|
||||
//nothing
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static Object *_create_ptr_func() {
|
||||
|
||||
return T::create();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void register_custom_instance_class() {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
T::initialize_class();
|
||||
ClassInfo *t = classes.getptr(T::get_class_static());
|
||||
ERR_FAIL_COND(!t);
|
||||
t->creation_func = &_create_ptr_func<T>;
|
||||
t->exposed = true;
|
||||
T::register_custom_data_to_otdb();
|
||||
}
|
||||
|
||||
static void get_class_list(List<StringName> *p_classes);
|
||||
static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
|
||||
static StringName get_parent_class_nocheck(const StringName &p_class);
|
||||
static StringName get_parent_class(const StringName &p_class);
|
||||
static bool class_exists(const StringName &p_class);
|
||||
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
|
||||
static bool can_instance(const StringName &p_class);
|
||||
static Object *instance(const StringName &p_class);
|
||||
static APIType get_api_type(const StringName &p_class);
|
||||
|
||||
static uint64_t get_api_hash(APIType p_api);
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, NULL, 0); //use static function, much smaller binary usage
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[1] = { &p_def1 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 1);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[2] = { &p_def1, &p_def2 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 2);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 3);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 4);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 5);
|
||||
}
|
||||
|
||||
template <class N, class M>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) {
|
||||
|
||||
MethodBind *bind = create_method_bind(p_method);
|
||||
const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 };
|
||||
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, ptr, 6);
|
||||
}
|
||||
|
||||
template <class M>
|
||||
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>()) {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
|
||||
MethodBind *bind = create_vararg_method_bind(p_method, p_info);
|
||||
ERR_FAIL_COND_V(!bind, NULL);
|
||||
|
||||
bind->set_name(p_name);
|
||||
bind->set_default_arguments(p_default_args);
|
||||
|
||||
String instance_type = bind->get_instance_class();
|
||||
|
||||
ClassInfo *type = classes.getptr(instance_type);
|
||||
if (!type) {
|
||||
memdelete(bind);
|
||||
ERR_FAIL_COND_V(!type, NULL);
|
||||
}
|
||||
|
||||
if (type->method_map.has(p_name)) {
|
||||
memdelete(bind);
|
||||
// overloading not supported
|
||||
ERR_EXPLAIN("Method already bound: " + instance_type + "::" + p_name);
|
||||
ERR_FAIL_V(NULL);
|
||||
}
|
||||
type->method_map[p_name] = bind;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
// FIXME: <reduz> set_return_type is no longer in MethodBind, so I guess it should be moved to vararg method bind
|
||||
//bind->set_return_type("Variant");
|
||||
type->method_order.push_back(p_name);
|
||||
#endif
|
||||
|
||||
return bind;
|
||||
}
|
||||
|
||||
static void add_signal(StringName p_class, const MethodInfo &p_signal);
|
||||
static bool has_signal(StringName p_class, StringName p_signal);
|
||||
static bool get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal);
|
||||
static void get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance = false);
|
||||
|
||||
static void add_property_group(StringName p_class, const String &p_name, const String &p_prefix = "");
|
||||
static void add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
|
||||
static void get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance = false, const Object *p_validator = NULL);
|
||||
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = NULL);
|
||||
static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
|
||||
static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
|
||||
static int get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
|
||||
static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
|
||||
static StringName get_property_setter(StringName p_class, const StringName p_property);
|
||||
static StringName get_property_getter(StringName p_class, const StringName p_property);
|
||||
|
||||
static bool has_method(StringName p_class, StringName p_method, bool p_no_inheritance = false);
|
||||
static void set_method_flags(StringName p_class, StringName p_method, int p_flags);
|
||||
|
||||
static void get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
||||
static MethodBind *get_method(StringName p_class, StringName p_name);
|
||||
|
||||
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true);
|
||||
static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
|
||||
|
||||
static void bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int p_constant);
|
||||
static void get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance = false);
|
||||
static int get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success = NULL);
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
static StringName get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
|
||||
static void get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance = false);
|
||||
static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false);
|
||||
#endif
|
||||
|
||||
static StringName get_category(const StringName &p_node);
|
||||
|
||||
static void set_class_enabled(StringName p_class, bool p_enable);
|
||||
static bool is_class_enabled(StringName p_class);
|
||||
|
||||
static bool is_class_exposed(StringName p_class);
|
||||
|
||||
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
|
||||
static void get_resource_base_extensions(List<String> *p_extensions);
|
||||
static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
|
||||
|
||||
static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback);
|
||||
static void init();
|
||||
|
||||
static void set_current_api(APIType p_api);
|
||||
static void cleanup();
|
||||
};
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
|
||||
#define BIND_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
|
||||
|
||||
#else
|
||||
|
||||
#define BIND_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
#define BIND_VMETHOD(m_method) \
|
||||
ClassDB::add_virtual_method(get_class_static(), m_method);
|
||||
|
||||
#else
|
||||
|
||||
#define BIND_VMETHOD(m_method)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CLASS_DB_H
|
||||
529
core/color.cpp
Normal file
529
core/color.cpp
Normal file
@ -0,0 +1,529 @@
|
||||
/*************************************************************************/
|
||||
/* color.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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_abgr32() const {
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_rgba32() const {
|
||||
|
||||
uint32_t c = (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(a * 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);
|
||||
if (color.length() == 3 || color.length() == 4) {
|
||||
String exp_color;
|
||||
for (int i = 0; i < color.length(); i++) {
|
||||
exp_color += color[i];
|
||||
exp_color += color[i];
|
||||
}
|
||||
color = exp_color;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Color Color::operator+(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r + p_color.r,
|
||||
g + p_color.g,
|
||||
b + p_color.b,
|
||||
a + p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator+=(const Color &p_color) {
|
||||
|
||||
r = r + p_color.r;
|
||||
g = g + p_color.g;
|
||||
b = b + p_color.b;
|
||||
a = a + p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator-(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r - p_color.r,
|
||||
g - p_color.g,
|
||||
b - p_color.b,
|
||||
a - p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator-=(const Color &p_color) {
|
||||
|
||||
r = r - p_color.r;
|
||||
g = g - p_color.g;
|
||||
b = b - p_color.b;
|
||||
a = a - p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator*(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r * p_color.r,
|
||||
g * p_color.g,
|
||||
b * p_color.b,
|
||||
a * p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator*(const real_t &rvalue) const {
|
||||
|
||||
return Color(
|
||||
r * rvalue,
|
||||
g * rvalue,
|
||||
b * rvalue,
|
||||
a * rvalue);
|
||||
}
|
||||
|
||||
void Color::operator*=(const Color &p_color) {
|
||||
|
||||
r = r * p_color.r;
|
||||
g = g * p_color.g;
|
||||
b = b * p_color.b;
|
||||
a = a * p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator*=(const real_t &rvalue) {
|
||||
|
||||
r = r * rvalue;
|
||||
g = g * rvalue;
|
||||
b = b * rvalue;
|
||||
a = a * rvalue;
|
||||
}
|
||||
|
||||
Color Color::operator/(const Color &p_color) const {
|
||||
|
||||
return Color(
|
||||
r / p_color.r,
|
||||
g / p_color.g,
|
||||
b / p_color.b,
|
||||
a / p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator/(const real_t &rvalue) const {
|
||||
|
||||
return Color(
|
||||
r / rvalue,
|
||||
g / rvalue,
|
||||
b / rvalue,
|
||||
a / rvalue);
|
||||
}
|
||||
|
||||
void Color::operator/=(const Color &p_color) {
|
||||
|
||||
r = r / p_color.r;
|
||||
g = g / p_color.g;
|
||||
b = b / p_color.b;
|
||||
a = a / p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator/=(const real_t &rvalue) {
|
||||
|
||||
if (rvalue == 0) {
|
||||
r = 1.0;
|
||||
g = 1.0;
|
||||
b = 1.0;
|
||||
a = 1.0;
|
||||
} else {
|
||||
r = r / rvalue;
|
||||
g = g / rvalue;
|
||||
b = b / rvalue;
|
||||
a = a / rvalue;
|
||||
}
|
||||
};
|
||||
|
||||
Color Color::operator-() const {
|
||||
|
||||
return Color(
|
||||
1.0 - r,
|
||||
1.0 - g,
|
||||
1.0 - b,
|
||||
1.0 - a);
|
||||
}
|
||||
232
core/color.h
Normal file
232
core/color.h
Normal file
@ -0,0 +1,232 @@
|
||||
/*************************************************************************/
|
||||
/* color.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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_rgba32() const;
|
||||
uint32_t to_argb32() const;
|
||||
uint32_t to_abgr32() 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];
|
||||
}
|
||||
|
||||
Color operator+(const Color &p_color) const;
|
||||
void operator+=(const Color &p_color);
|
||||
|
||||
Color operator-() const;
|
||||
Color operator-(const Color &p_color) const;
|
||||
void operator-=(const Color &p_color);
|
||||
|
||||
Color operator*(const Color &p_color) const;
|
||||
Color operator*(const real_t &rvalue) const;
|
||||
void operator*=(const Color &p_color);
|
||||
void operator*=(const real_t &rvalue);
|
||||
|
||||
Color operator/(const Color &p_color) const;
|
||||
Color operator/(const real_t &rvalue) const;
|
||||
void operator/=(const Color &p_color);
|
||||
void operator/=(const real_t &rvalue);
|
||||
|
||||
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 darkened(float p_amount) const {
|
||||
|
||||
Color res = *this;
|
||||
res.r = res.r * (1.0f - p_amount);
|
||||
res.g = res.g * (1.0f - p_amount);
|
||||
res.b = res.b * (1.0f - p_amount);
|
||||
return res;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Color lightened(float p_amount) const {
|
||||
|
||||
Color res = *this;
|
||||
res.r = res.r + (1.0f - res.r) * p_amount;
|
||||
res.g = res.g + (1.0f - res.g) * p_amount;
|
||||
res.b = res.b + (1.0f - res.b) * p_amount;
|
||||
return res;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
|
||||
|
||||
const float pow2to9 = 512.0f;
|
||||
const float B = 15.0f;
|
||||
//const float Emax = 31.0f;
|
||||
const float N = 9.0f;
|
||||
|
||||
float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);
|
||||
|
||||
float cRed = MAX(0.0f, MIN(sharedexp, r));
|
||||
float cGreen = MAX(0.0f, MIN(sharedexp, g));
|
||||
float cBlue = MAX(0.0f, MIN(sharedexp, b));
|
||||
|
||||
float cMax = MAX(cRed, MAX(cGreen, cBlue));
|
||||
|
||||
// expp = MAX(-B - 1, log2(maxc)) + 1 + B
|
||||
|
||||
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
|
||||
|
||||
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
|
||||
|
||||
float exps = expp + 1.0f;
|
||||
|
||||
if (0.0 <= sMax && sMax < pow2to9) {
|
||||
exps = expp;
|
||||
}
|
||||
|
||||
float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
|
||||
|
||||
return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
|
||||
}
|
||||
|
||||
_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);
|
||||
}
|
||||
_FORCE_INLINE_ Color to_srgb() const {
|
||||
|
||||
return Color(
|
||||
r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
|
||||
g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
|
||||
b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, 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));
|
||||
}
|
||||
130
core/command_queue_mt.cpp
Normal file
130
core/command_queue_mt.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
/*************************************************************************/
|
||||
/* command_queue_mt.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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) {
|
||||
|
||||
lock();
|
||||
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
|
||||
|
||||
if (!sync_sems[i].in_use) {
|
||||
sync_sems[i].in_use = true;
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
|
||||
if (idx == -1) {
|
||||
wait_for_flush();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return &sync_sems[idx];
|
||||
}
|
||||
|
||||
bool CommandQueueMT::dealloc_one() {
|
||||
tryagain:
|
||||
if (dealloc_ptr == write_ptr) {
|
||||
// The queue is empty
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t size = *(uint32_t *)&command_mem[dealloc_ptr];
|
||||
|
||||
if (size == 0) {
|
||||
// End of command buffer wrap down
|
||||
dealloc_ptr = 0;
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
if (size & 1) {
|
||||
// Still used, nothing can be deallocated
|
||||
return false;
|
||||
}
|
||||
|
||||
dealloc_ptr += (size >> 1) + sizeof(uint32_t);
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
480
core/command_queue_mt.h
Normal file
480
core/command_queue_mt.h
Normal file
@ -0,0 +1,480 @@
|
||||
/*************************************************************************/
|
||||
/* command_queue_mt.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 COMMAND_QUEUE_MT_H
|
||||
#define COMMAND_QUEUE_MT_H
|
||||
|
||||
#include "os/memory.h"
|
||||
#include "os/mutex.h"
|
||||
#include "os/semaphore.h"
|
||||
#include "simple_type.h"
|
||||
#include "typedefs.h"
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
#define COMMA(N) _COMMA_##N
|
||||
#define _COMMA_0
|
||||
#define _COMMA_1 ,
|
||||
#define _COMMA_2 ,
|
||||
#define _COMMA_3 ,
|
||||
#define _COMMA_4 ,
|
||||
#define _COMMA_5 ,
|
||||
#define _COMMA_6 ,
|
||||
#define _COMMA_7 ,
|
||||
#define _COMMA_8 ,
|
||||
#define _COMMA_9 ,
|
||||
#define _COMMA_10 ,
|
||||
#define _COMMA_11 ,
|
||||
#define _COMMA_12 ,
|
||||
|
||||
// 1-based comma separated list of ITEMs
|
||||
#define COMMA_SEP_LIST(ITEM, LENGTH) _COMMA_SEP_LIST_##LENGTH(ITEM)
|
||||
#define _COMMA_SEP_LIST_12(ITEM) \
|
||||
_COMMA_SEP_LIST_11(ITEM) \
|
||||
, ITEM(12)
|
||||
#define _COMMA_SEP_LIST_11(ITEM) \
|
||||
_COMMA_SEP_LIST_10(ITEM) \
|
||||
, ITEM(11)
|
||||
#define _COMMA_SEP_LIST_10(ITEM) \
|
||||
_COMMA_SEP_LIST_9(ITEM) \
|
||||
, ITEM(10)
|
||||
#define _COMMA_SEP_LIST_9(ITEM) \
|
||||
_COMMA_SEP_LIST_8(ITEM) \
|
||||
, ITEM(9)
|
||||
#define _COMMA_SEP_LIST_8(ITEM) \
|
||||
_COMMA_SEP_LIST_7(ITEM) \
|
||||
, ITEM(8)
|
||||
#define _COMMA_SEP_LIST_7(ITEM) \
|
||||
_COMMA_SEP_LIST_6(ITEM) \
|
||||
, ITEM(7)
|
||||
#define _COMMA_SEP_LIST_6(ITEM) \
|
||||
_COMMA_SEP_LIST_5(ITEM) \
|
||||
, ITEM(6)
|
||||
#define _COMMA_SEP_LIST_5(ITEM) \
|
||||
_COMMA_SEP_LIST_4(ITEM) \
|
||||
, ITEM(5)
|
||||
#define _COMMA_SEP_LIST_4(ITEM) \
|
||||
_COMMA_SEP_LIST_3(ITEM) \
|
||||
, ITEM(4)
|
||||
#define _COMMA_SEP_LIST_3(ITEM) \
|
||||
_COMMA_SEP_LIST_2(ITEM) \
|
||||
, ITEM(3)
|
||||
#define _COMMA_SEP_LIST_2(ITEM) \
|
||||
_COMMA_SEP_LIST_1(ITEM) \
|
||||
, ITEM(2)
|
||||
#define _COMMA_SEP_LIST_1(ITEM) \
|
||||
_COMMA_SEP_LIST_0(ITEM) \
|
||||
ITEM(1)
|
||||
#define _COMMA_SEP_LIST_0(ITEM)
|
||||
|
||||
// 1-based semicolon separated list of ITEMs
|
||||
#define SEMIC_SEP_LIST(ITEM, LENGTH) _SEMIC_SEP_LIST_##LENGTH(ITEM)
|
||||
#define _SEMIC_SEP_LIST_12(ITEM) \
|
||||
_SEMIC_SEP_LIST_11(ITEM); \
|
||||
ITEM(12)
|
||||
#define _SEMIC_SEP_LIST_11(ITEM) \
|
||||
_SEMIC_SEP_LIST_10(ITEM); \
|
||||
ITEM(11)
|
||||
#define _SEMIC_SEP_LIST_10(ITEM) \
|
||||
_SEMIC_SEP_LIST_9(ITEM); \
|
||||
ITEM(10)
|
||||
#define _SEMIC_SEP_LIST_9(ITEM) \
|
||||
_SEMIC_SEP_LIST_8(ITEM); \
|
||||
ITEM(9)
|
||||
#define _SEMIC_SEP_LIST_8(ITEM) \
|
||||
_SEMIC_SEP_LIST_7(ITEM); \
|
||||
ITEM(8)
|
||||
#define _SEMIC_SEP_LIST_7(ITEM) \
|
||||
_SEMIC_SEP_LIST_6(ITEM); \
|
||||
ITEM(7)
|
||||
#define _SEMIC_SEP_LIST_6(ITEM) \
|
||||
_SEMIC_SEP_LIST_5(ITEM); \
|
||||
ITEM(6)
|
||||
#define _SEMIC_SEP_LIST_5(ITEM) \
|
||||
_SEMIC_SEP_LIST_4(ITEM); \
|
||||
ITEM(5)
|
||||
#define _SEMIC_SEP_LIST_4(ITEM) \
|
||||
_SEMIC_SEP_LIST_3(ITEM); \
|
||||
ITEM(4)
|
||||
#define _SEMIC_SEP_LIST_3(ITEM) \
|
||||
_SEMIC_SEP_LIST_2(ITEM); \
|
||||
ITEM(3)
|
||||
#define _SEMIC_SEP_LIST_2(ITEM) \
|
||||
_SEMIC_SEP_LIST_1(ITEM); \
|
||||
ITEM(2)
|
||||
#define _SEMIC_SEP_LIST_1(ITEM) \
|
||||
_SEMIC_SEP_LIST_0(ITEM) \
|
||||
ITEM(1)
|
||||
#define _SEMIC_SEP_LIST_0(ITEM)
|
||||
|
||||
// 1-based space separated list of ITEMs
|
||||
#define SPACE_SEP_LIST(ITEM, LENGTH) _SPACE_SEP_LIST_##LENGTH(ITEM)
|
||||
#define _SPACE_SEP_LIST_12(ITEM) \
|
||||
_SPACE_SEP_LIST_11(ITEM) \
|
||||
ITEM(12)
|
||||
#define _SPACE_SEP_LIST_11(ITEM) \
|
||||
_SPACE_SEP_LIST_10(ITEM) \
|
||||
ITEM(11)
|
||||
#define _SPACE_SEP_LIST_10(ITEM) \
|
||||
_SPACE_SEP_LIST_9(ITEM) \
|
||||
ITEM(10)
|
||||
#define _SPACE_SEP_LIST_9(ITEM) \
|
||||
_SPACE_SEP_LIST_8(ITEM) \
|
||||
ITEM(9)
|
||||
#define _SPACE_SEP_LIST_8(ITEM) \
|
||||
_SPACE_SEP_LIST_7(ITEM) \
|
||||
ITEM(8)
|
||||
#define _SPACE_SEP_LIST_7(ITEM) \
|
||||
_SPACE_SEP_LIST_6(ITEM) \
|
||||
ITEM(7)
|
||||
#define _SPACE_SEP_LIST_6(ITEM) \
|
||||
_SPACE_SEP_LIST_5(ITEM) \
|
||||
ITEM(6)
|
||||
#define _SPACE_SEP_LIST_5(ITEM) \
|
||||
_SPACE_SEP_LIST_4(ITEM) \
|
||||
ITEM(5)
|
||||
#define _SPACE_SEP_LIST_4(ITEM) \
|
||||
_SPACE_SEP_LIST_3(ITEM) \
|
||||
ITEM(4)
|
||||
#define _SPACE_SEP_LIST_3(ITEM) \
|
||||
_SPACE_SEP_LIST_2(ITEM) \
|
||||
ITEM(3)
|
||||
#define _SPACE_SEP_LIST_2(ITEM) \
|
||||
_SPACE_SEP_LIST_1(ITEM) \
|
||||
ITEM(2)
|
||||
#define _SPACE_SEP_LIST_1(ITEM) \
|
||||
_SPACE_SEP_LIST_0(ITEM) \
|
||||
ITEM(1)
|
||||
#define _SPACE_SEP_LIST_0(ITEM)
|
||||
|
||||
#define ARG(N) p##N
|
||||
#define PARAM(N) P##N p##N
|
||||
#define TYPE_PARAM(N) class P##N
|
||||
#define PARAM_DECL(N) typename GetSimpleTypeT<P##N>::type_t p##N
|
||||
|
||||
#define DECL_CMD(N) \
|
||||
template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
|
||||
struct Command##N : public CommandBase { \
|
||||
T *instance; \
|
||||
M method; \
|
||||
SEMIC_SEP_LIST(PARAM_DECL, N); \
|
||||
virtual void call() { \
|
||||
(instance->*method)(COMMA_SEP_LIST(ARG, N)); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECL_CMD_RET(N) \
|
||||
template <class T, class M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) class R> \
|
||||
struct CommandRet##N : public SyncCommand { \
|
||||
R *ret; \
|
||||
T *instance; \
|
||||
M method; \
|
||||
SEMIC_SEP_LIST(PARAM_DECL, N); \
|
||||
virtual void call() { \
|
||||
*ret = (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECL_CMD_SYNC(N) \
|
||||
template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
|
||||
struct CommandSync##N : public SyncCommand { \
|
||||
T *instance; \
|
||||
M method; \
|
||||
SEMIC_SEP_LIST(PARAM_DECL, N); \
|
||||
virtual void call() { \
|
||||
(instance->*method)(COMMA_SEP_LIST(ARG, N)); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define TYPE_ARG(N) P##N
|
||||
#define CMD_TYPE(N) Command##N<T, M COMMA(N) COMMA_SEP_LIST(TYPE_ARG, N)>
|
||||
#define CMD_ASSIGN_PARAM(N) cmd->p##N = p##N
|
||||
|
||||
#define DECL_PUSH(N) \
|
||||
template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
|
||||
void push(T *p_instance, M p_method COMMA(N) COMMA_SEP_LIST(PARAM, N)) { \
|
||||
CMD_TYPE(N) *cmd = allocate_and_lock<CMD_TYPE(N)>(); \
|
||||
cmd->instance = p_instance; \
|
||||
cmd->method = p_method; \
|
||||
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
||||
unlock(); \
|
||||
if (sync) sync->post(); \
|
||||
}
|
||||
|
||||
#define CMD_RET_TYPE(N) CommandRet##N<T, M, COMMA_SEP_LIST(TYPE_ARG, N) COMMA(N) R>
|
||||
|
||||
#define DECL_PUSH_AND_RET(N) \
|
||||
template <class T, class M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) class R> \
|
||||
void push_and_ret(T *p_instance, M p_method, COMMA_SEP_LIST(PARAM, N) COMMA(N) R *r_ret) { \
|
||||
SyncSemaphore *ss = _alloc_sync_sem(); \
|
||||
CMD_RET_TYPE(N) *cmd = allocate_and_lock<CMD_RET_TYPE(N)>(); \
|
||||
cmd->instance = p_instance; \
|
||||
cmd->method = p_method; \
|
||||
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
||||
cmd->ret = r_ret; \
|
||||
cmd->sync_sem = ss; \
|
||||
unlock(); \
|
||||
if (sync) sync->post(); \
|
||||
ss->sem->wait(); \
|
||||
}
|
||||
|
||||
#define CMD_SYNC_TYPE(N) CommandSync##N<T, M COMMA(N) COMMA_SEP_LIST(TYPE_ARG, N)>
|
||||
|
||||
#define DECL_PUSH_AND_SYNC(N) \
|
||||
template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
|
||||
void push_and_sync(T *p_instance, M p_method COMMA(N) COMMA_SEP_LIST(PARAM, N)) { \
|
||||
SyncSemaphore *ss = _alloc_sync_sem(); \
|
||||
CMD_SYNC_TYPE(N) *cmd = allocate_and_lock<CMD_SYNC_TYPE(N)>(); \
|
||||
cmd->instance = p_instance; \
|
||||
cmd->method = p_method; \
|
||||
SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
|
||||
cmd->sync_sem = ss; \
|
||||
unlock(); \
|
||||
if (sync) sync->post(); \
|
||||
ss->sem->wait(); \
|
||||
}
|
||||
|
||||
#define MAX_CMD_PARAMS 12
|
||||
|
||||
class CommandQueueMT {
|
||||
|
||||
struct SyncSemaphore {
|
||||
|
||||
Semaphore *sem;
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
struct CommandBase {
|
||||
|
||||
virtual void call() = 0;
|
||||
virtual void post(){};
|
||||
virtual ~CommandBase(){};
|
||||
};
|
||||
|
||||
struct SyncCommand : public CommandBase {
|
||||
|
||||
SyncSemaphore *sync_sem;
|
||||
|
||||
virtual void post() {
|
||||
sync_sem->sem->post();
|
||||
sync_sem->in_use = false;
|
||||
}
|
||||
};
|
||||
|
||||
DECL_CMD(0)
|
||||
SPACE_SEP_LIST(DECL_CMD, 12)
|
||||
|
||||
/* comands that return */
|
||||
DECL_CMD_RET(0)
|
||||
SPACE_SEP_LIST(DECL_CMD_RET, 12)
|
||||
|
||||
/* commands that don't return but sync */
|
||||
DECL_CMD_SYNC(0)
|
||||
SPACE_SEP_LIST(DECL_CMD_SYNC, 12)
|
||||
|
||||
/***** BASE *******/
|
||||
|
||||
enum {
|
||||
COMMAND_MEM_SIZE_KB = 256,
|
||||
COMMAND_MEM_SIZE = COMMAND_MEM_SIZE_KB * 1024,
|
||||
SYNC_SEMAPHORES = 8
|
||||
};
|
||||
|
||||
uint8_t command_mem[COMMAND_MEM_SIZE];
|
||||
uint32_t read_ptr = 0;
|
||||
uint32_t write_ptr = 0;
|
||||
uint32_t dealloc_ptr = 0;
|
||||
SyncSemaphore sync_sems[SYNC_SEMAPHORES];
|
||||
Mutex *mutex;
|
||||
Semaphore *sync;
|
||||
|
||||
template <class T>
|
||||
T *allocate() {
|
||||
|
||||
// alloc size is size+T+safeguard
|
||||
uint32_t alloc_size = sizeof(T) + sizeof(uint32_t);
|
||||
|
||||
tryagain:
|
||||
|
||||
if (write_ptr < dealloc_ptr) {
|
||||
// behind dealloc_ptr, check that there is room
|
||||
if ((dealloc_ptr - write_ptr) <= alloc_size) {
|
||||
|
||||
// There is no more room, try to deallocate something
|
||||
if (dealloc_one()) {
|
||||
goto tryagain;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
} else if (write_ptr >= dealloc_ptr) {
|
||||
// ahead of dealloc_ptr, check that there is room
|
||||
|
||||
if ((COMMAND_MEM_SIZE - write_ptr) < alloc_size + sizeof(uint32_t)) {
|
||||
// no room at the end, wrap down;
|
||||
|
||||
if (dealloc_ptr == 0) { // don't want write_ptr to become dealloc_ptr
|
||||
|
||||
// There is no more room, try to deallocate something
|
||||
if (dealloc_one()) {
|
||||
goto tryagain;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if this happens, it's a bug
|
||||
ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < sizeof(uint32_t), NULL);
|
||||
// zero means, wrap to beginning
|
||||
|
||||
uint32_t *p = (uint32_t *)&command_mem[write_ptr];
|
||||
*p = 0;
|
||||
write_ptr = 0;
|
||||
goto tryagain;
|
||||
}
|
||||
}
|
||||
// Allocate the size and the 'in use' bit.
|
||||
// First bit used to mark if command is still in use (1)
|
||||
// or if it has been destroyed and can be deallocated (0).
|
||||
uint32_t *p = (uint32_t *)&command_mem[write_ptr];
|
||||
*p = (sizeof(T) << 1) | 1;
|
||||
write_ptr += sizeof(uint32_t);
|
||||
// allocate the command
|
||||
T *cmd = memnew_placement(&command_mem[write_ptr], T);
|
||||
write_ptr += sizeof(T);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *allocate_and_lock() {
|
||||
|
||||
lock();
|
||||
T *ret;
|
||||
|
||||
while ((ret = allocate<T>()) == NULL) {
|
||||
|
||||
unlock();
|
||||
// sleep a little until fetch happened and some room is made
|
||||
wait_for_flush();
|
||||
lock();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool flush_one(bool p_lock = true) {
|
||||
if (p_lock) lock();
|
||||
tryagain:
|
||||
|
||||
// tried to read an empty queue
|
||||
if (read_ptr == write_ptr)
|
||||
return false;
|
||||
|
||||
uint32_t size_ptr = read_ptr;
|
||||
uint32_t size = *(uint32_t *)&command_mem[read_ptr] >> 1;
|
||||
|
||||
if (size == 0) {
|
||||
//end of ringbuffer, wrap
|
||||
read_ptr = 0;
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
read_ptr += sizeof(uint32_t);
|
||||
|
||||
CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]);
|
||||
|
||||
read_ptr += size;
|
||||
|
||||
if (p_lock) unlock();
|
||||
cmd->call();
|
||||
if (p_lock) lock();
|
||||
|
||||
cmd->post();
|
||||
cmd->~CommandBase();
|
||||
*(uint32_t *)&command_mem[size_ptr] &= ~1;
|
||||
|
||||
if (p_lock) unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
void wait_for_flush();
|
||||
SyncSemaphore *_alloc_sync_sem();
|
||||
bool dealloc_one();
|
||||
|
||||
public:
|
||||
/* NORMAL PUSH COMMANDS */
|
||||
DECL_PUSH(0)
|
||||
SPACE_SEP_LIST(DECL_PUSH, 12)
|
||||
|
||||
/* PUSH AND RET COMMANDS */
|
||||
DECL_PUSH_AND_RET(0)
|
||||
SPACE_SEP_LIST(DECL_PUSH_AND_RET, 12)
|
||||
|
||||
/* PUSH AND RET SYNC COMMANDS*/
|
||||
DECL_PUSH_AND_SYNC(0)
|
||||
SPACE_SEP_LIST(DECL_PUSH_AND_SYNC, 12)
|
||||
|
||||
void wait_and_flush_one() {
|
||||
ERR_FAIL_COND(!sync);
|
||||
sync->wait();
|
||||
flush_one();
|
||||
}
|
||||
|
||||
void flush_all() {
|
||||
|
||||
//ERR_FAIL_COND(sync);
|
||||
lock();
|
||||
while (flush_one(false))
|
||||
;
|
||||
unlock();
|
||||
}
|
||||
|
||||
CommandQueueMT(bool p_sync);
|
||||
~CommandQueueMT();
|
||||
};
|
||||
|
||||
#undef ARG
|
||||
#undef PARAM
|
||||
#undef TYPE_PARAM
|
||||
#undef PARAM_DECL
|
||||
#undef DECL_CMD
|
||||
#undef DECL_CMD_RET
|
||||
#undef DECL_CMD_SYNC
|
||||
#undef TYPE_ARG
|
||||
#undef CMD_TYPE
|
||||
#undef CMD_ASSIGN_PARAM
|
||||
#undef DECL_PUSH
|
||||
#undef CMD_RET_TYPE
|
||||
#undef DECL_PUSH_AND_RET
|
||||
#undef CMD_SYNC_TYPE
|
||||
#undef DECL_CMD_SYNC
|
||||
|
||||
#endif
|
||||
314
core/compressed_translation.cpp
Normal file
314
core/compressed_translation.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
/*************************************************************************/
|
||||
/* compressed_translation.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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"
|
||||
|
||||
extern "C" {
|
||||
#include "thirdparty/misc/smaz.h"
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
PoolVector<int>::Write htwb = hash_table.write();
|
||||
PoolVector<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);
|
||||
PoolVector<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());
|
||||
|
||||
PoolVector<int>::Read htr = hash_table.read();
|
||||
const uint32_t *htptr = (const uint32_t *)&htr[0];
|
||||
PoolVector<int>::Read btr = bucket_table.read();
|
||||
const uint32_t *btptr = (const uint32_t *)&btr[0];
|
||||
PoolVector<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.ptrw(), 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::POOL_INT_ARRAY, "hash_table"));
|
||||
p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "bucket_table"));
|
||||
p_list->push_back(PropertyInfo(Variant::POOL_BYTE_ARRAY, "strings"));
|
||||
p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR));
|
||||
}
|
||||
void PHashTranslation::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("generate", "from"), &PHashTranslation::generate);
|
||||
}
|
||||
|
||||
PHashTranslation::PHashTranslation() {
|
||||
}
|
||||
92
core/compressed_translation.h
Normal file
92
core/compressed_translation.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*************************************************************************/
|
||||
/* compressed_translation.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 {
|
||||
|
||||
GDCLASS(PHashTranslation, Translation);
|
||||
|
||||
//this translation uses a sort of modified perfect hash algorithm
|
||||
//it requires 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
|
||||
PoolVector<int> hash_table;
|
||||
PoolVector<int> bucket_table;
|
||||
PoolVector<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,40 +1,41 @@
|
||||
/**************************************************************************/
|
||||
/* 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 */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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")),
|
||||
_meta(StaticCString::create("__meta__")),
|
||||
_script(StaticCString::create("script")),
|
||||
script_changed(StaticCString::create("script_changed")),
|
||||
___pdcdata(StaticCString::create("___pdcdata")),
|
||||
@ -43,38 +44,31 @@ CoreStringNames::CoreStringNames() :
|
||||
_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")) {
|
||||
_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");
|
||||
}
|
||||
|
||||
@ -1,46 +1,47 @@
|
||||
/**************************************************************************/
|
||||
/* 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 */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 void create() { singleton = memnew(CoreStringNames); }
|
||||
static void free() {
|
||||
memdelete(singleton);
|
||||
singleton = nullptr;
|
||||
singleton = NULL;
|
||||
}
|
||||
|
||||
CoreStringNames();
|
||||
@ -52,6 +53,7 @@ public:
|
||||
|
||||
StringName _free;
|
||||
StringName changed;
|
||||
StringName _meta;
|
||||
StringName _script;
|
||||
StringName script_changed;
|
||||
StringName ___pdcdata;
|
||||
@ -60,7 +62,6 @@ public:
|
||||
StringName _iter_next;
|
||||
StringName _iter_get;
|
||||
StringName get_rid;
|
||||
StringName _to_string;
|
||||
#ifdef TOOLS_ENABLED
|
||||
StringName _sections_unfolded;
|
||||
#endif
|
||||
@ -88,14 +89,6 @@ public:
|
||||
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
|
||||
251
core/dictionary.cpp
Normal file
251
core/dictionary.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
/*************************************************************************/
|
||||
/* dictionary.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 "ordered_hash_map.h"
|
||||
#include "safe_refcount.h"
|
||||
#include "variant.h"
|
||||
|
||||
struct DictionaryPrivate {
|
||||
|
||||
SafeRefCount refcount;
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
|
||||
};
|
||||
|
||||
void Dictionary::get_key_list(List<Variant> *p_keys) const {
|
||||
|
||||
if (_p->variant_map.empty())
|
||||
return;
|
||||
|
||||
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
|
||||
p_keys->push_back(E.key());
|
||||
}
|
||||
}
|
||||
|
||||
Variant &Dictionary::operator[](const Variant &p_key) {
|
||||
|
||||
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 {
|
||||
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
|
||||
|
||||
if (!E)
|
||||
return NULL;
|
||||
return &E.get();
|
||||
}
|
||||
|
||||
Variant *Dictionary::getptr(const Variant &p_key) {
|
||||
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(p_key);
|
||||
|
||||
if (!E)
|
||||
return NULL;
|
||||
return &E.get();
|
||||
}
|
||||
|
||||
Variant Dictionary::get_valid(const Variant &p_key) const {
|
||||
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
|
||||
|
||||
if (!E)
|
||||
return Variant();
|
||||
return E.get();
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
_p->variant_map.erase(p_key);
|
||||
}
|
||||
|
||||
bool Dictionary::erase_checked(const Variant &p_key) {
|
||||
|
||||
return _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() {
|
||||
|
||||
_p->variant_map.clear();
|
||||
}
|
||||
|
||||
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 varr;
|
||||
varr.resize(size());
|
||||
if (_p->variant_map.empty())
|
||||
return varr;
|
||||
|
||||
int i = 0;
|
||||
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
|
||||
varr[i] = E.key();
|
||||
i++;
|
||||
}
|
||||
|
||||
return varr;
|
||||
}
|
||||
|
||||
Array Dictionary::values() const {
|
||||
|
||||
Array varr;
|
||||
varr.resize(size());
|
||||
if (_p->variant_map.empty())
|
||||
return varr;
|
||||
|
||||
int i = 0;
|
||||
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
|
||||
varr[i] = E.get();
|
||||
i++;
|
||||
}
|
||||
|
||||
return varr;
|
||||
}
|
||||
|
||||
const Variant *Dictionary::next(const Variant *p_key) const {
|
||||
|
||||
if (p_key == NULL) {
|
||||
// caller wants to get the first element
|
||||
if (_p->variant_map.front())
|
||||
return &_p->variant_map.front().key();
|
||||
return NULL;
|
||||
}
|
||||
OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key);
|
||||
|
||||
if (E && E.next())
|
||||
return &E.next().key();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dictionary Dictionary::duplicate() const {
|
||||
|
||||
Dictionary n;
|
||||
|
||||
List<Variant> keys;
|
||||
get_key_list(&keys);
|
||||
|
||||
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
||||
n[E->get()] = operator[](E->get());
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void Dictionary::operator=(const Dictionary &p_dictionary) {
|
||||
|
||||
_ref(p_dictionary);
|
||||
}
|
||||
|
||||
Dictionary::Dictionary(const Dictionary &p_from) {
|
||||
_p = NULL;
|
||||
_ref(p_from);
|
||||
}
|
||||
|
||||
Dictionary::Dictionary() {
|
||||
|
||||
_p = memnew(DictionaryPrivate);
|
||||
_p->refcount.init();
|
||||
}
|
||||
Dictionary::~Dictionary() {
|
||||
|
||||
_unref();
|
||||
}
|
||||
86
core/dictionary.h
Normal file
86
core/dictionary.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*************************************************************************/
|
||||
/* dictionary.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 _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();
|
||||
|
||||
bool has(const Variant &p_key) const;
|
||||
bool has_all(const Array &p_keys) const;
|
||||
|
||||
void erase(const Variant &p_key);
|
||||
bool erase_checked(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 duplicate() const;
|
||||
|
||||
Dictionary(const Dictionary &p_from);
|
||||
Dictionary();
|
||||
~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
|
||||
71
core/dvector.cpp
Normal file
71
core/dvector.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*************************************************************************/
|
||||
/* dvector.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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;
|
||||
|
||||
PoolAllocator *MemoryPool::memory_pool = NULL;
|
||||
uint8_t *MemoryPool::pool_memory = NULL;
|
||||
size_t *MemoryPool::pool_size = NULL;
|
||||
|
||||
MemoryPool::Alloc *MemoryPool::allocs = NULL;
|
||||
MemoryPool::Alloc *MemoryPool::free_list = NULL;
|
||||
uint32_t MemoryPool::alloc_count = 0;
|
||||
uint32_t MemoryPool::allocs_used = 0;
|
||||
Mutex *MemoryPool::alloc_mutex = NULL;
|
||||
|
||||
size_t MemoryPool::total_memory = 0;
|
||||
size_t MemoryPool::max_memory = 0;
|
||||
|
||||
void MemoryPool::setup(uint32_t p_max_allocs) {
|
||||
|
||||
allocs = memnew_arr(Alloc, p_max_allocs);
|
||||
alloc_count = p_max_allocs;
|
||||
allocs_used = 0;
|
||||
|
||||
for (uint32_t i = 0; i < alloc_count - 1; i++) {
|
||||
|
||||
allocs[i].free_list = &allocs[i + 1];
|
||||
}
|
||||
|
||||
free_list = &allocs[0];
|
||||
|
||||
alloc_mutex = Mutex::create();
|
||||
}
|
||||
|
||||
void MemoryPool::cleanup() {
|
||||
|
||||
memdelete_arr(allocs);
|
||||
memdelete(alloc_mutex);
|
||||
|
||||
ERR_EXPLAINC("There are still MemoryPool allocs in use at exit!");
|
||||
ERR_FAIL_COND(allocs_used > 0);
|
||||
}
|
||||
643
core/dvector.h
Normal file
643
core/dvector.h
Normal file
@ -0,0 +1,643 @@
|
||||
/*************************************************************************/
|
||||
/* dvector.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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/copymem.h"
|
||||
#include "os/memory.h"
|
||||
#include "os/rw_lock.h"
|
||||
#include "pool_allocator.h"
|
||||
#include "safe_refcount.h"
|
||||
#include "ustring.h"
|
||||
|
||||
struct MemoryPool {
|
||||
|
||||
//avoid accessing these directly, must be public for template access
|
||||
|
||||
static PoolAllocator *memory_pool;
|
||||
static uint8_t *pool_memory;
|
||||
static size_t *pool_size;
|
||||
|
||||
struct Alloc {
|
||||
|
||||
SafeRefCount refcount;
|
||||
uint32_t lock;
|
||||
void *mem;
|
||||
PoolAllocator::ID pool_id;
|
||||
size_t size;
|
||||
|
||||
Alloc *free_list;
|
||||
|
||||
Alloc() {
|
||||
mem = NULL;
|
||||
lock = 0;
|
||||
pool_id = POOL_ALLOCATOR_INVALID_ID;
|
||||
size = 0;
|
||||
free_list = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
static Alloc *allocs;
|
||||
static Alloc *free_list;
|
||||
static uint32_t alloc_count;
|
||||
static uint32_t allocs_used;
|
||||
static Mutex *alloc_mutex;
|
||||
static size_t total_memory;
|
||||
static size_t max_memory;
|
||||
|
||||
static void setup(uint32_t p_max_allocs = (1 << 16));
|
||||
static void cleanup();
|
||||
};
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
class PoolVector {
|
||||
|
||||
MemoryPool::Alloc *alloc;
|
||||
|
||||
void _copy_on_write() {
|
||||
|
||||
if (!alloc)
|
||||
return;
|
||||
|
||||
// ERR_FAIL_COND(alloc->lock>0); should not be illegal to lock this for copy on write, as it's a copy on write after all
|
||||
|
||||
// Refcount should not be zero, otherwise it's a misuse of COW
|
||||
if (alloc->refcount.get() == 1)
|
||||
return; //nothing to do
|
||||
|
||||
//must allocate something
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
ERR_EXPLAINC("All memory pool allocations are in use, can't COW.");
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
MemoryPool::Alloc *old_alloc = alloc;
|
||||
|
||||
//take one from the free list
|
||||
alloc = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc->free_list;
|
||||
//increment the used counter
|
||||
MemoryPool::allocs_used++;
|
||||
|
||||
//copy the alloc data
|
||||
alloc->size = old_alloc->size;
|
||||
alloc->refcount.init();
|
||||
alloc->pool_id = POOL_ALLOCATOR_INVALID_ID;
|
||||
alloc->lock = 0;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::total_memory += alloc->size;
|
||||
if (MemoryPool::total_memory > MemoryPool::max_memory) {
|
||||
MemoryPool::max_memory = MemoryPool::total_memory;
|
||||
}
|
||||
#endif
|
||||
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
|
||||
} else {
|
||||
alloc->mem = memalloc(alloc->size);
|
||||
}
|
||||
|
||||
{
|
||||
Write w;
|
||||
w._ref(alloc);
|
||||
Read r;
|
||||
r._ref(old_alloc);
|
||||
|
||||
int cur_elements = alloc->size / sizeof(T);
|
||||
T *dst = (T *)w.ptr();
|
||||
const T *src = (const T *)r.ptr();
|
||||
for (int i = 0; i < cur_elements; i++) {
|
||||
memnew_placement(&dst[i], T(src[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (old_alloc->refcount.unref() == true) {
|
||||
//this should never happen but..
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
MemoryPool::total_memory -= old_alloc->size;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
#endif
|
||||
|
||||
{
|
||||
Write w;
|
||||
w._ref(old_alloc);
|
||||
|
||||
int cur_elements = old_alloc->size / sizeof(T);
|
||||
T *elems = (T *)w.ptr();
|
||||
for (int i = 0; i < cur_elements; i++) {
|
||||
elems[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
|
||||
memfree(old_alloc->mem);
|
||||
old_alloc->mem = NULL;
|
||||
old_alloc->size = 0;
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
old_alloc->free_list = MemoryPool::free_list;
|
||||
MemoryPool::free_list = old_alloc;
|
||||
MemoryPool::allocs_used--;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _reference(const PoolVector &p_dvector) {
|
||||
|
||||
if (alloc == p_dvector.alloc)
|
||||
return;
|
||||
|
||||
_unreference();
|
||||
|
||||
if (!p_dvector.alloc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_dvector.alloc->refcount.ref()) {
|
||||
alloc = p_dvector.alloc;
|
||||
}
|
||||
}
|
||||
|
||||
void _unreference() {
|
||||
|
||||
if (!alloc)
|
||||
return;
|
||||
|
||||
if (alloc->refcount.unref() == false) {
|
||||
alloc = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
//must be disposed!
|
||||
|
||||
{
|
||||
int cur_elements = alloc->size / sizeof(T);
|
||||
|
||||
// Don't use write() here because it could otherwise provoke COW,
|
||||
// which is not desirable here because we are destroying the last reference anyways
|
||||
Write w;
|
||||
// Reference to still prevent other threads from touching the alloc
|
||||
w._ref(alloc);
|
||||
|
||||
for (int i = 0; i < cur_elements; i++) {
|
||||
|
||||
w[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
MemoryPool::total_memory -= alloc->size;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
#endif
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
|
||||
memfree(alloc->mem);
|
||||
alloc->mem = NULL;
|
||||
alloc->size = 0;
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
alloc->free_list = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc;
|
||||
MemoryPool::allocs_used--;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
}
|
||||
|
||||
alloc = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
class Access {
|
||||
friend class PoolVector;
|
||||
|
||||
protected:
|
||||
MemoryPool::Alloc *alloc;
|
||||
T *mem;
|
||||
|
||||
_FORCE_INLINE_ void _ref(MemoryPool::Alloc *p_alloc) {
|
||||
alloc = p_alloc;
|
||||
if (alloc) {
|
||||
if (atomic_increment(&alloc->lock) == 1) {
|
||||
if (MemoryPool::memory_pool) {
|
||||
//lock it and get mem
|
||||
}
|
||||
}
|
||||
|
||||
mem = (T *)alloc->mem;
|
||||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void _unref() {
|
||||
|
||||
if (alloc) {
|
||||
if (atomic_decrement(&alloc->lock) == 0) {
|
||||
if (MemoryPool::memory_pool) {
|
||||
//put mem back
|
||||
}
|
||||
}
|
||||
|
||||
mem = NULL;
|
||||
alloc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Access() {
|
||||
alloc = NULL;
|
||||
mem = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~Access() {
|
||||
_unref();
|
||||
}
|
||||
};
|
||||
|
||||
class Read : public Access {
|
||||
public:
|
||||
_FORCE_INLINE_ const T &operator[](int p_index) const { return this->mem[p_index]; }
|
||||
_FORCE_INLINE_ const T *ptr() const { return this->mem; }
|
||||
|
||||
void operator=(const Read &p_read) {
|
||||
if (this->alloc == p_read.alloc)
|
||||
return;
|
||||
this->_unref();
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
|
||||
Read(const Read &p_read) {
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
|
||||
Read() {}
|
||||
};
|
||||
|
||||
class Write : public Access {
|
||||
public:
|
||||
_FORCE_INLINE_ T &operator[](int p_index) const { return this->mem[p_index]; }
|
||||
_FORCE_INLINE_ T *ptr() const { return this->mem; }
|
||||
|
||||
void operator=(const Write &p_read) {
|
||||
if (this->alloc == p_read.alloc)
|
||||
return;
|
||||
this->_unref();
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
|
||||
Write(const Write &p_read) {
|
||||
this->_ref(p_read.alloc);
|
||||
}
|
||||
|
||||
Write() {}
|
||||
};
|
||||
|
||||
Read read() const {
|
||||
|
||||
Read r;
|
||||
if (alloc) {
|
||||
r._ref(alloc);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
Write write() {
|
||||
|
||||
Write w;
|
||||
if (alloc) {
|
||||
_copy_on_write(); //make sure there is only one being acessed
|
||||
w._ref(alloc);
|
||||
}
|
||||
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 PoolVector<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];
|
||||
}
|
||||
|
||||
PoolVector<T> subarray(int p_from, int p_to) {
|
||||
|
||||
if (p_from < 0) {
|
||||
p_from = size() + p_from;
|
||||
}
|
||||
if (p_to < 0) {
|
||||
p_to = size() + p_to;
|
||||
}
|
||||
|
||||
CRASH_BAD_INDEX(p_from, size());
|
||||
CRASH_BAD_INDEX(p_to, size());
|
||||
|
||||
PoolVector<T> slice;
|
||||
int span = 1 + p_to - p_from;
|
||||
slice.resize(span);
|
||||
Read r = read();
|
||||
Write w = slice.write();
|
||||
for (int i = 0; i < span; ++i) {
|
||||
w[i] = r[p_from + i];
|
||||
}
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
String join(String delimiter) {
|
||||
String rs = "";
|
||||
int s = size();
|
||||
Read r = read();
|
||||
for (int i = 0; i < s; i++) {
|
||||
rs += r[i] + delimiter;
|
||||
}
|
||||
rs.erase(rs.length() - delimiter.length(), delimiter.length());
|
||||
return rs;
|
||||
}
|
||||
|
||||
bool is_locked() const { return alloc && alloc->lock > 0; }
|
||||
|
||||
inline const T operator[](int p_index) const;
|
||||
|
||||
Error resize(int p_size);
|
||||
|
||||
void invert();
|
||||
|
||||
void operator=(const PoolVector &p_dvector) { _reference(p_dvector); }
|
||||
PoolVector() { alloc = NULL; }
|
||||
PoolVector(const PoolVector &p_dvector) {
|
||||
alloc = NULL;
|
||||
_reference(p_dvector);
|
||||
}
|
||||
~PoolVector() { _unreference(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
int PoolVector<T>::size() const {
|
||||
|
||||
return alloc ? alloc->size / sizeof(T) : 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T PoolVector<T>::get(int p_index) const {
|
||||
|
||||
return operator[](p_index);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PoolVector<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 PoolVector<T>::push_back(const T &p_val) {
|
||||
|
||||
resize(size() + 1);
|
||||
set(size() - 1, p_val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T PoolVector<T>::operator[](int p_index) const {
|
||||
|
||||
CRASH_BAD_INDEX(p_index, size());
|
||||
|
||||
Read r = read();
|
||||
return r[p_index];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Error PoolVector<T>::resize(int p_size) {
|
||||
|
||||
if (alloc == NULL) {
|
||||
|
||||
if (p_size == 0)
|
||||
return OK; //nothing to do here
|
||||
|
||||
//must allocate something
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
if (MemoryPool::allocs_used == MemoryPool::alloc_count) {
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
ERR_EXPLAINC("All memory pool allocations are in use.");
|
||||
ERR_FAIL_V(ERR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
//take one from the free list
|
||||
alloc = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc->free_list;
|
||||
//increment the used counter
|
||||
MemoryPool::allocs_used++;
|
||||
|
||||
//cleanup the alloc
|
||||
alloc->size = 0;
|
||||
alloc->refcount.init();
|
||||
alloc->pool_id = POOL_ALLOCATOR_INVALID_ID;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
|
||||
} else {
|
||||
|
||||
ERR_FAIL_COND_V(alloc->lock > 0, ERR_LOCKED); //can't resize if locked!
|
||||
}
|
||||
|
||||
size_t new_size = sizeof(T) * p_size;
|
||||
|
||||
if (alloc->size == new_size)
|
||||
return OK; //nothing to do
|
||||
|
||||
if (p_size == 0) {
|
||||
_unreference();
|
||||
return OK;
|
||||
}
|
||||
|
||||
_copy_on_write(); // make it unique
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
MemoryPool::total_memory -= alloc->size;
|
||||
MemoryPool::total_memory += new_size;
|
||||
if (MemoryPool::total_memory > MemoryPool::max_memory) {
|
||||
MemoryPool::max_memory = MemoryPool::total_memory;
|
||||
}
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
#endif
|
||||
|
||||
int cur_elements = alloc->size / sizeof(T);
|
||||
|
||||
if (p_size > cur_elements) {
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
|
||||
if (alloc->size == 0) {
|
||||
alloc->mem = memalloc(new_size);
|
||||
} else {
|
||||
alloc->mem = memrealloc(alloc->mem, new_size);
|
||||
}
|
||||
}
|
||||
|
||||
alloc->size = new_size;
|
||||
|
||||
Write w = write();
|
||||
|
||||
for (int i = cur_elements; i < p_size; i++) {
|
||||
|
||||
memnew_placement(&w[i], T);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
{
|
||||
Write w = write();
|
||||
for (int i = p_size; i < cur_elements; i++) {
|
||||
|
||||
w[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
if (MemoryPool::memory_pool) {
|
||||
//resize memory pool
|
||||
//if none, create
|
||||
//if some resize
|
||||
} else {
|
||||
|
||||
if (new_size == 0) {
|
||||
memfree(alloc->mem);
|
||||
alloc->mem = NULL;
|
||||
alloc->size = 0;
|
||||
|
||||
MemoryPool::alloc_mutex->lock();
|
||||
alloc->free_list = MemoryPool::free_list;
|
||||
MemoryPool::free_list = alloc;
|
||||
MemoryPool::allocs_used--;
|
||||
MemoryPool::alloc_mutex->unlock();
|
||||
|
||||
} else {
|
||||
alloc->mem = memrealloc(alloc->mem, new_size);
|
||||
alloc->size = new_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PoolVector<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
|
||||
151
core/engine.cpp
Normal file
151
core/engine.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
/*************************************************************************/
|
||||
/* engine.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 "engine.h"
|
||||
|
||||
#include "version.h"
|
||||
#include "version_hash.gen.h"
|
||||
|
||||
void Engine::set_iterations_per_second(int p_ips) {
|
||||
|
||||
ips = p_ips;
|
||||
}
|
||||
int Engine::get_iterations_per_second() const {
|
||||
|
||||
return ips;
|
||||
}
|
||||
|
||||
void Engine::set_target_fps(int p_fps) {
|
||||
_target_fps = p_fps > 0 ? p_fps : 0;
|
||||
}
|
||||
|
||||
float Engine::get_target_fps() const {
|
||||
return _target_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(float p_scale) {
|
||||
|
||||
_time_scale = p_scale;
|
||||
}
|
||||
|
||||
float Engine::get_time_scale() const {
|
||||
|
||||
return _time_scale;
|
||||
}
|
||||
|
||||
Dictionary Engine::get_version_info() const {
|
||||
|
||||
Dictionary dict;
|
||||
dict["major"] = VERSION_MAJOR;
|
||||
dict["minor"] = VERSION_MINOR;
|
||||
#ifdef VERSION_PATCH
|
||||
dict["patch"] = VERSION_PATCH;
|
||||
#else
|
||||
dict["patch"] = 0;
|
||||
#endif
|
||||
dict["status"] = VERSION_STATUS;
|
||||
dict["build"] = VERSION_BUILD;
|
||||
dict["year"] = VERSION_YEAR;
|
||||
|
||||
String hash = VERSION_HASH;
|
||||
dict["hash"] = hash.length() == 0 ? 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;
|
||||
}
|
||||
|
||||
void Engine::add_singleton(const Singleton &p_singleton) {
|
||||
|
||||
singletons.push_back(p_singleton);
|
||||
singleton_ptrs[p_singleton.name] = p_singleton.ptr;
|
||||
}
|
||||
|
||||
Object *Engine::get_singleton_object(const String &p_name) const {
|
||||
|
||||
const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
|
||||
ERR_EXPLAIN("Failed to retrieve non-existent singleton '" + p_name + "'");
|
||||
ERR_FAIL_COND_V(!E, NULL);
|
||||
return E->get();
|
||||
};
|
||||
|
||||
bool Engine::has_singleton(const String &p_name) const {
|
||||
|
||||
return singleton_ptrs.has(p_name);
|
||||
};
|
||||
|
||||
void Engine::get_singletons(List<Singleton> *p_singletons) {
|
||||
|
||||
for (List<Singleton>::Element *E = singletons.front(); E; E = E->next())
|
||||
p_singletons->push_back(E->get());
|
||||
}
|
||||
|
||||
Engine *Engine::singleton = NULL;
|
||||
|
||||
Engine *Engine::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
Engine::Engine() {
|
||||
|
||||
singleton = this;
|
||||
frames_drawn = 0;
|
||||
ips = 60;
|
||||
_frame_delay = 0;
|
||||
_fps = 1;
|
||||
_target_fps = 0;
|
||||
_time_scale = 1.0;
|
||||
_pixel_snap = false;
|
||||
_physics_frames = 0;
|
||||
_idle_frames = 0;
|
||||
_in_physics = false;
|
||||
_frame_ticks = 0;
|
||||
_frame_step = 0;
|
||||
editor_hint = false;
|
||||
}
|
||||
121
core/engine.h
Normal file
121
core/engine.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*************************************************************************/
|
||||
/* engine.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2018 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 ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "list.h"
|
||||
#include "os/main_loop.h"
|
||||
#include "ustring.h"
|
||||
#include "vector.h"
|
||||
|
||||
class Engine {
|
||||
|
||||
public:
|
||||
struct Singleton {
|
||||
StringName name;
|
||||
Object *ptr;
|
||||
Singleton(const StringName &p_name = StringName(), Object *p_ptr = NULL) :
|
||||
name(p_name),
|
||||
ptr(p_ptr) {
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
friend class Main;
|
||||
|
||||
uint64_t frames_drawn;
|
||||
uint32_t _frame_delay;
|
||||
uint64_t _frame_ticks;
|
||||
float _frame_step;
|
||||
|
||||
int ips;
|
||||
float _fps;
|
||||
int _target_fps;
|
||||
float _time_scale;
|
||||
bool _pixel_snap;
|
||||
uint64_t _physics_frames;
|
||||
|
||||
uint64_t _idle_frames;
|
||||
bool _in_physics;
|
||||
|
||||
List<Singleton> singletons;
|
||||
Map<StringName, Object *> singleton_ptrs;
|
||||
|
||||
bool editor_hint;
|
||||
|
||||
static Engine *singleton;
|
||||
|
||||
public:
|
||||
static Engine *get_singleton();
|
||||
|
||||
virtual void set_iterations_per_second(int p_ips);
|
||||
virtual int get_iterations_per_second() const;
|
||||
|
||||
virtual void set_target_fps(int p_fps);
|
||||
virtual float get_target_fps() const;
|
||||
|
||||
virtual float get_frames_per_second() const { return _fps; }
|
||||
|
||||
uint64_t get_frames_drawn();
|
||||
|
||||
uint64_t get_physics_frames() const { return _physics_frames; }
|
||||
uint64_t get_idle_frames() const { return _idle_frames; }
|
||||
bool is_in_physics_frame() const { return _in_physics; }
|
||||
uint64_t get_idle_frame_ticks() const { return _frame_ticks; }
|
||||
float get_idle_frame_step() const { return _frame_step; }
|
||||
|
||||
void set_time_scale(float p_scale);
|
||||
float get_time_scale() 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 String &p_name) const;
|
||||
Object *get_singleton_object(const String &p_name) const;
|
||||
|
||||
_FORCE_INLINE_ bool get_use_pixel_snap() const { return _pixel_snap; }
|
||||
|
||||
#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; }
|
||||
#else
|
||||
_FORCE_INLINE_ void set_editor_hint(bool p_enabled) {}
|
||||
_FORCE_INLINE_ bool is_editor_hint() const { return false; }
|
||||
#endif
|
||||
|
||||
Dictionary get_version_info() const;
|
||||
|
||||
Engine();
|
||||
};
|
||||
|
||||
#endif // ENGINE_H
|
||||
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env_error = env.Clone()
|
||||
|
||||
env_error.add_source_files(env.core_sources, "*.cpp")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user