Compare commits
1197 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2da48c49f | |||
| ca5cbf05be | |||
| dc6410e7b8 | |||
| e1572a2a5c | |||
| a3dddbfa24 | |||
| d88b93d56b | |||
| bd0bc42adc | |||
| 04ef3c60d5 | |||
| a14de5e255 | |||
| 90f377fa83 | |||
| c79952a4d6 | |||
| d7dc0b76e5 | |||
| 27b3538b2f | |||
| 74ca6b2c51 | |||
| d49def6f7e | |||
| 72d1d8f085 | |||
| d31fc32399 | |||
| 615ec636d4 | |||
| 5ee7b0d939 | |||
| 9f7ae5bb58 | |||
| 5f756a6ceb | |||
| 5d9e6b7364 | |||
| 9db3439d0d | |||
| 544eb03f7e | |||
| 9d640656e6 | |||
| 9a1fd12a85 | |||
| aaf349170c | |||
| 422f2323d2 | |||
| 10d9d53e47 | |||
| 94e5a8b7bc | |||
| bda94834f7 | |||
| df3969dae1 | |||
| 789dfac27c | |||
| 4f78f79201 | |||
| 28335478bd | |||
| 58618bd402 | |||
| 0ee6aad3ec | |||
| 9205352f94 | |||
| 5079ddd20a | |||
| 2bd2bd5081 | |||
| d5100373be | |||
| 8c006f6e11 | |||
| 804826fbc7 | |||
| 0498f1488e | |||
| 96589557b3 | |||
| 3119c50789 | |||
| 04c1cf469d | |||
| 70ab159dd4 | |||
| ac54838eea | |||
| 5e5ee8e039 | |||
| bb9711277a | |||
| 96a1f20bee | |||
| 32629b7a44 | |||
| 1b46c0921f | |||
| b581ec837c | |||
| c0a5417108 | |||
| 45a1d33689 | |||
| bb3cefbe54 | |||
| e7b62ad1c3 | |||
| 7997d2bc4e | |||
| c44e97c8bc | |||
| f7deac4b63 | |||
| 70136509a9 | |||
| 38451f7dce | |||
| 63a70758f2 | |||
| 890248edf2 | |||
| 9536c37623 | |||
| bf6daed6d2 | |||
| 864f5f77f5 | |||
| b16a6199d0 | |||
| 093928f2f9 | |||
| d3b96742e7 | |||
| fb6bc75e3a | |||
| 61bb41c878 | |||
| c52c23013c | |||
| 17aa4ea60d | |||
| 76e4e1b8d4 | |||
| fe8260fe14 | |||
| 90f9754781 | |||
| 75d5023354 | |||
| 0711710544 | |||
| 23a6a8b69f | |||
| 020b0a90d7 | |||
| 6013705988 | |||
| 65397621e9 | |||
| cbd1e5c837 | |||
| 9282bcfbbf | |||
| 1d8ae580b7 | |||
| 694f8fbaf3 | |||
| 623752e69b | |||
| 420525f688 | |||
| 9b570a46d2 | |||
| b8ee20c7dc | |||
| 4696ed4f8a | |||
| c37aee0a27 | |||
| 7b34ddc089 | |||
| 028ccfca2e | |||
| 072d70722c | |||
| 875dd30d57 | |||
| 9c2a04aa21 | |||
| 83485d2f52 | |||
| 74760a7661 | |||
| 2a109e50fb | |||
| 67dad80e15 | |||
| 64a7985376 | |||
| d3073f5251 | |||
| 62047d2d4c | |||
| 2020b8b011 | |||
| 87e96a9017 | |||
| 0e5335a806 | |||
| e8b07e1588 | |||
| 1c4901305c | |||
| 7106d958d7 | |||
| cd7ad4e5f8 | |||
| c0ba3b0edb | |||
| b82f19a0df | |||
| 6f487bcab5 | |||
| f7e3480d79 | |||
| 7ff3b565e5 | |||
| cc6f5f83ac | |||
| c38a2870dc | |||
| 287c9432b7 | |||
| 0e95700349 | |||
| a99282f86d | |||
| e17eed7029 | |||
| 46c406cc9e | |||
| 6a1552505e | |||
| 2190031ccf | |||
| 228ef4e130 | |||
| dd8817582a | |||
| 3b642c0370 | |||
| 16159a9d98 | |||
| c87b315fef | |||
| b07528d9ce | |||
| 9e2e6759bd | |||
| 2485987901 | |||
| 1a6e706e57 | |||
| 21a3081b9f | |||
| 8f9989dc65 | |||
| a3e3ee396a | |||
| cd68f2463b | |||
| d1f11bbdb2 | |||
| 3b6100837f | |||
| cc85450ed5 | |||
| 70470bc421 | |||
| f995d12686 | |||
| 3645377b15 | |||
| 1e804a0a81 | |||
| fadc5beb1c | |||
| 5f019dc79f | |||
| b57a3165fa | |||
| b13139c6cc | |||
| fea4b3fcba | |||
| 329a6ce0ef | |||
| 53587ad162 | |||
| 086e4c9835 | |||
| ee9627bc15 | |||
| 9de5ee5615 | |||
| 125591dc71 | |||
| b0134ab1ce | |||
| 9f313491b8 | |||
| 8f7da81621 | |||
| 55971167c8 | |||
| 9f50146e68 | |||
| bda71c067b | |||
| cc1e5873a6 | |||
| c652bab9b2 | |||
| 13b1c16213 | |||
| f1c98320fc | |||
| bdb65857bc | |||
| 164670cceb | |||
| d7ddb2ef6f | |||
| 326b6f000a | |||
| 7cc2c143ab | |||
| 37bf4bb34f | |||
| 534d2388f5 | |||
| d5cb34f1b4 | |||
| 6b8d8b7913 | |||
| 14d12418b6 | |||
| 979168e82c | |||
| 7140c4a2d8 | |||
| 5f8e5d44dc | |||
| 31c9b85a3f | |||
| 958c7b2181 | |||
| 652f8ccb8d | |||
| 26f4574358 | |||
| 0eadf2de1e | |||
| ec67d04a0a | |||
| 2df931e090 | |||
| f552dd0c28 | |||
| 8cf10bf71d | |||
| 621d408078 | |||
| 1fdc91255b | |||
| 524b55b6c1 | |||
| 5e07a42417 | |||
| ea4f97aad8 | |||
| e7804f9d02 | |||
| 092df84170 | |||
| 22288b0561 | |||
| 43c1e40461 | |||
| 8f76fe4049 | |||
| 60ddf0ea89 | |||
| b299ed3246 | |||
| 7c55d50507 | |||
| d798b10d4c | |||
| a6430692d2 | |||
| 3bbfe9de8a | |||
| 94abdfd734 | |||
| a0d6f3c22b | |||
| bbdc2bc876 | |||
| 9bda3aa52a | |||
| 9faf9e43fb | |||
| e5f3329e88 | |||
| a8cf4e95c5 | |||
| f345e0dffc | |||
| 26e09aebe3 | |||
| 892e091643 | |||
| ef823c0646 | |||
| c043e64b6b | |||
| 2382e2cbbc | |||
| 2a28126700 | |||
| f9251e41a4 | |||
| 1f11f287ec | |||
| 0476251638 | |||
| d71f89718b | |||
| 55f76999b4 | |||
| 393514c13d | |||
| 126ea687e6 | |||
| d83dcdebf3 | |||
| 248f78ed56 | |||
| ee7f2b3724 | |||
| 0b8c06b149 | |||
| 8b0dd039ca | |||
| f28a3572bb | |||
| 31c3171b72 | |||
| e000acd6fc | |||
| 8c0c6c0142 | |||
| c22eae0e2d | |||
| e32f4d5f8c | |||
| eda4def35b | |||
| ac0cf01404 | |||
| 50639e2378 | |||
| 88a5e07f2e | |||
| 9c93828976 | |||
| fcbe624f7c | |||
| efed1f5b1d | |||
| 4849a49ba4 | |||
| 424e832ec7 | |||
| dae05e0549 | |||
| 007edb4651 | |||
| 3953e6ddc0 | |||
| 40f5032898 | |||
| a2e2ef51be | |||
| c46f78885e | |||
| 5c67c4f5d4 | |||
| 70cb4d3cd9 | |||
| 5416d385d3 | |||
| 2c809389ad | |||
| 8bd4ad03de | |||
| 01688bc050 | |||
| d5c89cb3de | |||
| 9e07e80fa1 | |||
| 3e848d93da | |||
| d0bf176178 | |||
| fce41b95f6 | |||
| fb6a9728a3 | |||
| 6a482c987c | |||
| f60007da83 | |||
| 2149995116 | |||
| 44036a26d0 | |||
| f2ecefb7ee | |||
| 6b4340ce24 | |||
| e0d97486ec | |||
| b65c84c02e | |||
| 5a45ccf70d | |||
| f3393c46a5 | |||
| 587578ccfb | |||
| 522015c2d7 | |||
| 81ae687238 | |||
| 311637616b | |||
| 1cf97186dd | |||
| 62946f6359 | |||
| 9cdd1cbc45 | |||
| 482d516c2e | |||
| 3e906686db | |||
| b219aaf708 | |||
| b6f8876315 | |||
| 583a5d9223 | |||
| d42b9321f2 | |||
| 997dc53a49 | |||
| 95d89382c9 | |||
| ecc6f83130 | |||
| 7ac23e35f8 | |||
| eeb543c653 | |||
| bb567cafde | |||
| d71a9efd92 | |||
| a4d7693a2f | |||
| 42dbd8db0a | |||
| c9d48d00e7 | |||
| a21abaac84 | |||
| bca5e908f1 | |||
| 4e683dcc15 | |||
| bdf6a11491 | |||
| 91fdd60b07 | |||
| 9572073eda | |||
| 75f1c8baaa | |||
| e9250ab365 | |||
| a45f067719 | |||
| ad1c573678 | |||
| c2cd3b64ff | |||
| 48b18bf84e | |||
| 694980160b | |||
| 90d633fb2d | |||
| e10aa1ff58 | |||
| 7efb3e3f3d | |||
| 982639f215 | |||
| 9986d62a28 | |||
| 2c1f6e561a | |||
| c4f57d19db | |||
| 1a6e4bf14b | |||
| 47f9bc2017 | |||
| eb2fc0f02f | |||
| 8ba17f1026 | |||
| 914f7b842e | |||
| 4879b9bd90 | |||
| f5adbc08fa | |||
| 2881ca17a0 | |||
| 1b8b585367 | |||
| 2ae20c5fc4 | |||
| c92a3e566e | |||
| d5fcdf6edb | |||
| 3afec6c897 | |||
| ee83c19c7b | |||
| 144b72109b | |||
| 7b8c013918 | |||
| 3e792e6cd7 | |||
| ed70eb24c7 | |||
| f46d1a4aba | |||
| 306cedeb39 | |||
| 66f66c5481 | |||
| 8c20ba83de | |||
| cdee91f258 | |||
| 8f6ceece10 | |||
| f5d3e30972 | |||
| 408d620b17 | |||
| 1d079842f6 | |||
| b6395cf6f1 | |||
| d0f5d3270f | |||
| 6e6a427488 | |||
| 48f890dd80 | |||
| d4bd2d372c | |||
| 7a6c1b8b86 | |||
| 0d3bae3761 | |||
| 3e073c45ba | |||
| fc5ff3feb7 | |||
| 01365f995d | |||
| 712eaebb25 | |||
| 90603792d7 | |||
| 04d61eba3c | |||
| 24396031a7 | |||
| b244ffedd2 | |||
| ff3bc557b2 | |||
| f0564e0b06 | |||
| 31fb25a43d | |||
| a870513086 | |||
| 5cf3803860 | |||
| e045f096a9 | |||
| 70593177c7 | |||
| 953ae3e9bb | |||
| 64f3f1e9bc | |||
| 3fa9f9e9cf | |||
| 80511d5a19 | |||
| 4482fc0bcf | |||
| 73ee5676c6 | |||
| a3ab7cd14e | |||
| 818ee98b27 | |||
| 2a7a07d2fc | |||
| 4a165d0661 | |||
| 226b1307c0 | |||
| 1dd8aa3db8 | |||
| 1af69421fa | |||
| b43196cd1a | |||
| aab48f1cc1 | |||
| b402603b1d | |||
| 1195572318 | |||
| a2113d4acc | |||
| b57018f55c | |||
| eab14e28da | |||
| a8f670a9c9 | |||
| 2e5d89c8cd | |||
| cde4415052 | |||
| b5117af4b8 | |||
| d7327d62e2 | |||
| b1b1b88982 | |||
| 17b95e3ee5 | |||
| 3d36d1ce71 | |||
| 92b155dbb3 | |||
| 42c042c249 | |||
| 5c6de69e0e | |||
| b30f845924 | |||
| b8ed115f63 | |||
| cbe07b842f | |||
| de7c6483e0 | |||
| f94ae3f3fd | |||
| 4b4bf833a9 | |||
| d5237715a5 | |||
| 395a72b7d4 | |||
| f80ded2057 | |||
| a2d4207504 | |||
| 627b1cee10 | |||
| eb75f8a8ad | |||
| 5bc76de7d6 | |||
| 4e78b49cac | |||
| 637850d06c | |||
| 4144c22dc4 | |||
| 2ce727d994 | |||
| 1855ff133e | |||
| 51004bbd9d | |||
| 873d42344b | |||
| 27b6ba83a6 | |||
| eeaf7eb733 | |||
| 2b59cbf0f1 | |||
| ab2cfe89ce | |||
| aab3d494ff | |||
| fe4e8f3dd2 | |||
| 0c2c643ea8 | |||
| 3bff65d6b6 | |||
| 1069ff0c60 | |||
| 03ab243f9b | |||
| b9d8e2b336 | |||
| ac67813198 | |||
| 6c2ba51926 | |||
| c73897ce7f | |||
| 32bab1e7bf | |||
| e26d793976 | |||
| 9e3c0f5e26 | |||
| b14f5f5cd6 | |||
| 59c54db275 | |||
| 1ebf4d49e5 | |||
| c73ab05d70 | |||
| d29c2fc5af | |||
| ec04e858ef | |||
| 421db7fee2 | |||
| 3bf9c1cc10 | |||
| e68807d574 | |||
| e03516e22e | |||
| a403c4d9ee | |||
| d13c722ce3 | |||
| 2cf70453f8 | |||
| da149d32cf | |||
| 66de1e744a | |||
| cae07f3623 | |||
| c1fa9e595c | |||
| 80e6853f44 | |||
| ec60c90963 | |||
| 8edc154501 | |||
| 86d0ccb210 | |||
| 74af2e53a8 | |||
| 3ea771fe22 | |||
| ec6e459aa7 | |||
| 959fa185c3 | |||
| fa2171503b | |||
| 2c2b403da1 | |||
| 69cdb1268a | |||
| a5afa04f8f | |||
| aeda759086 | |||
| 0508d5a987 | |||
| 31a000b2b6 | |||
| 95daff3e96 | |||
| 04439d9dec | |||
| 681564189f | |||
| f6ee5123d7 | |||
| 296ac0b940 | |||
| 141555377b | |||
| c0428c3316 | |||
| e7249d9d94 | |||
| f3d7ad0aa9 | |||
| 5a66e90b56 | |||
| cffc3f7f5d | |||
| 0a5d37fd9b | |||
| 531d005169 | |||
| c717a102fc | |||
| 4c906f4040 | |||
| 159fb8f5ee | |||
| 0c3d1e3ec6 | |||
| dd7dc28828 | |||
| a99f792979 | |||
| 713cf0d4b2 | |||
| 10541ac743 | |||
| 7c6148dfd8 | |||
| fae6a1ebe9 | |||
| bc1cb402ab | |||
| e973c3ee67 | |||
| bcbbd98898 | |||
| 4131e15f0e | |||
| e8ec5794d2 | |||
| a9f1163743 | |||
| 4be02f5832 | |||
| efab20e335 | |||
| c47907c0c3 | |||
| 7faa9aa23a | |||
| 64515404e9 | |||
| db14c8a0a6 | |||
| 10bab59acc | |||
| 2affebd375 | |||
| 3f2f567364 | |||
| dee445c32c | |||
| d65fe3bae3 | |||
| 04daf10a92 | |||
| 1a3c6bfc73 | |||
| b797d3b0f0 | |||
| bcefaea416 | |||
| 12a2a69ad7 | |||
| 68151592a4 | |||
| 5d2a3482c7 | |||
| e93eb6aae6 | |||
| b7f269f9bd | |||
| bb4c459296 | |||
| 404340b02e | |||
| 50c6b23e35 | |||
| 95d798f49e | |||
| 42a9eaf72e | |||
| 86044fcc05 | |||
| 285a824858 | |||
| 37e8fa7b76 | |||
| 315df12fbe | |||
| 3a3e8e2ad5 | |||
| ec2226f06e | |||
| 22239bc2d1 | |||
| 238526bdc4 | |||
| b1988776ab | |||
| de1ba2de6f | |||
| 65a68131cc | |||
| c6ecf12c32 | |||
| 177d48acb5 | |||
| 695b630e79 | |||
| ea1b2ada50 | |||
| 912d1503e5 | |||
| 9c9bb7ca53 | |||
| c665cc99b9 | |||
| bd43ca236b | |||
| 9e7fb79859 | |||
| 9cd8a74bba | |||
| daa06cb320 | |||
| bc1da787de | |||
| 11a8bb59ce | |||
| a324e05e8f | |||
| 747abba4f7 | |||
| e9eb9890a0 | |||
| deaab07793 | |||
| 5e31a678bd | |||
| f0176c3520 | |||
| 142202f519 | |||
| 634053432e | |||
| 17fbfc969b | |||
| e8e3d5dfa6 | |||
| f82e4b332d | |||
| 433a398b45 | |||
| ca9d98f466 | |||
| e97653d3f3 | |||
| b98d3ae572 | |||
| 53223bb2ab | |||
| 848ab51753 | |||
| d56f7a211f | |||
| 98a5985ce9 | |||
| 71a5d56105 | |||
| c91bc0d8c6 | |||
| 57052b3b14 | |||
| a889d888ff | |||
| 2b2b4f6b6f | |||
| 273b6c0228 | |||
| 1c12e3d530 | |||
| 05ffaf7cef | |||
| 144287ba1c | |||
| f0da221621 | |||
| 518ce457df | |||
| 5efbfc86ad | |||
| 36a9ffe3aa | |||
| 65b63da93a | |||
| c900b6525d | |||
| 176f95fbbc | |||
| cfefe7a24c | |||
| 299ca398fa | |||
| bc9c9d2e72 | |||
| 6d7e23f254 | |||
| b89d32ce2b | |||
| 3136079ca3 | |||
| 7f741c04ed | |||
| 5a2831d0cb | |||
| 896f75b789 | |||
| ba319d8499 | |||
| 320955f8b7 | |||
| 6378f62acd | |||
| 7c0d1ab977 | |||
| 4d1ac04e5c | |||
| 385ef7361c | |||
| b6ceed5c6d | |||
| 6fd636b421 | |||
| 1978cb6df9 | |||
| 8de2e6a424 | |||
| 915f6a719d | |||
| 12f5157bfb | |||
| 968e1328dc | |||
| 6aaa5832a8 | |||
| cf6b9b7ab5 | |||
| 5b50562a9f | |||
| 89d34650c0 | |||
| 39b89ada6c | |||
| 698a9f1938 | |||
| c920b75142 | |||
| 5178caeda6 | |||
| 7158cfb5bf | |||
| 2c9541f6a0 | |||
| 0b3259fcc3 | |||
| 309302c212 | |||
| ce1b47979e | |||
| 85cfc73bbf | |||
| 65e477cfd0 | |||
| 107bea9c2e | |||
| 918140bc6d | |||
| 390460907d | |||
| 73ff053470 | |||
| 9377466ec8 | |||
| 37032810c9 | |||
| 9e222d222c | |||
| 55621054d8 | |||
| 8d057f5b8e | |||
| f04d723b29 | |||
| 2bd66cf625 | |||
| c9a2a17166 | |||
| c5b7d2fe8a | |||
| 978b3f835a | |||
| 765cd7a0f0 | |||
| f19e0628c5 | |||
| 2090cba743 | |||
| 8d0cfcf05d | |||
| 97e2e9a61d | |||
| a1f225d2ef | |||
| c93b41a88d | |||
| 3e8a29cdd5 | |||
| 3d16f97e4c | |||
| 2afa287b67 | |||
| 8457687025 | |||
| 76c6696ead | |||
| 5a94116c9b | |||
| eb613d3e8a | |||
| c8dc8396f9 | |||
| 8cfc14f4b1 | |||
| 1ffe8a7b60 | |||
| 094a3cfe5a | |||
| 8c638e7947 | |||
| d719ef8d03 | |||
| 6ec35e5175 | |||
| dd9fa6e949 | |||
| be204fd2f5 | |||
| 787414451e | |||
| 552ce3e495 | |||
| 29f5556634 | |||
| 1e1c296300 | |||
| 1b278f5c56 | |||
| c2117f0254 | |||
| 648520a6dc | |||
| 42c657cb58 | |||
| b6a46a5ec2 | |||
| 6fef9b09fa | |||
| 941237342d | |||
| 9501d23f35 | |||
| 0a13e01d95 | |||
| 1f2260048a | |||
| 44d78dccbb | |||
| 5eb888868f | |||
| 38b1203bb2 | |||
| 627de10e72 | |||
| 644eb35b97 | |||
| ca48d60627 | |||
| a500f88b4c | |||
| 808c741ed7 | |||
| 9eaef3447c | |||
| 364676ceae | |||
| e21756d685 | |||
| 7df206f533 | |||
| e3ceaa3f9a | |||
| 8b2d3db3f1 | |||
| 589941d6b2 | |||
| f046642ba7 | |||
| 3792aa1984 | |||
| 024dd74ae1 | |||
| cdc8e4adb8 | |||
| 8c02dfbb3f | |||
| 9a84f9e4ac | |||
| 9322a2006a | |||
| 67b373c6df | |||
| 0842a95dd6 | |||
| c3ef9f993b | |||
| 378e48e7aa | |||
| 7ad497ca3b | |||
| 0e3dedbc5b | |||
| 414bce38bb | |||
| 67da36a611 | |||
| dc32386590 | |||
| e9bdc8b319 | |||
| 4449f1ddcf | |||
| 6562a8769e | |||
| fcb71134c2 | |||
| b7dcf9576e | |||
| 2eea7abc27 | |||
| 71b5b528fd | |||
| d5b8e44572 | |||
| b85184eee0 | |||
| 2e1691c2f1 | |||
| c3cc78b7c2 | |||
| 297b4f2a81 | |||
| e1ea6a0676 | |||
| 4378b9e455 | |||
| f843b3858a | |||
| f5c9dce34a | |||
| 8a80a26523 | |||
| 2e22abaff9 | |||
| d38badb54b | |||
| 17aca44a3b | |||
| dbd5c71344 | |||
| 49e05bc206 | |||
| 2d51332bf7 | |||
| e4804db160 | |||
| 4e5795ab91 | |||
| acecda482d | |||
| da85771472 | |||
| e8aa2f922b | |||
| 62a335fab0 | |||
| d813078e91 | |||
| 685a68b7b8 | |||
| c420318267 | |||
| a52b352bd9 | |||
| b4d20e128b | |||
| 89704bebe9 | |||
| 62fdfe2519 | |||
| 7a01ccb5fb | |||
| 2c653f8c92 | |||
| e5f4a52be1 | |||
| 924ee9085f | |||
| 4bdeb26e74 | |||
| 91c017713c | |||
| a379c551cb | |||
| 8a44ea5a99 | |||
| f8bfc3520b | |||
| 31c35a7dd9 | |||
| a11ffb5ea5 | |||
| 01ced1cacd | |||
| 09ebd7462a | |||
| 0281c6dcde | |||
| 048c1f6985 | |||
| a9a7bc0b70 | |||
| 898a5c4561 | |||
| b0966c9114 | |||
| cffa9aa58e | |||
| 0652a1c367 | |||
| c5491eea97 | |||
| cf397e1cc7 | |||
| d9855f2ed6 | |||
| 047eb2eddf | |||
| 8c94b56080 | |||
| bedb056645 | |||
| e6de28bb6a | |||
| 2e5adca99a | |||
| 9e5a48af4b | |||
| abf68328e6 | |||
| 609217a3bb | |||
| f8cf82a005 | |||
| 3c1622fbfd | |||
| 0bea917ef1 | |||
| 4de3512e12 | |||
| b747031e2f | |||
| 66a140f402 | |||
| b40384c329 | |||
| 7c39e5726d | |||
| 338e3bbd42 | |||
| 99566a0f0f | |||
| 1a604e24a0 | |||
| 9ecfe90708 | |||
| f9e8ad7c12 | |||
| 68c6a01805 | |||
| 96609815ec | |||
| 558a7d99ff | |||
| e186adc90e | |||
| 7df5a7c646 | |||
| 06ba894e39 | |||
| 7b3152885d | |||
| a82856176e | |||
| 4e3d5ad11c | |||
| 133e192b98 | |||
| aa64da9869 | |||
| 92520a3c17 | |||
| 0c167f38b7 | |||
| f4e62afe8a | |||
| a9b706becf | |||
| 09bd7c696b | |||
| 2475706df4 | |||
| 8719bfe820 | |||
| cd2669230e | |||
| d8f996ddc7 | |||
| 1093818381 | |||
| 067ae8fc8e | |||
| f721284f70 | |||
| f930c9b5dc | |||
| bb7ca521c4 | |||
| 6c8b5e5e8a | |||
| ce45c92dae | |||
| 7de30bef7c | |||
| a8c6b2b619 | |||
| a236bc0b81 | |||
| 58d0ed18e6 | |||
| 0df9f5c797 | |||
| 0c4a608b65 | |||
| e48e15f02f | |||
| eda07ac57b | |||
| 820c18968a | |||
| be7da82cfc | |||
| bb84a51478 | |||
| 03b16875c7 | |||
| 84bb56d68b | |||
| d28be9cf44 | |||
| 58e5c988af | |||
| e995736012 | |||
| 493f3430bc | |||
| 350112a0d7 | |||
| 5ca6dae8c3 | |||
| 21f419dd4b | |||
| 0d082f5773 | |||
| a3517b273c | |||
| e1a0e51bc7 | |||
| 12f4dc74d2 | |||
| 2196a3d791 | |||
| c505561118 | |||
| 809a1041b3 | |||
| 29d0281932 | |||
| e562a7d72c | |||
| 7bec45dacf | |||
| 5a96c0e717 | |||
| a7c9c6142c | |||
| dfca248ebd | |||
| 4cc0807384 | |||
| 7cbafcd86b | |||
| 20ce4642ea | |||
| 4528cce71c | |||
| aeb0bf700f | |||
| bb27f85951 | |||
| 94e7531109 | |||
| fd23a61846 | |||
| de566a361a | |||
| d925c8dab8 | |||
| a25eae5d10 | |||
| 6f7b138488 | |||
| 52fb941237 | |||
| 0694f87b0d | |||
| ed13de2d5b | |||
| 8d7225c056 | |||
| 4755c42d70 | |||
| 510fc443e8 | |||
| 27ab8ea404 | |||
| eed2cdfe04 | |||
| 4c4a559125 | |||
| 4c1519ba1b | |||
| 2253b5713b | |||
| 7d4bf8356e | |||
| c31e4023c4 | |||
| 3bbc7faf11 | |||
| 497aca829d | |||
| 7e28db91c2 | |||
| c71a34a1e9 | |||
| 30e825db75 | |||
| ad536a945e | |||
| 5dbc5f42d2 | |||
| 154076a5d0 | |||
| d719c534d4 | |||
| d63c21ec41 | |||
| 1fa7397b32 | |||
| 5bf645252f | |||
| 9568237c8e | |||
| 0232197cdc | |||
| 773047dc69 | |||
| 98ebbf8b99 | |||
| 1a2eb48705 | |||
| c615ad18a8 | |||
| 0ba261d338 | |||
| dc29ee180e | |||
| 8d16fb21b9 | |||
| 33ac9c8811 | |||
| 4f10f852c7 | |||
| e11587e72e | |||
| 16131b2858 | |||
| e878f5be15 | |||
| 19d77f0d81 | |||
| 2f9e72e03e | |||
| 47e2c82551 | |||
| 9e4fd9fadb | |||
| edd4e37111 | |||
| 01d5c6a25b | |||
| 31a6c052f3 | |||
| 74758f5380 | |||
| b7a3b10498 | |||
| dad41d9e0e | |||
| 1c27674fd5 | |||
| c39242ecba | |||
| 9614110f10 | |||
| 39c3b760ac | |||
| 72659a481e | |||
| 55a439645c | |||
| eece05c118 | |||
| 7950c0d9d7 | |||
| 7cdd35cc8d | |||
| 6f304040b0 | |||
| d2a0438b71 | |||
| dea3319b9d | |||
| 58fab97447 | |||
| a41ad511f0 | |||
| 44b45faa9a | |||
| e747a345d8 | |||
| dadb9207b9 | |||
| 086c2f155d | |||
| cfa7cac149 | |||
| 95748744a4 | |||
| 34629d46f3 | |||
| af54b907d7 | |||
| 2930b0ad67 | |||
| e00bf92f05 | |||
| c1dcc52a6a | |||
| c351e58c6e | |||
| c60b2cb4d7 | |||
| 2c70b74814 | |||
| e83b8afdd3 | |||
| 4cf20efe2e | |||
| b7d4758dde | |||
| 559aef2ee3 | |||
| 7fce25a2e4 | |||
| aaaf7c5c37 | |||
| 4265ba12d7 | |||
| 85c5c7f309 | |||
| c838a800b6 | |||
| 22af41193e | |||
| b450c65c93 | |||
| 4ce89f56cc | |||
| 57014851a7 | |||
| e6b0cd69ae | |||
| 70e9410da0 | |||
| 38c027704e | |||
| 31411e334b | |||
| 987e680908 | |||
| d5df227df5 | |||
| 60f21d1a92 | |||
| a26d0d03eb | |||
| a7c5397641 | |||
| 0112f70c05 | |||
| 1647fff024 | |||
| 9fe54dc02c | |||
| 6691aaca1e | |||
| 82a22b2a87 | |||
| 2016297fce | |||
| fa6b621368 | |||
| a17981bc87 | |||
| f88dd50098 | |||
| fb06fa2c8b | |||
| ad4c2484f3 | |||
| 3be4e50b78 | |||
| 499df770cc | |||
| 6f9f40192e | |||
| 64752781ed | |||
| 87e9046e41 | |||
| 1c74e89f0d | |||
| 272ffe2ea2 | |||
| d7e24f0168 | |||
| 0cf40729fa | |||
| c00769e2b8 | |||
| 1096daaeb7 | |||
| 9560bbe23e | |||
| 0d78a6ba67 | |||
| e07a07f13e | |||
| 2c1409c2a4 | |||
| b44c7ab32c | |||
| c18cefbb0b | |||
| 5b23a4b318 | |||
| 91247cc080 | |||
| 30fa911832 | |||
| c4b7f50609 | |||
| 7ccc0b83ff | |||
| 45a0b25ee4 | |||
| ac59cc4633 | |||
| cdc5106ef9 | |||
| dff13626c4 | |||
| 436d55932d | |||
| 2a6fb3ba81 | |||
| ea9dd48da9 | |||
| 547f4d1180 | |||
| 1ff49e1faf | |||
| 64f7c6bf64 | |||
| 0270772463 | |||
| f3b2011fef | |||
| dbee9f6816 | |||
| 2d98a46d94 | |||
| baf6048377 | |||
| 02c6354003 | |||
| 641e746ee1 | |||
| 9f7df23788 | |||
| c42ae97bb2 | |||
| e6e34a7baf | |||
| 1a4113009a | |||
| bc85c1b421 | |||
| f6aea86aeb | |||
| 86c5f3675b | |||
| 4f71976958 | |||
| 2fd251e7b1 | |||
| 08ae1917e8 | |||
| e779c3ca17 | |||
| 173f4e8092 | |||
| de7edf9e78 | |||
| 6b6f1eeb9b | |||
| 0847ccc360 | |||
| f5a37ec3b4 | |||
| acb1cef19d | |||
| 20c32ea6ed | |||
| 35ea0b5447 | |||
| e818d37dd6 | |||
| 048a4ac1e3 | |||
| f665642e71 | |||
| 6fb604a9a0 | |||
| 02e3697817 | |||
| 1c72798229 | |||
| 761d3735a7 | |||
| 71c2770df0 | |||
| c6be71c4ff | |||
| 754ccaa9b4 | |||
| 798b950046 | |||
| c9c35eb74e | |||
| f1f5dacb6f | |||
| 405ae519dd | |||
| f3366178ea | |||
| 38fcfee9a4 | |||
| 25811ed6d4 | |||
| 3ca0ea2e50 | |||
| a917567e92 | |||
| a633aa69c3 | |||
| 32440d6993 | |||
| 7b20bc38a4 | |||
| be720257ca | |||
| 5e9d153c6a | |||
| 1a1fadcc2f | |||
| abdc257332 | |||
| 59ba9102a6 | |||
| daa92db25c | |||
| 3df10d1d0a | |||
| 824ce1cacf | |||
| 4a8f336118 | |||
| 6ec6f9501b | |||
| b1ecb2f0eb | |||
| 474ce10e7e | |||
| 3c40c22049 | |||
| 9281db73a7 | |||
| 45a557f9c0 | |||
| 7698e79143 | |||
| 1c584e937a | |||
| 6ef5c76e1a | |||
| eebc4951de | |||
| 7048281931 | |||
| 9f76e9e230 | |||
| 4e4f4e700b | |||
| bf60955e5e | |||
| c53af39c92 | |||
| d034874fb7 | |||
| 5ec9716eac | |||
| 8896ebadda | |||
| a6050e6f27 | |||
| 1e046c0033 | |||
| 34cc546f00 | |||
| b21aeedae2 | |||
| 0872002dae | |||
| c4e4e38c4f | |||
| 63d3c9b1e0 | |||
| ccd919d4d6 | |||
| 88bd5b2534 | |||
| 0b8d4850f0 | |||
| 26f8e5aa9e | |||
| 06b2bf0094 | |||
| e596d48729 | |||
| ceacdc8d08 | |||
| 6a2c5169a9 | |||
| dea307179f | |||
| 0ab6e29792 | |||
| e718766073 | |||
| d3cdca6b33 | |||
| e48b642101 | |||
| 9acb597d5d | |||
| 00d960d61e | |||
| 5b4e209816 | |||
| 21c67b4777 | |||
| 2f507091b2 | |||
| 8b80f73641 | |||
| 6a8483a898 | |||
| 71e2cbe856 | |||
| af7b53814d | |||
| 147cadee16 | |||
| 77478f9515 | |||
| 64809f553b | |||
| 78a2f2e8f0 | |||
| 28da925c52 | |||
| 9083f511b5 | |||
| c2bb717a69 | |||
| 2408aa48c1 | |||
| 45286468c9 | |||
| 6f8c007a66 | |||
| c48a81a068 | |||
| aa0208072c | |||
| d3e02e23e5 | |||
| f12475ea99 | |||
| d966519d95 | |||
| 3f14d4bf64 | |||
| dfc69c9c8e | |||
| 53de6d018b | |||
| 3e8e839cd1 | |||
| c53bf2b7e3 | |||
| 219ad40088 | |||
| d9042b3db2 | |||
| c59586a934 | |||
| 7440cb0963 | |||
| d8805dc801 | |||
| 45b0bb24c4 | |||
| 759a9bd365 | |||
| 48214f925b | |||
| 2c0e9faa32 | |||
| 80c3056daf | |||
| 61bd491969 | |||
| fd64a33d3e | |||
| 2e502ce82a | |||
| 3c79be2910 | |||
| e03a819176 | |||
| 6a41ab0b6d | |||
| 22b4e25c02 | |||
| e71e6835de | |||
| b449353d2f | |||
| 94c5211ee6 | |||
| 75130fcca3 | |||
| 3f172442be | |||
| b049688d31 | |||
| 04799c89dc | |||
| ac99dc0ac4 | |||
| 8dc5c4e00b | |||
| edac611444 | |||
| 37a8380521 | |||
| 60a1de42a2 | |||
| b2beeb653b | |||
| 6ff5dcfa50 | |||
| 9a5c105db9 | |||
| aea28ce499 | |||
| c8cc899128 | |||
| 55747edaae | |||
| 15af6502a0 | |||
| 8c4771a738 | |||
| 2fee75517d | |||
| 580f4120dc | |||
| f874a0ad57 | |||
| a56090e70f | |||
| f0d0e0637c | |||
| eae38fa0c6 | |||
| 93f0b0e2e8 | |||
| 979f8bcfee | |||
| b9f11298e8 | |||
| 84f8e3a4b4 | |||
| 551c58db4f | |||
| ff438a6219 | |||
| 84a68c5977 | |||
| 889eb7d846 | |||
| 6eaecc8793 | |||
| df6bf1e04d | |||
| ff1ccdb7ee | |||
| d7fc221a6b | |||
| fcd1366d26 | |||
| 8cd90280c1 | |||
| 4e4fb91a6f | |||
| 55e287c890 | |||
| cc7655d804 | |||
| 676d87129c | |||
| 4a1c1ebe3a | |||
| bf190810dd | |||
| 2227642c13 | |||
| 76ee695a59 | |||
| 0d68e90b59 | |||
| 3b80a01813 | |||
| 89ac54520a | |||
| dc08f49bbe | |||
| 9fb0b00e75 | |||
| 96dc279ebd | |||
| fe943ca010 | |||
| 3396e10613 | |||
| 6bfb0205fd | |||
| c4be764f61 | |||
| cb09fb570d | |||
| 7e80a4fe0f | |||
| 44d1527759 | |||
| 5e6fcc9669 |
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||||
* text=auto
|
* text=auto eol=lf
|
||||||
|
|
||||||
# Explicitly declare text files you want to always be normalized and converted to native line endings on checkout.
|
# Explicitly declare text files you want to always be normalized and converted to native line endings on checkout.
|
||||||
*.c text diff=cpp
|
*.c text diff=cpp
|
||||||
|
|||||||
@@ -1,21 +1,36 @@
|
|||||||
name: Build Android
|
name: Build Android
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# Game
|
# Game
|
||||||
game-windows:
|
game-windows:
|
||||||
name: Game (Android, Release ARM64)
|
name: Game (Android, Release ARM64)
|
||||||
runs-on: "windows-2019"
|
runs-on: "windows-2022"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Setup .NET Workload
|
||||||
|
run: |
|
||||||
|
dotnet workload install android
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=ARM64 -platform=Android -configuration=Release -buildtargets=FlaxGame
|
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -arch=ARM64 -platform=Android -configuration=Release -buildtargets=FlaxGame
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
name: Build iOS
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# Game
|
||||||
|
game-windows:
|
||||||
|
name: Game (iOS, Release ARM64)
|
||||||
|
runs-on: "macos-latest"
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup Vulkan
|
||||||
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Setup .NET Workload
|
||||||
|
run: |
|
||||||
|
dotnet workload install ios
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
|
- name: Checkout LFS
|
||||||
|
run: |
|
||||||
|
git lfs version
|
||||||
|
git lfs pull
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
./Development/Scripts/Mac/CallBuildTool.sh -build -log -arch=ARM64 -platform=iOS -configuration=Release -buildtargets=FlaxGame
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
name: Build Linux
|
name: Build Linux
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
@@ -18,13 +22,21 @@ jobs:
|
|||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxEditor
|
./Development/Scripts/Linux/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxEditor
|
||||||
|
|
||||||
# Game
|
# Game
|
||||||
game-linux:
|
game-linux:
|
||||||
@@ -38,10 +50,18 @@ jobs:
|
|||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Release -buildtargets=FlaxGame
|
./Development/Scripts/Linux/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Linux -configuration=Release -buildtargets=FlaxGame
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
name: Build macOS
|
name: Build macOS
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
@@ -12,13 +16,21 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -arch=x64 -platform=Mac -configuration=Development -buildtargets=FlaxEditor
|
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Mac -configuration=Development -buildtargets=FlaxEditor
|
||||||
|
|
||||||
# Game
|
# Game
|
||||||
game-mac:
|
game-mac:
|
||||||
@@ -29,10 +41,18 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -arch=x64 -platform=Mac -configuration=Release -buildtargets=FlaxGame
|
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Mac -configuration=Release -buildtargets=FlaxGame
|
||||||
|
|||||||
@@ -1,38 +1,58 @@
|
|||||||
name: Build Windows
|
name: Build Windows
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
editor-windows:
|
editor-windows:
|
||||||
name: Editor (Windows, Development x64)
|
name: Editor (Windows, Development x64)
|
||||||
runs-on: "windows-2019"
|
runs-on: "windows-2022"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxEditor
|
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxEditor
|
||||||
|
|
||||||
# Game
|
# Game
|
||||||
game-windows:
|
game-windows:
|
||||||
name: Game (Windows, Release x64)
|
name: Game (Windows, Release x64)
|
||||||
runs-on: "windows-2019"
|
runs-on: "windows-2022"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Release -buildtargets=FlaxGame
|
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -arch=x64 -platform=Windows -configuration=Release -buildtargets=FlaxGame
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ on:
|
|||||||
- cron: '15 4 * * *'
|
- cron: '15 4 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# Windows
|
# Windows
|
||||||
package-windows-editor:
|
package-windows-editor:
|
||||||
name: Editor (Windows)
|
name: Editor (Windows)
|
||||||
runs-on: "windows-2019"
|
runs-on: "windows-2022"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -19,6 +23,14 @@ jobs:
|
|||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
.\PackageEditor.bat -arch=x64 -platform=Windows -deployOutput=Output
|
.\PackageEditor.bat -arch=x64 -platform=Windows -deployOutput=Output
|
||||||
@@ -34,7 +46,7 @@ jobs:
|
|||||||
path: Output/EditorDebugSymbols.zip
|
path: Output/EditorDebugSymbols.zip
|
||||||
package-windows-game:
|
package-windows-game:
|
||||||
name: Game (Windows)
|
name: Game (Windows)
|
||||||
runs-on: "windows-2019"
|
runs-on: "windows-2022"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -44,6 +56,14 @@ jobs:
|
|||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
.\PackagePlatforms.bat -arch=x64 -platform=Windows -deployOutput=Output
|
.\PackagePlatforms.bat -arch=x64 -platform=Windows -deployOutput=Output
|
||||||
@@ -72,6 +92,14 @@ jobs:
|
|||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./PackageEditor.sh -arch=x64 -platform=Linux -deployOutput=Output
|
./PackageEditor.sh -arch=x64 -platform=Linux -deployOutput=Output
|
||||||
@@ -98,6 +126,14 @@ jobs:
|
|||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./PackagePlatforms.sh -arch=x64 -platform=Linux -deployOutput=Output
|
./PackagePlatforms.sh -arch=x64 -platform=Linux -deployOutput=Output
|
||||||
@@ -120,6 +156,14 @@ jobs:
|
|||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./PackageEditor.command -arch=x64 -platform=Mac -deployOutput=Output
|
./PackageEditor.command -arch=x64 -platform=Mac -deployOutput=Output
|
||||||
@@ -140,6 +184,14 @@ jobs:
|
|||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Setup Vulkan
|
- name: Setup Vulkan
|
||||||
uses: ./.github/actions/vulkan
|
uses: ./.github/actions/vulkan
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./PackagePlatforms.command -arch=x64 -platform=Mac -deployOutput=Output
|
./PackagePlatforms.command -arch=x64 -platform=Mac -deployOutput=Output
|
||||||
|
|||||||
+39
-16
@@ -1,6 +1,10 @@
|
|||||||
name: Tests
|
name: Tests
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# Tests on Linux
|
# Tests on Linux
|
||||||
@@ -10,6 +14,14 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
@@ -22,41 +34,52 @@ jobs:
|
|||||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./GenerateProjectFiles.sh -vs2019
|
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs
|
||||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget
|
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget
|
||||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Debug -buildtargets=FlaxEditor -BuildBindingsOnly
|
dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
|
||||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Debug -buildtargets="FlaxEngine.Tests"
|
dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
|
||||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Debug -buildtargets="Flax.Build.Tests"
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
Binaries/Editor/Linux/Development/FlaxTests
|
${GITHUB_WORKSPACE}/Binaries/Editor/Linux/Development/FlaxTests
|
||||||
mono Source/Platforms/DotNet/NUnit/nunit3-console.exe Binaries/Tools/FlaxEngine.Tests.dll --framework=mono-4.0
|
dotnet test -f net7.0 Binaries/Tests/Flax.Build.Tests.dll
|
||||||
mono Source/Platforms/DotNet/NUnit/nunit3-console.exe Binaries/Tools/Flax.Build.Tests.dll --framework=mono-4.0
|
cp Binaries/Editor/Linux/Development/FlaxEngine.CSharp.dll Binaries/Tests
|
||||||
|
cp Binaries/Editor/Linux/Development/FlaxEngine.CSharp.runtimeconfig.json Binaries/Tests
|
||||||
|
cp Binaries/Editor/Linux/Development/Newtonsoft.Json.dll Binaries/Tests
|
||||||
|
dotnet test -f net7.0 Binaries/Tests/FlaxEngine.CSharp.dll
|
||||||
- name: Test UseLargeWorlds
|
- name: Test UseLargeWorlds
|
||||||
run: |
|
run: |
|
||||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget -UseLargeWorlds=true
|
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget -UseLargeWorlds=true
|
||||||
Binaries/Editor/Linux/Development/FlaxTests
|
${GITHUB_WORKSPACE}/Binaries/Editor/Linux/Development/FlaxTests
|
||||||
|
|
||||||
# Tests on Windows
|
# Tests on Windows
|
||||||
tests-windows:
|
tests-windows:
|
||||||
name: Tests (Windows)
|
name: Tests (Windows)
|
||||||
runs-on: "windows-2019"
|
runs-on: "windows-2022"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v3
|
||||||
|
with:
|
||||||
|
dotnet-version: 7.0.x
|
||||||
|
- name: Print .NET info
|
||||||
|
run: |
|
||||||
|
dotnet --info
|
||||||
|
dotnet workload --info
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
run: |
|
run: |
|
||||||
git lfs version
|
git lfs version
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
.\GenerateProjectFiles.bat -vs2019
|
.\GenerateProjectFiles.bat -vs2022 -log -verbose -printSDKs
|
||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxTestsTarget
|
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxTestsTarget
|
||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Debug -buildtargets=FlaxEditor -BuildBindingsOnly
|
dotnet msbuild Source\Tools\Flax.Build.Tests\Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
|
||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Debug -buildtargets="FlaxEngine.Tests"
|
|
||||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Debug -buildtargets="Flax.Build.Tests"
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
Binaries\Editor\Win64\Development\FlaxTests.exe
|
.\Binaries\Editor\Win64\Development\FlaxTests.exe
|
||||||
Source\Platforms\DotNet\NUnit\nunit3-console.exe Binaries\Tools\FlaxEngine.Tests.dll --framework=net-4.5.2
|
dotnet test -f net7.0 Binaries\Tests\Flax.Build.Tests.dll
|
||||||
Source\Platforms\DotNet\NUnit\nunit3-console.exe Binaries\Tools\Flax.Build.Tests.dll --framework=net-4.5.2
|
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.dll Binaries\Tests
|
||||||
|
xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.runtimeconfig.json Binaries\Tests
|
||||||
|
xcopy /y Binaries\Editor\Win64\Development\Newtonsoft.Json.dll Binaries\Tests
|
||||||
|
dotnet test -f net7.0 Binaries\Tests\FlaxEngine.CSharp.dll
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
obj/
|
obj/
|
||||||
Cache/
|
Cache/
|
||||||
Binaries/
|
Binaries/
|
||||||
|
Output/
|
||||||
Logs/
|
Logs/
|
||||||
|
Source/*.Gen.*
|
||||||
Source/*.csproj
|
Source/*.csproj
|
||||||
/Package_*/
|
/Package_*/
|
||||||
!Source/Engine/Debug
|
!Source/Engine/Debug
|
||||||
@@ -23,6 +25,7 @@ PackagePlatforms_Cert.bat
|
|||||||
*.opendb
|
*.opendb
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
*.xcodeproj
|
*.xcodeproj
|
||||||
|
launchSettings.json
|
||||||
|
|
||||||
# NUNIT
|
# NUNIT
|
||||||
*.VisualState.xml
|
*.VisualState.xml
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Deferred Shading: Defines
|
@0// Deferred Shading: Defines
|
||||||
@1// Deferred Shading: Includes
|
@1// Deferred Shading: Includes
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Distortion: Defines
|
@0// Distortion: Defines
|
||||||
@1// Distortion: Includes
|
@1// Distortion: Includes
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Forward Shading: Defines
|
@0// Forward Shading: Defines
|
||||||
#define MAX_LOCAL_LIGHTS 4
|
#define MAX_LOCAL_LIGHTS 4
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Global Illumination: Defines
|
@0// Global Illumination: Defines
|
||||||
#define USE_GI 1
|
#define USE_GI 1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Lightmap: Defines
|
@0// Lightmap: Defines
|
||||||
#define CAN_USE_LIGHTMAP 1
|
#define CAN_USE_LIGHTMAP 1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Motion Vectors: Defines
|
@0// Motion Vectors: Defines
|
||||||
@1// Motion Vectors: Includes
|
@1// Motion Vectors: Includes
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Tessellation: Defines
|
@0// Tessellation: Defines
|
||||||
#define TessalationProjectOntoPlane(planeNormal, planePosition, pointToProject) pointToProject - dot(pointToProject - planePosition, planeNormal) * planeNormal
|
#define TessalationProjectOntoPlane(planeNormal, planePosition, pointToProject) pointToProject - dot(pointToProject - planePosition, planeNormal) * planeNormal
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -10,8 +10,7 @@ if [ $testfilesize -le 1000 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Compile the build tool.
|
# Compile the build tool.
|
||||||
xbuild /nologo /verbosity:quiet "Source/Tools/Flax.Build/Flax.Build.csproj" /property:Configuration=Release /property:Platform=AnyCPU /target:Build
|
dotnet msbuild /nologo /verbosity:quiet "Source/Tools/Flax.Build/Flax.Build.csproj" /property:Configuration=Release /target:Restore,Build /property:RestorePackagesConfig=True /p:RuntimeIdentifiers=linux-x64
|
||||||
|
|
||||||
# Run the build tool using the provided arguments.
|
# Run the build tool using the provided arguments.
|
||||||
#mono --debug --debugger-agent=transport=dt_socket,server=y,address=127.0.0.1:55555 Binaries/Tools/Flax.Build.exe "$@"
|
Binaries/Tools/Flax.Build "$@"
|
||||||
mono Binaries/Tools/Flax.Build.exe "$@"
|
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ if [ $testfilesize -le 1000 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Compile the build tool.
|
# Compile the build tool.
|
||||||
xbuild /nologo /verbosity:quiet "Source/Tools/Flax.Build/Flax.Build.csproj" /property:Configuration=Release /property:Platform=AnyCPU /target:Build
|
dotnet msbuild /nologo /verbosity:quiet "Source/Tools/Flax.Build/Flax.Build.csproj" /property:Configuration=Release /target:Restore,Build /property:RestorePackagesConfig=True /p:RuntimeIdentifiers=osx-x64
|
||||||
|
|
||||||
# Run the build tool using the provided arguments.
|
# Run the build tool using the provided arguments.
|
||||||
#mono --debug --debugger-agent=transport=dt_socket,server=y,address=127.0.0.1:55555 Binaries/Tools/Flax.Build.exe "$@"
|
Binaries/Tools/Flax.Build "$@"
|
||||||
mono Binaries/Tools/Flax.Build.exe "$@"
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Copyright (c) 2012-2023 Wojciech Figat. All rights reserved
|
# Copyright (c) 2012-2023 Wojciech Figat. All rights reserved
|
||||||
|
|
||||||
# Fix mono bin to be in a path
|
# Fix mono bin to be in a path
|
||||||
export PATH=/Library/Frameworks/Mono.framework/Versions/Current/Commands:$PATH
|
#export PATH=/Library/Frameworks/Mono.framework/Versions/Current/Commands:$PATH
|
||||||
|
|
||||||
echo "Running Flax.Build $*"
|
echo "Running Flax.Build $*"
|
||||||
mono Binaries/Tools/Flax.Build.exe "$@"
|
Binaries/Tools/Flax.Build "$@"
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ fc /b Cache\Intermediate\Build\Flax.Build.Files.txt Cache\Intermediate\Build\Fla
|
|||||||
if not errorlevel 1 goto SkipClean
|
if not errorlevel 1 goto SkipClean
|
||||||
|
|
||||||
copy /y Cache\Intermediate\Build\Flax.Build.Files.txt Cache\Intermediate\Build\Flax.Build.PrevFiles.txt >nul
|
copy /y Cache\Intermediate\Build\Flax.Build.Files.txt Cache\Intermediate\Build\Flax.Build.PrevFiles.txt >nul
|
||||||
%MSBUILD_PATH% /nologo /verbosity:quiet Source\Tools\Flax.Build\Flax.Build.csproj /property:Configuration=Release /property:Platform=AnyCPU /target:Clean
|
%MSBUILD_PATH% /nologo /verbosity:quiet Source\Tools\Flax.Build\Flax.Build.csproj /property:Configuration=Release /target:Restore,Clean /property:RestorePackagesConfig=True /p:RuntimeIdentifiers=win-x64
|
||||||
:SkipClean
|
:SkipClean
|
||||||
%MSBUILD_PATH% /nologo /verbosity:quiet Source\Tools\Flax.Build\Flax.Build.csproj /property:Configuration=Release /property:Platform=AnyCPU /target:Build
|
%MSBUILD_PATH% /nologo /verbosity:quiet Source\Tools\Flax.Build\Flax.Build.csproj /property:Configuration=Release /target:Build /property:SelfContained=False /property:RuntimeIdentifiers=win-x64
|
||||||
if errorlevel 1 goto Error_CompilationFailed
|
if errorlevel 1 goto Error_CompilationFailed
|
||||||
|
|
||||||
Binaries\Tools\Flax.Build.exe %*
|
Binaries\Tools\Flax.Build.exe %*
|
||||||
|
|||||||
+4
-3
@@ -2,8 +2,8 @@
|
|||||||
"Name": "Flax",
|
"Name": "Flax",
|
||||||
"Version": {
|
"Version": {
|
||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 5,
|
"Minor": 6,
|
||||||
"Build": 6339
|
"Build": 6344
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
"EditorTarget": "FlaxEditor",
|
"EditorTarget": "FlaxEditor",
|
||||||
"Configuration": {
|
"Configuration": {
|
||||||
"UseCSharp": true,
|
"UseCSharp": true,
|
||||||
"UseLargeWorlds": false
|
"UseLargeWorlds": false,
|
||||||
|
"UseDotNet": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,6 +278,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=heightfield/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=heightfield/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Heightmap/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Heightmap/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=HLSL/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=HLSL/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=HRTF/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inlines/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inlines/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inscattering/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inscattering/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Interpolants/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Interpolants/@EntryIndexedValue">True</s:Boolean>
|
||||||
@@ -305,6 +306,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=occluder/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=occluder/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=offseted/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=offseted/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=offsetted/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=offsetted/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=opcode/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Perlin/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Perlin/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=phong/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=phong/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=preload/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=preload/@EntryIndexedValue">True</s:Boolean>
|
||||||
@@ -320,6 +322,9 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reimports/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reimports/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=reimported/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=reimported/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=renderable/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=renderable/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=retarget/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=retargeting/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=retargets/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=reverb/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=reverb/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=rigidbodies/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=rigidbodies/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=rigidbody/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=rigidbody/@EntryIndexedValue">True</s:Boolean>
|
||||||
@@ -334,6 +339,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Skybox/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Skybox/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Skyboxes/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Skyboxes/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=slerp/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=slerp/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Spatialization/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=splatmap/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=splatmap/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=splatmaps/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=splatmaps/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=SRGB/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=SRGB/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@@ -26,16 +26,12 @@ This repository contains full source code of the Flax Engine (excluding NDA-prot
|
|||||||
|
|
||||||
Follow the instructions below to compile and run the engine from source.
|
Follow the instructions below to compile and run the engine from source.
|
||||||
|
|
||||||
## Flax plugin for Visual Studio
|
|
||||||
|
|
||||||
Flax Visual Studio extension provides better programming workflow, C# scripts debugging functionality and allows to attach to running engine instance to debug C# source. This extension is available to download [here](https://marketplace.visualstudio.com/items?itemName=Flax.FlaxVS).
|
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
* Install Visual Studio 2015 or newer
|
* Install Visual Studio 2022 or newer
|
||||||
* Install Windows 8.1 SDK or newer (via Visual Studio Installer)
|
* Install Windows 8.1 SDK or newer (via Visual Studio Installer)
|
||||||
* Install Microsoft Visual C++ 2015 v140 toolset or newer (via Visual Studio Installer)
|
* Install Microsoft Visual C++ 2015 v140 toolset or newer (via Visual Studio Installer)
|
||||||
* Install .Net Framework 4.5.2 SDK/Targeting Pack (via Visual Studio Installer)
|
* Install .Net 7 SDK (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||||
* Install Git with LFS
|
* Install Git with LFS
|
||||||
* Clone repo (with LFS)
|
* Clone repo (with LFS)
|
||||||
* Run **GenerateProjectFiles.bat**
|
* Run **GenerateProjectFiles.bat**
|
||||||
@@ -44,16 +40,13 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
|||||||
* Compile Flax project (hit F7 or CTRL+Shift+B)
|
* Compile Flax project (hit F7 or CTRL+Shift+B)
|
||||||
* Run Flax (hit F5 key)
|
* Run Flax (hit F5 key)
|
||||||
|
|
||||||
> When building on Windows to support Vulkan rendering, first install the Vulkan SDK then set an environment variable to provide the path to the SDK prior to running GenerateProjectFiles.bat: `set VULKAN_SDK=%sdk_path%`
|
|
||||||
|
|
||||||
## Linux
|
## Linux
|
||||||
|
|
||||||
* Install Visual Studio Code
|
* Install Visual Studio Code
|
||||||
* Install Mono
|
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||||
* Ubuntu: see the instructions here: ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable))
|
* Ubuntu: `sudo apt install dotnet-sdk-7.0`
|
||||||
* Arch: `sudo pacman -S mono`
|
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||||
* Install Vulkan SDK
|
* Ubuntu: `sudo apt install vulkan-sdk`
|
||||||
* Ubuntu: see the instructions here: ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
|
||||||
* Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers`
|
* Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers`
|
||||||
* Install Git with LFS
|
* Install Git with LFS
|
||||||
* Ubuntu: `sudo apt-get install git git-lfs`
|
* Ubuntu: `sudo apt-get install git git-lfs`
|
||||||
@@ -73,13 +66,31 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
|||||||
## Mac
|
## Mac
|
||||||
|
|
||||||
* Install XCode
|
* Install XCode
|
||||||
* Install Mono ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable))
|
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||||
* Clone repo (with LFS)
|
* Clone repo (with LFS)
|
||||||
* Run `GenerateProjectFiles.command`
|
* Run `GenerateProjectFiles.command`
|
||||||
* Open workspace with XCode or Visual Studio Code
|
* Open workspace with XCode or Visual Studio Code
|
||||||
* Build and run (configuration `Editor.Mac.Development`)
|
* Build and run (configuration `Editor.Mac.Development`)
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
|
||||||
|
* `Could not execute because the specified command or file was not found.`
|
||||||
|
|
||||||
|
Restart PC - ensure DotNet is added to PATH for command line tools execution.
|
||||||
|
|
||||||
|
* `Microsoft.NET.TargetFrameworkInference.targets(141,5): error NETSDK1045: The current .NET SDK does not support targeting .NET 7.0. Either target .NET 5.0 or lower, or use a version of the .NET SDK that supports .NET 7.0`
|
||||||
|
|
||||||
|
Use Visual Studio 2022, older versions are not supported by .NET SDK 7.
|
||||||
|
|
||||||
|
* `Building for Windows without Vulkan rendering backend (Vulkan SDK is missing)`
|
||||||
|
|
||||||
|
Install the Vulkan SDK then set an environment variable to provide the path to the SDK prior to running GenerateProjectFiles.bat: `set VULKAN_SDK=%sdk_path%`.
|
||||||
|
|
||||||
|
* `The NuGetSdkResolver did not resolve this SDK`
|
||||||
|
|
||||||
|
Install `.NET SDK`, `NuGet package manager` and `NuGet targets and build tasks` in Visual Studio components.
|
||||||
|
|
||||||
## Workspace directory
|
## Workspace directory
|
||||||
|
|
||||||
- **Binaries/** - executable files
|
- **Binaries/** - executable files
|
||||||
@@ -93,7 +104,6 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
|||||||
- **Content/** - assets and binary files used by the engine and editor
|
- **Content/** - assets and binary files used by the engine and editor
|
||||||
- **Development/** - engine development files
|
- **Development/** - engine development files
|
||||||
- **Scripts/** - utility scripts
|
- **Scripts/** - utility scripts
|
||||||
- **packages/** - NuGet packages cache location
|
|
||||||
- **Source/** - source code location
|
- **Source/** - source code location
|
||||||
- **Editor/** - Flax Editor source code
|
- **Editor/** - Flax Editor source code
|
||||||
- **Engine/** - Flax Engine source code
|
- **Engine/** - Flax Engine source code
|
||||||
@@ -103,7 +113,6 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
|||||||
- ***PlatformName*/** - per-platform files
|
- ***PlatformName*/** - per-platform files
|
||||||
- **Binaries/** - per-platform binaries
|
- **Binaries/** - per-platform binaries
|
||||||
- **Game/** - Flax Game binaries
|
- **Game/** - Flax Game binaries
|
||||||
- **Mono/** - Mono runtime files and data
|
|
||||||
- **ThirdParty/** - prebuilt 3rd Party binaries
|
- **ThirdParty/** - prebuilt 3rd Party binaries
|
||||||
- **Shaders/** - shaders source code
|
- **Shaders/** - shaders source code
|
||||||
- **ThirdParty/** - 3rd Party source code
|
- **ThirdParty/** - 3rd Party source code
|
||||||
|
|||||||
@@ -1,49 +1,103 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "EditorAnalytics.h"
|
#include "EditorAnalytics.h"
|
||||||
#include "EditorAnalyticsController.h"
|
#include "Editor/Editor.h"
|
||||||
|
#include "Editor/ProjectInfo.h"
|
||||||
|
#include "Editor/Cooker/GameCooker.h"
|
||||||
|
#include "Engine/Threading/Task.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
|
#include "Engine/Platform/MemoryStats.h"
|
||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Core/Math/Vector2.h"
|
#include "Engine/Core/Math/Vector2.h"
|
||||||
#include "Engine/Core/Types/DateTime.h"
|
#include "Engine/Core/Types/DateTime.h"
|
||||||
#include "Engine/Core/Types/TimeSpan.h"
|
#include "Engine/Core/Types/TimeSpan.h"
|
||||||
#include "Editor/Editor.h"
|
|
||||||
#include "Editor/ProjectInfo.h"
|
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Engine/Engine/Globals.h"
|
||||||
#include "Engine/Graphics/GPUDevice.h"
|
#include "Engine/Graphics/GPUDevice.h"
|
||||||
#include "Engine/Utilities/StringConverter.h"
|
#include "Engine/Utilities/StringConverter.h"
|
||||||
|
#include "Engine/Utilities/TextWriter.h"
|
||||||
|
#include "Engine/ShadowsOfMordor/Builder.h"
|
||||||
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "FlaxEngine.Gen.h"
|
#include "FlaxEngine.Gen.h"
|
||||||
#include <ThirdParty/UniversalAnalytics/universal-analytics.h>
|
#include <ThirdParty/UniversalAnalytics/http.h>
|
||||||
|
|
||||||
#define FLAX_EDITOR_GOOGLE_ID "UA-88357703-3"
|
// Docs:
|
||||||
|
// https://developers.google.com/analytics/devguides/collection/ga4
|
||||||
|
// https://developers.google.com/analytics/devguides/collection/protocol/ga4
|
||||||
|
|
||||||
// Helper doc: https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
|
// [GA4] Flax Editor
|
||||||
|
#define GA_MEASUREMENT_ID "G-2SNY6RW6VX"
|
||||||
|
#define GA_API_SECRET "wFlau4khTPGFRnx-AIZ1zg"
|
||||||
|
#define GA_DEBUG 0
|
||||||
|
#if GA_DEBUG
|
||||||
|
#define GA_URL "https://www.google-analytics.com/debug/mp/collect"
|
||||||
|
#else
|
||||||
|
#define GA_URL "https://www.google-analytics.com/mp/collect"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace EditorAnalyticsImpl
|
namespace
|
||||||
{
|
{
|
||||||
UATracker Tracker = nullptr;
|
StringAnsi Url;
|
||||||
|
|
||||||
StringAnsi ClientId;
|
StringAnsi ClientId;
|
||||||
StringAnsi ProjectName;
|
|
||||||
StringAnsi ScreenResolution;
|
|
||||||
StringAnsi UserLanguage;
|
|
||||||
StringAnsi GPU;
|
|
||||||
DateTime SessionStartTime;
|
DateTime SessionStartTime;
|
||||||
|
|
||||||
CriticalSection Locker;
|
CriticalSection Locker;
|
||||||
bool IsSessionActive = false;
|
bool IsSessionActive = false;
|
||||||
EditorAnalyticsController Controller;
|
TextWriterANSI JsonBuffer;
|
||||||
Array<char> TmpBuffer;
|
curl_slist* CurlHttpHeadersList = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace EditorAnalyticsImpl;
|
size_t curl_null_data_handler(char* ptr, size_t size, size_t nmemb, void* userdata)
|
||||||
|
{
|
||||||
|
return nmemb * size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterGameCookingStart(GameCooker::EventType type)
|
||||||
|
{
|
||||||
|
if (type == GameCooker::EventType::BuildStarted)
|
||||||
|
{
|
||||||
|
auto& data = *GameCooker::GetCurrentData();
|
||||||
|
StringAnsi name = "Build " + StringAnsi(ToString(data.Platform));
|
||||||
|
const Pair<const char*, const char*> params[1] = { { "GameCooker", name.Get() } };
|
||||||
|
EditorAnalytics::SendEvent("Actions", ToSpan(params, ARRAY_COUNT(params)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterLightmapsBuildingStart()
|
||||||
|
{
|
||||||
|
const Pair<const char*, const char*> params[1] = { { "ShadowsOfMordor", "Build" }, };
|
||||||
|
EditorAnalytics::SendEvent("Actions", ToSpan(params, ARRAY_COUNT(params)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterError(LogType type, const StringView& msg)
|
||||||
|
{
|
||||||
|
if (type == LogType::Error && false)
|
||||||
|
{
|
||||||
|
StringAnsi value(msg);
|
||||||
|
const int32 MaxLength = 300;
|
||||||
|
if (msg.Length() > MaxLength)
|
||||||
|
value = value.Substring(0, MaxLength);
|
||||||
|
value.Replace('\n', ' ');
|
||||||
|
value.Replace('\r', ' ');
|
||||||
|
const Pair<const char*, const char*> params[1] = { { "Error", value.Get() }, };
|
||||||
|
EditorAnalytics::SendEvent("Errors", ToSpan(params, ARRAY_COUNT(params)));
|
||||||
|
}
|
||||||
|
else if (type == LogType::Fatal)
|
||||||
|
{
|
||||||
|
StringAnsi value(msg);
|
||||||
|
const int32 MaxLength = 300;
|
||||||
|
if (msg.Length() > MaxLength)
|
||||||
|
value = value.Substring(0, MaxLength);
|
||||||
|
value.Replace('\n', ' ');
|
||||||
|
value.Replace('\r', ' ');
|
||||||
|
const Pair<const char*, const char*> params[1] = { { "Fatal", value.Get() }, };
|
||||||
|
EditorAnalytics::SendEvent("Errors", ToSpan(params, ARRAY_COUNT(params)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class EditorAnalyticsService : public EngineService
|
class EditorAnalyticsService : public EngineService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
EditorAnalyticsService()
|
EditorAnalyticsService()
|
||||||
: EngineService(TEXT("Editor Analytics"))
|
: EngineService(TEXT("Editor Analytics"))
|
||||||
{
|
{
|
||||||
@@ -57,192 +111,141 @@ EditorAnalyticsService EditorAnalyticsServiceInstance;
|
|||||||
|
|
||||||
bool EditorAnalytics::IsSessionActive()
|
bool EditorAnalytics::IsSessionActive()
|
||||||
{
|
{
|
||||||
return EditorAnalyticsImpl::IsSessionActive;
|
return ::IsSessionActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorAnalytics::StartSession()
|
void EditorAnalytics::StartSession()
|
||||||
{
|
{
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
|
if (::IsSessionActive)
|
||||||
if (EditorAnalyticsImpl::IsSessionActive)
|
|
||||||
return;
|
return;
|
||||||
|
PROFILE_CPU();
|
||||||
|
|
||||||
// Prepare client metadata
|
// Prepare client metadata
|
||||||
if (ClientId.IsEmpty())
|
ClientId = Platform::GetUniqueDeviceId().ToString(Guid::FormatType::N).ToStringAnsi();
|
||||||
{
|
StringAnsi ProjectName = Editor::Project->Name.ToStringAnsi();
|
||||||
ClientId = Platform::GetUniqueDeviceId().ToString(Guid::FormatType::N).ToStringAnsi();
|
const auto desktopSize = Platform::GetDesktopSize();
|
||||||
}
|
StringAnsi ScreenResolution = StringAnsi::Format("{0}x{1}", (int32)desktopSize.X, (int32)desktopSize.Y);
|
||||||
if (ScreenResolution.IsEmpty())
|
const auto memoryStats = Platform::GetMemoryStats();
|
||||||
{
|
StringAnsi Memory = StringAnsi::Format("{0} GB", (int32)(memoryStats.TotalPhysicalMemory / 1024 / 1024 / 1000));
|
||||||
const auto desktopSize = Platform::GetDesktopSize();
|
StringAnsi UserLocale = Platform::GetUserLocaleName().ToStringAnsi();
|
||||||
ScreenResolution = StringAnsi(StringUtils::ToString((int32)desktopSize.X)) + "x" + StringAnsi(StringUtils::ToString((int32)desktopSize.Y));
|
StringAnsi GPU;
|
||||||
}
|
if (GPUDevice::Instance && GPUDevice::Instance->GetState() == GPUDevice::DeviceState::Ready)
|
||||||
if (UserLanguage.IsEmpty())
|
GPU = StringAsANSI<>(GPUDevice::Instance->GetAdapter()->GetDescription().GetText()).Get();
|
||||||
{
|
|
||||||
UserLanguage = Platform::GetUserLocaleName().ToStringAnsi();
|
|
||||||
}
|
|
||||||
if (GPU.IsEmpty())
|
|
||||||
{
|
|
||||||
const auto gpu = GPUDevice::Instance;
|
|
||||||
if (gpu && gpu->GetState() == GPUDevice::DeviceState::Ready)
|
|
||||||
GPU = StringAsANSI<>(gpu->GetAdapter()->GetDescription().GetText()).Get();
|
|
||||||
}
|
|
||||||
if (ProjectName.IsEmpty())
|
|
||||||
{
|
|
||||||
ProjectName = Editor::Project->Name.ToStringAnsi();
|
|
||||||
}
|
|
||||||
SessionStartTime = DateTime::Now();
|
SessionStartTime = DateTime::Now();
|
||||||
|
StringAnsiView EngineVersion = FLAXENGINE_VERSION_TEXT;
|
||||||
// Initialize the analytics tracker
|
|
||||||
Tracker = createTracker(FLAX_EDITOR_GOOGLE_ID, ClientId.Get(), nullptr);
|
|
||||||
Tracker->user_agent = "Flax Editor";
|
|
||||||
|
|
||||||
// Store these options permanently (for the lifetime of the tracker)
|
|
||||||
setTrackerOption(Tracker, UA_OPTION_QUEUE, 1);
|
|
||||||
UASettings GlobalSettings =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ UA_DOCUMENT_PATH, 0, "Flax Editor" },
|
|
||||||
{ UA_DOCUMENT_TITLE, 0, "Flax Editor" },
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
{ UA_USER_AGENT, 0, "Windows " FLAXENGINE_VERSION_TEXT },
|
StringAnsiView PlatformName = "Windows";
|
||||||
#elif PLATFORM_LINUX
|
#elif PLATFORM_LINUX
|
||||||
{ UA_USER_AGENT, 0, "Linux " FLAXENGINE_VERSION_TEXT },
|
StringAnsiView PlatformName = "Linux";
|
||||||
#elif PLATFORM_MAC
|
#elif PLATFORM_MAC
|
||||||
{ UA_USER_AGENT, 0, "Mac " FLAXENGINE_VERSION_TEXT },
|
StringAnsiView PlatformName = "Mac";
|
||||||
#else
|
#else
|
||||||
#error "Unknown platform"
|
#error "Unknown platform"
|
||||||
#endif
|
#endif
|
||||||
{ UA_ANONYMIZE_IP, 0, "0" },
|
|
||||||
{ UA_APP_ID, 0, "Flax Editor " FLAXENGINE_VERSION_TEXT },
|
|
||||||
{ UA_APP_INSTALLER_ID, 0, "Flax Editor" },
|
|
||||||
{ UA_APP_NAME, 0, "Flax Editor" },
|
|
||||||
{ UA_APP_VERSION, 0, FLAXENGINE_VERSION_TEXT },
|
|
||||||
{ UA_SCREEN_NAME, 0, "Flax Editor " FLAXENGINE_VERSION_TEXT },
|
|
||||||
{ UA_SCREEN_RESOLUTION, 0, ScreenResolution.Get() },
|
|
||||||
{ UA_USER_LANGUAGE, 0, UserLanguage.Get() },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
setParameters(Tracker, &GlobalSettings);
|
|
||||||
|
|
||||||
// Send the initial session event
|
// Initialize HTTP
|
||||||
UAOptions sessionViewOptions =
|
Url = StringAnsi::Format("{0}?measurement_id={1}&api_secret={2}", GA_URL, GA_MEASUREMENT_ID, GA_API_SECRET);
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
CurlHttpHeadersList = curl_slist_append(nullptr, "Content-Type: application/json");
|
||||||
|
::IsSessionActive = true;
|
||||||
|
|
||||||
|
// Start session
|
||||||
{
|
{
|
||||||
{
|
const Pair<const char*, const char*> params[1] = { { "Project", ProjectName.Get() }, };
|
||||||
{ UA_EVENT_CATEGORY, 0, "Session" },
|
SendEvent("Session", ToSpan(params, ARRAY_COUNT(params)));
|
||||||
{ UA_EVENT_ACTION, 0, "Start Editor" },
|
|
||||||
{ UA_EVENT_LABEL, 0, "Start Editor" },
|
|
||||||
{ UA_SESSION_CONTROL, 0, "start" },
|
|
||||||
{ UA_DOCUMENT_TITLE, 0, ProjectName.Get() },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
sendTracking(Tracker, UA_SCREENVIEW, &sessionViewOptions);
|
|
||||||
|
|
||||||
EditorAnalyticsImpl::IsSessionActive = true;
|
|
||||||
|
|
||||||
Controller.Init();
|
|
||||||
|
|
||||||
// Report GPU model
|
|
||||||
if (GPU.HasChars())
|
|
||||||
{
|
|
||||||
SendEvent("Telemetry", "GPU.Model", GPU.Get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Report telemetry stats
|
||||||
|
#define SEND_TELEMETRY(name, value) \
|
||||||
|
if (value.HasChars()) \
|
||||||
|
{ \
|
||||||
|
const Pair<const char*, const char*> params[1] = { { name, value.Get() } }; \
|
||||||
|
SendEvent("Telemetry", ToSpan(params, ARRAY_COUNT(params))); \
|
||||||
|
}
|
||||||
|
SEND_TELEMETRY("Platform", PlatformName);
|
||||||
|
SEND_TELEMETRY("GPU", GPU);
|
||||||
|
SEND_TELEMETRY("Memory", Memory);
|
||||||
|
SEND_TELEMETRY("Locale", UserLocale);
|
||||||
|
SEND_TELEMETRY("Screen", ScreenResolution);
|
||||||
|
SEND_TELEMETRY("Version", EngineVersion);
|
||||||
|
#undef SEND_TELEMETRY
|
||||||
|
|
||||||
|
// Bind events
|
||||||
|
GameCooker::OnEvent.Bind<RegisterGameCookingStart>();
|
||||||
|
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Bind<RegisterLightmapsBuildingStart>();
|
||||||
|
Log::Logger::OnError.Bind<RegisterError>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorAnalytics::EndSession()
|
void EditorAnalytics::EndSession()
|
||||||
{
|
{
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
|
if (!::IsSessionActive)
|
||||||
if (!EditorAnalyticsImpl::IsSessionActive)
|
|
||||||
return;
|
return;
|
||||||
|
PROFILE_CPU();
|
||||||
|
|
||||||
Controller.Cleanup();
|
// Unbind events
|
||||||
|
GameCooker::OnEvent.Unbind<RegisterGameCookingStart>();
|
||||||
|
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Unbind<RegisterLightmapsBuildingStart>();
|
||||||
|
Log::Logger::OnError.Unbind<RegisterError>();
|
||||||
|
|
||||||
StringAnsi sessionLength = StringAnsi::Format("{0}", (int32)(DateTime::Now() - SessionStartTime).GetTotalSeconds());
|
// End session
|
||||||
|
|
||||||
// Send the end session event
|
|
||||||
UAOptions sessionEventOptions =
|
|
||||||
{
|
{
|
||||||
|
StringAnsi sessionLength = StringAnsi::Format("{}", (int32)(DateTime::Now() - SessionStartTime).GetTotalSeconds());
|
||||||
|
const Pair<const char*, const char*> params[1] =
|
||||||
{
|
{
|
||||||
{ UA_EVENT_CATEGORY, 0, "Session" },
|
{ "Duration", sessionLength.Get() },
|
||||||
{ UA_EVENT_ACTION, 0, "Session Length" },
|
};
|
||||||
{ UA_EVENT_LABEL, 0, "Session Length" },
|
SendEvent("Session", ToSpan(params, ARRAY_COUNT(params)));
|
||||||
{ UA_EVENT_VALUE, 0, sessionLength.Get() },
|
}
|
||||||
{ UA_CUSTOM_DIMENSION, 1, "Session Length" },
|
|
||||||
{ UA_CUSTOM_METRIC, 1, sessionLength.Get() },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
sendTracking(Tracker, UA_EVENT, &sessionEventOptions);
|
|
||||||
|
|
||||||
// Send the end session event
|
|
||||||
UAOptions sessionViewOptions =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ UA_EVENT_CATEGORY, 0, "Session" },
|
|
||||||
{ UA_EVENT_ACTION, 0, "End Editor" },
|
|
||||||
{ UA_EVENT_LABEL, 0, "End Editor" },
|
|
||||||
{ UA_EVENT_VALUE, 0, sessionLength.Get() },
|
|
||||||
{ UA_SESSION_CONTROL, 0, "end" },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
sendTracking(Tracker, UA_SCREENVIEW, &sessionViewOptions);
|
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
removeTracker(Tracker);
|
curl_slist_free_all(CurlHttpHeadersList);
|
||||||
Tracker = nullptr;
|
CurlHttpHeadersList = nullptr;
|
||||||
|
curl_global_cleanup();
|
||||||
EditorAnalyticsImpl::IsSessionActive = false;
|
::IsSessionActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorAnalytics::SendEvent(const char* category, const char* name, const char* label)
|
void EditorAnalytics::SendEvent(const char* name, Span<Pair<const char*, const char*>> parameters)
|
||||||
{
|
{
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
|
if (!::IsSessionActive)
|
||||||
if (!EditorAnalyticsImpl::IsSessionActive)
|
|
||||||
return;
|
return;
|
||||||
|
PROFILE_CPU();
|
||||||
|
|
||||||
UAOptions opts =
|
// Create Json request contents
|
||||||
|
JsonBuffer.Clear();
|
||||||
|
JsonBuffer.Write("{ \"client_id\": \"");
|
||||||
|
JsonBuffer.Write(ClientId);
|
||||||
|
JsonBuffer.Write("\", \"events\": [ { \"name\": \"");
|
||||||
|
JsonBuffer.Write(name);
|
||||||
|
JsonBuffer.Write("\", \"params\": {");
|
||||||
|
for (int32 i = 0; i < parameters.Length(); i++)
|
||||||
{
|
{
|
||||||
{
|
if (i != 0)
|
||||||
{ UA_EVENT_CATEGORY, 0, (char*)category },
|
JsonBuffer.Write(",");
|
||||||
{ UA_EVENT_ACTION, 0, (char*)name },
|
const auto& e = parameters[i];
|
||||||
{ UA_EVENT_LABEL, 0, (char*)label },
|
JsonBuffer.Write("\"");
|
||||||
}
|
JsonBuffer.Write(e.First);
|
||||||
};
|
JsonBuffer.Write("\":\"");
|
||||||
|
JsonBuffer.Write(e.Second);
|
||||||
|
JsonBuffer.Write("\"");
|
||||||
|
}
|
||||||
|
JsonBuffer.Write("}}]}");
|
||||||
|
const StringAnsiView json((const char*)JsonBuffer.GetBuffer()->GetHandle(), (int32)JsonBuffer.GetBuffer()->GetPosition());
|
||||||
|
|
||||||
sendTracking(Tracker, UA_EVENT, &opts);
|
// Send HTTP request
|
||||||
}
|
CURL* curl = curl_easy_init();
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
void EditorAnalytics::SendEvent(const char* category, const char* name, const StringView& label)
|
curl_easy_setopt(curl, CURLOPT_URL, Url.Get());
|
||||||
{
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, CurlHttpHeadersList);
|
||||||
SendEvent(category, name, label.Get());
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.Get());
|
||||||
}
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, json.Length());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Flax Editor");
|
||||||
void EditorAnalytics::SendEvent(const char* category, const char* name, const Char* label)
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl);
|
||||||
{
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_null_data_handler);
|
||||||
ScopeLock lock(Locker);
|
CURLcode res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
if (!EditorAnalyticsImpl::IsSessionActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ASSERT(category && name && label);
|
|
||||||
|
|
||||||
const int32 labelLength = StringUtils::Length(label);
|
|
||||||
TmpBuffer.Clear();
|
|
||||||
TmpBuffer.Resize(labelLength + 1);
|
|
||||||
StringUtils::ConvertUTF162ANSI(label, TmpBuffer.Get(), labelLength);
|
|
||||||
TmpBuffer[labelLength] = 0;
|
|
||||||
|
|
||||||
UAOptions opts =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ UA_EVENT_CATEGORY, 0, (char*)category },
|
|
||||||
{ UA_EVENT_ACTION, 0, (char*)name },
|
|
||||||
{ UA_EVENT_LABEL, 0, (char*)TmpBuffer.Get() },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sendTracking(Tracker, UA_EVENT, &opts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorAnalyticsService::Init()
|
bool EditorAnalyticsService::Init()
|
||||||
@@ -265,8 +268,7 @@ bool EditorAnalyticsService::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG(Info, "Editor analytics service is enabled. Curl version: {0}", TEXT(LIBCURL_VERSION));
|
LOG(Info, "Editor analytics service is enabled. Curl version: {0}", TEXT(LIBCURL_VERSION));
|
||||||
|
Task::StartNew(EditorAnalytics::StartSession);
|
||||||
EditorAnalytics::StartSession();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,9 @@
|
|||||||
class EditorAnalytics
|
class EditorAnalytics
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether analytics session is active.
|
/// Determines whether analytics session is active.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns><c>true</c> if there is active analytics session running; otherwise, <c>false</c>.</returns>
|
|
||||||
static bool IsSessionActive();
|
static bool IsSessionActive();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -30,24 +28,7 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends the custom event.
|
/// Sends the custom event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="category">The event category name.</param>
|
|
||||||
/// <param name="name">The event name.</param>
|
/// <param name="name">The event name.</param>
|
||||||
/// <param name="label">The event label.</param>
|
/// <param name="parameters">The event parameters (key and value pairs).</param>
|
||||||
static void SendEvent(const char* category, const char* name, const char* label = nullptr);
|
static void SendEvent(const char* name, Span<Pair<const char*, const char*>> parameters);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends the custom event.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="category">The event category name.</param>
|
|
||||||
/// <param name="name">The event name.</param>
|
|
||||||
/// <param name="label">The event label.</param>
|
|
||||||
static void SendEvent(const char* category, const char* name, const StringView& label);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends the custom event.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="category">The event category name.</param>
|
|
||||||
/// <param name="name">The event name.</param>
|
|
||||||
/// <param name="label">The event label.</param>
|
|
||||||
static void SendEvent(const char* category, const char* name, const Char* label);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#include "EditorAnalyticsController.h"
|
|
||||||
#include "Editor/Cooker/GameCooker.h"
|
|
||||||
#include "EditorAnalytics.h"
|
|
||||||
#include "Engine/ShadowsOfMordor/Builder.h"
|
|
||||||
|
|
||||||
void RegisterGameCookingStart(GameCooker::EventType type)
|
|
||||||
{
|
|
||||||
auto& data = *GameCooker::GetCurrentData();
|
|
||||||
auto platform = ToString(data.Platform);
|
|
||||||
if (type == GameCooker::EventType::BuildStarted)
|
|
||||||
{
|
|
||||||
EditorAnalytics::SendEvent("Actions", "GameCooker.Start", platform);
|
|
||||||
}
|
|
||||||
else if (type == GameCooker::EventType::BuildFailed)
|
|
||||||
{
|
|
||||||
EditorAnalytics::SendEvent("Actions", "GameCooker.Failed", platform);
|
|
||||||
}
|
|
||||||
else if (type == GameCooker::EventType::BuildDone)
|
|
||||||
{
|
|
||||||
EditorAnalytics::SendEvent("Actions", "GameCooker.End", platform);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterLightmapsBuildingStart()
|
|
||||||
{
|
|
||||||
EditorAnalytics::SendEvent("Actions", "ShadowsOfMordor.Build", "ShadowsOfMordor.Build");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterError(LogType type, const StringView& msg)
|
|
||||||
{
|
|
||||||
if (type == LogType::Error && false)
|
|
||||||
{
|
|
||||||
String value = msg.ToString();
|
|
||||||
const int32 MaxLength = 300;
|
|
||||||
if (msg.Length() > MaxLength)
|
|
||||||
value = value.Substring(0, MaxLength);
|
|
||||||
value.Replace('\n', ' ');
|
|
||||||
value.Replace('\r', ' ');
|
|
||||||
|
|
||||||
EditorAnalytics::SendEvent("Errors", "Log.Error", value);
|
|
||||||
}
|
|
||||||
else if (type == LogType::Fatal)
|
|
||||||
{
|
|
||||||
String value = msg.ToString();
|
|
||||||
const int32 MaxLength = 300;
|
|
||||||
if (msg.Length() > MaxLength)
|
|
||||||
value = value.Substring(0, MaxLength);
|
|
||||||
value.Replace('\n', ' ');
|
|
||||||
value.Replace('\r', ' ');
|
|
||||||
|
|
||||||
EditorAnalytics::SendEvent("Errors", "Log.Fatal", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorAnalyticsController::Init()
|
|
||||||
{
|
|
||||||
GameCooker::OnEvent.Bind<RegisterGameCookingStart>();
|
|
||||||
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Bind<RegisterLightmapsBuildingStart>();
|
|
||||||
Log::Logger::OnError.Bind<RegisterError>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorAnalyticsController::Cleanup()
|
|
||||||
{
|
|
||||||
GameCooker::OnEvent.Unbind<RegisterGameCookingStart>();
|
|
||||||
ShadowsOfMordor::Builder::Instance()->OnBuildStarted.Unbind<RegisterLightmapsBuildingStart>();
|
|
||||||
Log::Logger::OnError.Unbind<RegisterError>();
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The controller object for the tracking events for the editor analytics.
|
|
||||||
/// </summary>
|
|
||||||
class EditorAnalyticsController
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Starts the service (registers to event handlers).
|
|
||||||
/// </summary>
|
|
||||||
void Init();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ends the service (unregisters to event handlers).
|
|
||||||
/// </summary>
|
|
||||||
void Cleanup();
|
|
||||||
};
|
|
||||||
@@ -692,10 +692,13 @@ namespace FlaxEditor.Content.GUI
|
|||||||
c = char.ToLowerInvariant(c);
|
c = char.ToLowerInvariant(c);
|
||||||
for (int i = 0; i < _items.Count; i++)
|
for (int i = 0; i < _items.Count; i++)
|
||||||
{
|
{
|
||||||
var name = _items[i].ShortName;
|
var item = _items[i];
|
||||||
|
var name = item.ShortName;
|
||||||
if (!string.IsNullOrEmpty(name) && char.ToLowerInvariant(name[0]) == c)
|
if (!string.IsNullOrEmpty(name) && char.ToLowerInvariant(name[0]) == c)
|
||||||
{
|
{
|
||||||
Select(_items[i]);
|
Select(item);
|
||||||
|
if (Parent is Panel panel)
|
||||||
|
panel.ScrollViewTo(item, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Interop;
|
||||||
|
|
||||||
namespace FlaxEditor.Content.Import
|
namespace FlaxEditor.Content.Import
|
||||||
{
|
{
|
||||||
@@ -93,6 +93,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
internal struct InternalOptions
|
internal struct InternalOptions
|
||||||
{
|
{
|
||||||
|
[MarshalAs(UnmanagedType.I1)]
|
||||||
public AudioFormat Format;
|
public AudioFormat Format;
|
||||||
public byte DisableStreaming;
|
public byte DisableStreaming;
|
||||||
public byte Is3D;
|
public byte Is3D;
|
||||||
@@ -144,7 +145,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
/// Audio asset import entry.
|
/// Audio asset import entry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="AssetImportEntry" />
|
/// <seealso cref="AssetImportEntry" />
|
||||||
public class AudioImportEntry : AssetImportEntry
|
public partial class AudioImportEntry : AssetImportEntry
|
||||||
{
|
{
|
||||||
private AudioImportSettings _settings = new AudioImportSettings();
|
private AudioImportSettings _settings = new AudioImportSettings();
|
||||||
|
|
||||||
@@ -182,8 +183,9 @@ namespace FlaxEditor.Content.Import
|
|||||||
|
|
||||||
#region Internal Calls
|
#region Internal Calls
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[LibraryImport("FlaxEngine", EntryPoint = "AudioImportEntryInternal_GetAudioImportOptions", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
|
||||||
internal static extern bool Internal_GetAudioImportOptions(string path, out AudioImportSettings.InternalOptions result);
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
internal static partial bool Internal_GetAudioImportOptions(string path, out AudioImportSettings.InternalOptions result);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,88 +1,47 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.ComponentModel;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using FlaxEditor.CustomEditors.Editors;
|
||||||
using System.Runtime.InteropServices;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Tools;
|
||||||
|
|
||||||
|
namespace FlaxEngine.Tools
|
||||||
|
{
|
||||||
|
partial class ModelTool
|
||||||
|
{
|
||||||
|
partial struct Options
|
||||||
|
{
|
||||||
|
private bool ShowGeometry => Type == ModelTool.ModelType.Model || Type == ModelTool.ModelType.SkinnedModel;
|
||||||
|
private bool ShowModel => Type == ModelTool.ModelType.Model;
|
||||||
|
private bool ShowSkinnedModel => Type == ModelTool.ModelType.SkinnedModel;
|
||||||
|
private bool ShowAnimation => Type == ModelTool.ModelType.Animation;
|
||||||
|
private bool ShowSmoothingNormalsAngle => ShowGeometry && CalculateNormals;
|
||||||
|
private bool ShowSmoothingTangentsAngle => ShowGeometry && CalculateTangents;
|
||||||
|
private bool ShowFramesRange => ShowAnimation && Duration == ModelTool.AnimationDuration.Custom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for <see cref="FlaxEngine.Tools.ModelTool.Options"/>.
|
||||||
|
/// </summary>
|
||||||
|
[CustomEditor(typeof(FlaxEngine.Tools.ModelTool.Options)), DefaultEditor]
|
||||||
|
public class ModelToolOptionsEditor : GenericEditor
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override List<ItemInfo> GetItemsForType(ScriptType type)
|
||||||
|
{
|
||||||
|
// Show both fields and properties
|
||||||
|
return GetItemsForType(type, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace FlaxEditor.Content.Import
|
namespace FlaxEditor.Content.Import
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Importing model lightmap UVs source
|
|
||||||
/// </summary>
|
|
||||||
[HideInEditor]
|
|
||||||
public enum ModelLightmapUVsSource : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// No lightmap UVs.
|
|
||||||
/// </summary>
|
|
||||||
Disable = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generate lightmap UVs from model geometry.
|
|
||||||
/// </summary>
|
|
||||||
Generate = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The texcoords channel 0.
|
|
||||||
/// </summary>
|
|
||||||
Channel0 = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The texcoords channel 1.
|
|
||||||
/// </summary>
|
|
||||||
Channel1 = 3,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The texcoords channel 2.
|
|
||||||
/// </summary>
|
|
||||||
Channel2 = 4,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The texcoords channel 3.
|
|
||||||
/// </summary>
|
|
||||||
Channel3 = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Declares the imported data type.
|
|
||||||
/// </summary>
|
|
||||||
[HideInEditor]
|
|
||||||
public enum ModelType : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The model asset.
|
|
||||||
/// </summary>
|
|
||||||
Model = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The skinned model asset.
|
|
||||||
/// </summary>
|
|
||||||
SkinnedModel = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The animation asset.
|
|
||||||
/// </summary>
|
|
||||||
Animation = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Declares the imported animation clip duration.
|
|
||||||
/// </summary>
|
|
||||||
[HideInEditor]
|
|
||||||
public enum AnimationDuration : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The imported duration.
|
|
||||||
/// </summary>
|
|
||||||
Imported = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The custom duration specified via keyframes range.
|
|
||||||
/// </summary>
|
|
||||||
Custom = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Proxy object to present model import settings in <see cref="ImportFilesDialog"/>.
|
/// Proxy object to present model import settings in <see cref="ImportFilesDialog"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -90,431 +49,10 @@ namespace FlaxEditor.Content.Import
|
|||||||
public class ModelImportSettings
|
public class ModelImportSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of the imported asset.
|
/// The settings data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditorOrder(0)]
|
[EditorDisplay(null, EditorDisplayAttribute.InlineStyle)]
|
||||||
public ModelType Type { get; set; } = ModelType.Model;
|
public ModelTool.Options Settings = ModelTool.Options.Default;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enable model normal vectors recalculating.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(20), DefaultValue(false)]
|
|
||||||
public bool CalculateNormals { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies the maximum angle (in degrees) that may be between two face normals at the same vertex position that their are smoothed together. The default value is 175.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowSmoothingNormalsAngle))]
|
|
||||||
[EditorOrder(30), DefaultValue(175.0f), Limit(0, 175, 0.1f)]
|
|
||||||
public float SmoothingNormalsAngle { get; set; } = 175.0f;
|
|
||||||
|
|
||||||
private bool ShowSmoothingNormalsAngle => ShowGeometry && CalculateNormals;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the imported normal vectors of the mesh will be flipped (scaled by -1).
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(35), DefaultValue(false)]
|
|
||||||
public bool FlipNormals { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enable model tangent vectors recalculating.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(40), DefaultValue(false)]
|
|
||||||
public bool CalculateTangents { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies the maximum angle (in degrees) that may be between two vertex tangents that their tangents and bi-tangents are smoothed. The default value is 45.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowSmoothingTangentsAngle))]
|
|
||||||
[EditorOrder(45), DefaultValue(45.0f), Limit(0, 45, 0.1f)]
|
|
||||||
public float SmoothingTangentsAngle { get; set; } = 45.0f;
|
|
||||||
|
|
||||||
private bool ShowSmoothingTangentsAngle => ShowGeometry && CalculateTangents;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enable/disable meshes geometry optimization.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(50), DefaultValue(true)]
|
|
||||||
public bool OptimizeMeshes { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enable/disable geometry merge for meshes with the same materials.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(60), DefaultValue(true)]
|
|
||||||
public bool MergeMeshes { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enable/disable importing meshes Level of Details.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry", "Import LODs"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(70), DefaultValue(true)]
|
|
||||||
public bool ImportLODs { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enable/disable importing vertex colors (channel 0 only).
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowModel))]
|
|
||||||
[EditorOrder(80), DefaultValue(true)]
|
|
||||||
public bool ImportVertexColors { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enable/disable importing blend shapes (morph targets).
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowSkinnedModel))]
|
|
||||||
[EditorOrder(85), DefaultValue(false)]
|
|
||||||
public bool ImportBlendShapes { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The lightmap UVs source.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry", "Lightmap UVs Source"), VisibleIf(nameof(ShowModel))]
|
|
||||||
[EditorOrder(90), DefaultValue(ModelLightmapUVsSource.Disable)]
|
|
||||||
public ModelLightmapUVsSource LightmapUVsSource { get; set; } = ModelLightmapUVsSource.Disable;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If specified, all meshes which name starts with this prefix will be imported as a separate collision data (excluded used for rendering).
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Geometry"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(100), DefaultValue("")]
|
|
||||||
public string CollisionMeshesPrefix { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Custom uniform import scale.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(500), DefaultValue(1.0f), EditorDisplay("Transform")]
|
|
||||||
public float Scale { get; set; } = 1.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Custom import geometry rotation.
|
|
||||||
/// </summary>
|
|
||||||
[DefaultValue(typeof(Quaternion), "0,0,0,1")]
|
|
||||||
[EditorOrder(510), EditorDisplay("Transform")]
|
|
||||||
public Quaternion Rotation { get; set; } = Quaternion.Identity;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Custom import geometry offset.
|
|
||||||
/// </summary>
|
|
||||||
[DefaultValue(typeof(Float3), "0,0,0")]
|
|
||||||
[EditorOrder(520), EditorDisplay("Transform")]
|
|
||||||
public Float3 Translation { get; set; } = Float3.Zero;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the imported geometry will be shifted to the center of mass.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(530), DefaultValue(false), EditorDisplay("Transform")]
|
|
||||||
public bool CenterGeometry { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Imported animation duration mode. Can use the original value or overriden by settings.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1000), DefaultValue(AnimationDuration.Imported)]
|
|
||||||
public AnimationDuration Duration { get; set; } = AnimationDuration.Imported;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Imported animation first frame index. Used only if Duration mode is set to Custom.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowFramesRange))]
|
|
||||||
[EditorOrder(1010), DefaultValue(0.0f), Limit(0)]
|
|
||||||
public float FramesRangeStart { get; set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Imported animation last frame index. Used only if Duration mode is set to Custom.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowFramesRange))]
|
|
||||||
[EditorOrder(1020), DefaultValue(0.0f), Limit(0)]
|
|
||||||
public float FramesRangeEnd { get; set; } = 0;
|
|
||||||
|
|
||||||
private bool ShowFramesRange => ShowAnimation && Duration == AnimationDuration.Custom;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The imported animation default frame rate. Can specify the default frames per second amount for imported animation. If value is 0 then the original animation frame rate will be used.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1025), DefaultValue(0.0f), Limit(0, 1000, 0.01f)]
|
|
||||||
public float DefaultFrameRate { get; set; } = 0.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The imported animation sampling rate. If value is 0 then the original animation speed will be used.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1030), DefaultValue(0.0f), Limit(0, 1000, 0.01f)]
|
|
||||||
public float SamplingRate { get; set; } = 0.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The imported animation will have removed tracks with no keyframes or unspecified data.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1040), DefaultValue(true)]
|
|
||||||
public bool SkipEmptyCurves { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The imported animation channels will be optimized to remove redundant keyframes.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1050), DefaultValue(true)]
|
|
||||||
public bool OptimizeKeyframes { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the importer will import scale animation tracks (otherwise scale animation will be ignored).
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1055), DefaultValue(false)]
|
|
||||||
public bool ImportScaleTracks { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables root motion extraction support from this animation.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1060), DefaultValue(false)]
|
|
||||||
public bool EnableRootMotion { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The custom node name to be used as a root motion source. If not specified the actual root node will be used.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Animation"), VisibleIf(nameof(ShowAnimation))]
|
|
||||||
[EditorOrder(1070), DefaultValue(typeof(string), "")]
|
|
||||||
public string RootNodeName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the importer will generate a sequence of LODs based on the base LOD index.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Level Of Detail", "Generate LODs"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(1100), DefaultValue(false)]
|
|
||||||
public bool GenerateLODs { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The index of the LOD from the source model data to use as a reference for following LODs generation.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Level Of Detail", "Base LOD"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(1110), DefaultValue(0), Limit(0, Model.MaxLODs - 1)]
|
|
||||||
public int BaseLOD { get; set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The amount of LODs to include in the model (all remaining ones starting from Base LOD will be generated).
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Level Of Detail", "LOD Count"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(1120), DefaultValue(4), Limit(1, Model.MaxLODs)]
|
|
||||||
public int LODCount { get; set; } = 4;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The target amount of triangles for the generated LOD (based on the higher LOD). Normalized to range 0-1. For instance 0.4 cuts the triangle count to 40%.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Level Of Detail"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(1130), DefaultValue(0.5f), Limit(0, 1, 0.001f)]
|
|
||||||
public float TriangleReduction { get; set; } = 0.5f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the importer will create materials for model meshes as specified in the file.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Materials"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(400), DefaultValue(true)]
|
|
||||||
public bool ImportMaterials { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the importer will import texture files used by the model and any embedded texture resources.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Materials"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(410), DefaultValue(true)]
|
|
||||||
public bool ImportTextures { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the importer will try to restore the model material slots.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("Materials", "Restore Materials On Reimport"), VisibleIf(nameof(ShowGeometry))]
|
|
||||||
[EditorOrder(420), DefaultValue(true)]
|
|
||||||
public bool RestoreMaterialsOnReimport { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, enables generation of Signed Distance Field (SDF).
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("SDF"), VisibleIf(nameof(ShowModel))]
|
|
||||||
[EditorOrder(1500), DefaultValue(false)]
|
|
||||||
public bool GenerateSDF { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resolution scale for generated Signed Distance Field (SDF) texture. Higher values improve accuracy but increase memory usage and reduce performance.
|
|
||||||
/// </summary>
|
|
||||||
[EditorDisplay("SDF"), VisibleIf(nameof(ShowModel))]
|
|
||||||
[EditorOrder(1510), DefaultValue(1.0f), Limit(0.0001f, 100.0f)]
|
|
||||||
public float SDFResolution { get; set; } = 1.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If checked, the imported mesh/animations are splitted into separate assets. Used if ObjectIndex is set to -1.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(2000), DefaultValue(false), EditorDisplay("Splitting")]
|
|
||||||
public bool SplitObjects { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The zero-based index for the mesh/animation clip to import. If the source file has more than one mesh/animation it can be used to pick a desire object. Default -1 imports all objects.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(2010), DefaultValue(-1), EditorDisplay("Splitting")]
|
|
||||||
public int ObjectIndex { get; set; } = -1;
|
|
||||||
|
|
||||||
private bool ShowGeometry => Type == ModelType.Model || Type == ModelType.SkinnedModel;
|
|
||||||
private bool ShowModel => Type == ModelType.Model;
|
|
||||||
private bool ShowSkinnedModel => Type == ModelType.SkinnedModel;
|
|
||||||
private bool ShowAnimation => Type == ModelType.Animation;
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct InternalOptions
|
|
||||||
{
|
|
||||||
public ModelType Type;
|
|
||||||
|
|
||||||
// Geometry
|
|
||||||
public byte CalculateNormals;
|
|
||||||
public float SmoothingNormalsAngle;
|
|
||||||
public byte FlipNormals;
|
|
||||||
public float SmoothingTangentsAngle;
|
|
||||||
public byte CalculateTangents;
|
|
||||||
public byte OptimizeMeshes;
|
|
||||||
public byte MergeMeshes;
|
|
||||||
public byte ImportLODs;
|
|
||||||
public byte ImportVertexColors;
|
|
||||||
public byte ImportBlendShapes;
|
|
||||||
public ModelLightmapUVsSource LightmapUVsSource;
|
|
||||||
public string CollisionMeshesPrefix;
|
|
||||||
|
|
||||||
// Transform
|
|
||||||
public float Scale;
|
|
||||||
public Quaternion Rotation;
|
|
||||||
public Float3 Translation;
|
|
||||||
public byte CenterGeometry;
|
|
||||||
|
|
||||||
// Animation
|
|
||||||
public AnimationDuration Duration;
|
|
||||||
public float FramesRangeStart;
|
|
||||||
public float FramesRangeEnd;
|
|
||||||
public float DefaultFrameRate;
|
|
||||||
public float SamplingRate;
|
|
||||||
public byte SkipEmptyCurves;
|
|
||||||
public byte OptimizeKeyframes;
|
|
||||||
public byte ImportScaleTracks;
|
|
||||||
public byte EnableRootMotion;
|
|
||||||
public string RootNodeName;
|
|
||||||
|
|
||||||
// Level Of Detail
|
|
||||||
public byte GenerateLODs;
|
|
||||||
public int BaseLOD;
|
|
||||||
public int LODCount;
|
|
||||||
public float TriangleReduction;
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
public byte ImportMaterials;
|
|
||||||
public byte ImportTextures;
|
|
||||||
public byte RestoreMaterialsOnReimport;
|
|
||||||
|
|
||||||
// SDF
|
|
||||||
public byte GenerateSDF;
|
|
||||||
public float SDFResolution;
|
|
||||||
|
|
||||||
// Splitting
|
|
||||||
public byte SplitObjects;
|
|
||||||
public int ObjectIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ToInternal(out InternalOptions options)
|
|
||||||
{
|
|
||||||
options = new InternalOptions
|
|
||||||
{
|
|
||||||
Type = Type,
|
|
||||||
CalculateNormals = (byte)(CalculateNormals ? 1 : 0),
|
|
||||||
SmoothingNormalsAngle = SmoothingNormalsAngle,
|
|
||||||
FlipNormals = (byte)(FlipNormals ? 1 : 0),
|
|
||||||
SmoothingTangentsAngle = SmoothingTangentsAngle,
|
|
||||||
CalculateTangents = (byte)(CalculateTangents ? 1 : 0),
|
|
||||||
OptimizeMeshes = (byte)(OptimizeMeshes ? 1 : 0),
|
|
||||||
MergeMeshes = (byte)(MergeMeshes ? 1 : 0),
|
|
||||||
ImportLODs = (byte)(ImportLODs ? 1 : 0),
|
|
||||||
ImportVertexColors = (byte)(ImportVertexColors ? 1 : 0),
|
|
||||||
ImportBlendShapes = (byte)(ImportBlendShapes ? 1 : 0),
|
|
||||||
LightmapUVsSource = LightmapUVsSource,
|
|
||||||
CollisionMeshesPrefix = CollisionMeshesPrefix,
|
|
||||||
Scale = Scale,
|
|
||||||
Rotation = Rotation,
|
|
||||||
Translation = Translation,
|
|
||||||
CenterGeometry = (byte)(CenterGeometry ? 1 : 0),
|
|
||||||
Duration = Duration,
|
|
||||||
FramesRangeStart = FramesRangeStart,
|
|
||||||
FramesRangeEnd = FramesRangeEnd,
|
|
||||||
DefaultFrameRate = DefaultFrameRate,
|
|
||||||
SamplingRate = SamplingRate,
|
|
||||||
SkipEmptyCurves = (byte)(SkipEmptyCurves ? 1 : 0),
|
|
||||||
OptimizeKeyframes = (byte)(OptimizeKeyframes ? 1 : 0),
|
|
||||||
ImportScaleTracks = (byte)(ImportScaleTracks ? 1 : 0),
|
|
||||||
EnableRootMotion = (byte)(EnableRootMotion ? 1 : 0),
|
|
||||||
RootNodeName = RootNodeName,
|
|
||||||
GenerateLODs = (byte)(GenerateLODs ? 1 : 0),
|
|
||||||
BaseLOD = BaseLOD,
|
|
||||||
LODCount = LODCount,
|
|
||||||
TriangleReduction = TriangleReduction,
|
|
||||||
ImportMaterials = (byte)(ImportMaterials ? 1 : 0),
|
|
||||||
ImportTextures = (byte)(ImportTextures ? 1 : 0),
|
|
||||||
RestoreMaterialsOnReimport = (byte)(RestoreMaterialsOnReimport ? 1 : 0),
|
|
||||||
GenerateSDF = (byte)(GenerateSDF ? 1 : 0),
|
|
||||||
SDFResolution = SDFResolution,
|
|
||||||
SplitObjects = (byte)(SplitObjects ? 1 : 0),
|
|
||||||
ObjectIndex = ObjectIndex,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void FromInternal(ref InternalOptions options)
|
|
||||||
{
|
|
||||||
Type = options.Type;
|
|
||||||
CalculateNormals = options.CalculateNormals != 0;
|
|
||||||
SmoothingNormalsAngle = options.SmoothingNormalsAngle;
|
|
||||||
FlipNormals = options.FlipNormals != 0;
|
|
||||||
SmoothingTangentsAngle = options.SmoothingTangentsAngle;
|
|
||||||
CalculateTangents = options.CalculateTangents != 0;
|
|
||||||
OptimizeMeshes = options.OptimizeMeshes != 0;
|
|
||||||
MergeMeshes = options.MergeMeshes != 0;
|
|
||||||
ImportLODs = options.ImportLODs != 0;
|
|
||||||
ImportVertexColors = options.ImportVertexColors != 0;
|
|
||||||
ImportBlendShapes = options.ImportBlendShapes != 0;
|
|
||||||
LightmapUVsSource = options.LightmapUVsSource;
|
|
||||||
CollisionMeshesPrefix = options.CollisionMeshesPrefix;
|
|
||||||
Scale = options.Scale;
|
|
||||||
Rotation = options.Rotation;
|
|
||||||
Translation = options.Translation;
|
|
||||||
CenterGeometry = options.CenterGeometry != 0;
|
|
||||||
FramesRangeStart = options.FramesRangeStart;
|
|
||||||
FramesRangeEnd = options.FramesRangeEnd;
|
|
||||||
DefaultFrameRate = options.DefaultFrameRate;
|
|
||||||
SamplingRate = options.SamplingRate;
|
|
||||||
SkipEmptyCurves = options.SkipEmptyCurves != 0;
|
|
||||||
OptimizeKeyframes = options.OptimizeKeyframes != 0;
|
|
||||||
ImportScaleTracks = options.ImportScaleTracks != 0;
|
|
||||||
EnableRootMotion = options.EnableRootMotion != 0;
|
|
||||||
RootNodeName = options.RootNodeName;
|
|
||||||
GenerateLODs = options.GenerateLODs != 0;
|
|
||||||
BaseLOD = options.BaseLOD;
|
|
||||||
LODCount = options.LODCount;
|
|
||||||
TriangleReduction = options.TriangleReduction;
|
|
||||||
ImportMaterials = options.ImportMaterials != 0;
|
|
||||||
ImportTextures = options.ImportTextures != 0;
|
|
||||||
RestoreMaterialsOnReimport = options.RestoreMaterialsOnReimport != 0;
|
|
||||||
GenerateSDF = options.GenerateSDF != 0;
|
|
||||||
SDFResolution = options.SDFResolution;
|
|
||||||
SplitObjects = options.SplitObjects != 0;
|
|
||||||
ObjectIndex = options.ObjectIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries the restore the asset import options from the target resource file. Applies the project default options too.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <param name="assetPath">The asset path.</param>
|
|
||||||
/// <returns>True settings has been restored, otherwise false.</returns>
|
|
||||||
public static void TryRestore(ref ModelImportSettings options, string assetPath)
|
|
||||||
{
|
|
||||||
ModelImportEntry.Internal_GetModelImportOptions(assetPath, out var internalOptions);
|
|
||||||
options.FromInternal(ref internalOptions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -523,7 +61,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
/// <seealso cref="AssetImportEntry" />
|
/// <seealso cref="AssetImportEntry" />
|
||||||
public class ModelImportEntry : AssetImportEntry
|
public class ModelImportEntry : AssetImportEntry
|
||||||
{
|
{
|
||||||
private ModelImportSettings _settings = new ModelImportSettings();
|
private ModelImportSettings _settings = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ModelImportEntry"/> class.
|
/// Initializes a new instance of the <see cref="ModelImportEntry"/> class.
|
||||||
@@ -533,7 +71,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
: base(ref request)
|
: base(ref request)
|
||||||
{
|
{
|
||||||
// Try to restore target asset model import options (useful for fast reimport)
|
// Try to restore target asset model import options (useful for fast reimport)
|
||||||
ModelImportSettings.TryRestore(ref _settings, ResultUrl);
|
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -542,9 +80,14 @@ namespace FlaxEditor.Content.Import
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool TryOverrideSettings(object settings)
|
public override bool TryOverrideSettings(object settings)
|
||||||
{
|
{
|
||||||
if (settings is ModelImportSettings o)
|
if (settings is ModelImportSettings s)
|
||||||
{
|
{
|
||||||
_settings = o;
|
_settings.Settings = s.Settings;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (settings is ModelTool.Options o)
|
||||||
|
{
|
||||||
|
_settings.Settings = o;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -553,14 +96,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Import()
|
public override bool Import()
|
||||||
{
|
{
|
||||||
return Editor.Import(SourceUrl, ResultUrl, _settings);
|
return Editor.Import(SourceUrl, ResultUrl, _settings.Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Internal Calls
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal static extern void Internal_GetModelImportOptions(string path, out ModelImportSettings.InternalOptions result);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,56 +3,94 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using FlaxEditor.CustomEditors.Editors;
|
||||||
using System.Runtime.InteropServices;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Tools;
|
||||||
|
|
||||||
// ReSharper disable InconsistentNaming
|
namespace FlaxEngine.Tools
|
||||||
|
{
|
||||||
|
partial class TextureTool
|
||||||
|
{
|
||||||
|
partial struct Options
|
||||||
|
{
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
public enum CustomMaxSizes
|
||||||
|
{
|
||||||
|
_32 = 32,
|
||||||
|
_64 = 64,
|
||||||
|
_128 = 128,
|
||||||
|
_256 = 256,
|
||||||
|
_512 = 512,
|
||||||
|
_1024 = 1024,
|
||||||
|
_2048 = 2048,
|
||||||
|
_4096 = 4096,
|
||||||
|
_8192 = 8192,
|
||||||
|
_16384 = 16384,
|
||||||
|
}
|
||||||
|
#pragma warning restore CS1591
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.
|
||||||
|
/// </summary>
|
||||||
|
[EditorOrder(110), VisibleIf(nameof(Resize)), DefaultValue(typeof(Int2), "1024,1024")]
|
||||||
|
public Int2 Size
|
||||||
|
{
|
||||||
|
get => new Int2(SizeX, SizeY);
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SizeX = value.X;
|
||||||
|
SizeY = value.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum size of the texture (for both width and height). Higher resolution textures will be resized during importing process.
|
||||||
|
/// </summary>
|
||||||
|
[EditorOrder(90), DefaultValue(CustomMaxSizes._8192), EditorDisplay(null, "Max Size")]
|
||||||
|
public CustomMaxSizes CustomMaxSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var value = MaxSize;
|
||||||
|
if (!Mathf.IsPowerOfTwo(value))
|
||||||
|
value = Mathf.NextPowerOfTwo(value);
|
||||||
|
FieldInfo[] fields = typeof(CustomMaxSizes).GetFields();
|
||||||
|
for (int i = 0; i < fields.Length; i++)
|
||||||
|
{
|
||||||
|
var field = fields[i];
|
||||||
|
if (field.Name.Equals("value__"))
|
||||||
|
continue;
|
||||||
|
if (value == (int)field.GetRawConstantValue())
|
||||||
|
return (CustomMaxSizes)value;
|
||||||
|
}
|
||||||
|
return CustomMaxSizes._8192;
|
||||||
|
}
|
||||||
|
set => MaxSize = (int)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for <see cref="FlaxEngine.Tools.TextureTool.Options"/>.
|
||||||
|
/// </summary>
|
||||||
|
[CustomEditor(typeof(FlaxEngine.Tools.TextureTool.Options)), DefaultEditor]
|
||||||
|
public class TextureToolOptionsEditor : GenericEditor
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override List<ItemInfo> GetItemsForType(ScriptType type)
|
||||||
|
{
|
||||||
|
// Show both fields and properties
|
||||||
|
return GetItemsForType(type, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace FlaxEditor.Content.Import
|
namespace FlaxEditor.Content.Import
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Texture format types.
|
|
||||||
/// </summary>
|
|
||||||
[HideInEditor]
|
|
||||||
public enum TextureFormatType : byte
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The unknown.
|
|
||||||
/// </summary>
|
|
||||||
Unknown = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color with RGB channels.
|
|
||||||
/// </summary>
|
|
||||||
ColorRGB = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color with RGBA channels.
|
|
||||||
/// </summary>
|
|
||||||
ColorRGBA = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The normal map (packed and compressed).
|
|
||||||
/// </summary>
|
|
||||||
NormalMap = 3,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The gray scale (R channel).
|
|
||||||
/// </summary>
|
|
||||||
GrayScale = 4,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The HDR color (RGBA channels).
|
|
||||||
/// </summary>
|
|
||||||
HdrRGBA = 5,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The HDR color (RGB channels).
|
|
||||||
/// </summary>
|
|
||||||
HdrRGB = 6
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Proxy object to present texture import settings in <see cref="ImportFilesDialog"/>.
|
/// Proxy object to present texture import settings in <see cref="ImportFilesDialog"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -60,346 +98,10 @@ namespace FlaxEditor.Content.Import
|
|||||||
public class TextureImportSettings
|
public class TextureImportSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A custom version of <see cref="TextureFormatType"/> for GUI.
|
/// The settings data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum CustomTextureFormatType
|
[EditorDisplay(null, EditorDisplayAttribute.InlineStyle)]
|
||||||
{
|
public TextureTool.Options Settings = TextureTool.Options.Default;
|
||||||
/// <summary>
|
|
||||||
/// The color with RGB channels.
|
|
||||||
/// </summary>
|
|
||||||
ColorRGB = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The color with RGBA channels.
|
|
||||||
/// </summary>
|
|
||||||
ColorRGBA = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The normal map (packed and compressed).
|
|
||||||
/// </summary>
|
|
||||||
NormalMap = 3,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The gray scale (R channel).
|
|
||||||
/// </summary>
|
|
||||||
GrayScale = 4,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The HDR color (RGBA channels).
|
|
||||||
/// </summary>
|
|
||||||
HdrRGBA = 5,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The HDR color (RGB channels).
|
|
||||||
/// </summary>
|
|
||||||
HdrRGB = 6
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A custom set of max texture import sizes.
|
|
||||||
/// </summary>
|
|
||||||
public enum CustomMaxSizeType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The 32.
|
|
||||||
/// </summary>
|
|
||||||
_32 = 32,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 64.
|
|
||||||
/// </summary>
|
|
||||||
_64 = 64,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 128.
|
|
||||||
/// </summary>
|
|
||||||
_128 = 128,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 256.
|
|
||||||
/// </summary>
|
|
||||||
_256 = 256,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 512.
|
|
||||||
/// </summary>
|
|
||||||
_512 = 512,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 1024.
|
|
||||||
/// </summary>
|
|
||||||
_1024 = 1024,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 2048.
|
|
||||||
/// </summary>
|
|
||||||
_2048 = 2048,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 4096.
|
|
||||||
/// </summary>
|
|
||||||
_4096 = 4096,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 8192.
|
|
||||||
/// </summary>
|
|
||||||
_8192 = 8192,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts the maximum size to enum.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="f">The max size.</param>
|
|
||||||
/// <returns>The converted enum.</returns>
|
|
||||||
public static CustomMaxSizeType ConvertMaxSize(int f)
|
|
||||||
{
|
|
||||||
if (!Mathf.IsPowerOfTwo(f))
|
|
||||||
f = Mathf.NextPowerOfTwo(f);
|
|
||||||
|
|
||||||
FieldInfo[] fields = typeof(CustomMaxSizeType).GetFields();
|
|
||||||
for (int i = 0; i < fields.Length; i++)
|
|
||||||
{
|
|
||||||
var field = fields[i];
|
|
||||||
if (field.Name.Equals("value__"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (f == (int)field.GetRawConstantValue())
|
|
||||||
return (CustomMaxSizeType)f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CustomMaxSizeType._8192;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The sprite info.
|
|
||||||
/// </summary>
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct SpriteInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The sprite area.
|
|
||||||
/// </summary>
|
|
||||||
public Rectangle Area;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The sprite name.
|
|
||||||
/// </summary>
|
|
||||||
public string Name;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SpriteInfo"/> struct.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="area">The area.</param>
|
|
||||||
/// <param name="name">The name.</param>
|
|
||||||
public SpriteInfo(Rectangle area, string name)
|
|
||||||
{
|
|
||||||
Area = area;
|
|
||||||
Name = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture format type
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(0), DefaultValue(CustomTextureFormatType.ColorRGB), Tooltip("Texture import format type")]
|
|
||||||
public CustomTextureFormatType Type { get; set; } = CustomTextureFormatType.ColorRGB;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if texture should be imported as a texture atlas resource
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(10), DefaultValue(false), Tooltip("True if texture should be imported as a texture atlas (with sprites)")]
|
|
||||||
public bool IsAtlas { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if disable dynamic texture streaming
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(20), DefaultValue(false), Tooltip("True if disable dynamic texture streaming")]
|
|
||||||
public bool NeverStream { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables/disables texture data compression.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(30), DefaultValue(true), Tooltip("True if compress texture data")]
|
|
||||||
public bool Compress { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if texture channels have independent data
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(40), DefaultValue(false), Tooltip("True if texture channels have independent data (for compression methods)")]
|
|
||||||
public bool IndependentChannels { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if use sRGB format for texture data. Recommended for color maps and diffuse color textures.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(50), DefaultValue(false), EditorDisplay(null, "sRGB"), Tooltip("True if use sRGB format for texture data. Recommended for color maps and diffuse color textures.")]
|
|
||||||
public bool sRGB { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if generate mip maps chain for the texture.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(60), DefaultValue(true), Tooltip("True if generate mip maps chain for the texture")]
|
|
||||||
public bool GenerateMipMaps { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if flip Y coordinate of the texture.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(65), DefaultValue(false), EditorDisplay(null, "Flip Y"), Tooltip("True if flip Y coordinate of the texture.")]
|
|
||||||
public bool FlipY { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The import texture scale.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(70), DefaultValue(1.0f), Tooltip("Texture scale. Default is 1.")]
|
|
||||||
public float Scale { get; set; } = 1.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum size of the texture (for both width and height).
|
|
||||||
/// Higher resolution textures will be resized during importing process.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(80), DefaultValue(CustomMaxSizeType._8192), Tooltip("Maximum texture size (will be resized if need to)")]
|
|
||||||
public CustomMaxSizeType MaxSize { get; set; } = CustomMaxSizeType._8192;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if resize texture on import. Use Size property to define texture width and height. Texture scale property will be ignored.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(90), DefaultValue(false), Tooltip("True if resize texture on import. Use Size property to define texture width and height. Texture scale property will be ignored.")]
|
|
||||||
public bool Resize { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the size of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(100), VisibleIf("Resize"), DefaultValue(typeof(Int2), "1024,1024"), Tooltip("The size of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored.")]
|
|
||||||
public Int2 Size { get; set; } = new Int2(1024, 1024);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(240), DefaultValue(false), Tooltip("Check to preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value.")]
|
|
||||||
public bool PreserveAlphaCoverage { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The reference value for the alpha coverage preserving.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(250), VisibleIf("PreserveAlphaCoverage"), DefaultValue(0.5f), Tooltip("The reference value for the alpha coverage preserving.")]
|
|
||||||
public float PreserveAlphaCoverageReference { get; set; } = 0.5f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture group for streaming (negative if unused). See Streaming Settings.
|
|
||||||
/// </summary>
|
|
||||||
[CustomEditor(typeof(CustomEditors.Dedicated.TextureGroupEditor))]
|
|
||||||
[EditorOrder(300), Tooltip("Texture group for streaming (negative if unused). See Streaming Settings.")]
|
|
||||||
public int TextureGroup = -1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The sprites. Used to keep created sprites on sprite atlas reimport.
|
|
||||||
/// </summary>
|
|
||||||
[HideInEditor]
|
|
||||||
public List<SpriteInfo> Sprites = new List<SpriteInfo>();
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct InternalOptions
|
|
||||||
{
|
|
||||||
public TextureFormatType Type;
|
|
||||||
public byte IsAtlas;
|
|
||||||
public byte NeverStream;
|
|
||||||
public byte Compress;
|
|
||||||
public byte IndependentChannels;
|
|
||||||
public byte sRGB;
|
|
||||||
public byte GenerateMipMaps;
|
|
||||||
public byte FlipY;
|
|
||||||
public byte Resize;
|
|
||||||
public byte PreserveAlphaCoverage;
|
|
||||||
public float PreserveAlphaCoverageReference;
|
|
||||||
public float Scale;
|
|
||||||
public int MaxSize;
|
|
||||||
public int TextureGroup;
|
|
||||||
public Int2 Size;
|
|
||||||
public Rectangle[] SpriteAreas;
|
|
||||||
public string[] SpriteNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void ToInternal(out InternalOptions options)
|
|
||||||
{
|
|
||||||
options = new InternalOptions
|
|
||||||
{
|
|
||||||
Type = (TextureFormatType)(int)Type,
|
|
||||||
IsAtlas = (byte)(IsAtlas ? 1 : 0),
|
|
||||||
NeverStream = (byte)(NeverStream ? 1 : 0),
|
|
||||||
Compress = (byte)(Compress ? 1 : 0),
|
|
||||||
IndependentChannels = (byte)(IndependentChannels ? 1 : 0),
|
|
||||||
sRGB = (byte)(sRGB ? 1 : 0),
|
|
||||||
GenerateMipMaps = (byte)(GenerateMipMaps ? 1 : 0),
|
|
||||||
FlipY = (byte)(FlipY ? 1 : 0),
|
|
||||||
Resize = (byte)(Resize ? 1 : 0),
|
|
||||||
PreserveAlphaCoverage = (byte)(PreserveAlphaCoverage ? 1 : 0),
|
|
||||||
PreserveAlphaCoverageReference = PreserveAlphaCoverageReference,
|
|
||||||
Scale = Scale,
|
|
||||||
Size = Size,
|
|
||||||
MaxSize = (int)MaxSize,
|
|
||||||
TextureGroup = TextureGroup,
|
|
||||||
};
|
|
||||||
if (Sprites != null && Sprites.Count > 0)
|
|
||||||
{
|
|
||||||
int count = Sprites.Count;
|
|
||||||
options.SpriteAreas = new Rectangle[count];
|
|
||||||
options.SpriteNames = new string[count];
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
options.SpriteAreas[i] = Sprites[i].Area;
|
|
||||||
options.SpriteNames[i] = Sprites[i].Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
options.SpriteAreas = null;
|
|
||||||
options.SpriteNames = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void FromInternal(ref InternalOptions options)
|
|
||||||
{
|
|
||||||
Type = (CustomTextureFormatType)(int)options.Type;
|
|
||||||
IsAtlas = options.IsAtlas != 0;
|
|
||||||
NeverStream = options.NeverStream != 0;
|
|
||||||
Compress = options.Compress != 0;
|
|
||||||
IndependentChannels = options.IndependentChannels != 0;
|
|
||||||
sRGB = options.sRGB != 0;
|
|
||||||
GenerateMipMaps = options.GenerateMipMaps != 0;
|
|
||||||
FlipY = options.FlipY != 0;
|
|
||||||
Resize = options.Resize != 0;
|
|
||||||
PreserveAlphaCoverage = options.PreserveAlphaCoverage != 0;
|
|
||||||
PreserveAlphaCoverageReference = options.PreserveAlphaCoverageReference;
|
|
||||||
Scale = options.Scale;
|
|
||||||
MaxSize = ConvertMaxSize(options.MaxSize);
|
|
||||||
TextureGroup = options.TextureGroup;
|
|
||||||
Size = options.Size;
|
|
||||||
if (options.SpriteAreas != null)
|
|
||||||
{
|
|
||||||
int spritesCount = options.SpriteAreas.Length;
|
|
||||||
Sprites.Capacity = spritesCount;
|
|
||||||
for (int i = 0; i < spritesCount; i++)
|
|
||||||
{
|
|
||||||
Sprites.Add(new SpriteInfo(options.SpriteAreas[i], options.SpriteNames[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries the restore the asset import options from the target resource file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options">The options.</param>
|
|
||||||
/// <param name="assetPath">The asset path.</param>
|
|
||||||
/// <returns>True settings has been restored, otherwise false.</returns>
|
|
||||||
public static bool TryRestore(ref TextureImportSettings options, string assetPath)
|
|
||||||
{
|
|
||||||
if (TextureImportEntry.Internal_GetTextureImportOptions(assetPath, out var internalOptions))
|
|
||||||
{
|
|
||||||
// Restore settings
|
|
||||||
options.FromInternal(ref internalOptions);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -408,7 +110,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
/// <seealso cref="AssetImportEntry" />
|
/// <seealso cref="AssetImportEntry" />
|
||||||
public class TextureImportEntry : AssetImportEntry
|
public class TextureImportEntry : AssetImportEntry
|
||||||
{
|
{
|
||||||
private TextureImportSettings _settings = new TextureImportSettings();
|
private TextureImportSettings _settings = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="TextureImportEntry"/> class.
|
/// Initializes a new instance of the <see cref="TextureImportEntry"/> class.
|
||||||
@@ -423,15 +125,15 @@ namespace FlaxEditor.Content.Import
|
|||||||
if (extension == ".raw")
|
if (extension == ".raw")
|
||||||
{
|
{
|
||||||
// Raw image data in 16bit gray-scale, preserve the quality
|
// Raw image data in 16bit gray-scale, preserve the quality
|
||||||
_settings.Type = TextureImportSettings.CustomTextureFormatType.HdrRGBA;
|
_settings.Settings.Type = TextureFormatType.HdrRGBA;
|
||||||
_settings.Compress = false;
|
_settings.Settings.Compress = false;
|
||||||
}
|
}
|
||||||
else if (extension == ".hdr")
|
else if (extension == ".hdr")
|
||||||
{
|
{
|
||||||
// HDR sky texture
|
// HDR sky texture
|
||||||
_settings.Type = TextureImportSettings.CustomTextureFormatType.HdrRGB;
|
_settings.Settings.Type = TextureFormatType.HdrRGB;
|
||||||
}
|
}
|
||||||
else if (_settings.Type != TextureImportSettings.CustomTextureFormatType.ColorRGB)
|
else if (_settings.Settings.Type != TextureFormatType.ColorRGB)
|
||||||
{
|
{
|
||||||
// Skip checking
|
// Skip checking
|
||||||
}
|
}
|
||||||
@@ -443,7 +145,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
|| snl.EndsWith("normals"))
|
|| snl.EndsWith("normals"))
|
||||||
{
|
{
|
||||||
// Normal map
|
// Normal map
|
||||||
_settings.Type = TextureImportSettings.CustomTextureFormatType.NormalMap;
|
_settings.Settings.Type = TextureFormatType.NormalMap;
|
||||||
}
|
}
|
||||||
else if (snl.EndsWith("_d")
|
else if (snl.EndsWith("_d")
|
||||||
|| snl.Contains("diffuse")
|
|| snl.Contains("diffuse")
|
||||||
@@ -454,8 +156,8 @@ namespace FlaxEditor.Content.Import
|
|||||||
|| snl.Contains("albedo"))
|
|| snl.Contains("albedo"))
|
||||||
{
|
{
|
||||||
// Albedo or diffuse map
|
// Albedo or diffuse map
|
||||||
_settings.Type = TextureImportSettings.CustomTextureFormatType.ColorRGB;
|
_settings.Settings.Type = TextureFormatType.ColorRGB;
|
||||||
_settings.sRGB = true;
|
_settings.Settings.sRGB = true;
|
||||||
}
|
}
|
||||||
else if (snl.EndsWith("ao")
|
else if (snl.EndsWith("ao")
|
||||||
|| snl.EndsWith("ambientocclusion")
|
|| snl.EndsWith("ambientocclusion")
|
||||||
@@ -478,11 +180,11 @@ namespace FlaxEditor.Content.Import
|
|||||||
|| snl.EndsWith("metallic"))
|
|| snl.EndsWith("metallic"))
|
||||||
{
|
{
|
||||||
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
|
// Glossiness, metalness, ambient occlusion, displacement, height, cavity or specular
|
||||||
_settings.Type = TextureImportSettings.CustomTextureFormatType.GrayScale;
|
_settings.Settings.Type = TextureFormatType.GrayScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to restore target asset texture import options (useful for fast reimport)
|
// Try to restore target asset texture import options (useful for fast reimport)
|
||||||
TextureImportSettings.TryRestore(ref _settings, ResultUrl);
|
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -491,11 +193,18 @@ namespace FlaxEditor.Content.Import
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool TryOverrideSettings(object settings)
|
public override bool TryOverrideSettings(object settings)
|
||||||
{
|
{
|
||||||
if (settings is TextureImportSettings o)
|
if (settings is TextureImportSettings s)
|
||||||
{
|
{
|
||||||
var sprites = o.Sprites ?? _settings.Sprites; // Preserve sprites if not specified to override
|
var sprites = s.Settings.Sprites ?? _settings.Settings.Sprites; // Preserve sprites if not specified to override
|
||||||
_settings = o;
|
_settings.Settings = s.Settings;
|
||||||
_settings.Sprites = sprites;
|
_settings.Settings.Sprites = sprites;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (settings is TextureTool.Options o)
|
||||||
|
{
|
||||||
|
var sprites = o.Sprites ?? _settings.Settings.Sprites; // Preserve sprites if not specified to override
|
||||||
|
_settings.Settings = o;
|
||||||
|
_settings.Settings.Sprites = sprites;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -504,14 +213,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Import()
|
public override bool Import()
|
||||||
{
|
{
|
||||||
return Editor.Import(SourceUrl, ResultUrl, _settings);
|
return Editor.Import(SourceUrl, ResultUrl, _settings.Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Internal Calls
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
|
||||||
internal static extern bool Internal_GetTextureImportOptions(string path, out TextureImportSettings.InternalOptions result);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
@@ -25,6 +23,11 @@ namespace FlaxEditor.Content
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string TypeName { get; }
|
public string TypeName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if asset is now loaded.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLoaded => FlaxEngine.Content.GetAsset(ID)?.IsLoaded ?? false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="AssetItem"/> class.
|
/// Initializes a new instance of the <see cref="AssetItem"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -38,14 +41,6 @@ namespace FlaxEditor.Content
|
|||||||
ID = id;
|
ID = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override void UpdateTooltipText()
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
OnBuildTooltipText(sb);
|
|
||||||
TooltipText = sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class TooltipDoubleClickHook : Control
|
private sealed class TooltipDoubleClickHook : Control
|
||||||
{
|
{
|
||||||
public AssetItem Item;
|
public AssetItem Item;
|
||||||
@@ -74,20 +69,46 @@ namespace FlaxEditor.Content
|
|||||||
hook.Item = this;
|
hook.Item = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when building tooltip text.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sb">The String Builder.</param>
|
|
||||||
protected virtual void OnBuildTooltipText(StringBuilder sb)
|
|
||||||
{
|
|
||||||
sb.Append("Type: ").Append(TypeName).AppendLine();
|
|
||||||
sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((int)new FileInfo(Path).Length)).AppendLine();
|
|
||||||
sb.Append("Path: ").Append(Path).AppendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ContentItemType ItemType => ContentItemType.Asset;
|
public override ContentItemType ItemType => ContentItemType.Asset;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// Translate asset type name
|
||||||
|
var typeName = TypeName;
|
||||||
|
string[] typeNamespaces = typeName.Split('.');
|
||||||
|
if (typeNamespaces.Length != 0 && typeNamespaces.Length != 0)
|
||||||
|
{
|
||||||
|
typeName = Utilities.Utils.GetPropertyNameUI(typeNamespaces[typeNamespaces.Length - 1]);
|
||||||
|
}
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the asset.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The asset object.</returns>
|
||||||
|
public Asset LoadAsync()
|
||||||
|
{
|
||||||
|
return FlaxEngine.Content.LoadAsync<Asset>(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reloads the asset (if it's loaded).
|
||||||
|
/// </summary>
|
||||||
|
public void Reload()
|
||||||
|
{
|
||||||
|
var asset = FlaxEngine.Content.GetAsset(ID);
|
||||||
|
if (asset != null && asset.IsLoaded)
|
||||||
|
{
|
||||||
|
asset.Reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether asset is of the specified type (included inheritance checks).
|
/// Determines whether asset is of the specified type (included inheritance checks).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ namespace FlaxEditor.Content
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => "C# Source Code";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CSharpScript128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CSharpScript128;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using FlaxEditor.GUI.Drag;
|
using FlaxEditor.GUI.Drag;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
@@ -112,7 +113,15 @@ namespace FlaxEditor.Content
|
|||||||
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Other;
|
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Other;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanRename => ParentFolder != null; // Deny rename action for root folders
|
public override bool CanRename
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var hasParentFolder = ParentFolder != null;
|
||||||
|
var isContentFolder = Node is MainContentTreeNode;
|
||||||
|
return hasParentFolder && !isContentFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanDrag => ParentFolder != null; // Deny rename action for root folders
|
public override bool CanDrag => ParentFolder != null; // Deny rename action for root folders
|
||||||
@@ -120,6 +129,9 @@ namespace FlaxEditor.Content
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Exists => Directory.Exists(Path);
|
public override bool Exists => Directory.Exists(Path);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => "Folder";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Folder128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Folder128;
|
||||||
|
|
||||||
@@ -135,9 +147,10 @@ namespace FlaxEditor.Content
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void UpdateTooltipText()
|
protected override void OnBuildTooltipText(StringBuilder sb)
|
||||||
{
|
{
|
||||||
TooltipText = Path;
|
sb.Append("Type: ").Append(TypeDescription).AppendLine();
|
||||||
|
sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using FlaxEditor.Content.GUI;
|
using FlaxEditor.Content.GUI;
|
||||||
using FlaxEditor.GUI.Drag;
|
using FlaxEditor.GUI.Drag;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
@@ -222,7 +224,7 @@ namespace FlaxEditor.Content
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this item can be dragged and dropped.
|
/// Gets a value indicating whether this item can be dragged and dropped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool CanDrag => true;
|
public virtual bool CanDrag => Root != null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this <see cref="ContentItem"/> exists on drive.
|
/// Gets a value indicating whether this <see cref="ContentItem"/> exists on drive.
|
||||||
@@ -273,6 +275,11 @@ namespace FlaxEditor.Content
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string NamePath => FlaxEditor.Utilities.Utils.GetAssetNamePath(Path);
|
public string NamePath => FlaxEditor.Utilities.Utils.GetAssetNamePath(Path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the content item type description (for UI).
|
||||||
|
/// </summary>
|
||||||
|
public abstract string TypeDescription { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the default name of the content item thumbnail. Returns null if not used.
|
/// Gets the default name of the content item thumbnail. Returns null if not used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -357,7 +364,29 @@ namespace FlaxEditor.Content
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void UpdateTooltipText()
|
public virtual void UpdateTooltipText()
|
||||||
{
|
{
|
||||||
TooltipText = "Path: " + Path;
|
var sb = new StringBuilder();
|
||||||
|
OnBuildTooltipText(sb);
|
||||||
|
if (sb.Length != 0 && sb[sb.Length - 1] == '\n')
|
||||||
|
{
|
||||||
|
// Remove new-line from end
|
||||||
|
int sub = 1;
|
||||||
|
if (sb.Length != 1 && sb[sb.Length - 2] == '\r')
|
||||||
|
sub = 2;
|
||||||
|
sb.Length -= sub;
|
||||||
|
}
|
||||||
|
TooltipText = sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when building tooltip text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sb">The output string builder.</param>
|
||||||
|
protected virtual void OnBuildTooltipText(StringBuilder sb)
|
||||||
|
{
|
||||||
|
sb.Append("Type: ").Append(TypeDescription).AppendLine();
|
||||||
|
if (File.Exists(Path))
|
||||||
|
sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((int)new FileInfo(Path).Length)).AppendLine();
|
||||||
|
sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -690,7 +719,7 @@ namespace FlaxEditor.Content
|
|||||||
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
Focus();
|
Focus();
|
||||||
|
|
||||||
// Open
|
// Open
|
||||||
(Parent as ContentView).OnItemDoubleClick(this);
|
(Parent as ContentView).OnItemDoubleClick(this);
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ namespace FlaxEditor.Content
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => Path.EndsWith(".h") ? "C++ Header File" : "C++ Source Code";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ namespace FlaxEditor.Content
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Other;
|
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => "File";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
|
||||||
namespace FlaxEditor.Content
|
namespace FlaxEditor.Content
|
||||||
@@ -39,10 +40,19 @@ namespace FlaxEditor.Content
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Other;
|
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Other;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => "New";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override bool DrawShadow => true;
|
protected override bool DrawShadow => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void UpdateTooltipText()
|
||||||
|
{
|
||||||
|
TooltipText = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ namespace FlaxEditor.Content
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Scene;
|
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Scene;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => "Scene";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Scene128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Scene128;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace FlaxEditor.Content
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Shader;
|
public override ContentItemSearchFilter SearchFilter => ContentItemSearchFilter.Shader;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string TypeDescription => "Shader Source Code";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
|
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.Document128;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Reflection;
|
|||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.Json;
|
using FlaxEngine.Json;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
using Object = FlaxEngine.Object;
|
using Object = FlaxEngine.Object;
|
||||||
|
|
||||||
namespace FlaxEditor.Content
|
namespace FlaxEditor.Content
|
||||||
@@ -134,7 +135,7 @@ namespace FlaxEditor.Content
|
|||||||
_index = index;
|
_index = index;
|
||||||
type.Asset.GetMethodSignature(index, out _name, out _flags, out var returnTypeName, out var paramNames, out var paramTypeNames, out var paramOuts);
|
type.Asset.GetMethodSignature(index, out _name, out _flags, out var returnTypeName, out var paramNames, out var paramTypeNames, out var paramOuts);
|
||||||
_returnType = TypeUtils.GetType(returnTypeName);
|
_returnType = TypeUtils.GetType(returnTypeName);
|
||||||
if (paramNames.Length != 0)
|
if (paramNames != null && paramNames.Length != 0)
|
||||||
{
|
{
|
||||||
_parameters = new ScriptMemberInfo.Parameter[paramNames.Length];
|
_parameters = new ScriptMemberInfo.Parameter[paramNames.Length];
|
||||||
for (int i = 0; i < _parameters.Length; i++)
|
for (int i = 0; i < _parameters.Length; i++)
|
||||||
@@ -310,7 +311,10 @@ namespace FlaxEditor.Content
|
|||||||
|
|
||||||
internal void Dispose()
|
internal void Dispose()
|
||||||
{
|
{
|
||||||
OnAssetReloading(_asset);
|
if (_parameters != null)
|
||||||
|
{
|
||||||
|
OnAssetReloading(_asset);
|
||||||
|
}
|
||||||
_asset = null;
|
_asset = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
|
|
||||||
namespace FlaxEditor.Content
|
namespace FlaxEditor.Content
|
||||||
{
|
{
|
||||||
@@ -42,7 +43,7 @@ namespace FlaxEditor.Content
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
|
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
|
||||||
{
|
{
|
||||||
var type = Scripting.TypeUtils.GetType(typeName).Type;
|
var type = TypeUtils.GetType(typeName).Type;
|
||||||
|
|
||||||
if (typeof(TextureBase).IsAssignableFrom(type))
|
if (typeof(TextureBase).IsAssignableFrom(type))
|
||||||
return new TextureAssetItem(path, ref id, typeName, type);
|
return new TextureAssetItem(path, ref id, typeName, type);
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ namespace FlaxEditor.Content
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The associated model.</param>
|
/// <param name="model">The associated model.</param>
|
||||||
/// <param name="created">The action to call once the collision data gets created (or reused from existing).</param>
|
/// <param name="created">The action to call once the collision data gets created (or reused from existing).</param>
|
||||||
public void CreateCollisionDataFromModel(Model model, Action<CollisionData> created = null)
|
/// <param name="withRenaming">True if start initial item renaming by user, or tru to skip it.</param>
|
||||||
|
public void CreateCollisionDataFromModel(Model model, Action<CollisionData> created = null, bool withRenaming = true)
|
||||||
{
|
{
|
||||||
// Check if there already is collision data for that model to reuse
|
// Check if there already is collision data for that model to reuse
|
||||||
var modelItem = (AssetItem)Editor.Instance.ContentDatabase.Find(model.ID);
|
var modelItem = (AssetItem)Editor.Instance.ContentDatabase.Find(model.ID);
|
||||||
@@ -140,7 +141,7 @@ namespace FlaxEditor.Content
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
var initialName = (modelItem?.ShortName ?? Path.GetFileNameWithoutExtension(model.Path)) + " Collision";
|
var initialName = (modelItem?.ShortName ?? Path.GetFileNameWithoutExtension(model.Path)) + " Collision";
|
||||||
Editor.Instance.Windows.ContentWin.NewItem(this, null, create, initialName);
|
Editor.Instance.Windows.ContentWin.NewItem(this, null, create, initialName, withRenaming);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ namespace FlaxEditor.Content
|
|||||||
/// Json assets proxy.
|
/// Json assets proxy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
||||||
[ContentContextMenu("New/Json Asset")]
|
|
||||||
public abstract class JsonAssetProxy : JsonAssetBaseProxy
|
public abstract class JsonAssetProxy : JsonAssetBaseProxy
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -127,6 +126,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Generic Json assets proxy (supports all json assets that don't have dedicated proxy).
|
/// Generic Json assets proxy (supports all json assets that don't have dedicated proxy).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
||||||
|
[ContentContextMenu("New/Json Asset")]
|
||||||
public class GenericJsonAssetProxy : JsonAssetProxy
|
public class GenericJsonAssetProxy : JsonAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -72,11 +72,9 @@ namespace FlaxEditor.Content
|
|||||||
/// <param name="materialItem">The material item to use as a base material.</param>
|
/// <param name="materialItem">The material item to use as a base material.</param>
|
||||||
public static void CreateMaterialInstance(BinaryAssetItem materialItem)
|
public static void CreateMaterialInstance(BinaryAssetItem materialItem)
|
||||||
{
|
{
|
||||||
if (materialItem == null)
|
var materialInstanceName = materialItem.ShortName + " Instance";
|
||||||
throw new ArgumentNullException();
|
|
||||||
|
|
||||||
var materialInstanceProxy = Editor.Instance.ContentDatabase.GetProxy<MaterialInstance>();
|
var materialInstanceProxy = Editor.Instance.ContentDatabase.GetProxy<MaterialInstance>();
|
||||||
Editor.Instance.Windows.ContentWin.NewItem(materialInstanceProxy, null, item => OnMaterialInstanceCreated(item, materialItem));
|
Editor.Instance.Windows.ContentWin.NewItem(materialInstanceProxy, null, item => OnMaterialInstanceCreated(item, materialItem), materialInstanceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnMaterialInstanceCreated(ContentItem item, BinaryAssetItem materialItem)
|
private static void OnMaterialInstanceCreated(ContentItem item, BinaryAssetItem materialItem)
|
||||||
|
|||||||
@@ -47,9 +47,23 @@ namespace FlaxEditor.Content
|
|||||||
|
|
||||||
menu.AddButton("Create collision data", () =>
|
menu.AddButton("Create collision data", () =>
|
||||||
{
|
{
|
||||||
var model = FlaxEngine.Content.LoadAsync<Model>(((ModelItem)item).ID);
|
|
||||||
var collisionDataProxy = (CollisionDataProxy)Editor.Instance.ContentDatabase.GetProxy<CollisionData>();
|
var collisionDataProxy = (CollisionDataProxy)Editor.Instance.ContentDatabase.GetProxy<CollisionData>();
|
||||||
collisionDataProxy.CreateCollisionDataFromModel(model);
|
var selection = Editor.Instance.Windows.ContentWin.View.Selection;
|
||||||
|
if (selection.Count > 1)
|
||||||
|
{
|
||||||
|
// Batch action
|
||||||
|
var items = selection.ToArray(); // Clone to prevent issue when iterating over and content window changes the selection
|
||||||
|
foreach (var contentItem in items)
|
||||||
|
{
|
||||||
|
if (contentItem is ModelItem modelItem)
|
||||||
|
collisionDataProxy.CreateCollisionDataFromModel(FlaxEngine.Content.LoadAsync<Model>(modelItem.ID), null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var model = FlaxEngine.Content.LoadAsync<Model>(((ModelItem)item).ID);
|
||||||
|
collisionDataProxy.CreateCollisionDataFromModel(model);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace FlaxEditor.Content
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string NewItemName => "Script";
|
public override string NewItemName => "MyScript";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanCreate(ContentFolder targetLocation)
|
public override bool CanCreate(ContentFolder targetLocation)
|
||||||
@@ -72,6 +72,8 @@ namespace FlaxEditor.Content
|
|||||||
// Scripts cannot start with digit.
|
// Scripts cannot start with digit.
|
||||||
if (Char.IsDigit(filename[0]))
|
if (Char.IsDigit(filename[0]))
|
||||||
return false;
|
return false;
|
||||||
|
if (filename.Equals("Script"))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,10 @@ namespace FlaxEditor.Content
|
|||||||
|
|
||||||
// Check if asset is streamed enough
|
// Check if asset is streamed enough
|
||||||
var asset = (SkinnedModel)request.Asset;
|
var asset = (SkinnedModel)request.Asset;
|
||||||
return asset.LoadedLODs >= Mathf.Max(1, (int)(asset.LODs.Length * ThumbnailsModule.MinimumRequiredResourcesQuality));
|
var lods = asset.LODs.Length;
|
||||||
|
if (asset.IsLoaded && lods == 0)
|
||||||
|
return true; // Skeleton-only model
|
||||||
|
return asset.LoadedLODs >= Mathf.Max(1, (int)(lods * ThumbnailsModule.MinimumRequiredResourcesQuality));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using FlaxEditor.Windows;
|
|||||||
using FlaxEditor.Windows.Assets;
|
using FlaxEditor.Windows.Assets;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.Json;
|
using FlaxEngine.Json;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
|
|
||||||
namespace FlaxEditor.Content
|
namespace FlaxEditor.Content
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -242,21 +242,36 @@ namespace FlaxEditor.Content.Thumbnails
|
|||||||
if (!atlas.IsReady)
|
if (!atlas.IsReady)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Setup
|
try
|
||||||
_guiRoot.RemoveChildren();
|
{
|
||||||
_guiRoot.AccentColor = request.Proxy.AccentColor;
|
// Setup
|
||||||
|
_guiRoot.RemoveChildren();
|
||||||
|
_guiRoot.AccentColor = request.Proxy.AccentColor;
|
||||||
|
|
||||||
// Call proxy to prepare for thumbnail rendering
|
// Call proxy to prepare for thumbnail rendering
|
||||||
request.Proxy.OnThumbnailDrawBegin(request, _guiRoot, context);
|
request.Proxy.OnThumbnailDrawBegin(request, _guiRoot, context);
|
||||||
_guiRoot.UnlockChildrenRecursive();
|
_guiRoot.UnlockChildrenRecursive();
|
||||||
|
|
||||||
// Draw preview
|
// Draw preview
|
||||||
context.Clear(_output.View(), Color.Black);
|
context.Clear(_output.View(), Color.Black);
|
||||||
Render2D.CallDrawing(_guiRoot, context, _output);
|
Render2D.CallDrawing(_guiRoot, context, _output);
|
||||||
|
|
||||||
// Call proxy and cleanup UI (delete create controls, shared controls should be unlinked during OnThumbnailDrawEnd event)
|
// Call proxy and cleanup UI (delete create controls, shared controls should be unlinked during OnThumbnailDrawEnd event)
|
||||||
request.Proxy.OnThumbnailDrawEnd(request, _guiRoot);
|
request.Proxy.OnThumbnailDrawEnd(request, _guiRoot);
|
||||||
_guiRoot.DisposeChildren();
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Handle internal errors gracefully (eg. when asset is corrupted and proxy fails)
|
||||||
|
Editor.LogError("Failed to render thumbnail icon for asset: " + request.Item);
|
||||||
|
Editor.LogWarning(ex);
|
||||||
|
request.FinishRender(ref SpriteHandle.Invalid);
|
||||||
|
RemoveRequest(request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_guiRoot.DisposeChildren();
|
||||||
|
}
|
||||||
|
|
||||||
// Copy backbuffer with rendered preview into atlas
|
// Copy backbuffer with rendered preview into atlas
|
||||||
SpriteHandle icon = atlas.OccupySlot(_output, request.Item.ID);
|
SpriteHandle icon = atlas.OccupySlot(_output, request.Item.ID);
|
||||||
|
|||||||
@@ -115,9 +115,19 @@ API_ENUM() enum class BuildPlatform
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_ENUM(Attributes="EditorDisplay(null, \"Mac x64\")")
|
API_ENUM(Attributes="EditorDisplay(null, \"Mac x64\")")
|
||||||
MacOSx64 = 12,
|
MacOSx64 = 12,
|
||||||
};
|
|
||||||
|
|
||||||
extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform);
|
/// <summary>
|
||||||
|
/// MacOS (ARM64 Apple Silicon)
|
||||||
|
/// </summary>
|
||||||
|
API_ENUM(Attributes="EditorDisplay(null, \"Mac ARM64\")")
|
||||||
|
MacOSARM64 = 13,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// iOS (ARM64)
|
||||||
|
/// </summary>
|
||||||
|
API_ENUM(Attributes="EditorDisplay(null, \"iOS ARM64\")")
|
||||||
|
iOSARM64 = 14,
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Game build configuration modes.
|
/// Game build configuration modes.
|
||||||
@@ -140,7 +150,35 @@ API_ENUM() enum class BuildConfiguration
|
|||||||
Release = 2,
|
Release = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// .NET Ahead of Time Compilation (AOT) modes.
|
||||||
|
/// </summary>
|
||||||
|
enum class DotNetAOTModes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// AOT is not used.
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use .NET Native IL Compiler (shorten as ILC) to convert all C# assemblies in native platform executable binary.
|
||||||
|
/// </summary>
|
||||||
|
ILC,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use Mono AOT to cross-compile all used C# assemblies into native platform shared libraries.
|
||||||
|
/// </summary>
|
||||||
|
MonoAOTDynamic,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use Mono AOT to cross-compile all used C# assemblies into native platform static libraries which can be linked into a single shared library.
|
||||||
|
/// </summary>
|
||||||
|
MonoAOTStatic,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform);
|
||||||
extern FLAXENGINE_API const Char* ToString(const BuildConfiguration configuration);
|
extern FLAXENGINE_API const Char* ToString(const BuildConfiguration configuration);
|
||||||
|
extern FLAXENGINE_API const Char* ToString(const DotNetAOTModes mode);
|
||||||
|
|
||||||
#define BUILD_STEP_CANCEL_CHECK if (GameCooker::IsCancelRequested()) return true
|
#define BUILD_STEP_CANCEL_CHECK if (GameCooker::IsCancelRequested()) return true
|
||||||
|
|
||||||
@@ -188,7 +226,7 @@ public:
|
|||||||
API_FIELD(ReadOnly) String OriginalOutputPath;
|
API_FIELD(ReadOnly) String OriginalOutputPath;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The output path for data files (Content, Mono, etc.).
|
/// The output path for data files (Content, Dotnet, Mono, etc.).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(ReadOnly) String DataOutputPath;
|
API_FIELD(ReadOnly) String DataOutputPath;
|
||||||
|
|
||||||
@@ -300,15 +338,18 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the absolute path to the Platform Data folder that contains the binary files used by the current build configuration.
|
/// Gets the absolute path to the Platform Data folder that contains the binary files used by the current build configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The platform data folder path.</returns>
|
|
||||||
String GetGameBinariesPath() const;
|
String GetGameBinariesPath() const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the absolute path to the platform folder that contains the dependency files used by the current build configuration.
|
/// Gets the absolute path to the platform folder that contains the dependency files used by the current build configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The platform deps folder path.</returns>
|
|
||||||
String GetPlatformBinariesRoot() const;
|
String GetPlatformBinariesRoot() const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the platform and architecture for the current BuildPlatform.
|
||||||
|
/// </summary>
|
||||||
|
void GetBuildPlatformName(const Char*& platform, const Char*& architecture) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -368,17 +409,15 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void Error(const String& msg);
|
void Error(const StringView& msg);
|
||||||
|
|
||||||
|
void Error(const String& msg)
|
||||||
|
{
|
||||||
|
Error(StringView(msg));
|
||||||
|
}
|
||||||
|
|
||||||
void Error(const Char* msg)
|
void Error(const Char* msg)
|
||||||
{
|
{
|
||||||
Error(String(msg));
|
Error(StringView(msg));
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void Error(const Char* format, const Args& ... args)
|
|
||||||
{
|
|
||||||
const String msg = String::Format(format, args...);
|
|
||||||
Error(msg);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
#include "GameCooker.h"
|
#include "GameCooker.h"
|
||||||
#include "PlatformTools.h"
|
#include "PlatformTools.h"
|
||||||
#include "FlaxEngine.Gen.h"
|
#include "FlaxEngine.Gen.h"
|
||||||
#include "Engine/Scripting/MainThreadManagedInvokeAction.h"
|
|
||||||
#include "Engine/Scripting/ManagedCLR/MTypes.h"
|
#include "Engine/Scripting/ManagedCLR/MTypes.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
||||||
|
#include "Engine/Scripting/ManagedCLR/MException.h"
|
||||||
|
#include "Engine/Scripting/Internal/MainThreadManagedInvokeAction.h"
|
||||||
#include "Engine/Scripting/Scripting.h"
|
#include "Engine/Scripting/Scripting.h"
|
||||||
#include "Engine/Scripting/ScriptingType.h"
|
#include "Engine/Scripting/ScriptingType.h"
|
||||||
#include "Engine/Scripting/BinaryModule.h"
|
#include "Engine/Scripting/BinaryModule.h"
|
||||||
@@ -23,12 +24,12 @@
|
|||||||
#include "Steps/CookAssetsStep.h"
|
#include "Steps/CookAssetsStep.h"
|
||||||
#include "Steps/PostProcessStep.h"
|
#include "Steps/PostProcessStep.h"
|
||||||
#include "Engine/Platform/ConditionVariable.h"
|
#include "Engine/Platform/ConditionVariable.h"
|
||||||
|
#include "Engine/Platform/CreateProcessSettings.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MDomain.h"
|
#include "Engine/Scripting/ManagedCLR/MDomain.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
|
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
|
||||||
#include "Engine/Content/JsonAsset.h"
|
#include "Engine/Content/JsonAsset.h"
|
||||||
#include "Engine/Content/AssetReference.h"
|
#include "Engine/Content/AssetReference.h"
|
||||||
#include "Engine/Scripting/MException.h"
|
|
||||||
#if PLATFORM_TOOLS_WINDOWS
|
#if PLATFORM_TOOLS_WINDOWS
|
||||||
#include "Platform/Windows/WindowsPlatformTools.h"
|
#include "Platform/Windows/WindowsPlatformTools.h"
|
||||||
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
|
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
|
||||||
@@ -63,6 +64,10 @@
|
|||||||
#include "Platform/Mac/MacPlatformTools.h"
|
#include "Platform/Mac/MacPlatformTools.h"
|
||||||
#include "Engine/Platform/Mac/MacPlatformSettings.h"
|
#include "Engine/Platform/Mac/MacPlatformSettings.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if PLATFORM_TOOLS_IOS
|
||||||
|
#include "Platform/iOS/iOSPlatformTools.h"
|
||||||
|
#include "Engine/Platform/iOS/iOSPlatformSettings.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace GameCookerImpl
|
namespace GameCookerImpl
|
||||||
{
|
{
|
||||||
@@ -139,8 +144,12 @@ const Char* ToString(const BuildPlatform platform)
|
|||||||
return TEXT("PlayStation 5");
|
return TEXT("PlayStation 5");
|
||||||
case BuildPlatform::MacOSx64:
|
case BuildPlatform::MacOSx64:
|
||||||
return TEXT("Mac x64");
|
return TEXT("Mac x64");
|
||||||
|
case BuildPlatform::MacOSARM64:
|
||||||
|
return TEXT("Mac ARM64");
|
||||||
|
case BuildPlatform::iOSARM64:
|
||||||
|
return TEXT("iOS ARM64");
|
||||||
default:
|
default:
|
||||||
return TEXT("?");
|
return TEXT("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,10 +164,37 @@ const Char* ToString(const BuildConfiguration configuration)
|
|||||||
case BuildConfiguration::Release:
|
case BuildConfiguration::Release:
|
||||||
return TEXT("Release");
|
return TEXT("Release");
|
||||||
default:
|
default:
|
||||||
return TEXT("?");
|
return TEXT("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Char* ToString(const DotNetAOTModes mode)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case DotNetAOTModes::None:
|
||||||
|
return TEXT("None");
|
||||||
|
case DotNetAOTModes::ILC:
|
||||||
|
return TEXT("ILC");
|
||||||
|
case DotNetAOTModes::MonoAOTDynamic:
|
||||||
|
return TEXT("MonoAOTDynamic");
|
||||||
|
case DotNetAOTModes::MonoAOTStatic:
|
||||||
|
return TEXT("MonoAOTStatic");
|
||||||
|
default:
|
||||||
|
return TEXT("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlatformTools::IsNativeCodeFile(CookingData& data, const String& file)
|
||||||
|
{
|
||||||
|
const String filename = StringUtils::GetFileName(file);
|
||||||
|
if (filename.Contains(TEXT(".CSharp")) ||
|
||||||
|
filename.Contains(TEXT("Newtonsoft.Json")))
|
||||||
|
return false;
|
||||||
|
// TODO: maybe use Mono.Cecil via Flax.Build to read assembly image metadata and check if it contains C#?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CookingData::AssetTypeStatistics::operator<(const AssetTypeStatistics& other) const
|
bool CookingData::AssetTypeStatistics::operator<(const AssetTypeStatistics& other) const
|
||||||
{
|
{
|
||||||
if (ContentSize != other.ContentSize)
|
if (ContentSize != other.ContentSize)
|
||||||
@@ -211,6 +247,71 @@ String CookingData::GetPlatformBinariesRoot() const
|
|||||||
return Globals::StartupFolder / TEXT("Source/Platforms") / Tools->GetName() / TEXT("Binaries");
|
return Globals::StartupFolder / TEXT("Source/Platforms") / Tools->GetName() / TEXT("Binaries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& architecture) const
|
||||||
|
{
|
||||||
|
switch (Platform)
|
||||||
|
{
|
||||||
|
case BuildPlatform::Windows32:
|
||||||
|
platform = TEXT("Windows");
|
||||||
|
architecture = TEXT("x86");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::Windows64:
|
||||||
|
platform = TEXT("Windows");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::UWPx86:
|
||||||
|
platform = TEXT("UWP");
|
||||||
|
architecture = TEXT("x86");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::UWPx64:
|
||||||
|
platform = TEXT("UWP");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::XboxOne:
|
||||||
|
platform = TEXT("XboxOne");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::LinuxX64:
|
||||||
|
platform = TEXT("Linux");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::PS4:
|
||||||
|
platform = TEXT("PS4");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::XboxScarlett:
|
||||||
|
platform = TEXT("XboxScarlett");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::AndroidARM64:
|
||||||
|
platform = TEXT("Android");
|
||||||
|
architecture = TEXT("ARM64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::Switch:
|
||||||
|
platform = TEXT("Switch");
|
||||||
|
architecture = TEXT("ARM64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::PS5:
|
||||||
|
platform = TEXT("PS5");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::MacOSx64:
|
||||||
|
platform = TEXT("Mac");
|
||||||
|
architecture = TEXT("x64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::MacOSARM64:
|
||||||
|
platform = TEXT("Mac");
|
||||||
|
architecture = TEXT("ARM64");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::iOSARM64:
|
||||||
|
platform = TEXT("iOS");
|
||||||
|
architecture = TEXT("ARM64");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG(Fatal, "Unknown or unsupported build platform.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CookingData::StepProgress(const String& info, const float stepProgress) const
|
void CookingData::StepProgress(const String& info, const float stepProgress) const
|
||||||
{
|
{
|
||||||
const float singleStepProgress = 1.0f / (StepsCount + 1);
|
const float singleStepProgress = 1.0f / (StepsCount + 1);
|
||||||
@@ -242,7 +343,7 @@ void CookingData::AddRootEngineAsset(const String& internalPath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CookingData::Error(const String& msg)
|
void CookingData::Error(const StringView& msg)
|
||||||
{
|
{
|
||||||
LOG_STR(Error, msg);
|
LOG_STR(Error, msg);
|
||||||
}
|
}
|
||||||
@@ -340,6 +441,14 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
|
|||||||
case BuildPlatform::MacOSx64:
|
case BuildPlatform::MacOSx64:
|
||||||
result = New<MacPlatformTools>(ArchitectureType::x64);
|
result = New<MacPlatformTools>(ArchitectureType::x64);
|
||||||
break;
|
break;
|
||||||
|
case BuildPlatform::MacOSARM64:
|
||||||
|
result = New<MacPlatformTools>(ArchitectureType::ARM64);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if PLATFORM_TOOLS_IOS
|
||||||
|
case BuildPlatform::iOSARM64:
|
||||||
|
result = New<iOSPlatformTools>();
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Tools.Add(platform, result);
|
Tools.Add(platform, result);
|
||||||
@@ -470,7 +579,10 @@ void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& build
|
|||||||
buildPlatform = BuildPlatform::PS5;
|
buildPlatform = BuildPlatform::PS5;
|
||||||
break;
|
break;
|
||||||
case PlatformType::Mac:
|
case PlatformType::Mac:
|
||||||
buildPlatform = BuildPlatform::MacOSx64;
|
buildPlatform = PLATFORM_ARCH_ARM || PLATFORM_ARCH_ARM64 ? BuildPlatform::MacOSARM64 : BuildPlatform::MacOSx64;
|
||||||
|
break;
|
||||||
|
case PlatformType::iOS:
|
||||||
|
buildPlatform = BuildPlatform::iOSARM64;
|
||||||
break;
|
break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
@@ -511,9 +623,9 @@ void GameCookerImpl::OnCollectAssets(HashSet<Guid>& assets)
|
|||||||
ASSERT(GameCookerImpl::Internal_OnCollectAssets);
|
ASSERT(GameCookerImpl::Internal_OnCollectAssets);
|
||||||
}
|
}
|
||||||
|
|
||||||
MCore::AttachThread();
|
MCore::Thread::Attach();
|
||||||
MObject* exception = nullptr;
|
MObject* exception = nullptr;
|
||||||
auto list = (MonoArray*)Internal_OnCollectAssets->Invoke(nullptr, nullptr, &exception);
|
auto list = (MArray*)Internal_OnCollectAssets->Invoke(nullptr, nullptr, &exception);
|
||||||
if (exception)
|
if (exception)
|
||||||
{
|
{
|
||||||
MException ex(exception);
|
MException ex(exception);
|
||||||
@@ -547,13 +659,13 @@ bool GameCookerImpl::Build()
|
|||||||
Steps.Add(New<PostProcessStep>());
|
Steps.Add(New<PostProcessStep>());
|
||||||
}
|
}
|
||||||
|
|
||||||
MCore::AttachThread();
|
MCore::Thread::Attach();
|
||||||
|
|
||||||
// Build Started
|
// Build Started
|
||||||
CallEvent(GameCooker::EventType::BuildStarted);
|
CallEvent(GameCooker::EventType::BuildStarted);
|
||||||
|
data.Tools->OnBuildStarted(data);
|
||||||
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
||||||
Steps[stepIndex]->OnBuildStarted(data);
|
Steps[stepIndex]->OnBuildStarted(data);
|
||||||
data.Tools->OnBuildStarted(data);
|
|
||||||
data.InitProgress(Steps.Count());
|
data.InitProgress(Steps.Count());
|
||||||
|
|
||||||
// Execute all steps in a sequence
|
// Execute all steps in a sequence
|
||||||
@@ -602,7 +714,15 @@ bool GameCookerImpl::Build()
|
|||||||
const String commandLine = commandLineFormat.HasChars() ? String::Format(*commandLineFormat, gameArgs) : gameArgs;
|
const String commandLine = commandLineFormat.HasChars() ? String::Format(*commandLineFormat, gameArgs) : gameArgs;
|
||||||
if (workingDir.IsEmpty())
|
if (workingDir.IsEmpty())
|
||||||
workingDir = data.NativeCodeOutputPath;
|
workingDir = data.NativeCodeOutputPath;
|
||||||
Platform::StartProcess(executableFile, commandLine, workingDir);
|
CreateProcessSettings procSettings;
|
||||||
|
procSettings.FileName = executableFile;
|
||||||
|
procSettings.Arguments = commandLine;
|
||||||
|
procSettings.WorkingDirectory = workingDir;
|
||||||
|
procSettings.HiddenWindow = false;
|
||||||
|
procSettings.WaitForEnd = false;
|
||||||
|
procSettings.LogOutput = false;
|
||||||
|
procSettings.ShellExecute = true;
|
||||||
|
Platform::CreateProcess(procSettings);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -612,9 +732,9 @@ bool GameCookerImpl::Build()
|
|||||||
}
|
}
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
CancelFlag = 0;
|
CancelFlag = 0;
|
||||||
data.Tools->OnBuildEnded(data, failed);
|
|
||||||
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
||||||
Steps[stepIndex]->OnBuildEnded(data, failed);
|
Steps[stepIndex]->OnBuildEnded(data, failed);
|
||||||
|
data.Tools->OnBuildEnded(data, failed);
|
||||||
CallEvent(failed ? GameCooker::EventType::BuildFailed : GameCooker::EventType::BuildDone);
|
CallEvent(failed ? GameCooker::EventType::BuildFailed : GameCooker::EventType::BuildDone);
|
||||||
Delete(Data);
|
Delete(Data);
|
||||||
Data = nullptr;
|
Data = nullptr;
|
||||||
@@ -667,7 +787,7 @@ void GameCookerService::Update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
MainThreadManagedInvokeAction::ParamsBuilder params;
|
MainThreadManagedInvokeAction::ParamsBuilder params;
|
||||||
params.AddParam(ProgressMsg, Scripting::GetScriptsDomain()->GetNative());
|
params.AddParam(ProgressMsg, Scripting::GetScriptsDomain());
|
||||||
params.AddParam(ProgressValue);
|
params.AddParam(ProgressValue);
|
||||||
MainThreadManagedInvokeAction::Invoke(Internal_OnProgress, params);
|
MainThreadManagedInvokeAction::Invoke(Internal_OnProgress, params);
|
||||||
GameCooker::OnProgress(ProgressMsg, ProgressValue);
|
GameCooker::OnProgress(ProgressMsg, ProgressValue);
|
||||||
|
|||||||
@@ -103,7 +103,9 @@ namespace FlaxEditor
|
|||||||
case BuildPlatform.AndroidARM64: return PlatformType.Android;
|
case BuildPlatform.AndroidARM64: return PlatformType.Android;
|
||||||
case BuildPlatform.XboxScarlett: return PlatformType.XboxScarlett;
|
case BuildPlatform.XboxScarlett: return PlatformType.XboxScarlett;
|
||||||
case BuildPlatform.Switch: return PlatformType.Switch;
|
case BuildPlatform.Switch: return PlatformType.Switch;
|
||||||
|
case BuildPlatform.MacOSARM64:
|
||||||
case BuildPlatform.MacOSx64: return PlatformType.Mac;
|
case BuildPlatform.MacOSx64: return PlatformType.Mac;
|
||||||
|
case BuildPlatform.iOSARM64: return PlatformType.iOS;
|
||||||
default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null);
|
default: throw new ArgumentOutOfRangeException(nameof(buildPlatform), buildPlatform, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "Editor/Utilities/EditorUtilities.h"
|
#include "Editor/Utilities/EditorUtilities.h"
|
||||||
#include "Engine/Platform/File.h"
|
#include "Engine/Platform/File.h"
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
|
#include "Engine/Platform/CreateProcessSettings.h"
|
||||||
#include "Engine/Platform/Android/AndroidPlatformSettings.h"
|
#include "Engine/Platform/Android/AndroidPlatformSettings.h"
|
||||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||||
#include "Engine/Graphics/Textures/TextureData.h"
|
#include "Engine/Graphics/Textures/TextureData.h"
|
||||||
@@ -115,8 +116,6 @@ void AndroidPlatformTools::OnBuildStarted(CookingData& data)
|
|||||||
data.DataOutputPath /= TEXT("app/assets");
|
data.DataOutputPath /= TEXT("app/assets");
|
||||||
data.NativeCodeOutputPath /= TEXT("app/assets");
|
data.NativeCodeOutputPath /= TEXT("app/assets");
|
||||||
data.ManagedCodeOutputPath /= TEXT("app/assets");
|
data.ManagedCodeOutputPath /= TEXT("app/assets");
|
||||||
|
|
||||||
PlatformTools::OnBuildStarted(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||||
@@ -140,33 +139,8 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
|
|
||||||
// Setup package name (eg. com.company.project)
|
// Setup package name (eg. com.company.project)
|
||||||
String packageName = platformSettings->PackageName;
|
String packageName = platformSettings->PackageName;
|
||||||
{
|
if (EditorUtilities::FormatAppPackageName(packageName))
|
||||||
String productName = gameSettings->ProductName;
|
return true;
|
||||||
productName.Replace(TEXT(" "), TEXT(""));
|
|
||||||
productName.Replace(TEXT("."), TEXT(""));
|
|
||||||
productName.Replace(TEXT("-"), TEXT(""));
|
|
||||||
String companyName = gameSettings->CompanyName;
|
|
||||||
companyName.Replace(TEXT(" "), TEXT(""));
|
|
||||||
companyName.Replace(TEXT("."), TEXT(""));
|
|
||||||
companyName.Replace(TEXT("-"), TEXT(""));
|
|
||||||
packageName.Replace(TEXT("${PROJECT_NAME}"), *productName, StringSearchCase::IgnoreCase);
|
|
||||||
packageName.Replace(TEXT("${COMPANY_NAME}"), *companyName, StringSearchCase::IgnoreCase);
|
|
||||||
packageName = packageName.ToLower();
|
|
||||||
for (int32 i = 0; i < packageName.Length(); i++)
|
|
||||||
{
|
|
||||||
const auto c = packageName[i];
|
|
||||||
if (c != '_' && c != '.' && !StringUtils::IsAlnum(c))
|
|
||||||
{
|
|
||||||
LOG(Error, "Android Package Name \'{0}\' contains invalid character. Only letters, numbers, dots and underscore characters are allowed.", packageName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (packageName.IsEmpty())
|
|
||||||
{
|
|
||||||
LOG(Error, "Android Package Name is empty.", packageName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup Android application permissions
|
// Setup Android application permissions
|
||||||
HashSet<String> permissionsList;
|
HashSet<String> permissionsList;
|
||||||
@@ -267,7 +241,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate Mono files hash id used to skip deploying Mono files if already extracted on device (Mono cannot access files packed into .apk via unix file access)
|
// Generate Dotnet files hash id used to skip deploying Dotnet files if already extracted on device (Dotnet cannot access files packed into .apk via unix file access)
|
||||||
File::WriteAllText(assetsPath / TEXT("hash.txt"), Guid::New().ToString(), Encoding::ANSI);
|
File::WriteAllText(assetsPath / TEXT("hash.txt"), Guid::New().ToString(), Encoding::ANSI);
|
||||||
|
|
||||||
// TODO: expose event to inject custom gradle and manifest options or custom binaries into app
|
// TODO: expose event to inject custom gradle and manifest options or custom binaries into app
|
||||||
@@ -309,11 +283,13 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
Platform::RunProcess(String::Format(TEXT("chmod +x \"{0}/gradlew\""), data.OriginalOutputPath), data.OriginalOutputPath, Dictionary<String, String>(), true);
|
Platform::RunProcess(String::Format(TEXT("chmod +x \"{0}/gradlew\""), data.OriginalOutputPath), data.OriginalOutputPath, Dictionary<String, String>(), true);
|
||||||
#endif
|
#endif
|
||||||
const bool distributionPackage = buildSettings->ForDistribution;
|
const bool distributionPackage = buildSettings->ForDistribution;
|
||||||
const String gradleCommand = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));
|
CreateProcessSettings procSettings;
|
||||||
const int32 result = Platform::RunProcess(gradleCommand, data.OriginalOutputPath, Dictionary<String, String>(), true);
|
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));
|
||||||
|
procSettings.WorkingDirectory = data.OriginalOutputPath;
|
||||||
|
const int32 result = Platform::CreateProcess(procSettings);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to build Gradle project into package (result code: {0}). See log for more info."), result);
|
data.Error(String::Format(TEXT("Failed to build Gradle project into package (result code: {0}). See log for more info."), result));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "GDKPlatformTools.h"
|
#include "GDKPlatformTools.h"
|
||||||
#include "Engine/Platform/File.h"
|
#include "Engine/Platform/File.h"
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
|
#include "Engine/Platform/CreateProcessSettings.h"
|
||||||
#include "Engine/Platform/GDK/GDKPlatformSettings.h"
|
#include "Engine/Platform/GDK/GDKPlatformSettings.h"
|
||||||
#include "Engine/Core/Types/StringBuilder.h"
|
#include "Engine/Core/Types/StringBuilder.h"
|
||||||
#include "Engine/Core/Collections/Sorting.h"
|
#include "Engine/Core/Collections/Sorting.h"
|
||||||
@@ -36,24 +37,9 @@ GDKPlatformTools::GDKPlatformTools()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDKPlatformTools::UseAOT() const
|
DotNetAOTModes GDKPlatformTools::UseAOT() const
|
||||||
{
|
{
|
||||||
return true;
|
return DotNetAOTModes::MonoAOTDynamic;
|
||||||
}
|
|
||||||
|
|
||||||
bool GDKPlatformTools::OnScriptsStepDone(CookingData& data)
|
|
||||||
{
|
|
||||||
// Override Newtonsoft.Json.dll for some platforms (that don't support runtime code generation)
|
|
||||||
const String customBinPath = data.GetPlatformBinariesRoot() / TEXT("Newtonsoft.Json.dll");
|
|
||||||
const String assembliesPath = data.ManagedCodeOutputPath;
|
|
||||||
if (FileSystem::CopyFile(assembliesPath / TEXT("Newtonsoft.Json.dll"), customBinPath))
|
|
||||||
{
|
|
||||||
data.Error(TEXT("Failed to copy deloy custom assembly."));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
FileSystem::DeleteFile(assembliesPath / TEXT("Newtonsoft.Json.pdb"));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDKPlatformTools::OnDeployBinaries(CookingData& data)
|
bool GDKPlatformTools::OnDeployBinaries(CookingData& data)
|
||||||
@@ -66,7 +52,7 @@ bool GDKPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
files.Add(binPath / executableFilename);
|
files.Add(binPath / executableFilename);
|
||||||
if (!FileSystem::FileExists(files[0]))
|
if (!FileSystem::FileExists(files[0]))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Missing executable file ({0})."), files[0]);
|
data.Error(String::Format(TEXT("Missing executable file ({0})."), files[0]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
FileSystem::DirectoryGetFiles(files, binPath, TEXT("*.dll"), DirectorySearchOption::TopDirectoryOnly);
|
FileSystem::DirectoryGetFiles(files, binPath, TEXT("*.dll"), DirectorySearchOption::TopDirectoryOnly);
|
||||||
@@ -74,7 +60,7 @@ bool GDKPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
{
|
{
|
||||||
if (FileSystem::CopyFile(data.NativeCodeOutputPath / StringUtils::GetFileName(files[i]), files[i]))
|
if (FileSystem::CopyFile(data.NativeCodeOutputPath / StringUtils::GetFileName(files[i]), files[i]))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to setup output directory (file {0})."), files[i]);
|
data.Error(String::Format(TEXT("Failed to setup output directory (file {0})."), files[i]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,85 +68,6 @@ bool GDKPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDKPlatformTools::OnConfigureAOT(CookingData& data, AotConfig& config)
|
|
||||||
{
|
|
||||||
const auto platformDataPath = data.GetPlatformBinariesRoot();
|
|
||||||
const bool useInterpreter = true; // TODO: use Full AOT on GDK
|
|
||||||
const bool enableDebug = data.Configuration != BuildConfiguration::Release;
|
|
||||||
const Char* aotMode = useInterpreter ? TEXT("full,interp") : TEXT("full");
|
|
||||||
const Char* debugMode = enableDebug ? TEXT("soft-debug") : TEXT("nodebug");
|
|
||||||
config.AotCompilerArgs = String::Format(TEXT("--aot={0},verbose,stats,print-skipped,{1} -O=all"), aotMode, debugMode);
|
|
||||||
if (enableDebug)
|
|
||||||
config.AotCompilerArgs = TEXT("--debug ") + config.AotCompilerArgs;
|
|
||||||
config.AotCompilerPath = platformDataPath / TEXT("Tools/mono.exe");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GDKPlatformTools::OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath)
|
|
||||||
{
|
|
||||||
// Skip .dll.dll which could be a false result from the previous AOT which could fail
|
|
||||||
if (assemblyPath.EndsWith(TEXT(".dll.dll")))
|
|
||||||
{
|
|
||||||
LOG(Warning, "Skip AOT for file '{0}' as it can be a result from the previous task", assemblyPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if skip this assembly (could be already processed)
|
|
||||||
const String filename = StringUtils::GetFileName(assemblyPath);
|
|
||||||
const String outputPath = config.AotCachePath / filename + TEXT(".dll");
|
|
||||||
if (FileSystem::FileExists(outputPath) && FileSystem::GetFileLastEditTime(assemblyPath) < FileSystem::GetFileLastEditTime(outputPath))
|
|
||||||
return false;
|
|
||||||
LOG(Info, "Calling AOT tool for \"{0}\"", assemblyPath);
|
|
||||||
|
|
||||||
// Cleanup temporary results (fromm the previous AT that fail or sth)
|
|
||||||
const String resultPath = assemblyPath + TEXT(".dll");
|
|
||||||
const String resultPathExp = resultPath + TEXT(".exp");
|
|
||||||
const String resultPathLib = resultPath + TEXT(".lib");
|
|
||||||
const String resultPathPdb = resultPath + TEXT(".pdb");
|
|
||||||
if (FileSystem::FileExists(resultPath))
|
|
||||||
FileSystem::DeleteFile(resultPath);
|
|
||||||
if (FileSystem::FileExists(resultPathExp))
|
|
||||||
FileSystem::DeleteFile(resultPathExp);
|
|
||||||
if (FileSystem::FileExists(resultPathLib))
|
|
||||||
FileSystem::DeleteFile(resultPathLib);
|
|
||||||
if (FileSystem::FileExists(resultPathPdb))
|
|
||||||
FileSystem::DeleteFile(resultPathPdb);
|
|
||||||
|
|
||||||
// Call tool
|
|
||||||
const String workingDir = StringUtils::GetDirectoryName(config.AotCompilerPath);
|
|
||||||
const String command = String::Format(TEXT("\"{0}\" {1} \"{2}\""), config.AotCompilerPath, config.AotCompilerArgs, assemblyPath);
|
|
||||||
const int32 result = Platform::RunProcess(command, workingDir, config.EnvVars);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
data.Error(TEXT("AOT tool execution failed with result code {1} for assembly \"{0}\". See log for more info."), assemblyPath, result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy result
|
|
||||||
if (FileSystem::CopyFile(outputPath, resultPath))
|
|
||||||
{
|
|
||||||
data.Error(TEXT("Failed to copy the AOT tool result file. It can be missing."));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy pdb file if exists
|
|
||||||
if (data.Configuration != BuildConfiguration::Release && FileSystem::FileExists(resultPathPdb))
|
|
||||||
{
|
|
||||||
FileSystem::CopyFile(config.AotCachePath / StringUtils::GetFileName(resultPathPdb), resultPathPdb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean intermediate results
|
|
||||||
if (FileSystem::DeleteFile(resultPath)
|
|
||||||
|| (FileSystem::FileExists(resultPathExp) && FileSystem::DeleteFile(resultPathExp))
|
|
||||||
|| (FileSystem::FileExists(resultPathLib) && FileSystem::DeleteFile(resultPathLib))
|
|
||||||
|| (FileSystem::FileExists(resultPathPdb) && FileSystem::DeleteFile(resultPathPdb))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
LOG(Warning, "Failed to remove the AOT tool result file(s).");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* platformSettings)
|
bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* platformSettings)
|
||||||
{
|
{
|
||||||
// Configuration
|
// Configuration
|
||||||
@@ -275,8 +182,10 @@ bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* pla
|
|||||||
data.StepProgress(TEXT("Generating package layout"), 0.3f);
|
data.StepProgress(TEXT("Generating package layout"), 0.3f);
|
||||||
const String gdkBinPath = _gdkPath / TEXT("../bin");
|
const String gdkBinPath = _gdkPath / TEXT("../bin");
|
||||||
const String makePkgPath = gdkBinPath / TEXT("MakePkg.exe");
|
const String makePkgPath = gdkBinPath / TEXT("MakePkg.exe");
|
||||||
const String command = String::Format(TEXT("\"{0}\" genmap /f layout.xml /d \"{1}\""), makePkgPath, data.DataOutputPath);
|
CreateProcessSettings procSettings;
|
||||||
const int32 result = Platform::RunProcess(command, data.DataOutputPath);
|
procSettings.FileName = String::Format(TEXT("\"{0}\" genmap /f layout.xml /d \"{1}\""), makePkgPath, data.DataOutputPath);
|
||||||
|
procSettings.WorkingDirectory = data.DataOutputPath;
|
||||||
|
const int32 result = Platform::CreateProcess(procSettings);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to generate package layout."));
|
data.Error(TEXT("Failed to generate package layout."));
|
||||||
|
|||||||
@@ -26,11 +26,8 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// [PlatformTools]
|
// [PlatformTools]
|
||||||
bool UseAOT() const override;
|
DotNetAOTModes UseAOT() const override;
|
||||||
bool OnScriptsStepDone(CookingData& data) override;
|
|
||||||
bool OnDeployBinaries(CookingData& data) override;
|
bool OnDeployBinaries(CookingData& data) override;
|
||||||
void OnConfigureAOT(CookingData& data, AotConfig& config) override;
|
|
||||||
bool OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#if PLATFORM_TOOLS_LINUX
|
#if PLATFORM_TOOLS_LINUX
|
||||||
|
|
||||||
@@ -34,6 +34,11 @@ ArchitectureType LinuxPlatformTools::GetArchitecture() const
|
|||||||
return ArchitectureType::x64;
|
return ArchitectureType::x64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LinuxPlatformTools::UseSystemDotnet() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool LinuxPlatformTools::OnDeployBinaries(CookingData& data)
|
bool LinuxPlatformTools::OnDeployBinaries(CookingData& data)
|
||||||
{
|
{
|
||||||
const auto gameSettings = GameSettings::Get();
|
const auto gameSettings = GameSettings::Get();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
const Char* GetName() const override;
|
const Char* GetName() const override;
|
||||||
PlatformType GetPlatform() const override;
|
PlatformType GetPlatform() const override;
|
||||||
ArchitectureType GetArchitecture() const override;
|
ArchitectureType GetArchitecture() const override;
|
||||||
|
bool UseSystemDotnet() const override;
|
||||||
bool OnDeployBinaries(CookingData& data) override;
|
bool OnDeployBinaries(CookingData& data) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#if PLATFORM_TOOLS_MAC
|
#if PLATFORM_TOOLS_MAC
|
||||||
|
|
||||||
@@ -59,6 +59,11 @@ ArchitectureType MacPlatformTools::GetArchitecture() const
|
|||||||
return _arch;
|
return _arch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacPlatformTools::UseSystemDotnet() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool MacPlatformTools::IsNativeCodeFile(CookingData& data, const String& file)
|
bool MacPlatformTools::IsNativeCodeFile(CookingData& data, const String& file)
|
||||||
{
|
{
|
||||||
String extension = FileSystem::GetExtension(file);
|
String extension = FileSystem::GetExtension(file);
|
||||||
@@ -87,33 +92,8 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
|
|
||||||
// Setup package name (eg. com.company.project)
|
// Setup package name (eg. com.company.project)
|
||||||
String appIdentifier = platformSettings->AppIdentifier;
|
String appIdentifier = platformSettings->AppIdentifier;
|
||||||
{
|
if (EditorUtilities::FormatAppPackageName(appIdentifier))
|
||||||
String productName = gameSettings->ProductName;
|
return true;
|
||||||
productName.Replace(TEXT(" "), TEXT(""));
|
|
||||||
productName.Replace(TEXT("."), TEXT(""));
|
|
||||||
productName.Replace(TEXT("-"), TEXT(""));
|
|
||||||
String companyName = gameSettings->CompanyName;
|
|
||||||
companyName.Replace(TEXT(" "), TEXT(""));
|
|
||||||
companyName.Replace(TEXT("."), TEXT(""));
|
|
||||||
companyName.Replace(TEXT("-"), TEXT(""));
|
|
||||||
appIdentifier.Replace(TEXT("${PROJECT_NAME}"), *productName, StringSearchCase::IgnoreCase);
|
|
||||||
appIdentifier.Replace(TEXT("${COMPANY_NAME}"), *companyName, StringSearchCase::IgnoreCase);
|
|
||||||
appIdentifier = appIdentifier.ToLower();
|
|
||||||
for (int32 i = 0; i < appIdentifier.Length(); i++)
|
|
||||||
{
|
|
||||||
const auto c = appIdentifier[i];
|
|
||||||
if (c != '_' && c != '.' && !StringUtils::IsAlnum(c))
|
|
||||||
{
|
|
||||||
LOG(Error, "Apple app identifier \'{0}\' contains invalid character. Only letters, numbers, dots and underscore characters are allowed.", appIdentifier);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (appIdentifier.IsEmpty())
|
|
||||||
{
|
|
||||||
LOG(Error, "Apple app identifier is empty.", appIdentifier);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find executable
|
// Find executable
|
||||||
String executableName;
|
String executableName;
|
||||||
@@ -187,7 +167,7 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
ADD_ENTRY("CFBundlePackageType", "APPL");
|
ADD_ENTRY("CFBundlePackageType", "APPL");
|
||||||
ADD_ENTRY("NSPrincipalClass", "NSApplication");
|
ADD_ENTRY("NSPrincipalClass", "NSApplication");
|
||||||
ADD_ENTRY("LSApplicationCategoryType", "public.app-category.games");
|
ADD_ENTRY("LSApplicationCategoryType", "public.app-category.games");
|
||||||
ADD_ENTRY("LSMinimumSystemVersion", "10.14");
|
ADD_ENTRY("LSMinimumSystemVersion", "10.15");
|
||||||
ADD_ENTRY("CFBundleIconFile", "icon.icns");
|
ADD_ENTRY("CFBundleIconFile", "icon.icns");
|
||||||
ADD_ENTRY_STR("CFBundleExecutable", executableName);
|
ADD_ENTRY_STR("CFBundleExecutable", executableName);
|
||||||
ADD_ENTRY_STR("CFBundleIdentifier", appIdentifier);
|
ADD_ENTRY_STR("CFBundleIdentifier", appIdentifier);
|
||||||
@@ -201,10 +181,19 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
|
|
||||||
dict.append_child(PUGIXML_TEXT("key")).set_child_value(PUGIXML_TEXT("LSMinimumSystemVersionByArchitecture"));
|
dict.append_child(PUGIXML_TEXT("key")).set_child_value(PUGIXML_TEXT("LSMinimumSystemVersionByArchitecture"));
|
||||||
xml_node LSMinimumSystemVersionByArchitecture = dict.append_child(PUGIXML_TEXT("dict"));
|
xml_node LSMinimumSystemVersionByArchitecture = dict.append_child(PUGIXML_TEXT("dict"));
|
||||||
LSMinimumSystemVersionByArchitecture.append_child(PUGIXML_TEXT("key")).set_child_value(PUGIXML_TEXT("x86_64"));
|
switch (_arch)
|
||||||
LSMinimumSystemVersionByArchitecture.append_child(PUGIXML_TEXT("string")).set_child_value(PUGIXML_TEXT("10.14"));
|
{
|
||||||
|
case ArchitectureType::x64:
|
||||||
|
LSMinimumSystemVersionByArchitecture.append_child(PUGIXML_TEXT("key")).set_child_value(PUGIXML_TEXT("x86_64"));
|
||||||
|
break;
|
||||||
|
case ArchitectureType::ARM64:
|
||||||
|
LSMinimumSystemVersionByArchitecture.append_child(PUGIXML_TEXT("key")).set_child_value(PUGIXML_TEXT("arm64"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LSMinimumSystemVersionByArchitecture.append_child(PUGIXML_TEXT("string")).set_child_value(PUGIXML_TEXT("10.15"));
|
||||||
|
|
||||||
#undef ADD_ENTRY
|
#undef ADD_ENTRY
|
||||||
|
#undef ADD_ENTRY_STR
|
||||||
|
|
||||||
if (!doc.save_file(*StringAnsi(plistPath)))
|
if (!doc.save_file(*StringAnsi(plistPath)))
|
||||||
{
|
{
|
||||||
@@ -215,8 +204,6 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
|
|
||||||
// TODO: sign binaries
|
// TODO: sign binaries
|
||||||
|
|
||||||
// TODO: expose event to inject custom post-processing before app packaging (eg. third-party plugins)
|
|
||||||
|
|
||||||
// Package application
|
// Package application
|
||||||
const auto buildSettings = BuildSettings::Get();
|
const auto buildSettings = BuildSettings::Get();
|
||||||
if (buildSettings->SkipPackaging)
|
if (buildSettings->SkipPackaging)
|
||||||
@@ -228,7 +215,7 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
const int32 result = Platform::RunProcess(dmgCommand, data.OriginalOutputPath);
|
const int32 result = Platform::RunProcess(dmgCommand, data.OriginalOutputPath);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to package app (result code: {0}). See log for more info."), result);
|
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// TODO: sign dmg
|
// TODO: sign dmg
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
const Char* GetName() const override;
|
const Char* GetName() const override;
|
||||||
PlatformType GetPlatform() const override;
|
PlatformType GetPlatform() const override;
|
||||||
ArchitectureType GetArchitecture() const override;
|
ArchitectureType GetArchitecture() const override;
|
||||||
|
bool UseSystemDotnet() const override;
|
||||||
bool IsNativeCodeFile(CookingData& data, const String& file) override;
|
bool IsNativeCodeFile(CookingData& data, const String& file) override;
|
||||||
void OnBuildStarted(CookingData& data) override;
|
void OnBuildStarted(CookingData& data) override;
|
||||||
bool OnPostProcess(CookingData& data) override;
|
bool OnPostProcess(CookingData& data) override;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#if PLATFORM_TOOLS_UWP
|
#if PLATFORM_TOOLS_UWP
|
||||||
|
|
||||||
#include "UWPPlatformTools.h"
|
#include "UWPPlatformTools.h"
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
#include "Engine/Platform/File.h"
|
#include "Engine/Platform/File.h"
|
||||||
|
#include "Engine/Platform/CreateProcessSettings.h"
|
||||||
#include "Engine/Platform/UWP/UWPPlatformSettings.h"
|
#include "Engine/Platform/UWP/UWPPlatformSettings.h"
|
||||||
#include "Engine/Core/Config/GameSettings.h"
|
#include "Engine/Core/Config/GameSettings.h"
|
||||||
#include "Engine/Core/Types/StringBuilder.h"
|
#include "Engine/Core/Types/StringBuilder.h"
|
||||||
@@ -36,24 +37,9 @@ ArchitectureType UWPPlatformTools::GetArchitecture() const
|
|||||||
return _arch;
|
return _arch;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UWPPlatformTools::UseAOT() const
|
DotNetAOTModes UWPPlatformTools::UseAOT() const
|
||||||
{
|
{
|
||||||
return true;
|
return DotNetAOTModes::MonoAOTDynamic;
|
||||||
}
|
|
||||||
|
|
||||||
bool UWPPlatformTools::OnScriptsStepDone(CookingData& data)
|
|
||||||
{
|
|
||||||
// Override Newtonsoft.Json.dll for some platforms (that don't support runtime code generation)
|
|
||||||
const String customBinPath = data.GetPlatformBinariesRoot() / TEXT("Newtonsoft.Json.dll");
|
|
||||||
const String assembliesPath = data.ManagedCodeOutputPath;
|
|
||||||
if (FileSystem::CopyFile(assembliesPath / TEXT("Newtonsoft.Json.dll"), customBinPath))
|
|
||||||
{
|
|
||||||
data.Error(TEXT("Failed to copy deploy custom assembly."));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
FileSystem::DeleteFile(assembliesPath / TEXT("Newtonsoft.Json.pdb"));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
||||||
@@ -79,7 +65,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
{
|
{
|
||||||
if (!FileSystem::FileExists(files[i]))
|
if (!FileSystem::FileExists(files[i]))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Missing source file {0}."), files[i]);
|
data.Error(String::Format(TEXT("Missing source file {0}."), files[i]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,90 +400,9 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UWPPlatformTools::OnConfigureAOT(CookingData& data, AotConfig& config)
|
|
||||||
{
|
|
||||||
const auto platformDataPath = data.GetPlatformBinariesRoot();
|
|
||||||
const bool useInterpreter = true; // TODO: support using Full AOT instead of interpreter
|
|
||||||
const bool enableDebug = data.Configuration != BuildConfiguration::Release;
|
|
||||||
const Char* aotMode = useInterpreter ? TEXT("full,interp") : TEXT("full");
|
|
||||||
const Char* debugMode = enableDebug ? TEXT("soft-debug") : TEXT("nodebug");
|
|
||||||
config.AotCompilerArgs = String::Format(TEXT("--aot={0},verbose,stats,print-skipped,{1} -O=all"),
|
|
||||||
aotMode,
|
|
||||||
debugMode);
|
|
||||||
if (enableDebug)
|
|
||||||
config.AotCompilerArgs = TEXT("--debug ") + config.AotCompilerArgs;
|
|
||||||
config.AotCompilerPath = platformDataPath / TEXT("Tools/mono.exe");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UWPPlatformTools::OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath)
|
|
||||||
{
|
|
||||||
// Skip .dll.dll which could be a false result from the previous AOT which could fail
|
|
||||||
if (assemblyPath.EndsWith(TEXT(".dll.dll")))
|
|
||||||
{
|
|
||||||
LOG(Warning, "Skip AOT for file '{0}' as it can be a result from the previous task", assemblyPath);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if skip this assembly (could be already processed)
|
|
||||||
const String filename = StringUtils::GetFileName(assemblyPath);
|
|
||||||
const String outputPath = config.AotCachePath / filename + TEXT(".dll");
|
|
||||||
if (FileSystem::FileExists(outputPath) && FileSystem::GetFileLastEditTime(assemblyPath) < FileSystem::GetFileLastEditTime(outputPath))
|
|
||||||
return false;
|
|
||||||
LOG(Info, "Calling AOT tool for \"{0}\"", assemblyPath);
|
|
||||||
|
|
||||||
// Cleanup temporary results (fromm the previous AT that fail or sth)
|
|
||||||
const String resultPath = assemblyPath + TEXT(".dll");
|
|
||||||
const String resultPathExp = resultPath + TEXT(".exp");
|
|
||||||
const String resultPathLib = resultPath + TEXT(".lib");
|
|
||||||
const String resultPathPdb = resultPath + TEXT(".pdb");
|
|
||||||
if (FileSystem::FileExists(resultPath))
|
|
||||||
FileSystem::DeleteFile(resultPath);
|
|
||||||
if (FileSystem::FileExists(resultPathExp))
|
|
||||||
FileSystem::DeleteFile(resultPathExp);
|
|
||||||
if (FileSystem::FileExists(resultPathLib))
|
|
||||||
FileSystem::DeleteFile(resultPathLib);
|
|
||||||
if (FileSystem::FileExists(resultPathPdb))
|
|
||||||
FileSystem::DeleteFile(resultPathPdb);
|
|
||||||
|
|
||||||
// Call tool
|
|
||||||
String workingDir = StringUtils::GetDirectoryName(config.AotCompilerPath);
|
|
||||||
String command = String::Format(TEXT("\"{0}\" {1} \"{2}\""), config.AotCompilerPath, config.AotCompilerArgs, assemblyPath);
|
|
||||||
const int32 result = Platform::RunProcess(command, workingDir, config.EnvVars);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
data.Error(TEXT("AOT tool execution failed with result code {1} for assembly \"{0}\". See log for more info."), assemblyPath, result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy result
|
|
||||||
if (FileSystem::CopyFile(outputPath, resultPath))
|
|
||||||
{
|
|
||||||
data.Error(TEXT("Failed to copy the AOT tool result file. It can be missing."));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy pdb file if exists
|
|
||||||
if (data.Configuration != BuildConfiguration::Release && FileSystem::FileExists(resultPathPdb))
|
|
||||||
{
|
|
||||||
FileSystem::CopyFile(config.AotCachePath / StringUtils::GetFileName(resultPathPdb), resultPathPdb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean intermediate results
|
|
||||||
if (FileSystem::DeleteFile(resultPath)
|
|
||||||
|| (FileSystem::FileExists(resultPathExp) && FileSystem::DeleteFile(resultPathExp))
|
|
||||||
|| (FileSystem::FileExists(resultPathLib) && FileSystem::DeleteFile(resultPathLib))
|
|
||||||
|| (FileSystem::FileExists(resultPathPdb) && FileSystem::DeleteFile(resultPathPdb))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
LOG(Warning, "Failed to remove the AOT tool result file(s).");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UWPPlatformTools::OnPostProcess(CookingData& data)
|
bool UWPPlatformTools::OnPostProcess(CookingData& data)
|
||||||
{
|
{
|
||||||
LOG(Error, "UWP (Windows Store) platform has been deprecated and soon will be removed!");
|
LOG(Error, "UWP (Windows Store) platform has been deprecated and is no longer supported");
|
||||||
|
|
||||||
// Special case for UWP
|
// Special case for UWP
|
||||||
// FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll)
|
// FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -29,11 +29,8 @@ public:
|
|||||||
const Char* GetName() const override;
|
const Char* GetName() const override;
|
||||||
PlatformType GetPlatform() const override;
|
PlatformType GetPlatform() const override;
|
||||||
ArchitectureType GetArchitecture() const override;
|
ArchitectureType GetArchitecture() const override;
|
||||||
bool UseAOT() const override;
|
DotNetAOTModes UseAOT() const override;
|
||||||
bool OnScriptsStepDone(CookingData& data) override;
|
|
||||||
bool OnDeployBinaries(CookingData& data) override;
|
bool OnDeployBinaries(CookingData& data) override;
|
||||||
void OnConfigureAOT(CookingData& data, AotConfig& config) override;
|
|
||||||
bool OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath) override;
|
|
||||||
bool OnPostProcess(CookingData& data) override;
|
bool OnPostProcess(CookingData& data) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#if PLATFORM_TOOLS_WINDOWS
|
#if PLATFORM_TOOLS_WINDOWS
|
||||||
|
|
||||||
@@ -33,6 +33,11 @@ ArchitectureType WindowsPlatformTools::GetArchitecture() const
|
|||||||
return _arch;
|
return _arch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WindowsPlatformTools::UseSystemDotnet() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
|
bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
|
||||||
{
|
{
|
||||||
const auto platformSettings = WindowsPlatformSettings::Get();
|
const auto platformSettings = WindowsPlatformSettings::Get();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ public:
|
|||||||
const Char* GetName() const override;
|
const Char* GetName() const override;
|
||||||
PlatformType GetPlatform() const override;
|
PlatformType GetPlatform() const override;
|
||||||
ArchitectureType GetArchitecture() const override;
|
ArchitectureType GetArchitecture() const override;
|
||||||
|
bool UseSystemDotnet() const override;
|
||||||
bool OnDeployBinaries(CookingData& data) override;
|
bool OnDeployBinaries(CookingData& data) override;
|
||||||
void OnRun(CookingData& data, String& executableFile, String& commandLineFormat, String& workingDir) override;
|
void OnRun(CookingData& data, String& executableFile, String& commandLineFormat, String& workingDir) override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,284 @@
|
|||||||
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if PLATFORM_TOOLS_IOS
|
||||||
|
|
||||||
|
#include "iOSPlatformTools.h"
|
||||||
|
#include "Engine/Platform/File.h"
|
||||||
|
#include "Engine/Platform/FileSystem.h"
|
||||||
|
#include "Engine/Platform/CreateProcessSettings.h"
|
||||||
|
#include "Engine/Platform/iOS/iOSPlatformSettings.h"
|
||||||
|
#include "Engine/Core/Config/GameSettings.h"
|
||||||
|
#include "Engine/Core/Config/BuildSettings.h"
|
||||||
|
#include "Engine/Core/Collections/Dictionary.h"
|
||||||
|
#include "Engine/Graphics/Textures/TextureData.h"
|
||||||
|
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||||
|
#include "Engine/Content/Content.h"
|
||||||
|
#include "Engine/Content/JsonAsset.h"
|
||||||
|
#include "Engine/Engine/Globals.h"
|
||||||
|
#include "Editor/Editor.h"
|
||||||
|
#include "Editor/ProjectInfo.h"
|
||||||
|
#include "Editor/Cooker/GameCooker.h"
|
||||||
|
#include "Editor/Utilities/EditorUtilities.h"
|
||||||
|
|
||||||
|
IMPLEMENT_SETTINGS_GETTER(iOSPlatformSettings, iOSPlatform);
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
String GetAppName()
|
||||||
|
{
|
||||||
|
const auto gameSettings = GameSettings::Get();
|
||||||
|
String productName = gameSettings->ProductName;
|
||||||
|
productName.Replace(TEXT(" "), TEXT(""));
|
||||||
|
productName.Replace(TEXT("."), TEXT(""));
|
||||||
|
productName.Replace(TEXT("-"), TEXT(""));
|
||||||
|
return productName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Char* GetExportMethod(iOSPlatformSettings::ExportMethods method)
|
||||||
|
{
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case iOSPlatformSettings::ExportMethods::AppStore: return TEXT("app-store");
|
||||||
|
case iOSPlatformSettings::ExportMethods::Development: return TEXT("development");
|
||||||
|
case iOSPlatformSettings::ExportMethods::AdHoc: return TEXT("ad-hoc");
|
||||||
|
case iOSPlatformSettings::ExportMethods::Enterprise: return TEXT("enterprise");
|
||||||
|
default: return TEXT("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String GetUIInterfaceOrientation(iOSPlatformSettings::UIInterfaceOrientations orientations)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
if (EnumHasAnyFlags(orientations, iOSPlatformSettings::UIInterfaceOrientations::Portrait))
|
||||||
|
result += TEXT("UIInterfaceOrientationPortrait ");
|
||||||
|
if (EnumHasAnyFlags(orientations, iOSPlatformSettings::UIInterfaceOrientations::PortraitUpsideDown))
|
||||||
|
result += TEXT("UIInterfaceOrientationPortraitUpsideDown ");
|
||||||
|
if (EnumHasAnyFlags(orientations, iOSPlatformSettings::UIInterfaceOrientations::LandscapeLeft))
|
||||||
|
result += TEXT("UIInterfaceOrientationLandscapeLeft ");
|
||||||
|
if (EnumHasAnyFlags(orientations, iOSPlatformSettings::UIInterfaceOrientations::LandscapeRight))
|
||||||
|
result += TEXT("UIInterfaceOrientationLandscapeRight ");
|
||||||
|
result = result.TrimTrailing();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Char* iOSPlatformTools::GetDisplayName() const
|
||||||
|
{
|
||||||
|
return TEXT("iOS");
|
||||||
|
}
|
||||||
|
|
||||||
|
const Char* iOSPlatformTools::GetName() const
|
||||||
|
{
|
||||||
|
return TEXT("iOS");
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformType iOSPlatformTools::GetPlatform() const
|
||||||
|
{
|
||||||
|
return PlatformType::iOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArchitectureType iOSPlatformTools::GetArchitecture() const
|
||||||
|
{
|
||||||
|
return ArchitectureType::ARM64;
|
||||||
|
}
|
||||||
|
|
||||||
|
DotNetAOTModes iOSPlatformTools::UseAOT() const
|
||||||
|
{
|
||||||
|
return DotNetAOTModes::MonoAOTDynamic;
|
||||||
|
}
|
||||||
|
|
||||||
|
PixelFormat iOSPlatformTools::GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format)
|
||||||
|
{
|
||||||
|
// TODO: add ETC compression support for iOS
|
||||||
|
// TODO: add ASTC compression support for iOS
|
||||||
|
|
||||||
|
if (PixelFormatExtensions::IsCompressedBC(format))
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case PixelFormat::BC1_Typeless:
|
||||||
|
case PixelFormat::BC2_Typeless:
|
||||||
|
case PixelFormat::BC3_Typeless:
|
||||||
|
return PixelFormat::R8G8B8A8_Typeless;
|
||||||
|
case PixelFormat::BC1_UNorm:
|
||||||
|
case PixelFormat::BC2_UNorm:
|
||||||
|
case PixelFormat::BC3_UNorm:
|
||||||
|
return PixelFormat::R8G8B8A8_UNorm;
|
||||||
|
case PixelFormat::BC1_UNorm_sRGB:
|
||||||
|
case PixelFormat::BC2_UNorm_sRGB:
|
||||||
|
case PixelFormat::BC3_UNorm_sRGB:
|
||||||
|
return PixelFormat::R8G8B8A8_UNorm_sRGB;
|
||||||
|
case PixelFormat::BC4_Typeless:
|
||||||
|
return PixelFormat::R8_Typeless;
|
||||||
|
case PixelFormat::BC4_UNorm:
|
||||||
|
return PixelFormat::R8_UNorm;
|
||||||
|
case PixelFormat::BC4_SNorm:
|
||||||
|
return PixelFormat::R8_SNorm;
|
||||||
|
case PixelFormat::BC5_Typeless:
|
||||||
|
return PixelFormat::R16G16_Typeless;
|
||||||
|
case PixelFormat::BC5_UNorm:
|
||||||
|
return PixelFormat::R16G16_UNorm;
|
||||||
|
case PixelFormat::BC5_SNorm:
|
||||||
|
return PixelFormat::R16G16_SNorm;
|
||||||
|
case PixelFormat::BC7_Typeless:
|
||||||
|
case PixelFormat::BC6H_Typeless:
|
||||||
|
return PixelFormat::R16G16B16A16_Typeless;
|
||||||
|
case PixelFormat::BC7_UNorm:
|
||||||
|
case PixelFormat::BC6H_Uf16:
|
||||||
|
case PixelFormat::BC6H_Sf16:
|
||||||
|
return PixelFormat::R16G16B16A16_Float;
|
||||||
|
case PixelFormat::BC7_UNorm_sRGB:
|
||||||
|
return PixelFormat::R16G16B16A16_UNorm;
|
||||||
|
default:
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iOSPlatformTools::IsNativeCodeFile(CookingData& data, const String& file)
|
||||||
|
{
|
||||||
|
String extension = FileSystem::GetExtension(file);
|
||||||
|
return extension.IsEmpty() || extension == TEXT("dylib");
|
||||||
|
}
|
||||||
|
|
||||||
|
void iOSPlatformTools::OnBuildStarted(CookingData& data)
|
||||||
|
{
|
||||||
|
// Adjust the cooking output folders for packaging app
|
||||||
|
const Char* subDir = TEXT("FlaxGame/Data");
|
||||||
|
data.DataOutputPath /= subDir;
|
||||||
|
data.NativeCodeOutputPath /= subDir;
|
||||||
|
data.ManagedCodeOutputPath /= subDir;
|
||||||
|
|
||||||
|
PlatformTools::OnBuildStarted(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iOSPlatformTools::OnPostProcess(CookingData& data)
|
||||||
|
{
|
||||||
|
const auto gameSettings = GameSettings::Get();
|
||||||
|
const auto platformSettings = iOSPlatformSettings::Get();
|
||||||
|
const auto platformDataPath = data.GetPlatformBinariesRoot();
|
||||||
|
const auto projectVersion = Editor::Project->Version.ToString();
|
||||||
|
const auto appName = GetAppName();
|
||||||
|
|
||||||
|
// Setup package name (eg. com.company.project)
|
||||||
|
String appIdentifier = platformSettings->AppIdentifier;
|
||||||
|
if (EditorUtilities::FormatAppPackageName(appIdentifier))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Copy fresh Gradle project template
|
||||||
|
if (FileSystem::CopyDirectory(data.OriginalOutputPath, platformDataPath / TEXT("Project"), true))
|
||||||
|
{
|
||||||
|
LOG(Error, "Failed to deploy XCode project to {0} from {1}", data.OriginalOutputPath, platformDataPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format project template files
|
||||||
|
Dictionary<String, String> configReplaceMap;
|
||||||
|
configReplaceMap[TEXT("${AppName}")] = appName;
|
||||||
|
configReplaceMap[TEXT("${AppIdentifier}")] = appIdentifier;
|
||||||
|
configReplaceMap[TEXT("${AppTeamId}")] = platformSettings->AppTeamId;
|
||||||
|
configReplaceMap[TEXT("${AppVersion}")] = platformSettings->AppVersion;
|
||||||
|
configReplaceMap[TEXT("${ProjectName}")] = gameSettings->ProductName;
|
||||||
|
configReplaceMap[TEXT("${ProjectVersion}")] = projectVersion;
|
||||||
|
configReplaceMap[TEXT("${HeaderSearchPaths}")] = Globals::StartupFolder;
|
||||||
|
configReplaceMap[TEXT("${ExportMethod}")] = GetExportMethod(platformSettings->ExportMethod);
|
||||||
|
configReplaceMap[TEXT("${UISupportedInterfaceOrientations_iPhone}")] = GetUIInterfaceOrientation(platformSettings->SupportedInterfaceOrientationsiPhone);
|
||||||
|
configReplaceMap[TEXT("${UISupportedInterfaceOrientations_iPad}")] = GetUIInterfaceOrientation(platformSettings->SupportedInterfaceOrientationsiPad);
|
||||||
|
{
|
||||||
|
// Initialize auto-generated areas as empty
|
||||||
|
configReplaceMap[TEXT("${PBXBuildFile}")] = String::Empty;
|
||||||
|
configReplaceMap[TEXT("${PBXCopyFilesBuildPhaseFiles}")] = String::Empty;
|
||||||
|
configReplaceMap[TEXT("${PBXFileReference}")] = String::Empty;
|
||||||
|
configReplaceMap[TEXT("${PBXFrameworksBuildPhase}")] = String::Empty;
|
||||||
|
configReplaceMap[TEXT("${PBXFrameworksGroup}")] = String::Empty;
|
||||||
|
configReplaceMap[TEXT("${PBXFilesGroup}")] = String::Empty;
|
||||||
|
configReplaceMap[TEXT("${PBXResourcesGroup}")] = String::Empty;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Rename dotnet license files to not mislead the actual game licensing
|
||||||
|
FileSystem::MoveFile(data.DataOutputPath / TEXT("Dotnet/DOTNET-LICENSE.TXT"), data.DataOutputPath / TEXT("Dotnet/LICENSE.TXT"), true);
|
||||||
|
FileSystem::MoveFile(data.DataOutputPath / TEXT("Dotnet/DOTNET-THIRD-PARTY-NOTICES.TXT"), data.DataOutputPath / TEXT("Dotnet/THIRD-PARTY-NOTICES.TXT"), true);
|
||||||
|
}
|
||||||
|
Array<String> files;
|
||||||
|
FileSystem::DirectoryGetFiles(files, data.DataOutputPath, TEXT("*"), DirectorySearchOption::AllDirectories);
|
||||||
|
for (const String& file : files)
|
||||||
|
{
|
||||||
|
String name = StringUtils::GetFileName(file);
|
||||||
|
if (name == TEXT(".DS_Store") || name == TEXT("FlaxGame"))
|
||||||
|
continue;
|
||||||
|
String fileId = Guid::New().ToString(Guid::FormatType::N).Left(24);
|
||||||
|
String projectPath = FileSystem::ConvertAbsolutePathToRelative(data.DataOutputPath, file);
|
||||||
|
if (name.EndsWith(TEXT(".dylib")))
|
||||||
|
{
|
||||||
|
String frameworkId = Guid::New().ToString(Guid::FormatType::N).Left(24);
|
||||||
|
String frameworkEmbedId = Guid::New().ToString(Guid::FormatType::N).Left(24);
|
||||||
|
configReplaceMap[TEXT("${PBXBuildFile}")] += String::Format(TEXT("\t\t{0} /* {1} in Frameworks */ = {{isa = PBXBuildFile; fileRef = {2} /* {1} */; }};\n"), frameworkId, name, fileId);
|
||||||
|
configReplaceMap[TEXT("${PBXBuildFile}")] += String::Format(TEXT("\t\t{0} /* {1} in Embed Frameworks */ = {{isa = PBXBuildFile; fileRef = {2} /* {1} */; settings = {{ATTRIBUTES = (CodeSignOnCopy, ); }}; }};\n"), frameworkEmbedId, name, fileId);
|
||||||
|
configReplaceMap[TEXT("${PBXCopyFilesBuildPhaseFiles}")] += String::Format(TEXT("\t\t\t\t{0} /* {1} in Embed Frameworks */,\n"), frameworkEmbedId, name);
|
||||||
|
configReplaceMap[TEXT("${PBXFileReference}")] += String::Format(TEXT("\t\t{0} /* {1} */ = {{isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = \"{1}\"; path = \"FlaxGame/Data/{2}\"; sourceTree = \"<group>\"; }};\n"), fileId, name, projectPath);
|
||||||
|
configReplaceMap[TEXT("${PBXFrameworksBuildPhase}")] += String::Format(TEXT("\t\t\t\t{0} /* {1} in Frameworks */,\n"), frameworkId, name);
|
||||||
|
configReplaceMap[TEXT("${PBXFrameworksGroup}")] += String::Format(TEXT("\t\t\t\t{0} /* {1} */,\n"), fileId, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String fileRefId = Guid::New().ToString(Guid::FormatType::N).Left(24);
|
||||||
|
configReplaceMap[TEXT("${PBXBuildFile}")] += String::Format(TEXT("\t\t{0} /* {1} in Resources */ = {{isa = PBXBuildFile; fileRef = {2} /* {1} */; }};\n"), fileRefId, name, fileId);
|
||||||
|
configReplaceMap[TEXT("${PBXFileReference}")] += String::Format(TEXT("\t\t{0} /* {1} */ = {{isa = PBXFileReference; lastKnownFileType = file; name = \"{1}\"; path = \"Data/{2}\"; sourceTree = \"<group>\"; }};\n"), fileId, name, projectPath);
|
||||||
|
configReplaceMap[TEXT("${PBXFilesGroup}")] += String::Format(TEXT("\t\t\t\t{0} /* {1} */,\n"), fileId, name);
|
||||||
|
configReplaceMap[TEXT("${PBXResourcesGroup}")] += String::Format(TEXT("\t\t\t\t{0} /* {1} in Resources */,\n"), fileRefId, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool failed = false;
|
||||||
|
failed |= EditorUtilities::ReplaceInFile(data.OriginalOutputPath / TEXT("FlaxGame.xcodeproj/project.pbxproj"), configReplaceMap);
|
||||||
|
failed |= EditorUtilities::ReplaceInFile(data.OriginalOutputPath / TEXT("ExportOptions.plist"), configReplaceMap);
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
LOG(Error, "Failed to format XCode project");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export images
|
||||||
|
// TODO: provide per-device icons (eg. iPad 1x, iPad 2x) instead of a single icon size
|
||||||
|
TextureData iconData;
|
||||||
|
if (!EditorUtilities::GetApplicationImage(platformSettings->OverrideIcon, iconData))
|
||||||
|
{
|
||||||
|
String outputPath = data.OriginalOutputPath / TEXT("FlaxGame/Assets.xcassets/AppIcon.appiconset/ios_store_icon.png");
|
||||||
|
if (EditorUtilities::ExportApplicationImage(iconData, 1024, 1024, PixelFormat::R8G8B8A8_UNorm, outputPath))
|
||||||
|
{
|
||||||
|
LOG(Error, "Failed to export application icon.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package application
|
||||||
|
const auto buildSettings = BuildSettings::Get();
|
||||||
|
if (buildSettings->SkipPackaging)
|
||||||
|
return false;
|
||||||
|
GameCooker::PackageFiles();
|
||||||
|
{
|
||||||
|
LOG(Info, "Building app package...");
|
||||||
|
const Char* configuration = data.Configuration == BuildConfiguration::Release ? TEXT("Release") : TEXT("Debug");
|
||||||
|
String command = String::Format(TEXT("xcodebuild -project FlaxGame.xcodeproj -configuration {} -scheme FlaxGame -archivePath FlaxGame.xcarchive archive"), configuration);
|
||||||
|
int32 result = Platform::RunProcess(command, data.OriginalOutputPath);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
command = TEXT("xcodebuild -exportArchive -archivePath FlaxGame.xcarchive -allowProvisioningUpdates -exportPath . -exportOptionsPlist ExportOptions.plist");
|
||||||
|
result = Platform::RunProcess(command, data.OriginalOutputPath);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const String ipaPath = data.OriginalOutputPath / TEXT("FlaxGame.ipa");
|
||||||
|
LOG(Info, "Output application package: {0} (size: {1} MB)", ipaPath, FileSystem::GetFileSize(ipaPath) / 1024 / 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if PLATFORM_TOOLS_IOS
|
||||||
|
|
||||||
|
#include "../../PlatformTools.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The iOS platform support tools.
|
||||||
|
/// </summary>
|
||||||
|
class iOSPlatformTools : public PlatformTools
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// [PlatformTools]
|
||||||
|
const Char* GetDisplayName() const override;
|
||||||
|
const Char* GetName() const override;
|
||||||
|
PlatformType GetPlatform() const override;
|
||||||
|
ArchitectureType GetArchitecture() const override;
|
||||||
|
DotNetAOTModes UseAOT() const override;
|
||||||
|
PixelFormat GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format) override;
|
||||||
|
bool IsNativeCodeFile(CookingData& data, const String& file) override;
|
||||||
|
void OnBuildStarted(CookingData& data) override;
|
||||||
|
bool OnPostProcess(CookingData& data) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CookingData.h"
|
#include "CookingData.h"
|
||||||
#include "Engine/Core/Collections/Dictionary.h"
|
|
||||||
#include "Editor/Scripting/ScriptsBuilder.h"
|
#include "Editor/Scripting/ScriptsBuilder.h"
|
||||||
#include "Engine/Graphics/PixelFormat.h"
|
#include "Engine/Graphics/PixelFormat.h"
|
||||||
|
|
||||||
@@ -15,7 +14,6 @@ class TextureBase;
|
|||||||
class FLAXENGINE_API PlatformTools
|
class FLAXENGINE_API PlatformTools
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finalizes an instance of the <see cref="PlatformTools"/> class.
|
/// Finalizes an instance of the <see cref="PlatformTools"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -24,32 +22,35 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name of the platform for UI and logging.
|
/// Gets the name of the platform for UI and logging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The name.</returns>
|
|
||||||
virtual const Char* GetDisplayName() const = 0;
|
virtual const Char* GetDisplayName() const = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name of the platform for filesystem cache directories, deps folder.
|
/// Gets the name of the platform for filesystem cache directories, deps folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The name.</returns>
|
|
||||||
virtual const Char* GetName() const = 0;
|
virtual const Char* GetName() const = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of the platform.
|
/// Gets the type of the platform.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The platform type.</returns>
|
|
||||||
virtual PlatformType GetPlatform() const = 0;
|
virtual PlatformType GetPlatform() const = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the architecture of the platform.
|
/// Gets the architecture of the platform.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The architecture type.</returns>
|
|
||||||
virtual ArchitectureType GetArchitecture() const = 0;
|
virtual ArchitectureType GetArchitecture() const = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the value indicating whenever platform requires AOT.
|
/// Gets the value indicating whenever platform requires AOT (needs C# assemblies to be precompiled).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if platform uses AOT and needs C# assemblies to be precompiled, otherwise false.</returns>
|
virtual DotNetAOTModes UseAOT() const
|
||||||
virtual bool UseAOT() const
|
{
|
||||||
|
return DotNetAOTModes::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value indicating whenever platform supports using system-installed .Net Runtime.
|
||||||
|
/// </summary>
|
||||||
|
virtual bool UseSystemDotnet() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -72,13 +73,9 @@ public:
|
|||||||
/// <param name="data">The cooking data.</param>
|
/// <param name="data">The cooking data.</param>
|
||||||
/// <param name="file">The file path.</param>
|
/// <param name="file">The file path.</param>
|
||||||
/// <returns>True if it's a native file, otherwise false.<returns>
|
/// <returns>True if it's a native file, otherwise false.<returns>
|
||||||
virtual bool IsNativeCodeFile(CookingData& data, const String& file)
|
virtual bool IsNativeCodeFile(CookingData& data, const String& file);
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when game building starts.
|
/// Called when game building starts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -136,64 +133,6 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The C# scripts AOT configuration options.
|
|
||||||
/// </summary>
|
|
||||||
struct AotConfig
|
|
||||||
{
|
|
||||||
String AotCompilerPath;
|
|
||||||
String AotCompilerArgs;
|
|
||||||
String AssemblerPath;
|
|
||||||
String AssemblerArgs;
|
|
||||||
String ArchiverPath;
|
|
||||||
String ArchiverArgs;
|
|
||||||
String AuxToolPath;
|
|
||||||
String AuxToolArgs;
|
|
||||||
String AotCachePath;
|
|
||||||
Dictionary<String, String> EnvVars;
|
|
||||||
Array<String> AssembliesSearchDirs;
|
|
||||||
Array<String> Assemblies;
|
|
||||||
|
|
||||||
AotConfig(CookingData& data)
|
|
||||||
{
|
|
||||||
Platform::GetEnvironmentVariables(EnvVars);
|
|
||||||
EnvVars[TEXT("MONO_PATH")] = data.DataOutputPath / TEXT("Mono/lib/mono/4.5");
|
|
||||||
AssembliesSearchDirs.Add(data.DataOutputPath / TEXT("Mono/lib/mono/4.5"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called to configure AOT options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The cooking data.</param>
|
|
||||||
/// <param name="config">The configuration.</param>
|
|
||||||
virtual void OnConfigureAOT(CookingData& data, AotConfig& config)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called to execute AOT for the given assembly.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The cooking data.</param>
|
|
||||||
/// <param name="config">The configuration.</param>
|
|
||||||
/// <param name="assemblyPath">The input managed library file path.</param>
|
|
||||||
/// <returns>True if failed, otherwise false.<returns>
|
|
||||||
virtual bool OnPerformAOT(CookingData& data, AotConfig& config, const String& assemblyPath)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called after AOT execution for the assemblies.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The cooking data.</param>
|
|
||||||
/// <param name="config">The configuration.</param>
|
|
||||||
/// <returns>True if failed, otherwise false.<returns>
|
|
||||||
virtual bool OnPostProcessAOT(CookingData& data, AotConfig& config)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called during staged build post-processing.
|
/// Called during staged build post-processing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
|
|||||||
Scripting::ProcessBuildInfoPath(e.NativePath, projectFolderPath);
|
Scripting::ProcessBuildInfoPath(e.NativePath, projectFolderPath);
|
||||||
Scripting::ProcessBuildInfoPath(e.ManagedPath, projectFolderPath);
|
Scripting::ProcessBuildInfoPath(e.ManagedPath, projectFolderPath);
|
||||||
|
|
||||||
e.NativePath = StringUtils::GetFileName(e.NativePath);
|
e.NativePath = String(StringUtils::GetFileName(e.NativePath));
|
||||||
e.ManagedPath = StringUtils::GetFileName(e.ManagedPath);
|
e.ManagedPath = String(StringUtils::GetFileName(e.ManagedPath));
|
||||||
|
|
||||||
LOG(Info, "Collecting binary module {0}", e.Name);
|
LOG(Info, "Collecting binary module {0}", e.Name);
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
|
|||||||
continue;
|
continue;
|
||||||
if (FileSystem::CopyFile(dst, file))
|
if (FileSystem::CopyFile(dst, file))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to copy file from {0} to {1}."), file, dst);
|
data.Error(String::Format(TEXT("Failed to copy file from {0} to {1}."), file, dst));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,60 +154,7 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
|||||||
String target = project->GameTarget;
|
String target = project->GameTarget;
|
||||||
StringView workingDir;
|
StringView workingDir;
|
||||||
const Char *platform, *architecture, *configuration = ::ToString(data.Configuration);
|
const Char *platform, *architecture, *configuration = ::ToString(data.Configuration);
|
||||||
switch (data.Platform)
|
data.GetBuildPlatformName(platform, architecture);
|
||||||
{
|
|
||||||
case BuildPlatform::Windows32:
|
|
||||||
platform = TEXT("Windows");
|
|
||||||
architecture = TEXT("x86");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::Windows64:
|
|
||||||
platform = TEXT("Windows");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::UWPx86:
|
|
||||||
platform = TEXT("UWP");
|
|
||||||
architecture = TEXT("x86");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::UWPx64:
|
|
||||||
platform = TEXT("UWP");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::XboxOne:
|
|
||||||
platform = TEXT("XboxOne");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::LinuxX64:
|
|
||||||
platform = TEXT("Linux");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::PS4:
|
|
||||||
platform = TEXT("PS4");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::XboxScarlett:
|
|
||||||
platform = TEXT("XboxScarlett");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::AndroidARM64:
|
|
||||||
platform = TEXT("Android");
|
|
||||||
architecture = TEXT("ARM64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::Switch:
|
|
||||||
platform = TEXT("Switch");
|
|
||||||
architecture = TEXT("ARM64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::PS5:
|
|
||||||
platform = TEXT("PS5");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
case BuildPlatform::MacOSx64:
|
|
||||||
platform = TEXT("Mac");
|
|
||||||
architecture = TEXT("x64");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG(Error, "Unknown or unsupported build platform.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
String targetBuildInfo = project->ProjectFolderPath / TEXT("Binaries") / target / platform / architecture / configuration / target + TEXT(".Build.json");
|
String targetBuildInfo = project->ProjectFolderPath / TEXT("Binaries") / target / platform / architecture / configuration / target + TEXT(".Build.json");
|
||||||
if (target.IsEmpty())
|
if (target.IsEmpty())
|
||||||
{
|
{
|
||||||
@@ -241,8 +188,8 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
|||||||
LOG(Info, "Starting scripts compilation for game...");
|
LOG(Info, "Starting scripts compilation for game...");
|
||||||
const String logFile = data.CacheDirectory / TEXT("CompileLog.txt");
|
const String logFile = data.CacheDirectory / TEXT("CompileLog.txt");
|
||||||
auto args = String::Format(
|
auto args = String::Format(
|
||||||
TEXT("-log -logfile=\"{4}\" -build -mutex -buildtargets={0} -platform={1} -arch={2} -configuration={3}"),
|
TEXT("-log -logfile=\"{4}\" -build -mutex -buildtargets={0} -platform={1} -arch={2} -configuration={3} -aotMode={5}"),
|
||||||
target, platform, architecture, configuration, logFile);
|
target, platform, architecture, configuration, logFile, ToString(data.Tools->UseAOT()));
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
if (data.Platform == BuildPlatform::LinuxX64)
|
if (data.Platform == BuildPlatform::LinuxX64)
|
||||||
#elif PLATFORM_LINUX
|
#elif PLATFORM_LINUX
|
||||||
@@ -257,7 +204,7 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
|||||||
// Assume FlaxGame was prebuilt for target platform
|
// Assume FlaxGame was prebuilt for target platform
|
||||||
args += TEXT(" -SkipTargets=FlaxGame");
|
args += TEXT(" -SkipTargets=FlaxGame");
|
||||||
}
|
}
|
||||||
for (auto& define : data.CustomDefines)
|
for (const String& define : data.CustomDefines)
|
||||||
{
|
{
|
||||||
args += TEXT(" -D");
|
args += TEXT(" -D");
|
||||||
args += define;
|
args += define;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "Engine/Engine/Base/GameBase.h"
|
#include "Engine/Engine/Base/GameBase.h"
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Engine/Engine/Globals.h"
|
||||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||||
|
#include "Engine/Scripting/Enums.h"
|
||||||
#if PLATFORM_TOOLS_WINDOWS
|
#if PLATFORM_TOOLS_WINDOWS
|
||||||
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
|
#include "Engine/Platform/Windows/WindowsPlatformSettings.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -327,8 +328,8 @@ bool CookAssetsStep::ProcessDefaultAsset(AssetCookData& options)
|
|||||||
{
|
{
|
||||||
// Use compact json
|
// Use compact json
|
||||||
rapidjson_flax::StringBuffer buffer;
|
rapidjson_flax::StringBuffer buffer;
|
||||||
rapidjson_flax::Writer<rapidjson_flax::StringBuffer> writer(buffer);
|
CompactJsonWriter writerObj(buffer);
|
||||||
asJsonAsset->Document.Accept(writer);
|
asJsonAsset->Save(writerObj);
|
||||||
|
|
||||||
// Store json data in the first chunk
|
// Store json data in the first chunk
|
||||||
auto chunk = New<FlaxChunk>();
|
auto chunk = New<FlaxChunk>();
|
||||||
@@ -409,7 +410,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
|||||||
assetBase->InitCompilationOptions(options); \
|
assetBase->InitCompilationOptions(options); \
|
||||||
if (ShadersCompilation::Compile(options)) \
|
if (ShadersCompilation::Compile(options)) \
|
||||||
{ \
|
{ \
|
||||||
data.Data.Error(TEXT("Failed to compile shader '{0}' (profile: {1})."), asset->ToString(), ::ToString(options.Profile)); \
|
data.Data.Error(String::Format(TEXT("Failed to compile shader '{0}' (profile: {1})."), asset->ToString(), ::ToString(options.Profile))); \
|
||||||
return true; \
|
return true; \
|
||||||
} \
|
} \
|
||||||
includes.Clear(); \
|
includes.Clear(); \
|
||||||
@@ -528,11 +529,20 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
|||||||
#endif
|
#endif
|
||||||
#if PLATFORM_TOOLS_MAC
|
#if PLATFORM_TOOLS_MAC
|
||||||
case BuildPlatform::MacOSx64:
|
case BuildPlatform::MacOSx64:
|
||||||
|
case BuildPlatform::MacOSARM64:
|
||||||
{
|
{
|
||||||
const char* platformDefineName = "PLATFORM_MAC";
|
const char* platformDefineName = "PLATFORM_MAC";
|
||||||
COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
|
COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if PLATFORM_TOOLS_IOS
|
||||||
|
case BuildPlatform::iOSARM64:
|
||||||
|
{
|
||||||
|
const char* platformDefineName = "PLATFORM_IOS";
|
||||||
|
COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -647,7 +657,7 @@ bool ProcessTextureBase(CookAssetsStep::AssetCookData& data)
|
|||||||
// Convert texture data to the target format
|
// Convert texture data to the target format
|
||||||
if (TextureTool::Convert(textureDataTmp1, *textureData, targetFormat))
|
if (TextureTool::Convert(textureDataTmp1, *textureData, targetFormat))
|
||||||
{
|
{
|
||||||
LOG(Error, "Failed to convert texture {0} from format {1} to {2}", asset->ToString(), (int32)format, (int32)targetFormat);
|
LOG(Error, "Failed to convert texture {0} from format {1} to {2}", asset->ToString(), ScriptingEnum::ToString(format), ScriptingEnum::ToString(targetFormat));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
textureData = &textureDataTmp1;
|
textureData = &textureDataTmp1;
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "DeployDataStep.h"
|
#include "DeployDataStep.h"
|
||||||
|
#include "Engine/Platform/File.h"
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
#include "Editor/Cooker/PlatformTools.h"
|
#include "Engine/Core/Collections/Sorting.h"
|
||||||
#include "Engine/Core/Config/BuildSettings.h"
|
#include "Engine/Core/Config/BuildSettings.h"
|
||||||
#include "Engine/Core/Config/GameSettings.h"
|
#include "Engine/Core/Config/GameSettings.h"
|
||||||
#include "Engine/Renderer/ReflectionsPass.h"
|
#include "Engine/Renderer/ReflectionsPass.h"
|
||||||
#include "Engine/Renderer/AntiAliasing/SMAA.h"
|
#include "Engine/Renderer/AntiAliasing/SMAA.h"
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Engine/Engine/Globals.h"
|
||||||
|
#include "Editor/Cooker/PlatformTools.h"
|
||||||
|
#include "Editor/Utilities/EditorUtilities.h"
|
||||||
|
|
||||||
bool DeployDataStep::Perform(CookingData& data)
|
bool DeployDataStep::Perform(CookingData& data)
|
||||||
{
|
{
|
||||||
data.StepProgress(TEXT("Deploying engine data"), 0);
|
data.StepProgress(TEXT("Deploying engine data"), 0);
|
||||||
const String depsRoot = data.GetPlatformBinariesRoot();
|
const String depsRoot = data.GetPlatformBinariesRoot();
|
||||||
const auto gameSettings = GameSettings::Get();
|
const auto& gameSettings = *GameSettings::Get();
|
||||||
|
const auto& buildSettings = *BuildSettings::Get();
|
||||||
|
|
||||||
// Setup output folders and copy required data
|
// Setup output folders and copy required data
|
||||||
const auto contentDir = data.DataOutputPath / TEXT("Content");
|
const auto contentDir = data.DataOutputPath / TEXT("Content");
|
||||||
@@ -26,22 +30,275 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
Platform::Sleep(10);
|
Platform::Sleep(10);
|
||||||
}
|
}
|
||||||
FileSystem::CreateDirectory(contentDir);
|
FileSystem::CreateDirectory(contentDir);
|
||||||
const auto srcMono = depsRoot / TEXT("Mono");
|
const String dstMono = data.DataOutputPath / TEXT("Mono");
|
||||||
const auto dstMono = data.DataOutputPath / TEXT("Mono");
|
#if USE_NETCORE
|
||||||
|
{
|
||||||
|
// Remove old Mono files
|
||||||
|
FileSystem::DeleteDirectory(dstMono);
|
||||||
|
FileSystem::DeleteFile(data.DataOutputPath / TEXT("MonoPosixHelper.dll"));
|
||||||
|
}
|
||||||
|
String dstDotnet = data.DataOutputPath / TEXT("Dotnet");
|
||||||
|
const DotNetAOTModes aotMode = data.Tools->UseAOT();
|
||||||
|
const bool usAOT = aotMode != DotNetAOTModes::None;
|
||||||
|
if (usAOT)
|
||||||
|
{
|
||||||
|
// Deploy Dotnet files into intermediate cooking directory for AOT
|
||||||
|
FileSystem::DeleteDirectory(dstDotnet);
|
||||||
|
dstDotnet = data.ManagedCodeOutputPath;
|
||||||
|
}
|
||||||
|
if (buildSettings.SkipDotnetPackaging && data.Tools->UseSystemDotnet())
|
||||||
|
{
|
||||||
|
// Use system-installed .Net Runtime
|
||||||
|
FileSystem::DeleteDirectory(dstDotnet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Deploy .Net Runtime files
|
||||||
|
FileSystem::CreateDirectory(dstDotnet);
|
||||||
|
String srcDotnet = depsRoot / TEXT("Dotnet");
|
||||||
|
if (FileSystem::DirectoryExists(srcDotnet))
|
||||||
|
{
|
||||||
|
// Use prebuilt .Net installation for that platform
|
||||||
|
LOG(Info, "Using .Net Runtime {} at {}", data.Tools->GetName(), srcDotnet);
|
||||||
|
if (EditorUtilities::CopyDirectoryIfNewer(dstDotnet, srcDotnet, true))
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to copy .Net runtime data files."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool canUseSystemDotnet = false;
|
||||||
|
switch (data.Platform)
|
||||||
|
{
|
||||||
|
case BuildPlatform::Windows32:
|
||||||
|
case BuildPlatform::Windows64:
|
||||||
|
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Windows;
|
||||||
|
break;
|
||||||
|
case BuildPlatform::LinuxX64:
|
||||||
|
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Linux;
|
||||||
|
break;
|
||||||
|
case BuildPlatform::MacOSx64:
|
||||||
|
case BuildPlatform::MacOSARM64:
|
||||||
|
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Mac;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (canUseSystemDotnet && (aotMode == DotNetAOTModes::None || aotMode == DotNetAOTModes::ILC))
|
||||||
|
{
|
||||||
|
// Ask Flax.Build to provide .Net SDK location for the current platform
|
||||||
|
String sdks;
|
||||||
|
bool failed = ScriptsBuilder::RunBuildTool(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs"), data.CacheDirectory);
|
||||||
|
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
|
||||||
|
int32 idx = sdks.Find(TEXT("DotNetSdk, "), StringSearchCase::CaseSensitive);
|
||||||
|
if (idx != -1)
|
||||||
|
{
|
||||||
|
idx = sdks.Find(TEXT(", "), StringSearchCase::CaseSensitive, idx + 12);
|
||||||
|
idx += 2;
|
||||||
|
int32 end = sdks.Find(TEXT("\n"), StringSearchCase::CaseSensitive, idx);
|
||||||
|
if (sdks[end] == '\r')
|
||||||
|
end--;
|
||||||
|
srcDotnet = String(sdks.Get() + idx, end - idx).TrimTrailing();
|
||||||
|
}
|
||||||
|
if (failed || !FileSystem::DirectoryExists(srcDotnet))
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to get .Net SDK location for a current platform."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select version to use
|
||||||
|
Array<String> versions;
|
||||||
|
FileSystem::GetChildDirectories(versions, srcDotnet / TEXT("host/fxr"));
|
||||||
|
if (versions.Count() == 0)
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to get .Net SDK location for a current platform."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (String& version : versions)
|
||||||
|
{
|
||||||
|
version = String(StringUtils::GetFileName(version));
|
||||||
|
if (!version.StartsWith(TEXT("7.")))
|
||||||
|
version.Clear();
|
||||||
|
}
|
||||||
|
Sorting::QuickSort(versions.Get(), versions.Count());
|
||||||
|
const String version = versions.Last();
|
||||||
|
FileSystem::NormalizePath(srcDotnet);
|
||||||
|
LOG(Info, "Using .Net Runtime {} at {}", version, srcDotnet);
|
||||||
|
|
||||||
|
// Check if previously deployed files are valid (eg. system-installed .NET was updated from version 7.0.3 to 7.0.5)
|
||||||
|
{
|
||||||
|
const String dotnetCacheFilePath = data.CacheDirectory / TEXT("SystemDotnetInfo.txt");
|
||||||
|
String dotnetCachedValue = String::Format(TEXT("{};{}"), version, srcDotnet);
|
||||||
|
if (FileSystem::DirectoryExists(dstDotnet))
|
||||||
|
{
|
||||||
|
String cachedData;
|
||||||
|
File::ReadAllText(dotnetCacheFilePath, cachedData);
|
||||||
|
if (cachedData != dotnetCachedValue)
|
||||||
|
{
|
||||||
|
FileSystem::DeleteDirectory(dstDotnet);
|
||||||
|
FileSystem::CreateDirectory(dstDotnet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File::WriteAllText(dotnetCacheFilePath, dotnetCachedValue, Encoding::ANSI);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deploy runtime files
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("LICENSE.TXT"), srcDotnet / TEXT("LICENSE.txt"));
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("LICENSE.TXT"), srcDotnet / TEXT("LICENSE.TXT"));
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("THIRD-PARTY-NOTICES.TXT"), srcDotnet / TEXT("ThirdPartyNotices.txt"));
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("THIRD-PARTY-NOTICES.TXT"), srcDotnet / TEXT("THIRD-PARTY-NOTICES.TXT"));
|
||||||
|
if (usAOT)
|
||||||
|
{
|
||||||
|
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("host/fxr") / version, srcDotnet / TEXT("host/fxr") / version, true);
|
||||||
|
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("shared/Microsoft.NETCore.App") / version, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version, true);
|
||||||
|
}
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to copy .Net runtime data files."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ask Flax.Build to provide .Net Host Runtime location for the target platform
|
||||||
|
String sdks;
|
||||||
|
const Char *platformName, *archName;
|
||||||
|
data.GetBuildPlatformName(platformName, archName);
|
||||||
|
String args = String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printDotNetRuntime -platform={} -arch={}"), platformName, archName);
|
||||||
|
bool failed = ScriptsBuilder::RunBuildTool(args, data.CacheDirectory);
|
||||||
|
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
|
||||||
|
Array<String> parts;
|
||||||
|
sdks.Split(',', parts);
|
||||||
|
failed |= parts.Count() != 3;
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
srcDotnet = parts[2].TrimTrailing();
|
||||||
|
}
|
||||||
|
if (failed || !FileSystem::DirectoryExists(srcDotnet))
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to get .Net SDK location for a current platform."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
FileSystem::NormalizePath(srcDotnet);
|
||||||
|
LOG(Info, "Using .Net Runtime {} at {}", TEXT("Host"), srcDotnet);
|
||||||
|
|
||||||
|
// Deploy runtime files
|
||||||
|
const Char* corlibPrivateName = TEXT("System.Private.CoreLib.dll");
|
||||||
|
const bool srcDotnetFromEngine = srcDotnet.Contains(TEXT("Source/Platforms"));
|
||||||
|
String packFolder = srcDotnet / TEXT("../../../");
|
||||||
|
String dstDotnetLibs = dstDotnet, srcDotnetLibs = srcDotnet;
|
||||||
|
StringUtils::PathRemoveRelativeParts(packFolder);
|
||||||
|
if (usAOT)
|
||||||
|
{
|
||||||
|
if (srcDotnetFromEngine)
|
||||||
|
{
|
||||||
|
// AOT runtime files inside Engine Platform folder
|
||||||
|
packFolder /= TEXT("Dotnet");
|
||||||
|
dstDotnetLibs /= TEXT("lib/net7.0");
|
||||||
|
srcDotnetLibs = packFolder / TEXT("lib/net7.0");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Runtime files inside Dotnet SDK folder but placed for AOT
|
||||||
|
dstDotnetLibs /= TEXT("lib/net7.0");
|
||||||
|
srcDotnetLibs /= TEXT("../lib/net7.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (srcDotnetFromEngine)
|
||||||
|
{
|
||||||
|
// Runtime files inside Engine Platform folder
|
||||||
|
dstDotnetLibs /= TEXT("lib/net7.0");
|
||||||
|
srcDotnetLibs /= TEXT("lib/net7.0");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Runtime files inside Dotnet SDK folder
|
||||||
|
dstDotnetLibs /= TEXT("shared/Microsoft.NETCore.App");
|
||||||
|
srcDotnetLibs /= TEXT("../lib/net7.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("LICENSE.TXT"), packFolder / TEXT("LICENSE.txt"));
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("LICENSE.TXT"), packFolder / TEXT("LICENSE.TXT"));
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("THIRD-PARTY-NOTICES.TXT"), packFolder / TEXT("ThirdPartyNotices.txt"));
|
||||||
|
FileSystem::CopyFile(dstDotnet / TEXT("THIRD-PARTY-NOTICES.TXT"), packFolder / TEXT("THIRD-PARTY-NOTICES.TXT"));
|
||||||
|
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnetLibs, srcDotnetLibs, true);
|
||||||
|
if (FileSystem::FileExists(srcDotnet / corlibPrivateName))
|
||||||
|
failed |= EditorUtilities::CopyFileIfNewer(dstDotnetLibs / corlibPrivateName, srcDotnet / corlibPrivateName);
|
||||||
|
switch (data.Platform)
|
||||||
|
{
|
||||||
|
#define DEPLOY_NATIVE_FILE(filename) failed |= FileSystem::CopyFile(data.NativeCodeOutputPath / TEXT(filename), srcDotnet / TEXT(filename));
|
||||||
|
case BuildPlatform::AndroidARM64:
|
||||||
|
if (data.Configuration != BuildConfiguration::Release)
|
||||||
|
{
|
||||||
|
DEPLOY_NATIVE_FILE("libmono-component-debugger.so");
|
||||||
|
DEPLOY_NATIVE_FILE("libmono-component-diagnostics_tracing.so");
|
||||||
|
DEPLOY_NATIVE_FILE("libmono-component-hot_reload.so");
|
||||||
|
}
|
||||||
|
DEPLOY_NATIVE_FILE("libmonosgen-2.0.so");
|
||||||
|
DEPLOY_NATIVE_FILE("libSystem.IO.Compression.Native.so");
|
||||||
|
DEPLOY_NATIVE_FILE("libSystem.Native.so");
|
||||||
|
DEPLOY_NATIVE_FILE("libSystem.Security.Cryptography.Native.Android.so");
|
||||||
|
break;
|
||||||
|
case BuildPlatform::iOSARM64:
|
||||||
|
DEPLOY_NATIVE_FILE("libmonosgen-2.0.dylib");
|
||||||
|
DEPLOY_NATIVE_FILE("libSystem.IO.Compression.Native.dylib");
|
||||||
|
DEPLOY_NATIVE_FILE("libSystem.Native.dylib");
|
||||||
|
DEPLOY_NATIVE_FILE("libSystem.Net.Security.Native.dylib");
|
||||||
|
DEPLOY_NATIVE_FILE("libSystem.Security.Cryptography.Native.Apple.dylib");
|
||||||
|
break;
|
||||||
|
#undef DEPLOY_NATIVE_FILE
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to copy .Net runtime data files."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize deployed C# class library (remove DLLs unused by scripts)
|
||||||
|
if (aotMode == DotNetAOTModes::None && buildSettings.SkipUnusedDotnetLibsPackaging)
|
||||||
|
{
|
||||||
|
LOG(Info, "Optimizing .NET class library size to include only used assemblies");
|
||||||
|
const String logFile = data.CacheDirectory / TEXT("StripDotnetLibs.txt");
|
||||||
|
String args = String::Format(
|
||||||
|
TEXT("-log -logfile=\"{}\" -runDotNetClassLibStripping -mutex -binaries=\"{}\""),
|
||||||
|
logFile, data.DataOutputPath);
|
||||||
|
for (const String& define : data.CustomDefines)
|
||||||
|
{
|
||||||
|
args += TEXT(" -D");
|
||||||
|
args += define;
|
||||||
|
}
|
||||||
|
if (ScriptsBuilder::RunBuildTool(args))
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to optimize .Net class library."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!FileSystem::DirectoryExists(dstMono))
|
if (!FileSystem::DirectoryExists(dstMono))
|
||||||
{
|
{
|
||||||
|
// Deploy Mono files (from platform data folder)
|
||||||
|
const String srcMono = depsRoot / TEXT("Mono");
|
||||||
if (!FileSystem::DirectoryExists(srcMono))
|
if (!FileSystem::DirectoryExists(srcMono))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Missing Mono runtime data files."));
|
data.Error(TEXT("Missing Mono runtime data files."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileSystem::CopyDirectory(dstMono, srcMono, true))
|
if (FileSystem::CopyDirectory(dstMono, srcMono, true))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to copy Mono runtime data files."));
|
data.Error(TEXT("Failed to copy Mono runtime data files."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Deploy engine data for the target platform
|
// Deploy engine data for the target platform
|
||||||
if (data.Tools->OnDeployBinaries(data))
|
if (data.Tools->OnDeployBinaries(data))
|
||||||
@@ -82,7 +339,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
data.AddRootEngineAsset(TEXT("Engine/DefaultMaterial"));
|
data.AddRootEngineAsset(TEXT("Engine/DefaultMaterial"));
|
||||||
data.AddRootEngineAsset(TEXT("Engine/DefaultDeformableMaterial"));
|
data.AddRootEngineAsset(TEXT("Engine/DefaultDeformableMaterial"));
|
||||||
data.AddRootEngineAsset(TEXT("Engine/DefaultTerrainMaterial"));
|
data.AddRootEngineAsset(TEXT("Engine/DefaultTerrainMaterial"));
|
||||||
if (!gameSettings->NoSplashScreen && !gameSettings->SplashScreen.IsValid())
|
if (!gameSettings.NoSplashScreen && !gameSettings.SplashScreen.IsValid())
|
||||||
data.AddRootEngineAsset(TEXT("Engine/Textures/Logo"));
|
data.AddRootEngineAsset(TEXT("Engine/Textures/Logo"));
|
||||||
data.AddRootEngineAsset(TEXT("Engine/Textures/NormalTexture"));
|
data.AddRootEngineAsset(TEXT("Engine/Textures/NormalTexture"));
|
||||||
data.AddRootEngineAsset(TEXT("Engine/Textures/BlackTexture"));
|
data.AddRootEngineAsset(TEXT("Engine/Textures/BlackTexture"));
|
||||||
@@ -112,7 +369,6 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
|
|
||||||
// Register game assets
|
// Register game assets
|
||||||
data.StepProgress(TEXT("Deploying game data"), 50);
|
data.StepProgress(TEXT("Deploying game data"), 50);
|
||||||
auto& buildSettings = *BuildSettings::Get();
|
|
||||||
for (auto& e : buildSettings.AdditionalAssets)
|
for (auto& e : buildSettings.AdditionalAssets)
|
||||||
data.AddRootAsset(e.GetID());
|
data.AddRootAsset(e.GetID());
|
||||||
for (auto& e : buildSettings.AdditionalScenes)
|
for (auto& e : buildSettings.AdditionalScenes)
|
||||||
|
|||||||
@@ -2,9 +2,20 @@
|
|||||||
|
|
||||||
#include "PostProcessStep.h"
|
#include "PostProcessStep.h"
|
||||||
#include "Editor/Cooker/PlatformTools.h"
|
#include "Editor/Cooker/PlatformTools.h"
|
||||||
|
#include "Engine/Platform/FileSystem.h"
|
||||||
|
|
||||||
bool PostProcessStep::Perform(CookingData& data)
|
bool PostProcessStep::Perform(CookingData& data)
|
||||||
{
|
{
|
||||||
|
// Print .NET stats
|
||||||
|
const DotNetAOTModes aotMode = data.Tools->UseAOT();
|
||||||
|
uint64 outputSize = FileSystem::GetDirectorySize(data.DataOutputPath / TEXT("Dotnet"));
|
||||||
|
if (aotMode == DotNetAOTModes::None)
|
||||||
|
{
|
||||||
|
for (auto& binaryModule : data.BinaryModules)
|
||||||
|
outputSize += FileSystem::GetFileSize(data.DataOutputPath / binaryModule.ManagedPath);
|
||||||
|
}
|
||||||
|
LOG(Info, "Output .NET files size: {0} MB", (uint32)(outputSize / (1024ull * 1024)));
|
||||||
|
|
||||||
GameCooker::PostProcessFiles();
|
GameCooker::PostProcessFiles();
|
||||||
return data.Tools->OnPostProcess(data);
|
return data.Tools->OnPostProcess(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,78 +1,86 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "PrecompileAssembliesStep.h"
|
#include "PrecompileAssembliesStep.h"
|
||||||
#include "Editor/Scripting/ScriptsBuilder.h"
|
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
|
#include "Engine/Platform/File.h"
|
||||||
|
#include "Engine/Core/Config/BuildSettings.h"
|
||||||
|
#include "Engine/Engine/Globals.h"
|
||||||
|
#include "Editor/Scripting/ScriptsBuilder.h"
|
||||||
#include "Editor/Cooker/PlatformTools.h"
|
#include "Editor/Cooker/PlatformTools.h"
|
||||||
|
#include "Editor/Utilities/EditorUtilities.h"
|
||||||
|
|
||||||
|
void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
|
||||||
|
{
|
||||||
|
const DotNetAOTModes aotMode = data.Tools->UseAOT();
|
||||||
|
if (aotMode == DotNetAOTModes::None)
|
||||||
|
return;
|
||||||
|
const auto& buildSettings = *BuildSettings::Get();
|
||||||
|
|
||||||
|
// Redirect C# assemblies to intermediate cooking directory (processed by ILC)
|
||||||
|
data.ManagedCodeOutputPath = data.CacheDirectory / TEXT("AOTAssemblies");
|
||||||
|
|
||||||
|
// Reset any AOT cache from previous run if the AOT mode has changed (eg. Mono AOT -> ILC on Desktop)
|
||||||
|
const String aotModeCacheFilePath = data.ManagedCodeOutputPath / TEXT("AOTMode.txt");
|
||||||
|
String aotModeCacheValue = String::Format(TEXT("{};{};{};{}"),
|
||||||
|
(int32)aotMode,
|
||||||
|
(int32)data.Configuration,
|
||||||
|
(int32)buildSettings.SkipUnusedDotnetLibsPackaging,
|
||||||
|
FileSystem::GetFileLastEditTime(ScriptsBuilder::GetBuildToolPath()).Ticks);
|
||||||
|
for (const String& define : data.CustomDefines)
|
||||||
|
aotModeCacheValue += define;
|
||||||
|
if (FileSystem::DirectoryExists(data.ManagedCodeOutputPath))
|
||||||
|
{
|
||||||
|
String cachedData;
|
||||||
|
File::ReadAllText(aotModeCacheFilePath, cachedData);
|
||||||
|
if (cachedData != aotModeCacheValue)
|
||||||
|
{
|
||||||
|
LOG(Info, "AOT cache invalidation");
|
||||||
|
FileSystem::DeleteDirectory(data.ManagedCodeOutputPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!FileSystem::DirectoryExists(data.ManagedCodeOutputPath))
|
||||||
|
{
|
||||||
|
FileSystem::CreateDirectory(data.ManagedCodeOutputPath);
|
||||||
|
File::WriteAllText(aotModeCacheFilePath, aotModeCacheValue, Encoding::ANSI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool PrecompileAssembliesStep::Perform(CookingData& data)
|
bool PrecompileAssembliesStep::Perform(CookingData& data)
|
||||||
{
|
{
|
||||||
// Skip for some platforms
|
const DotNetAOTModes aotMode = data.Tools->UseAOT();
|
||||||
if (!data.Tools->UseAOT())
|
if (aotMode == DotNetAOTModes::None)
|
||||||
|
return false;
|
||||||
|
const auto& buildSettings = *BuildSettings::Get();
|
||||||
|
if (buildSettings.SkipDotnetPackaging && data.Tools->UseSystemDotnet())
|
||||||
return false;
|
return false;
|
||||||
LOG(Info, "Using AOT...");
|
LOG(Info, "Using AOT...");
|
||||||
|
|
||||||
// Useful references about AOT:
|
|
||||||
// http://www.mono-project.com/docs/advanced/runtime/docs/aot/
|
|
||||||
// http://www.mono-project.com/docs/advanced/aot/
|
|
||||||
|
|
||||||
const String infoMsg = TEXT("Running AOT");
|
const String infoMsg = TEXT("Running AOT");
|
||||||
data.StepProgress(infoMsg, 0);
|
data.StepProgress(infoMsg, 0);
|
||||||
|
|
||||||
// Setup
|
// Override Newtonsoft.Json with AOT-version (one that doesn't use System.Reflection.Emit)
|
||||||
PlatformTools::AotConfig config(data);
|
EditorUtilities::CopyFileIfNewer(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.dll"), Globals::StartupFolder / TEXT("Source/Platforms/DotNet/AOT/Newtonsoft.Json.dll"));
|
||||||
data.Tools->OnConfigureAOT(data, config);
|
FileSystem::DeleteFile(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.xml"));
|
||||||
|
FileSystem::DeleteFile(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.pdb"));
|
||||||
|
|
||||||
// Prepare output directory
|
// Run AOT by Flax.Build (see DotNetAOT)
|
||||||
config.AotCachePath = data.DataOutputPath / TEXT("Mono/lib/mono/aot-cache");
|
const Char *platform, *architecture, *configuration = ::ToString(data.Configuration);
|
||||||
switch (data.Tools->GetArchitecture())
|
data.GetBuildPlatformName(platform, architecture);
|
||||||
|
const String logFile = data.CacheDirectory / TEXT("AOTLog.txt");
|
||||||
|
String args = String::Format(
|
||||||
|
TEXT("-log -logfile=\"{}\" -runDotNetAOT -mutex -platform={} -arch={} -configuration={} -aotMode={} -binaries=\"{}\" -intermediate=\"{}\""),
|
||||||
|
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath);
|
||||||
|
if (!buildSettings.SkipUnusedDotnetLibsPackaging)
|
||||||
|
args += TEXT(" -skipUnusedDotnetLibs=false"); // Run AOT on whole class library (not just used libs)
|
||||||
|
for (const String& define : data.CustomDefines)
|
||||||
{
|
{
|
||||||
case ArchitectureType::x86:
|
args += TEXT(" -D");
|
||||||
config.AotCachePath /= TEXT("x86");
|
args += define;
|
||||||
break;
|
}
|
||||||
case ArchitectureType::x64:
|
if (ScriptsBuilder::RunBuildTool(args))
|
||||||
config.AotCachePath /= TEXT("amd64");
|
{
|
||||||
break;
|
data.Error(TEXT("Failed to precompile game scripts."));
|
||||||
default:
|
|
||||||
data.Error(TEXT("Not supported AOT architecture"));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!FileSystem::DirectoryExists(config.AotCachePath))
|
|
||||||
{
|
|
||||||
if (FileSystem::CreateDirectory(config.AotCachePath))
|
|
||||||
{
|
|
||||||
data.Error(TEXT("Failed to setup AOT output directory."));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect assemblies for AOT
|
|
||||||
// TODO: don't perform AOT on all assemblies but only ones used by the game and engine assemblies
|
|
||||||
for (auto& dir : config.AssembliesSearchDirs)
|
|
||||||
FileSystem::DirectoryGetFiles(config.Assemblies, dir, TEXT("*.dll"), DirectorySearchOption::TopDirectoryOnly);
|
|
||||||
for (auto& binaryModule : data.BinaryModules)
|
|
||||||
if (binaryModule.ManagedPath.HasChars())
|
|
||||||
config.Assemblies.Add(data.ManagedCodeOutputPath / binaryModule.ManagedPath);
|
|
||||||
// TODO: move AOT to Flax.Build and perform it on all C# assemblies used in target build
|
|
||||||
config.Assemblies.Add(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.dll"));
|
|
||||||
|
|
||||||
// Perform AOT for the assemblies
|
|
||||||
for (int32 i = 0; i < config.Assemblies.Count(); i++)
|
|
||||||
{
|
|
||||||
BUILD_STEP_CANCEL_CHECK;
|
|
||||||
|
|
||||||
if (data.Tools->OnPerformAOT(data, config, config.Assemblies[i]))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
data.StepProgress(infoMsg, static_cast<float>(i) / config.Assemblies.Count());
|
|
||||||
}
|
|
||||||
|
|
||||||
BUILD_STEP_CANCEL_CHECK;
|
|
||||||
|
|
||||||
if (data.Tools->OnPostProcessAOT(data, config))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// TODO: maybe remove GAC/assemblies? aot-cache could be only used in the build game
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
#include "Editor/Cooker/GameCooker.h"
|
#include "Editor/Cooker/GameCooker.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optional step used only on selected platform that precompiles C# script assemblies.
|
/// Optional step used only on selected platform that precompiles C# script assemblies. Uses Ahead of Time Compilation (AOT) feature.
|
||||||
/// Uses Mono Ahead of Time Compilation (AOT) feature.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="GameCooker::BuildStep" />
|
/// <seealso cref="GameCooker::BuildStep" />
|
||||||
class PrecompileAssembliesStep : public GameCooker::BuildStep
|
class PrecompileAssembliesStep : public GameCooker::BuildStep
|
||||||
@@ -14,5 +13,6 @@ class PrecompileAssembliesStep : public GameCooker::BuildStep
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// [BuildStep]
|
// [BuildStep]
|
||||||
|
void OnBuildStarted(CookingData& data) override;
|
||||||
bool Perform(CookingData& data) override;
|
bool Perform(CookingData& data) override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
using FlaxEditor.CustomEditors;
|
using FlaxEditor.CustomEditors;
|
||||||
using FlaxEditor.Windows;
|
using FlaxEditor.Windows;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine;
|
|
||||||
using DockState = FlaxEditor.GUI.Docking.DockState;
|
using DockState = FlaxEditor.GUI.Docking.DockState;
|
||||||
|
|
||||||
namespace FlaxEditor
|
namespace FlaxEditor
|
||||||
@@ -86,8 +85,12 @@ namespace FlaxEditor
|
|||||||
if (!FlaxEngine.Scripting.IsTypeFromGameScripts(type))
|
if (!FlaxEngine.Scripting.IsTypeFromGameScripts(type))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Editor.Instance.Windows.AddToRestore(this);
|
if (!Window.IsHidden)
|
||||||
|
{
|
||||||
|
Editor.Instance.Windows.AddToRestore(this);
|
||||||
|
}
|
||||||
Window.Close();
|
Window.Close();
|
||||||
|
Window.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using FlaxEditor.CustomEditors.GUI;
|
|||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using JsonSerializer = FlaxEngine.Json.JsonSerializer;
|
using JsonSerializer = FlaxEngine.Json.JsonSerializer;
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Special case for root objects to run normal layout build
|
// Special case for root objects to run normal layout build
|
||||||
if (_presenter.Selection == Values)
|
if (_presenter != null && _presenter.Selection == Values)
|
||||||
{
|
{
|
||||||
_presenter.BuildLayout();
|
_presenter.BuildLayout();
|
||||||
return;
|
return;
|
||||||
@@ -158,7 +159,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
var layout = _layout;
|
var layout = _layout;
|
||||||
var control = layout.ContainerControl;
|
var control = layout.ContainerControl;
|
||||||
var parent = _parent;
|
var parent = _parent;
|
||||||
var parentScrollV = (_presenter.Panel.Parent as Panel)?.VScrollBar?.Value ?? -1;
|
var parentScrollV = (_presenter?.Panel.Parent as Panel)?.VScrollBar?.Value ?? -1;
|
||||||
|
|
||||||
control.IsLayoutLocked = true;
|
control.IsLayoutLocked = true;
|
||||||
control.DisposeChildren();
|
control.DisposeChildren();
|
||||||
@@ -248,6 +249,28 @@ namespace FlaxEditor.CustomEditors
|
|||||||
|
|
||||||
internal virtual void RefreshRootChild()
|
internal virtual void RefreshRootChild()
|
||||||
{
|
{
|
||||||
|
// Check if need to update value
|
||||||
|
if (_hasValueDirty)
|
||||||
|
{
|
||||||
|
IsSettingValue = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Cleanup (won't retry update in case of exception)
|
||||||
|
object val = _valueToSet;
|
||||||
|
_hasValueDirty = false;
|
||||||
|
_valueToSet = null;
|
||||||
|
|
||||||
|
// Assign value
|
||||||
|
for (int i = 0; i < _values.Count; i++)
|
||||||
|
_values[i] = val;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
OnUnDirty();
|
||||||
|
IsSettingValue = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Refresh();
|
Refresh();
|
||||||
|
|
||||||
for (int i = 0; i < _children.Count; i++)
|
for (int i = 0; i < _children.Count; i++)
|
||||||
@@ -603,9 +626,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
JsonSerializer.Deserialize(obj, text);
|
JsonSerializer.Deserialize(obj, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning disable 618
|
else if (!text.StartsWith("{") || !text.EndsWith("}"))
|
||||||
else if (Newtonsoft.Json.Schema.JsonSchema.Parse(text) == null)
|
|
||||||
#pragma warning restore 618
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -628,7 +649,14 @@ namespace FlaxEditor.CustomEditors
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Default
|
// Default
|
||||||
obj = JsonConvert.DeserializeObject(text, TypeUtils.GetType(Values.Type), JsonSerializer.Settings);
|
try
|
||||||
|
{
|
||||||
|
obj = JsonConvert.DeserializeObject(text, TypeUtils.GetType(Values.Type), JsonSerializer.Settings);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
obj = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj == null || Values.Type.IsInstanceOfType(obj))
|
if (obj == null || Values.Type.IsInstanceOfType(obj))
|
||||||
@@ -795,6 +823,8 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// <returns>True if allow to handle this event, otherwise false.</returns>
|
/// <returns>True if allow to handle this event, otherwise false.</returns>
|
||||||
protected virtual bool OnDirty(CustomEditor editor, object value, object token = null)
|
protected virtual bool OnDirty(CustomEditor editor, object value, object token = null)
|
||||||
{
|
{
|
||||||
|
if (ParentEditor == null)
|
||||||
|
return false;
|
||||||
return ParentEditor.OnDirty(editor, value, token);
|
return ParentEditor.OnDirty(editor, value, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors
|
namespace FlaxEditor.CustomEditors
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
||||||
#include "FlaxEngine.Gen.h"
|
#include "FlaxEngine.Gen.h"
|
||||||
#include <ThirdParty/mono-2.0/mono/metadata/reflection.h>
|
|
||||||
|
|
||||||
#define TRACK_ASSEMBLY(assembly) \
|
#define TRACK_ASSEMBLY(assembly) \
|
||||||
if (assembly->IsLoaded()) \
|
if (assembly->IsLoaded()) \
|
||||||
@@ -49,24 +48,24 @@ struct Entry
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Dictionary<MonoType*, Entry> Cache(512);
|
Dictionary<MType*, Entry> Cache(512);
|
||||||
|
|
||||||
void OnAssemblyLoaded(MAssembly* assembly);
|
void OnAssemblyLoaded(MAssembly* assembly);
|
||||||
void OnAssemblyUnloading(MAssembly* assembly);
|
void OnAssemblyUnloading(MAssembly* assembly);
|
||||||
void OnBinaryModuleLoaded(BinaryModule* module);
|
void OnBinaryModuleLoaded(BinaryModule* module);
|
||||||
|
|
||||||
MonoReflectionType* CustomEditorsUtil::GetCustomEditor(MonoReflectionType* refType)
|
MTypeObject* CustomEditorsUtil::GetCustomEditor(MTypeObject* refType)
|
||||||
{
|
{
|
||||||
if (!refType)
|
if (!refType)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
MonoType* type = mono_reflection_type_get_type(refType);
|
MType* type = INTERNAL_TYPE_OBJECT_GET(refType);
|
||||||
Entry result;
|
Entry result;
|
||||||
if (Cache.TryGet(type, result))
|
if (Cache.TryGet(type, result))
|
||||||
{
|
{
|
||||||
const auto editor = result.CustomEditor ? result.CustomEditor : result.DefaultEditor;
|
MClass* editor = result.CustomEditor ? result.CustomEditor : result.DefaultEditor;
|
||||||
if (editor)
|
if (editor)
|
||||||
{
|
{
|
||||||
return MUtils::GetType(editor->GetNative());
|
return MUtils::GetType(editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -123,19 +122,19 @@ void OnAssemblyLoaded(MAssembly* assembly)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto attribute = mclass->GetAttribute(customEditorAttribute);
|
const auto attribute = mclass->GetAttribute(customEditorAttribute);
|
||||||
if (attribute == nullptr || mono_object_get_class(attribute) != customEditorAttribute->GetNative())
|
if (attribute == nullptr || MCore::Object::GetClass(attribute) != customEditorAttribute)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check if attribute references a valid class
|
// Check if attribute references a valid class
|
||||||
MonoReflectionType* refType = nullptr;
|
MTypeObject* refType = nullptr;
|
||||||
customEditorTypeField->GetValue(attribute, &refType);
|
customEditorTypeField->GetValue(attribute, &refType);
|
||||||
if (refType == nullptr)
|
if (refType == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MonoType* type = mono_reflection_type_get_type(refType);
|
MType* type = INTERNAL_TYPE_OBJECT_GET(refType);
|
||||||
if (type == nullptr)
|
if (type == nullptr)
|
||||||
continue;
|
continue;
|
||||||
MonoClass* typeClass = mono_type_get_class(type);
|
MClass* typeClass = MCore::Type::GetClass(type);
|
||||||
|
|
||||||
// Check if it's a custom editor class
|
// Check if it's a custom editor class
|
||||||
if (mclass->IsSubClassOf(customEditor))
|
if (mclass->IsSubClassOf(customEditor))
|
||||||
@@ -152,18 +151,14 @@ void OnAssemblyLoaded(MAssembly* assembly)
|
|||||||
entry.CustomEditor = mclass;
|
entry.CustomEditor = mclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
//LOG(Info, "Custom Editor {0} for type {1} (default: {2})", String(mclass->GetFullName()), String(mono_type_get_name(type)), isDefault);
|
//LOG(Info, "Custom Editor {0} for type {1} (default: {2})", String(mclass->GetFullName()), MCore::Type::ToString(type), isDefault);
|
||||||
}
|
}
|
||||||
else if (typeClass)
|
else if (typeClass)
|
||||||
{
|
{
|
||||||
MClass* referencedClass = Scripting::FindClass(typeClass);
|
auto& entry = Cache[mclass->GetType()];
|
||||||
if (referencedClass)
|
entry.CustomEditor = typeClass;
|
||||||
{
|
|
||||||
auto& entry = Cache[mono_class_get_type(mclass->GetNative())];
|
|
||||||
entry.CustomEditor = referencedClass;
|
|
||||||
|
|
||||||
//LOG(Info, "Custom Editor {0} for type {1}", String(referencedClass->GetFullName()), String(mclass->GetFullName()));
|
//LOG(Info, "Custom Editor {0} for type {1}", String(typeClass->GetFullName()), String(mclass->GetFullName()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,17 +178,16 @@ void OnAssemblyUnloading(MAssembly* assembly)
|
|||||||
// Remove entries with user classes
|
// Remove entries with user classes
|
||||||
for (auto i = Cache.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = Cache.Begin(); i.IsNotEnd(); ++i)
|
||||||
{
|
{
|
||||||
MonoClass* monoClass = (MonoClass*)(void*)i->Key;
|
MClass* mClass = MCore::Type::GetClass(i->Key);
|
||||||
|
if (mClass && mClass->GetAssembly() == assembly)
|
||||||
if (assembly->GetClass(monoClass))
|
|
||||||
{
|
{
|
||||||
Cache.Remove(i);
|
Cache.Remove(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (i->Value.DefaultEditor && assembly->GetClass(i->Value.DefaultEditor->GetNative()))
|
if (i->Value.DefaultEditor && i->Value.DefaultEditor->GetAssembly() == assembly)
|
||||||
i->Value.DefaultEditor = nullptr;
|
i->Value.DefaultEditor = nullptr;
|
||||||
if (i->Value.CustomEditor && assembly->GetClass(i->Value.CustomEditor->GetNative()))
|
if (i->Value.CustomEditor && i->Value.CustomEditor->GetAssembly() == assembly)
|
||||||
i->Value.CustomEditor = nullptr;
|
i->Value.CustomEditor = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.InteropServices.Marshalling;
|
||||||
|
using FlaxEditor.CustomEditors.Dedicated;
|
||||||
using FlaxEditor.CustomEditors.Editors;
|
using FlaxEditor.CustomEditors.Editors;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Interop;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors
|
namespace FlaxEditor.CustomEditors
|
||||||
{
|
{
|
||||||
internal static class CustomEditorsUtil
|
internal static partial class CustomEditorsUtil
|
||||||
{
|
{
|
||||||
internal static readonly Dictionary<Type, string> InBuildTypeNames = new Dictionary<Type, string>()
|
internal static readonly Dictionary<Type, string> InBuildTypeNames = new Dictionary<Type, string>()
|
||||||
{
|
{
|
||||||
@@ -107,7 +111,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
// Select default editor (based on type)
|
// Select default editor (based on type)
|
||||||
if (targetType.IsEnum)
|
if (targetType.IsEnum)
|
||||||
return new EnumEditor();
|
return new EnumEditor();
|
||||||
if (targetType.IsGenericType)
|
if (targetType.IsGenericType)
|
||||||
{
|
{
|
||||||
if (targetTypeType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
if (targetTypeType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
||||||
return new DictionaryEditor();
|
return new DictionaryEditor();
|
||||||
@@ -118,12 +122,15 @@ namespace FlaxEditor.CustomEditors
|
|||||||
if (customEditorType != null)
|
if (customEditorType != null)
|
||||||
return (CustomEditor)Activator.CreateInstance(customEditorType);
|
return (CustomEditor)Activator.CreateInstance(customEditorType);
|
||||||
}
|
}
|
||||||
|
if (typeof(FlaxEngine.Object).IsAssignableFrom(targetTypeType))
|
||||||
|
return new ScriptingObjectEditor();
|
||||||
|
|
||||||
// The most generic editor
|
// The most generic editor
|
||||||
return new GenericEditor();
|
return new GenericEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[LibraryImport("FlaxEngine", EntryPoint = "CustomEditorsUtilInternal_GetCustomEditor", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
|
||||||
internal static extern Type Internal_GetCustomEditor(Type targetType);
|
[return: MarshalUsing(typeof(SystemTypeMarshaller))]
|
||||||
|
internal static partial Type Internal_GetCustomEditor([MarshalUsing(typeof(SystemTypeMarshaller))] Type targetType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class CustomEditorsUtil
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#if USE_MONO
|
#if USE_CSHARP
|
||||||
static MonoReflectionType* GetCustomEditor(MonoReflectionType* refType);
|
static MTypeObject* GetCustomEditor(MTypeObject* refType);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using FlaxEditor.Scripting;
|
|||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Json;
|
using FlaxEngine.Json;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Dedicated
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.CustomEditors.Editors.GenericEditor" />
|
/// <seealso cref="FlaxEditor.CustomEditors.Editors.GenericEditor" />
|
||||||
[CustomEditor(typeof(Actor)), DefaultEditor]
|
[CustomEditor(typeof(Actor)), DefaultEditor]
|
||||||
public class ActorEditor : GenericEditor
|
public class ActorEditor : ScriptingObjectEditor
|
||||||
{
|
{
|
||||||
private Guid _linkedPrefabId;
|
private Guid _linkedPrefabId;
|
||||||
|
|
||||||
@@ -94,19 +95,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
{
|
{
|
||||||
if (actor != null)
|
if (actor != null)
|
||||||
group.Panel.TooltipText = Surface.SurfaceUtils.GetVisualScriptTypeDescription(TypeUtils.GetObjectType(actor));
|
group.Panel.TooltipText = Surface.SurfaceUtils.GetVisualScriptTypeDescription(TypeUtils.GetObjectType(actor));
|
||||||
float settingsButtonSize = group.Panel.HeaderHeight;
|
var settingsButton = group.AddSettingsButton();
|
||||||
var settingsButton = new Image
|
|
||||||
{
|
|
||||||
TooltipText = "Settings",
|
|
||||||
AutoFocus = true,
|
|
||||||
AnchorPreset = AnchorPresets.TopRight,
|
|
||||||
Parent = group.Panel,
|
|
||||||
Bounds = new Rectangle(group.Panel.Width - settingsButtonSize, 0, settingsButtonSize, settingsButtonSize),
|
|
||||||
IsScrollable = false,
|
|
||||||
Color = FlaxEngine.GUI.Style.Current.ForegroundGrey,
|
|
||||||
Margin = new Margin(1),
|
|
||||||
Brush = new SpriteBrush(FlaxEngine.GUI.Style.Current.Settings),
|
|
||||||
};
|
|
||||||
settingsButton.Clicked += OnSettingsButtonClicked;
|
settingsButton.Clicked += OnSettingsButtonClicked;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -218,7 +207,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
node.Text = Utilities.Utils.GetPropertyNameUI(sceneObject.GetType().Name);
|
node.Text = Utilities.Utils.GetPropertyNameUI(sceneObject.GetType().Name);
|
||||||
}
|
}
|
||||||
// Array Item
|
// Array Item
|
||||||
else if (editor.ParentEditor?.Values?.Type.IsArray ?? false)
|
else if (editor.ParentEditor is CollectionEditor)
|
||||||
{
|
{
|
||||||
node.Text = "Element " + editor.ParentEditor.ChildrenEditors.IndexOf(editor);
|
node.Text = "Element " + editor.ParentEditor.ChildrenEditors.IndexOf(editor);
|
||||||
}
|
}
|
||||||
@@ -261,16 +250,14 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip if no change detected
|
// Skip if no change detected
|
||||||
if (!editor.Values.IsReferenceValueModified && skipIfNotModified)
|
var isRefEdited = editor.Values.IsReferenceValueModified;
|
||||||
|
if (!isRefEdited && skipIfNotModified)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
TreeNode result = null;
|
TreeNode result = null;
|
||||||
|
if (editor.ChildrenEditors.Count == 0 || (isRefEdited && editor is CollectionEditor))
|
||||||
if (editor.ChildrenEditors.Count == 0)
|
|
||||||
result = CreateDiffNode(editor);
|
result = CreateDiffNode(editor);
|
||||||
|
|
||||||
bool isScriptEditorWithRefValue = editor is ScriptsEditor && editor.Values.HasReferenceValue;
|
bool isScriptEditorWithRefValue = editor is ScriptsEditor && editor.Values.HasReferenceValue;
|
||||||
|
|
||||||
for (int i = 0; i < editor.ChildrenEditors.Count; i++)
|
for (int i = 0; i < editor.ChildrenEditors.Count; i++)
|
||||||
{
|
{
|
||||||
var child = ProcessDiff(editor.ChildrenEditors[i], !isScriptEditorWithRefValue);
|
var child = ProcessDiff(editor.ChildrenEditors[i], !isScriptEditorWithRefValue);
|
||||||
@@ -278,7 +265,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
{
|
{
|
||||||
if (result == null)
|
if (result == null)
|
||||||
result = CreateDiffNode(editor);
|
result = CreateDiffNode(editor);
|
||||||
|
|
||||||
result.AddChild(child);
|
result.AddChild(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for <see cref="AudioSource"/>.
|
||||||
|
/// </summary>
|
||||||
|
[CustomEditor(typeof(AudioSource)), DefaultEditor]
|
||||||
|
public class AudioSourceEditor : ActorEditor
|
||||||
|
{
|
||||||
|
private Label _infoLabel;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
base.Initialize(layout);
|
||||||
|
|
||||||
|
// Show playback options during simulation
|
||||||
|
if (Editor.IsPlayMode)
|
||||||
|
{
|
||||||
|
var playbackGroup = layout.Group("Playback");
|
||||||
|
playbackGroup.Panel.Open();
|
||||||
|
|
||||||
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
|
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
||||||
|
var gridControl = grid.CustomControl;
|
||||||
|
gridControl.ClipChildren = false;
|
||||||
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
gridControl.SlotsHorizontally = 3;
|
||||||
|
gridControl.SlotsVertically = 1;
|
||||||
|
grid.Button("Play").Button.Clicked += () => Foreach(x => x.Play());
|
||||||
|
grid.Button("Pause").Button.Clicked += () => Foreach(x => x.Pause());
|
||||||
|
grid.Button("Stop").Button.Clicked += () => Foreach(x => x.Stop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
base.Refresh();
|
||||||
|
|
||||||
|
if (_infoLabel != null)
|
||||||
|
{
|
||||||
|
var text = string.Empty;
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is AudioSource audioSource && audioSource.Clip)
|
||||||
|
text += $"Time: {audioSource.Time:##0.0}s / {audioSource.Clip.Length:##0.0}s\n";
|
||||||
|
}
|
||||||
|
_infoLabel.Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Foreach(Action<AudioSource> func)
|
||||||
|
{
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is AudioSource audioSource)
|
||||||
|
func(audioSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
var upperRightCell = new VerticalPanel
|
var upperRightCell = new VerticalPanel
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
Pivot = new Float2(0.0f, 0.0f),
|
Pivot = new Float2(0.00001f, 0.0f),
|
||||||
Offset = new Float2(-labelsWidth, 0),
|
Offset = new Float2(-labelsWidth, 0),
|
||||||
Rotation = -90,
|
Rotation = -90,
|
||||||
Spacing = 0,
|
Spacing = 0,
|
||||||
|
|||||||
@@ -145,7 +145,10 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No localization so initialize with empty table
|
// No localization so initialize with empty table
|
||||||
var path = Path.Combine(Path.Combine(Path.GetDirectoryName(GameSettings.Load().Localization.Path), "Localization", culture.Name + ".json"));
|
var folder = Path.Combine(Path.GetDirectoryName(GameSettings.Load().Localization.Path), "Localization");
|
||||||
|
if (!Directory.Exists(folder))
|
||||||
|
Directory.CreateDirectory(folder);
|
||||||
|
var path = Path.Combine(Path.Combine(folder, culture.Name + ".json"));
|
||||||
var table = FlaxEngine.Content.CreateVirtualAsset<LocalizedStringTable>();
|
var table = FlaxEngine.Content.CreateVirtualAsset<LocalizedStringTable>();
|
||||||
table.Locale = culture.Name;
|
table.Locale = culture.Name;
|
||||||
if (!table.Save(path))
|
if (!table.Save(path))
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FlaxEditor.Surface;
|
using FlaxEditor.Surface;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Dedicated
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
{
|
{
|
||||||
@@ -13,6 +15,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
[CustomEditor(typeof(ParticleEffect)), DefaultEditor]
|
[CustomEditor(typeof(ParticleEffect)), DefaultEditor]
|
||||||
public class ParticleEffectEditor : ActorEditor
|
public class ParticleEffectEditor : ActorEditor
|
||||||
{
|
{
|
||||||
|
private Label _infoLabel;
|
||||||
private bool _isValid;
|
private bool _isValid;
|
||||||
private bool _isActive;
|
private bool _isActive;
|
||||||
private uint _parametersVersion;
|
private uint _parametersVersion;
|
||||||
@@ -48,6 +51,15 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Foreach(Action<ParticleEffect> func)
|
||||||
|
{
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is ParticleEffect player)
|
||||||
|
func(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
{
|
{
|
||||||
@@ -60,6 +72,26 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
_parametersVersion = effect.ParametersVersion;
|
_parametersVersion = effect.ParametersVersion;
|
||||||
_isActive = effect.IsActive;
|
_isActive = effect.IsActive;
|
||||||
|
|
||||||
|
// Show playback options during simulation
|
||||||
|
if (Editor.IsPlayMode)
|
||||||
|
{
|
||||||
|
var playbackGroup = layout.Group("Playback");
|
||||||
|
playbackGroup.Panel.Open();
|
||||||
|
|
||||||
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
|
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
||||||
|
var gridControl = grid.CustomControl;
|
||||||
|
gridControl.ClipChildren = false;
|
||||||
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
gridControl.SlotsHorizontally = 3;
|
||||||
|
gridControl.SlotsVertically = 1;
|
||||||
|
grid.Button("Play").Button.Clicked += () => Foreach(x => x.Play());
|
||||||
|
grid.Button("Pause").Button.Clicked += () => Foreach(x => x.Pause());
|
||||||
|
grid.Button("Stop").Button.Clicked += () => Foreach(x => x.Stop());
|
||||||
|
}
|
||||||
|
|
||||||
// Show all effect parameters grouped by the emitter track name
|
// Show all effect parameters grouped by the emitter track name
|
||||||
var groups = layout.Group("Parameters");
|
var groups = layout.Group("Parameters");
|
||||||
groups.Panel.Open();
|
groups.Panel.Open();
|
||||||
@@ -99,7 +131,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
base.RefreshRootChild();
|
base.RefreshRootChild();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ChildrenEditors.Count; i++)
|
for (int i = 0; i < ChildrenEditors.Count; i++)
|
||||||
{
|
{
|
||||||
if (_isActive != effect.IsActive || _parametersVersion != effect.ParametersVersion)
|
if (_isActive != effect.IsActive || _parametersVersion != effect.ParametersVersion)
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
Presenter.Undo?.AddAction(new MultiUndoAction(actions));
|
Presenter.Undo?.AddAction(new MultiUndoAction(actions));
|
||||||
|
|
||||||
// Build ragdoll
|
// Build ragdoll
|
||||||
SceneGraph.Actors.AnimatedModelNode.BuildRagdoll(animatedModel, options, ragdoll);
|
AnimatedModelNode.BuildRagdoll(animatedModel, options, ragdoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRebuildBone(Button button)
|
private void OnRebuildBone(Button button)
|
||||||
@@ -191,7 +191,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build ragdoll
|
// Build ragdoll
|
||||||
SceneGraph.Actors.AnimatedModelNode.BuildRagdoll(animatedModel, new AnimatedModelNode.RebuildOptions(), ragdoll, name);
|
AnimatedModelNode.BuildRagdoll(animatedModel, new AnimatedModelNode.RebuildOptions(), ragdoll, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRemoveBone(Button button)
|
private void OnRemoveBone(Button button)
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for <see cref="SceneAnimationPlayer"/>.
|
||||||
|
/// </summary>
|
||||||
|
[CustomEditor(typeof(SceneAnimationPlayer)), DefaultEditor]
|
||||||
|
public class SceneAnimationPlayerEditor : ActorEditor
|
||||||
|
{
|
||||||
|
private Label _infoLabel;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
base.Initialize(layout);
|
||||||
|
|
||||||
|
// Show playback options during simulation
|
||||||
|
if (Editor.IsPlayMode)
|
||||||
|
{
|
||||||
|
var playbackGroup = layout.Group("Playback");
|
||||||
|
playbackGroup.Panel.Open();
|
||||||
|
|
||||||
|
_infoLabel = playbackGroup.Label(string.Empty).Label;
|
||||||
|
_infoLabel.AutoHeight = true;
|
||||||
|
|
||||||
|
var grid = playbackGroup.CustomContainer<UniformGridPanel>();
|
||||||
|
var gridControl = grid.CustomControl;
|
||||||
|
gridControl.ClipChildren = false;
|
||||||
|
gridControl.Height = Button.DefaultHeight;
|
||||||
|
gridControl.SlotsHorizontally = 3;
|
||||||
|
gridControl.SlotsVertically = 1;
|
||||||
|
grid.Button("Play").Button.Clicked += () => Foreach(x => x.Play());
|
||||||
|
grid.Button("Pause").Button.Clicked += () => Foreach(x => x.Pause());
|
||||||
|
grid.Button("Stop").Button.Clicked += () => Foreach(x => x.Stop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Refresh()
|
||||||
|
{
|
||||||
|
base.Refresh();
|
||||||
|
|
||||||
|
if (_infoLabel != null)
|
||||||
|
{
|
||||||
|
var text = string.Empty;
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is SceneAnimationPlayer player && player.Animation)
|
||||||
|
text += $"Time: {player.Time:##0.0}s / {player.Animation.Duration:##0.0}s\n";
|
||||||
|
}
|
||||||
|
_infoLabel.Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Foreach(Action<SceneAnimationPlayer> func)
|
||||||
|
{
|
||||||
|
foreach (var value in Values)
|
||||||
|
{
|
||||||
|
if (value is SceneAnimationPlayer player)
|
||||||
|
func(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using FlaxEditor.CustomEditors.Editors;
|
||||||
|
using FlaxEngine.Networking;
|
||||||
|
|
||||||
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom editor for <see cref="FlaxEngine.Object"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class ScriptingObjectEditor : GenericEditor
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
|
{
|
||||||
|
// Network objects debugging
|
||||||
|
var obj = Values[0] as FlaxEngine.Object;
|
||||||
|
if (Editor.IsPlayMode && NetworkManager.IsConnected && NetworkReplicator.HasObject(obj))
|
||||||
|
{
|
||||||
|
var group = layout.Group("Network");
|
||||||
|
group.Panel.Open();
|
||||||
|
group.Label("Role", Utilities.Utils.GetPropertyNameUI(NetworkReplicator.GetObjectRole(obj).ToString()));
|
||||||
|
group.Label("Owner Client Id", NetworkReplicator.GetObjectOwnerClientId(obj).ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Initialize(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using FlaxEditor.Actions;
|
using FlaxEditor.Actions;
|
||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.GUI;
|
using FlaxEditor.GUI;
|
||||||
@@ -12,6 +11,7 @@ using FlaxEditor.GUI.Drag;
|
|||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
using FlaxEngine.Utilities;
|
||||||
using Object = FlaxEngine.Object;
|
using Object = FlaxEngine.Object;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Dedicated
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
@@ -462,20 +462,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
var group = layout.Group("Missing script");
|
var group = layout.Group("Missing script");
|
||||||
|
|
||||||
// Add settings button to the group
|
// Add settings button to the group
|
||||||
const float settingsButtonSize = 14;
|
var settingsButton = group.AddSettingsButton();
|
||||||
var settingsButton = new Image
|
settingsButton.Tag = index;
|
||||||
{
|
|
||||||
TooltipText = "Settings",
|
|
||||||
AutoFocus = true,
|
|
||||||
AnchorPreset = AnchorPresets.TopRight,
|
|
||||||
Parent = group.Panel,
|
|
||||||
Bounds = new Rectangle(group.Panel.Width - settingsButtonSize, 0, settingsButtonSize, settingsButtonSize),
|
|
||||||
IsScrollable = false,
|
|
||||||
Color = FlaxEngine.GUI.Style.Current.ForegroundGrey,
|
|
||||||
Margin = new Margin(1),
|
|
||||||
Brush = new SpriteBrush(FlaxEngine.GUI.Style.Current.Settings),
|
|
||||||
Tag = index,
|
|
||||||
};
|
|
||||||
settingsButton.Clicked += MissingSettingsButtonOnClicked;
|
settingsButton.Clicked += MissingSettingsButtonOnClicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,19 +653,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add settings button to the group
|
// Add settings button to the group
|
||||||
var settingsButton = new Image
|
var settingsButton = group.AddSettingsButton();
|
||||||
{
|
settingsButton.Tag = script;
|
||||||
TooltipText = "Settings",
|
|
||||||
AutoFocus = true,
|
|
||||||
AnchorPreset = AnchorPresets.TopRight,
|
|
||||||
Parent = group.Panel,
|
|
||||||
Bounds = new Rectangle(group.Panel.Width - headerHeight, 0, headerHeight, headerHeight),
|
|
||||||
IsScrollable = false,
|
|
||||||
Color = FlaxEngine.GUI.Style.Current.ForegroundGrey,
|
|
||||||
Margin = new Margin(1),
|
|
||||||
Brush = new SpriteBrush(FlaxEngine.GUI.Style.Current.Settings),
|
|
||||||
Tag = script,
|
|
||||||
};
|
|
||||||
settingsButton.Clicked += OnSettingsButtonClicked;
|
settingsButton.Clicked += OnSettingsButtonClicked;
|
||||||
|
|
||||||
group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right - 12, 15, 2, 2);
|
group.Panel.HeaderTextMargin = new Margin(scriptDrag.Right - 12, 15, 2, 2);
|
||||||
|
|||||||
@@ -408,6 +408,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
{
|
{
|
||||||
private Type _cachedType;
|
private Type _cachedType;
|
||||||
private bool _anchorDropDownClosed = true;
|
private bool _anchorDropDownClosed = true;
|
||||||
|
private Button _pivotRelativeButton;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
@@ -484,13 +485,54 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
horDown.CustomControl.Height = TextBoxBase.DefaultHeight;
|
horDown.CustomControl.Height = TextBoxBase.DefaultHeight;
|
||||||
|
|
||||||
GetAnchorEquality(out _cachedXEq, out _cachedYEq, valueTypes);
|
GetAnchorEquality(out _cachedXEq, out _cachedYEq, valueTypes);
|
||||||
|
|
||||||
BuildLocationSizeOffsets(horUp, horDown, _cachedXEq, _cachedYEq, valueTypes);
|
BuildLocationSizeOffsets(horUp, horDown, _cachedXEq, _cachedYEq, valueTypes);
|
||||||
|
BuildExtraButtons(group);
|
||||||
|
|
||||||
main.Space(10);
|
main.Space(10);
|
||||||
BuildAnchorsDropper(main, valueTypes);
|
BuildAnchorsDropper(main, valueTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BuildExtraButtons(VerticalPanelElement group)
|
||||||
|
{
|
||||||
|
var control = (Control)Values[0];
|
||||||
|
var pivotRelative = Editor.Instance.Windows.PropertiesWin.UIPivotRelative;
|
||||||
|
control.PivotRelative = pivotRelative;
|
||||||
|
|
||||||
|
var panel = group.CustomContainer<Panel>();
|
||||||
|
panel.CustomControl.Height = TextBoxBase.DefaultHeight;
|
||||||
|
panel.CustomControl.ClipChildren = false;
|
||||||
|
panel.CustomControl.Parent = group.ContainerControl;
|
||||||
|
|
||||||
|
_pivotRelativeButton = new Button
|
||||||
|
{
|
||||||
|
TooltipText = "Toggles UI control resizing based on where the pivot is rather than just the top-left.",
|
||||||
|
Size = new Float2(18),
|
||||||
|
Parent = panel.ContainerControl,
|
||||||
|
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Scale32),
|
||||||
|
AnchorPreset = AnchorPresets.TopRight,
|
||||||
|
X = 77,
|
||||||
|
};
|
||||||
|
|
||||||
|
SetStyle(pivotRelative);
|
||||||
|
_pivotRelativeButton.Clicked += PivotRelativeClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PivotRelativeClicked()
|
||||||
|
{
|
||||||
|
var control = (Control)Values[0];
|
||||||
|
var pivotRelative = control.PivotRelative;
|
||||||
|
control.PivotRelative = !pivotRelative;
|
||||||
|
Editor.Instance.Windows.PropertiesWin.UIPivotRelative = !pivotRelative;
|
||||||
|
SetStyle(control.PivotRelative);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStyle(bool current)
|
||||||
|
{
|
||||||
|
var style = FlaxEngine.GUI.Style.Current;
|
||||||
|
var backgroundColor = current ? style.Foreground : style.ForegroundDisabled;
|
||||||
|
_pivotRelativeButton.SetColors(backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
private void BuildAnchorsDropper(LayoutElementsContainer main, ScriptType[] valueTypes)
|
private void BuildAnchorsDropper(LayoutElementsContainer main, ScriptType[] valueTypes)
|
||||||
{
|
{
|
||||||
ScriptMemberInfo minInfo = valueTypes[0].GetProperty("AnchorMin");
|
ScriptMemberInfo minInfo = valueTypes[0].GetProperty("AnchorMin");
|
||||||
@@ -655,7 +697,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
if (uiControl.Name.StartsWith(previousName))
|
if (uiControl.Name.StartsWith(previousName))
|
||||||
{
|
{
|
||||||
string newName = controlType.Name + uiControl.Name.Substring(previousName.Length);
|
string newName = controlType.Name + uiControl.Name.Substring(previousName.Length);
|
||||||
uiControl.Name = StringUtils.IncrementNameNumber(newName, x => uiControl.Parent.GetChild(x) == null);
|
if (uiControl.Parent != null)
|
||||||
|
newName = Utilities.Utils.IncrementNameNumber(newName, x => uiControl.Parent.GetChild(x) == null);
|
||||||
|
uiControl.Name = newName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,16 +27,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
element.ComboBox.SelectedIndexChanged += OnSelectedIndexChanged;
|
element.ComboBox.SelectedIndexChanged += OnSelectedIndexChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetActorsTree(List<Actor> list, Actor a)
|
|
||||||
{
|
|
||||||
list.Add(a);
|
|
||||||
int cnt = a.ChildrenCount;
|
|
||||||
for (int i = 0; i < cnt; i++)
|
|
||||||
{
|
|
||||||
GetActorsTree(list, a.GetChild(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSelectedIndexChanged(ComboBox comboBox)
|
private void OnSelectedIndexChanged(ComboBox comboBox)
|
||||||
{
|
{
|
||||||
int value = comboBox.SelectedIndex;
|
int value = comboBox.SelectedIndex;
|
||||||
@@ -60,7 +50,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
// Note: this possibly breaks the design a little bit
|
// Note: this possibly breaks the design a little bit
|
||||||
// But it's the easiest way to set value for selected actor and its children with one undo action
|
// But it's the easiest way to set value for selected actor and its children with one undo action
|
||||||
List<Actor> actors = new List<Actor>(32);
|
List<Actor> actors = new List<Actor>(32);
|
||||||
GetActorsTree(actors, actor);
|
Utilities.Utils.GetActorsTree(actors, actor);
|
||||||
if (Presenter.Undo != null)
|
if (Presenter.Undo != null)
|
||||||
{
|
{
|
||||||
using (new UndoMultiBlock(Presenter.Undo, actors.ToArray(), "Change layer"))
|
using (new UndoMultiBlock(Presenter.Undo, actors.ToArray(), "Change layer"))
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user