Compare commits
	
		
			917 commits
		
	
	
		
			21cb6859a2
			...
			de43670ec2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | de43670ec2 | ||
|   | d0f4815ef9 | ||
|   | e94e6fabd2 | ||
|   | f59bb2be3e | ||
|   | 33419cfee3 | ||
|   | 72ddf606f3 | ||
|   | 335cb5d396 | ||
|   | fa7904a469 | ||
|   | e69cf0064a | ||
|   | 69b39bd884 | ||
|   | ffe1e7efaf | ||
|   | c82b9753c6 | ||
|   | dc96e3e3ad | ||
|   | 26e7220959 | ||
|   | fa71e1fc85 | ||
|   | 5b031b7095 | ||
|   | 89de7718e6 | ||
|   | d9a7858c2d | ||
|   | 072865d2e5 | ||
|   | 193f42318c | ||
|   | c5b858021f | ||
|   | bd27d0e562 | ||
|   | e0a4dee72b | ||
|   | 719142ca12 | ||
|   | c76c9b57ed | ||
|   | 88d968a533 | ||
|   | 63e6ba7709 | ||
|   | 8b8387ff87 | ||
|   | 6c68edf955 | ||
|   | 7d6e30cb8e | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 86838739f0 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | f497f1ef84 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 6b26d4e7b2 | ||
|   | dfb00b96df | ||
|   | 258466e02c | ||
|   | f85bf9283a | ||
|   | 94d81c0c6b | ||
|   | 5a8ebfa7ae | ||
|   | 35b7cf053c | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 0f3c1af3e1 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 0f3a5fe010 | ||
|   | 43e6063eb4 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 76038686d5 | ||
|   | 73beea8842 | ||
|   | 2ffc1ca9b0 | ||
|   | ad8569532a | ||
|   | f387e1e525 | ||
|   | 9ac941686b | ||
|   | 9076772cf6 | ||
|   | 13a891b477 | ||
|   | 791bf16586 | ||
|   | 7527e845a9 | ||
|   | 7200acc382 | ||
|   | 5c9e90d805 | ||
|   | 51806d1742 | ||
|   | 6b09b7cb9b | ||
|   | 4e74a8d38e | ||
|   | 40fc41b724 | ||
|   | d5cda9b353 | ||
|   | 6cb668f546 | ||
|   | 01ae858906 | ||
|   | 90f663ee1a | ||
|   | c3d39e2571 | ||
|   | cf2a495e26 | ||
|   | 17af5e27ac | ||
|   | 8e9db6a2fe | ||
|   | a6f8547455 | ||
|   | 331b2d855f | ||
|   | 4bd749d976 | ||
|   | d160ec2e28 | ||
|   | 7723aee1d8 | ||
|   | fa50defe62 | ||
|   | c0025abd32 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 0744740f9a | ||
|   | 327129999e | ||
|   | 1e821fdf6c | ||
|   | bbb09f64f0 | ||
|   | 7722eeb539 | ||
|   | b2653fd585 | ||
|   | 788bd114cc | ||
|   | b8a0dae042 | ||
|   | afcca785eb | ||
|   | 3a8cdb8ea1 | ||
|   | 2750168287 | ||
|   | 847c5d951e | ||
|   | 5f661df9fd | ||
|   | 5716d89d52 | ||
|   | 9eea0a4dc8 | ||
|   | f684d62cb1 | ||
|   | 76c6ac2ccd | ||
|   | b89938b48a | ||
|   | e51fd8b77b | ||
|   | ec06cc62e1 | ||
|   | a81d6f340d | ||
|   | 559f577597 | ||
|   | ceb58c1a4c | ||
|   | 55e7979070 | ||
|   | 2a24716d77 | ||
|   | 5262551e1d | ||
|   | a656a723db | ||
|   | 41a2b989ae | ||
|   | 99219f1c44 | ||
|   | 9d13023a51 | ||
|   | fdcc5f01c9 | ||
|   | b626293f54 | ||
|   | 5d39d42061 | ||
|   | dbde1adaa3 | ||
|   | 69d9137faf | ||
|   | 48c5dd4fc4 | ||
|   | cfa7c774ac | ||
|   | 16a962dbec | ||
|   | ccd27980a2 | ||
|   | a5a96eb7c4 | ||
|   | 19e8e51505 | ||
|   | 3000e23cb1 | ||
|   | 8a56d3deed | ||
|   | cb81287c08 | ||
|   | 337406971a | ||
|   | ac4521483d | ||
|   | 9f641dcdc5 | ||
|   | 9f7f1bf860 | ||
|   | d4b3c1869b | ||
|   | 696c277f94 | ||
|   | b6aa85a916 | ||
|   | e86fec8d99 | ||
|   | 012d70b3a2 | ||
|   | 58b6c5e1eb | ||
|   | cb5f5379cb | ||
|   | a87cb01935 | ||
|   | 8d7d29bf5e | ||
|   | e3cf37f9ed | ||
|   | 26e24da4b5 | ||
|   | 7b6e0478d4 | ||
|   | 36b2e77ecf | ||
|   | fbacb7dc13 | ||
|   | 52675721b4 | ||
|   | 28ca8df5df | ||
|   | 0ff0f6ea17 | ||
|   | 4306bb09ae | ||
|   | 34ec35caf0 | ||
|   | 4425c53c8e | ||
|   | e76260dffa | ||
|   | 0b3f2c49db | ||
|   | 9ec1a62403 | ||
|   | 0dcf8eabab | ||
|   | c9d1e4cd08 | ||
|   | c36144bab3 | ||
|   | f7ef3ad1f7 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | ed1bb7422d | ||
|   | 83c5d15cdf | ||
|   | ad65bcf424 | ||
|   | d12fe2b7a5 | ||
|   | f3620d99a2 | ||
|   | 3718fc8872 | ||
|   | 7748d27b95 | ||
|   | 9ce411d85b | ||
|   | ea2c2e8f58 | ||
|   | ffbe3aedad | ||
|   | 0e90f8a7a1 | ||
|   | ac475999f5 | ||
|   | 4ad2983c24 | ||
|   | 5e10cdd6b4 | ||
|   | 6fca723404 | ||
|   | 3de270c2a1 | ||
|   | 6667f46c53 | ||
|   | 102650e936 | ||
|   | 9c486d5018 | ||
|   | ea7be1fa3a | ||
|   | 4e3600414e | ||
|   | 571fdfa692 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 0da5051408 | ||
|   | 25e32cf0ec | ||
|   | 6d23b094e6 | ||
|   | 6c7b5b3d22 | ||
|   | 10021a8ba2 | ||
|   | 81b0402e8a | ||
|   | 3cf6b96c8c | ||
|   | 9d188b7d95 | ||
|   | c4af3724c1 | ||
|   | 8f84a42e26 | ||
|   | e78aca7377 | ||
|   | c7a19658ef | ||
|   | fb675811dd | ||
|   | 9d6a0358d0 | ||
|   | 699f60d399 | ||
|   | 60d52b5c59 | ||
|   | 04e45978ad | ||
|   | e845968e57 | ||
|   | 4ed1fda1ae | ||
|   | 38d36d37f6 | ||
|   | 68fcecdc15 | ||
|   | f08a7d9a8d | ||
|   | f3debc08de | ||
|   | 018052b78d | ||
|   | ade40806b6 | ||
|   | 2a5068c4bb | ||
|   | b0e7f24be2 | ||
|   | c0280fcfab | ||
|   | 68a5baa5c4 | ||
|   | e49adafda9 | ||
|   | ef7caf5519 | ||
|   | 926cce1eac | ||
|   | f709380a97 | ||
|   | fd6c224fc2 | ||
|   | 2025698d88 | ||
|   | 0ec90737d3 | ||
|   | dd76fbf748 | ||
|   | 4ad3e92730 | ||
|   | b90deae897 | ||
|   | fbc1351031 | ||
|   | 953975a851 | ||
|   | 4c8f0b4df6 | ||
|   | a9067bf5d9 | ||
|   | 9e24a781a6 | ||
|   | 46cd75cff4 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 8e0c95d6ea | ||
|   | d6e574c877 | ||
|   | 4955dcd2c9 | ||
|   | d5e5019811 | ||
|   | 21e5697073 | ||
|   | 44a864f50f | ||
|   | 2d4ad2737e | ||
|   | 58f2609fe7 | ||
|   | 8989c0e88c | ||
|   | 0438b65208 | ||
|   | 969267b661 | ||
|   | 4906800a22 | ||
|   | 3d7da7d971 | ||
|   | 781aa40e8c | ||
|   | 2821eff71f | ||
|   | 3288ba30ec | ||
|   | 2daf4d8ba4 | ||
|   | 759a9e4379 | ||
|   | e10ebdeb5e | ||
|   | f481d57ed1 | ||
|   | 16a73ed872 | ||
|   | 309a5ed25e | ||
|   | 1f0d2a7a66 | ||
|   | 314d3f5b9b | ||
|   | 34eb3af698 | ||
|   | 0ac0e03ff8 | ||
|   | 0f95439b61 | ||
|   | 0bda6296c0 | ||
|   | 6ca76b9eca | ||
|   | 63585af26d | ||
|   | 094d286b41 | ||
|   | 8b7a3e9781 | ||
|   | ac6d6093ec | ||
|   | add57ff26f | ||
|   | a754d66844 | ||
|   | fc83a7a36f | ||
|   | 7c99bbc185 | ||
|   | ac12cce5f2 | ||
|   | 7fef5789de | ||
|   | 9570dcf20e | ||
|   | 05335fad84 | ||
|   | f0ef6b35dd | ||
|   | 4ddff43813 | ||
|   | dcc7a1f637 | ||
|   | b169f46f5f | ||
|   | ef480f6d10 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 01dbb96f1f | ||
|   | b084ccb1f4 | ||
|   | 3c5b126c67 | ||
|   | 73355c9424 | ||
|   | 4532327f50 | ||
|   | dc074b0262 | ||
|   | 86926178df | ||
|   | 1fdefe83de | ||
|   | 490989ac2a | ||
|   | 0c59a0d4d2 | ||
|   | f40c24ce6f | ||
|   | 671ec1d658 | ||
|   | f37a77a9f7 | ||
|   | 4719badc54 | ||
|   | 228ec191f6 | ||
|   | 34fc6d584f | ||
|   | 82ba51909e | ||
|   | 56961efe76 | ||
|   | 81f09e07f0 | ||
|   | 8cdd8526eb | ||
|   | 2f2516b998 | ||
|   | 3ba569354e | ||
|   | 104fe790fb | ||
|   | ae24991432 | ||
|   | 8dde98d2a9 | ||
|   | 65e3a66750 | ||
|   | 1a1c668d62 | ||
|   | 33e18765b7 | ||
|   | e3ccce5d5b | ||
|   | e82fa93fb0 | ||
|   | 7a8a0302e0 | ||
|   | 33c73ef0e2 | ||
|   | 1bdfdcafad | ||
|   | b117d2088a | ||
|   | 05ff080d78 | ||
|   | 53ade7fc53 | ||
|   | 02ec27dd2f | ||
|   | 33cfd4bc0e | ||
|   | cc54e4d834 | ||
|   | e4fc13aa92 | ||
|   | 1e1422a3dd | ||
|   | 16507adbe9 | ||
|   | 3f83c8e4a9 | ||
|   | d00b2fe063 | ||
|   | d3d9823459 | ||
|   | a6ba312f6b | ||
|   | 46972e8769 | ||
|   | d63c2a3ef9 | ||
|   | 163b703964 | ||
|   | b60318c393 | ||
|   | 8646c3da6d | ||
|   | 3998f0fe36 | ||
|   | 7e9895e002 | ||
|   | c00016cb69 | ||
|   | 2eb65defbc | ||
|   | f9e79b3e40 | ||
|   | cf87cc9bf0 | ||
|   | 8da440ea1f | ||
|   | e6cfef06a7 | ||
|   | 2720ad6a38 | ||
|   | f06191f290 | ||
|   | 59a8fdbf56 | ||
|   | cd7435a4d5 | ||
|   | 9f33189c18 | ||
|   | 895e760fee | ||
|   | d34cd68471 | ||
|   | a8da035566 | ||
|   | 549f7ece61 | ||
|   | 87af6479d6 | ||
|   | 6ecb3f6ffb | ||
|   | 4f58827c96 | ||
|   | ef197bf578 | ||
|   | 33f92bcda5 | ||
|   | d21a11963f | ||
|   | b84c36c91a | ||
|   | 22ed4c36fc | ||
|   | 62414e5b10 | ||
|   | 2569e3e3d8 | ||
|   | 8f9338e4d3 | ||
|   | 66abfc853d | ||
|   | e47a3c28c9 | ||
|   | 3d43360e21 | ||
|   | 12b0705322 | ||
|   | db20e21ccb | ||
|   | 72f4296e1e | ||
|   | 64c2555b4b | ||
|   | 3168725b00 | ||
|   | 071c2f60bf | ||
|   | 27cfabcc66 | ||
|   | b02dca5877 | ||
|   | ef731038a2 | ||
|   | 152d072242 | ||
|   | d6e2bfe9ab | ||
|   | 9f5c126b7f | ||
|   | b4694d637b | ||
|   | 3f9f5fcb90 | ||
|   | 97693fdace | ||
|   | 3537a233ca | ||
|   | d34224c135 | ||
|   | 44c37a8435 | ||
|   | 17b2db64ef | ||
|   | 81ec5f9f7a | ||
|   | ddd8977586 | ||
|   | ceb1ca8416 | ||
|   | 24f5f0a3e3 | ||
|   | 484c08c455 | ||
|   | ac3c986568 | ||
|   | 443f5a3615 | ||
|   | be972cdb7e | ||
|   | 5968fd981c | ||
|   | 316da55000 | ||
|   | b74229a3f4 | ||
|   | 15f906ad5a | ||
|   | 6afcf1312f | ||
|   | c29c0e82dd | ||
|   | bdb73b645c | ||
|   | 58e2058efc | ||
|   | 751d443546 | ||
|   | 0f52aac32d | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | da6fe3a6fb | ||
|   | c64cd45953 | ||
|   | fe61f31c40 | ||
|   | 260b7c73a4 | ||
|   | 1c23718654 | ||
|   | 1ff686629b | ||
|   | 0086dc3e0f | ||
|   | 77716e8f0b | ||
|   | ae8eb3e05e | ||
|   | 430ff9e984 | ||
|   | 7c06aa8e6e | ||
|   | 529291d2a2 | ||
|   | 2ecc49ddb3 | ||
|   | c07e2bca53 | ||
|   | 9c16a88b63 | ||
|   | 6b2f3dd84f | ||
|   | 7fdf25f1e7 | ||
|   | b2e4215ea8 | ||
|   | 7380dbe21a | ||
|   | fecea10525 | ||
|   | 401dc3ea69 | ||
|   | 7d2635608d | ||
|   | f5ab6f3ef7 | ||
|   | a7c6be2bab | ||
|   | fee00b737a | ||
|   | c9ead60dd4 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | eb925c2ca1 | ||
|   | f00b92274a | ||
|   | e25f56fcae | ||
|   | 71bfbcc6ce | ||
|   | 50006ada37 | ||
|   | 4ab4a8825b | ||
|   | befa5f3ded | ||
|   | dc72e9fbfc | ||
|   | 6509fc7043 | ||
|   | 504cde0e8b | ||
|   | f0ba7296d5 | ||
|   | 8dfb2fe69c | ||
|   | 2be140d291 | ||
|   | ec296d98eb | ||
|   | ab682567c6 | ||
|   | c139b156ee | ||
|   | a9daf47741 | ||
|   | c6596b3e7d | ||
|   | 9bd5af03f9 | ||
|   | 6d107f6c2d | ||
|   | e641c0b0e5 | ||
|   | 35d642e76f | ||
|   | fea9083f7d | ||
|   | 83f5fa92e0 | ||
|   | e667155cd5 | ||
|   | 087f6ef310 | ||
|   | f7ee395eba | ||
|   | 0b820b6d3e | ||
|   | 3ef794a25e | ||
|   | 61ac1e5612 | ||
|   | 0fff5f9e4d | ||
|   | 9e5890d95e | ||
|   | f82ed0d9d4 | ||
|   | a8568d24f6 | ||
|   | 5e368aaced | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | e8e25e08cc | ||
|   | ed357f6bb0 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 61d52fc45f | ||
|   | 7fc3d4e217 | ||
|   | 7e02add8de | ||
|   | db6ff3e0a4 | ||
|   | d5dadb5175 | ||
|   | d633f7746c | ||
|   | dc3258d149 | ||
|   | 8be9cc72de | ||
|   | b4f888ad15 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | adf3e7fed6 | ||
|   | 827a5210c2 | ||
|   | b536aa5336 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 68f05ece85 | ||
|   | 171ba471a2 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 17b1413c05 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | b4c133ac77 | ||
|   | 7e203415c4 | ||
|   | f9a3ff2a83 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 2bdde92d1b | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 7cb2ca3e05 | ||
|   | f44b1918af | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 506d05b3ca | ||
|   | 57a3dfd4eb | ||
|   | 7ee86867ad | ||
|   | 37af83676e | ||
|   | e0c2f537a3 | ||
|   | 501ea22ea2 | ||
|   | e189abea4d | ||
|   | efb54b123c | ||
|   | 84ce6589a3 | ||
|   | f2955a841a | ||
|   | 7b70d91093 | ||
|   | 75c4741d9a | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 44b1cdd801 | ||
|   | fbed3fc8ab | ||
|   | e43c0594d1 | ||
|   | 0043283881 | ||
|   | e8e7cd6dea | ||
|   | 2927419b6d | ||
|   | 36e8690ad1 | ||
|   | 4038fb2c43 | ||
|   | bc79ed11a3 | ||
|   | f3c846f0b1 | ||
|   | 64d24591f3 | ||
|   | 05c05fec5c | ||
|   | f84a86a3a3 | ||
|   | 36339e613f | ||
|   | ba62004002 | ||
|   | 0a3913bdee | ||
|   | c1aeefb0eb | ||
|   | 517ec9b266 | ||
|   | 8e11ae5efd | ||
|   | 17982013be | ||
|   | 85eadf6f93 | ||
|   | 1d564ff7b9 | ||
|   | 11fc6ac495 | ||
|   | 3055284664 | ||
|   | e094a9854f | ||
|   | 47a3c1a015 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 467cb35648 | ||
|   | 9d0a75d032 | ||
|   | 42314a64b2 | ||
|   | 508b5f55a2 | ||
|   | 69d5a36f55 | ||
|   | 165edc9a90 | ||
|   | a92248b4d9 | ||
|   | c94e483c6e | ||
|   | e522f85a72 | ||
|   | 607d72d7bb | ||
|   | a3e9d68dc4 | ||
|   | 3f5a0056e4 | ||
|   | 8e2674f83e | ||
|   | e7b2981bd6 | ||
|   | 6ef24bf4ed | ||
|   | 0a749c1245 | ||
|   | f7d2346924 | ||
|   | be8237da72 | ||
|   | 3ea37ba104 | ||
|   | eb3b76dcf4 | ||
|   | 87e43a528e | ||
|   | 2f9908b54e | ||
|   | 4a4075b50f | ||
|   | 6408e1b876 | ||
|   | 923dad4e2e | ||
|   | 71f967d536 | ||
|   | d81f187d88 | ||
|   | a947dc6b9f | ||
|   | 60b4833eb2 | ||
|   | db95a11e17 | ||
|   | 736fd43b46 | ||
|   | 7edafe8d78 | ||
|   | 2fd94c6575 | ||
|   | dc284974b3 | ||
|   | 91b4d6c2c2 | ||
|   | 23a99f081a | ||
|   | 9a5d24544e | ||
|   | d9d8f8de8a | ||
|   | 7ab12e7b4b | ||
|   | cac89129af | ||
|   | e62ef3a7f3 | ||
|   | 3629dd36f2 | ||
|   | 89ef256647 | ||
|   | d8233a2c41 | ||
|   | 5d8f3786de | ||
|   | 4432bcb93c | ||
|   | 5bb4a7f95a | ||
|   | 3685599693 | ||
|   | 7b72cb4c71 | ||
|   | 1a5503a6f6 | ||
|   | 05515c59b8 | ||
|   | fc8d65d4d1 | ||
|   | cfed61c6ff | ||
|   | d0d9adfd1a | ||
|   | 1a32748b8e | ||
|   | 6da34fc151 | ||
|   | 7ed89fdd5d | ||
|   | 875fb8a8c9 | ||
|   | 1dce1b2b35 | ||
|   | daa5bd24dc | ||
|   | c73698619d | ||
|   | 84d88f5040 | ||
|   | c78fd097a1 | ||
|   | a792538e29 | ||
|   | c7be1d37e0 | ||
|   | 5be46de20a | ||
|   | 4ba0c5e3ba | ||
|   | 7a064c750a | ||
|   | 432d794626 | ||
|   | b5241ff1f7 | ||
|   | d6f94f2e19 | ||
|   | 14f97347d5 | ||
|   | 2e973bf654 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 8ec983b654 | ||
|   | 99ec41c7c7 | ||
|   | b1b06bc125 | ||
|   | 70c858d847 | ||
|   | f156716173 | ||
|   | 517013633d | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 097df7894e | ||
|   | f01a357f98 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 0681b523fe | ||
|   | f7a55ec85b | ||
|   | f34a3e2145 | ||
|   | 6bf3ae833a | ||
|   | 983e9b467d | ||
|   | 4cd0885023 | ||
|   | ddac6c1963 | ||
|   | 41a134eb6b | ||
|   | 9a171464ff | ||
|   | 27f8c1f56c | ||
|   | ecf7579d8e | ||
|   | 9d0c1c539c | ||
|   | c0b7f85278 | ||
|   | 9174a4de91 | ||
|   | 7dabda88ff | ||
|   | 74066aa195 | ||
|   | f7a1668c3f | ||
|   | bef8628bb6 | ||
|   | 88b1d5c2a7 | ||
|   | 0c17744bc6 | ||
|   | 80c3cb70d2 | ||
|   | a3eb53a649 | ||
|   | 57b773d009 | ||
|   | a65504a2cb | ||
|   | cc0ebcd13c | ||
|   | f010ea8fad | ||
|   | 77e02b76b1 | ||
|   | 3e681abfdb | ||
|   | 172203ec16 | ||
|   | 82ea0dacd3 | ||
|   | ddf53b5b43 | ||
|   | 14b699d660 | ||
|   | 6a5e04b35a | ||
|   | e3cee80eba | ||
|   | 83a1989cee | ||
|   | 37af0714ae | ||
|   | 10aabce3a1 | ||
|   | 1c4551522d | ||
|   | 7c884fec55 | ||
|   | 3562edcb7a | ||
|   | b7970bb631 | ||
|   | c492f11466 | ||
|   | ac48ac24ab | ||
|   | 40149ae32c | ||
|   | 44f91a3a86 | ||
|   | b93c76ef1b | ||
|   | 57f6b41a47 | ||
|   | 9f7026bf9c | ||
|   | dcea34118f | ||
|   | a8132ef9f1 | ||
|   | d3ae404f7a | ||
|   | e0cd3610a6 | ||
|   | a5919ac917 | ||
|   | 1b07c6f5b5 | ||
|   | 80d5be956d | ||
|   | e93697b162 | ||
|   | bd4c8776a5 | ||
|   | 5be8d7b7c0 | ||
|   | 608b1af24f | ||
|   | 1ac85e253f | ||
|   | 1c8d7f5be9 | ||
|   | 84f0003bef | ||
|   | 13a015cd5f | ||
|   | 7b938f9458 | ||
|   | a287789d87 | ||
|   | aba904af3c | ||
|   | fd7de65e86 | ||
|   | 372712745c | ||
|   | 64b679a002 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | cee1831fb2 | ||
|   | 000d0064ad | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 7b99dffb3e | ||
|   | 40b3ecce16 | ||
|   | 82cec1d744 | ||
|   | 61a93dbc30 | ||
|   | 9e7075c7e5 | ||
|   | f12f209a0d | ||
|   | 0f9b595ce7 | ||
|   | e3fa3fdd61 | ||
|   | f1e9296299 | ||
|   | d45801bd50 | ||
|   | d6a0a17d3f | ||
|   | 6e13ed2c85 | ||
|   | 27b2d79a65 | ||
|   | 036acf3c85 | ||
|   | 1ea94b02cd | ||
|   | 90aaf2bad6 | ||
|   | 6b3149fbce | ||
|   | c74a56206c | ||
|   | 88807a05a1 | ||
|   | eb47443bba | ||
|   | d64eb762b4 | ||
|   | e61ac8814d | ||
|   | 01f790020e | ||
|   | d726da5d73 | ||
|   | 0dcc6ef4b1 | ||
|   | ed353248e0 | ||
|   | f2e1db491f | ||
|   | df1fc2fe54 | ||
|   | 1fd696d787 | ||
|   | 8c7c04c797 | ||
|   | 9e07b03b78 | ||
|   | a78d02617f | ||
|   | b7d4cdd51c | ||
|   | 41f8434d35 | ||
|   | ff60b3c891 | ||
|   | 5fb27151b3 | ||
|   | 3ec58659f5 | ||
|   | 5d91bbf32f | ||
|   | 6f70499105 | ||
|   | 07cac3a03f | ||
|   | 84bbfe4413 | ||
|   | 75a8f7f351 | ||
|   | 9ab9d6b2d0 | ||
|   | fef83c8aa7 | ||
|   | dab88ebb98 | ||
|   | ed9e7ad72f | ||
|   | d539f7723e | ||
|   | 71d2345e66 | ||
|   | b1f32ab0f5 | ||
|   | dbfacdfd28 | ||
|   | 5dd30131e3 | ||
|   | c4f78df149 | ||
|   | 831e0f7d1b | ||
|   | ee5719cb55 | ||
|   | 694d3224b5 | ||
|   | 756249c3ad | ||
|   | 4a66715923 | ||
|   | f0bfca8588 | ||
|   | 950620de6e | ||
|   | b13d2106d4 | ||
|   | 35f2c85a19 | ||
|   | b5ac254259 | ||
|   | 0683cd2326 | ||
|   | 2029806a5f | ||
|   | 4cd98ef4ac | ||
|   | ae91686d4c | ||
|   | 4471843f8b | ||
|   | 881502c970 | ||
|   | f7949cc404 | ||
|   | 845d5b5707 | ||
|   | 2a9dc72721 | ||
|   | d209ce97ea | ||
|   | f1e35532b9 | ||
|   | b466ac818c | ||
|   | 50b6a8dd9b | ||
|   | 6dbd020591 | ||
|   | 94bb3c9430 | ||
|   | 73d3eedcdc | ||
|   | 3f52f79210 | ||
|   | 7a070b3e7f | ||
|   | e16db1823d | ||
|   | 20b8c0da7d | ||
|   | 158a4171d2 | ||
|   | ccf5f6a3d8 | ||
|   | 8e114c555f | ||
|   | e8f20938cd | ||
|   | ac40fd93b7 | ||
|   | b5a89b51db | ||
|   | a7939a3a19 | ||
|   | 96c6baa6c9 | ||
|   | 67c510cbd8 | ||
|   | 57d65cf086 | ||
|   | 5c57ae0edc | ||
|   | 236d7c1e35 | ||
|   | 2c9a8a33a4 | ||
|   | 0bce0e2bd7 | ||
|   | 194638f759 | ||
|   | 6c2e31e3cb | ||
|   | a5106f4640 | ||
|   | b4652f6d2d | ||
|   | 5195519ef1 | ||
|   | c04cbc2929 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 43d8fc5207 | ||
|   | 1843f387ff | ||
|   | 72a1697d65 | ||
|   | fe9311325b | ||
|   | a82e379f9b | ||
|   | ee998232f7 | ||
|   | a8845514c6 | ||
|   | 9ee6e2ee25 | ||
|   | 620a0dba25 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 907d80943e | ||
|   | bf3454d9a4 | ||
|   | bc3b1ad3d2 | ||
|   | 25fb9bdae0 | ||
|   | 67706dc186 | ||
|   | 78b453249a | ||
|   | 60a059078c | ||
|   | 0c20e49831 | ||
|   | aec937aa97 | ||
|   | e9ee5c6911 | ||
|   | 685f3cee10 | ||
|   | 2f37e42b38 | ||
|   | 1fd51d23f3 | ||
|   | a03cf83d58 | ||
|   | aabf4fcbb0 | ||
|   | 3b8e0d8180 | ||
|   | 0cfad82933 | ||
|   | 0ec81e5832 | ||
|   | 250a535fc3 | ||
|   | 534b679d63 | ||
|   | 491a33794f | ||
|   | 57625b9680 | ||
|   | ad10e019fe | ||
|   | 9730ae581b | ||
|   | 411c570b67 | ||
|   | 20fd03bbdb | ||
|   | 19415cd0a1 | ||
|   | 84233868d6 | ||
|   | 74f3a15eb2 | ||
|   | 621cbb3d51 | ||
|   | 31940441ed | ||
|   | cd16902635 | ||
|   | da271c326a | ||
|   | 27828943f4 | ||
|   | 2b7d1ab7c9 | ||
|   | 0a0989e5f4 | ||
|   | f5d867cf1a | ||
|   | ec4387112e | ||
|   | 06a2a18c06 | ||
|   | d92f6c7204 | ||
|   | c2209908a0 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | fe9affcefe | ||
|   | f8efa20b7c | ||
|   | 1436b7bba6 | ||
|   | 41c1125388 | ||
|   | 1a8f38cb4b | ||
|   | 4eeac9f830 | ||
|   | fe4a324a04 | ||
|   | a548497767 | ||
|   | 50cf49568d | ||
|   | c811b95129 | ||
|   | f672ff553a | ||
|   | 295bbda921 | ||
|   | a1d9b25f0b | ||
|   | 2d8c3c8175 | ||
|   | d039fef4f1 | ||
|   | 3434db279e | ||
|   | 94edeefee0 | ||
|   | 40d70b0a13 | ||
|   | 584f5943b6 | ||
|   | dafb71e75c | ||
|   | 70cb3ab6d2 | ||
|   | 20dbc7f5b7 | ||
|   | 76809de2df | ||
|   | 6063de2095 | ||
|   | 928b3397d2 | ||
|   | 6b0aaea773 | ||
|   | 8212d24d34 | ||
|   | 9f4a798d67 | ||
|   | 47b7d475c8 | ||
|   | efee1653e1 | ||
|   | 1a30743c0a | ||
|   | cea2993665 | ||
|   | c8dc8ed630 | ||
|   | 8fc392681a | ||
|   | 7101cdf183 | ||
|   | 38a2831779 | ||
|   | 829d8a3152 | ||
|   | 9182d170de | ||
|   | 0108799718 | ||
|   | 0481281680 | ||
|   | f8e0ab5b56 | ||
|   | da79f47416 | ||
|   | 88b8a8001f | ||
|   | eda7751eb9 | ||
|   | 7254fc71fb | ||
|   | a357489a55 | ||
|   | d1e583d252 | ||
|   | 2d9d240a5a | ||
|   | 6c7f7f952f | ||
|   | 421cae6716 | ||
|   | 6953eddea6 | ||
|   | 1b79c37fd2 | ||
|   | 7c15a8272b | ||
|   | ccacc7f7db | ||
|   | 264ed5a943 | ||
|   | 79e39021a6 | ||
|   | 88246b26fe | ||
|   | 4b4cc3b500 | ||
|   | d5703fe522 | ||
|   | 3b5323cea0 | ||
|   | c5d004aa48 | ||
|   | d48baab44c | ||
|   | 02bf673105 | ||
|   | 46e0adee15 | ||
|   | 4a7bff0d37 | ||
|   | ba7a518b4d | ||
|   | 403d7fdc2a | ||
|   | fb94934d1b | ||
|   | d9f9e89b19 | ||
|   | 797f26e461 | ||
|   | 2cd0a16028 | ||
|   | 0585ab828c | ||
|   | 5c3bcaa0ce | ||
|   | b16a299b16 | ||
|   | 5f27d1e484 | ||
|   | dfab86a4ad | ||
|   | a4c945803c | ||
|   | f5a5d3172f | ||
|   | a2efe1a928 | ||
|   | f2c9de4b36 | ||
|   | 3be82e1d1f | ||
|   | 80070109db | ||
|   | e683154f02 | ||
|   | 97b5b6f4ca | ||
|   | c92b881d4a | ||
|   | 838032c8d6 | ||
|   | 7f672f709b | ||
|   | fe37d6080a | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | d545656176 | ||
|   | d0b843c103 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | a7b6a28c42 | ||
|   | 79138692cb | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 9a1b95e63e | ||
|   | d7adbb3a01 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | c363f5a1b7 | ||
|   | 9092599929 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | be5dad0195 | ||
|   | d2cb5c1e93 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 5d051e127f | ||
|   | 475460ff84 | ||
|   | 1b16b903a0 | ||
|   | 449912e655 | ||
|   | 06efa2da58 | ||
|   | 83c833e89c | ||
|   | 6f2a087ef8 | ||
|   | f1bc8d2b13 | ||
|   | a94dc82c1f | ||
|   | bc62236351 | ||
|   | 3789845a36 | ||
|   | 3ab18392b3 | ||
|   | ef6494f4c3 | 
							
								
								
									
										1
									
								
								.clang-format-ignore
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | CMakePresets.json | ||||||
							
								
								
									
										19
									
								
								.clang-tidy
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,19 @@ | ||||||
|  | Checks: | ||||||
|  |   - '-*' | ||||||
|  |   - 'bugprone-*' | ||||||
|  |   - 'clang-analyzer-*' | ||||||
|  |   - 'cppcoreguidelines-*' | ||||||
|  |   - 'misc-*' | ||||||
|  |   - 'modernize-*' | ||||||
|  |   - 'performance-*' | ||||||
|  |   - '-bugprone-easily-swappable-parameters' | ||||||
|  |   - '-cppcoreguidelines-avoid-do-while' | ||||||
|  |   - '-cppcoreguidelines-avoid-non-const-global-variables' | ||||||
|  |   - '-cppcoreguidelines-pro-type-reinterpret-cast' | ||||||
|  |   - '-cppcoreguidelines-pro-type-union-access' | ||||||
|  |   - '-misc-include-cleaner' | ||||||
|  |   - '-misc-non-private-member-variables-in-classes' | ||||||
|  |   - '-misc-use-anonymous-namespace' | ||||||
|  |   - '-modernize-return-braced-init-list' | ||||||
|  |   - '-modernize-use-trailing-return-type' | ||||||
|  | FormatStyle: 'file' | ||||||
							
								
								
									
										250
									
								
								.github/workflows/ci.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -11,7 +11,7 @@ on: | ||||||
| 
 | 
 | ||||||
| concurrency: | concurrency: | ||||||
|   # Cancel in-progress jobs for the same pull request |   # Cancel in-progress jobs for the same pull request | ||||||
|   group: ${{ github.head_ref || github.run_id }} |   group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | ||||||
|   cancel-in-progress: true |   cancel-in-progress: true | ||||||
| 
 | 
 | ||||||
| jobs: | jobs: | ||||||
|  | @ -20,47 +20,114 @@ jobs: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
|         include: |         include: | ||||||
|           - name: win64_msvc2022 |           - name: windows_msvc2022_x64 | ||||||
|             os: windows-2022 |             os: windows-2022 | ||||||
|             build_type: Release |             build_type: Release | ||||||
|             env_cc: '' |             env_cc: '' | ||||||
|             env_cxx: '' |             env_cxx: '' | ||||||
|             compiler: msvc |             compiler: msvc | ||||||
|  |             cppflags: '' | ||||||
|  |             ldflags: '' | ||||||
|             msvc_arch: x64 |             msvc_arch: x64 | ||||||
|             msvc_version: 2022 |             msvc_version: 2022 | ||||||
|             qt_version: 6.7.2 |             qt_version: 6.9.2 | ||||||
|             qt_arch_aqt: win64_msvc2019_64 |             qt_arch_aqt: win64_msvc2022_64 | ||||||
|             qt_arch_dir: msvc2019_64 |             qt_arch_dir: msvc2022_64 | ||||||
|             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport |             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport | ||||||
|             qt_tools: '' |             qt_tools: '' | ||||||
|             conan_arch: x86_64 |  | ||||||
|             conan_compiler: Visual Studio |  | ||||||
|             conan_compiler_version: 17 |  | ||||||
|             conan_compiler_runtime: --settings compiler.runtime=MD |  | ||||||
|             conan_package_manager: '' |             conan_package_manager: '' | ||||||
|  |             conan_profile: scwx-windows_msvc2022_x64 | ||||||
|  |             appimage_arch: '' | ||||||
|             artifact_suffix: windows-x64 |             artifact_suffix: windows-x64 | ||||||
|           - name: linux64_gcc |           - name: linux_gcc_x64 | ||||||
|             os: ubuntu-22.04 |             os: ubuntu-22.04 | ||||||
|             build_type: Release |             build_type: Release | ||||||
|             env_cc: gcc-11 |             env_cc: gcc-11 | ||||||
|             env_cxx: g++-11 |             env_cxx: g++-11 | ||||||
|             compiler: gcc |             compiler: gcc | ||||||
|             qt_version: 6.7.2 |             cppflags: '' | ||||||
|  |             ldflags: '' | ||||||
|  |             qt_version: 6.9.2 | ||||||
|             qt_arch_aqt: linux_gcc_64 |             qt_arch_aqt: linux_gcc_64 | ||||||
|             qt_arch_dir: gcc_64 |             qt_arch_dir: gcc_64 | ||||||
|             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport |             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport | ||||||
|             qt_tools: '' |             qt_tools: '' | ||||||
|             conan_arch: x86_64 |  | ||||||
|             conan_compiler: gcc |  | ||||||
|             conan_compiler_version: 11 |  | ||||||
|             conan_compiler_runtime: '' |  | ||||||
|             conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True |             conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True | ||||||
|  |             conan_profile: scwx-linux_gcc-11 | ||||||
|  |             appimage_arch: x86_64 | ||||||
|             artifact_suffix: linux-x64 |             artifact_suffix: linux-x64 | ||||||
|  |             compiler_packages: '' | ||||||
|  |           - name: linux_clang_x64 | ||||||
|  |             os: ubuntu-24.04 | ||||||
|  |             build_type: Release | ||||||
|  |             env_cc: clang-17 | ||||||
|  |             env_cxx: clang++-17 | ||||||
|  |             compiler: clang | ||||||
|  |             cppflags: '' | ||||||
|  |             ldflags: '' | ||||||
|  |             qt_version: 6.9.2 | ||||||
|  |             qt_arch_aqt: linux_gcc_64 | ||||||
|  |             qt_arch_dir: gcc_64 | ||||||
|  |             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport | ||||||
|  |             qt_tools: '' | ||||||
|  |             conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True | ||||||
|  |             conan_profile: scwx-linux_clang-17 | ||||||
|  |             appimage_arch: x86_64 | ||||||
|  |             artifact_suffix: linux-clang-x64 | ||||||
|  |             compiler_packages: clang-17 | ||||||
|  |           - name: linux_gcc_arm64 | ||||||
|  |             os: ubuntu-24.04-arm | ||||||
|  |             build_type: Release | ||||||
|  |             env_cc: gcc-11 | ||||||
|  |             env_cxx: g++-11 | ||||||
|  |             compiler: gcc | ||||||
|  |             cppflags: '' | ||||||
|  |             ldflags: '' | ||||||
|  |             qt_version: 6.9.2 | ||||||
|  |             qt_arch_aqt: linux_gcc_arm64 | ||||||
|  |             qt_arch_dir: gcc_arm64 | ||||||
|  |             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport | ||||||
|  |             qt_tools: '' | ||||||
|  |             conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True | ||||||
|  |             conan_profile: scwx-linux_gcc-11_armv8 | ||||||
|  |             appimage_arch: aarch64 | ||||||
|  |             artifact_suffix: linux-arm64 | ||||||
|  |             compiler_packages: g++-11 | ||||||
|  |           - name: macos_clang18_x64 | ||||||
|  |             os: macos-13 | ||||||
|  |             build_type: Release | ||||||
|  |             env_cc: clang | ||||||
|  |             env_cxx: clang++ | ||||||
|  |             compiler: clang | ||||||
|  |             qt_version: 6.9.2 | ||||||
|  |             qt_arch_aqt: clang_64 | ||||||
|  |             qt_arch_dir: macos | ||||||
|  |             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport | ||||||
|  |             qt_tools: '' | ||||||
|  |             conan_package_manager: '' | ||||||
|  |             conan_profile: scwx-macos_clang-18 | ||||||
|  |             appimage_arch: '' | ||||||
|  |             artifact_suffix: macos-x64 | ||||||
|  |           - name: macos_clang18_arm64 | ||||||
|  |             os: macos-14 | ||||||
|  |             build_type: Release | ||||||
|  |             env_cc: clang | ||||||
|  |             env_cxx: clang++ | ||||||
|  |             compiler: clang | ||||||
|  |             qt_version: 6.9.2 | ||||||
|  |             qt_arch_aqt: clang_64 | ||||||
|  |             qt_arch_dir: macos | ||||||
|  |             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport | ||||||
|  |             qt_tools: '' | ||||||
|  |             conan_package_manager: '' | ||||||
|  |             conan_profile: scwx-macos_clang-18_armv8 | ||||||
|  |             appimage_arch: '' | ||||||
|  |             artifact_suffix: macos-arm64 | ||||||
|     name: ${{ matrix.name }} |     name: ${{ matrix.name }} | ||||||
|     env: |     env: | ||||||
|       CC: ${{ matrix.env_cc }} |       CC: ${{ matrix.env_cc }} | ||||||
|       CXX: ${{ matrix.env_cxx }} |       CXX: ${{ matrix.env_cxx }} | ||||||
|       SCWX_VERSION: v0.4.5 |       SCWX_VERSION: v0.5.1 | ||||||
|     runs-on: ${{ matrix.os }} |     runs-on: ${{ matrix.os }} | ||||||
| 
 | 
 | ||||||
|     steps: |     steps: | ||||||
|  | @ -68,13 +135,15 @@ jobs: | ||||||
|       run: git config --global core.longpaths true |       run: git config --global core.longpaths true | ||||||
| 
 | 
 | ||||||
|     - name: Checkout |     - name: Checkout | ||||||
|       uses: actions/checkout@v4 |       uses: actions/checkout@v5 | ||||||
|       with: |       with: | ||||||
|         path: source |         path: source | ||||||
|         submodules: recursive |         submodules: recursive | ||||||
| 
 | 
 | ||||||
|     - name: Install Qt |     - name: Install Qt | ||||||
|       uses: jurplel/install-qt-action@v3 |       uses: jdpurcell/install-qt-action@v5 | ||||||
|  |       env: | ||||||
|  |         AQT_CONFIG: ${{ github.workspace }}/source/tools/aqt-settings.ini | ||||||
|       with: |       with: | ||||||
|         version: ${{ matrix.qt_version }} |         version: ${{ matrix.qt_version }} | ||||||
|         arch: ${{ matrix.qt_arch_aqt }} |         arch: ${{ matrix.qt_arch_aqt }} | ||||||
|  | @ -89,50 +158,79 @@ jobs: | ||||||
|         vsversion: ${{ matrix.msvc_version }} |         vsversion: ${{ matrix.msvc_version }} | ||||||
| 
 | 
 | ||||||
|     - name: Setup Ubuntu Environment |     - name: Setup Ubuntu Environment | ||||||
|       if: matrix.os == 'ubuntu-22.04' |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|       shell: bash |       shell: bash | ||||||
|       run: | |       run: | | ||||||
|         sudo apt-get install doxygen \ |         sudo apt-get install doxygen \ | ||||||
|                              libfuse2 \ |                              libfuse2 \ | ||||||
|                              ninja-build |                              ninja-build \ | ||||||
|  |                              wayland-protocols \ | ||||||
|  |                              libwayland-dev \ | ||||||
|  |                              libwayland-egl-backend-dev \ | ||||||
|  |                              flatpak \ | ||||||
|  |                              flatpak-builder \ | ||||||
|  |                              ${{ matrix.compiler_packages }} | ||||||
|  | 
 | ||||||
|  |     - name: Setup macOS Environment | ||||||
|  |       if: ${{ startsWith(matrix.os, 'macos') }} | ||||||
|  |       shell: bash | ||||||
|  |       run: | | ||||||
|  |         brew install llvm@18 | ||||||
|  |         LLVM_PATH=$(brew --prefix llvm@18) | ||||||
|  |         echo "CC=${LLVM_PATH}/bin/clang" >> $GITHUB_ENV | ||||||
|  |         echo "CXX=${LLVM_PATH}/bin/clang++" >> $GITHUB_ENV | ||||||
|  |         echo "CPPFLAGS=-I${LLVM_PATH}/include" >> $GITHUB_ENV | ||||||
|  |         echo "LDFLAGS=-L${LLVM_PATH}/lib -L${LLVM_PATH}/lib/c++" >> $GITHUB_ENV | ||||||
| 
 | 
 | ||||||
|     - name: Setup Python Environment |     - name: Setup Python Environment | ||||||
|       shell: pwsh |       shell: pwsh | ||||||
|       run: | |       run: | | ||||||
|         pip install geopandas ` |         pip install geopandas ` | ||||||
|                     GitPython |                     GitPython ` | ||||||
|  |                     conan | ||||||
|  | 
 | ||||||
|  |     - name: Cache Conan Packages | ||||||
|  |       uses: actions/cache@v4 | ||||||
|  |       with: | ||||||
|  |         path: ~/.conan2 | ||||||
|  |         key: build-${{ matrix.conan_profile }}-${{ hashFiles('./source/conanfile.py', './source/tools/conan/profiles/*') }} | ||||||
| 
 | 
 | ||||||
|     - name: Install Conan Packages |     - name: Install Conan Packages | ||||||
|       shell: pwsh |       shell: pwsh | ||||||
|       run: | |       run: | | ||||||
|         pip install "conan<2.0" |         conan config install ` | ||||||
|         conan profile new default --detect |           ./source/tools/conan/profiles/${{ matrix.conan_profile }} ` | ||||||
|         conan install ./source/ ` |           -tf profiles | ||||||
|  |         mkdir build | ||||||
|  |         cd build | ||||||
|  |         mkdir conan | ||||||
|  |         conan install ../source/ ` | ||||||
|           --remote conancenter ` |           --remote conancenter ` | ||||||
|           --build missing ` |           --build missing ` | ||||||
|           --settings arch=${{ matrix.conan_arch }} ` |           --profile:all ${{ matrix.conan_profile }} ` | ||||||
|           --settings build_type=${{ matrix.build_type }} ` |           --settings:all build_type=${{ matrix.build_type }} ` | ||||||
|           --settings compiler="${{ matrix.conan_compiler }}" ` |           --output-folder ./conan/ ` | ||||||
|           --settings compiler.version=${{ matrix.conan_compiler_version }} ` |  | ||||||
|           ${{ matrix.conan_compiler_runtime }} ` |  | ||||||
|           ${{ matrix.conan_package_manager }} |           ${{ matrix.conan_package_manager }} | ||||||
| 
 | 
 | ||||||
|     - name: Build Supercell Wx |     - name: Build Supercell Wx | ||||||
|       shell: pwsh |       shell: pwsh | ||||||
|       run: | |       run: | | ||||||
|         mkdir build |  | ||||||
|         cd build |         cd build | ||||||
|         cmake ../source/ ` |         cmake ../source/ ` | ||||||
|           -G Ninja ` |           -G Ninja ` | ||||||
|           -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" ` |           -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" ` | ||||||
|           -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/supercell-wx" |           -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="${{ github.workspace }}/source/external/cmake-conan/conan_provider.cmake" ` | ||||||
|  |           -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/supercell-wx" ` | ||||||
|  |           -DCONAN_HOST_PROFILE="${{ matrix.conan_profile }}" ` | ||||||
|  |           -DCONAN_BUILD_PROFILE="${{ matrix.conan_profile }}" | ||||||
|         ninja supercell-wx wxtest |         ninja supercell-wx wxtest | ||||||
| 
 | 
 | ||||||
|     - name: Separate Debug Symbols (Linux) |     - name: Separate Debug Symbols (Linux) | ||||||
|       if: matrix.os == 'ubuntu-22.04' |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|       shell: bash |       shell: bash | ||||||
|       run: | |       run: | | ||||||
|         cd build/ |         cd build/ | ||||||
|  |         cd Release/ | ||||||
|         cd bin/ |         cd bin/ | ||||||
|         objcopy --only-keep-debug supercell-wx supercell-wx.debug |         objcopy --only-keep-debug supercell-wx supercell-wx.debug | ||||||
|         objcopy --strip-debug --strip-unneeded supercell-wx |         objcopy --strip-debug --strip-unneeded supercell-wx | ||||||
|  | @ -148,7 +246,7 @@ jobs: | ||||||
|         cmake --install . --component supercell-wx |         cmake --install . --component supercell-wx | ||||||
| 
 | 
 | ||||||
|     - name: Collect Artifacts |     - name: Collect Artifacts | ||||||
|       if: matrix.os == 'ubuntu-22.04' |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|       shell: bash |       shell: bash | ||||||
|       run: | |       run: | | ||||||
|         pushd supercell-wx/ |         pushd supercell-wx/ | ||||||
|  | @ -161,6 +259,8 @@ jobs: | ||||||
|         cd plugins/ |         cd plugins/ | ||||||
|         mkdir -p sqldrivers/ |         mkdir -p sqldrivers/ | ||||||
|         cp "${RUNNER_WORKSPACE}/Qt/${{ matrix.qt_version }}/${{ matrix.qt_arch_dir }}/plugins/sqldrivers/libqsqlite.so" sqldrivers/ |         cp "${RUNNER_WORKSPACE}/Qt/${{ matrix.qt_version }}/${{ matrix.qt_arch_dir }}/plugins/sqldrivers/libqsqlite.so" sqldrivers/ | ||||||
|  |         mkdir -p platforms/ | ||||||
|  |         cp ${RUNNER_WORKSPACE}/Qt/${{ matrix.qt_version }}/${{ matrix.qt_arch_dir }}/plugins/platforms/libqwayland* platforms/ | ||||||
|         cd .. |         cd .. | ||||||
|         popd |         popd | ||||||
|         tar -czf supercell-wx-${{ matrix.artifact_suffix }}.tar.gz supercell-wx/ |         tar -czf supercell-wx-${{ matrix.artifact_suffix }}.tar.gz supercell-wx/ | ||||||
|  | @ -177,23 +277,23 @@ jobs: | ||||||
|       uses: actions/upload-artifact@v4 |       uses: actions/upload-artifact@v4 | ||||||
|       with: |       with: | ||||||
|         name: supercell-wx-debug-${{ matrix.artifact_suffix }} |         name: supercell-wx-debug-${{ matrix.artifact_suffix }} | ||||||
|         path: ${{ github.workspace }}/build/bin/*.pdb |         path: ${{ github.workspace }}/build/Release/bin/*.pdb | ||||||
| 
 | 
 | ||||||
|     - name: Upload Artifacts (Linux) |     - name: Upload Artifacts (Linux) | ||||||
|       if: matrix.os == 'ubuntu-22.04' |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|       uses: actions/upload-artifact@v4 |       uses: actions/upload-artifact@v4 | ||||||
|       with: |       with: | ||||||
|         name: supercell-wx-${{ matrix.artifact_suffix }} |         name: supercell-wx-${{ matrix.artifact_suffix }} | ||||||
|         path: ${{ github.workspace }}/supercell-wx-${{ matrix.artifact_suffix }}.tar.gz |         path: ${{ github.workspace }}/supercell-wx-${{ matrix.artifact_suffix }}.tar.gz | ||||||
| 
 | 
 | ||||||
|     - name: Upload Debug Artifacts (Linux) |     - name: Upload Debug Artifacts (Linux) | ||||||
|       if: matrix.os == 'ubuntu-22.04' |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|       uses: actions/upload-artifact@v4 |       uses: actions/upload-artifact@v4 | ||||||
|       with: |       with: | ||||||
|         name: supercell-wx-debug-${{ matrix.artifact_suffix }} |         name: supercell-wx-debug-${{ matrix.artifact_suffix }} | ||||||
|         path: | |         path: | | ||||||
|           ${{ github.workspace }}/build/bin/*.debug |           ${{ github.workspace }}/build/Release/bin/*.debug | ||||||
|           ${{ github.workspace }}/build/lib/*.debug |           ${{ github.workspace }}/build/Release/lib/*.debug | ||||||
| 
 | 
 | ||||||
|     - name: Build Installer (Windows) |     - name: Build Installer (Windows) | ||||||
|       if: matrix.os == 'windows-2022' |       if: matrix.os == 'windows-2022' | ||||||
|  | @ -210,42 +310,90 @@ jobs: | ||||||
|         path: ${{ github.workspace }}/build/supercell-wx-*.msi* |         path: ${{ github.workspace }}/build/supercell-wx-*.msi* | ||||||
| 
 | 
 | ||||||
|     - name: Build AppImage (Linux) |     - name: Build AppImage (Linux) | ||||||
|       if: matrix.os == 'ubuntu-22.04' |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|       env: |       env: | ||||||
|         APPIMAGE_DIR: ${{ github.workspace }}/supercell-wx/ |         INSTALL_DIR: ${{ github.workspace }}/supercell-wx/ | ||||||
|         LDAI_UPDATE_INFORMATION: gh-releases-zsync|dpaulat|supercell-wx|latest|*x86_64.AppImage.zsync |         APPIMAGE_DIR: ${{ github.workspace }}/supercell-wx-appimage/ | ||||||
|         LDAI_OUTPUT: supercell-wx-${{ env.SCWX_VERSION }}-x86_64.AppImage |         LDAI_UPDATE_INFORMATION: gh-releases-zsync|dpaulat|supercell-wx|latest|*${{ matrix.appimage_arch }}.AppImage.zsync | ||||||
|  |         LDAI_OUTPUT: supercell-wx-${{ env.SCWX_VERSION }}-${{ matrix.appimage_arch }}.AppImage | ||||||
|         LINUXDEPLOY_OUTPUT_APP_NAME: supercell-wx |         LINUXDEPLOY_OUTPUT_APP_NAME: supercell-wx | ||||||
|         LINUXDEPLOY_OUTPUT_VERSION: ${{ env.SCWX_VERSION }} |         LINUXDEPLOY_OUTPUT_VERSION: ${{ env.SCWX_VERSION }} | ||||||
|       shell: bash |       shell: bash | ||||||
|       run: | |       run: | | ||||||
|         wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage |         wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${{ matrix.appimage_arch }}.AppImage | ||||||
|         chmod +x linuxdeploy-x86_64.AppImage |         chmod +x linuxdeploy-${{ matrix.appimage_arch }}.AppImage | ||||||
|         cp "${{ github.workspace }}/source/scwx-qt/res/icons/scwx-256.png" supercell-wx.png |         cp "${{ github.workspace }}/source/scwx-qt/res/icons/scwx-256.png" supercell-wx.png | ||||||
|         cp "${{ github.workspace }}/source/scwx-qt/res/linux/supercell-wx.desktop" . |         cp "${{ github.workspace }}/source/scwx-qt/res/linux/supercell-wx.desktop" . | ||||||
|  |         cp -r "${{ env.INSTALL_DIR }}" "${{ env.APPIMAGE_DIR }}" | ||||||
|         pushd "${{ env.APPIMAGE_DIR }}" |         pushd "${{ env.APPIMAGE_DIR }}" | ||||||
|         mkdir -p usr/ |         mkdir -p usr/ | ||||||
|         mv bin/ usr/ |         mv bin/ usr/ | ||||||
|         mv lib/ usr/ |         mv lib/ usr/ | ||||||
|         mv plugins/ usr/ |         mv plugins/ usr/ | ||||||
|         popd |         popd | ||||||
|         ./linuxdeploy-x86_64.AppImage --appdir ${{ env.APPIMAGE_DIR }} -i supercell-wx.png -d supercell-wx.desktop |         ./linuxdeploy-${{ matrix.appimage_arch }}.AppImage --appdir ${{ env.APPIMAGE_DIR }} -i supercell-wx.png -d supercell-wx.desktop | ||||||
|         ./linuxdeploy-x86_64.AppImage --appdir ${{ env.APPIMAGE_DIR }} --output appimage |         ./linuxdeploy-${{ matrix.appimage_arch }}.AppImage --appdir ${{ env.APPIMAGE_DIR }} --output appimage | ||||||
|         rm -f linuxdeploy-x86_64.AppImage |         rm -f linuxdeploy-${{ matrix.appimage_arch }}.AppImage | ||||||
| 
 | 
 | ||||||
|     - name: Upload AppImage (Linux) |     - name: Upload AppImage (Linux) | ||||||
|       if: matrix.os == 'ubuntu-22.04' |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|       uses: actions/upload-artifact@v4 |       uses: actions/upload-artifact@v4 | ||||||
|       with: |       with: | ||||||
|         name: supercell-wx-appimage-x64 |         name: supercell-wx-appimage-${{ matrix.artifact_suffix }} | ||||||
|         path: ${{ github.workspace }}/*-x86_64.AppImage* |         path: ${{ github.workspace }}/*-${{ matrix.appimage_arch }}.AppImage* | ||||||
|  | 
 | ||||||
|  |     - name: Build FlatPak (Linux) | ||||||
|  |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|  |       env: | ||||||
|  |         INSTALL_DIR: ${{ github.workspace }}/supercell-wx/ | ||||||
|  |         FLATPAK_DIR: ${{ github.workspace }}/supercell-wx-flatpak/ | ||||||
|  |       shell: bash | ||||||
|  |       run: | | ||||||
|  |         cp -r ${{ env.INSTALL_DIR }} ${{ env.FLATPAK_DIR }} | ||||||
|  |         # Copy krb5 libraries to flatpak | ||||||
|  |         cp /usr/lib/*/libkrb5.so* \ | ||||||
|  |            /usr/lib/*/libkrb5support.so* \ | ||||||
|  |            /usr/lib/*/libgssapi_krb5.so* \ | ||||||
|  |            /usr/lib/*/libk5crypto.so* \ | ||||||
|  |            /usr/lib/*/libkeyutils.so* \ | ||||||
|  |            ${{ env.FLATPAK_DIR }}/lib | ||||||
|  | 
 | ||||||
|  |         flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo | ||||||
|  |         flatpak-builder --force-clean \ | ||||||
|  |             --user \ | ||||||
|  |             --install-deps-from=flathub \ | ||||||
|  |             --repo=flatpak-repo \ | ||||||
|  |             --install flatpak-build \ | ||||||
|  |             ${{ github.workspace }}/source/tools/net.supercellwx.app.yml | ||||||
|  |         flatpak build-bundle flatpak-repo supercell-wx.flatpak net.supercellwx.app | ||||||
|  | 
 | ||||||
|  |     - name: Upload FlatPak (Linux) | ||||||
|  |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|  |       uses: actions/upload-artifact@v4 | ||||||
|  |       with: | ||||||
|  |         name: supercell-wx-flatpak-${{ matrix.artifact_suffix }} | ||||||
|  |         path: ${{ github.workspace }}/supercell-wx.flatpak | ||||||
|  | 
 | ||||||
|  |     - name: Build Disk Image (macOS) | ||||||
|  |       if: ${{ startsWith(matrix.os, 'macos') }} | ||||||
|  |       shell: pwsh | ||||||
|  |       run: | | ||||||
|  |         cd build | ||||||
|  |         cpack | ||||||
|  | 
 | ||||||
|  |     - name: Upload Disk Image (macOS) | ||||||
|  |       if: ${{ startsWith(matrix.os, 'macos') }} | ||||||
|  |       uses: actions/upload-artifact@v4 | ||||||
|  |       with: | ||||||
|  |         name: supercell-wx-${{ matrix.artifact_suffix }} | ||||||
|  |         path: ${{ github.workspace }}/build/supercell-wx-*.dmg* | ||||||
| 
 | 
 | ||||||
|     - name: Test Supercell Wx |     - name: Test Supercell Wx | ||||||
|       working-directory: ${{ github.workspace }}/build |       working-directory: ${{ github.workspace }}/build | ||||||
|       env: |       env: | ||||||
|         MAPBOX_API_KEY:   ${{ secrets.MAPBOX_API_KEY }} |         MAPBOX_API_KEY:   ${{ secrets.MAPBOX_API_KEY }} | ||||||
|         MAPTILER_API_KEY: ${{ secrets.MAPTILER_API_KEY }} |         MAPTILER_API_KEY: ${{ secrets.MAPTILER_API_KEY }} | ||||||
|       run: ctest -C ${{ matrix.build_type }} --exclude-regex test_mln.* |       run: ctest -C ${{ matrix.build_type }} --exclude-regex "test_mln.*|NtpClient.*|UpdateManager.*" | ||||||
| 
 | 
 | ||||||
|     - name: Upload Test Logs |     - name: Upload Test Logs | ||||||
|       if: ${{ !cancelled() }} |       if: ${{ !cancelled() }} | ||||||
|  |  | ||||||
							
								
								
									
										42
									
								
								.github/workflows/clang-format-check.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,42 @@ | ||||||
|  | name: clang-format-check | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   workflow_dispatch: | ||||||
|  |   pull_request: | ||||||
|  |     branches: | ||||||
|  |       - 'develop' | ||||||
|  | 
 | ||||||
|  | concurrency: | ||||||
|  |   # Cancel in-progress jobs for the same pull request | ||||||
|  |   group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | ||||||
|  |   cancel-in-progress: true | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   format: | ||||||
|  |     runs-on: ubuntu-24.04 | ||||||
|  |     steps: | ||||||
|  | 
 | ||||||
|  |     - name: Checkout | ||||||
|  |       uses: actions/checkout@v5 | ||||||
|  |       with: | ||||||
|  |         fetch-depth: 0 | ||||||
|  |         submodules: false | ||||||
|  | 
 | ||||||
|  |     - name: Update References | ||||||
|  |       shell: bash | ||||||
|  |       run: | | ||||||
|  |         git fetch origin develop | ||||||
|  | 
 | ||||||
|  |     - name: Setup Ubuntu Environment | ||||||
|  |       shell: bash | ||||||
|  |       run: | | ||||||
|  |         sudo apt-get install clang-format-19 | ||||||
|  |         sudo rm -f /usr/bin/clang-format | ||||||
|  |         sudo ln -s /usr/bin/clang-format-19 /usr/bin/clang-format | ||||||
|  | 
 | ||||||
|  |     - name: Check Formatting | ||||||
|  |       shell: bash | ||||||
|  |       run: | | ||||||
|  |         MERGE_BASE=$(git merge-base origin/develop ${{ github.event.pull_request.head.sha || github.ref }}) | ||||||
|  |         echo "Comparing against ${MERGE_BASE}" | ||||||
|  |         git clang-format-19 --diff --style=file -v ${MERGE_BASE} | ||||||
							
								
								
									
										21
									
								
								.github/workflows/clang-tidy-comments.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,21 @@ | ||||||
|  | name: Post clang-tidy Review Comments | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   workflow_run: | ||||||
|  |     workflows: ["clang-tidy-review"] | ||||||
|  |     types: | ||||||
|  |       - completed | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     if: ${{ github.event.workflow_run.conclusion != 'cancelled' }} | ||||||
|  | 
 | ||||||
|  |     steps: | ||||||
|  |       - name: Post Comments | ||||||
|  |         uses: ZedThree/clang-tidy-review/post@v0.21.0 | ||||||
|  |         with: | ||||||
|  |           lgtm_comment_body: '' | ||||||
|  |           annotations: false | ||||||
|  |           max_comments: 25 | ||||||
|  |           num_comments_as_exitcode: false | ||||||
							
								
								
									
										152
									
								
								.github/workflows/clang-tidy-review.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,152 @@ | ||||||
|  | name: clang-tidy-review | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   pull_request: | ||||||
|  |     branches: | ||||||
|  |       - 'develop' | ||||||
|  | 
 | ||||||
|  | concurrency: | ||||||
|  |   # Cancel in-progress jobs for the same pull request | ||||||
|  |   group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | ||||||
|  |   cancel-in-progress: true | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |     strategy: | ||||||
|  |       matrix: | ||||||
|  |         include: | ||||||
|  |           - name: linux_clang-tidy_x64 | ||||||
|  |             os: ubuntu-24.04 | ||||||
|  |             build_type: Release | ||||||
|  |             env_cc: clang-18 | ||||||
|  |             env_cxx: clang++-18 | ||||||
|  |             qt_version: 6.9.2 | ||||||
|  |             qt_arch_aqt: linux_gcc_64 | ||||||
|  |             qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport | ||||||
|  |             qt_tools: '' | ||||||
|  |             conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True | ||||||
|  |             conan_profile: scwx-linux_clang-18 | ||||||
|  |             compiler_packages: clang-18 clang-tidy-18 | ||||||
|  |             clang_tidy_binary: clang-tidy-18 | ||||||
|  |     name: ${{ matrix.name }} | ||||||
|  |     runs-on: ${{ matrix.os }} | ||||||
|  |     env: | ||||||
|  |       CC: ${{ matrix.env_cc }} | ||||||
|  |       CXX: ${{ matrix.env_cxx }} | ||||||
|  |     steps: | ||||||
|  | 
 | ||||||
|  |     - name: Checkout | ||||||
|  |       uses: actions/checkout@v5 | ||||||
|  |       with: | ||||||
|  |         path: source | ||||||
|  |         submodules: recursive | ||||||
|  | 
 | ||||||
|  |     - name: Checkout clang-tidy-review Repository | ||||||
|  |       uses: actions/checkout@v5 | ||||||
|  |       with: | ||||||
|  |         repository: ZedThree/clang-tidy-review | ||||||
|  |         ref: v0.20.1 | ||||||
|  |         path: clang-tidy-review | ||||||
|  | 
 | ||||||
|  |     - name: Install Qt | ||||||
|  |       uses: jdpurcell/install-qt-action@v5 | ||||||
|  |       env: | ||||||
|  |         AQT_CONFIG: ${{ github.workspace }}/source/tools/aqt-settings.ini | ||||||
|  |       with: | ||||||
|  |         version: ${{ matrix.qt_version }} | ||||||
|  |         arch: ${{ matrix.qt_arch_aqt }} | ||||||
|  |         modules: ${{ matrix.qt_modules }} | ||||||
|  |         tools: ${{ matrix.qt_tools }} | ||||||
|  | 
 | ||||||
|  |     - name: Setup Ubuntu Environment | ||||||
|  |       if: ${{ startsWith(matrix.os, 'ubuntu') }} | ||||||
|  |       shell: bash | ||||||
|  |       run: | | ||||||
|  |         sudo apt-get install doxygen \ | ||||||
|  |                              libfuse2 \ | ||||||
|  |                              ninja-build \ | ||||||
|  |                              wayland-protocols \ | ||||||
|  |                              libwayland-dev \ | ||||||
|  |                              libwayland-egl-backend-dev \ | ||||||
|  |                              ${{ matrix.compiler_packages }} | ||||||
|  | 
 | ||||||
|  |     - name: Setup Python Environment | ||||||
|  |       shell: pwsh | ||||||
|  |       run: | | ||||||
|  |         pip install geopandas ` | ||||||
|  |                     GitPython ` | ||||||
|  |                     conan | ||||||
|  |         pip install --break-system-packages clang-tidy-review/post/clang_tidy_review | ||||||
|  | 
 | ||||||
|  |     - name: Cache Conan Packages | ||||||
|  |       uses: actions/cache@v4 | ||||||
|  |       with: | ||||||
|  |         path: ~/.conan2 | ||||||
|  |         key: build-${{ matrix.conan_profile }}-${{ hashFiles('./source/conanfile.py', './source/tools/conan/profiles/*') }} | ||||||
|  | 
 | ||||||
|  |     - name: Install Conan Packages | ||||||
|  |       shell: pwsh | ||||||
|  |       run: | | ||||||
|  |         conan config install ` | ||||||
|  |           ./source/tools/conan/profiles/${{ matrix.conan_profile }} ` | ||||||
|  |           -tf profiles | ||||||
|  |         mkdir build | ||||||
|  |         cd build | ||||||
|  |         mkdir conan | ||||||
|  |         conan install ../source/ ` | ||||||
|  |           --remote conancenter ` | ||||||
|  |           --build missing ` | ||||||
|  |           --profile:all ${{ matrix.conan_profile }} ` | ||||||
|  |           --settings:all build_type=${{ matrix.build_type }} ` | ||||||
|  |           --output-folder ./conan/ ` | ||||||
|  |           ${{ matrix.conan_package_manager }} | ||||||
|  | 
 | ||||||
|  |     - name: Autogenerate | ||||||
|  |       shell: pwsh | ||||||
|  |       run: | | ||||||
|  |         cd build | ||||||
|  |         cmake ../source/ ` | ||||||
|  |           -G Ninja ` | ||||||
|  |           -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" ` | ||||||
|  |           -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="${{ github.workspace }}/source/external/cmake-conan/conan_provider.cmake" ` | ||||||
|  |           -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/supercell-wx" ` | ||||||
|  |           -DCONAN_HOST_PROFILE="${{ matrix.conan_profile }}" ` | ||||||
|  |           -DCONAN_BUILD_PROFILE="${{ matrix.conan_profile }}" ` | ||||||
|  |           -DCMAKE_EXPORT_COMPILE_COMMANDS=on | ||||||
|  |         ninja glad_gl_core_33 ` | ||||||
|  |               scwx-qt_generate_counties_db ` | ||||||
|  |               scwx-qt_generate_versions ` | ||||||
|  |               scwx-qt_autogen | ||||||
|  | 
 | ||||||
|  |     - name: Code Review | ||||||
|  |       id: review | ||||||
|  |       shell: bash | ||||||
|  |       run: | | ||||||
|  |         cd source | ||||||
|  |         review --clang_tidy_binary=${{ matrix.clang_tidy_binary }} \ | ||||||
|  |                --token=${{ github.token }} \ | ||||||
|  |                --repo='${{ github.repository }}' \ | ||||||
|  |                --pr='${{ github.event.pull_request.number }}' \ | ||||||
|  |                --build_dir='../build' \ | ||||||
|  |                --base_dir='${{ github.workspace }}/source' \ | ||||||
|  |                --clang_tidy_checks='' \ | ||||||
|  |                --config_file='' \ | ||||||
|  |                --include='*.[ch],*.[ch]xx,*.[chi]pp,*.[ch]++,*.cc,*.hh' \ | ||||||
|  |                --exclude='' \ | ||||||
|  |                --apt-packages='' \ | ||||||
|  |                --cmake-command='' \ | ||||||
|  |                --max-comments=25 \ | ||||||
|  |                --lgtm-comment-body='' \ | ||||||
|  |                --split_workflow=true \ | ||||||
|  |                --annotations=false \ | ||||||
|  |                --parallel=0 | ||||||
|  |         rsync -avzh --ignore-missing-args clang-tidy-review-output.json ../ | ||||||
|  |         rsync -avzh --ignore-missing-args clang-tidy-review-metadata.json ../ | ||||||
|  |         rsync -avzh --ignore-missing-args clang_fixes.json ../ | ||||||
|  | 
 | ||||||
|  |     - name: Upload Review | ||||||
|  |       uses: ZedThree/clang-tidy-review/upload@v0.21.0 | ||||||
|  | 
 | ||||||
|  |     - name: Status Check | ||||||
|  |       if: steps.review.outputs.total_comments > 0 | ||||||
|  |       run: exit 1 | ||||||
							
								
								
									
										11
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -5,9 +5,20 @@ CMakeLists.txt.user | ||||||
| CMakeCache.txt | CMakeCache.txt | ||||||
| CMakeFiles | CMakeFiles | ||||||
| CMakeScripts | CMakeScripts | ||||||
|  | CMakeUserPresets.json | ||||||
| Testing | Testing | ||||||
| cmake_install.cmake | cmake_install.cmake | ||||||
| install_manifest.txt | install_manifest.txt | ||||||
| compile_commands.json | compile_commands.json | ||||||
| CTestTestfile.cmake | CTestTestfile.cmake | ||||||
| _deps | _deps | ||||||
|  | 
 | ||||||
|  | # Editor directories | ||||||
|  | .idea/ | ||||||
|  | .vs/ | ||||||
|  | 
 | ||||||
|  | # Python Virtual Environment | ||||||
|  | .venv/ | ||||||
|  | 
 | ||||||
|  | # Specific excludes for Supercell Wx | ||||||
|  | tools/lib/user-setup.sh | ||||||
|  |  | ||||||
							
								
								
									
										60
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,39 +1,45 @@ | ||||||
| [submodule "external/cmake-conan"] |  | ||||||
| 	path = external/cmake-conan |  | ||||||
| 	url = https://github.com/conan-io/cmake-conan.git |  | ||||||
| [submodule "test/data"] |  | ||||||
| 	path = test/data |  | ||||||
| 	url = https://github.com/dpaulat/supercell-wx-test-data |  | ||||||
| [submodule "external/hsluv-c"] |  | ||||||
| 	path = external/hsluv-c |  | ||||||
| 	url = https://github.com/hsluv/hsluv-c.git |  | ||||||
| [submodule "external/stb"] |  | ||||||
| 	path = external/stb |  | ||||||
| 	url = https://github.com/nothings/stb.git |  | ||||||
| [submodule "data"] | [submodule "data"] | ||||||
| 	path = data | 	path = data | ||||||
| 	url = https://github.com/dpaulat/supercell-wx-data | 	url = https://github.com/dpaulat/supercell-wx-data | ||||||
|  | [submodule "external/aws-sdk-cpp"] | ||||||
|  | 	path = external/aws-sdk-cpp | ||||||
|  | 	url = https://github.com/aws/aws-sdk-cpp.git | ||||||
|  | [submodule "external/cmake-conan"] | ||||||
|  | 	path = external/cmake-conan | ||||||
|  | 	url = https://github.com/conan-io/cmake-conan.git | ||||||
|  | [submodule "external/date"] | ||||||
|  | 	path = external/date | ||||||
|  | 	url = https://github.com/HowardHinnant/date.git | ||||||
|  | [submodule "external/glad"] | ||||||
|  | 	path = external/glad | ||||||
|  | 	url = https://github.com/Dav1dde/glad.git | ||||||
|  | [submodule "external/hsluv-c"] | ||||||
|  | 	path = external/hsluv-c | ||||||
|  | 	url = https://github.com/hsluv/hsluv-c.git | ||||||
| [submodule "external/imgui"] | [submodule "external/imgui"] | ||||||
| 	path = external/imgui | 	path = external/imgui | ||||||
| 	url = https://github.com/ocornut/imgui.git | 	url = https://github.com/ocornut/imgui.git | ||||||
| [submodule "external/imgui-backend-qt"] | [submodule "external/imgui-backend-qt"] | ||||||
| 	path = external/imgui-backend-qt | 	path = external/imgui-backend-qt | ||||||
| 	url = https://github.com/dpaulat/imgui-backend-qt | 	url = https://github.com/dpaulat/imgui-backend-qt | ||||||
| [submodule "external/aws-sdk-cpp"] |  | ||||||
| 	path = external/aws-sdk-cpp |  | ||||||
| 	url = https://github.com/aws/aws-sdk-cpp.git |  | ||||||
| [submodule "external/date"] |  | ||||||
| 	path = external/date |  | ||||||
| 	url = https://github.com/HowardHinnant/date.git |  | ||||||
| [submodule "external/units"] |  | ||||||
| 	path = external/units |  | ||||||
| 	url = https://github.com/nholthaus/units.git |  | ||||||
| [submodule "external/textflowcpp"] |  | ||||||
| 	path = external/textflowcpp |  | ||||||
| 	url = https://github.com/catchorg/textflowcpp.git |  | ||||||
| [submodule "external/maplibre-native-qt"] |  | ||||||
| 	path = external/maplibre-native-qt |  | ||||||
| 	url = https://github.com/dpaulat/maplibre-native-qt.git |  | ||||||
| [submodule "external/maplibre-native"] | [submodule "external/maplibre-native"] | ||||||
| 	path = external/maplibre-native | 	path = external/maplibre-native | ||||||
| 	url = https://github.com/dpaulat/maplibre-gl-native.git | 	url = https://github.com/dpaulat/maplibre-gl-native.git | ||||||
|  | [submodule "external/maplibre-native-qt"] | ||||||
|  | 	path = external/maplibre-native-qt | ||||||
|  | 	url = https://github.com/dpaulat/maplibre-native-qt.git | ||||||
|  | [submodule "external/qt6ct"] | ||||||
|  | 	path = external/qt6ct | ||||||
|  | 	url = https://github.com/AdenKoperczak/qt6ct.git | ||||||
|  | [submodule "external/stb"] | ||||||
|  | 	path = external/stb | ||||||
|  | 	url = https://github.com/nothings/stb.git | ||||||
|  | [submodule "external/textflowcpp"] | ||||||
|  | 	path = external/textflowcpp | ||||||
|  | 	url = https://github.com/catchorg/textflowcpp.git | ||||||
|  | [submodule "external/units"] | ||||||
|  | 	path = external/units | ||||||
|  | 	url = https://github.com/nholthaus/units.git | ||||||
|  | [submodule "test/data"] | ||||||
|  | 	path = test/data | ||||||
|  | 	url = https://github.com/dpaulat/supercell-wx-test-data | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ Supercell Wx uses code from the following dependencies: | ||||||
| | [FreeType GL](https://github.com/rougier/freetype-gl) | [BSD 2-Clause with views sentence](https://spdx.org/licenses/BSD-2-Clause-Views.html) | | | [FreeType GL](https://github.com/rougier/freetype-gl) | [BSD 2-Clause with views sentence](https://spdx.org/licenses/BSD-2-Clause-Views.html) | | ||||||
| | [GeographicLib](https://geographiclib.sourceforge.io/) | [MIT License](https://spdx.org/licenses/MIT.html) | | | [GeographicLib](https://geographiclib.sourceforge.io/) | [MIT License](https://spdx.org/licenses/MIT.html) | | ||||||
| | [geos](https://libgeos.org/) | [GNU Lesser General Public License v2.1 or later](https://spdx.org/licenses/LGPL-2.1-or-later.html) | | | [geos](https://libgeos.org/) | [GNU Lesser General Public License v2.1 or later](https://spdx.org/licenses/LGPL-2.1-or-later.html) | | ||||||
| | [GLEW](https://www.opengl.org/sdk/libs/GLEW/) | [MIT License](https://spdx.org/licenses/MIT.html) | | | [GLAD](https://github.com/Dav1dde/glad) | [MIT License](https://spdx.org/licenses/MIT.html) | | ||||||
| | [GLM](https://github.com/g-truc/glm) | [MIT License](https://spdx.org/licenses/MIT.html) | | | [GLM](https://github.com/g-truc/glm) | [MIT License](https://spdx.org/licenses/MIT.html) | | ||||||
| | [GoogleTest](https://google.github.io/googletest/) | [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html) | | | [GoogleTest](https://google.github.io/googletest/) | [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html) | | ||||||
| | [HSLuv](https://www.hsluv.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | | | [HSLuv](https://www.hsluv.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | | ||||||
|  | @ -32,9 +32,12 @@ Supercell Wx uses code from the following dependencies: | ||||||
| | [libpng](http://libpng.org/pub/png/libpng.html) | [PNG Reference Library version 2](https://spdx.org/licenses/libpng-2.0.html) | | | [libpng](http://libpng.org/pub/png/libpng.html) | [PNG Reference Library version 2](https://spdx.org/licenses/libpng-2.0.html) | | ||||||
| | [libxml2](http://xmlsoft.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | | | [libxml2](http://xmlsoft.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | | ||||||
| | [MapLibre Native](https://maplibre.org/projects/maplibre-native/) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) | | | [MapLibre Native](https://maplibre.org/projects/maplibre-native/) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) | | ||||||
|  | | [Mesa 3D](https://mesa3d.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | | ||||||
| | [nunicode](https://bitbucket.org/alekseyt/nunicode/src/master/) | [MIT License](https://spdx.org/licenses/MIT.html) | Modified for MapLibre Native | | | [nunicode](https://bitbucket.org/alekseyt/nunicode/src/master/) | [MIT License](https://spdx.org/licenses/MIT.html) | Modified for MapLibre Native | | ||||||
| | [OpenSSL](https://www.openssl.org/) | [OpenSSL License](https://spdx.org/licenses/OpenSSL.html) | | | [OpenSSL](https://www.openssl.org/) | [OpenSSL License](https://spdx.org/licenses/OpenSSL.html) | | ||||||
| | [Qt](https://www.qt.io/) | [GNU Lesser General Public License v3.0 only](https://spdx.org/licenses/LGPL-3.0-only.html) | Qt Core, Qt GUI, Qt Multimedia, Qt Network, Qt OpenGL, Qt Positioning, Qt Serial Port, Qt SQL, Qt SVG, Qt Widgets<br/>Additional Licenses: https://doc.qt.io/qt-6/licenses-used-in-qt.html | | | [Qt](https://www.qt.io/) | [GNU Lesser General Public License v3.0 only](https://spdx.org/licenses/LGPL-3.0-only.html) | Qt Core, Qt GUI, Qt Multimedia, Qt Network, Qt OpenGL, Qt Positioning, Qt Serial Port, Qt SQL, Qt SVG, Qt Widgets<br/>Additional Licenses: https://doc.qt.io/qt-6/licenses-used-in-qt.html | | ||||||
|  | | [qt6ct](https://github.com/trialuser02/qt6ct) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) | | ||||||
|  | | [range-v3](https://github.com/ericniebler/range-v3) | [Boost Software License 1.0](https://spdx.org/licenses/BSL-1.0.html)<br/>[MIT License](https://spdx.org/licenses/MIT.html)<br/>[Stepanov and McJones, "Elements of Programming" license](https://github.com/ericniebler/range-v3/tree/0.12.0?tab=License-1-ov-file)<br/>[SGI C++ Standard Template Library license](https://github.com/ericniebler/range-v3/tree/0.12.0?tab=License-1-ov-file) | | ||||||
| | [re2](https://github.com/google/re2) | [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html) | | | [re2](https://github.com/google/re2) | [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html) | | ||||||
| | [spdlog](https://github.com/gabime/spdlog) | [MIT License](https://spdx.org/licenses/MIT.html) | | | [spdlog](https://github.com/gabime/spdlog) | [MIT License](https://spdx.org/licenses/MIT.html) | | ||||||
| | [SQLite](https://www.sqlite.org/) | Public Domain | | | [SQLite](https://www.sqlite.org/) | Public Domain | | ||||||
|  | @ -67,6 +70,7 @@ Supercell Wx uses assets from the following sources: | ||||||
| | [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License | | | [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License | | ||||||
| | [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | SIL Open Font License | | | [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | SIL Open Font License | | ||||||
| | [NOAA's Weather and Climate Toolkit](https://www.ncdc.noaa.gov/wct/) | Public Domain | Default Color Tables | | | [NOAA's Weather and Climate Toolkit](https://www.ncdc.noaa.gov/wct/) | Public Domain | Default Color Tables | | ||||||
|  | | [qt6ct](https://github.com/trialuser02/qt6ct) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) | | ||||||
| | [Roboto Flex](https://fonts.google.com/specimen/Roboto+Flex) | SIL Open Font License | | | [Roboto Flex](https://fonts.google.com/specimen/Roboto+Flex) | SIL Open Font License | | ||||||
| | [Supercell thunderstorm with dramatic clouds](https://www.shutterstock.com/image-photo/supercell-thunderstorm-dramatic-clouds-1354353521) | Shutterstock Standard License | Photo by John Sirlin | | [Supercell thunderstorm with dramatic clouds](https://www.shutterstock.com/image-photo/supercell-thunderstorm-dramatic-clouds-1354353521) | Shutterstock Standard License | Photo by John Sirlin | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,14 @@ | ||||||
| cmake_minimum_required(VERSION 3.21) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME supercell-wx) | set(PROJECT_NAME supercell-wx) | ||||||
|  | 
 | ||||||
|  | include(tools/scwx_config.cmake) | ||||||
|  | 
 | ||||||
|  | set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0) | ||||||
|  | 
 | ||||||
|  | scwx_python_setup() | ||||||
|  | 
 | ||||||
| project(${PROJECT_NAME} | project(${PROJECT_NAME} | ||||||
|         VERSION      0.4.5 |         VERSION      0.5.1 | ||||||
|         DESCRIPTION  "Supercell Wx is a free, open source advanced weather radar viewer." |         DESCRIPTION  "Supercell Wx is a free, open source advanced weather radar viewer." | ||||||
|         HOMEPAGE_URL "https://github.com/dpaulat/supercell-wx" |         HOMEPAGE_URL "https://github.com/dpaulat/supercell-wx" | ||||||
|         LANGUAGES    C CXX) |         LANGUAGES    C CXX) | ||||||
|  | @ -11,40 +18,21 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) | ||||||
| set(CMAKE_POLICY_DEFAULT_CMP0079 NEW) | set(CMAKE_POLICY_DEFAULT_CMP0079 NEW) | ||||||
| set(CMAKE_POLICY_DEFAULT_CMP0148 OLD) # aws-sdk-cpp uses FindPythonInterp | set(CMAKE_POLICY_DEFAULT_CMP0148 OLD) # aws-sdk-cpp uses FindPythonInterp | ||||||
| 
 | 
 | ||||||
|  | scwx_output_dirs_setup() | ||||||
|  | 
 | ||||||
| enable_testing() | enable_testing() | ||||||
| 
 | 
 | ||||||
| set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) | set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) | ||||||
| 
 | 
 | ||||||
| include(${PROJECT_SOURCE_DIR}/external/cmake-conan/conan.cmake) |  | ||||||
| 
 |  | ||||||
| set_property(DIRECTORY | set_property(DIRECTORY | ||||||
|              APPEND |              APPEND | ||||||
|              PROPERTY CMAKE_CONFIGURE_DEPENDS |              PROPERTY CMAKE_CONFIGURE_DEPENDS | ||||||
|              conanfile.py) |              conanfile.py) | ||||||
| 
 | 
 | ||||||
| # Don't use RelWithDebInfo Conan packages |  | ||||||
| if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") |  | ||||||
|     set(conan_build_type "Release") |  | ||||||
| else() |  | ||||||
|     set(conan_build_type ${CMAKE_BUILD_TYPE}) |  | ||||||
| endif() |  | ||||||
| 
 |  | ||||||
| conan_cmake_autodetect(settings |  | ||||||
|                        BUILD_TYPE ${conan_build_type}) |  | ||||||
| 
 |  | ||||||
| conan_cmake_install(PATH_OR_REFERENCE ${PROJECT_SOURCE_DIR} |  | ||||||
|                     BUILD missing |  | ||||||
|                     REMOTE conancenter |  | ||||||
|                     SETTINGS ${settings}) |  | ||||||
| 
 |  | ||||||
| include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) |  | ||||||
| include(${CMAKE_BINARY_DIR}/conan_paths.cmake) |  | ||||||
| conan_basic_setup(TARGETS) |  | ||||||
| 
 |  | ||||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ALL_NO_LIB") | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ALL_NO_LIB") | ||||||
| 
 | 
 | ||||||
| set(SCWX_DIR ${PROJECT_SOURCE_DIR}) | set(SCWX_DIR ${PROJECT_SOURCE_DIR}) | ||||||
| set(SCWX_VERSION "0.4.5") | set(SCWX_VERSION "0.5.1") | ||||||
| 
 | 
 | ||||||
| option(SCWX_ADDRESS_SANITIZER "Build with Address Sanitizer" OFF) | option(SCWX_ADDRESS_SANITIZER "Build with Address Sanitizer" OFF) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										383
									
								
								CMakePresets.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,383 @@ | ||||||
|  | { | ||||||
|  |   "version": 5, | ||||||
|  |   "cmakeMinimumRequired": { | ||||||
|  |     "major": 3, | ||||||
|  |     "minor": 24, | ||||||
|  |     "patch": 0 | ||||||
|  |   }, | ||||||
|  |   "configurePresets": [ | ||||||
|  |     { | ||||||
|  |       "name": "base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "generator": "Ninja", | ||||||
|  |       "binaryDir": "${sourceDir}/build/${presetName}", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "${sourceDir}/external/cmake-conan/conan_provider.cmake", | ||||||
|  |         "SCWX_VIRTUAL_ENV": "${sourceDir}/.venv" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-base", | ||||||
|  |       "inherits": "base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "generator": "Visual Studio 17 2022", | ||||||
|  |       "condition": { | ||||||
|  |         "type": "equals", | ||||||
|  |         "lhs": "${hostSystemName}", | ||||||
|  |         "rhs": "Windows" | ||||||
|  |       }, | ||||||
|  |       "vendor": { | ||||||
|  |         "microsoft.com/VisualStudioSettings/CMake/1.0": { | ||||||
|  |           "hostOS": [ | ||||||
|  |             "Windows" | ||||||
|  |           ] | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-x64-base", | ||||||
|  |       "inherits": "windows-base", | ||||||
|  |       "hidden": true | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-base", | ||||||
|  |       "inherits": "base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "condition": { | ||||||
|  |         "type": "equals", | ||||||
|  |         "lhs": "${hostSystemName}", | ||||||
|  |         "rhs": "Linux" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-base", | ||||||
|  |       "inherits": "windows-x64-base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_PREFIX_PATH": "C:/Qt/6.9.2/msvc2022_64" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-ninja-base", | ||||||
|  |       "inherits": "windows-msvc2022-x64-base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "generator": "Ninja", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_PREFIX_PATH": "C:/Qt/6.9.2/msvc2022_64" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-base", | ||||||
|  |       "inherits": "linux-base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_PREFIX_PATH": "/opt/Qt/6.9.2/gcc_64" | ||||||
|  |       }, | ||||||
|  |       "environment": { | ||||||
|  |         "CC": "gcc-11", | ||||||
|  |         "CXX": "g++-11" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-debug", | ||||||
|  |       "inherits": "windows-msvc2022-x64-base", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Debug", | ||||||
|  |       "architecture": { | ||||||
|  |         "value": "x64", | ||||||
|  |         "strategy": "external" | ||||||
|  |       }, | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Debug", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64-debug", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64-debug" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-release", | ||||||
|  |       "inherits": "windows-msvc2022-x64-base", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Release", | ||||||
|  |       "architecture": { | ||||||
|  |         "value": "x64", | ||||||
|  |         "strategy": "external" | ||||||
|  |       }, | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-ninja-debug", | ||||||
|  |       "inherits": "windows-msvc2022-x64-ninja-base", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Ninja Debug", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Debug", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64-debug", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64-debug" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-ninja-release", | ||||||
|  |       "inherits": "windows-msvc2022-x64-ninja-base", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Ninja Release", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-debug", | ||||||
|  |       "inherits": "linux-gcc-base", | ||||||
|  |       "displayName": "Linux GCC Debug", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Debug", | ||||||
|  |         "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Debug/supercell-wx", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-linux_gcc-11-debug", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11-debug" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-release", | ||||||
|  |       "inherits": "linux-gcc-base", | ||||||
|  |       "displayName": "Linux GCC Release", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Release/supercell-wx", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-linux_gcc-11", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-debug-asan", | ||||||
|  |       "inherits": "linux-gcc-base", | ||||||
|  |       "displayName": "Linux GCC Debug Address Sanitizer", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Debug", | ||||||
|  |         "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Debug/supercell-wx", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-linux_gcc-11-debug", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11-debug", | ||||||
|  |         "SCWX_ADDRESS_SANITIZER": { | ||||||
|  |           "type": "BOOL", | ||||||
|  |           "value": "ON" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-release-asan", | ||||||
|  |       "inherits": "linux-gcc-base", | ||||||
|  |       "displayName": "Linux GCC Release Address Sanitizer", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Release/supercell-wx", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-linux_gcc-11", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11", | ||||||
|  |         "SCWX_ADDRESS_SANITIZER": { | ||||||
|  |           "type": "BOOL", | ||||||
|  |           "value": "ON" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "ci-linux-gcc14", | ||||||
|  |       "inherits": "linux-gcc-base", | ||||||
|  |       "displayName": "CI Linux GCC 14", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-linux_gcc-14", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-linux_gcc-14" | ||||||
|  |       }, | ||||||
|  |       "environment": { | ||||||
|  |         "CC": "gcc-14", | ||||||
|  |         "CXX": "g++-14" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "ci-linux-clang17", | ||||||
|  |       "inherits": "linux-gcc-base", | ||||||
|  |       "displayName": "CI Linux Clang 17", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-linux_clang-17", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-linux_clang-17" | ||||||
|  |       }, | ||||||
|  |       "environment": { | ||||||
|  |         "CC": "clang-17", | ||||||
|  |         "CXX": "clang++-17" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "ci-linux-gcc-arm64", | ||||||
|  |       "inherits": "linux-gcc-base", | ||||||
|  |       "displayName": "CI Linux GCC ARM64", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CMAKE_PREFIX_PATH": "/opt/Qt/6.9.2/gcc_arm64", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-linux_gcc-11_armv8", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11_armv8" | ||||||
|  |       }, | ||||||
|  |       "environment": { | ||||||
|  |         "CC": "gcc-11", | ||||||
|  |         "CXX": "g++-11" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-base", | ||||||
|  |       "inherits": "base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_PREFIX_PATH": "$env{HOME}/Qt/6.9.2/macos" | ||||||
|  |       }, | ||||||
|  |       "condition": { | ||||||
|  |         "type": "equals", | ||||||
|  |         "lhs": "${hostSystemName}", | ||||||
|  |         "rhs": "Darwin" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-base", | ||||||
|  |       "inherits": "macos-base", | ||||||
|  |       "hidden": true | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-x64-base", | ||||||
|  |       "inherits": "macos-clang18-base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "environment": { | ||||||
|  |         "CC": "/usr/local/opt/llvm@18/bin/clang", | ||||||
|  |         "CXX": "/usr/local/opt/llvm@18/bin/clang++", | ||||||
|  |         "PATH": "/usr/local/opt/llvm@18/bin:$penv{PATH}", | ||||||
|  |         "CPPFLAGS": "-I/usr/local/opt/llvm@18/include", | ||||||
|  |         "LDFLAGS": "-L/usr/local/opt/llvm@18/lib -L/usr/local/opt/llvm@18/lib/c++" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-arm64-base", | ||||||
|  |       "inherits": "macos-clang18-base", | ||||||
|  |       "hidden": true, | ||||||
|  |       "environment": { | ||||||
|  |         "CC": "/opt/homebrew/opt/llvm@18/bin/clang", | ||||||
|  |         "CXX": "/opt/homebrew/opt/llvm@18/bin/clang++", | ||||||
|  |         "PATH": "/opt/homebrew/opt/llvm@18/bin:$penv{PATH}", | ||||||
|  |         "CPPFLAGS": "-I/opt/homebrew/opt/llvm@18/include", | ||||||
|  |         "LDFLAGS": "-L/opt/homebrew/opt/llvm@18/lib -L/opt/homebrew/opt/llvm@18/lib/c++" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-x64-debug", | ||||||
|  |       "inherits": "macos-clang18-x64-base", | ||||||
|  |       "displayName": "macOS Clang 18 x64 Debug", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Debug", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-macos_clang-18-debug", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-macos_clang-18-debug" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-x64-release", | ||||||
|  |       "inherits": "macos-clang18-x64-base", | ||||||
|  |       "displayName": "macOS Clang 18 x64 Release", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-macos_clang-18", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-macos_clang-18" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-arm64-debug", | ||||||
|  |       "inherits": "macos-clang18-arm64-base", | ||||||
|  |       "displayName": "macOS Clang 18 Arm64 Debug", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Debug", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-macos_clang-18_armv8-debug", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-macos_clang-18_armv8-debug" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-arm64-release", | ||||||
|  |       "inherits": "macos-clang18-arm64-base", | ||||||
|  |       "displayName": "macOS Clang 18 Arm64 Release", | ||||||
|  |       "cacheVariables": { | ||||||
|  |         "CMAKE_BUILD_TYPE": "Release", | ||||||
|  |         "CONAN_HOST_PROFILE": "scwx-macos_clang-18_armv8", | ||||||
|  |         "CONAN_BUILD_PROFILE": "scwx-macos_clang-18_armv8" | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ], | ||||||
|  |   "buildPresets": [ | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-debug", | ||||||
|  |       "configurePreset": "windows-msvc2022-x64-debug", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Debug", | ||||||
|  |       "configuration": "Debug" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-release", | ||||||
|  |       "configurePreset": "windows-msvc2022-x64-release", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Release", | ||||||
|  |       "configuration": "Release" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-debug", | ||||||
|  |       "configurePreset": "linux-gcc-debug", | ||||||
|  |       "displayName": "Linux GCC Debug", | ||||||
|  |       "configuration": "Debug" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-release", | ||||||
|  |       "configurePreset": "linux-gcc-release", | ||||||
|  |       "displayName": "Linux GCC Release", | ||||||
|  |       "configuration": "Release" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-x64-debug", | ||||||
|  |       "configurePreset": "macos-clang18-x64-debug", | ||||||
|  |       "displayName": "macOS Clang 18 x64 Debug", | ||||||
|  |       "configuration": "Debug" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-x64-release", | ||||||
|  |       "configurePreset": "macos-clang18-x64-release", | ||||||
|  |       "displayName": "macOS Clang 18 x64 Release", | ||||||
|  |       "configuration": "Release" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-arm64-debug", | ||||||
|  |       "configurePreset": "macos-clang18-arm64-debug", | ||||||
|  |       "displayName": "macOS Clang 18 Arm64 Debug", | ||||||
|  |       "configuration": "Debug" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "macos-clang18-arm64-release", | ||||||
|  |       "configurePreset": "macos-clang18-arm64-release", | ||||||
|  |       "displayName": "macOS Clang 18 Arm64 Release", | ||||||
|  |       "configuration": "Release" | ||||||
|  |     } | ||||||
|  |   ], | ||||||
|  |   "testPresets": [ | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-debug", | ||||||
|  |       "configurePreset": "windows-msvc2022-x64-debug", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Debug", | ||||||
|  |       "configuration": "Debug" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "windows-msvc2022-x64-release", | ||||||
|  |       "configurePreset": "windows-msvc2022-x64-release", | ||||||
|  |       "displayName": "Windows MSVC 2022 x64 Release", | ||||||
|  |       "configuration": "Release" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-debug", | ||||||
|  |       "configurePreset": "linux-gcc-debug", | ||||||
|  |       "displayName": "Linux GCC Debug", | ||||||
|  |       "configuration": "Debug" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "name": "linux-gcc-release", | ||||||
|  |       "configurePreset": "linux-gcc-release", | ||||||
|  |       "displayName": "Linux GCC Release", | ||||||
|  |       "configuration": "Release" | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | } | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| The MIT License (MIT) | The MIT License (MIT) | ||||||
| 
 | 
 | ||||||
| Copyright (c) 2021-2024 Dan Paulat | Copyright (c) 2021-2025 Dan Paulat | ||||||
| 
 | 
 | ||||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
| of this software and associated documentation files (the "Software"), to deal | of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  | ||||||
|  | @ -26,13 +26,17 @@ Supercell Wx supports the following 64-bit operating systems: | ||||||
|   - Fedora Linux 34+ |   - Fedora Linux 34+ | ||||||
|   - openSUSE Tumbleweed |   - openSUSE Tumbleweed | ||||||
|   - Ubuntu 22.04+ |   - Ubuntu 22.04+ | ||||||
|  |   - NixOS 25.05+ | ||||||
|   - Most distributions supporting the GCC Standard C++ Library 11+ |   - Most distributions supporting the GCC Standard C++ Library 11+ | ||||||
|  | - macOS | ||||||
|  |   - 13.6+ for Intel-based Macs | ||||||
|  |   - 14.0+ for Apple silicon-based Macs | ||||||
| 
 | 
 | ||||||
| ## Linux Dependencies | ## Linux Dependencies | ||||||
| 
 | 
 | ||||||
| Supercell Wx requires the following Linux dependencies: | Supercell Wx requires the following Linux dependencies: | ||||||
| 
 | 
 | ||||||
| - Linux/X11 (Wayland works too) with support for GCC 11 and OpenGL 3.3 | - Linux/X11 (Wayland works too) with support for GCC 11, OpenGL 3.3 and OpenGL ES 3.0 | ||||||
| - X11/XCB libraries including xcb-cursor | - X11/XCB libraries including xcb-cursor | ||||||
| 
 | 
 | ||||||
| ## FAQ | ## FAQ | ||||||
|  |  | ||||||
							
								
								
									
										83
									
								
								conanfile.py
									
										
									
									
									
								
							
							
						
						|  | @ -1,37 +1,66 @@ | ||||||
| from conans import ConanFile | from conan import ConanFile | ||||||
|  | from conan.tools.cmake import CMake | ||||||
|  | from conan.tools.files import copy | ||||||
|  | import os | ||||||
| 
 | 
 | ||||||
| class SupercellWxConan(ConanFile): | class SupercellWxConan(ConanFile): | ||||||
|     settings   = ("os", "compiler", "build_type", "arch") |     settings   = ("os", "compiler", "build_type", "arch") | ||||||
|     requires   = ("boost/1.85.0", |     requires   = ("boost/1.88.0", | ||||||
|                   "cpr/1.10.5", |                   "cpr/1.12.0", | ||||||
|                   "fontconfig/2.15.0", |                   "fontconfig/2.15.0", | ||||||
|                   "freetype/2.13.2", |                   "freetype/2.13.2", | ||||||
|                   "geographiclib/2.3", |                   "geographiclib/2.4", | ||||||
|                   "geos/3.12.2", |                   "geos/3.13.0", | ||||||
|                   "glew/2.2.0", |                   "glm/1.0.1", | ||||||
|                   "glm/cci.20230113", |                   "gtest/1.17.0", | ||||||
|                   "gtest/1.15.0", |                   "libcurl/8.12.1", | ||||||
|                   "libcurl/8.9.1", |                   "libpng/1.6.50", | ||||||
|                   "libxml2/2.12.7", |                   "libxml2/2.14.5", | ||||||
|                   "openssl/3.3.1", |                   "openssl/3.5.0", | ||||||
|                   "re2/20240702", |                   "range-v3/0.12.0", | ||||||
|                   "spdlog/1.14.1", |                   "re2/20250722", | ||||||
|                   "sqlite3/3.46.0", |                   "spdlog/1.15.1", | ||||||
|                   "vulkan-loader/1.3.243.0", |                   "sqlite3/3.49.1", | ||||||
|  |                   "vulkan-loader/1.3.290.0", | ||||||
|                   "zlib/1.3.1") |                   "zlib/1.3.1") | ||||||
|     generators = ("cmake", |     generators = ("CMakeDeps") | ||||||
|                   "cmake_find_package", |     default_options = {"geos/*:shared"     : True, | ||||||
|                   "cmake_paths") |                        "libiconv/*:shared" : True} | ||||||
|     default_options = {"geos:shared"      : True, | 
 | ||||||
|                        "libiconv:shared"  : True, |     def configure(self): | ||||||
|                        "openssl:no_module": True, |         if self.settings.os == "Windows": | ||||||
|                        "openssl:shared"   : True} |             self.options["libcurl"].with_ssl = "schannel" | ||||||
|  |         elif self.settings.os == "Linux": | ||||||
|  |             self.options["openssl"].shared    = True | ||||||
|  |             self.options["libcurl"].ca_bundle = "none" | ||||||
|  |             self.options["libcurl"].ca_path   = "none" | ||||||
|  |         elif self.settings.os == "Macos": | ||||||
|  |             self.options["openssl"].shared    = True | ||||||
|  |             self.options["libcurl"].ca_bundle = "none" | ||||||
|  |             self.options["libcurl"].ca_path   = "none" | ||||||
| 
 | 
 | ||||||
|     def requirements(self): |     def requirements(self): | ||||||
|         if self.settings.os == "Linux": |         if self.settings.os == "Linux": | ||||||
|             self.requires("onetbb/2021.12.0") |             self.requires("mesa-glu/9.0.3") | ||||||
|  |             self.requires("onetbb/2022.2.0") | ||||||
| 
 | 
 | ||||||
|     def imports(self): |     def generate(self): | ||||||
|         self.copy("*.dll", dst="bin", src="bin") |         build_folder = os.path.join(self.build_folder, | ||||||
|         self.copy("*.dylib", dst="bin", src="lib") |                                     "..", | ||||||
|         self.copy("license*", dst="licenses", src=".", folder=True, ignore_case=True) |                                     str(self.settings.build_type), | ||||||
|  |                                     self.cpp_info.bindirs[0]) | ||||||
|  | 
 | ||||||
|  |         for dep in self.dependencies.values(): | ||||||
|  |             if dep.cpp_info.bindirs: | ||||||
|  |                 copy(self, "*.dll", dep.cpp_info.bindirs[0], build_folder) | ||||||
|  |             if dep.cpp_info.libdirs: | ||||||
|  |                 copy(self, "*.dylib", dep.cpp_info.libdirs[0], build_folder) | ||||||
|  | 
 | ||||||
|  |     def build(self): | ||||||
|  |         cmake = CMake(self) | ||||||
|  |         cmake.configure() | ||||||
|  |         cmake.build() | ||||||
|  | 
 | ||||||
|  |     def package(self): | ||||||
|  |         cmake = CMake(self) | ||||||
|  |         cmake.install() | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								data
									
										
									
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit 8eb89b19fdd1c78e896cc6cb47e07425bb473699 | Subproject commit fd72b32cc12419b4a9c9a72487e58ffa04fb2a70 | ||||||
							
								
								
									
										8
									
								
								external/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-external) | set(PROJECT_NAME scwx-external) | ||||||
| 
 | 
 | ||||||
| set_property(DIRECTORY | set_property(DIRECTORY | ||||||
|  | @ -6,18 +6,22 @@ set_property(DIRECTORY | ||||||
|              PROPERTY CMAKE_CONFIGURE_DEPENDS |              PROPERTY CMAKE_CONFIGURE_DEPENDS | ||||||
|              aws-sdk-cpp.cmake |              aws-sdk-cpp.cmake | ||||||
|              date.cmake |              date.cmake | ||||||
|  |              glad.cmake | ||||||
|              hsluv-c.cmake |              hsluv-c.cmake | ||||||
|              imgui.cmake |              imgui.cmake | ||||||
|              maplibre-native-qt.cmake |              maplibre-native-qt.cmake | ||||||
|              stb.cmake |              stb.cmake | ||||||
|              textflowcpp.cmake |              textflowcpp.cmake | ||||||
|              units.cmake) |              units.cmake | ||||||
|  |              qt6ct.cmake) | ||||||
| 
 | 
 | ||||||
| include(aws-sdk-cpp.cmake) | include(aws-sdk-cpp.cmake) | ||||||
| include(date.cmake) | include(date.cmake) | ||||||
|  | include(glad.cmake) | ||||||
| include(hsluv-c.cmake) | include(hsluv-c.cmake) | ||||||
| include(imgui.cmake) | include(imgui.cmake) | ||||||
| include(maplibre-native-qt.cmake) | include(maplibre-native-qt.cmake) | ||||||
| include(stb.cmake) | include(stb.cmake) | ||||||
| include(textflowcpp.cmake) | include(textflowcpp.cmake) | ||||||
| include(units.cmake) | include(units.cmake) | ||||||
|  | include(qt6ct.cmake) | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								external/aws-sdk-cpp
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit d5eb42fe7c632868d4535b454ee2e5ba0e349b7f | Subproject commit 8d31e042f950fe70924391a205cceaf342ecec00 | ||||||
							
								
								
									
										6
									
								
								external/aws-sdk-cpp.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-aws-sdk-cpp) | set(PROJECT_NAME scwx-aws-sdk-cpp) | ||||||
| 
 | 
 | ||||||
| set(AWS_SDK_WARNINGS_ARE_ERRORS OFF) | set(AWS_SDK_WARNINGS_ARE_ERRORS OFF) | ||||||
|  | @ -21,6 +21,10 @@ set(MINIMIZE_SIZE      OFF  CACHE BOOL   "If enabled, the SDK will be built via | ||||||
| # Save off ${CMAKE_CXX_FLAGS} before modifying compiler settings | # Save off ${CMAKE_CXX_FLAGS} before modifying compiler settings | ||||||
| set(CMAKE_CXX_FLAGS_PREV "${CMAKE_CXX_FLAGS}") | set(CMAKE_CXX_FLAGS_PREV "${CMAKE_CXX_FLAGS}") | ||||||
| 
 | 
 | ||||||
|  | # Configure OpenSSL crypto library | ||||||
|  | find_package(OpenSSL) | ||||||
|  | add_library(crypto ALIAS OpenSSL::Crypto) | ||||||
|  | 
 | ||||||
| # Fix CMake errors for internal variables not set | # Fix CMake errors for internal variables not set | ||||||
| include(aws-sdk-cpp/cmake/compiler_settings.cmake) | include(aws-sdk-cpp/cmake/compiler_settings.cmake) | ||||||
| set_msvc_warnings() | set_msvc_warnings() | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								external/cmake-conan
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit b240c809b5ea097077fc8222cad71d2329288e48 | Subproject commit b0e4d1ec08edb35ef31033938567d621f6643c17 | ||||||
							
								
								
									
										2
									
								
								external/date
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit cc4685a21e4a4fdae707ad1233c61bbaff241f93 | Subproject commit a5db3aecec580bc78b6c01c118f2628676769b69 | ||||||
							
								
								
									
										2
									
								
								external/date.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-date) | set(PROJECT_NAME scwx-date) | ||||||
| 
 | 
 | ||||||
| set(USE_SYSTEM_TZ_DB ON) | set(USE_SYSTEM_TZ_DB ON) | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								external/glad
									
										
									
									
										vendored
									
									
										Submodule
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | Subproject commit 73db193f853e2ee079bf3ca8a64aa2eaf6459043 | ||||||
							
								
								
									
										11
									
								
								external/glad.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,11 @@ | ||||||
|  | cmake_minimum_required(VERSION 3.24) | ||||||
|  | set(PROJECT_NAME scwx-glad) | ||||||
|  | 
 | ||||||
|  | # Path to glad directory | ||||||
|  | set(GLAD_SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/glad/") | ||||||
|  | 
 | ||||||
|  | # Path to glad CMake files | ||||||
|  | add_subdirectory("${GLAD_SOURCES_DIR}/cmake" glad_cmake) | ||||||
|  | 
 | ||||||
|  | # Specify glad settings | ||||||
|  | glad_add_library(glad_gl_core_33 LOADER REPRODUCIBLE API gl:core=3.3) | ||||||
							
								
								
									
										2
									
								
								external/hsluv-c
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit 59539e04a6fa648935cbe57c2104041f23136c4a | Subproject commit 982217c65a9ff574302335177d2dc078d9bfa6f5 | ||||||
							
								
								
									
										2
									
								
								external/hsluv-c.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-hsluv-c) | set(PROJECT_NAME scwx-hsluv-c) | ||||||
| 
 | 
 | ||||||
| set(HSLUV_C_TESTS OFF) | set(HSLUV_C_TESTS OFF) | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								external/imgui
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit 6ccc561a2ab497ad4ae6ee1dbd3b992ffada35cb | Subproject commit 45acd5e0e82f4c954432533ae9985ff0e1aad6d5 | ||||||
							
								
								
									
										2
									
								
								external/imgui-backend-qt
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit 0fe974ebd037844c9f23d6325dbcc128e9973749 | Subproject commit 023345ca8abf731fc50568c0197ceebe76bb4324 | ||||||
							
								
								
									
										7
									
								
								external/imgui.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-imgui) | set(PROJECT_NAME scwx-imgui) | ||||||
| 
 | 
 | ||||||
| find_package(QT NAMES Qt6 | find_package(QT NAMES Qt6 | ||||||
|  | @ -12,7 +12,7 @@ find_package(Qt${QT_VERSION_MAJOR} | ||||||
|               |               | ||||||
| find_package(Freetype) | find_package(Freetype) | ||||||
| 
 | 
 | ||||||
| set(IMGUI_SOURCES imgui/imconfig.h | set(IMGUI_SOURCES include/scwx/external/imgui/imconfig.h | ||||||
|                   imgui/imgui.cpp |                   imgui/imgui.cpp | ||||||
|                   imgui/imgui.h |                   imgui/imgui.h | ||||||
|                   imgui/imgui_demo.cpp |                   imgui/imgui_demo.cpp | ||||||
|  | @ -33,8 +33,9 @@ set(IMGUI_SOURCES imgui/imconfig.h | ||||||
| add_library(imgui STATIC ${IMGUI_SOURCES}) | add_library(imgui STATIC ${IMGUI_SOURCES}) | ||||||
| 
 | 
 | ||||||
| target_include_directories(imgui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/imgui) | target_include_directories(imgui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/imgui) | ||||||
|  | target_include_directories(imgui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) | ||||||
| 
 | 
 | ||||||
| target_compile_definitions(imgui PRIVATE IMGUI_ENABLE_FREETYPE) | target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG=<scwx/external/imgui/imconfig.h>) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(imgui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets | target_link_libraries(imgui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets | ||||||
|                                     Freetype::Freetype) |                                     Freetype::Freetype) | ||||||
|  |  | ||||||
							
								
								
									
										147
									
								
								external/include/scwx/external/imgui/imconfig.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,147 @@ | ||||||
|  | // clang-format off
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // DEAR IMGUI COMPILE-TIME OPTIONS
 | ||||||
|  | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
 | ||||||
|  | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
 | ||||||
|  | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
 | ||||||
|  | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
 | ||||||
|  | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
 | ||||||
|  | // Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
 | ||||||
|  | //-----------------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | //---- Define assertion handler. Defaults to calling assert().
 | ||||||
|  | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
 | ||||||
|  | //#define IM_ASSERT(_EXPR)  MyAssert(_EXPR)
 | ||||||
|  | //#define IM_ASSERT(_EXPR)  ((void)(_EXPR))     // Disable asserts
 | ||||||
|  | 
 | ||||||
|  | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
 | ||||||
|  | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
 | ||||||
|  | // - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
 | ||||||
|  | //   for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
 | ||||||
|  | //#define IMGUI_API __declspec(dllexport)                   // MSVC Windows: DLL export
 | ||||||
|  | //#define IMGUI_API __declspec(dllimport)                   // MSVC Windows: DLL import
 | ||||||
|  | //#define IMGUI_API __attribute__((visibility("default")))  // GCC/Clang: override visibility when set is hidden
 | ||||||
|  | 
 | ||||||
|  | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
 | ||||||
|  | #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS | ||||||
|  | 
 | ||||||
|  | //---- Disable all of Dear ImGui or don't implement standard windows/tools.
 | ||||||
|  | // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
 | ||||||
|  | //#define IMGUI_DISABLE                                     // Disable everything: all headers and source files will be empty.
 | ||||||
|  | //#define IMGUI_DISABLE_DEMO_WINDOWS                        // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
 | ||||||
|  | //#define IMGUI_DISABLE_DEBUG_TOOLS                         // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
 | ||||||
|  | 
 | ||||||
|  | //---- Don't implement some functions to reduce linkage requirements.
 | ||||||
|  | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS   // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
 | ||||||
|  | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS          // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
 | ||||||
|  | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS         // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
 | ||||||
|  | //#define IMGUI_DISABLE_WIN32_FUNCTIONS                     // [Win32] Won't use and link with any Win32 function (clipboard, IME).
 | ||||||
|  | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS      // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
 | ||||||
|  | //#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS             // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
 | ||||||
|  | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS            // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
 | ||||||
|  | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS              // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
 | ||||||
|  | //#define IMGUI_DISABLE_FILE_FUNCTIONS                      // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
 | ||||||
|  | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS              // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
 | ||||||
|  | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS                  // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
 | ||||||
|  | //#define IMGUI_DISABLE_DEFAULT_FONT                        // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert.
 | ||||||
|  | //#define IMGUI_DISABLE_SSE                                 // Disable use of SSE intrinsics even if available
 | ||||||
|  | 
 | ||||||
|  | //---- Enable Test Engine / Automation features.
 | ||||||
|  | //#define IMGUI_ENABLE_TEST_ENGINE                          // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
 | ||||||
|  | 
 | ||||||
|  | //---- Include imgui_user.h at the end of imgui.h as a convenience
 | ||||||
|  | // May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
 | ||||||
|  | //#define IMGUI_INCLUDE_IMGUI_USER_H
 | ||||||
|  | //#define IMGUI_USER_H_FILENAME         "my_folder/my_imgui_user.h"
 | ||||||
|  | 
 | ||||||
|  | //---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
 | ||||||
|  | //#define IMGUI_USE_BGRA_PACKED_COLOR
 | ||||||
|  | 
 | ||||||
|  | //---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate.
 | ||||||
|  | //#define IMGUI_USE_LEGACY_CRC32_ADLER
 | ||||||
|  | 
 | ||||||
|  | //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
 | ||||||
|  | //#define IMGUI_USE_WCHAR32
 | ||||||
|  | 
 | ||||||
|  | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
 | ||||||
|  | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
 | ||||||
|  | //#define IMGUI_STB_TRUETYPE_FILENAME   "my_folder/stb_truetype.h"
 | ||||||
|  | //#define IMGUI_STB_RECT_PACK_FILENAME  "my_folder/stb_rect_pack.h"
 | ||||||
|  | //#define IMGUI_STB_SPRINTF_FILENAME    "my_folder/stb_sprintf.h"    // only used if IMGUI_USE_STB_SPRINTF is defined.
 | ||||||
|  | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
 | ||||||
|  | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
 | ||||||
|  | //#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION                   // only disabled if IMGUI_USE_STB_SPRINTF is defined.
 | ||||||
|  | 
 | ||||||
|  | //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
 | ||||||
|  | // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
 | ||||||
|  | //#define IMGUI_USE_STB_SPRINTF
 | ||||||
|  | 
 | ||||||
|  | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
 | ||||||
|  | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
 | ||||||
|  | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
 | ||||||
|  | #define IMGUI_ENABLE_FREETYPE | ||||||
|  | 
 | ||||||
|  | //---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
 | ||||||
|  | // Only works in combination with IMGUI_ENABLE_FREETYPE.
 | ||||||
|  | // - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
 | ||||||
|  | // - Both require headers to be available in the include path + program to be linked with the library code (not provided).
 | ||||||
|  | // - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
 | ||||||
|  | //#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
 | ||||||
|  | //#define IMGUI_ENABLE_FREETYPE_LUNASVG
 | ||||||
|  | 
 | ||||||
|  | //---- Use stb_truetype to build and rasterize the font atlas (default)
 | ||||||
|  | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
 | ||||||
|  | //#define IMGUI_ENABLE_STB_TRUETYPE
 | ||||||
|  | 
 | ||||||
|  | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
 | ||||||
|  | // This will be inlined as part of ImVec2 and ImVec4 class declarations.
 | ||||||
|  | /*
 | ||||||
|  | #define IM_VEC2_CLASS_EXTRA                                                     \ | ||||||
|  |         constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {}                   \ | ||||||
|  |         operator MyVec2() const { return MyVec2(x,y); } | ||||||
|  | 
 | ||||||
|  | #define IM_VEC4_CLASS_EXTRA                                                     \ | ||||||
|  |         constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {}   \ | ||||||
|  |         operator MyVec4() const { return MyVec4(x,y,z,w); } | ||||||
|  | */ | ||||||
|  | //---- ...Or use Dear ImGui's own very basic math operators.
 | ||||||
|  | //#define IMGUI_DEFINE_MATH_OPERATORS
 | ||||||
|  | 
 | ||||||
|  | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
 | ||||||
|  | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
 | ||||||
|  | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
 | ||||||
|  | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
 | ||||||
|  | //#define ImDrawIdx unsigned int
 | ||||||
|  | 
 | ||||||
|  | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
 | ||||||
|  | //struct ImDrawList;
 | ||||||
|  | //struct ImDrawCmd;
 | ||||||
|  | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
 | ||||||
|  | //#define ImDrawCallback MyImDrawCallback
 | ||||||
|  | 
 | ||||||
|  | //---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
 | ||||||
|  | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
 | ||||||
|  | //#define IM_DEBUG_BREAK  IM_ASSERT(0)
 | ||||||
|  | //#define IM_DEBUG_BREAK  __debugbreak()
 | ||||||
|  | 
 | ||||||
|  | //---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set.
 | ||||||
|  | // (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use)
 | ||||||
|  | //#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS
 | ||||||
|  | 
 | ||||||
|  | //---- Debug Tools: Enable slower asserts
 | ||||||
|  | //#define IMGUI_DEBUG_PARANOID
 | ||||||
|  | 
 | ||||||
|  | //---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
 | ||||||
|  | /*
 | ||||||
|  | namespace ImGui | ||||||
|  | { | ||||||
|  |     void MyFunction(const char* name, MyMatrix44* mtx); | ||||||
|  | } | ||||||
|  | */ | ||||||
|  | // clang-format on
 | ||||||
							
								
								
									
										2
									
								
								external/maplibre-native
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit 3d4ca3fdf07c50db3002b11bff93c81ec380e493 | Subproject commit 3654f5fa9f06534d7fd2d95b810049a82e5953ef | ||||||
							
								
								
									
										2
									
								
								external/maplibre-native-qt
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit 805ccf6204a546e43fed599631ad5d698f68ae86 | Subproject commit 8b40697895c19da4479cd037a76608f4c36935e8 | ||||||
							
								
								
									
										19
									
								
								external/maplibre-native-qt.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-mln) | set(PROJECT_NAME scwx-mln) | ||||||
| 
 | 
 | ||||||
| set(gtest_disable_pthreads ON) | set(gtest_disable_pthreads ON) | ||||||
|  | @ -19,11 +19,28 @@ if (MSVC) | ||||||
|     target_link_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:/DEBUG>") |     target_link_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:/DEBUG>") | ||||||
|     target_link_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:/OPT:REF>") |     target_link_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:/OPT:REF>") | ||||||
|     target_link_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>") |     target_link_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>") | ||||||
|  | 
 | ||||||
|  |     # Enable multi-processor compilation | ||||||
|  |     target_compile_options(MLNQtCore PRIVATE "/MP") | ||||||
|  |     target_compile_options(mbgl-core PRIVATE "/MP") | ||||||
|  |     target_compile_options(mbgl-vendor-csscolorparser PRIVATE "/MP") | ||||||
|  |     target_compile_options(mbgl-vendor-nunicode PRIVATE "/MP") | ||||||
|  |     target_compile_options(mbgl-vendor-parsedate PRIVATE "/MP") | ||||||
|  | 
 | ||||||
|  |     if (TARGET mbgl-vendor-sqlite) | ||||||
|  |         target_compile_options(mbgl-vendor-sqlite PRIVATE "/MP") | ||||||
|  |     endif() | ||||||
| else() | else() | ||||||
|     target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:-g>") |     target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:-g>") | ||||||
|     target_compile_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:-g>") |     target_compile_options(MLNQtCore PRIVATE "$<$<CONFIG:Release>:-g>") | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
|  | if (APPLE) | ||||||
|  |     # Enable GL check error debug | ||||||
|  |     target_compile_definitions(mbgl-core PRIVATE MLN_GL_CHECK_ERRORS=1) | ||||||
|  |     target_compile_definitions(MLNQtCore PRIVATE MLN_GL_CHECK_ERRORS=1) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| set(MLN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native/include | set(MLN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native/include | ||||||
|                      ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native-qt/src/core/include |                      ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native-qt/src/core/include | ||||||
|                      ${CMAKE_CURRENT_BINARY_DIR}/maplibre-native-qt/src/core/include PARENT_SCOPE) |                      ${CMAKE_CURRENT_BINARY_DIR}/maplibre-native-qt/src/core/include PARENT_SCOPE) | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								external/qt6ct
									
										
									
									
										vendored
									
									
										Submodule
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | Subproject commit 2c569c6c4776ea5a1299030c079b16f70473c9e6 | ||||||
							
								
								
									
										62
									
								
								external/qt6ct.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,62 @@ | ||||||
|  | cmake_minimum_required(VERSION 3.16.0) | ||||||
|  | set(PROJECT_NAME scwx-qt6ct) | ||||||
|  | 
 | ||||||
|  | find_package(QT NAMES Qt6 | ||||||
|  |              COMPONENTS Gui Widgets | ||||||
|  |              REQUIRED) | ||||||
|  | find_package(Qt${QT_VERSION_MAJOR} | ||||||
|  |              COMPONENTS Gui Widgets | ||||||
|  |              REQUIRED) | ||||||
|  | 
 | ||||||
|  | #extract version from qt6ct.h | ||||||
|  | file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/qt6ct/src/qt6ct-common/qt6ct.h" | ||||||
|  |      QT6CT_VERSION_DATA REGEX "^#define[ \t]+QT6CT_VERSION_[A-Z]+[ \t]+[0-9]+.*$") | ||||||
|  | 
 | ||||||
|  | if(QT6CT_VERSION_DATA) | ||||||
|  |   foreach(item IN ITEMS MAJOR MINOR) | ||||||
|  |     string(REGEX REPLACE ".*#define[ \t]+QT6CT_VERSION_${item}[ \t]+([0-9]+).*" | ||||||
|  |        "\\1" QT6CT_VERSION_${item} ${QT6CT_VERSION_DATA}) | ||||||
|  |   endforeach() | ||||||
|  |   set(QT6CT_VERSION "${QT6CT_VERSION_MAJOR}.${QT6CT_VERSION_MINOR}") | ||||||
|  |   set(QT6CT_SOVERSION "${QT6CT_VERSION_MAJOR}") | ||||||
|  |   message(STATUS "qt6ct version: ${QT6CT_VERSION}") | ||||||
|  | else() | ||||||
|  |   message(FATAL_ERROR "invalid header") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | set(qt6ct-common-source | ||||||
|  |   qt6ct/src/qt6ct-common/qt6ct.cpp | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | set(qt6ct-widgets-source | ||||||
|  |   qt6ct/src/qt6ct/paletteeditdialog.cpp | ||||||
|  |   qt6ct/src/qt6ct/paletteeditdialog.ui | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | set(CMAKE_AUTOMOC ON) | ||||||
|  | set(CMAKE_AUTORCC ON) | ||||||
|  | set(CMAKE_AUTOUIC ON) | ||||||
|  | 
 | ||||||
|  | include_directories(qt6ct/src/qt6ct-common) | ||||||
|  | 
 | ||||||
|  | add_library(qt6ct-common STATIC ${qt6ct-common-source}) | ||||||
|  | set_target_properties(qt6ct-common PROPERTIES VERSION ${QT6CT_VERSION}) | ||||||
|  | target_link_libraries(qt6ct-common PRIVATE Qt6::Gui) | ||||||
|  | target_compile_definitions(qt6ct-common PRIVATE QT6CT_LIBRARY) | ||||||
|  | 
 | ||||||
|  | add_library(qt6ct-widgets STATIC ${qt6ct-widgets-source}) | ||||||
|  | set_target_properties(qt6ct-widgets PROPERTIES VERSION ${QT6CT_VERSION}) | ||||||
|  | target_link_libraries(qt6ct-widgets PRIVATE Qt6::Widgets qt6ct-common) | ||||||
|  | target_compile_definitions(qt6ct-widgets PRIVATE QT6CT_LIBRARY) | ||||||
|  | 
 | ||||||
|  | if (MSVC) | ||||||
|  |     # Produce PDB file for debug | ||||||
|  |     target_compile_options(qt6ct-common PRIVATE "$<$<CONFIG:Release>:/Zi>") | ||||||
|  |     target_compile_options(qt6ct-widgets PRIVATE "$<$<CONFIG:Release>:/Zi>") | ||||||
|  | else() | ||||||
|  |     target_compile_options(qt6ct-common PRIVATE "$<$<CONFIG:Release>:-g>") | ||||||
|  |     target_compile_options(qt6ct-widgets PRIVATE "$<$<CONFIG:Release>:-g>") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | target_include_directories( qt6ct-common INTERFACE qt6ct/src ) | ||||||
|  | target_include_directories( qt6ct-widgets INTERFACE qt6ct/src ) | ||||||
							
								
								
									
										2
									
								
								external/stb
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1 +1 @@ | ||||||
| Subproject commit beebb24b945efdea3b9bba23affb8eb3ba8982e7 | Subproject commit f58f558c120e9b32c217290b80bad1a0729fbb2c | ||||||
							
								
								
									
										2
									
								
								external/stb.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-stb) | set(PROJECT_NAME scwx-stb) | ||||||
| 
 | 
 | ||||||
| set(STB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stb PARENT_SCOPE) | set(STB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stb PARENT_SCOPE) | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								external/textflowcpp.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-textflowcpp) | set(PROJECT_NAME scwx-textflowcpp) | ||||||
| 
 | 
 | ||||||
| set(TEXTFLOWCPP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/textflowcpp PARENT_SCOPE) | set(TEXTFLOWCPP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/textflowcpp PARENT_SCOPE) | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								external/units.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.24) | ||||||
| set(PROJECT_NAME scwx-units) | set(PROJECT_NAME scwx-units) | ||||||
| 
 | 
 | ||||||
| add_subdirectory(units) | add_subdirectory(units) | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								requirements.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,3 @@ | ||||||
|  | conan | ||||||
|  | geopandas | ||||||
|  | GitPython | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.21) | cmake_minimum_required(VERSION 3.24) | ||||||
| 
 | 
 | ||||||
| set_property(DIRECTORY | set_property(DIRECTORY | ||||||
|              APPEND |              APPEND | ||||||
|  |  | ||||||
|  | @ -26,6 +26,9 @@ void main() | ||||||
|    // Always set displayed to true |    // Always set displayed to true | ||||||
|    vsOut.displayed = 1; |    vsOut.displayed = 1; | ||||||
| 
 | 
 | ||||||
|  |    // Initialize texCoord to default value | ||||||
|  |    vsOut.texCoord = vec3(0.0f, 0.0f, 0.0f); | ||||||
|  | 
 | ||||||
|    // Pass the threshold and time range to the geometry shader |    // Pass the threshold and time range to the geometry shader | ||||||
|    vsOut.threshold = aThreshold; |    vsOut.threshold = aThreshold; | ||||||
|    vsOut.timeRange = aTimeRange; |    vsOut.timeRange = aTimeRange; | ||||||
|  |  | ||||||
|  | @ -9,14 +9,14 @@ uniform float uDataMomentScale; | ||||||
| 
 | 
 | ||||||
| uniform bool uCFPEnabled; | uniform bool uCFPEnabled; | ||||||
| 
 | 
 | ||||||
| flat in uint dataMoment; | in float dataMoment; | ||||||
| flat in uint cfpMoment; | in float cfpMoment; | ||||||
| 
 | 
 | ||||||
| layout (location = 0) out vec4 fragColor; | layout (location = 0) out vec4 fragColor; | ||||||
| 
 | 
 | ||||||
| void main() | void main() | ||||||
| { | { | ||||||
|    float texCoord = float(dataMoment - uDataMomentOffset) / uDataMomentScale; |    float texCoord = (dataMoment - float(uDataMomentOffset)) / uDataMomentScale; | ||||||
| 
 | 
 | ||||||
|    if (uCFPEnabled && cfpMoment > 8u) |    if (uCFPEnabled && cfpMoment > 8u) | ||||||
|    { |    { | ||||||
|  |  | ||||||
|  | @ -13,8 +13,8 @@ layout (location = 2) in uint aCfpMoment; | ||||||
| uniform mat4 uMVPMatrix; | uniform mat4 uMVPMatrix; | ||||||
| uniform vec2 uMapScreenCoord; | uniform vec2 uMapScreenCoord; | ||||||
| 
 | 
 | ||||||
| flat out uint dataMoment; | out float dataMoment; | ||||||
| flat out uint cfpMoment; | out float cfpMoment; | ||||||
| 
 | 
 | ||||||
| vec2 latLngToScreenCoordinate(in vec2 latLng) | vec2 latLngToScreenCoordinate(in vec2 latLng) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -21,7 +21,9 @@ smooth out vec4 color; | ||||||
| void main() | void main() | ||||||
| { | { | ||||||
|    if (gsIn[0].displayed != 0 && |    if (gsIn[0].displayed != 0 && | ||||||
|        (gsIn[0].threshold <= 0 ||            // If Threshold: 0 was specified, no threshold |        (gsIn[0].threshold == 0 ||            // If Threshold: 0 was specified, no threshold | ||||||
|  |         uMapDistance == 0 ||                 // If uMapDistance is zero, threshold is disabled | ||||||
|  |         (gsIn[0].threshold < 0 && -(gsIn[0].threshold) <= uMapDistance) || // If Threshold is negative and below current map distance | ||||||
|         gsIn[0].threshold >= uMapDistance || // If Threshold is above current map distance |         gsIn[0].threshold >= uMapDistance || // If Threshold is above current map distance | ||||||
|         gsIn[0].threshold >= 999) &&         // If Threshold: 999 was specified (or greater), no threshold |         gsIn[0].threshold >= 999) &&         // If Threshold: 999 was specified (or greater), no threshold | ||||||
|        (gsIn[0].timeRange[0] == 0 ||              // If there is no start time specified |        (gsIn[0].timeRange[0] == 0 ||              // If there is no start time specified | ||||||
|  |  | ||||||
|  | @ -67,7 +67,7 @@ | ||||||
| 	{ "type": "wsr88d", "id": "KLVX", "lat": 37.9753058, "lon": -85.9438455,  "country": "USA", "state": "KY",  "place": "Louisville",              "tz": "America/New_York",             "elevation": 833.0 }, | 	{ "type": "wsr88d", "id": "KLVX", "lat": 37.9753058, "lon": -85.9438455,  "country": "USA", "state": "KY",  "place": "Louisville",              "tz": "America/New_York",             "elevation": 833.0 }, | ||||||
| 	{ "type": "wsr88d", "id": "KPAH", "lat": 37.068333,  "lon": -88.771944,   "country": "USA", "state": "KY",  "place": "Paducah",                 "tz": "America/Chicago",              "elevation": 506.0 }, | 	{ "type": "wsr88d", "id": "KPAH", "lat": 37.068333,  "lon": -88.771944,   "country": "USA", "state": "KY",  "place": "Paducah",                 "tz": "America/Chicago",              "elevation": 506.0 }, | ||||||
| 	{ "type": "wsr88d", "id": "KPOE", "lat": 31.1556923, "lon": -92.9762596,  "country": "USA", "state": "LA",  "place": "Fort Polk",               "tz": "America/Chicago",              "elevation": 473.0 }, | 	{ "type": "wsr88d", "id": "KPOE", "lat": 31.1556923, "lon": -92.9762596,  "country": "USA", "state": "LA",  "place": "Fort Polk",               "tz": "America/Chicago",              "elevation": 473.0 }, | ||||||
| 	{ "type": "wsr88d", "id": "KHDC", "lat": 30.519306,  "lon": -90.424028,   "country": "USA", "state": "LA",  "place": "New Orleans (Hammond)",   "tz": "America/Chicago",              "elevation": 43.0 }, | 	{ "type": "wsr88d", "id": "KHDC", "lat": 30.5196,    "lon": -90.4074,     "country": "USA", "state": "LA",  "place": "New Orleans (Hammond)",   "tz": "America/Chicago",              "elevation": 43.0 }, | ||||||
| 	{ "type": "wsr88d", "id": "KLCH", "lat": 30.125306,  "lon": -93.215889,   "country": "USA", "state": "LA",  "place": "Lake Charles",            "tz": "America/Chicago",              "elevation": 137.0 }, | 	{ "type": "wsr88d", "id": "KLCH", "lat": 30.125306,  "lon": -93.215889,   "country": "USA", "state": "LA",  "place": "Lake Charles",            "tz": "America/Chicago",              "elevation": 137.0 }, | ||||||
| 	{ "type": "wsr88d", "id": "KSHV", "lat": 32.450833,  "lon": -93.84125,    "country": "USA", "state": "LA",  "place": "Shreveport",              "tz": "America/Chicago",              "elevation": 387.0 }, | 	{ "type": "wsr88d", "id": "KSHV", "lat": 32.450833,  "lon": -93.84125,    "country": "USA", "state": "LA",  "place": "Shreveport",              "tz": "America/Chicago",              "elevation": 387.0 }, | ||||||
| 	{ "type": "wsr88d", "id": "KLIX", "lat": 30.3367133, "lon": -89.8256618,  "country": "USA", "state": "LA",  "place": "New Orleans (Slidell)",   "tz": "America/Chicago",              "elevation": 179.0 }, | 	{ "type": "wsr88d", "id": "KLIX", "lat": 30.3367133, "lon": -89.8256618,  "country": "USA", "state": "LA",  "place": "New Orleans (Slidell)",   "tz": "America/Chicago",              "elevation": 179.0 }, | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/briefcase-solid.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="#ffffff" d="M184 48l144 0c4.4 0 8 3.6 8 8l0 40L176 96l0-40c0-4.4 3.6-8 8-8zm-56 8l0 40L64 96C28.7 96 0 124.7 0 160l0 96 192 0 128 0 192 0 0-96c0-35.3-28.7-64-64-64l-64 0 0-40c0-30.9-25.1-56-56-56L184 0c-30.9 0-56 25.1-56 56zM512 288l-192 0 0 32c0 17.7-14.3 32-32 32l-64 0c-17.7 0-32-14.3-32-32l0-32L0 288 0 416c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-128z"/></svg> | ||||||
| After Width: | Height: | Size: 623 B | 
|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="#ffffff" d="M243.4 2.6l-224 96c-14 6-21.8 21-18.7 35.8S16.8 160 32 160l0 8c0 13.3 10.7 24 24 24l400 0c13.3 0 24-10.7 24-24l0-8c15.2 0 28.3-10.7 31.3-25.6s-4.8-29.9-18.7-35.8l-224-96c-8-3.4-17.2-3.4-25.2 0zM128 224l-64 0 0 196.3c-.6 .3-1.2 .7-1.8 1.1l-48 32c-11.7 7.8-17 22.4-12.9 35.9S17.9 512 32 512l448 0c14.1 0 26.5-9.2 30.6-22.7s-1.1-28.1-12.9-35.9l-48-32c-.6-.4-1.2-.7-1.8-1.1L448 224l-64 0 0 192-40 0 0-192-64 0 0 192-48 0 0-192-64 0 0 192-40 0 0-192zM256 64a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg> | ||||||
| After Width: | Height: | Size: 757 B | 
							
								
								
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/building-solid.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 384 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="#ffffff" d="M48 0C21.5 0 0 21.5 0 48L0 464c0 26.5 21.5 48 48 48l96 0 0-80c0-26.5 21.5-48 48-48s48 21.5 48 48l0 80 96 0c26.5 0 48-21.5 48-48l0-416c0-26.5-21.5-48-48-48L48 0zM64 240c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zm112-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32c0-8.8 7.2-16 16-16zm80 16c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zM80 96l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32c0-8.8 7.2-16 16-16zm80 16c0-8.8 7.2-16 16-16l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32zM272 96l32 0c8.8 0 16 7.2 16 16l0 32c0 8.8-7.2 16-16 16l-32 0c-8.8 0-16-7.2-16-16l0-32c0-8.8 7.2-16 16-16z"/></svg> | ||||||
| After Width: | Height: | Size: 1 KiB | 
							
								
								
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/caravan-solid.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" viewBox="0 0 640 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="#ffffff" d="M0 112C0 67.8 35.8 32 80 32l336 0c88.4 0 160 71.6 160 160l0 160 32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0-288 0c0 53-43 96-96 96s-96-43-96-96l-16 0c-44.2 0-80-35.8-80-80L0 112zM320 352l128 0 0-96-32 0c-8.8 0-16-7.2-16-16s7.2-16 16-16l32 0 0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32l0 192zM96 128c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l128 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32L96 128zm96 336a48 48 0 1 0 0-96 48 48 0 1 0 0 96z"/></svg> | ||||||
| After Width: | Height: | Size: 732 B | 
							
								
								
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/house-solid-white.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" height="16" width="18" viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#ffffff" d="M575.8 255.5c0 18-15 32.1-32 32.1h-32l.7 160.2c0 2.7-.2 5.4-.5 8.1V472c0 22.1-17.9 40-40 40H456c-1.1 0-2.2 0-3.3-.1c-1.4 .1-2.8 .1-4.2 .1H416 392c-22.1 0-40-17.9-40-40V448 384c0-17.7-14.3-32-32-32H256c-17.7 0-32 14.3-32 32v64 24c0 22.1-17.9 40-40 40H160 128.1c-1.5 0-3-.1-4.5-.2c-1.2 .1-2.4 .2-3.6 .2H104c-22.1 0-40-17.9-40-40V360c0-.9 0-1.9 .1-2.8V287.6H32c-18 0-32-14-32-32.1c0-9 3-17 10-24L266.4 8c7-7 15-8 22-8s15 2 21 7L564.8 231.5c8 7 12 15 11 24z"/></svg> | ||||||
| After Width: | Height: | Size: 735 B | 
|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="#ffffff" d="M256 0c17.7 0 32 14.3 32 32l0 34.7C368.4 80.1 431.9 143.6 445.3 224l34.7 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-34.7 0C431.9 368.4 368.4 431.9 288 445.3l0 34.7c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-34.7C143.6 431.9 80.1 368.4 66.7 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l34.7 0C80.1 143.6 143.6 80.1 224 66.7L224 32c0-17.7 14.3-32 32-32zM128 256a128 128 0 1 0 256 0 128 128 0 1 0 -256 0zm128-80a80 80 0 1 1 0 160 80 80 0 1 1 0-160z"/></svg> | ||||||
| After Width: | Height: | Size: 708 B | 
							
								
								
									
										4
									
								
								scwx-qt/res/icons/font-awesome-6/location-pin.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,4 @@ | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 384 512"> | ||||||
|  |     <!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--> | ||||||
|  |     <path fill="#ffffff" d="M215.7 499.2C267 435 384 279.4 384 192C384 86 298 0 192 0S0 86 0 192c0 87.4 117 243 168.3 307.2c12.3 15.3 35.1 15.3 47.4 0zM192 128a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"/> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 463 B | 
							
								
								
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/star-solid-white.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" height="16" width="18" viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="#ffffff" d="M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z"/></svg> | ||||||
| After Width: | Height: | Size: 616 B | 
							
								
								
									
										1
									
								
								scwx-qt/res/icons/font-awesome-6/tent-solid.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1 @@ | ||||||
|  | <svg xmlns="http://www.w3.org/2000/svg" width="18" height="16" viewBox="0 0 576 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="#ffffff" d="M269.4 6C280.5-2 295.5-2 306.6 6l224 160c7.4 5.3 12.2 13.5 13.2 22.5l32 288c1 9-1.9 18.1-8 24.9s-14.7 10.7-23.8 10.7l-80 0-28.2 0c-12.1 0-23.2-6.8-28.6-17.7L306.7 293.5c-1.7-3.4-5.1-5.5-8.8-5.5c-5.5 0-9.9 4.4-9.9 9.9L288 480c0 17.7-14.3 32-32 32l-16 0L32 512c-9.1 0-17.8-3.9-23.8-10.7s-9-15.8-8-24.9l32-288c1-9 5.8-17.2 13.2-22.5L269.4 6z"/></svg> | ||||||
| After Width: | Height: | Size: 608 B | 
							
								
								
									
										
											BIN
										
									
								
								scwx-qt/res/icons/scwx.icns
									
										
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								scwx-qt/res/linux/net.supercellwx.app.desktop
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,7 @@ | ||||||
|  | [Desktop Entry] | ||||||
|  | Type=Application | ||||||
|  | Name=Supercell Wx | ||||||
|  | Comment=Weather Radar and Data Viewer | ||||||
|  | Exec=supercell-wx | ||||||
|  | Icon=net.supercellwx.app.png | ||||||
|  | Categories=Network;Science; | ||||||
							
								
								
									
										42
									
								
								scwx-qt/res/scwx-qt.plist.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,42 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||||
|  | <plist version="1.0"> | ||||||
|  | <dict> | ||||||
|  | 	<key>CFBundleInfoDictionaryVersion</key> | ||||||
|  | 	<string>6.0</string> | ||||||
|  | 	<key>CFBundlePackageType</key> | ||||||
|  | 	<string>APPL</string> | ||||||
|  | 
 | ||||||
|  | 	<key>CFBundleName</key> | ||||||
|  | 	<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string> | ||||||
|  | 	<key>CFBundleIdentifier</key> | ||||||
|  | 	<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string> | ||||||
|  | 	<key>CFBundleExecutable</key> | ||||||
|  | 	<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string> | ||||||
|  | 
 | ||||||
|  | 	<key>CFBundleVersion</key> | ||||||
|  | 	<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string> | ||||||
|  | 	<key>CFBundleShortVersionString</key> | ||||||
|  | 	<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string> | ||||||
|  | 
 | ||||||
|  | 	<key>LSMinimumSystemVersion</key> | ||||||
|  | 	<string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string> | ||||||
|  | 
 | ||||||
|  | 	<key>NSHumanReadableCopyright</key> | ||||||
|  | 	<string>${MACOSX_BUNDLE_COPYRIGHT}</string> | ||||||
|  | 
 | ||||||
|  | 	<key>CFBundleIconFile</key> | ||||||
|  | 	<string>${MACOSX_BUNDLE_ICON_FILE}</string> | ||||||
|  | 
 | ||||||
|  | 	<key>CFBundleDevelopmentRegion</key> | ||||||
|  | 	<string>en</string> | ||||||
|  | 	<key>CFBundleAllowMixedLocalizations</key> | ||||||
|  | 	<true/> | ||||||
|  | 
 | ||||||
|  | 	<key>NSPrincipalClass</key> | ||||||
|  | 	<string>NSApplication</string> | ||||||
|  | 
 | ||||||
|  | 	<key>NSSupportsAutomaticGraphicsSwitching</key> | ||||||
|  | 	<true/> | ||||||
|  | </dict> | ||||||
|  | </plist> | ||||||
							
								
								
									
										9
									
								
								scwx-qt/res/textures/images/dot.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,9 @@ | ||||||
|  | <svg version="1.1" | ||||||
|  |      viewBox="0 0 100 100" | ||||||
|  |      width="3" height="3" | ||||||
|  |      xmlns="http://www.w3.org/2000/svg"> | ||||||
|  | 
 | ||||||
|  |      <circle r="50" cx="50" cy="50" fill="black"></circle> | ||||||
|  |      <circle r="25" cx="50" cy="50" fill="white"></circle> | ||||||
|  | 
 | ||||||
|  |  </svg> | ||||||
| After Width: | Height: | Size: 241 B | 
							
								
								
									
										11
									
								
								scwx-qt/res/textures/images/location-marker.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,11 @@ | ||||||
|  | <svg version="1.1" | ||||||
|  |      viewBox="0 0 170 150" | ||||||
|  |      width="17" height="15" | ||||||
|  |      xmlns="http://www.w3.org/2000/svg"> | ||||||
|  | 
 | ||||||
|  |     <path d="M 40,118 L 85,40 L 130,118 L 40,118 L 85,40 Z" | ||||||
|  |         stroke="black" stroke-width="40" fill="none"/> | ||||||
|  |     <path d="M 40,118 L 85,40 L 130,118 L 40,118 L 85,40 Z" | ||||||
|  |         stroke="#ffffff" stroke-width="20" fill="none"/> | ||||||
|  | 
 | ||||||
|  |  </svg> | ||||||
| After Width: | Height: | Size: 357 B | 
|  | @ -1,4 +1,4 @@ | ||||||
| cmake_minimum_required(VERSION 3.21) | cmake_minimum_required(VERSION 3.24) | ||||||
| 
 | 
 | ||||||
| project(scwx-qt LANGUAGES CXX) | project(scwx-qt LANGUAGES CXX) | ||||||
| 
 | 
 | ||||||
|  | @ -6,17 +6,19 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) | ||||||
| 
 | 
 | ||||||
| set(CMAKE_AUTOUIC ON) | set(CMAKE_AUTOUIC ON) | ||||||
| set(CMAKE_AUTOMOC ON) | set(CMAKE_AUTOMOC ON) | ||||||
| set(CMAKE_AUTORCC ON) | set(CMAKE_AUTORCC OFF) | ||||||
| 
 | 
 | ||||||
| set(CMAKE_CXX_STANDARD 20) | set(CMAKE_CXX_STANDARD 20) | ||||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||||
| 
 | 
 | ||||||
|  | OPTION(SCWX_DISABLE_CONSOLE "Disables the Windows console in release mode" ON) | ||||||
|  | 
 | ||||||
| find_package(Boost) | find_package(Boost) | ||||||
| find_package(Fontconfig) | find_package(Fontconfig) | ||||||
| find_package(geographiclib) | find_package(geographiclib) | ||||||
| find_package(geos) | find_package(geos) | ||||||
| find_package(GLEW) |  | ||||||
| find_package(glm) | find_package(glm) | ||||||
|  | find_package(OpenGL) | ||||||
| find_package(Python COMPONENTS Interpreter) | find_package(Python COMPONENTS Interpreter) | ||||||
| find_package(SQLite3) | find_package(SQLite3) | ||||||
| 
 | 
 | ||||||
|  | @ -30,7 +32,9 @@ find_package(QT NAMES Qt6 | ||||||
|                         Positioning |                         Positioning | ||||||
|                         SerialPort |                         SerialPort | ||||||
|                         Svg |                         Svg | ||||||
|                         Widgets REQUIRED) |                         Widgets | ||||||
|  |                         Sql | ||||||
|  |              REQUIRED) | ||||||
| 
 | 
 | ||||||
| find_package(Qt${QT_VERSION_MAJOR} | find_package(Qt${QT_VERSION_MAJOR} | ||||||
|              COMPONENTS Gui |              COMPONENTS Gui | ||||||
|  | @ -49,9 +53,13 @@ find_package(Qt${QT_VERSION_MAJOR} | ||||||
| set(SRC_EXE_MAIN source/scwx/qt/main/main.cpp) | set(SRC_EXE_MAIN source/scwx/qt/main/main.cpp) | ||||||
| 
 | 
 | ||||||
| set(HDR_MAIN source/scwx/qt/main/application.hpp | set(HDR_MAIN source/scwx/qt/main/application.hpp | ||||||
|              source/scwx/qt/main/main_window.hpp) |              source/scwx/qt/main/check_privilege.hpp | ||||||
|  |              source/scwx/qt/main/main_window.hpp | ||||||
|  |              source/scwx/qt/main/process_validation.hpp) | ||||||
| set(SRC_MAIN source/scwx/qt/main/application.cpp | set(SRC_MAIN source/scwx/qt/main/application.cpp | ||||||
|              source/scwx/qt/main/main_window.cpp) |              source/scwx/qt/main/check_privilege.cpp | ||||||
|  |              source/scwx/qt/main/main_window.cpp | ||||||
|  |              source/scwx/qt/main/process_validation.cpp) | ||||||
| set(UI_MAIN  source/scwx/qt/main/main_window.ui) | set(UI_MAIN  source/scwx/qt/main/main_window.ui) | ||||||
| set(HDR_CONFIG source/scwx/qt/config/county_database.hpp | set(HDR_CONFIG source/scwx/qt/config/county_database.hpp | ||||||
|                source/scwx/qt/config/radar_site.hpp) |                source/scwx/qt/config/radar_site.hpp) | ||||||
|  | @ -95,11 +103,13 @@ set(HDR_MANAGER source/scwx/qt/manager/alert_manager.hpp | ||||||
|                 source/scwx/qt/manager/log_manager.hpp |                 source/scwx/qt/manager/log_manager.hpp | ||||||
|                 source/scwx/qt/manager/media_manager.hpp |                 source/scwx/qt/manager/media_manager.hpp | ||||||
|                 source/scwx/qt/manager/placefile_manager.hpp |                 source/scwx/qt/manager/placefile_manager.hpp | ||||||
|  |                 source/scwx/qt/manager/marker_manager.hpp | ||||||
|                 source/scwx/qt/manager/position_manager.hpp |                 source/scwx/qt/manager/position_manager.hpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager.hpp |                 source/scwx/qt/manager/radar_product_manager.hpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager_notifier.hpp |                 source/scwx/qt/manager/radar_product_manager_notifier.hpp | ||||||
|                 source/scwx/qt/manager/resource_manager.hpp |                 source/scwx/qt/manager/resource_manager.hpp | ||||||
|                 source/scwx/qt/manager/settings_manager.hpp |                 source/scwx/qt/manager/settings_manager.hpp | ||||||
|  |                 source/scwx/qt/manager/task_manager.hpp | ||||||
|                 source/scwx/qt/manager/text_event_manager.hpp |                 source/scwx/qt/manager/text_event_manager.hpp | ||||||
|                 source/scwx/qt/manager/thread_manager.hpp |                 source/scwx/qt/manager/thread_manager.hpp | ||||||
|                 source/scwx/qt/manager/timeline_manager.hpp |                 source/scwx/qt/manager/timeline_manager.hpp | ||||||
|  | @ -111,11 +121,13 @@ set(SRC_MANAGER source/scwx/qt/manager/alert_manager.cpp | ||||||
|                 source/scwx/qt/manager/log_manager.cpp |                 source/scwx/qt/manager/log_manager.cpp | ||||||
|                 source/scwx/qt/manager/media_manager.cpp |                 source/scwx/qt/manager/media_manager.cpp | ||||||
|                 source/scwx/qt/manager/placefile_manager.cpp |                 source/scwx/qt/manager/placefile_manager.cpp | ||||||
|  |                 source/scwx/qt/manager/marker_manager.cpp | ||||||
|                 source/scwx/qt/manager/position_manager.cpp |                 source/scwx/qt/manager/position_manager.cpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager.cpp |                 source/scwx/qt/manager/radar_product_manager.cpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager_notifier.cpp |                 source/scwx/qt/manager/radar_product_manager_notifier.cpp | ||||||
|                 source/scwx/qt/manager/resource_manager.cpp |                 source/scwx/qt/manager/resource_manager.cpp | ||||||
|                 source/scwx/qt/manager/settings_manager.cpp |                 source/scwx/qt/manager/settings_manager.cpp | ||||||
|  |                 source/scwx/qt/manager/task_manager.cpp | ||||||
|                 source/scwx/qt/manager/text_event_manager.cpp |                 source/scwx/qt/manager/text_event_manager.cpp | ||||||
|                 source/scwx/qt/manager/thread_manager.cpp |                 source/scwx/qt/manager/thread_manager.cpp | ||||||
|                 source/scwx/qt/manager/timeline_manager.cpp |                 source/scwx/qt/manager/timeline_manager.cpp | ||||||
|  | @ -132,6 +144,7 @@ set(HDR_MAP source/scwx/qt/map/alert_layer.hpp | ||||||
|             source/scwx/qt/map/overlay_layer.hpp |             source/scwx/qt/map/overlay_layer.hpp | ||||||
|             source/scwx/qt/map/overlay_product_layer.hpp |             source/scwx/qt/map/overlay_product_layer.hpp | ||||||
|             source/scwx/qt/map/placefile_layer.hpp |             source/scwx/qt/map/placefile_layer.hpp | ||||||
|  |             source/scwx/qt/map/marker_layer.hpp | ||||||
|             source/scwx/qt/map/radar_product_layer.hpp |             source/scwx/qt/map/radar_product_layer.hpp | ||||||
|             source/scwx/qt/map/radar_range_layer.hpp |             source/scwx/qt/map/radar_range_layer.hpp | ||||||
|             source/scwx/qt/map/radar_site_layer.hpp) |             source/scwx/qt/map/radar_site_layer.hpp) | ||||||
|  | @ -146,6 +159,7 @@ set(SRC_MAP source/scwx/qt/map/alert_layer.cpp | ||||||
|             source/scwx/qt/map/overlay_layer.cpp |             source/scwx/qt/map/overlay_layer.cpp | ||||||
|             source/scwx/qt/map/overlay_product_layer.cpp |             source/scwx/qt/map/overlay_product_layer.cpp | ||||||
|             source/scwx/qt/map/placefile_layer.cpp |             source/scwx/qt/map/placefile_layer.cpp | ||||||
|  |             source/scwx/qt/map/marker_layer.cpp | ||||||
|             source/scwx/qt/map/radar_product_layer.cpp |             source/scwx/qt/map/radar_product_layer.cpp | ||||||
|             source/scwx/qt/map/radar_range_layer.cpp |             source/scwx/qt/map/radar_range_layer.cpp | ||||||
|             source/scwx/qt/map/radar_site_layer.cpp) |             source/scwx/qt/map/radar_site_layer.cpp) | ||||||
|  | @ -154,6 +168,7 @@ set(HDR_MODEL source/scwx/qt/model/alert_model.hpp | ||||||
|               source/scwx/qt/model/imgui_context_model.hpp |               source/scwx/qt/model/imgui_context_model.hpp | ||||||
|               source/scwx/qt/model/layer_model.hpp |               source/scwx/qt/model/layer_model.hpp | ||||||
|               source/scwx/qt/model/placefile_model.hpp |               source/scwx/qt/model/placefile_model.hpp | ||||||
|  |               source/scwx/qt/model/marker_model.hpp | ||||||
|               source/scwx/qt/model/radar_site_model.hpp |               source/scwx/qt/model/radar_site_model.hpp | ||||||
|               source/scwx/qt/model/tree_item.hpp |               source/scwx/qt/model/tree_item.hpp | ||||||
|               source/scwx/qt/model/tree_model.hpp) |               source/scwx/qt/model/tree_model.hpp) | ||||||
|  | @ -162,6 +177,7 @@ set(SRC_MODEL source/scwx/qt/model/alert_model.cpp | ||||||
|               source/scwx/qt/model/imgui_context_model.cpp |               source/scwx/qt/model/imgui_context_model.cpp | ||||||
|               source/scwx/qt/model/layer_model.cpp |               source/scwx/qt/model/layer_model.cpp | ||||||
|               source/scwx/qt/model/placefile_model.cpp |               source/scwx/qt/model/placefile_model.cpp | ||||||
|  |               source/scwx/qt/model/marker_model.cpp | ||||||
|               source/scwx/qt/model/radar_site_model.cpp |               source/scwx/qt/model/radar_site_model.cpp | ||||||
|               source/scwx/qt/model/tree_item.cpp |               source/scwx/qt/model/tree_item.cpp | ||||||
|               source/scwx/qt/model/tree_model.cpp) |               source/scwx/qt/model/tree_model.cpp) | ||||||
|  | @ -169,9 +185,11 @@ set(HDR_REQUEST source/scwx/qt/request/download_request.hpp | ||||||
|                 source/scwx/qt/request/nexrad_file_request.hpp) |                 source/scwx/qt/request/nexrad_file_request.hpp) | ||||||
| set(SRC_REQUEST source/scwx/qt/request/download_request.cpp | set(SRC_REQUEST source/scwx/qt/request/download_request.cpp | ||||||
|                 source/scwx/qt/request/nexrad_file_request.cpp) |                 source/scwx/qt/request/nexrad_file_request.cpp) | ||||||
| set(HDR_SETTINGS source/scwx/qt/settings/audio_settings.hpp | set(HDR_SETTINGS source/scwx/qt/settings/alert_palette_settings.hpp | ||||||
|  |                  source/scwx/qt/settings/audio_settings.hpp | ||||||
|                  source/scwx/qt/settings/general_settings.hpp |                  source/scwx/qt/settings/general_settings.hpp | ||||||
|                  source/scwx/qt/settings/hotkey_settings.hpp |                  source/scwx/qt/settings/hotkey_settings.hpp | ||||||
|  |                  source/scwx/qt/settings/line_settings.hpp | ||||||
|                  source/scwx/qt/settings/map_settings.hpp |                  source/scwx/qt/settings/map_settings.hpp | ||||||
|                  source/scwx/qt/settings/palette_settings.hpp |                  source/scwx/qt/settings/palette_settings.hpp | ||||||
|                  source/scwx/qt/settings/product_settings.hpp |                  source/scwx/qt/settings/product_settings.hpp | ||||||
|  | @ -185,9 +203,11 @@ set(HDR_SETTINGS source/scwx/qt/settings/audio_settings.hpp | ||||||
|                  source/scwx/qt/settings/text_settings.hpp |                  source/scwx/qt/settings/text_settings.hpp | ||||||
|                  source/scwx/qt/settings/ui_settings.hpp |                  source/scwx/qt/settings/ui_settings.hpp | ||||||
|                  source/scwx/qt/settings/unit_settings.hpp) |                  source/scwx/qt/settings/unit_settings.hpp) | ||||||
| set(SRC_SETTINGS source/scwx/qt/settings/audio_settings.cpp | set(SRC_SETTINGS source/scwx/qt/settings/alert_palette_settings.cpp | ||||||
|  |                  source/scwx/qt/settings/audio_settings.cpp | ||||||
|                  source/scwx/qt/settings/general_settings.cpp |                  source/scwx/qt/settings/general_settings.cpp | ||||||
|                  source/scwx/qt/settings/hotkey_settings.cpp |                  source/scwx/qt/settings/hotkey_settings.cpp | ||||||
|  |                  source/scwx/qt/settings/line_settings.cpp | ||||||
|                  source/scwx/qt/settings/map_settings.cpp |                  source/scwx/qt/settings/map_settings.cpp | ||||||
|                  source/scwx/qt/settings/palette_settings.cpp |                  source/scwx/qt/settings/palette_settings.cpp | ||||||
|                  source/scwx/qt/settings/product_settings.cpp |                  source/scwx/qt/settings/product_settings.cpp | ||||||
|  | @ -210,6 +230,7 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp | ||||||
|               source/scwx/qt/types/layer_types.hpp |               source/scwx/qt/types/layer_types.hpp | ||||||
|               source/scwx/qt/types/location_types.hpp |               source/scwx/qt/types/location_types.hpp | ||||||
|               source/scwx/qt/types/map_types.hpp |               source/scwx/qt/types/map_types.hpp | ||||||
|  |               source/scwx/qt/types/marker_types.hpp | ||||||
|               source/scwx/qt/types/media_types.hpp |               source/scwx/qt/types/media_types.hpp | ||||||
|               source/scwx/qt/types/qt_types.hpp |               source/scwx/qt/types/qt_types.hpp | ||||||
|               source/scwx/qt/types/radar_product_record.hpp |               source/scwx/qt/types/radar_product_record.hpp | ||||||
|  | @ -238,10 +259,13 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp | ||||||
|            source/scwx/qt/ui/alert_dialog.hpp |            source/scwx/qt/ui/alert_dialog.hpp | ||||||
|            source/scwx/qt/ui/alert_dock_widget.hpp |            source/scwx/qt/ui/alert_dock_widget.hpp | ||||||
|            source/scwx/qt/ui/animation_dock_widget.hpp |            source/scwx/qt/ui/animation_dock_widget.hpp | ||||||
|  |            source/scwx/qt/ui/api_key_edit_widget.hpp | ||||||
|            source/scwx/qt/ui/collapsible_group.hpp |            source/scwx/qt/ui/collapsible_group.hpp | ||||||
|            source/scwx/qt/ui/county_dialog.hpp |            source/scwx/qt/ui/county_dialog.hpp | ||||||
|            source/scwx/qt/ui/wfo_dialog.hpp |            source/scwx/qt/ui/custom_layer_dialog.hpp | ||||||
|            source/scwx/qt/ui/download_dialog.hpp |            source/scwx/qt/ui/download_dialog.hpp | ||||||
|  |            source/scwx/qt/ui/edit_line_dialog.hpp | ||||||
|  |            source/scwx/qt/ui/edit_marker_dialog.hpp | ||||||
|            source/scwx/qt/ui/flow_layout.hpp |            source/scwx/qt/ui/flow_layout.hpp | ||||||
|            source/scwx/qt/ui/gps_info_dialog.hpp |            source/scwx/qt/ui/gps_info_dialog.hpp | ||||||
|            source/scwx/qt/ui/hotkey_edit.hpp |            source/scwx/qt/ui/hotkey_edit.hpp | ||||||
|  | @ -252,22 +276,29 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp | ||||||
|            source/scwx/qt/ui/level2_products_widget.hpp |            source/scwx/qt/ui/level2_products_widget.hpp | ||||||
|            source/scwx/qt/ui/level2_settings_widget.hpp |            source/scwx/qt/ui/level2_settings_widget.hpp | ||||||
|            source/scwx/qt/ui/level3_products_widget.hpp |            source/scwx/qt/ui/level3_products_widget.hpp | ||||||
|  |            source/scwx/qt/ui/line_label.hpp | ||||||
|            source/scwx/qt/ui/open_url_dialog.hpp |            source/scwx/qt/ui/open_url_dialog.hpp | ||||||
|            source/scwx/qt/ui/placefile_dialog.hpp |            source/scwx/qt/ui/placefile_dialog.hpp | ||||||
|            source/scwx/qt/ui/placefile_settings_widget.hpp |            source/scwx/qt/ui/placefile_settings_widget.hpp | ||||||
|  |            source/scwx/qt/ui/marker_dialog.hpp | ||||||
|  |            source/scwx/qt/ui/marker_settings_widget.hpp | ||||||
|            source/scwx/qt/ui/progress_dialog.hpp |            source/scwx/qt/ui/progress_dialog.hpp | ||||||
|            source/scwx/qt/ui/radar_site_dialog.hpp |            source/scwx/qt/ui/radar_site_dialog.hpp | ||||||
|            source/scwx/qt/ui/serial_port_dialog.hpp |            source/scwx/qt/ui/serial_port_dialog.hpp | ||||||
|            source/scwx/qt/ui/settings_dialog.hpp |            source/scwx/qt/ui/settings_dialog.hpp | ||||||
|            source/scwx/qt/ui/update_dialog.hpp) |            source/scwx/qt/ui/update_dialog.hpp | ||||||
|  |            source/scwx/qt/ui/wfo_dialog.hpp) | ||||||
| set(SRC_UI source/scwx/qt/ui/about_dialog.cpp | set(SRC_UI source/scwx/qt/ui/about_dialog.cpp | ||||||
|            source/scwx/qt/ui/alert_dialog.cpp |            source/scwx/qt/ui/alert_dialog.cpp | ||||||
|            source/scwx/qt/ui/alert_dock_widget.cpp |            source/scwx/qt/ui/alert_dock_widget.cpp | ||||||
|            source/scwx/qt/ui/animation_dock_widget.cpp |            source/scwx/qt/ui/animation_dock_widget.cpp | ||||||
|  |            source/scwx/qt/ui/api_key_edit_widget.cpp | ||||||
|            source/scwx/qt/ui/collapsible_group.cpp |            source/scwx/qt/ui/collapsible_group.cpp | ||||||
|            source/scwx/qt/ui/county_dialog.cpp |            source/scwx/qt/ui/county_dialog.cpp | ||||||
|            source/scwx/qt/ui/wfo_dialog.cpp |            source/scwx/qt/ui/custom_layer_dialog.cpp | ||||||
|            source/scwx/qt/ui/download_dialog.cpp |            source/scwx/qt/ui/download_dialog.cpp | ||||||
|  |            source/scwx/qt/ui/edit_line_dialog.cpp | ||||||
|  |            source/scwx/qt/ui/edit_marker_dialog.cpp | ||||||
|            source/scwx/qt/ui/flow_layout.cpp |            source/scwx/qt/ui/flow_layout.cpp | ||||||
|            source/scwx/qt/ui/gps_info_dialog.cpp |            source/scwx/qt/ui/gps_info_dialog.cpp | ||||||
|            source/scwx/qt/ui/hotkey_edit.cpp |            source/scwx/qt/ui/hotkey_edit.cpp | ||||||
|  | @ -278,36 +309,47 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp | ||||||
|            source/scwx/qt/ui/level2_products_widget.cpp |            source/scwx/qt/ui/level2_products_widget.cpp | ||||||
|            source/scwx/qt/ui/level2_settings_widget.cpp |            source/scwx/qt/ui/level2_settings_widget.cpp | ||||||
|            source/scwx/qt/ui/level3_products_widget.cpp |            source/scwx/qt/ui/level3_products_widget.cpp | ||||||
|  |            source/scwx/qt/ui/line_label.cpp | ||||||
|            source/scwx/qt/ui/open_url_dialog.cpp |            source/scwx/qt/ui/open_url_dialog.cpp | ||||||
|            source/scwx/qt/ui/placefile_dialog.cpp |            source/scwx/qt/ui/placefile_dialog.cpp | ||||||
|            source/scwx/qt/ui/placefile_settings_widget.cpp |            source/scwx/qt/ui/placefile_settings_widget.cpp | ||||||
|  |            source/scwx/qt/ui/marker_dialog.cpp | ||||||
|  |            source/scwx/qt/ui/marker_settings_widget.cpp | ||||||
|            source/scwx/qt/ui/progress_dialog.cpp |            source/scwx/qt/ui/progress_dialog.cpp | ||||||
|            source/scwx/qt/ui/radar_site_dialog.cpp |            source/scwx/qt/ui/radar_site_dialog.cpp | ||||||
|            source/scwx/qt/ui/settings_dialog.cpp |            source/scwx/qt/ui/settings_dialog.cpp | ||||||
|            source/scwx/qt/ui/serial_port_dialog.cpp |            source/scwx/qt/ui/serial_port_dialog.cpp | ||||||
|            source/scwx/qt/ui/update_dialog.cpp) |            source/scwx/qt/ui/update_dialog.cpp | ||||||
|  |            source/scwx/qt/ui/wfo_dialog.cpp) | ||||||
| set(UI_UI  source/scwx/qt/ui/about_dialog.ui | set(UI_UI  source/scwx/qt/ui/about_dialog.ui | ||||||
|            source/scwx/qt/ui/alert_dialog.ui |            source/scwx/qt/ui/alert_dialog.ui | ||||||
|            source/scwx/qt/ui/alert_dock_widget.ui |            source/scwx/qt/ui/alert_dock_widget.ui | ||||||
|            source/scwx/qt/ui/animation_dock_widget.ui |            source/scwx/qt/ui/animation_dock_widget.ui | ||||||
|            source/scwx/qt/ui/collapsible_group.ui |            source/scwx/qt/ui/collapsible_group.ui | ||||||
|            source/scwx/qt/ui/county_dialog.ui |            source/scwx/qt/ui/county_dialog.ui | ||||||
|            source/scwx/qt/ui/wfo_dialog.ui |            source/scwx/qt/ui/custom_layer_dialog.ui | ||||||
|  |            source/scwx/qt/ui/edit_line_dialog.ui | ||||||
|  |            source/scwx/qt/ui/edit_marker_dialog.ui | ||||||
|            source/scwx/qt/ui/gps_info_dialog.ui |            source/scwx/qt/ui/gps_info_dialog.ui | ||||||
|            source/scwx/qt/ui/imgui_debug_dialog.ui |            source/scwx/qt/ui/imgui_debug_dialog.ui | ||||||
|            source/scwx/qt/ui/layer_dialog.ui |            source/scwx/qt/ui/layer_dialog.ui | ||||||
|            source/scwx/qt/ui/open_url_dialog.ui |            source/scwx/qt/ui/open_url_dialog.ui | ||||||
|            source/scwx/qt/ui/placefile_dialog.ui |            source/scwx/qt/ui/placefile_dialog.ui | ||||||
|            source/scwx/qt/ui/placefile_settings_widget.ui |            source/scwx/qt/ui/placefile_settings_widget.ui | ||||||
|  |            source/scwx/qt/ui/marker_dialog.ui | ||||||
|  |            source/scwx/qt/ui/marker_settings_widget.ui | ||||||
|            source/scwx/qt/ui/progress_dialog.ui |            source/scwx/qt/ui/progress_dialog.ui | ||||||
|            source/scwx/qt/ui/radar_site_dialog.ui |            source/scwx/qt/ui/radar_site_dialog.ui | ||||||
|            source/scwx/qt/ui/settings_dialog.ui |            source/scwx/qt/ui/settings_dialog.ui | ||||||
|            source/scwx/qt/ui/serial_port_dialog.ui |            source/scwx/qt/ui/serial_port_dialog.ui | ||||||
|            source/scwx/qt/ui/update_dialog.ui) |            source/scwx/qt/ui/update_dialog.ui | ||||||
| set(HDR_UI_SETTINGS source/scwx/qt/ui/settings/hotkey_settings_widget.hpp |            source/scwx/qt/ui/wfo_dialog.ui) | ||||||
|  | set(HDR_UI_SETTINGS source/scwx/qt/ui/settings/alert_palette_settings_widget.hpp | ||||||
|  |                     source/scwx/qt/ui/settings/hotkey_settings_widget.hpp | ||||||
|                     source/scwx/qt/ui/settings/settings_page_widget.hpp |                     source/scwx/qt/ui/settings/settings_page_widget.hpp | ||||||
|                     source/scwx/qt/ui/settings/unit_settings_widget.hpp) |                     source/scwx/qt/ui/settings/unit_settings_widget.hpp) | ||||||
| set(SRC_UI_SETTINGS source/scwx/qt/ui/settings/hotkey_settings_widget.cpp | set(SRC_UI_SETTINGS source/scwx/qt/ui/settings/alert_palette_settings_widget.cpp | ||||||
|  |                     source/scwx/qt/ui/settings/hotkey_settings_widget.cpp | ||||||
|                     source/scwx/qt/ui/settings/settings_page_widget.cpp |                     source/scwx/qt/ui/settings/settings_page_widget.cpp | ||||||
|                     source/scwx/qt/ui/settings/unit_settings_widget.cpp) |                     source/scwx/qt/ui/settings/unit_settings_widget.cpp) | ||||||
| set(HDR_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.hpp | set(HDR_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.hpp | ||||||
|  | @ -322,6 +364,9 @@ set(SRC_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.cpp | ||||||
|                  source/scwx/qt/ui/setup/map_provider_page.cpp |                  source/scwx/qt/ui/setup/map_provider_page.cpp | ||||||
|                  source/scwx/qt/ui/setup/setup_wizard.cpp |                  source/scwx/qt/ui/setup/setup_wizard.cpp | ||||||
|                  source/scwx/qt/ui/setup/welcome_page.cpp) |                  source/scwx/qt/ui/setup/welcome_page.cpp) | ||||||
|  | set(HDR_UI_WIDGETS source/scwx/qt/ui/widgets/focused_combo_box.hpp | ||||||
|  |                    source/scwx/qt/ui/widgets/focused_double_spin_box.hpp | ||||||
|  |                    source/scwx/qt/ui/widgets/focused_spin_box.hpp) | ||||||
| set(HDR_UTIL source/scwx/qt/util/color.hpp | set(HDR_UTIL source/scwx/qt/util/color.hpp | ||||||
|              source/scwx/qt/util/file.hpp |              source/scwx/qt/util/file.hpp | ||||||
|              source/scwx/qt/util/geographic_lib.hpp |              source/scwx/qt/util/geographic_lib.hpp | ||||||
|  | @ -331,8 +376,10 @@ set(HDR_UTIL source/scwx/qt/util/color.hpp | ||||||
|              source/scwx/qt/util/network.hpp |              source/scwx/qt/util/network.hpp | ||||||
|              source/scwx/qt/util/streams.hpp |              source/scwx/qt/util/streams.hpp | ||||||
|              source/scwx/qt/util/texture_atlas.hpp |              source/scwx/qt/util/texture_atlas.hpp | ||||||
|  |              source/scwx/qt/util/q_color_modulate.hpp | ||||||
|              source/scwx/qt/util/q_file_buffer.hpp |              source/scwx/qt/util/q_file_buffer.hpp | ||||||
|              source/scwx/qt/util/q_file_input_stream.hpp |              source/scwx/qt/util/q_file_input_stream.hpp | ||||||
|  |              source/scwx/qt/util/queue_counter.hpp | ||||||
|              source/scwx/qt/util/time.hpp |              source/scwx/qt/util/time.hpp | ||||||
|              source/scwx/qt/util/tooltip.hpp) |              source/scwx/qt/util/tooltip.hpp) | ||||||
| set(SRC_UTIL source/scwx/qt/util/color.cpp | set(SRC_UTIL source/scwx/qt/util/color.cpp | ||||||
|  | @ -343,8 +390,10 @@ set(SRC_UTIL source/scwx/qt/util/color.cpp | ||||||
|              source/scwx/qt/util/maplibre.cpp |              source/scwx/qt/util/maplibre.cpp | ||||||
|              source/scwx/qt/util/network.cpp |              source/scwx/qt/util/network.cpp | ||||||
|              source/scwx/qt/util/texture_atlas.cpp |              source/scwx/qt/util/texture_atlas.cpp | ||||||
|  |              source/scwx/qt/util/q_color_modulate.cpp | ||||||
|              source/scwx/qt/util/q_file_buffer.cpp |              source/scwx/qt/util/q_file_buffer.cpp | ||||||
|              source/scwx/qt/util/q_file_input_stream.cpp |              source/scwx/qt/util/q_file_input_stream.cpp | ||||||
|  |              source/scwx/qt/util/queue_counter.cpp | ||||||
|              source/scwx/qt/util/time.cpp |              source/scwx/qt/util/time.cpp | ||||||
|              source/scwx/qt/util/tooltip.cpp) |              source/scwx/qt/util/tooltip.cpp) | ||||||
| set(HDR_VIEW source/scwx/qt/view/level2_product_view.hpp | set(HDR_VIEW source/scwx/qt/view/level2_product_view.hpp | ||||||
|  | @ -385,13 +434,13 @@ set(JSON_FILES res/config/radar_sites.json) | ||||||
| set(TS_FILES ts/scwx_en_US.ts) | set(TS_FILES ts/scwx_en_US.ts) | ||||||
| 
 | 
 | ||||||
| set(RADAR_SITES_FILE ${scwx-qt_SOURCE_DIR}/res/config/radar_sites.json) | set(RADAR_SITES_FILE ${scwx-qt_SOURCE_DIR}/res/config/radar_sites.json) | ||||||
| set(COUNTY_DBF_FILES ${SCWX_DIR}/data/db/c_05mr24.dbf) | set(COUNTY_DBF_FILES ${SCWX_DIR}/data/db/c_18mr25.dbf) | ||||||
| set(ZONE_DBF_FILES   ${SCWX_DIR}/data/db/fz05mr24.dbf | set(ZONE_DBF_FILES   ${SCWX_DIR}/data/db/fz18mr25.dbf | ||||||
|                      ${SCWX_DIR}/data/db/mz05mr24.dbf |                      ${SCWX_DIR}/data/db/mz18mr25.dbf | ||||||
|                      ${SCWX_DIR}/data/db/oz05mr24.dbf |                      ${SCWX_DIR}/data/db/oz18mr25.dbf | ||||||
|                      ${SCWX_DIR}/data/db/z_05mr24.dbf) |                      ${SCWX_DIR}/data/db/z_18mr25.dbf) | ||||||
| set(STATE_DBF_FILES  ${SCWX_DIR}/data/db/s_05mr24.dbf) | set(STATE_DBF_FILES  ${SCWX_DIR}/data/db/s_18mr25.dbf) | ||||||
| set(WFO_DBF_FILES    ${SCWX_DIR}/data/db/w_05mr24.dbf) | set(WFO_DBF_FILES    ${SCWX_DIR}/data/db/w_18mr25.dbf) | ||||||
| set(COUNTIES_SQLITE_DB ${scwx-qt_BINARY_DIR}/res/db/counties.db) | set(COUNTIES_SQLITE_DB ${scwx-qt_BINARY_DIR}/res/db/counties.db) | ||||||
| 
 | 
 | ||||||
| set(RESOURCE_INPUT  ${scwx-qt_SOURCE_DIR}/res/scwx-qt.rc.in) | set(RESOURCE_INPUT  ${scwx-qt_SOURCE_DIR}/res/scwx-qt.rc.in) | ||||||
|  | @ -429,17 +478,19 @@ set(PROJECT_SOURCES ${HDR_MAIN} | ||||||
|                     ${SRC_UI_SETTINGS} |                     ${SRC_UI_SETTINGS} | ||||||
|                     ${HDR_UI_SETUP} |                     ${HDR_UI_SETUP} | ||||||
|                     ${SRC_UI_SETUP} |                     ${SRC_UI_SETUP} | ||||||
|  |                     ${HDR_UI_WIDGETS} | ||||||
|                     ${HDR_UTIL} |                     ${HDR_UTIL} | ||||||
|                     ${SRC_UTIL} |                     ${SRC_UTIL} | ||||||
|                     ${HDR_VIEW} |                     ${HDR_VIEW} | ||||||
|                     ${SRC_VIEW} |                     ${SRC_VIEW} | ||||||
|                     ${SHADER_FILES} |                     ${SHADER_FILES} | ||||||
|                     ${JSON_FILES} |                     ${JSON_FILES} | ||||||
|                     ${RESOURCE_FILES} |  | ||||||
|                     ${TS_FILES} |                     ${TS_FILES} | ||||||
|                     ${CMAKE_FILES}) |                     ${CMAKE_FILES}) | ||||||
| set(EXECUTABLE_SOURCES ${SRC_EXE_MAIN}) | set(EXECUTABLE_SOURCES ${SRC_EXE_MAIN}) | ||||||
| 
 | 
 | ||||||
|  | qt_add_resources(PROJECT_SOURCES ${RESOURCE_FILES}) | ||||||
|  | 
 | ||||||
| source_group("Header Files\\main"         FILES ${HDR_MAIN}) | source_group("Header Files\\main"         FILES ${HDR_MAIN}) | ||||||
| source_group("Source Files\\main"         FILES ${SRC_MAIN}) | source_group("Source Files\\main"         FILES ${SRC_MAIN}) | ||||||
| source_group("Header Files\\config"       FILES ${HDR_CONFIG}) | source_group("Header Files\\config"       FILES ${HDR_CONFIG}) | ||||||
|  | @ -468,6 +519,7 @@ source_group("Header Files\\ui\\settings" FILES ${HDR_UI_SETTINGS}) | ||||||
| source_group("Source Files\\ui\\settings" FILES ${SRC_UI_SETTINGS}) | source_group("Source Files\\ui\\settings" FILES ${SRC_UI_SETTINGS}) | ||||||
| source_group("Header Files\\ui\\setup"    FILES ${HDR_UI_SETUP}) | source_group("Header Files\\ui\\setup"    FILES ${HDR_UI_SETUP}) | ||||||
| source_group("Source Files\\ui\\setup"    FILES ${SRC_UI_SETUP}) | source_group("Source Files\\ui\\setup"    FILES ${SRC_UI_SETUP}) | ||||||
|  | source_group("Header Files\\ui\\widgets"  FILES ${HDR_UI_WIDGETS}) | ||||||
| source_group("UI Files\\ui"               FILES ${UI_UI}) | source_group("UI Files\\ui"               FILES ${UI_UI}) | ||||||
| source_group("Header Files\\util"         FILES ${HDR_UTIL}) | source_group("Header Files\\util"         FILES ${HDR_UTIL}) | ||||||
| source_group("Source Files\\util"         FILES ${SRC_UTIL}) | source_group("Source Files\\util"         FILES ${SRC_UTIL}) | ||||||
|  | @ -480,6 +532,7 @@ source_group("I18N Files"                 FILES ${TS_FILES}) | ||||||
| 
 | 
 | ||||||
| add_library(scwx-qt OBJECT ${PROJECT_SOURCES}) | add_library(scwx-qt OBJECT ${PROJECT_SOURCES}) | ||||||
| set_property(TARGET scwx-qt PROPERTY AUTOMOC ON) | set_property(TARGET scwx-qt PROPERTY AUTOMOC ON) | ||||||
|  | set_property(TARGET scwx-qt PROPERTY AUTOGEN_ORIGIN_DEPENDS OFF) | ||||||
| 
 | 
 | ||||||
| add_custom_command(OUTPUT  ${COUNTIES_SQLITE_DB} | add_custom_command(OUTPUT  ${COUNTIES_SQLITE_DB} | ||||||
|                    COMMAND ${Python_EXECUTABLE} |                    COMMAND ${Python_EXECUTABLE} | ||||||
|  | @ -526,7 +579,8 @@ else() | ||||||
|                                -v ${SCWX_VERSION} |                                -v ${SCWX_VERSION} | ||||||
|                                -c ${VERSIONS_CACHE} |                                -c ${VERSIONS_CACHE} | ||||||
|                                -i ${VERSIONS_INPUT} |                                -i ${VERSIONS_INPUT} | ||||||
|                                -o ${VERSIONS_HEADER}) |                                -o ${VERSIONS_HEADER} | ||||||
|  |                                -b ${SCWX_BUILD_NUM}) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| add_custom_target(scwx-qt_generate_versions ALL | add_custom_target(scwx-qt_generate_versions ALL | ||||||
|  | @ -572,7 +626,29 @@ set_target_properties(scwx-qt_update_radar_sites   PROPERTIES FOLDER generate) | ||||||
| if (WIN32) | if (WIN32) | ||||||
|     set(APP_ICON_RESOURCE_WINDOWS ${RESOURCE_OUTPUT}) |     set(APP_ICON_RESOURCE_WINDOWS ${RESOURCE_OUTPUT}) | ||||||
|     qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES} ${APP_ICON_RESOURCE_WINDOWS}) |     qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES} ${APP_ICON_RESOURCE_WINDOWS}) | ||||||
|  |     if (SCWX_DISABLE_CONSOLE) | ||||||
|         set_target_properties(supercell-wx PROPERTIES WIN32_EXECUTABLE $<IF:$<CONFIG:Release>,TRUE,FALSE>) |         set_target_properties(supercell-wx PROPERTIES WIN32_EXECUTABLE $<IF:$<CONFIG:Release>,TRUE,FALSE>) | ||||||
|  |     endif() | ||||||
|  | elseif (APPLE) | ||||||
|  |     set(SCWX_ICON "${scwx-qt_SOURCE_DIR}/res/icons/scwx.icns") | ||||||
|  | 
 | ||||||
|  |     set_source_files_properties(${SCWX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") | ||||||
|  | 
 | ||||||
|  |     qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES} ${SCWX_ICON}) | ||||||
|  | 
 | ||||||
|  |     string(TIMESTAMP CURRENT_YEAR "%Y") | ||||||
|  | 
 | ||||||
|  |     set_target_properties(supercell-wx PROPERTIES | ||||||
|  |                           MACOSX_BUNDLE                      TRUE | ||||||
|  |                           MACOSX_BUNDLE_INFO_PLIST           "${scwx-qt_SOURCE_DIR}/res/scwx-qt.plist.in" | ||||||
|  |                           MACOSX_BUNDLE_GUI_IDENTIFIER       "net.supercellwx.app" | ||||||
|  |                           MACOSX_BUNDLE_BUNDLE_NAME          "Supercell Wx" | ||||||
|  |                           MACOSX_BUNDLE_BUNDLE_VERSION       "${SCWX_VERSION}" | ||||||
|  |                           MACOSX_BUNDLE_SHORT_VERSION_STRING "${SCWX_VERSION}" | ||||||
|  |                           MACOSX_BUNDLE_COPYRIGHT            "Copyright ${CURRENT_YEAR} Dan Paulat" | ||||||
|  |                           MACOSX_BUNDLE_ICON_FILE            "scwx.icns" | ||||||
|  |                           MACOSX_BUNDLE_INFO_STRING          "Free and open source advanced weather radar" | ||||||
|  |                           RESOURCE                           ${SCWX_ICON}) | ||||||
| else() | else() | ||||||
|     qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES}) |     qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES}) | ||||||
| endif() | endif() | ||||||
|  | @ -582,12 +658,17 @@ if (WIN32) | ||||||
|     target_compile_definitions(supercell-wx PUBLIC WIN32_LEAN_AND_MEAN) |     target_compile_definitions(supercell-wx PUBLIC WIN32_LEAN_AND_MEAN) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| if (NOT MSVC) | if (LINUX) | ||||||
|     # Qt emit keyword is incompatible with TBB |     # Qt emit keyword is incompatible with TBB | ||||||
|     target_compile_definitions(scwx-qt      PRIVATE QT_NO_EMIT) |     target_compile_definitions(scwx-qt      PRIVATE QT_NO_EMIT) | ||||||
|     target_compile_definitions(supercell-wx PRIVATE QT_NO_EMIT) |     target_compile_definitions(supercell-wx PRIVATE QT_NO_EMIT) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
|  | if (APPLE) | ||||||
|  |     target_compile_definitions(scwx-qt      PRIVATE GL_SILENCE_DEPRECATION) | ||||||
|  |     target_compile_definitions(supercell-wx PRIVATE GL_SILENCE_DEPRECATION) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| target_include_directories(scwx-qt PUBLIC ${scwx-qt_SOURCE_DIR}/source | target_include_directories(scwx-qt PUBLIC ${scwx-qt_SOURCE_DIR}/source | ||||||
|                                           ${FTGL_INCLUDE_DIR} |                                           ${FTGL_INCLUDE_DIR} | ||||||
|                                           ${IMGUI_INCLUDE_DIRS} |                                           ${IMGUI_INCLUDE_DIRS} | ||||||
|  | @ -643,6 +724,25 @@ else() | ||||||
|     target_compile_options(supercell-wx PRIVATE "$<$<CONFIG:Release>:-g>") |     target_compile_options(supercell-wx PRIVATE "$<$<CONFIG:Release>:-g>") | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
|  | if (LINUX) | ||||||
|  |     # Add wayland client packages | ||||||
|  |     find_package(QT NAMES Qt6 | ||||||
|  |                  COMPONENTS WaylandClient | ||||||
|  |                  REQUIRED) | ||||||
|  | 
 | ||||||
|  |     find_package(Qt${QT_VERSION_MAJOR} | ||||||
|  |                  COMPONENTS WaylandClient | ||||||
|  |                  REQUIRED) | ||||||
|  |     target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::WaylandClient) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (LINUX) | ||||||
|  |     find_package(mesa-glu REQUIRED) | ||||||
|  |     target_link_libraries(scwx-qt PUBLIC mesa-glu::mesa-glu) | ||||||
|  | else() | ||||||
|  |     target_link_libraries(scwx-qt PUBLIC OpenGL::GLU) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets | target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets | ||||||
|                                      Qt${QT_VERSION_MAJOR}::OpenGLWidgets |                                      Qt${QT_VERSION_MAJOR}::OpenGLWidgets | ||||||
|                                      Qt${QT_VERSION_MAJOR}::Multimedia |                                      Qt${QT_VERSION_MAJOR}::Multimedia | ||||||
|  | @ -651,6 +751,7 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets | ||||||
|                                      Qt${QT_VERSION_MAJOR}::Svg |                                      Qt${QT_VERSION_MAJOR}::Svg | ||||||
|                                      Boost::json |                                      Boost::json | ||||||
|                                      Boost::timer |                                      Boost::timer | ||||||
|  |                                      Boost::atomic | ||||||
|                                      QMapLibre::Core |                                      QMapLibre::Core | ||||||
|                                      $<$<CXX_COMPILER_ID:MSVC>:opengl32> |                                      $<$<CXX_COMPILER_ID:MSVC>:opengl32> | ||||||
|                                      $<$<CXX_COMPILER_ID:MSVC>:SetupAPI> |                                      $<$<CXX_COMPILER_ID:MSVC>:SetupAPI> | ||||||
|  | @ -658,18 +759,22 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets | ||||||
|                                      GeographicLib::GeographicLib |                                      GeographicLib::GeographicLib | ||||||
|                                      GEOS::geos |                                      GEOS::geos | ||||||
|                                      GEOS::geos_cxx_flags |                                      GEOS::geos_cxx_flags | ||||||
|                                      GLEW::GLEW |                                      glad_gl_core_33 | ||||||
|                                      glm::glm |                                      glm::glm | ||||||
|                                      imgui |                                      imgui | ||||||
|  |                                      qt6ct-common | ||||||
|  |                                      qt6ct-widgets | ||||||
|                                      SQLite::SQLite3 |                                      SQLite::SQLite3 | ||||||
|                                      wxdata) |                                      wxdata) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(supercell-wx PRIVATE scwx-qt | target_link_libraries(supercell-wx PRIVATE scwx-qt | ||||||
|                                            wxdata) |                                            wxdata) | ||||||
| 
 | 
 | ||||||
|  | if (LINUX) | ||||||
|     # Set DT_RUNPATH for Linux targets |     # Set DT_RUNPATH for Linux targets | ||||||
|     set_target_properties(MLNQtCore    PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core |     set_target_properties(MLNQtCore    PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core | ||||||
|     set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") |     set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") | ||||||
|  | endif() | ||||||
| 
 | 
 | ||||||
| install(TARGETS supercell-wx | install(TARGETS supercell-wx | ||||||
|                 MLNQtCore # QMapLibre::Core |                 MLNQtCore # QMapLibre::Core | ||||||
|  | @ -679,7 +784,15 @@ install(TARGETS supercell-wx | ||||||
|                                "^(/usr)?/lib/.*\\.so(\\..*)?" |                                "^(/usr)?/lib/.*\\.so(\\..*)?" | ||||||
|         RUNTIME |         RUNTIME | ||||||
|           COMPONENT supercell-wx |           COMPONENT supercell-wx | ||||||
|  |         BUNDLE | ||||||
|  |           DESTINATION . | ||||||
|  |           COMPONENT supercell-wx | ||||||
|  |           OPTIONAL | ||||||
|         LIBRARY |         LIBRARY | ||||||
|  |           COMPONENT supercell-wx | ||||||
|  |           OPTIONAL | ||||||
|  |         FRAMEWORK | ||||||
|  |           DESTINATION Frameworks | ||||||
|           COMPONENT supercell-wx |           COMPONENT supercell-wx | ||||||
|           OPTIONAL) |           OPTIONAL) | ||||||
| 
 | 
 | ||||||
|  | @ -701,14 +814,64 @@ install(SCRIPT ${deploy_script_qmaplibre_core} | ||||||
| install(SCRIPT ${deploy_script_scwx} | install(SCRIPT ${deploy_script_scwx} | ||||||
|         COMPONENT supercell-wx) |         COMPONENT supercell-wx) | ||||||
| 
 | 
 | ||||||
| if (MSVC) | if (APPLE) | ||||||
|  |     # Install additional script to fix up the bundle | ||||||
|  |     install(CODE [[ | ||||||
|  |             include (BundleUtilities) | ||||||
|  | 
 | ||||||
|  |             # Define the bundle path | ||||||
|  |             set(BUNDLE_PATH "${CMAKE_INSTALL_PREFIX}/supercell-wx.app") | ||||||
|  | 
 | ||||||
|  |             file(GLOB_RECURSE PLUGIN_DYLIBS "${BUNDLE_PATH}/Contents/PlugIns/**/*.dylib") | ||||||
|  | 
 | ||||||
|  |             # Add the correct rpath for plugins to find bundled frameworks | ||||||
|  |             foreach(PLUGIN_DYLIB ${PLUGIN_DYLIBS}) | ||||||
|  |                 execute_process( | ||||||
|  |                     COMMAND install_name_tool -add_rpath "@loader_path/../../Frameworks" | ||||||
|  |                     ${PLUGIN_DYLIB} | ||||||
|  |                     ) | ||||||
|  |             endforeach() | ||||||
|  | 
 | ||||||
|  |             # Fix up the bundle with all dependencies | ||||||
|  |             fixup_bundle( | ||||||
|  |                 "${BUNDLE_PATH}" | ||||||
|  |                 "" | ||||||
|  |                 "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/Frameworks" | ||||||
|  |                 ) | ||||||
|  | 
 | ||||||
|  |             # Re-sign the bundle | ||||||
|  |             execute_process( | ||||||
|  |                 COMMAND codesign --force --deep --sign - "${BUNDLE_PATH}" | ||||||
|  |                 ) | ||||||
|  | 
 | ||||||
|  |             # Verify the bundle | ||||||
|  |             verify_app("${BUNDLE_PATH}") | ||||||
|  | 
 | ||||||
|  |             # Rename to "Supercell Wx.app" | ||||||
|  |             file(REMOVE_RECURSE | ||||||
|  |                  "${CMAKE_INSTALL_PREFIX}/Supercell Wx.app") | ||||||
|  |             file(RENAME | ||||||
|  |                  "${BUNDLE_PATH}" | ||||||
|  |                  "${CMAKE_INSTALL_PREFIX}/Supercell Wx.app") | ||||||
|  | 
 | ||||||
|  |             # Remove extra directories | ||||||
|  |             file(REMOVE_RECURSE | ||||||
|  |                  "${CMAKE_INSTALL_PREFIX}/Frameworks") | ||||||
|  |             file(REMOVE_RECURSE | ||||||
|  |                  "${CMAKE_INSTALL_PREFIX}/lib") | ||||||
|  |             ]] | ||||||
|  |             COMPONENT supercell-wx) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| set(CPACK_PACKAGE_NAME          "Supercell Wx") | set(CPACK_PACKAGE_NAME          "Supercell Wx") | ||||||
| set(CPACK_PACKAGE_VENDOR        "Dan Paulat") | set(CPACK_PACKAGE_VENDOR        "Dan Paulat") | ||||||
|  | set(CPACK_PACKAGE_CHECKSUM      SHA256) | ||||||
|  | set(CPACK_RESOURCE_FILE_LICENSE "${SCWX_DIR}/LICENSE.txt") | ||||||
|  | 
 | ||||||
|  | if (MSVC) | ||||||
|     set(CPACK_PACKAGE_FILE_NAME           "supercell-wx-v${SCWX_VERSION}-windows-x64") |     set(CPACK_PACKAGE_FILE_NAME           "supercell-wx-v${SCWX_VERSION}-windows-x64") | ||||||
|     set(CPACK_PACKAGE_INSTALL_DIRECTORY   "Supercell Wx") |     set(CPACK_PACKAGE_INSTALL_DIRECTORY   "Supercell Wx") | ||||||
|     set(CPACK_PACKAGE_ICON                "${CMAKE_CURRENT_SOURCE_DIR}/res/icons/scwx-256.ico") |     set(CPACK_PACKAGE_ICON                "${CMAKE_CURRENT_SOURCE_DIR}/res/icons/scwx-256.ico") | ||||||
|     set(CPACK_PACKAGE_CHECKSUM            SHA256) |  | ||||||
|     set(CPACK_RESOURCE_FILE_LICENSE       "${SCWX_DIR}/LICENSE.txt") |  | ||||||
|     set(CPACK_GENERATOR                   WIX) |     set(CPACK_GENERATOR                   WIX) | ||||||
|     set(CPACK_PACKAGE_EXECUTABLES         "supercell-wx;Supercell Wx") |     set(CPACK_PACKAGE_EXECUTABLES         "supercell-wx;Supercell Wx") | ||||||
|     set(CPACK_WIX_UPGRADE_GUID            36AD0F51-4D4F-4B5D-AB61-94C6B4E4FE1C) |     set(CPACK_WIX_UPGRADE_GUID            36AD0F51-4D4F-4B5D-AB61-94C6B4E4FE1C) | ||||||
|  | @ -720,5 +883,15 @@ if (MSVC) | ||||||
|     set(CPACK_INSTALL_CMAKE_PROJECTS |     set(CPACK_INSTALL_CMAKE_PROJECTS | ||||||
|         "${CMAKE_CURRENT_BINARY_DIR};${CMAKE_PROJECT_NAME};supercell-wx;/") |         "${CMAKE_CURRENT_BINARY_DIR};${CMAKE_PROJECT_NAME};supercell-wx;/") | ||||||
| 
 | 
 | ||||||
|  |     include(CPack) | ||||||
|  | elseif(APPLE) | ||||||
|  |     set(CPACK_PACKAGE_FILE_NAME   "supercell-wx-v${SCWX_VERSION}-macos") | ||||||
|  |     set(CPACK_PACKAGE_ICON        "${SCWX_ICON}") | ||||||
|  |     set(CPACK_PACKAGE_VERSION     "${SCWX_VERSION}") | ||||||
|  | 
 | ||||||
|  |     set(CPACK_GENERATOR DragNDrop) | ||||||
|  | 
 | ||||||
|  |     set(CPACK_COMPONENTS_ALL supercell-wx) | ||||||
|  | 
 | ||||||
|     include(CPack) |     include(CPack) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | @ -32,6 +32,10 @@ | ||||||
|         <file>res/icons/font-awesome-6/angles-up-solid.svg</file> |         <file>res/icons/font-awesome-6/angles-up-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/backward-step-solid.svg</file> |         <file>res/icons/font-awesome-6/backward-step-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/book-solid.svg</file> |         <file>res/icons/font-awesome-6/book-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/briefcase-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/building-columns-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/building-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/caravan-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/copy-regular.svg</file> |         <file>res/icons/font-awesome-6/copy-regular.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/discord.svg</file> |         <file>res/icons/font-awesome-6/discord.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/earth-americas-solid.svg</file> |         <file>res/icons/font-awesome-6/earth-americas-solid.svg</file> | ||||||
|  | @ -40,8 +44,11 @@ | ||||||
|         <file>res/icons/font-awesome-6/gears-solid.svg</file> |         <file>res/icons/font-awesome-6/gears-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/github.svg</file> |         <file>res/icons/font-awesome-6/github.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/house-solid.svg</file> |         <file>res/icons/font-awesome-6/house-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/house-solid-white.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/keyboard-regular.svg</file> |         <file>res/icons/font-awesome-6/keyboard-regular.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/layer-group-solid.svg</file> |         <file>res/icons/font-awesome-6/layer-group-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/location-crosshairs-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/location-pin.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/palette-solid.svg</file> |         <file>res/icons/font-awesome-6/palette-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/pause-solid.svg</file> |         <file>res/icons/font-awesome-6/pause-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/play-solid.svg</file> |         <file>res/icons/font-awesome-6/play-solid.svg</file> | ||||||
|  | @ -53,7 +60,9 @@ | ||||||
|         <file>res/icons/font-awesome-6/square-minus-regular.svg</file> |         <file>res/icons/font-awesome-6/square-minus-regular.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/square-plus-regular.svg</file> |         <file>res/icons/font-awesome-6/square-plus-regular.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/star-solid.svg</file> |         <file>res/icons/font-awesome-6/star-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/star-solid-white.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/stop-solid.svg</file> |         <file>res/icons/font-awesome-6/stop-solid.svg</file> | ||||||
|  |         <file>res/icons/font-awesome-6/tent-solid.svg</file> | ||||||
|         <file>res/icons/font-awesome-6/volume-high-solid.svg</file> |         <file>res/icons/font-awesome-6/volume-high-solid.svg</file> | ||||||
|         <file>res/palettes/wct/CC.pal</file> |         <file>res/palettes/wct/CC.pal</file> | ||||||
|         <file>res/palettes/wct/Default16.pal</file> |         <file>res/palettes/wct/Default16.pal</file> | ||||||
|  | @ -70,11 +79,20 @@ | ||||||
|         <file>res/palettes/wct/SW.pal</file> |         <file>res/palettes/wct/SW.pal</file> | ||||||
|         <file>res/palettes/wct/VIL.pal</file> |         <file>res/palettes/wct/VIL.pal</file> | ||||||
|         <file>res/palettes/wct/ZDR.pal</file> |         <file>res/palettes/wct/ZDR.pal</file> | ||||||
|  |         <file alias="res/qt6ct_colors/airy.conf">../external/qt6ct/colors/airy.conf</file> | ||||||
|  |         <file alias="res/qt6ct_colors/darker.conf">../external/qt6ct/colors/darker.conf</file> | ||||||
|  |         <file alias="res/qt6ct_colors/dusk.conf">../external/qt6ct/colors/dusk.conf</file> | ||||||
|  |         <file alias="res/qt6ct_colors/ia_ora.conf">../external/qt6ct/colors/ia_ora.conf</file> | ||||||
|  |         <file alias="res/qt6ct_colors/sand.conf">../external/qt6ct/colors/sand.conf</file> | ||||||
|  |         <file alias="res/qt6ct_colors/simple.conf">../external/qt6ct/colors/simple.conf</file> | ||||||
|  |         <file alias="res/qt6ct_colors/waves.conf">../external/qt6ct/colors/waves.conf</file> | ||||||
|         <file>res/textures/lines/default-1x7.png</file> |         <file>res/textures/lines/default-1x7.png</file> | ||||||
|         <file>res/textures/lines/test-pattern.png</file> |         <file>res/textures/lines/test-pattern.png</file> | ||||||
|         <file>res/textures/images/cursor-17.png</file> |         <file>res/textures/images/cursor-17.png</file> | ||||||
|         <file>res/textures/images/crosshairs-24.png</file> |         <file>res/textures/images/crosshairs-24.png</file> | ||||||
|         <file>res/textures/images/dot-3.png</file> |         <file>res/textures/images/dot-3.png</file> | ||||||
|  |         <file>res/textures/images/dot.svg</file> | ||||||
|  |         <file>res/textures/images/location-marker.svg</file> | ||||||
|         <file>res/textures/images/mapbox-logo.svg</file> |         <file>res/textures/images/mapbox-logo.svg</file> | ||||||
|         <file>res/textures/images/maptiler-logo.svg</file> |         <file>res/textures/images/maptiler-logo.svg</file> | ||||||
|     </qresource> |     </qresource> | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <boost/json.hpp> | #include <boost/json.hpp> | ||||||
| 
 | 
 | ||||||
| #if !defined(_MSC_VER) | #if (__cpp_lib_chrono < 201907L) | ||||||
| #   include <date/date.h> | #   include <date/date.h> | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -51,6 +51,7 @@ public: | ||||||
|    std::string state_ {}; |    std::string state_ {}; | ||||||
|    std::string place_ {}; |    std::string place_ {}; | ||||||
|    std::string tzName_ {}; |    std::string tzName_ {}; | ||||||
|  |    double      altitude_ {0.0}; | ||||||
| 
 | 
 | ||||||
|    const scwx::util::time_zone* timeZone_ {nullptr}; |    const scwx::util::time_zone* timeZone_ {nullptr}; | ||||||
| }; | }; | ||||||
|  | @ -142,6 +143,11 @@ const scwx::util::time_zone* RadarSite::time_zone() const | ||||||
|    return p->timeZone_; |    return p->timeZone_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | units::length::feet<double> RadarSite::altitude() const | ||||||
|  | { | ||||||
|  |    return units::length::feet<double>(p->altitude_); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::shared_ptr<RadarSite> RadarSite::Get(const std::string& id) | std::shared_ptr<RadarSite> RadarSite::Get(const std::string& id) | ||||||
| { | { | ||||||
|    std::shared_lock           lock(siteMutex_); |    std::shared_lock           lock(siteMutex_); | ||||||
|  | @ -239,7 +245,7 @@ size_t RadarSite::ReadConfig(const std::string& path) | ||||||
|    bool   dataValid  = true; |    bool   dataValid  = true; | ||||||
|    size_t sitesAdded = 0; |    size_t sitesAdded = 0; | ||||||
| 
 | 
 | ||||||
|    boost::json::value j = util::json::ReadJsonFile(path); |    boost::json::value j = util::json::ReadJsonQFile(path); | ||||||
| 
 | 
 | ||||||
|    dataValid = j.is_array(); |    dataValid = j.is_array(); | ||||||
| 
 | 
 | ||||||
|  | @ -268,10 +274,12 @@ size_t RadarSite::ReadConfig(const std::string& path) | ||||||
|             site->p->state_ = boost::json::value_to<std::string>(o.at("state")); |             site->p->state_ = boost::json::value_to<std::string>(o.at("state")); | ||||||
|             site->p->place_ = boost::json::value_to<std::string>(o.at("place")); |             site->p->place_ = boost::json::value_to<std::string>(o.at("place")); | ||||||
|             site->p->tzName_ = boost::json::value_to<std::string>(o.at("tz")); |             site->p->tzName_ = boost::json::value_to<std::string>(o.at("tz")); | ||||||
|  |             site->p->altitude_ = | ||||||
|  |                boost::json::value_to<double>(o.at("elevation")); | ||||||
| 
 | 
 | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
| #if defined(_MSC_VER) | #if (__cpp_lib_chrono >= 201907L) | ||||||
|                using namespace std::chrono; |                using namespace std::chrono; | ||||||
| #else | #else | ||||||
|                using namespace date; |                using namespace date; | ||||||
|  |  | ||||||
|  | @ -6,12 +6,9 @@ | ||||||
| #include <optional> | #include <optional> | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
|  | #include <units/length.h> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::config | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace config |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| class RadarSiteImpl; | class RadarSiteImpl; | ||||||
|  | @ -28,18 +25,19 @@ public: | ||||||
|    RadarSite(RadarSite&&) noexcept; |    RadarSite(RadarSite&&) noexcept; | ||||||
|    RadarSite& operator=(RadarSite&&) noexcept; |    RadarSite& operator=(RadarSite&&) noexcept; | ||||||
| 
 | 
 | ||||||
|    std::string type() const; |    [[nodiscard]] std::string                 type() const; | ||||||
|    std::string type_name() const; |    [[nodiscard]] std::string                 type_name() const; | ||||||
|    std::string id() const; |    [[nodiscard]] std::string                 id() const; | ||||||
|    double      latitude() const; |    [[nodiscard]] double                      latitude() const; | ||||||
|    double      longitude() const; |    [[nodiscard]] double                      longitude() const; | ||||||
|    std::string country() const; |    [[nodiscard]] std::string                 country() const; | ||||||
|    std::string state() const; |    [[nodiscard]] std::string                 state() const; | ||||||
|    std::string place() const; |    [[nodiscard]] std::string                 place() const; | ||||||
|    std::string location_name() const; |    [[nodiscard]] std::string                 location_name() const; | ||||||
|    std::string tz_name() const; |    [[nodiscard]] std::string                 tz_name() const; | ||||||
|  |    [[nodiscard]] units::length::feet<double> altitude() const; | ||||||
| 
 | 
 | ||||||
|    const scwx::util::time_zone* time_zone() const; |    [[nodiscard]] const scwx::util::time_zone* time_zone() const; | ||||||
| 
 | 
 | ||||||
|    static std::shared_ptr<RadarSite>              Get(const std::string& id); |    static std::shared_ptr<RadarSite>              Get(const std::string& id); | ||||||
|    static std::vector<std::shared_ptr<RadarSite>> GetAll(); |    static std::vector<std::shared_ptr<RadarSite>> GetAll(); | ||||||
|  | @ -67,6 +65,4 @@ private: | ||||||
| 
 | 
 | ||||||
| std::string GetRadarIdFromSiteId(const std::string& siteId); | std::string GetRadarIdFromSiteId(const std::string& siteId); | ||||||
| 
 | 
 | ||||||
| } // namespace config
 | } // namespace scwx::qt::config
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -30,13 +30,11 @@ static const std::string logPrefix_ = "scwx::qt::gl::draw::draw_item"; | ||||||
| class DrawItem::Impl | class DrawItem::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit Impl(OpenGLFunctions& gl) : gl_ {gl} {} |    explicit Impl() = default; | ||||||
|    ~Impl() {} |    ~Impl()         = default; | ||||||
| 
 |  | ||||||
|    OpenGLFunctions& gl_; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| DrawItem::DrawItem(OpenGLFunctions& gl) : p(std::make_unique<Impl>(gl)) {} | DrawItem::DrawItem() : p(std::make_unique<Impl>()) {} | ||||||
| DrawItem::~DrawItem() = default; | DrawItem::~DrawItem() = default; | ||||||
| 
 | 
 | ||||||
| DrawItem::DrawItem(DrawItem&&) noexcept            = default; | DrawItem::DrawItem(DrawItem&&) noexcept            = default; | ||||||
|  | @ -74,7 +72,7 @@ void DrawItem::UseDefaultProjection( | ||||||
|                                      0.0f, |                                      0.0f, | ||||||
|                                      static_cast<float>(params.height)); |                                      static_cast<float>(params.height)); | ||||||
| 
 | 
 | ||||||
|    p->gl_.glUniformMatrix4fv( |    glUniformMatrix4fv( | ||||||
|       uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(projection)); |       uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(projection)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -91,7 +89,7 @@ void DrawItem::UseRotationProjection( | ||||||
|                             glm::radians<float>(params.bearing), |                             glm::radians<float>(params.bearing), | ||||||
|                             glm::vec3(0.0f, 0.0f, 1.0f)); |                             glm::vec3(0.0f, 0.0f, 1.0f)); | ||||||
| 
 | 
 | ||||||
|    p->gl_.glUniformMatrix4fv( |    glUniformMatrix4fv( | ||||||
|       uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(projection)); |       uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(projection)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -100,16 +98,14 @@ void DrawItem::UseMapProjection( | ||||||
|    GLint                                         uMVPMatrixLocation, |    GLint                                         uMVPMatrixLocation, | ||||||
|    GLint                                         uMapScreenCoordLocation) |    GLint                                         uMapScreenCoordLocation) | ||||||
| { | { | ||||||
|    OpenGLFunctions& gl = p->gl_; |  | ||||||
| 
 |  | ||||||
|    const glm::mat4 uMVPMatrix = util::maplibre::GetMapMatrix(params); |    const glm::mat4 uMVPMatrix = util::maplibre::GetMapMatrix(params); | ||||||
| 
 | 
 | ||||||
|    gl.glUniform2fv(uMapScreenCoordLocation, |    glUniform2fv(uMapScreenCoordLocation, | ||||||
|                 1, |                 1, | ||||||
|                 glm::value_ptr(util::maplibre::LatLongToScreenCoordinate( |                 glm::value_ptr(util::maplibre::LatLongToScreenCoordinate( | ||||||
|                    {params.latitude, params.longitude}))); |                    {params.latitude, params.longitude}))); | ||||||
| 
 | 
 | ||||||
|    gl.glUniformMatrix4fv( |    glUniformMatrix4fv( | ||||||
|       uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(uMVPMatrix)); |       uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(uMVPMatrix)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,8 +21,8 @@ namespace draw | ||||||
| class DrawItem | class DrawItem | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit DrawItem(OpenGLFunctions& gl); |    explicit DrawItem(); | ||||||
|    ~DrawItem(); |    virtual ~DrawItem(); | ||||||
| 
 | 
 | ||||||
|    DrawItem(const DrawItem&)            = delete; |    DrawItem(const DrawItem&)            = delete; | ||||||
|    DrawItem& operator=(const DrawItem&) = delete; |    DrawItem& operator=(const DrawItem&) = delete; | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| #include <scwx/qt/util/texture_atlas.hpp> | #include <scwx/qt/util/texture_atlas.hpp> | ||||||
| #include <scwx/qt/util/tooltip.hpp> | #include <scwx/qt/util/tooltip.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <execution> | #include <execution> | ||||||
| 
 | 
 | ||||||
|  | @ -38,7 +39,7 @@ static constexpr std::size_t kIntegersPerVertex_ = 4; | ||||||
| static constexpr std::size_t kIntegerBufferLength_ = | static constexpr std::size_t kIntegerBufferLength_ = | ||||||
|    kNumTriangles * kVerticesPerTriangle * kIntegersPerVertex_; |    kNumTriangles * kVerticesPerTriangle * kIntegersPerVertex_; | ||||||
| 
 | 
 | ||||||
| struct GeoIconDrawItem | struct GeoIconDrawItem : types::EventHandler | ||||||
| { | { | ||||||
|    units::length::nautical_miles<double>       threshold_ {}; |    units::length::nautical_miles<double>       threshold_ {}; | ||||||
|    std::chrono::sys_time<std::chrono::seconds> startTime_ {}; |    std::chrono::sys_time<std::chrono::seconds> startTime_ {}; | ||||||
|  | @ -144,7 +145,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| GeoIcons::GeoIcons(const std::shared_ptr<GlContext>& context) : | GeoIcons::GeoIcons(const std::shared_ptr<GlContext>& context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| GeoIcons::~GeoIcons() = default; | GeoIcons::~GeoIcons() = default; | ||||||
|  | @ -165,8 +166,6 @@ void GeoIcons::set_thresholded(bool thresholded) | ||||||
| 
 | 
 | ||||||
| void GeoIcons::Initialize() | void GeoIcons::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -181,88 +180,95 @@ void GeoIcons::Initialize() | ||||||
|    p->uSelectedTimeLocation_ = |    p->uSelectedTimeLocation_ = | ||||||
|       p->shaderProgram_->GetUniformLocation("uSelectedTime"); |       p->shaderProgram_->GetUniformLocation("uSelectedTime"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |    glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
|  | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
| 
 | 
 | ||||||
|    // aLatLong
 |    // aLatLong
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aModulate
 |    // aModulate
 | ||||||
|    gl.glVertexAttribPointer(3, |    glVertexAttribPointer(3, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    // aAngle
 |    // aAngle
 | ||||||
|    gl.glVertexAttribPointer(4, |    glVertexAttribPointer(4, | ||||||
|                          1, |                          1, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(8 * sizeof(float))); |                          reinterpret_cast<void*>(8 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(4); |    glEnableVertexAttribArray(4); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aTexCoord
 |    // aTexCoord
 | ||||||
|    gl.glVertexAttribPointer(2, |    glVertexAttribPointer(2, | ||||||
|                          3, |                          3, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerTexCoord * sizeof(float), |                          kPointsPerTexCoord * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(2); |    glEnableVertexAttribArray(2); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aThreshold
 |    // aThreshold
 | ||||||
|    gl.glVertexAttribIPointer(5, //
 |    glVertexAttribIPointer(5, //
 | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           0, |                           0, | ||||||
|                           static_cast<void*>(0)); |                           static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(5); |    glEnableVertexAttribArray(5); | ||||||
| 
 | 
 | ||||||
|    // aTimeRange
 |    // aTimeRange
 | ||||||
|    gl.glVertexAttribIPointer(6, //
 |    glVertexAttribIPointer(6, //
 | ||||||
|                           2, |                           2, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           reinterpret_cast<void*>(1 * sizeof(GLint))); |                           reinterpret_cast<void*>(1 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(6); |    glEnableVertexAttribArray(6); | ||||||
| 
 | 
 | ||||||
|    // aDisplayed
 |    // aDisplayed
 | ||||||
|    gl.glVertexAttribPointer(7, |    glVertexAttribIPointer(7, | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                             GL_FALSE, |  | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                             reinterpret_cast<void*>(3 * sizeof(float))); |                           reinterpret_cast<void*>(3 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(7); |    glEnableVertexAttribArray(7); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -284,9 +290,7 @@ void GeoIcons::Render(const QMapLibre::CustomLayerRenderParameters& params, | ||||||
| 
 | 
 | ||||||
|    if (!p->currentIconList_.empty()) |    if (!p->currentIconList_.empty()) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(textureAtlasChanged); |       p->Update(textureAtlasChanged); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -299,40 +303,38 @@ void GeoIcons::Render(const QMapLibre::CustomLayerRenderParameters& params, | ||||||
|          // If thresholding is enabled, set the map distance
 |          // If thresholding is enabled, set the map distance
 | ||||||
|          units::length::nautical_miles<float> mapDistance = |          units::length::nautical_miles<float> mapDistance = | ||||||
|             util::maplibre::GetMapDistance(params); |             util::maplibre::GetMapDistance(params); | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); |          glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          // If thresholding is disabled, set the map distance to 0
 |          // If thresholding is disabled, set the map distance to 0
 | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); |          glUniform1f(p->uMapDistanceLocation_, 0.0f); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Selected time
 |       // Selected time
 | ||||||
|       std::chrono::system_clock::time_point selectedTime = |       std::chrono::system_clock::time_point selectedTime = | ||||||
|          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|             std::chrono::system_clock::now() : |             scwx::util::time::now() : | ||||||
|             p->selectedTime_; |             p->selectedTime_; | ||||||
|       gl.glUniform1i( |       glUniform1i( | ||||||
|          p->uSelectedTimeLocation_, |          p->uSelectedTimeLocation_, | ||||||
|          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( |          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( | ||||||
|                                selectedTime.time_since_epoch()) |                                selectedTime.time_since_epoch()) | ||||||
|                                .count())); |                                .count())); | ||||||
| 
 | 
 | ||||||
|       // Interpolate texture coordinates
 |       // Interpolate texture coordinates
 | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||||
| 
 | 
 | ||||||
|       // Draw icons
 |       // Draw icons
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); |       glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GeoIcons::Deinitialize() | void GeoIcons::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->iconMutex_}; |    std::unique_lock lock {p->iconMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -692,7 +694,7 @@ void GeoIcons::Impl::UpdateSingleBuffer( | ||||||
|                                hoverIcons.end(), |                                hoverIcons.end(), | ||||||
|                                [&di](auto& entry) { return entry.di_ == di; }); |                                [&di](auto& entry) { return entry.di_ == di; }); | ||||||
| 
 | 
 | ||||||
|    if (di->visible_ && !di->hoverText_.empty()) |    if (di->visible_ && (!di->hoverText_.empty() || di->event_ != nullptr)) | ||||||
|    { |    { | ||||||
|       const units::angle::radians<double> radians = angle; |       const units::angle::radians<double> radians = angle; | ||||||
| 
 | 
 | ||||||
|  | @ -848,8 +850,6 @@ void GeoIcons::Impl::UpdateModifiedIconBuffers() | ||||||
| 
 | 
 | ||||||
| void GeoIcons::Impl::Update(bool textureAtlasChanged) | void GeoIcons::Impl::Update(bool textureAtlasChanged) | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|    UpdateModifiedIconBuffers(); |    UpdateModifiedIconBuffers(); | ||||||
| 
 | 
 | ||||||
|    // If the texture atlas has changed
 |    // If the texture atlas has changed
 | ||||||
|  | @ -865,9 +865,10 @@ void GeoIcons::Impl::Update(bool textureAtlasChanged) | ||||||
|       UpdateTextureBuffer(); |       UpdateTextureBuffer(); | ||||||
| 
 | 
 | ||||||
|       // Buffer texture data
 |       // Buffer texture data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * textureBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * textureBuffer_.size()), | ||||||
|          textureBuffer_.data(), |          textureBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  | @ -878,16 +879,18 @@ void GeoIcons::Impl::Update(bool textureAtlasChanged) | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       // Buffer vertex data
 |       // Buffer vertex data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * currentIconBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * currentIconBuffer_.size()), | ||||||
|          currentIconBuffer_.data(), |          currentIconBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       // Buffer threshold data
 |       // Buffer threshold data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLint) * currentIntegerBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLint) * currentIntegerBuffer_.size()), | ||||||
|          currentIntegerBuffer_.data(), |          currentIntegerBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  | @ -904,7 +907,7 @@ bool GeoIcons::RunMousePicking( | ||||||
|    const QPointF&   mouseGlobalPos, |    const QPointF&   mouseGlobalPos, | ||||||
|    const glm::vec2& mouseCoords, |    const glm::vec2& mouseCoords, | ||||||
|    const common::Coordinate& /* mouseGeoCoords */, |    const common::Coordinate& /* mouseGeoCoords */, | ||||||
|    std::shared_ptr<types::EventHandler>& /* eventHandler */) |    std::shared_ptr<types::EventHandler>& eventHandler) | ||||||
| { | { | ||||||
|    std::unique_lock lock {p->iconMutex_}; |    std::unique_lock lock {p->iconMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -928,7 +931,7 @@ bool GeoIcons::RunMousePicking( | ||||||
|    // If no time has been selected, use the current time
 |    // If no time has been selected, use the current time
 | ||||||
|    std::chrono::system_clock::time_point selectedTime = |    std::chrono::system_clock::time_point selectedTime = | ||||||
|       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|          std::chrono::system_clock::now() : |          scwx::util::time::now() : | ||||||
|          p->selectedTime_; |          p->selectedTime_; | ||||||
| 
 | 
 | ||||||
|    // For each pickable icon
 |    // For each pickable icon
 | ||||||
|  | @ -947,8 +950,10 @@ bool GeoIcons::RunMousePicking( | ||||||
|                    units::length::nautical_miles<double> {icon.di_->threshold_} |                    units::length::nautical_miles<double> {icon.di_->threshold_} | ||||||
|                       .value())) < 999 && |                       .value())) < 999 && | ||||||
| 
 | 
 | ||||||
|                 // Map distance is beyond the threshold
 |                 // Map distance is beyond/within the threshold
 | ||||||
|                 icon.di_->threshold_ < mapDistance) || |                 icon.di_->threshold_ < mapDistance && | ||||||
|  |                 (icon.di_->threshold_.value() >= 0.0 || | ||||||
|  |                  -(icon.di_->threshold_) > mapDistance)) || | ||||||
| 
 | 
 | ||||||
|              ( |              ( | ||||||
|                 // Geo icon has a start time
 |                 // Geo icon has a start time
 | ||||||
|  | @ -992,12 +997,27 @@ bool GeoIcons::RunMousePicking( | ||||||
|    if (it != p->currentHoverIcons_.crend()) |    if (it != p->currentHoverIcons_.crend()) | ||||||
|    { |    { | ||||||
|       itemPicked = true; |       itemPicked = true; | ||||||
|  |       if (!it->di_->hoverText_.empty()) | ||||||
|  |       { | ||||||
|  |          // Show tooltip
 | ||||||
|          util::tooltip::Show(it->di_->hoverText_, mouseGlobalPos); |          util::tooltip::Show(it->di_->hoverText_, mouseGlobalPos); | ||||||
|       } |       } | ||||||
|  |       if (it->di_->event_ != nullptr) | ||||||
|  |       { | ||||||
|  |          eventHandler = it->di_; | ||||||
|  |       } | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    return itemPicked; |    return itemPicked; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void GeoIcons::RegisterEventHandler( | ||||||
|  |    const std::shared_ptr<GeoIconDrawItem>& di, | ||||||
|  |    const std::function<void(QEvent*)>&     eventHandler) | ||||||
|  | { | ||||||
|  |    di->event_ = eventHandler; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace draw
 | } // namespace draw
 | ||||||
| } // namespace gl
 | } // namespace gl
 | ||||||
| } // namespace qt
 | } // namespace qt
 | ||||||
|  |  | ||||||
|  | @ -183,6 +183,16 @@ public: | ||||||
|     */ |     */ | ||||||
|    void FinishIcons(); |    void FinishIcons(); | ||||||
| 
 | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Registers an event handler for an icon. | ||||||
|  |     * | ||||||
|  |     * @param [in] di Icon draw item | ||||||
|  |     * @param [in] eventHandler Event handler function | ||||||
|  |     */ | ||||||
|  |    static void | ||||||
|  |    RegisterEventHandler(const std::shared_ptr<GeoIconDrawItem>& di, | ||||||
|  |                         const std::function<void(QEvent*)>&     eventHandler); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|    class Impl; |    class Impl; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| #include <scwx/qt/util/maplibre.hpp> | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/qt/util/tooltip.hpp> | #include <scwx/qt/util/tooltip.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <execution> | #include <execution> | ||||||
| 
 | 
 | ||||||
|  | @ -50,6 +51,7 @@ struct GeoLineDrawItem : types::EventHandler | ||||||
|    units::angle::degrees<float> angle_ {}; |    units::angle::degrees<float> angle_ {}; | ||||||
|    std::string                  hoverText_ {}; |    std::string                  hoverText_ {}; | ||||||
|    GeoLines::HoverCallback      hoverCallback_ {nullptr}; |    GeoLines::HoverCallback      hoverCallback_ {nullptr}; | ||||||
|  |    size_t                       lineIndex_ {0}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class GeoLines::Impl | class GeoLines::Impl | ||||||
|  | @ -87,10 +89,10 @@ public: | ||||||
|    void UpdateBuffers(); |    void UpdateBuffers(); | ||||||
|    void UpdateModifiedLineBuffers(); |    void UpdateModifiedLineBuffers(); | ||||||
|    void UpdateSingleBuffer(const std::shared_ptr<GeoLineDrawItem>& di, |    void UpdateSingleBuffer(const std::shared_ptr<GeoLineDrawItem>& di, | ||||||
|                            std::size_t                             lineIndex, |  | ||||||
|                            std::vector<float>&                     linesBuffer, |                            std::vector<float>&                     linesBuffer, | ||||||
|                            std::vector<GLint>&                 integerBuffer, |                            std::vector<GLint>&                 integerBuffer, | ||||||
|                            std::vector<LineHoverEntry>& hoverLines); |                            std::unordered_map<std::shared_ptr<GeoLineDrawItem>, | ||||||
|  |                                               LineHoverEntry>& hoverLines); | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<GlContext> context_; |    std::shared_ptr<GlContext> context_; | ||||||
| 
 | 
 | ||||||
|  | @ -112,8 +114,10 @@ public: | ||||||
|    std::vector<float> newLinesBuffer_ {}; |    std::vector<float> newLinesBuffer_ {}; | ||||||
|    std::vector<GLint> newIntegerBuffer_ {}; |    std::vector<GLint> newIntegerBuffer_ {}; | ||||||
| 
 | 
 | ||||||
|    std::vector<LineHoverEntry> currentHoverLines_ {}; |    std::unordered_map<std::shared_ptr<GeoLineDrawItem>, LineHoverEntry> | ||||||
|    std::vector<LineHoverEntry> newHoverLines_ {}; |       currentHoverLines_ {}; | ||||||
|  |    std::unordered_map<std::shared_ptr<GeoLineDrawItem>, LineHoverEntry> | ||||||
|  |       newHoverLines_ {}; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<ShaderProgram> shaderProgram_; |    std::shared_ptr<ShaderProgram> shaderProgram_; | ||||||
|    GLint                          uMVPMatrixLocation_; |    GLint                          uMVPMatrixLocation_; | ||||||
|  | @ -127,7 +131,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| GeoLines::GeoLines(std::shared_ptr<GlContext> context) : | GeoLines::GeoLines(std::shared_ptr<GlContext> context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| GeoLines::~GeoLines() = default; | GeoLines::~GeoLines() = default; | ||||||
|  | @ -148,8 +152,6 @@ void GeoLines::set_thresholded(bool thresholded) | ||||||
| 
 | 
 | ||||||
| void GeoLines::Initialize() | void GeoLines::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -164,79 +166,86 @@ void GeoLines::Initialize() | ||||||
|    p->uSelectedTimeLocation_ = |    p->uSelectedTimeLocation_ = | ||||||
|       p->shaderProgram_->GetUniformLocation("uSelectedTime"); |       p->shaderProgram_->GetUniformLocation("uSelectedTime"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |    glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, |    glBufferData(GL_ARRAY_BUFFER, | ||||||
|                 sizeof(float) * kLineBufferLength_, |                 sizeof(float) * kLineBufferLength_, | ||||||
|                 nullptr, |                 nullptr, | ||||||
|                 GL_DYNAMIC_DRAW); |                 GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  | 
 | ||||||
|    // aLatLong
 |    // aLatLong
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aModulate
 |    // aModulate
 | ||||||
|    gl.glVertexAttribPointer(3, |    glVertexAttribPointer(3, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    // aAngle
 |    // aAngle
 | ||||||
|    gl.glVertexAttribPointer(4, |    glVertexAttribPointer(4, | ||||||
|                          1, |                          1, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(8 * sizeof(float))); |                          reinterpret_cast<void*>(8 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(4); |    glEnableVertexAttribArray(4); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aThreshold
 |    // aThreshold
 | ||||||
|    gl.glVertexAttribIPointer(5, //
 |    glVertexAttribIPointer(5, //
 | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           static_cast<void*>(0)); |                           static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(5); |    glEnableVertexAttribArray(5); | ||||||
| 
 | 
 | ||||||
|    // aTimeRange
 |    // aTimeRange
 | ||||||
|    gl.glVertexAttribIPointer(6, //
 |    glVertexAttribIPointer(6, //
 | ||||||
|                           2, |                           2, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           reinterpret_cast<void*>(1 * sizeof(GLint))); |                           reinterpret_cast<void*>(1 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(6); |    glEnableVertexAttribArray(6); | ||||||
| 
 | 
 | ||||||
|    // aDisplayed
 |    // aDisplayed
 | ||||||
|    gl.glVertexAttribPointer(7, |    glVertexAttribIPointer(7, | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                             GL_FALSE, |  | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                             reinterpret_cast<void*>(3 * sizeof(float))); |                           reinterpret_cast<void*>(3 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(7); |    glEnableVertexAttribArray(7); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -252,9 +261,7 @@ void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
| 
 | 
 | ||||||
|    if (p->newLineList_.size() > 0) |    if (p->newLineList_.size() > 0) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(); |       p->Update(); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -267,27 +274,27 @@ void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
|          // If thresholding is enabled, set the map distance
 |          // If thresholding is enabled, set the map distance
 | ||||||
|          units::length::nautical_miles<float> mapDistance = |          units::length::nautical_miles<float> mapDistance = | ||||||
|             util::maplibre::GetMapDistance(params); |             util::maplibre::GetMapDistance(params); | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); |          glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          // If thresholding is disabled, set the map distance to 0
 |          // If thresholding is disabled, set the map distance to 0
 | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); |          glUniform1f(p->uMapDistanceLocation_, 0.0f); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Selected time
 |       // Selected time
 | ||||||
|       std::chrono::system_clock::time_point selectedTime = |       std::chrono::system_clock::time_point selectedTime = | ||||||
|          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|             std::chrono::system_clock::now() : |             scwx::util::time::now() : | ||||||
|             p->selectedTime_; |             p->selectedTime_; | ||||||
|       gl.glUniform1i( |       glUniform1i( | ||||||
|          p->uSelectedTimeLocation_, |          p->uSelectedTimeLocation_, | ||||||
|          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( |          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( | ||||||
|                                selectedTime.time_since_epoch()) |                                selectedTime.time_since_epoch()) | ||||||
|                                .count())); |                                .count())); | ||||||
| 
 | 
 | ||||||
|       // Draw icons
 |       // Draw icons
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, |       glDrawArrays(GL_TRIANGLES, | ||||||
|                    0, |                    0, | ||||||
|                    static_cast<GLsizei>(p->currentLineList_.size() * |                    static_cast<GLsizei>(p->currentLineList_.size() * | ||||||
|                                         kVerticesPerRectangle)); |                                         kVerticesPerRectangle)); | ||||||
|  | @ -296,10 +303,8 @@ void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
| 
 | 
 | ||||||
| void GeoLines::Deinitialize() | void GeoLines::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->lineMutex_}; |    std::unique_lock lock {p->lineMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -324,7 +329,9 @@ void GeoLines::StartLines() | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<GeoLineDrawItem> GeoLines::AddLine() | std::shared_ptr<GeoLineDrawItem> GeoLines::AddLine() | ||||||
| { | { | ||||||
|    return p->newLineList_.emplace_back(std::make_shared<GeoLineDrawItem>()); |    auto& di = p->newLineList_.emplace_back(std::make_shared<GeoLineDrawItem>()); | ||||||
|  |    di->lineIndex_ = p->newLineList_.size() - 1; | ||||||
|  |    return di; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GeoLines::SetLineLocation(const std::shared_ptr<GeoLineDrawItem>& di, | void GeoLines::SetLineLocation(const std::shared_ptr<GeoLineDrawItem>& di, | ||||||
|  | @ -471,7 +478,7 @@ void GeoLines::Impl::UpdateBuffers() | ||||||
| 
 | 
 | ||||||
|       // Update line buffer
 |       // Update line buffer
 | ||||||
|       UpdateSingleBuffer( |       UpdateSingleBuffer( | ||||||
|          di, i, newLinesBuffer_, newIntegerBuffer_, newHoverLines_); |          di, newLinesBuffer_, newIntegerBuffer_, newHoverLines_); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // All lines have been updated
 |    // All lines have been updated
 | ||||||
|  | @ -489,23 +496,15 @@ void GeoLines::Impl::UpdateModifiedLineBuffers() | ||||||
|    // Update buffers for modified lines
 |    // Update buffers for modified lines
 | ||||||
|    for (auto& di : dirtyLines_) |    for (auto& di : dirtyLines_) | ||||||
|    { |    { | ||||||
|       // Find modified line in the current list
 |       // Check if modified line is in the current list
 | ||||||
|       auto it = |       if (di->lineIndex_ >= currentLineList_.size() || | ||||||
|          std::find(currentLineList_.cbegin(), currentLineList_.cend(), di); |           currentLineList_[di->lineIndex_] != di) | ||||||
| 
 |  | ||||||
|       // Ignore invalid lines
 |  | ||||||
|       if (it == currentLineList_.cend()) |  | ||||||
|       { |       { | ||||||
|          continue; |          continue; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       auto lineIndex = std::distance(currentLineList_.cbegin(), it); |       UpdateSingleBuffer( | ||||||
| 
 |          di, currentLinesBuffer_, currentIntegerBuffer_, currentHoverLines_); | ||||||
|       UpdateSingleBuffer(di, |  | ||||||
|                          lineIndex, |  | ||||||
|                          currentLinesBuffer_, |  | ||||||
|                          currentIntegerBuffer_, |  | ||||||
|                          currentHoverLines_); |  | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // Clear list of modified lines
 |    // Clear list of modified lines
 | ||||||
|  | @ -518,10 +517,10 @@ void GeoLines::Impl::UpdateModifiedLineBuffers() | ||||||
| 
 | 
 | ||||||
| void GeoLines::Impl::UpdateSingleBuffer( | void GeoLines::Impl::UpdateSingleBuffer( | ||||||
|    const std::shared_ptr<GeoLineDrawItem>& di, |    const std::shared_ptr<GeoLineDrawItem>& di, | ||||||
|    std::size_t                             lineIndex, |  | ||||||
|    std::vector<float>&                     lineBuffer, |    std::vector<float>&                     lineBuffer, | ||||||
|    std::vector<GLint>&                     integerBuffer, |    std::vector<GLint>&                     integerBuffer, | ||||||
|    std::vector<LineHoverEntry>&            hoverLines) |    std::unordered_map<std::shared_ptr<GeoLineDrawItem>, LineHoverEntry>& | ||||||
|  |       hoverLines) | ||||||
| { | { | ||||||
|    // Threshold value
 |    // Threshold value
 | ||||||
|    units::length::nautical_miles<double> threshold = di->threshold_; |    units::length::nautical_miles<double> threshold = di->threshold_; | ||||||
|  | @ -589,10 +588,10 @@ void GeoLines::Impl::UpdateSingleBuffer( | ||||||
| 
 | 
 | ||||||
|    // Buffer position data
 |    // Buffer position data
 | ||||||
|    auto lineBufferPosition = lineBuffer.end(); |    auto lineBufferPosition = lineBuffer.end(); | ||||||
|    auto lineBufferOffset   = lineIndex * kLineBufferLength_; |    auto lineBufferOffset   = di->lineIndex_ * kLineBufferLength_; | ||||||
| 
 | 
 | ||||||
|    auto integerBufferPosition = integerBuffer.end(); |    auto integerBufferPosition = integerBuffer.end(); | ||||||
|    auto integerBufferOffset   = lineIndex * kIntegerBufferLength_; |    auto integerBufferOffset   = di->lineIndex_ * kIntegerBufferLength_; | ||||||
| 
 | 
 | ||||||
|    if (lineBufferOffset < lineBuffer.size()) |    if (lineBufferOffset < lineBuffer.size()) | ||||||
|    { |    { | ||||||
|  | @ -621,9 +620,7 @@ void GeoLines::Impl::UpdateSingleBuffer( | ||||||
|       std::copy(integerData.begin(), integerData.end(), integerBufferPosition); |       std::copy(integerData.begin(), integerData.end(), integerBufferPosition); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    auto hoverIt = std::find_if(hoverLines.begin(), |    auto hoverIt = hoverLines.find(di); | ||||||
|                                hoverLines.end(), |  | ||||||
|                                [&di](auto& entry) { return entry.di_ == di; }); |  | ||||||
| 
 | 
 | ||||||
|    if (di->visible_ && (!di->hoverText_.empty() || |    if (di->visible_ && (!di->hoverText_.empty() || | ||||||
|                         di->hoverCallback_ != nullptr || di->event_ != nullptr)) |                         di->hoverCallback_ != nullptr || di->event_ != nullptr)) | ||||||
|  | @ -645,17 +642,23 @@ void GeoLines::Impl::UpdateSingleBuffer( | ||||||
| 
 | 
 | ||||||
|       if (hoverIt == hoverLines.end()) |       if (hoverIt == hoverLines.end()) | ||||||
|       { |       { | ||||||
|          hoverLines.emplace_back( |          hoverLines.emplace(di, | ||||||
|             LineHoverEntry {di, sc1, sc2, otl, otr, obl, obr}); |                             LineHoverEntry {.di_  = di, | ||||||
|  |                                             .p1_  = sc1, | ||||||
|  |                                             .p2_  = sc2, | ||||||
|  |                                             .otl_ = otl, | ||||||
|  |                                             .otr_ = otr, | ||||||
|  |                                             .obl_ = obl, | ||||||
|  |                                             .obr_ = obr}); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          hoverIt->p1_  = sc1; |          hoverIt->second.p1_  = sc1; | ||||||
|          hoverIt->p2_  = sc2; |          hoverIt->second.p2_  = sc2; | ||||||
|          hoverIt->otl_ = otl; |          hoverIt->second.otl_ = otl; | ||||||
|          hoverIt->otr_ = otr; |          hoverIt->second.otr_ = otr; | ||||||
|          hoverIt->obl_ = obl; |          hoverIt->second.obl_ = obl; | ||||||
|          hoverIt->obr_ = obr; |          hoverIt->second.obr_ = obr; | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
|    else if (hoverIt != hoverLines.end()) |    else if (hoverIt != hoverLines.end()) | ||||||
|  | @ -671,19 +674,19 @@ void GeoLines::Impl::Update() | ||||||
|    // If the lines have been updated
 |    // If the lines have been updated
 | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|       // Buffer lines data
 |       // Buffer lines data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * currentLinesBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * currentLinesBuffer_.size()), | ||||||
|          currentLinesBuffer_.data(), |          currentLinesBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       // Buffer threshold data
 |       // Buffer threshold data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLint) * currentIntegerBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLint) * currentIntegerBuffer_.size()), | ||||||
|          currentIntegerBuffer_.data(), |          currentIntegerBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
|    } |    } | ||||||
|  | @ -721,16 +724,18 @@ bool GeoLines::RunMousePicking( | ||||||
|    // If no time has been selected, use the current time
 |    // If no time has been selected, use the current time
 | ||||||
|    std::chrono::system_clock::time_point selectedTime = |    std::chrono::system_clock::time_point selectedTime = | ||||||
|       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|          std::chrono::system_clock::now() : |          scwx::util::time::now() : | ||||||
|          p->selectedTime_; |          p->selectedTime_; | ||||||
| 
 | 
 | ||||||
|    // For each pickable line
 |    // For each pickable line
 | ||||||
|    auto it = std::find_if( |    auto it = std::find_if( | ||||||
|       std::execution::par_unseq, |       std::execution::par_unseq, | ||||||
|       p->currentHoverLines_.rbegin(), |       p->currentHoverLines_.cbegin(), | ||||||
|       p->currentHoverLines_.rend(), |       p->currentHoverLines_.cend(), | ||||||
|       [&mapDistance, &selectedTime, &mapMatrix, &mouseCoords](const auto& line) |       [&mapDistance, &selectedTime, &mapMatrix, &mouseCoords]( | ||||||
|  |          const auto& lineIt) | ||||||
|       { |       { | ||||||
|  |          const auto& line = lineIt.second; | ||||||
|          if (( |          if (( | ||||||
|                 // Placefile is thresholded
 |                 // Placefile is thresholded
 | ||||||
|                 mapDistance > units::length::meters<double> {0.0} && |                 mapDistance > units::length::meters<double> {0.0} && | ||||||
|  | @ -740,8 +745,10 @@ bool GeoLines::RunMousePicking( | ||||||
|                    units::length::nautical_miles<double> {line.di_->threshold_} |                    units::length::nautical_miles<double> {line.di_->threshold_} | ||||||
|                       .value())) < 999 && |                       .value())) < 999 && | ||||||
| 
 | 
 | ||||||
|                 // Map distance is beyond the threshold
 |                 // Map distance is beyond/within the threshold
 | ||||||
|                 line.di_->threshold_ < mapDistance) || |                 line.di_->threshold_ < mapDistance && | ||||||
|  |                 (line.di_->threshold_.value() >= 0.0 || | ||||||
|  |                  -(line.di_->threshold_) > mapDistance)) || | ||||||
| 
 | 
 | ||||||
|              ( |              ( | ||||||
|                 // Line has a start time
 |                 // Line has a start time
 | ||||||
|  | @ -784,24 +791,24 @@ bool GeoLines::RunMousePicking( | ||||||
|          return util::maplibre::IsPointInPolygon({tl, bl, br, tr}, mouseCoords); |          return util::maplibre::IsPointInPolygon({tl, bl, br, tr}, mouseCoords); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|    if (it != p->currentHoverLines_.crend()) |    if (it != p->currentHoverLines_.cend()) | ||||||
|    { |    { | ||||||
|       itemPicked = true; |       itemPicked = true; | ||||||
| 
 | 
 | ||||||
|       if (!it->di_->hoverText_.empty()) |       if (!it->second.di_->hoverText_.empty()) | ||||||
|       { |       { | ||||||
|          // Show tooltip
 |          // Show tooltip
 | ||||||
|          util::tooltip::Show(it->di_->hoverText_, mouseGlobalPos); |          util::tooltip::Show(it->second.di_->hoverText_, mouseGlobalPos); | ||||||
|       } |       } | ||||||
|       else if (it->di_->hoverCallback_ != nullptr) |       else if (it->second.di_->hoverCallback_ != nullptr) | ||||||
|       { |       { | ||||||
|          it->di_->hoverCallback_(it->di_, mouseGlobalPos); |          it->second.di_->hoverCallback_(it->second.di_, mouseGlobalPos); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (it->di_->event_ != nullptr) |       if (it->second.di_->event_ != nullptr) | ||||||
|       { |       { | ||||||
|          // Register event handler
 |          // Register event handler
 | ||||||
|          eventHandler = it->di_; |          eventHandler = it->second.di_; | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,9 +19,8 @@ struct GeoLineDrawItem; | ||||||
| class GeoLines : public DrawItem | class GeoLines : public DrawItem | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    typedef std::function<void(std::shared_ptr<GeoLineDrawItem>&, |    using HoverCallback = std::function<void( | ||||||
|                               const QPointF&)> |       const std::shared_ptr<GeoLineDrawItem>&, const QPointF&)>; | ||||||
|       HoverCallback; |  | ||||||
| 
 | 
 | ||||||
|    explicit GeoLines(std::shared_ptr<GlContext> context); |    explicit GeoLines(std::shared_ptr<GlContext> context); | ||||||
|    ~GeoLines(); |    ~GeoLines(); | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| static constexpr std::size_t kNumRectangles       = 1; | static constexpr std::size_t kNumRectangles       = 1; | ||||||
| static constexpr std::size_t kNumTriangles        = kNumRectangles * 2; | static constexpr std::size_t kNumTriangles        = kNumRectangles * 2; | ||||||
| static constexpr std::size_t kVerticesPerTriangle = 3; | static constexpr std::size_t kVerticesPerTriangle = 3; | ||||||
| static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; |  | ||||||
| static constexpr std::size_t kPointsPerVertex     = 10; | static constexpr std::size_t kPointsPerVertex     = 10; | ||||||
| static constexpr std::size_t kPointsPerTexCoord   = 3; | static constexpr std::size_t kPointsPerTexCoord   = 3; | ||||||
| static constexpr std::size_t kIconBufferLength = | static constexpr std::size_t kIconBufferLength = | ||||||
|  | @ -117,7 +116,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Icons::Icons(const std::shared_ptr<GlContext>& context) : | Icons::Icons(const std::shared_ptr<GlContext>& context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| Icons::~Icons() = default; | Icons::~Icons() = default; | ||||||
|  | @ -127,8 +126,6 @@ Icons& Icons::operator=(Icons&&) noexcept = default; | ||||||
| 
 | 
 | ||||||
| void Icons::Initialize() | void Icons::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/texture2d_array.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/texture2d_array.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -136,69 +133,77 @@ void Icons::Initialize() | ||||||
| 
 | 
 | ||||||
|    p->uMVPMatrixLocation_ = p->shaderProgram_->GetUniformLocation("uMVPMatrix"); |    p->uMVPMatrixLocation_ = p->shaderProgram_->GetUniformLocation("uMVPMatrix"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |    glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
|  | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
| 
 | 
 | ||||||
|    // aVertex
 |    // aVertex
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(0)); |                          reinterpret_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aModulate
 |    // aModulate
 | ||||||
|    gl.glVertexAttribPointer(3, |    glVertexAttribPointer(3, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    // aAngle
 |    // aAngle
 | ||||||
|    gl.glVertexAttribPointer(4, |    glVertexAttribPointer(4, | ||||||
|                          1, |                          1, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(8 * sizeof(float))); |                          reinterpret_cast<void*>(8 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(4); |    glEnableVertexAttribArray(4); | ||||||
| 
 | 
 | ||||||
|    // aDisplayed
 |    // aDisplayed
 | ||||||
|    gl.glVertexAttribPointer(5, |    glVertexAttribPointer(5, | ||||||
|                          1, |                          1, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(9 * sizeof(float))); |                          reinterpret_cast<void*>(9 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(5); |    glEnableVertexAttribArray(5); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aTexCoord
 |    // aTexCoord
 | ||||||
|    gl.glVertexAttribPointer(2, |    glVertexAttribPointer(2, | ||||||
|                          3, |                          3, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerTexCoord * sizeof(float), |                          kPointsPerTexCoord * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(2); |    glEnableVertexAttribArray(2); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -220,29 +225,25 @@ void Icons::Render(const QMapLibre::CustomLayerRenderParameters& params, | ||||||
| 
 | 
 | ||||||
|    if (!p->currentIconList_.empty()) |    if (!p->currentIconList_.empty()) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(textureAtlasChanged); |       p->Update(textureAtlasChanged); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|       UseDefaultProjection(params, p->uMVPMatrixLocation_); |       UseDefaultProjection(params, p->uMVPMatrixLocation_); | ||||||
| 
 | 
 | ||||||
|       // Interpolate texture coordinates
 |       // Interpolate texture coordinates
 | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||||
| 
 | 
 | ||||||
|       // Draw icons
 |       // Draw icons
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); |       glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Icons::Deinitialize() | void Icons::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->iconMutex_}; |    std::unique_lock lock {p->iconMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -680,8 +681,6 @@ void Icons::Impl::UpdateModifiedIconBuffers() | ||||||
| 
 | 
 | ||||||
| void Icons::Impl::Update(bool textureAtlasChanged) | void Icons::Impl::Update(bool textureAtlasChanged) | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|    UpdateModifiedIconBuffers(); |    UpdateModifiedIconBuffers(); | ||||||
| 
 | 
 | ||||||
|    // If the texture atlas has changed
 |    // If the texture atlas has changed
 | ||||||
|  | @ -697,9 +696,10 @@ void Icons::Impl::Update(bool textureAtlasChanged) | ||||||
|       UpdateTextureBuffer(); |       UpdateTextureBuffer(); | ||||||
| 
 | 
 | ||||||
|       // Buffer texture data
 |       // Buffer texture data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * textureBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * textureBuffer_.size()), | ||||||
|          textureBuffer_.data(), |          textureBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  | @ -710,9 +710,10 @@ void Icons::Impl::Update(bool textureAtlasChanged) | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       // Buffer vertex data
 |       // Buffer vertex data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * currentIconBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * currentIconBuffer_.size()), | ||||||
|          currentIconBuffer_.data(), |          currentIconBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  | @ -741,7 +742,7 @@ bool Icons::RunMousePicking( | ||||||
| 
 | 
 | ||||||
|    // For each pickable icon
 |    // For each pickable icon
 | ||||||
|    auto it = std::find_if( //
 |    auto it = std::find_if( //
 | ||||||
|       std::execution::par_unseq, |       std::execution::par, | ||||||
|       p->currentHoverIcons_.crbegin(), |       p->currentHoverIcons_.crbegin(), | ||||||
|       p->currentHoverIcons_.crend(), |       p->currentHoverIcons_.crend(), | ||||||
|       [&mouseLocalCoords](const auto& icon) |       [&mouseLocalCoords](const auto& icon) | ||||||
|  |  | ||||||
|  | @ -63,14 +63,12 @@ class LinkedVectors::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit Impl(std::shared_ptr<GlContext> context) : |    explicit Impl(std::shared_ptr<GlContext> context) : | ||||||
|        context_ {context}, geoLines_ {std::make_shared<GeoLines>(context)} |        geoLines_ {std::make_shared<GeoLines>(context)} | ||||||
|    { |    { | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    ~Impl() {} |    ~Impl() {} | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<GlContext> context_; |  | ||||||
| 
 |  | ||||||
|    bool borderEnabled_ {true}; |    bool borderEnabled_ {true}; | ||||||
|    bool visible_ {true}; |    bool visible_ {true}; | ||||||
| 
 | 
 | ||||||
|  | @ -79,7 +77,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| LinkedVectors::LinkedVectors(std::shared_ptr<GlContext> context) : | LinkedVectors::LinkedVectors(std::shared_ptr<GlContext> context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| LinkedVectors::~LinkedVectors() = default; | LinkedVectors::~LinkedVectors() = default; | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| #include <scwx/qt/util/texture_atlas.hpp> | #include <scwx/qt/util/texture_atlas.hpp> | ||||||
| #include <scwx/qt/util/tooltip.hpp> | #include <scwx/qt/util/tooltip.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <execution> | #include <execution> | ||||||
| 
 | 
 | ||||||
|  | @ -140,7 +141,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| PlacefileIcons::PlacefileIcons(const std::shared_ptr<GlContext>& context) : | PlacefileIcons::PlacefileIcons(const std::shared_ptr<GlContext>& context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| PlacefileIcons::~PlacefileIcons() = default; | PlacefileIcons::~PlacefileIcons() = default; | ||||||
|  | @ -161,9 +162,6 @@ void PlacefileIcons::set_thresholded(bool thresholded) | ||||||
| 
 | 
 | ||||||
| void PlacefileIcons::Initialize() | void PlacefileIcons::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl   = p->context_->gl(); |  | ||||||
|    auto&                gl30 = p->context_->gl30(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -178,82 +176,90 @@ void PlacefileIcons::Initialize() | ||||||
|    p->uSelectedTimeLocation_ = |    p->uSelectedTimeLocation_ = | ||||||
|       p->shaderProgram_->GetUniformLocation("uSelectedTime"); |       p->shaderProgram_->GetUniformLocation("uSelectedTime"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |    glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
|  | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
| 
 | 
 | ||||||
|    // aLatLong
 |    // aLatLong
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aModulate
 |    // aModulate
 | ||||||
|    gl.glVertexAttribPointer(3, |    glVertexAttribPointer(3, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    // aAngle
 |    // aAngle
 | ||||||
|    gl.glVertexAttribPointer(4, |    glVertexAttribPointer(4, | ||||||
|                          1, |                          1, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(8 * sizeof(float))); |                          reinterpret_cast<void*>(8 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(4); |    glEnableVertexAttribArray(4); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aTexCoord
 |    // aTexCoord
 | ||||||
|    gl.glVertexAttribPointer(2, |    glVertexAttribPointer(2, | ||||||
|                          3, |                          3, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerTexCoord * sizeof(float), |                          kPointsPerTexCoord * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(2); |    glEnableVertexAttribArray(2); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aThreshold
 |    // aThreshold
 | ||||||
|    gl.glVertexAttribIPointer(5, //
 |    glVertexAttribIPointer(5, //
 | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           0, |                           0, | ||||||
|                           static_cast<void*>(0)); |                           static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(5); |    glEnableVertexAttribArray(5); | ||||||
| 
 | 
 | ||||||
|    // aTimeRange
 |    // aTimeRange
 | ||||||
|    gl.glVertexAttribIPointer(6, //
 |    glVertexAttribIPointer(6, //
 | ||||||
|                           2, |                           2, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           reinterpret_cast<void*>(1 * sizeof(GLint))); |                           reinterpret_cast<void*>(1 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(6); |    glEnableVertexAttribArray(6); | ||||||
| 
 | 
 | ||||||
|    // aDisplayed
 |    // aDisplayed
 | ||||||
|    gl30.glVertexAttribI1i(7, 1); |    glVertexAttribI1i(7, 1); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -266,9 +272,7 @@ void PlacefileIcons::Render( | ||||||
| 
 | 
 | ||||||
|    if (!p->currentIconList_.empty()) |    if (!p->currentIconList_.empty()) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(textureAtlasChanged); |       p->Update(textureAtlasChanged); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -281,40 +285,38 @@ void PlacefileIcons::Render( | ||||||
|          // If thresholding is enabled, set the map distance
 |          // If thresholding is enabled, set the map distance
 | ||||||
|          units::length::nautical_miles<float> mapDistance = |          units::length::nautical_miles<float> mapDistance = | ||||||
|             util::maplibre::GetMapDistance(params); |             util::maplibre::GetMapDistance(params); | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); |          glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          // If thresholding is disabled, set the map distance to 0
 |          // If thresholding is disabled, set the map distance to 0
 | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); |          glUniform1f(p->uMapDistanceLocation_, 0.0f); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Selected time
 |       // Selected time
 | ||||||
|       std::chrono::system_clock::time_point selectedTime = |       std::chrono::system_clock::time_point selectedTime = | ||||||
|          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|             std::chrono::system_clock::now() : |             scwx::util::time::now() : | ||||||
|             p->selectedTime_; |             p->selectedTime_; | ||||||
|       gl.glUniform1i( |       glUniform1i( | ||||||
|          p->uSelectedTimeLocation_, |          p->uSelectedTimeLocation_, | ||||||
|          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( |          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( | ||||||
|                                selectedTime.time_since_epoch()) |                                selectedTime.time_since_epoch()) | ||||||
|                                .count())); |                                .count())); | ||||||
| 
 | 
 | ||||||
|       // Interpolate texture coordinates
 |       // Interpolate texture coordinates
 | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||||
| 
 | 
 | ||||||
|       // Draw icons
 |       // Draw icons
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); |       glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileIcons::Deinitialize() | void PlacefileIcons::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->iconMutex_}; |    std::unique_lock lock {p->iconMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -642,8 +644,6 @@ void PlacefileIcons::Impl::UpdateTextureBuffer() | ||||||
| 
 | 
 | ||||||
| void PlacefileIcons::Impl::Update(bool textureAtlasChanged) | void PlacefileIcons::Impl::Update(bool textureAtlasChanged) | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|    // If the texture atlas has changed
 |    // If the texture atlas has changed
 | ||||||
|    if (dirty_ || textureAtlasChanged) |    if (dirty_ || textureAtlasChanged) | ||||||
|    { |    { | ||||||
|  | @ -657,9 +657,10 @@ void PlacefileIcons::Impl::Update(bool textureAtlasChanged) | ||||||
|       UpdateTextureBuffer(); |       UpdateTextureBuffer(); | ||||||
| 
 | 
 | ||||||
|       // Buffer texture data
 |       // Buffer texture data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * textureBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * textureBuffer_.size()), | ||||||
|          textureBuffer_.data(), |          textureBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
|    } |    } | ||||||
|  | @ -668,16 +669,18 @@ void PlacefileIcons::Impl::Update(bool textureAtlasChanged) | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       // Buffer vertex data
 |       // Buffer vertex data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * currentIconBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * currentIconBuffer_.size()), | ||||||
|          currentIconBuffer_.data(), |          currentIconBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       // Buffer threshold data
 |       // Buffer threshold data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLint) * currentIntegerBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLint) * currentIntegerBuffer_.size()), | ||||||
|          currentIntegerBuffer_.data(), |          currentIntegerBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  | @ -718,7 +721,7 @@ bool PlacefileIcons::RunMousePicking( | ||||||
|    // If no time has been selected, use the current time
 |    // If no time has been selected, use the current time
 | ||||||
|    std::chrono::system_clock::time_point selectedTime = |    std::chrono::system_clock::time_point selectedTime = | ||||||
|       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|          std::chrono::system_clock::now() : |          scwx::util::time::now() : | ||||||
|          p->selectedTime_; |          p->selectedTime_; | ||||||
| 
 | 
 | ||||||
|    // For each pickable icon
 |    // For each pickable icon
 | ||||||
|  | @ -737,8 +740,10 @@ bool PlacefileIcons::RunMousePicking( | ||||||
|                    units::length::nautical_miles<double> {icon.di_->threshold_} |                    units::length::nautical_miles<double> {icon.di_->threshold_} | ||||||
|                       .value())) < 999 && |                       .value())) < 999 && | ||||||
| 
 | 
 | ||||||
|                 // Map distance is beyond the threshold
 |                 // Map distance is beyond/within the threshold
 | ||||||
|                 icon.di_->threshold_ < mapDistance) || |                 icon.di_->threshold_ < mapDistance && | ||||||
|  |                 (icon.di_->threshold_.value() >= 0.0 || | ||||||
|  |                  -(icon.di_->threshold_) > mapDistance)) || | ||||||
| 
 | 
 | ||||||
|              ( |              ( | ||||||
|                 // Line has a start time
 |                 // Line has a start time
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| #include <scwx/qt/util/maplibre.hpp> | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/qt/util/texture_atlas.hpp> | #include <scwx/qt/util/texture_atlas.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <QDir> | #include <QDir> | ||||||
| #include <QUrl> | #include <QUrl> | ||||||
|  | @ -117,7 +118,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| PlacefileImages::PlacefileImages(const std::shared_ptr<GlContext>& context) : | PlacefileImages::PlacefileImages(const std::shared_ptr<GlContext>& context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| PlacefileImages::~PlacefileImages() = default; | PlacefileImages::~PlacefileImages() = default; | ||||||
|  | @ -139,9 +140,6 @@ void PlacefileImages::set_thresholded(bool thresholded) | ||||||
| 
 | 
 | ||||||
| void PlacefileImages::Initialize() | void PlacefileImages::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl   = p->context_->gl(); |  | ||||||
|    auto&                gl30 = p->context_->gl30(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -156,73 +154,81 @@ void PlacefileImages::Initialize() | ||||||
|    p->uSelectedTimeLocation_ = |    p->uSelectedTimeLocation_ = | ||||||
|       p->shaderProgram_->GetUniformLocation("uSelectedTime"); |       p->shaderProgram_->GetUniformLocation("uSelectedTime"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |    glGenBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
|  | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
| 
 | 
 | ||||||
|    // aLatLong
 |    // aLatLong
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aModulate
 |    // aModulate
 | ||||||
|    gl.glVertexAttribPointer(3, |    glVertexAttribPointer(3, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aTexCoord
 |    // aTexCoord
 | ||||||
|    gl.glVertexAttribPointer(2, |    glVertexAttribPointer(2, | ||||||
|                          3, |                          3, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerTexCoord * sizeof(float), |                          kPointsPerTexCoord * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(2); |    glEnableVertexAttribArray(2); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aThreshold
 |    // aThreshold
 | ||||||
|    gl.glVertexAttribIPointer(5, //
 |    glVertexAttribIPointer(5, //
 | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           static_cast<void*>(0)); |                           static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(5); |    glEnableVertexAttribArray(5); | ||||||
| 
 | 
 | ||||||
|    // aTimeRange
 |    // aTimeRange
 | ||||||
|    gl.glVertexAttribIPointer(6, //
 |    glVertexAttribIPointer(6, //
 | ||||||
|                           2, |                           2, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           reinterpret_cast<void*>(1 * sizeof(GLint))); |                           reinterpret_cast<void*>(1 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(6); |    glEnableVertexAttribArray(6); | ||||||
| 
 | 
 | ||||||
|    // aDisplayed
 |    // aDisplayed
 | ||||||
|    gl30.glVertexAttribI1i(7, 1); |    glVertexAttribI1i(7, 1); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -235,9 +241,7 @@ void PlacefileImages::Render( | ||||||
| 
 | 
 | ||||||
|    if (!p->currentImageList_.empty()) |    if (!p->currentImageList_.empty()) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(textureAtlasChanged); |       p->Update(textureAtlasChanged); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -250,40 +254,38 @@ void PlacefileImages::Render( | ||||||
|          // If thresholding is enabled, set the map distance
 |          // If thresholding is enabled, set the map distance
 | ||||||
|          units::length::nautical_miles<float> mapDistance = |          units::length::nautical_miles<float> mapDistance = | ||||||
|             util::maplibre::GetMapDistance(params); |             util::maplibre::GetMapDistance(params); | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); |          glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          // If thresholding is disabled, set the map distance to 0
 |          // If thresholding is disabled, set the map distance to 0
 | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); |          glUniform1f(p->uMapDistanceLocation_, 0.0f); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Selected time
 |       // Selected time
 | ||||||
|       std::chrono::system_clock::time_point selectedTime = |       std::chrono::system_clock::time_point selectedTime = | ||||||
|          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|             std::chrono::system_clock::now() : |             scwx::util::time::now() : | ||||||
|             p->selectedTime_; |             p->selectedTime_; | ||||||
|       gl.glUniform1i( |       glUniform1i( | ||||||
|          p->uSelectedTimeLocation_, |          p->uSelectedTimeLocation_, | ||||||
|          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( |          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( | ||||||
|                                selectedTime.time_since_epoch()) |                                selectedTime.time_since_epoch()) | ||||||
|                                .count())); |                                .count())); | ||||||
| 
 | 
 | ||||||
|       // Interpolate texture coordinates
 |       // Interpolate texture coordinates
 | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||||
|       gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |       glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||||
| 
 | 
 | ||||||
|       // Draw images
 |       // Draw images
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); |       glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileImages::Deinitialize() | void PlacefileImages::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(static_cast<GLsizei>(p->vbo_.size()), p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->imageMutex_}; |    std::unique_lock lock {p->imageMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -439,8 +441,6 @@ void PlacefileImages::Impl::UpdateTextureBuffer() | ||||||
| 
 | 
 | ||||||
| void PlacefileImages::Impl::Update(bool textureAtlasChanged) | void PlacefileImages::Impl::Update(bool textureAtlasChanged) | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|    // If the texture atlas has changed
 |    // If the texture atlas has changed
 | ||||||
|    if (dirty_ || textureAtlasChanged) |    if (dirty_ || textureAtlasChanged) | ||||||
|    { |    { | ||||||
|  | @ -454,9 +454,10 @@ void PlacefileImages::Impl::Update(bool textureAtlasChanged) | ||||||
|       UpdateTextureBuffer(); |       UpdateTextureBuffer(); | ||||||
| 
 | 
 | ||||||
|       // Buffer texture data
 |       // Buffer texture data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * textureBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * textureBuffer_.size()), | ||||||
|          textureBuffer_.data(), |          textureBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
|    } |    } | ||||||
|  | @ -465,16 +466,18 @@ void PlacefileImages::Impl::Update(bool textureAtlasChanged) | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       // Buffer vertex data
 |       // Buffer vertex data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * currentImageBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * currentImageBuffer_.size()), | ||||||
|          currentImageBuffer_.data(), |          currentImageBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       // Buffer threshold data
 |       // Buffer threshold data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLint) * currentIntegerBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLint) * currentIntegerBuffer_.size()), | ||||||
|          currentIntegerBuffer_.data(), |          currentIntegerBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| #include <scwx/qt/util/maplibre.hpp> | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/qt/util/tooltip.hpp> | #include <scwx/qt/util/tooltip.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <execution> | #include <execution> | ||||||
| 
 | 
 | ||||||
|  | @ -18,13 +19,9 @@ namespace draw | ||||||
| static const std::string logPrefix_ = "scwx::qt::gl::draw::placefile_lines"; | static const std::string logPrefix_ = "scwx::qt::gl::draw::placefile_lines"; | ||||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| 
 | 
 | ||||||
| static constexpr std::size_t kNumRectangles        = 1; |  | ||||||
| static constexpr std::size_t kNumTriangles         = kNumRectangles * 2; |  | ||||||
| static constexpr std::size_t kVerticesPerTriangle  = 3; | static constexpr std::size_t kVerticesPerTriangle  = 3; | ||||||
| static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; | static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; | ||||||
| static constexpr std::size_t kPointsPerVertex      = 9; | static constexpr std::size_t kPointsPerVertex      = 9; | ||||||
| static constexpr std::size_t kBufferLength = |  | ||||||
|    kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; |  | ||||||
| 
 | 
 | ||||||
| // Threshold, start time, end time
 | // Threshold, start time, end time
 | ||||||
| static constexpr std::size_t kIntegersPerVertex_ = 3; | static constexpr std::size_t kIntegersPerVertex_ = 3; | ||||||
|  | @ -110,7 +107,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| PlacefileLines::PlacefileLines(const std::shared_ptr<GlContext>& context) : | PlacefileLines::PlacefileLines(const std::shared_ptr<GlContext>& context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| PlacefileLines::~PlacefileLines() = default; | PlacefileLines::~PlacefileLines() = default; | ||||||
|  | @ -131,9 +128,6 @@ void PlacefileLines::set_thresholded(bool thresholded) | ||||||
| 
 | 
 | ||||||
| void PlacefileLines::Initialize() | void PlacefileLines::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl   = p->context_->gl(); |  | ||||||
|    auto&                gl30 = p->context_->gl30(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -148,70 +142,78 @@ void PlacefileLines::Initialize() | ||||||
|    p->uSelectedTimeLocation_ = |    p->uSelectedTimeLocation_ = | ||||||
|       p->shaderProgram_->GetUniformLocation("uSelectedTime"); |       p->shaderProgram_->GetUniformLocation("uSelectedTime"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(2, p->vbo_.data()); |    glGenBuffers(2, p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
|  | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
| 
 | 
 | ||||||
|    // aLatLong
 |    // aLatLong
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aModulate
 |    // aModulate
 | ||||||
|    gl.glVertexAttribPointer(3, |    glVertexAttribPointer(3, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    // aAngle
 |    // aAngle
 | ||||||
|    gl.glVertexAttribPointer(4, |    glVertexAttribPointer(4, | ||||||
|                          1, |                          1, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(8 * sizeof(float))); |                          reinterpret_cast<void*>(8 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(4); |    glEnableVertexAttribArray(4); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aThreshold
 |    // aThreshold
 | ||||||
|    gl.glVertexAttribIPointer(5, //
 |    glVertexAttribIPointer(5, //
 | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           static_cast<void*>(0)); |                           static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(5); |    glEnableVertexAttribArray(5); | ||||||
| 
 | 
 | ||||||
|    // aTimeRange
 |    // aTimeRange
 | ||||||
|    gl.glVertexAttribIPointer(6, //
 |    glVertexAttribIPointer(6, //
 | ||||||
|                           2, |                           2, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           reinterpret_cast<void*>(1 * sizeof(GLint))); |                           reinterpret_cast<void*>(1 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(6); |    glEnableVertexAttribArray(6); | ||||||
| 
 | 
 | ||||||
|    // aDisplayed
 |    // aDisplayed
 | ||||||
|    gl30.glVertexAttribI1i(7, 1); |    glVertexAttribI1i(7, 1); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -223,9 +225,7 @@ void PlacefileLines::Render( | ||||||
| 
 | 
 | ||||||
|    if (p->currentNumLines_ > 0) |    if (p->currentNumLines_ > 0) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(); |       p->Update(); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -238,36 +238,34 @@ void PlacefileLines::Render( | ||||||
|          // If thresholding is enabled, set the map distance
 |          // If thresholding is enabled, set the map distance
 | ||||||
|          units::length::nautical_miles<float> mapDistance = |          units::length::nautical_miles<float> mapDistance = | ||||||
|             util::maplibre::GetMapDistance(params); |             util::maplibre::GetMapDistance(params); | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); |          glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          // If thresholding is disabled, set the map distance to 0
 |          // If thresholding is disabled, set the map distance to 0
 | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); |          glUniform1f(p->uMapDistanceLocation_, 0.0f); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Selected time
 |       // Selected time
 | ||||||
|       std::chrono::system_clock::time_point selectedTime = |       std::chrono::system_clock::time_point selectedTime = | ||||||
|          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|             std::chrono::system_clock::now() : |             scwx::util::time::now() : | ||||||
|             p->selectedTime_; |             p->selectedTime_; | ||||||
|       gl.glUniform1i( |       glUniform1i( | ||||||
|          p->uSelectedTimeLocation_, |          p->uSelectedTimeLocation_, | ||||||
|          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( |          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( | ||||||
|                                selectedTime.time_since_epoch()) |                                selectedTime.time_since_epoch()) | ||||||
|                                .count())); |                                .count())); | ||||||
| 
 | 
 | ||||||
|       // Draw icons
 |       // Draw icons
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); |       glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileLines::Deinitialize() | void PlacefileLines::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(2, p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(2, p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->lineMutex_}; |    std::unique_lock lock {p->lineMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -479,19 +477,19 @@ void PlacefileLines::Impl::Update() | ||||||
|    // If the placefile has been updated
 |    // If the placefile has been updated
 | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|       // Buffer lines data
 |       // Buffer lines data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(float) * currentLinesBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(float) * currentLinesBuffer_.size()), | ||||||
|          currentLinesBuffer_.data(), |          currentLinesBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       // Buffer threshold data
 |       // Buffer threshold data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLint) * currentIntegerBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLint) * currentIntegerBuffer_.size()), | ||||||
|          currentIntegerBuffer_.data(), |          currentIntegerBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
|    } |    } | ||||||
|  | @ -529,7 +527,7 @@ bool PlacefileLines::RunMousePicking( | ||||||
|    // If no time has been selected, use the current time
 |    // If no time has been selected, use the current time
 | ||||||
|    std::chrono::system_clock::time_point selectedTime = |    std::chrono::system_clock::time_point selectedTime = | ||||||
|       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |       (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|          std::chrono::system_clock::now() : |          scwx::util::time::now() : | ||||||
|          p->selectedTime_; |          p->selectedTime_; | ||||||
| 
 | 
 | ||||||
|    // For each pickable line
 |    // For each pickable line
 | ||||||
|  | @ -548,8 +546,10 @@ bool PlacefileLines::RunMousePicking( | ||||||
|                    units::length::nautical_miles<double> {line.di_->threshold_} |                    units::length::nautical_miles<double> {line.di_->threshold_} | ||||||
|                       .value())) < 999 && |                       .value())) < 999 && | ||||||
| 
 | 
 | ||||||
|                 // Map distance is beyond the threshold
 |                 // Map distance is beyond/within the threshold
 | ||||||
|                 line.di_->threshold_ < mapDistance) || |                 line.di_->threshold_ < mapDistance && | ||||||
|  |                 (line.di_->threshold_.value() >= 0.0 || | ||||||
|  |                  -(line.di_->threshold_) > mapDistance)) || | ||||||
| 
 | 
 | ||||||
|              ( |              ( | ||||||
|                 // Line has a start time
 |                 // Line has a start time
 | ||||||
|  |  | ||||||
|  | @ -1,13 +1,19 @@ | ||||||
| #include <scwx/qt/gl/draw/placefile_polygons.hpp> | #include <scwx/qt/gl/draw/placefile_polygons.hpp> | ||||||
| #include <scwx/qt/util/maplibre.hpp> | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <mutex> | #include <mutex> | ||||||
| 
 | 
 | ||||||
| #include <GL/glu.h> |  | ||||||
| #include <boost/container/stable_vector.hpp> | #include <boost/container/stable_vector.hpp> | ||||||
| 
 | 
 | ||||||
| #if defined(_WIN32) | #if !defined(__APPLE__) | ||||||
|  | #   include <GL/glu.h> | ||||||
|  | #else | ||||||
|  | #   include <OpenGL/glu.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if defined(_WIN32) || defined(__APPLE__) | ||||||
| typedef void (*_GLUfuncptr)(void); | typedef void (*_GLUfuncptr)(void); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -31,7 +37,6 @@ static constexpr std::size_t kIntegersPerVertex_ = 3; | ||||||
| 
 | 
 | ||||||
| static constexpr std::size_t kTessVertexScreenX_ = 0; | static constexpr std::size_t kTessVertexScreenX_ = 0; | ||||||
| static constexpr std::size_t kTessVertexScreenY_ = 1; | static constexpr std::size_t kTessVertexScreenY_ = 1; | ||||||
| static constexpr std::size_t kTessVertexScreenZ_ = 2; |  | ||||||
| static constexpr std::size_t kTessVertexXOffset_ = 3; | static constexpr std::size_t kTessVertexXOffset_ = 3; | ||||||
| static constexpr std::size_t kTessVertexYOffset_ = 4; | static constexpr std::size_t kTessVertexYOffset_ = 4; | ||||||
| static constexpr std::size_t kTessVertexR_       = 5; | static constexpr std::size_t kTessVertexR_       = 5; | ||||||
|  | @ -126,7 +131,7 @@ public: | ||||||
| 
 | 
 | ||||||
| PlacefilePolygons::PlacefilePolygons( | PlacefilePolygons::PlacefilePolygons( | ||||||
|    const std::shared_ptr<GlContext>& context) : |    const std::shared_ptr<GlContext>& context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| PlacefilePolygons::~PlacefilePolygons() = default; | PlacefilePolygons::~PlacefilePolygons() = default; | ||||||
|  | @ -148,8 +153,6 @@ void PlacefilePolygons::set_thresholded(bool thresholded) | ||||||
| 
 | 
 | ||||||
| void PlacefilePolygons::Initialize() | void PlacefilePolygons::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/map_color.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/map_color.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -164,58 +167,66 @@ void PlacefilePolygons::Initialize() | ||||||
|    p->uSelectedTimeLocation_ = |    p->uSelectedTimeLocation_ = | ||||||
|       p->shaderProgram_->GetUniformLocation("uSelectedTime"); |       p->shaderProgram_->GetUniformLocation("uSelectedTime"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(2, p->vbo_.data()); |    glGenBuffers(2, p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
|  | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
| 
 | 
 | ||||||
|    // aScreenCoord
 |    // aScreenCoord
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aColor
 |    // aColor
 | ||||||
|    gl.glVertexAttribPointer(2, |    glVertexAttribPointer(2, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(2); |    glEnableVertexAttribArray(2); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aThreshold
 |    // aThreshold
 | ||||||
|    gl.glVertexAttribIPointer(3, //
 |    glVertexAttribIPointer(3, //
 | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           static_cast<void*>(0)); |                           static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    // aTimeRange
 |    // aTimeRange
 | ||||||
|    gl.glVertexAttribIPointer(4, //
 |    glVertexAttribIPointer(4, //
 | ||||||
|                           2, |                           2, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           reinterpret_cast<void*>(1 * sizeof(GLint))); |                           reinterpret_cast<void*>(1 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(4); |    glEnableVertexAttribArray(4); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -225,9 +236,7 @@ void PlacefilePolygons::Render( | ||||||
| { | { | ||||||
|    if (!p->currentBuffer_.empty()) |    if (!p->currentBuffer_.empty()) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(); |       p->Update(); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -240,36 +249,34 @@ void PlacefilePolygons::Render( | ||||||
|          // If thresholding is enabled, set the map distance
 |          // If thresholding is enabled, set the map distance
 | ||||||
|          units::length::nautical_miles<float> mapDistance = |          units::length::nautical_miles<float> mapDistance = | ||||||
|             util::maplibre::GetMapDistance(params); |             util::maplibre::GetMapDistance(params); | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); |          glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          // If thresholding is disabled, set the map distance to 0
 |          // If thresholding is disabled, set the map distance to 0
 | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); |          glUniform1f(p->uMapDistanceLocation_, 0.0f); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Selected time
 |       // Selected time
 | ||||||
|       std::chrono::system_clock::time_point selectedTime = |       std::chrono::system_clock::time_point selectedTime = | ||||||
|          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|             std::chrono::system_clock::now() : |             scwx::util::time::now() : | ||||||
|             p->selectedTime_; |             p->selectedTime_; | ||||||
|       gl.glUniform1i( |       glUniform1i( | ||||||
|          p->uSelectedTimeLocation_, |          p->uSelectedTimeLocation_, | ||||||
|          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( |          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( | ||||||
|                                selectedTime.time_since_epoch()) |                                selectedTime.time_since_epoch()) | ||||||
|                                .count())); |                                .count())); | ||||||
| 
 | 
 | ||||||
|       // Draw icons
 |       // Draw icons
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); |       glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefilePolygons::Deinitialize() | void PlacefilePolygons::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(2, p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(2, p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->bufferMutex_}; |    std::unique_lock lock {p->bufferMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -314,21 +321,21 @@ void PlacefilePolygons::Impl::Update() | ||||||
| { | { | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|       std::unique_lock lock {bufferMutex_}; |       std::unique_lock lock {bufferMutex_}; | ||||||
| 
 | 
 | ||||||
|       // Buffer vertex data
 |       // Buffer vertex data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLfloat) * currentBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLfloat) * currentBuffer_.size()), | ||||||
|          currentBuffer_.data(), |          currentBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       // Buffer threshold data
 |       // Buffer threshold data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLint) * currentIntegerBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLint) * currentIntegerBuffer_.size()), | ||||||
|          currentIntegerBuffer_.data(), |          currentIntegerBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,22 +1,16 @@ | ||||||
| #include <scwx/qt/gl/draw/placefile_text.hpp> | #include <scwx/qt/gl/draw/placefile_text.hpp> | ||||||
| #include <scwx/qt/manager/font_manager.hpp> | #include <scwx/qt/manager/font_manager.hpp> | ||||||
| #include <scwx/qt/manager/placefile_manager.hpp> |  | ||||||
| #include <scwx/qt/settings/text_settings.hpp> | #include <scwx/qt/settings/text_settings.hpp> | ||||||
| #include <scwx/qt/util/maplibre.hpp> | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/qt/util/tooltip.hpp> | #include <scwx/qt/util/tooltip.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
| #include <imgui.h> | #include <imgui.h> | ||||||
| #include <mbgl/util/constants.hpp> | #include <mbgl/util/constants.hpp> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::gl::draw | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace gl |  | ||||||
| { |  | ||||||
| namespace draw |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| static const std::string logPrefix_ = "scwx::qt::gl::draw::placefile_text"; | static const std::string logPrefix_ = "scwx::qt::gl::draw::placefile_text"; | ||||||
|  | @ -25,13 +19,16 @@ static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| class PlacefileText::Impl | class PlacefileText::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit Impl(const std::shared_ptr<GlContext>& context, |    explicit Impl(std::string placefileName) : | ||||||
|                  const std::string&                placefileName) : |        placefileName_ {std::move(placefileName)} | ||||||
|        context_ {context}, placefileName_ {placefileName} |  | ||||||
|    { |    { | ||||||
|    } |    } | ||||||
|  |    ~Impl() = default; | ||||||
| 
 | 
 | ||||||
|    ~Impl() {} |    Impl(const Impl&)             = delete; | ||||||
|  |    Impl& operator=(const Impl&)  = delete; | ||||||
|  |    Impl(const Impl&&)            = delete; | ||||||
|  |    Impl& operator=(const Impl&&) = delete; | ||||||
| 
 | 
 | ||||||
|    void RenderTextDrawItem( |    void RenderTextDrawItem( | ||||||
|       const QMapLibre::CustomLayerRenderParameters&             params, |       const QMapLibre::CustomLayerRenderParameters&             params, | ||||||
|  | @ -43,8 +40,6 @@ public: | ||||||
|                    float                                         x, |                    float                                         x, | ||||||
|                    float                                         y); |                    float                                         y); | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<GlContext> context_; |  | ||||||
| 
 |  | ||||||
|    std::string placefileName_; |    std::string placefileName_; | ||||||
| 
 | 
 | ||||||
|    bool thresholded_ {false}; |    bool thresholded_ {false}; | ||||||
|  | @ -66,13 +61,16 @@ public: | ||||||
|    std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> textList_ {}; |    std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> textList_ {}; | ||||||
|    std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> newList_ {}; |    std::vector<std::shared_ptr<const gr::Placefile::TextDrawItem>> newList_ {}; | ||||||
| 
 | 
 | ||||||
|    std::vector<std::shared_ptr<types::ImGuiFont>> fonts_ {}; |    std::vector<std::pair<std::shared_ptr<types::ImGuiFont>, | ||||||
|    std::vector<std::shared_ptr<types::ImGuiFont>> newFonts_ {}; |                          units::font_size::pixels<float>>> | ||||||
|  |       fonts_ {}; | ||||||
|  |    std::vector<std::pair<std::shared_ptr<types::ImGuiFont>, | ||||||
|  |                          units::font_size::pixels<float>>> | ||||||
|  |       newFonts_ {}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| PlacefileText::PlacefileText(const std::shared_ptr<GlContext>& context, | PlacefileText::PlacefileText(const std::string& placefileName) : | ||||||
|                              const std::string&                placefileName) : |     DrawItem(), p(std::make_unique<Impl>(placefileName)) | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context, placefileName)) |  | ||||||
| { | { | ||||||
| } | } | ||||||
| PlacefileText::~PlacefileText() = default; | PlacefileText::~PlacefileText() = default; | ||||||
|  | @ -133,10 +131,14 @@ void PlacefileText::Impl::RenderTextDrawItem( | ||||||
|    // If no time has been selected, use the current time
 |    // If no time has been selected, use the current time
 | ||||||
|    std::chrono::system_clock::time_point selectedTime = |    std::chrono::system_clock::time_point selectedTime = | ||||||
|       (selectedTime_ == std::chrono::system_clock::time_point {}) ? |       (selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|          std::chrono::system_clock::now() : |          scwx::util::time::now() : | ||||||
|          selectedTime_; |          selectedTime_; | ||||||
| 
 | 
 | ||||||
|    if ((!thresholded_ || mapDistance_ <= di->threshold_) && |    const bool thresholdMet = | ||||||
|  |       !thresholded_ || mapDistance_ <= di->threshold_ || | ||||||
|  |       (di->threshold_.value() < 0.0 && mapDistance_ >= -(di->threshold_)); | ||||||
|  | 
 | ||||||
|  |    if (thresholdMet && | ||||||
|        (di->startTime_ == std::chrono::system_clock::time_point {} || |        (di->startTime_ == std::chrono::system_clock::time_point {} || | ||||||
|         (di->startTime_ <= selectedTime && selectedTime < di->endTime_))) |         (di->startTime_ <= selectedTime && selectedTime < di->endTime_))) | ||||||
|    { |    { | ||||||
|  | @ -160,7 +162,8 @@ void PlacefileText::Impl::RenderTextDrawItem( | ||||||
|       std::size_t fontNumber = std::clamp<std::size_t>(di->fontNumber_, 0, 8); |       std::size_t fontNumber = std::clamp<std::size_t>(di->fontNumber_, 0, 8); | ||||||
| 
 | 
 | ||||||
|       // Set the font for the drop shadow and text
 |       // Set the font for the drop shadow and text
 | ||||||
|       ImGui::PushFont(fonts_[fontNumber]->font()); |       ImGui::PushFont(fonts_[fontNumber].first->font(), | ||||||
|  |                       fonts_[fontNumber].second.value()); | ||||||
| 
 | 
 | ||||||
|       if (settings::TextSettings::Instance() |       if (settings::TextSettings::Instance() | ||||||
|              .placefile_text_drop_shadow_enabled() |              .placefile_text_drop_shadow_enabled() | ||||||
|  | @ -262,9 +265,7 @@ void PlacefileText::StartText() | ||||||
|    p->newList_.clear(); |    p->newList_.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileText::SetFonts( | void PlacefileText::SetFonts(const manager::PlacefileManager::FontMap& fonts) | ||||||
|    const boost::unordered_flat_map<std::size_t, |  | ||||||
|                                    std::shared_ptr<types::ImGuiFont>>& fonts) |  | ||||||
| { | { | ||||||
|    auto defaultFont = manager::FontManager::Instance().GetImGuiFont( |    auto defaultFont = manager::FontManager::Instance().GetImGuiFont( | ||||||
|       types::FontCategory::Default); |       types::FontCategory::Default); | ||||||
|  | @ -306,7 +307,4 @@ void PlacefileText::FinishText() | ||||||
|    p->newFonts_.clear(); |    p->newFonts_.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace draw
 | } // namespace scwx::qt::gl::draw
 | ||||||
| } // namespace gl
 |  | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <scwx/qt/gl/gl_context.hpp> | #include <scwx/qt/gl/gl_context.hpp> | ||||||
| #include <scwx/qt/gl/draw/draw_item.hpp> | #include <scwx/qt/gl/draw/draw_item.hpp> | ||||||
|  | #include <scwx/qt/manager/placefile_manager.hpp> | ||||||
| #include <scwx/qt/types/imgui_font.hpp> | #include <scwx/qt/types/imgui_font.hpp> | ||||||
| #include <scwx/gr/placefile.hpp> | #include <scwx/gr/placefile.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -19,8 +20,7 @@ namespace draw | ||||||
| class PlacefileText : public DrawItem | class PlacefileText : public DrawItem | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit PlacefileText(const std::shared_ptr<GlContext>& context, |    explicit PlacefileText(const std::string& placefileName); | ||||||
|                           const std::string&                placefileName); |  | ||||||
|    ~PlacefileText(); |    ~PlacefileText(); | ||||||
| 
 | 
 | ||||||
|    PlacefileText(const PlacefileText&)            = delete; |    PlacefileText(const PlacefileText&)            = delete; | ||||||
|  | @ -55,10 +55,7 @@ public: | ||||||
|     * |     * | ||||||
|     * @param [in] fonts A map of ImGui fonts |     * @param [in] fonts A map of ImGui fonts | ||||||
|     */ |     */ | ||||||
|    void |    void SetFonts(const manager::PlacefileManager::FontMap& fonts); | ||||||
|    SetFonts(const boost::unordered_flat_map<std::size_t, |  | ||||||
|                                             std::shared_ptr<types::ImGuiFont>>& |  | ||||||
|                fonts); |  | ||||||
| 
 | 
 | ||||||
|    /**
 |    /**
 | ||||||
|     * Adds placefile text to the internal draw list. |     * Adds placefile text to the internal draw list. | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include <scwx/qt/gl/draw/placefile_triangles.hpp> | #include <scwx/qt/gl/draw/placefile_triangles.hpp> | ||||||
| #include <scwx/qt/util/maplibre.hpp> | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| #include <mutex> | #include <mutex> | ||||||
| 
 | 
 | ||||||
|  | @ -74,7 +75,7 @@ public: | ||||||
| 
 | 
 | ||||||
| PlacefileTriangles::PlacefileTriangles( | PlacefileTriangles::PlacefileTriangles( | ||||||
|    const std::shared_ptr<GlContext>& context) : |    const std::shared_ptr<GlContext>& context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| PlacefileTriangles::~PlacefileTriangles() = default; | PlacefileTriangles::~PlacefileTriangles() = default; | ||||||
|  | @ -96,8 +97,6 @@ void PlacefileTriangles::set_thresholded(bool thresholded) | ||||||
| 
 | 
 | ||||||
| void PlacefileTriangles::Initialize() | void PlacefileTriangles::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = p->context_->GetShaderProgram( |    p->shaderProgram_ = p->context_->GetShaderProgram( | ||||||
|       {{GL_VERTEX_SHADER, ":/gl/map_color.vert"}, |       {{GL_VERTEX_SHADER, ":/gl/map_color.vert"}, | ||||||
|        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, |        {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, | ||||||
|  | @ -112,58 +111,66 @@ void PlacefileTriangles::Initialize() | ||||||
|    p->uSelectedTimeLocation_ = |    p->uSelectedTimeLocation_ = | ||||||
|       p->shaderProgram_->GetUniformLocation("uSelectedTime"); |       p->shaderProgram_->GetUniformLocation("uSelectedTime"); | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(2, p->vbo_.data()); |    glGenBuffers(2, p->vbo_.data()); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
|  | 
 | ||||||
|  |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
| 
 | 
 | ||||||
|    // aScreenCoord
 |    // aScreenCoord
 | ||||||
|    gl.glVertexAttribPointer(0, |    glVertexAttribPointer(0, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    // aXYOffset
 |    // aXYOffset
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          2, |                          2, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(2 * sizeof(float))); |                          reinterpret_cast<void*>(2 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
| 
 | 
 | ||||||
|    // aColor
 |    // aColor
 | ||||||
|    gl.glVertexAttribPointer(2, |    glVertexAttribPointer(2, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          kPointsPerVertex * sizeof(float), |                          kPointsPerVertex * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(4 * sizeof(float))); |                          reinterpret_cast<void*>(4 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(2); |    glEnableVertexAttribArray(2); | ||||||
| 
 | 
 | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); | ||||||
|    gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); |    glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    // aThreshold
 |    // aThreshold
 | ||||||
|    gl.glVertexAttribIPointer(3, //
 |    glVertexAttribIPointer(3, //
 | ||||||
|                           1, |                           1, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           static_cast<void*>(0)); |                           static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(3); |    glEnableVertexAttribArray(3); | ||||||
| 
 | 
 | ||||||
|    // aTimeRange
 |    // aTimeRange
 | ||||||
|    gl.glVertexAttribIPointer(4, //
 |    glVertexAttribIPointer(4, //
 | ||||||
|                           2, |                           2, | ||||||
|                           GL_INT, |                           GL_INT, | ||||||
|                           kIntegersPerVertex_ * sizeof(GLint), |                           kIntegersPerVertex_ * sizeof(GLint), | ||||||
|                           reinterpret_cast<void*>(1 * sizeof(GLint))); |                           reinterpret_cast<void*>(1 * sizeof(GLint))); | ||||||
|    gl.glEnableVertexAttribArray(4); |    glEnableVertexAttribArray(4); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -173,9 +180,7 @@ void PlacefileTriangles::Render( | ||||||
| { | { | ||||||
|    if (!p->currentBuffer_.empty()) |    if (!p->currentBuffer_.empty()) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |  | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(); |       p->Update(); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -188,36 +193,34 @@ void PlacefileTriangles::Render( | ||||||
|          // If thresholding is enabled, set the map distance
 |          // If thresholding is enabled, set the map distance
 | ||||||
|          units::length::nautical_miles<float> mapDistance = |          units::length::nautical_miles<float> mapDistance = | ||||||
|             util::maplibre::GetMapDistance(params); |             util::maplibre::GetMapDistance(params); | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); |          glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|          // If thresholding is disabled, set the map distance to 0
 |          // If thresholding is disabled, set the map distance to 0
 | ||||||
|          gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); |          glUniform1f(p->uMapDistanceLocation_, 0.0f); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Selected time
 |       // Selected time
 | ||||||
|       std::chrono::system_clock::time_point selectedTime = |       std::chrono::system_clock::time_point selectedTime = | ||||||
|          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? |          (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? | ||||||
|             std::chrono::system_clock::now() : |             scwx::util::time::now() : | ||||||
|             p->selectedTime_; |             p->selectedTime_; | ||||||
|       gl.glUniform1i( |       glUniform1i( | ||||||
|          p->uSelectedTimeLocation_, |          p->uSelectedTimeLocation_, | ||||||
|          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( |          static_cast<GLint>(std::chrono::duration_cast<std::chrono::minutes>( | ||||||
|                                selectedTime.time_since_epoch()) |                                selectedTime.time_since_epoch()) | ||||||
|                                .count())); |                                .count())); | ||||||
| 
 | 
 | ||||||
|       // Draw icons
 |       // Draw icons
 | ||||||
|       gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); |       glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileTriangles::Deinitialize() | void PlacefileTriangles::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(2, p->vbo_.data()); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(2, p->vbo_.data()); |  | ||||||
| 
 | 
 | ||||||
|    std::unique_lock lock {p->bufferMutex_}; |    std::unique_lock lock {p->bufferMutex_}; | ||||||
| 
 | 
 | ||||||
|  | @ -320,21 +323,21 @@ void PlacefileTriangles::Impl::Update() | ||||||
| { | { | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|       std::unique_lock lock {bufferMutex_}; |       std::unique_lock lock {bufferMutex_}; | ||||||
| 
 | 
 | ||||||
|       // Buffer vertex data
 |       // Buffer vertex data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLfloat) * currentBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLfloat) * currentBuffer_.size()), | ||||||
|          currentBuffer_.data(), |          currentBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       // Buffer threshold data
 |       // Buffer threshold data
 | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); |       glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData( | ||||||
|                       sizeof(GLint) * currentIntegerBuffer_.size(), |          GL_ARRAY_BUFFER, | ||||||
|  |          static_cast<GLsizeiptr>(sizeof(GLint) * currentIntegerBuffer_.size()), | ||||||
|          currentIntegerBuffer_.data(), |          currentIntegerBuffer_.data(), | ||||||
|          GL_DYNAMIC_DRAW); |          GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,13 +3,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <optional> | #include <optional> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::gl::draw | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace gl |  | ||||||
| { |  | ||||||
| namespace draw |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| static const std::string logPrefix_ = "scwx::qt::gl::draw::rectangle"; | static const std::string logPrefix_ = "scwx::qt::gl::draw::rectangle"; | ||||||
|  | @ -27,7 +21,7 @@ class Rectangle::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit Impl(std::shared_ptr<GlContext> context) : |    explicit Impl(std::shared_ptr<GlContext> context) : | ||||||
|        context_ {context}, |        context_ {std::move(context)}, | ||||||
|        dirty_ {false}, |        dirty_ {false}, | ||||||
|        visible_ {true}, |        visible_ {true}, | ||||||
|        x_ {0.0f}, |        x_ {0.0f}, | ||||||
|  | @ -44,8 +38,12 @@ public: | ||||||
|        vbo_ {GL_INVALID_INDEX} |        vbo_ {GL_INVALID_INDEX} | ||||||
|    { |    { | ||||||
|    } |    } | ||||||
|  |    ~Impl() = default; | ||||||
| 
 | 
 | ||||||
|    ~Impl() {} |    Impl(const Impl&)             = delete; | ||||||
|  |    Impl& operator=(const Impl&)  = delete; | ||||||
|  |    Impl(const Impl&&)            = delete; | ||||||
|  |    Impl& operator=(const Impl&&) = delete; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<GlContext> context_; |    std::shared_ptr<GlContext> context_; | ||||||
| 
 | 
 | ||||||
|  | @ -73,7 +71,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Rectangle::Rectangle(std::shared_ptr<GlContext> context) : | Rectangle::Rectangle(std::shared_ptr<GlContext> context) : | ||||||
|     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) |     DrawItem(), p(std::make_unique<Impl>(context)) | ||||||
| { | { | ||||||
| } | } | ||||||
| Rectangle::~Rectangle() = default; | Rectangle::~Rectangle() = default; | ||||||
|  | @ -83,41 +81,45 @@ Rectangle& Rectangle::operator=(Rectangle&&) noexcept = default; | ||||||
| 
 | 
 | ||||||
| void Rectangle::Initialize() | void Rectangle::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |  | ||||||
| 
 |  | ||||||
|    p->shaderProgram_ = |    p->shaderProgram_ = | ||||||
|       p->context_->GetShaderProgram(":/gl/color.vert", ":/gl/color.frag"); |       p->context_->GetShaderProgram(":/gl/color.vert", ":/gl/color.frag"); | ||||||
| 
 | 
 | ||||||
|    p->uMVPMatrixLocation_ = |    p->uMVPMatrixLocation_ = | ||||||
|       gl.glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); |       glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); | ||||||
|    if (p->uMVPMatrixLocation_ == -1) |    if (p->uMVPMatrixLocation_ == -1) | ||||||
|    { |    { | ||||||
|       logger_->warn("Could not find uMVPMatrix"); |       logger_->warn("Could not find uMVPMatrix"); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    gl.glGenVertexArrays(1, &p->vao_); |    glGenVertexArrays(1, &p->vao_); | ||||||
|    gl.glGenBuffers(1, &p->vbo_); |    glGenBuffers(1, &p->vbo_); | ||||||
| 
 | 
 | ||||||
|    gl.glBindVertexArray(p->vao_); |    glBindVertexArray(p->vao_); | ||||||
|    gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); |    glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); | ||||||
|    gl.glBufferData( |    glBufferData( | ||||||
|       GL_ARRAY_BUFFER, sizeof(float) * BUFFER_LENGTH, nullptr, GL_DYNAMIC_DRAW); |       GL_ARRAY_BUFFER, sizeof(float) * BUFFER_LENGTH, nullptr, GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|    gl.glVertexAttribPointer(0, |    // NOLINTBEGIN(modernize-use-nullptr)
 | ||||||
|  |    // NOLINTBEGIN(performance-no-int-to-ptr)
 | ||||||
|  | 
 | ||||||
|  |    glVertexAttribPointer(0, | ||||||
|                          3, |                          3, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          POINTS_PER_VERTEX * sizeof(float), |                          POINTS_PER_VERTEX * sizeof(float), | ||||||
|                          static_cast<void*>(0)); |                          static_cast<void*>(0)); | ||||||
|    gl.glEnableVertexAttribArray(0); |    glEnableVertexAttribArray(0); | ||||||
| 
 | 
 | ||||||
|    gl.glVertexAttribPointer(1, |    glVertexAttribPointer(1, | ||||||
|                          4, |                          4, | ||||||
|                          GL_FLOAT, |                          GL_FLOAT, | ||||||
|                          GL_FALSE, |                          GL_FALSE, | ||||||
|                          POINTS_PER_VERTEX * sizeof(float), |                          POINTS_PER_VERTEX * sizeof(float), | ||||||
|                          reinterpret_cast<void*>(3 * sizeof(float))); |                          reinterpret_cast<void*>(3 * sizeof(float))); | ||||||
|    gl.glEnableVertexAttribArray(1); |    glEnableVertexAttribArray(1); | ||||||
|  | 
 | ||||||
|  |    // NOLINTEND(performance-no-int-to-ptr)
 | ||||||
|  |    // NOLINTEND(modernize-use-nullptr)
 | ||||||
| 
 | 
 | ||||||
|    p->dirty_ = true; |    p->dirty_ = true; | ||||||
| } | } | ||||||
|  | @ -126,10 +128,8 @@ void Rectangle::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
| { | { | ||||||
|    if (p->visible_) |    if (p->visible_) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = p->context_->gl(); |       glBindVertexArray(p->vao_); | ||||||
| 
 |       glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); | ||||||
|       gl.glBindVertexArray(p->vao_); |  | ||||||
|       gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); |  | ||||||
| 
 | 
 | ||||||
|       p->Update(); |       p->Update(); | ||||||
|       p->shaderProgram_->Use(); |       p->shaderProgram_->Use(); | ||||||
|  | @ -138,23 +138,23 @@ void Rectangle::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
|       if (p->fillColor_.has_value()) |       if (p->fillColor_.has_value()) | ||||||
|       { |       { | ||||||
|          // Draw fill
 |          // Draw fill
 | ||||||
|          gl.glDrawArrays(GL_TRIANGLES, 24, 6); |          // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |          glDrawArrays(GL_TRIANGLES, 24, 6); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (p->borderWidth_ > 0.0f) |       if (p->borderWidth_ > 0.0f) | ||||||
|       { |       { | ||||||
|          // Draw border
 |          // Draw border
 | ||||||
|          gl.glDrawArrays(GL_TRIANGLES, 0, 24); |          // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |          glDrawArrays(GL_TRIANGLES, 0, 24); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Rectangle::Deinitialize() | void Rectangle::Deinitialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    glDeleteVertexArrays(1, &p->vao_); | ||||||
| 
 |    glDeleteBuffers(1, &p->vbo_); | ||||||
|    gl.glDeleteVertexArrays(1, &p->vao_); |  | ||||||
|    gl.glDeleteBuffers(1, &p->vbo_); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Rectangle::SetBorder(float width, boost::gil::rgba8_pixel_t color) | void Rectangle::SetBorder(float width, boost::gil::rgba8_pixel_t color) | ||||||
|  | @ -206,8 +206,6 @@ void Rectangle::Impl::Update() | ||||||
| { | { | ||||||
|    if (dirty_) |    if (dirty_) | ||||||
|    { |    { | ||||||
|       gl::OpenGLFunctions& gl = context_->gl(); |  | ||||||
| 
 |  | ||||||
|       const float lox = x_; |       const float lox = x_; | ||||||
|       const float rox = x_ + width_; |       const float rox = x_ + width_; | ||||||
|       const float boy = y_; |       const float boy = y_; | ||||||
|  | @ -289,16 +287,13 @@ void Rectangle::Impl::Update() | ||||||
|              {lox, toy, z_, fc0, fc1, fc2, fc3}  // TL
 |              {lox, toy, z_, fc0, fc1, fc2, fc3}  // TL
 | ||||||
|           }}; |           }}; | ||||||
| 
 | 
 | ||||||
|       gl.glBufferData(GL_ARRAY_BUFFER, |       glBufferData(GL_ARRAY_BUFFER, | ||||||
|                    sizeof(float) * BUFFER_LENGTH, |                    sizeof(float) * BUFFER_LENGTH, | ||||||
|                       buffer, |                    static_cast<const void*>(buffer), | ||||||
|                    GL_DYNAMIC_DRAW); |                    GL_DYNAMIC_DRAW); | ||||||
| 
 | 
 | ||||||
|       dirty_ = false; |       dirty_ = false; | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace draw
 | } // namespace scwx::qt::gl::draw
 | ||||||
| } // namespace gl
 |  | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -1,25 +1,12 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <QOpenGLFunctions_3_3_Core> | #include <glad/gl.h> | ||||||
| 
 | 
 | ||||||
| #define SCWX_GL_CHECK_ERROR()                                                  \ | #define SCWX_GL_CHECK_ERROR()                                                  \ | ||||||
|    {                                                                           \ |    {                                                                           \ | ||||||
|       GLenum err;                                                              \ |       GLenum err;                                                              \ | ||||||
|       while ((err = gl.glGetError()) != GL_NO_ERROR)                           \ |       while ((err = glGetError()) != GL_NO_ERROR)                              \ | ||||||
|       {                                                                        \ |       {                                                                        \ | ||||||
|          logger_->error("GL Error: {}, {}: {}", err, __FILE__, __LINE__);      \ |          logger_->error("GL Error: {}, {}: {}", err, __FILE__, __LINE__);      \ | ||||||
|       }                                                                        \ |       }                                                                        \ | ||||||
|    } |    } | ||||||
| 
 |  | ||||||
| namespace scwx |  | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace gl |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| using OpenGLFunctions = QOpenGLFunctions_3_3_Core; |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -3,45 +3,38 @@ | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
| #include <boost/container_hash/hash.hpp> | #include <boost/container_hash/hash.hpp> | ||||||
|  | #include <QMessageBox> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::gl | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace gl |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| static const std::string logPrefix_ = "scwx::qt::gl::gl_context"; | static const std::string logPrefix_ = "scwx::qt::gl::gl_context"; | ||||||
|  | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| 
 | 
 | ||||||
| class GlContext::Impl | class GlContext::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit Impl() : |    explicit Impl() = default; | ||||||
|        gl_ {}, |    ~Impl()         = default; | ||||||
|        shaderProgramMap_ {}, | 
 | ||||||
|        shaderProgramMutex_ {}, |    Impl(const Impl&)             = delete; | ||||||
|        textureAtlas_ {GL_INVALID_INDEX}, |    Impl& operator=(const Impl&)  = delete; | ||||||
|        textureMutex_ {} |    Impl(const Impl&&)            = delete; | ||||||
|    { |    Impl& operator=(const Impl&&) = delete; | ||||||
|    } |  | ||||||
|    ~Impl() {} |  | ||||||
| 
 | 
 | ||||||
|    void InitializeGL(); |    void InitializeGL(); | ||||||
| 
 | 
 | ||||||
|    static std::size_t |    static std::size_t | ||||||
|    GetShaderKey(std::initializer_list<std::pair<GLenum, std::string>> shaders); |    GetShaderKey(std::initializer_list<std::pair<GLenum, std::string>> shaders); | ||||||
| 
 | 
 | ||||||
|    gl::OpenGLFunctions  gl_; |  | ||||||
|    QOpenGLFunctions_3_0 gl30_; |  | ||||||
| 
 |  | ||||||
|    bool glInitialized_ {false}; |    bool glInitialized_ {false}; | ||||||
| 
 | 
 | ||||||
|    std::unordered_map<std::size_t, std::shared_ptr<gl::ShaderProgram>> |    std::unordered_map<std::size_t, std::shared_ptr<gl::ShaderProgram>> | ||||||
|               shaderProgramMap_; |               shaderProgramMap_ {}; | ||||||
|    std::mutex shaderProgramMutex_; |    std::mutex shaderProgramMutex_ {}; | ||||||
| 
 | 
 | ||||||
|    GLuint     textureAtlas_; |    GLuint     textureAtlas_ {GL_INVALID_INDEX}; | ||||||
|    std::mutex textureMutex_; |    std::mutex textureMutex_ {}; | ||||||
| 
 | 
 | ||||||
|    std::uint64_t textureBufferCount_ {}; |    std::uint64_t textureBufferCount_ {}; | ||||||
| }; | }; | ||||||
|  | @ -52,16 +45,6 @@ GlContext::~GlContext() = default; | ||||||
| GlContext::GlContext(GlContext&&) noexcept            = default; | GlContext::GlContext(GlContext&&) noexcept            = default; | ||||||
| GlContext& GlContext::operator=(GlContext&&) noexcept = default; | GlContext& GlContext::operator=(GlContext&&) noexcept = default; | ||||||
| 
 | 
 | ||||||
| gl::OpenGLFunctions& GlContext::gl() |  | ||||||
| { |  | ||||||
|    return p->gl_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| QOpenGLFunctions_3_0& GlContext::gl30() |  | ||||||
| { |  | ||||||
|    return p->gl30_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::uint64_t GlContext::texture_buffer_count() const | std::uint64_t GlContext::texture_buffer_count() const | ||||||
| { | { | ||||||
|    return p->textureBufferCount_; |    return p->textureBufferCount_; | ||||||
|  | @ -74,10 +57,54 @@ void GlContext::Impl::InitializeGL() | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    gl_.initializeOpenGLFunctions(); |    const int gladVersion = gladLoaderLoadGL(); | ||||||
|    gl30_.initializeOpenGLFunctions(); |    if (!gladVersion) | ||||||
|  |    { | ||||||
|  |       logger_->error("gladLoaderLoadGL failed"); | ||||||
| 
 | 
 | ||||||
|    gl_.glGenTextures(1, &textureAtlas_); |       QMessageBox::critical( | ||||||
|  |          nullptr, "Supercell Wx", "Unable to initialize OpenGL"); | ||||||
|  | 
 | ||||||
|  |       throw std::runtime_error("Unable to initialize OpenGL"); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    logger_->info("GLAD initialization complete: OpenGL {}.{}", | ||||||
|  |                  GLAD_VERSION_MAJOR(gladVersion), | ||||||
|  |                  GLAD_VERSION_MINOR(gladVersion)); | ||||||
|  | 
 | ||||||
|  |    auto glVersion  = reinterpret_cast<const char*>(glGetString(GL_VERSION)); | ||||||
|  |    auto glVendor   = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | ||||||
|  |    auto glRenderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); | ||||||
|  | 
 | ||||||
|  |    logger_->info("OpenGL Version: {}", glVersion); | ||||||
|  |    logger_->info("OpenGL Vendor: {}", glVendor); | ||||||
|  |    logger_->info("OpenGL Renderer: {}", glRenderer); | ||||||
|  | 
 | ||||||
|  |    // Get OpenGL version
 | ||||||
|  |    GLint major = 0; | ||||||
|  |    GLint minor = 0; | ||||||
|  |    glGetIntegerv(GL_MAJOR_VERSION, &major); | ||||||
|  |    glGetIntegerv(GL_MINOR_VERSION, &minor); | ||||||
|  | 
 | ||||||
|  |    if (major < 3 || (major == 3 && minor < 3) || !GLAD_GL_VERSION_3_3) | ||||||
|  |    { | ||||||
|  |       logger_->error( | ||||||
|  |          "OpenGL 3.3 or greater is required, found {}.{}", major, minor); | ||||||
|  | 
 | ||||||
|  |       QMessageBox::critical( | ||||||
|  |          nullptr, | ||||||
|  |          "Supercell Wx", | ||||||
|  |          QString("OpenGL 3.3 or greater is required, found %1.%2\n\n%3\n%4\n%5") | ||||||
|  |             .arg(major) | ||||||
|  |             .arg(minor) | ||||||
|  |             .arg(glVersion) | ||||||
|  |             .arg(glVendor) | ||||||
|  |             .arg(glRenderer)); | ||||||
|  | 
 | ||||||
|  |       throw std::runtime_error("OpenGL version too low"); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    glGenTextures(1, &textureAtlas_); | ||||||
| 
 | 
 | ||||||
|    glInitialized_ = true; |    glInitialized_ = true; | ||||||
| } | } | ||||||
|  | @ -102,7 +129,7 @@ std::shared_ptr<gl::ShaderProgram> GlContext::GetShaderProgram( | ||||||
| 
 | 
 | ||||||
|    if (it == p->shaderProgramMap_.end()) |    if (it == p->shaderProgramMap_.end()) | ||||||
|    { |    { | ||||||
|       shaderProgram = std::make_shared<gl::ShaderProgram>(p->gl_); |       shaderProgram = std::make_shared<gl::ShaderProgram>(); | ||||||
|       shaderProgram->Load(shaders); |       shaderProgram->Load(shaders); | ||||||
|       p->shaderProgramMap_[key] = shaderProgram; |       p->shaderProgramMap_[key] = shaderProgram; | ||||||
|    } |    } | ||||||
|  | @ -125,7 +152,7 @@ GLuint GlContext::GetTextureAtlas() | ||||||
|    if (p->textureBufferCount_ != textureAtlas.BuildCount()) |    if (p->textureBufferCount_ != textureAtlas.BuildCount()) | ||||||
|    { |    { | ||||||
|       p->textureBufferCount_ = textureAtlas.BuildCount(); |       p->textureBufferCount_ = textureAtlas.BuildCount(); | ||||||
|       textureAtlas.BufferAtlas(p->gl_, p->textureAtlas_); |       textureAtlas.BufferAtlas(p->textureAtlas_); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    return p->textureAtlas_; |    return p->textureAtlas_; | ||||||
|  | @ -138,10 +165,8 @@ void GlContext::Initialize() | ||||||
| 
 | 
 | ||||||
| void GlContext::StartFrame() | void GlContext::StartFrame() | ||||||
| { | { | ||||||
|    auto& gl = p->gl_; |    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | ||||||
| 
 |    glClear(GL_COLOR_BUFFER_BIT); | ||||||
|    gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |  | ||||||
|    gl.glClear(GL_COLOR_BUFFER_BIT); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::size_t GlContext::Impl::GetShaderKey( | std::size_t GlContext::Impl::GetShaderKey( | ||||||
|  | @ -156,6 +181,4 @@ std::size_t GlContext::Impl::GetShaderKey( | ||||||
|    return seed; |    return seed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace gl
 | } // namespace scwx::qt::gl
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -3,8 +3,6 @@ | ||||||
| #include <scwx/qt/gl/gl.hpp> | #include <scwx/qt/gl/gl.hpp> | ||||||
| #include <scwx/qt/gl/shader_program.hpp> | #include <scwx/qt/gl/shader_program.hpp> | ||||||
| 
 | 
 | ||||||
| #include <QOpenGLFunctions_3_0> |  | ||||||
| 
 |  | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
| namespace qt | namespace qt | ||||||
|  | @ -24,9 +22,6 @@ public: | ||||||
|    GlContext(GlContext&&) noexcept; |    GlContext(GlContext&&) noexcept; | ||||||
|    GlContext& operator=(GlContext&&) noexcept; |    GlContext& operator=(GlContext&&) noexcept; | ||||||
| 
 | 
 | ||||||
|    gl::OpenGLFunctions&  gl(); |  | ||||||
|    QOpenGLFunctions_3_0& gl30(); |  | ||||||
| 
 |  | ||||||
|    std::uint64_t texture_buffer_count() const; |    std::uint64_t texture_buffer_count() const; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<gl::ShaderProgram> |    std::shared_ptr<gl::ShaderProgram> | ||||||
|  |  | ||||||
|  | @ -2,12 +2,9 @@ | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
| #include <QFile> | #include <QFile> | ||||||
|  | #include <QTextStream> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::gl | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace gl |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| static const std::string logPrefix_ = "scwx::qt::gl::shader_program"; | static const std::string logPrefix_ = "scwx::qt::gl::shader_program"; | ||||||
|  | @ -23,29 +20,25 @@ static const std::unordered_map<GLenum, std::string> kShaderNames_ { | ||||||
| class ShaderProgram::Impl | class ShaderProgram::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit Impl(OpenGLFunctions& gl) : gl_(gl), id_ {GL_INVALID_INDEX} |    explicit Impl() : id_ {glCreateProgram()} {} | ||||||
|    { |  | ||||||
|       // Create shader program
 |  | ||||||
|       id_ = gl_.glCreateProgram(); |  | ||||||
|    } |  | ||||||
| 
 | 
 | ||||||
|    ~Impl() |    ~Impl() | ||||||
|    { |    { | ||||||
|       // Delete shader program
 |       // Delete shader program
 | ||||||
|       gl_.glDeleteProgram(id_); |       glDeleteProgram(id_); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    static std::string ShaderName(GLenum type); |    Impl(const Impl&)             = delete; | ||||||
|  |    Impl& operator=(const Impl&)  = delete; | ||||||
|  |    Impl(const Impl&&)            = delete; | ||||||
|  |    Impl& operator=(const Impl&&) = delete; | ||||||
| 
 | 
 | ||||||
|    OpenGLFunctions& gl_; |    static std::string ShaderName(GLenum type); | ||||||
| 
 | 
 | ||||||
|    GLuint id_; |    GLuint id_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ShaderProgram::ShaderProgram(OpenGLFunctions& gl) : | ShaderProgram::ShaderProgram() : p(std::make_unique<Impl>()) {} | ||||||
|     p(std::make_unique<Impl>(gl)) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| ShaderProgram::~ShaderProgram() = default; | ShaderProgram::~ShaderProgram() = default; | ||||||
| 
 | 
 | ||||||
| ShaderProgram::ShaderProgram(ShaderProgram&&) noexcept            = default; | ShaderProgram::ShaderProgram(ShaderProgram&&) noexcept            = default; | ||||||
|  | @ -58,7 +51,7 @@ GLuint ShaderProgram::id() const | ||||||
| 
 | 
 | ||||||
| GLint ShaderProgram::GetUniformLocation(const std::string& name) | GLint ShaderProgram::GetUniformLocation(const std::string& name) | ||||||
| { | { | ||||||
|    GLint location = p->gl_.glGetUniformLocation(p->id_, name.c_str()); |    const GLint location = glGetUniformLocation(p->id_, name.c_str()); | ||||||
|    if (location == -1) |    if (location == -1) | ||||||
|    { |    { | ||||||
|       logger_->warn("Could not find {}", name); |       logger_->warn("Could not find {}", name); | ||||||
|  | @ -88,8 +81,6 @@ bool ShaderProgram::Load( | ||||||
| { | { | ||||||
|    logger_->debug("Load()"); |    logger_->debug("Load()"); | ||||||
| 
 | 
 | ||||||
|    OpenGLFunctions& gl = p->gl_; |  | ||||||
| 
 |  | ||||||
|    GLint   glSuccess; |    GLint   glSuccess; | ||||||
|    bool    success = true; |    bool    success = true; | ||||||
|    char    infoLog[kInfoLogBufSize]; |    char    infoLog[kInfoLogBufSize]; | ||||||
|  | @ -120,16 +111,17 @@ bool ShaderProgram::Load( | ||||||
|       const char* shaderSourceC = shaderSource.c_str(); |       const char* shaderSourceC = shaderSource.c_str(); | ||||||
| 
 | 
 | ||||||
|       // Create a shader
 |       // Create a shader
 | ||||||
|       GLuint shaderId = gl.glCreateShader(shader.first); |       const GLuint shaderId = glCreateShader(shader.first); | ||||||
|       shaderIds.push_back(shaderId); |       shaderIds.push_back(shaderId); | ||||||
| 
 | 
 | ||||||
|       // Attach the shader source code and compile the shader
 |       // Attach the shader source code and compile the shader
 | ||||||
|       gl.glShaderSource(shaderId, 1, &shaderSourceC, NULL); |       glShaderSource(shaderId, 1, &shaderSourceC, nullptr); | ||||||
|       gl.glCompileShader(shaderId); |       glCompileShader(shaderId); | ||||||
| 
 | 
 | ||||||
|       // Check for errors
 |       // Check for errors
 | ||||||
|       gl.glGetShaderiv(shaderId, GL_COMPILE_STATUS, &glSuccess); |       glGetShaderiv(shaderId, GL_COMPILE_STATUS, &glSuccess); | ||||||
|       gl.glGetShaderInfoLog(shaderId, kInfoLogBufSize, &logLength, infoLog); |       glGetShaderInfoLog( | ||||||
|  |          shaderId, kInfoLogBufSize, &logLength, static_cast<GLchar*>(infoLog)); | ||||||
|       if (!glSuccess) |       if (!glSuccess) | ||||||
|       { |       { | ||||||
|          logger_->error("Shader compilation failed: {}", infoLog); |          logger_->error("Shader compilation failed: {}", infoLog); | ||||||
|  | @ -138,7 +130,7 @@ bool ShaderProgram::Load( | ||||||
|       } |       } | ||||||
|       else if (logLength > 0) |       else if (logLength > 0) | ||||||
|       { |       { | ||||||
|          logger_->error("Shader compiled with warnings: {}", infoLog); |          logger_->warn("Shader compiled with warnings: {}", infoLog); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  | @ -146,13 +138,14 @@ bool ShaderProgram::Load( | ||||||
|    { |    { | ||||||
|       for (auto& shaderId : shaderIds) |       for (auto& shaderId : shaderIds) | ||||||
|       { |       { | ||||||
|          gl.glAttachShader(p->id_, shaderId); |          glAttachShader(p->id_, shaderId); | ||||||
|       } |       } | ||||||
|       gl.glLinkProgram(p->id_); |       glLinkProgram(p->id_); | ||||||
| 
 | 
 | ||||||
|       // Check for errors
 |       // Check for errors
 | ||||||
|       gl.glGetProgramiv(p->id_, GL_LINK_STATUS, &glSuccess); |       glGetProgramiv(p->id_, GL_LINK_STATUS, &glSuccess); | ||||||
|       gl.glGetProgramInfoLog(p->id_, kInfoLogBufSize, &logLength, infoLog); |       glGetProgramInfoLog( | ||||||
|  |          p->id_, kInfoLogBufSize, &logLength, static_cast<GLchar*>(infoLog)); | ||||||
|       if (!glSuccess) |       if (!glSuccess) | ||||||
|       { |       { | ||||||
|          logger_->error("Shader program link failed: {}", infoLog); |          logger_->error("Shader program link failed: {}", infoLog); | ||||||
|  | @ -160,14 +153,14 @@ bool ShaderProgram::Load( | ||||||
|       } |       } | ||||||
|       else if (logLength > 0) |       else if (logLength > 0) | ||||||
|       { |       { | ||||||
|          logger_->error("Shader program linked with warnings: {}", infoLog); |          logger_->warn("Shader program linked with warnings: {}", infoLog); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // Delete shaders
 |    // Delete shaders
 | ||||||
|    for (auto& shaderId : shaderIds) |    for (auto& shaderId : shaderIds) | ||||||
|    { |    { | ||||||
|       gl.glDeleteShader(shaderId); |       glDeleteShader(shaderId); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    return success; |    return success; | ||||||
|  | @ -175,9 +168,7 @@ bool ShaderProgram::Load( | ||||||
| 
 | 
 | ||||||
| void ShaderProgram::Use() const | void ShaderProgram::Use() const | ||||||
| { | { | ||||||
|    p->gl_.glUseProgram(p->id_); |    glUseProgram(p->id_); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace gl
 | } // namespace scwx::qt::gl
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ namespace gl | ||||||
| class ShaderProgram | class ShaderProgram | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit ShaderProgram(OpenGLFunctions& gl); |    explicit ShaderProgram(); | ||||||
|    virtual ~ShaderProgram(); |    virtual ~ShaderProgram(); | ||||||
| 
 | 
 | ||||||
|    ShaderProgram(const ShaderProgram&)            = delete; |    ShaderProgram(const ShaderProgram&)            = delete; | ||||||
|  |  | ||||||
|  | @ -44,6 +44,14 @@ void WaitForInitialization() | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Only use for test cases
 | ||||||
|  | void ResetInitilization() | ||||||
|  | { | ||||||
|  |    logger_->debug("Application initialization reset"); | ||||||
|  |    std::unique_lock lock(initializationMutex_); | ||||||
|  |    initialized_ = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace Application
 | } // namespace Application
 | ||||||
| } // namespace main
 | } // namespace main
 | ||||||
| } // namespace qt
 | } // namespace qt
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,8 @@ namespace Application | ||||||
| 
 | 
 | ||||||
| void FinishInitialization(); | void FinishInitialization(); | ||||||
| void WaitForInitialization(); | void WaitForInitialization(); | ||||||
|  | // Only use for test cases
 | ||||||
|  | void ResetInitilization(); | ||||||
| 
 | 
 | ||||||
| } // namespace Application
 | } // namespace Application
 | ||||||
| } // namespace main
 | } // namespace main
 | ||||||
|  |  | ||||||
							
								
								
									
										136
									
								
								scwx-qt/source/scwx/qt/main/check_privilege.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,136 @@ | ||||||
|  | #include <scwx/qt/settings/general_settings.hpp> | ||||||
|  | #include <scwx/qt/main/check_privilege.hpp> | ||||||
|  | #include <QtGlobal> | ||||||
|  | #include <QStandardPaths> | ||||||
|  | #include <filesystem> | ||||||
|  | #include <QObject> | ||||||
|  | #include <QMessageBox> | ||||||
|  | #include <QCheckBox> | ||||||
|  | 
 | ||||||
|  | #ifdef _WIN32 | ||||||
|  | #   include <windows.h> | ||||||
|  | #else | ||||||
|  | #   include <unistd.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | namespace scwx::qt::main | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | bool is_high_privilege() | ||||||
|  | { | ||||||
|  | #if defined(_WIN32) | ||||||
|  |    bool            isAdmin = false; | ||||||
|  |    HANDLE          token   = NULL; | ||||||
|  |    TOKEN_ELEVATION elevation; | ||||||
|  |    DWORD           elevationSize = sizeof(TOKEN_ELEVATION); | ||||||
|  | 
 | ||||||
|  |    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    if (!GetTokenInformation( | ||||||
|  |           token, TokenElevation, &elevation, elevationSize, &elevationSize)) | ||||||
|  |    { | ||||||
|  |       CloseHandle(token); | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    isAdmin = elevation.TokenIsElevated; | ||||||
|  |    CloseHandle(token); | ||||||
|  |    return isAdmin; | ||||||
|  | #elif defined(Q_OS_UNIX) | ||||||
|  |    // On UNIX root is always uid 0. On Linux this is enforced by the kernel.
 | ||||||
|  |    return geteuid() == 0; | ||||||
|  | #else | ||||||
|  |    return false; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #if defined(_WIN32) | ||||||
|  | static const QString message = QObject::tr( | ||||||
|  |    "Supercell Wx has been run with administrator permissions. It is " | ||||||
|  |    "recommended to run it without administrator permissions Do you wish to " | ||||||
|  |    "continue?"); | ||||||
|  | #elif defined(Q_OS_UNIX) | ||||||
|  | static const QString message = QObject::tr( | ||||||
|  |    "Supercell Wx has been run as root. It is recommended to run it as a normal " | ||||||
|  |    "user. Do you wish to continue?"); | ||||||
|  | #else | ||||||
|  | static const QString message = QObject::tr(""); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | static const QString title = QObject::tr("Supercell Wx"); | ||||||
|  | static const QString checkBoxText = | ||||||
|  |    QObject::tr("Do not show this warning again."); | ||||||
|  | 
 | ||||||
|  | class PrivilegeChecker::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl() : | ||||||
|  |        highPrivilege_ {is_high_privilege()}, | ||||||
|  |        dialog_ {QMessageBox::Icon::Warning, title, message}, | ||||||
|  |        checkBox_(new QCheckBox(checkBoxText, &dialog_)) | ||||||
|  |    { | ||||||
|  |       const std::string appDataPath { | ||||||
|  |          QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) | ||||||
|  |             .toStdString()}; | ||||||
|  |       hasAppData_ = std::filesystem::exists(appDataPath); | ||||||
|  | 
 | ||||||
|  |       dialog_.setStandardButtons(QMessageBox::Yes | QMessageBox::No); | ||||||
|  |       dialog_.setDefaultButton(QMessageBox::No); | ||||||
|  |       dialog_.setCheckBox(checkBox_); | ||||||
|  |    }; | ||||||
|  | 
 | ||||||
|  |    bool hasAppData_; | ||||||
|  |    bool firstCheckCheckBoxState_ {true}; | ||||||
|  |    bool highPrivilege_; | ||||||
|  | 
 | ||||||
|  |    QMessageBox dialog_; | ||||||
|  |    QCheckBox*  checkBox_; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | PrivilegeChecker::PrivilegeChecker() : | ||||||
|  |     p(std::make_unique<PrivilegeChecker::Impl>()) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PrivilegeChecker::~PrivilegeChecker() = default; | ||||||
|  | 
 | ||||||
|  | bool PrivilegeChecker::pre_settings_check() | ||||||
|  | { | ||||||
|  |    if (p->hasAppData_ || !p->highPrivilege_) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    const int result            = p->dialog_.exec(); | ||||||
|  |    p->firstCheckCheckBoxState_ = p->checkBox_->isChecked(); | ||||||
|  | 
 | ||||||
|  |    return result != QMessageBox::Yes; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool PrivilegeChecker::post_settings_check() | ||||||
|  | { | ||||||
|  |    auto& highPrivilegeWarningEnabled = | ||||||
|  |       settings::GeneralSettings::Instance().high_privilege_warning_enabled(); | ||||||
|  |    if (!highPrivilegeWarningEnabled.GetValue() || !p->highPrivilege_) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    else if (!p->hasAppData_) | ||||||
|  |    { | ||||||
|  |       highPrivilegeWarningEnabled.StageValue(!p->firstCheckCheckBoxState_); | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    switch (p->dialog_.exec()) | ||||||
|  |    { | ||||||
|  |    case QMessageBox::Yes: | ||||||
|  |       highPrivilegeWarningEnabled.StageValue(!p->checkBox_->isChecked()); | ||||||
|  |       return false; | ||||||
|  |    case QMessageBox::No: | ||||||
|  |    default: | ||||||
|  |       return true; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace scwx::qt::main
 | ||||||
							
								
								
									
										30
									
								
								scwx-qt/source/scwx/qt/main/check_privilege.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,30 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | namespace scwx::qt::main | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | bool is_high_privilege(); | ||||||
|  | 
 | ||||||
|  | class PrivilegeChecker | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit PrivilegeChecker(); | ||||||
|  |    ~PrivilegeChecker(); | ||||||
|  | 
 | ||||||
|  |    PrivilegeChecker(const PrivilegeChecker&)             = delete; | ||||||
|  |    PrivilegeChecker& operator=(const PrivilegeChecker&)  = delete; | ||||||
|  |    PrivilegeChecker(const PrivilegeChecker&&)            = delete; | ||||||
|  |    PrivilegeChecker& operator=(const PrivilegeChecker&&) = delete; | ||||||
|  | 
 | ||||||
|  |    // returning true means check failed.
 | ||||||
|  |    bool pre_settings_check(); | ||||||
|  |    bool post_settings_check(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace scwx::qt::main
 | ||||||
|  | @ -3,15 +3,18 @@ | ||||||
| #include <scwx/qt/config/county_database.hpp> | #include <scwx/qt/config/county_database.hpp> | ||||||
| #include <scwx/qt/config/radar_site.hpp> | #include <scwx/qt/config/radar_site.hpp> | ||||||
| #include <scwx/qt/main/main_window.hpp> | #include <scwx/qt/main/main_window.hpp> | ||||||
|  | #include <scwx/qt/main/process_validation.hpp> | ||||||
| #include <scwx/qt/main/versions.hpp> | #include <scwx/qt/main/versions.hpp> | ||||||
| #include <scwx/qt/manager/log_manager.hpp> | #include <scwx/qt/manager/log_manager.hpp> | ||||||
| #include <scwx/qt/manager/radar_product_manager.hpp> | #include <scwx/qt/manager/radar_product_manager.hpp> | ||||||
| #include <scwx/qt/manager/resource_manager.hpp> | #include <scwx/qt/manager/resource_manager.hpp> | ||||||
| #include <scwx/qt/manager/settings_manager.hpp> | #include <scwx/qt/manager/settings_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/task_manager.hpp> | ||||||
| #include <scwx/qt/manager/thread_manager.hpp> | #include <scwx/qt/manager/thread_manager.hpp> | ||||||
| #include <scwx/qt/settings/general_settings.hpp> | #include <scwx/qt/settings/general_settings.hpp> | ||||||
| #include <scwx/qt/types/qt_types.hpp> | #include <scwx/qt/types/qt_types.hpp> | ||||||
| #include <scwx/qt/ui/setup/setup_wizard.hpp> | #include <scwx/qt/ui/setup/setup_wizard.hpp> | ||||||
|  | #include <scwx/qt/main/check_privilege.hpp> | ||||||
| #include <scwx/network/cpr.hpp> | #include <scwx/network/cpr.hpp> | ||||||
| #include <scwx/util/environment.hpp> | #include <scwx/util/environment.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | @ -25,11 +28,21 @@ | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
| #include <QStandardPaths> | #include <QStandardPaths> | ||||||
|  | #include <QStyleHints> | ||||||
|  | #include <QSurfaceFormat> | ||||||
| #include <QTranslator> | #include <QTranslator> | ||||||
|  | #include <QPalette> | ||||||
|  | #include <QStyle> | ||||||
|  | 
 | ||||||
|  | #define QT6CT_LIBRARY | ||||||
|  | #include <qt6ct-common/qt6ct.h> | ||||||
|  | #undef QT6CT_LIBRARY | ||||||
| 
 | 
 | ||||||
| static const std::string logPrefix_ = "scwx::main"; | static const std::string logPrefix_ = "scwx::main"; | ||||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| 
 | 
 | ||||||
|  | static void ConfigureTheme(const std::vector<std::string>& args); | ||||||
|  | static void InitializeOpenGL(); | ||||||
| static void OverrideDefaultStyle(const std::vector<std::string>& args); | static void OverrideDefaultStyle(const std::vector<std::string>& args); | ||||||
| 
 | 
 | ||||||
| int main(int argc, char* argv[]) | int main(int argc, char* argv[]) | ||||||
|  | @ -41,19 +54,28 @@ int main(int argc, char* argv[]) | ||||||
|       args.push_back(argv[i]); |       args.push_back(argv[i]); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |    if (!scwx::util::GetEnvironment("SCWX_TEST").empty()) | ||||||
|  |    { | ||||||
|  |       QStandardPaths::setTestModeEnabled(true); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    // Initialize logger
 |    // Initialize logger
 | ||||||
|    auto& logManager = scwx::qt::manager::LogManager::Instance(); |    auto& logManager = scwx::qt::manager::LogManager::Instance(); | ||||||
|    logManager.Initialize(); |    logManager.Initialize(); | ||||||
| 
 | 
 | ||||||
|    logger_->info("Supercell Wx v{} ({})", |    QCoreApplication::setApplicationName("Supercell Wx"); | ||||||
|  | 
 | ||||||
|  |    logManager.InitializeLogFile(); | ||||||
|  | 
 | ||||||
|  |    logger_->info("Supercell Wx v{}.{} ({})", | ||||||
|                  scwx::qt::main::kVersionString_, |                  scwx::qt::main::kVersionString_, | ||||||
|  |                  scwx::qt::main::kBuildNumber_, | ||||||
|                  scwx::qt::main::kCommitString_); |                  scwx::qt::main::kCommitString_); | ||||||
| 
 | 
 | ||||||
|    QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); |    InitializeOpenGL(); | ||||||
| 
 | 
 | ||||||
|    QApplication a(argc, argv); |    QApplication a(argc, argv); | ||||||
| 
 | 
 | ||||||
|    QCoreApplication::setApplicationName("Supercell Wx"); |  | ||||||
|    scwx::network::cpr::SetUserAgent( |    scwx::network::cpr::SetUserAgent( | ||||||
|       fmt::format("SupercellWx/{}", scwx::qt::main::kVersionString_)); |       fmt::format("SupercellWx/{}", scwx::qt::main::kVersionString_)); | ||||||
| 
 | 
 | ||||||
|  | @ -64,9 +86,11 @@ int main(int argc, char* argv[]) | ||||||
|       QCoreApplication::installTranslator(&translator); |       QCoreApplication::installTranslator(&translator); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    if (!scwx::util::GetEnvironment("SCWX_TEST").empty()) |    // Test to see if scwx was run with high privilege
 | ||||||
|  |    scwx::qt::main::PrivilegeChecker privilegeChecker; | ||||||
|  |    if (privilegeChecker.pre_settings_check()) | ||||||
|    { |    { | ||||||
|       QStandardPaths::setTestModeEnabled(true); |       return 0; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // Start the io_context main loop
 |    // Start the io_context main loop
 | ||||||
|  | @ -96,26 +120,25 @@ int main(int argc, char* argv[]) | ||||||
|    Aws::InitAPI(awsSdkOptions); |    Aws::InitAPI(awsSdkOptions); | ||||||
| 
 | 
 | ||||||
|    // Initialize application
 |    // Initialize application
 | ||||||
|    logManager.InitializeLogFile(); |  | ||||||
|    scwx::qt::config::RadarSite::Initialize(); |    scwx::qt::config::RadarSite::Initialize(); | ||||||
|    scwx::qt::config::CountyDatabase::Initialize(); |    scwx::qt::config::CountyDatabase::Initialize(); | ||||||
|  |    scwx::qt::manager::TaskManager::Initialize(); | ||||||
|    scwx::qt::manager::SettingsManager::Instance().Initialize(); |    scwx::qt::manager::SettingsManager::Instance().Initialize(); | ||||||
|    scwx::qt::manager::ResourceManager::Initialize(); |    scwx::qt::manager::ResourceManager::Initialize(); | ||||||
| 
 | 
 | ||||||
|    // Theme
 |    // Theme
 | ||||||
|    auto uiStyle = scwx::qt::types::GetUiStyle( |    ConfigureTheme(args); | ||||||
|       scwx::qt::settings::GeneralSettings::Instance().theme().GetValue()); |  | ||||||
| 
 | 
 | ||||||
|    if (uiStyle == scwx::qt::types::UiStyle::Default) |    // Check process modules for compatibility
 | ||||||
|  |    scwx::qt::main::CheckProcessModules(); | ||||||
|  | 
 | ||||||
|  |    int result = 0; | ||||||
|  |    if (privilegeChecker.post_settings_check()) | ||||||
|    { |    { | ||||||
|       OverrideDefaultStyle(args); |       result = 1; | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       QApplication::setStyle( |  | ||||||
|          QString::fromStdString(scwx::qt::types::GetUiStyleName(uiStyle))); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|       // Run initial setup if required
 |       // Run initial setup if required
 | ||||||
|       if (scwx::qt::ui::setup::SetupWizard::IsSetupRequired()) |       if (scwx::qt::ui::setup::SetupWizard::IsSetupRequired()) | ||||||
|       { |       { | ||||||
|  | @ -125,12 +148,27 @@ int main(int argc, char* argv[]) | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Run Qt main loop
 |       // Run Qt main loop
 | ||||||
|    int result; |  | ||||||
|       { |       { | ||||||
|          scwx::qt::main::MainWindow w; |          scwx::qt::main::MainWindow w; | ||||||
|  | 
 | ||||||
|  |          bool initialized = false; | ||||||
|  | 
 | ||||||
|  |          try | ||||||
|  |          { | ||||||
|             w.show(); |             w.show(); | ||||||
|  |             initialized = true; | ||||||
|  |          } | ||||||
|  |          catch (const std::exception& ex) | ||||||
|  |          { | ||||||
|  |             logger_->critical(ex.what()); | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|  |          if (initialized) | ||||||
|  |          { | ||||||
|             result = a.exec(); |             result = a.exec(); | ||||||
|          } |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    // Deinitialize application
 |    // Deinitialize application
 | ||||||
|    scwx::qt::manager::RadarProductManager::Cleanup(); |    scwx::qt::manager::RadarProductManager::Cleanup(); | ||||||
|  | @ -145,6 +183,7 @@ int main(int argc, char* argv[]) | ||||||
|    // Shutdown application
 |    // Shutdown application
 | ||||||
|    scwx::qt::manager::ResourceManager::Shutdown(); |    scwx::qt::manager::ResourceManager::Shutdown(); | ||||||
|    scwx::qt::manager::SettingsManager::Instance().Shutdown(); |    scwx::qt::manager::SettingsManager::Instance().Shutdown(); | ||||||
|  |    scwx::qt::manager::TaskManager::Shutdown(); | ||||||
| 
 | 
 | ||||||
|    // Shutdown AWS SDK
 |    // Shutdown AWS SDK
 | ||||||
|    Aws::ShutdownAPI(awsSdkOptions); |    Aws::ShutdownAPI(awsSdkOptions); | ||||||
|  | @ -152,6 +191,73 @@ int main(int argc, char* argv[]) | ||||||
|    return result; |    return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void ConfigureTheme(const std::vector<std::string>& args) | ||||||
|  | { | ||||||
|  |    auto& generalSettings = scwx::qt::settings::GeneralSettings::Instance(); | ||||||
|  | 
 | ||||||
|  |    auto uiStyle = | ||||||
|  |       scwx::qt::types::GetUiStyle(generalSettings.theme().GetValue()); | ||||||
|  |    auto qtColorScheme = scwx::qt::types::GetQtColorScheme(uiStyle); | ||||||
|  | 
 | ||||||
|  |    if (uiStyle == scwx::qt::types::UiStyle::Default) | ||||||
|  |    { | ||||||
|  |       OverrideDefaultStyle(args); | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       QApplication::setStyle( | ||||||
|  |          QString::fromStdString(scwx::qt::types::GetQtStyleName(uiStyle))); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    QGuiApplication::styleHints()->setColorScheme(qtColorScheme); | ||||||
|  | 
 | ||||||
|  |    std::optional<std::string> paletteFile; | ||||||
|  |    if (uiStyle == scwx::qt::types::UiStyle::FusionCustom) | ||||||
|  |    { | ||||||
|  |       paletteFile = generalSettings.theme_file().GetValue(); | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       paletteFile = scwx::qt::types::GetQtPaletteFile(uiStyle); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    if (paletteFile) | ||||||
|  |    { | ||||||
|  |       QPalette defaultPalette = QApplication::style()->standardPalette(); | ||||||
|  |       QPalette palette        = Qt6CT::loadColorScheme( | ||||||
|  |          QString::fromStdString(*paletteFile), defaultPalette); | ||||||
|  | 
 | ||||||
|  |       if (defaultPalette == palette) | ||||||
|  |       { | ||||||
|  |          logger_->warn("Failed to load palette file '{}'", *paletteFile); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |          logger_->info("Loaded palette file '{}'", *paletteFile); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       QApplication::setPalette(palette); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void InitializeOpenGL() | ||||||
|  | { | ||||||
|  |    QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); | ||||||
|  | 
 | ||||||
|  |    QSurfaceFormat surfaceFormat = QSurfaceFormat::defaultFormat(); | ||||||
|  |    surfaceFormat.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); | ||||||
|  |    surfaceFormat.setRenderableType(QSurfaceFormat::RenderableType::OpenGL); | ||||||
|  | 
 | ||||||
|  | #if defined(__APPLE__) | ||||||
|  |    // For macOS, we must choose between OpenGL 4.1 Core and OpenGL 2.1
 | ||||||
|  |    // Compatibility. OpenGL 2.1 does not meet requirements for shaders used by
 | ||||||
|  |    // Supercell Wx.
 | ||||||
|  |    surfaceFormat.setVersion(4, 1); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |    QSurfaceFormat::setDefaultFormat(surfaceFormat); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| OverrideDefaultStyle([[maybe_unused]] const std::vector<std::string>& args) | OverrideDefaultStyle([[maybe_unused]] const std::vector<std::string>& args) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| #include "main_window.hpp" | #include "main_window.hpp" | ||||||
| #include "./ui_main_window.h" | #include "./ui_main_window.h" | ||||||
| 
 | 
 | ||||||
|  | #include <scwx/qt/gl/gl_context.hpp> | ||||||
| #include <scwx/qt/main/application.hpp> | #include <scwx/qt/main/application.hpp> | ||||||
| #include <scwx/qt/main/versions.hpp> | #include <scwx/qt/main/versions.hpp> | ||||||
| #include <scwx/qt/manager/alert_manager.hpp> | #include <scwx/qt/manager/alert_manager.hpp> | ||||||
| #include <scwx/qt/manager/hotkey_manager.hpp> | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
| #include <scwx/qt/manager/placefile_manager.hpp> | #include <scwx/qt/manager/placefile_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/marker_manager.hpp> | ||||||
| #include <scwx/qt/manager/position_manager.hpp> | #include <scwx/qt/manager/position_manager.hpp> | ||||||
| #include <scwx/qt/manager/radar_product_manager.hpp> | #include <scwx/qt/manager/radar_product_manager.hpp> | ||||||
| #include <scwx/qt/manager/text_event_manager.hpp> | #include <scwx/qt/manager/text_event_manager.hpp> | ||||||
|  | @ -30,6 +32,7 @@ | ||||||
| #include <scwx/qt/ui/level2_settings_widget.hpp> | #include <scwx/qt/ui/level2_settings_widget.hpp> | ||||||
| #include <scwx/qt/ui/level3_products_widget.hpp> | #include <scwx/qt/ui/level3_products_widget.hpp> | ||||||
| #include <scwx/qt/ui/placefile_dialog.hpp> | #include <scwx/qt/ui/placefile_dialog.hpp> | ||||||
|  | #include <scwx/qt/ui/marker_dialog.hpp> | ||||||
| #include <scwx/qt/ui/radar_site_dialog.hpp> | #include <scwx/qt/ui/radar_site_dialog.hpp> | ||||||
| #include <scwx/qt/ui/settings_dialog.hpp> | #include <scwx/qt/ui/settings_dialog.hpp> | ||||||
| #include <scwx/qt/ui/update_dialog.hpp> | #include <scwx/qt/ui/update_dialog.hpp> | ||||||
|  | @ -52,10 +55,6 @@ | ||||||
| #include <QTimer> | #include <QTimer> | ||||||
| #include <QToolButton> | #include <QToolButton> | ||||||
| 
 | 
 | ||||||
| #if !defined(_MSC_VER) |  | ||||||
| #   include <date/date.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
| namespace qt | namespace qt | ||||||
|  | @ -90,11 +89,13 @@ public: | ||||||
|        imGuiDebugDialog_ {nullptr}, |        imGuiDebugDialog_ {nullptr}, | ||||||
|        layerDialog_ {nullptr}, |        layerDialog_ {nullptr}, | ||||||
|        placefileDialog_ {nullptr}, |        placefileDialog_ {nullptr}, | ||||||
|  |        markerDialog_ {nullptr}, | ||||||
|        radarSiteDialog_ {nullptr}, |        radarSiteDialog_ {nullptr}, | ||||||
|        settingsDialog_ {nullptr}, |        settingsDialog_ {nullptr}, | ||||||
|        updateDialog_ {nullptr}, |        updateDialog_ {nullptr}, | ||||||
|        alertManager_ {manager::AlertManager::Instance()}, |        alertManager_ {manager::AlertManager::Instance()}, | ||||||
|        placefileManager_ {manager::PlacefileManager::Instance()}, |        placefileManager_ {manager::PlacefileManager::Instance()}, | ||||||
|  |        markerManager_ {manager::MarkerManager::Instance()}, | ||||||
|        positionManager_ {manager::PositionManager::Instance()}, |        positionManager_ {manager::PositionManager::Instance()}, | ||||||
|        textEventManager_ {manager::TextEventManager::Instance()}, |        textEventManager_ {manager::TextEventManager::Instance()}, | ||||||
|        timelineManager_ {manager::TimelineManager::Instance()}, |        timelineManager_ {manager::TimelineManager::Instance()}, | ||||||
|  | @ -139,6 +140,9 @@ public: | ||||||
|    } |    } | ||||||
|    ~MainWindowImpl() |    ~MainWindowImpl() | ||||||
|    { |    { | ||||||
|  |       homeRadarConnection_.disconnect(); | ||||||
|  |       defaultTimeZoneConnection_.disconnect(); | ||||||
|  | 
 | ||||||
|       auto& generalSettings = settings::GeneralSettings::Instance(); |       auto& generalSettings = settings::GeneralSettings::Instance(); | ||||||
| 
 | 
 | ||||||
|       auto& customStyleUrl       = generalSettings.custom_style_url(); |       auto& customStyleUrl       = generalSettings.custom_style_url(); | ||||||
|  | @ -187,6 +191,8 @@ public: | ||||||
|    map::MapProvider    mapProvider_; |    map::MapProvider    mapProvider_; | ||||||
|    map::MapWidget*     activeMap_; |    map::MapWidget*     activeMap_; | ||||||
| 
 | 
 | ||||||
|  |    std::shared_ptr<gl::GlContext> glContext_ {nullptr}; | ||||||
|  | 
 | ||||||
|    ui::CollapsibleGroup*     mapSettingsGroup_; |    ui::CollapsibleGroup*     mapSettingsGroup_; | ||||||
|    ui::CollapsibleGroup*     level2ProductsGroup_; |    ui::CollapsibleGroup*     level2ProductsGroup_; | ||||||
|    ui::CollapsibleGroup*     level2SettingsGroup_; |    ui::CollapsibleGroup*     level2SettingsGroup_; | ||||||
|  | @ -207,6 +213,7 @@ public: | ||||||
|    ui::ImGuiDebugDialog*    imGuiDebugDialog_; |    ui::ImGuiDebugDialog*    imGuiDebugDialog_; | ||||||
|    ui::LayerDialog*         layerDialog_; |    ui::LayerDialog*         layerDialog_; | ||||||
|    ui::PlacefileDialog*     placefileDialog_; |    ui::PlacefileDialog*     placefileDialog_; | ||||||
|  |    ui::MarkerDialog*        markerDialog_; | ||||||
|    ui::RadarSiteDialog*     radarSiteDialog_; |    ui::RadarSiteDialog*     radarSiteDialog_; | ||||||
|    ui::SettingsDialog*      settingsDialog_; |    ui::SettingsDialog*      settingsDialog_; | ||||||
|    ui::UpdateDialog*        updateDialog_; |    ui::UpdateDialog*        updateDialog_; | ||||||
|  | @ -221,6 +228,7 @@ public: | ||||||
|    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { |    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { | ||||||
|       manager::HotkeyManager::Instance()}; |       manager::HotkeyManager::Instance()}; | ||||||
|    std::shared_ptr<manager::PlacefileManager> placefileManager_; |    std::shared_ptr<manager::PlacefileManager> placefileManager_; | ||||||
|  |    std::shared_ptr<manager::MarkerManager>    markerManager_; | ||||||
|    std::shared_ptr<manager::PositionManager>  positionManager_; |    std::shared_ptr<manager::PositionManager>  positionManager_; | ||||||
|    std::shared_ptr<manager::TextEventManager> textEventManager_; |    std::shared_ptr<manager::TextEventManager> textEventManager_; | ||||||
|    std::shared_ptr<manager::TimelineManager>  timelineManager_; |    std::shared_ptr<manager::TimelineManager>  timelineManager_; | ||||||
|  | @ -237,9 +245,12 @@ public: | ||||||
|         layerActions_ {}; |         layerActions_ {}; | ||||||
|    bool layerActionsInitialized_ {false}; |    bool layerActionsInitialized_ {false}; | ||||||
| 
 | 
 | ||||||
|  |    boost::signals2::scoped_connection homeRadarConnection_ {}; | ||||||
|  |    boost::signals2::scoped_connection defaultTimeZoneConnection_ {}; | ||||||
|  | 
 | ||||||
|    std::vector<map::MapWidget*> maps_; |    std::vector<map::MapWidget*> maps_; | ||||||
| 
 | 
 | ||||||
|    std::chrono::system_clock::time_point volumeTime_ {}; |    std::chrono::system_clock::time_point selectedTime_ {}; | ||||||
| 
 | 
 | ||||||
| public slots: | public slots: | ||||||
|    void UpdateMapParameters(double latitude, |    void UpdateMapParameters(double latitude, | ||||||
|  | @ -265,6 +276,7 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
|    ui->vcpLabel->setVisible(false); |    ui->vcpLabel->setVisible(false); | ||||||
|    ui->vcpValueLabel->setVisible(false); |    ui->vcpValueLabel->setVisible(false); | ||||||
|    ui->vcpDescriptionLabel->setVisible(false); |    ui->vcpDescriptionLabel->setVisible(false); | ||||||
|  |    ui->saveRadarProductsButton->setVisible(true); | ||||||
| 
 | 
 | ||||||
|    p->radarSitePresetsMenu_ = new QMenu(this); |    p->radarSitePresetsMenu_ = new QMenu(this); | ||||||
|    ui->radarSitePresetsButton->setMenu(p->radarSitePresetsMenu_); |    ui->radarSitePresetsButton->setMenu(p->radarSitePresetsMenu_); | ||||||
|  | @ -279,7 +291,6 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
| 
 | 
 | ||||||
|    // Configure Alert Dock
 |    // Configure Alert Dock
 | ||||||
|    p->alertDockWidget_ = new ui::AlertDockWidget(this); |    p->alertDockWidget_ = new ui::AlertDockWidget(this); | ||||||
|    p->alertDockWidget_->setVisible(false); |  | ||||||
|    addDockWidget(Qt::BottomDockWidgetArea, p->alertDockWidget_); |    addDockWidget(Qt::BottomDockWidgetArea, p->alertDockWidget_); | ||||||
| 
 | 
 | ||||||
|    // GPS Info Dialog
 |    // GPS Info Dialog
 | ||||||
|  | @ -308,18 +319,25 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
|    // Placefile Manager Dialog
 |    // Placefile Manager Dialog
 | ||||||
|    p->placefileDialog_ = new ui::PlacefileDialog(this); |    p->placefileDialog_ = new ui::PlacefileDialog(this); | ||||||
| 
 | 
 | ||||||
|  |    // Marker Manager Dialog
 | ||||||
|  |    p->markerDialog_ = new ui::MarkerDialog(this); | ||||||
|  | 
 | ||||||
|    // Layer Dialog
 |    // Layer Dialog
 | ||||||
|    p->layerDialog_ = new ui::LayerDialog(this); |    p->layerDialog_ = new ui::LayerDialog(this); | ||||||
| 
 | 
 | ||||||
|    // Settings Dialog
 |    // Settings Dialog
 | ||||||
|    p->settingsDialog_ = new ui::SettingsDialog(this); |    p->settingsDialog_ = new ui::SettingsDialog(p->settings_, this); | ||||||
| 
 | 
 | ||||||
|    // Map Settings
 |    // Map Settings
 | ||||||
|    p->mapSettingsGroup_ = new ui::CollapsibleGroup(tr("Map Settings"), this); |    p->mapSettingsGroup_ = new ui::CollapsibleGroup(tr("Map Settings"), this); | ||||||
|    p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleLabel); |    p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleLabel); | ||||||
|    p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleComboBox); |    p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleComboBox); | ||||||
|  |    p->mapSettingsGroup_->GetContentsLayout()->addWidget( | ||||||
|  |       ui->smoothRadarDataCheckBox); | ||||||
|    p->mapSettingsGroup_->GetContentsLayout()->addWidget( |    p->mapSettingsGroup_->GetContentsLayout()->addWidget( | ||||||
|       ui->trackLocationCheckBox); |       ui->trackLocationCheckBox); | ||||||
|  |    p->mapSettingsGroup_->GetContentsLayout()->addWidget( | ||||||
|  |       ui->saveRadarProductsButton); | ||||||
|    ui->radarToolboxScrollAreaContents->layout()->replaceWidget( |    ui->radarToolboxScrollAreaContents->layout()->replaceWidget( | ||||||
|       ui->mapSettingsGroupBox, p->mapSettingsGroup_); |       ui->mapSettingsGroupBox, p->mapSettingsGroup_); | ||||||
|    ui->mapSettingsGroupBox->setVisible(false); |    ui->mapSettingsGroupBox->setVisible(false); | ||||||
|  | @ -361,6 +379,7 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
|    p->animationDockWidget_ = new ui::AnimationDockWidget(this); |    p->animationDockWidget_ = new ui::AnimationDockWidget(this); | ||||||
|    p->timelineGroup_->GetContentsLayout()->addWidget(p->animationDockWidget_); |    p->timelineGroup_->GetContentsLayout()->addWidget(p->animationDockWidget_); | ||||||
|    ui->radarToolboxScrollAreaContents->layout()->addWidget(p->timelineGroup_); |    ui->radarToolboxScrollAreaContents->layout()->addWidget(p->timelineGroup_); | ||||||
|  |    p->animationDockWidget_->UpdateTimeZone(p->activeMap_->GetDefaultTimeZone()); | ||||||
| 
 | 
 | ||||||
|    // Reset toolbox spacer at the bottom
 |    // Reset toolbox spacer at the bottom
 | ||||||
|    ui->radarToolboxScrollAreaContents->layout()->removeItem( |    ui->radarToolboxScrollAreaContents->layout()->removeItem( | ||||||
|  | @ -444,9 +463,38 @@ void MainWindow::keyReleaseEvent(QKeyEvent* ev) | ||||||
| void MainWindow::showEvent(QShowEvent* event) | void MainWindow::showEvent(QShowEvent* event) | ||||||
| { | { | ||||||
|    QMainWindow::showEvent(event); |    QMainWindow::showEvent(event); | ||||||
|  |    auto& uiSettings = settings::UiSettings::Instance(); | ||||||
| 
 | 
 | ||||||
|  |    // restore the geometry state
 | ||||||
|  |    std::string uiGeometry = uiSettings.main_ui_geometry().GetValue(); | ||||||
|  |    restoreGeometry( | ||||||
|  |       QByteArray::fromBase64(QByteArray::fromStdString(uiGeometry))); | ||||||
|  | 
 | ||||||
|  |    // restore the UI state
 | ||||||
|  |    std::string uiState = uiSettings.main_ui_state().GetValue(); | ||||||
|  | 
 | ||||||
|  |    bool restored = | ||||||
|  |       restoreState(QByteArray::fromBase64(QByteArray::fromStdString(uiState))); | ||||||
|  |    if (!restored) | ||||||
|  |    { | ||||||
|       resizeDocks({ui->radarToolboxDock}, {194}, Qt::Horizontal); |       resizeDocks({ui->radarToolboxDock}, {194}, Qt::Horizontal); | ||||||
|    } |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MainWindow::closeEvent(QCloseEvent* event) | ||||||
|  | { | ||||||
|  |    auto& uiSettings = settings::UiSettings::Instance(); | ||||||
|  | 
 | ||||||
|  |    // save the UI geometry
 | ||||||
|  |    QByteArray uiGeometry = saveGeometry().toBase64(); | ||||||
|  |    uiSettings.main_ui_geometry().StageValue(uiGeometry.data()); | ||||||
|  | 
 | ||||||
|  |    // save the UI state
 | ||||||
|  |    QByteArray uiState = saveState().toBase64(); | ||||||
|  |    uiSettings.main_ui_state().StageValue(uiState.data()); | ||||||
|  | 
 | ||||||
|  |    QMainWindow::closeEvent(event); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::on_actionOpenNexrad_triggered() | void MainWindow::on_actionOpenNexrad_triggered() | ||||||
| { | { | ||||||
|  | @ -461,11 +509,10 @@ void MainWindow::on_actionOpenNexrad_triggered() | ||||||
|    map::MapWidget* currentMap = p->activeMap_; |    map::MapWidget* currentMap = p->activeMap_; | ||||||
| 
 | 
 | ||||||
|    // Make sure the parent window properly repaints on close
 |    // Make sure the parent window properly repaints on close
 | ||||||
|    connect( |    connect(dialog, | ||||||
|       dialog, |  | ||||||
|            &QFileDialog::finished, |            &QFileDialog::finished, | ||||||
|            this, |            this, | ||||||
|       [this]() { update(); }, |            static_cast<void (MainWindow::*)()>(&MainWindow::update), | ||||||
|            Qt::QueuedConnection); |            Qt::QueuedConnection); | ||||||
| 
 | 
 | ||||||
|    connect( |    connect( | ||||||
|  | @ -527,11 +574,10 @@ void MainWindow::on_actionOpenTextEvent_triggered() | ||||||
|    dialog->setAttribute(Qt::WA_DeleteOnClose); |    dialog->setAttribute(Qt::WA_DeleteOnClose); | ||||||
| 
 | 
 | ||||||
|    // Make sure the parent window properly repaints on close
 |    // Make sure the parent window properly repaints on close
 | ||||||
|    connect( |    connect(dialog, | ||||||
|       dialog, |  | ||||||
|            &QFileDialog::finished, |            &QFileDialog::finished, | ||||||
|            this, |            this, | ||||||
|       [this]() { update(); }, |            static_cast<void (MainWindow::*)()>(&MainWindow::update), | ||||||
|            Qt::QueuedConnection); |            Qt::QueuedConnection); | ||||||
| 
 | 
 | ||||||
|    connect(dialog, |    connect(dialog, | ||||||
|  | @ -586,6 +632,11 @@ void MainWindow::on_actionPlacefileManager_triggered() | ||||||
|    p->placefileDialog_->show(); |    p->placefileDialog_->show(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MainWindow::on_actionMarkerManager_triggered() | ||||||
|  | { | ||||||
|  |    p->markerDialog_->show(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void MainWindow::on_actionLayerManager_triggered() | void MainWindow::on_actionLayerManager_triggered() | ||||||
| { | { | ||||||
|    p->layerDialog_->show(); |    p->layerDialog_->show(); | ||||||
|  | @ -606,6 +657,11 @@ void MainWindow::on_actionDumpRadarProductRecords_triggered() | ||||||
|    manager::RadarProductManager::DumpRecords(); |    manager::RadarProductManager::DumpRecords(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MainWindow::on_actionRadarWireframe_triggered(bool checked) | ||||||
|  | { | ||||||
|  |    p->activeMap_->SetRadarWireframeEnabled(checked); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void MainWindow::on_actionUserManual_triggered() | void MainWindow::on_actionUserManual_triggered() | ||||||
| { | { | ||||||
|    QDesktopServices::openUrl(QUrl {"https://supercell-wx.readthedocs.io/"}); |    QDesktopServices::openUrl(QUrl {"https://supercell-wx.readthedocs.io/"}); | ||||||
|  | @ -726,6 +782,8 @@ void MainWindowImpl::ConfigureMapLayout() | ||||||
|       } |       } | ||||||
|    }; |    }; | ||||||
| 
 | 
 | ||||||
|  |    glContext_ = std::make_shared<gl::GlContext>(); | ||||||
|  | 
 | ||||||
|    for (int64_t y = 0; y < gridHeight; y++) |    for (int64_t y = 0; y < gridHeight; y++) | ||||||
|    { |    { | ||||||
|       QSplitter* hs = new QSplitter(vs); |       QSplitter* hs = new QSplitter(vs); | ||||||
|  | @ -735,7 +793,9 @@ void MainWindowImpl::ConfigureMapLayout() | ||||||
|       { |       { | ||||||
|          if (maps_.at(mapIndex) == nullptr) |          if (maps_.at(mapIndex) == nullptr) | ||||||
|          { |          { | ||||||
|             maps_[mapIndex] = new map::MapWidget(mapIndex, settings_); |             // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Owned by parent
 | ||||||
|  |             maps_[mapIndex] = | ||||||
|  |                new map::MapWidget(mapIndex, settings_, glContext_); | ||||||
|          } |          } | ||||||
| 
 | 
 | ||||||
|          hs->addWidget(maps_[mapIndex]); |          hs->addWidget(maps_[mapIndex]); | ||||||
|  | @ -768,9 +828,9 @@ void MainWindowImpl::ConfigureMapStyles() | ||||||
|       if ((customStyleAvailable_ && styleName == "Custom") || |       if ((customStyleAvailable_ && styleName == "Custom") || | ||||||
|           std::find_if(mapProviderInfo.mapStyles_.cbegin(), |           std::find_if(mapProviderInfo.mapStyles_.cbegin(), | ||||||
|                        mapProviderInfo.mapStyles_.cend(), |                        mapProviderInfo.mapStyles_.cend(), | ||||||
|                        [&](const auto& mapStyle) { |                        [&](const auto& mapStyle) | ||||||
|                           return mapStyle.name_ == styleName; |                        { return mapStyle.name_ == styleName; }) != | ||||||
|                        }) != mapProviderInfo.mapStyles_.cend()) |              mapProviderInfo.mapStyles_.cend()) | ||||||
|       { |       { | ||||||
|          // Initialize map style from settings
 |          // Initialize map style from settings
 | ||||||
|          maps_.at(i)->SetInitialMapStyle(styleName); |          maps_.at(i)->SetInitialMapStyle(styleName); | ||||||
|  | @ -913,11 +973,28 @@ void MainWindowImpl::ConnectMapSignals() | ||||||
|             } |             } | ||||||
|          }, |          }, | ||||||
|          Qt::QueuedConnection); |          Qt::QueuedConnection); | ||||||
|  |       connect( | ||||||
|  |          mapWidget, | ||||||
|  |          &map::MapWidget::IncomingLevel2ElevationChanged, | ||||||
|  |          this, | ||||||
|  |          [this](std::optional<float>) | ||||||
|  |          { level2SettingsWidget_->UpdateSettings(activeMap_); }, | ||||||
|  |          Qt::QueuedConnection); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::ConnectAnimationSignals() | void MainWindowImpl::ConnectAnimationSignals() | ||||||
| { | { | ||||||
|  |    defaultTimeZoneConnection_ = settings::GeneralSettings::Instance() | ||||||
|  |                                    .default_time_zone() | ||||||
|  |                                    .changed_signal() | ||||||
|  |                                    .connect( | ||||||
|  |                                       [this]() | ||||||
|  |                                       { | ||||||
|  |                                          animationDockWidget_->UpdateTimeZone( | ||||||
|  |                                             activeMap_->GetDefaultTimeZone()); | ||||||
|  |                                       }); | ||||||
|  | 
 | ||||||
|    connect(animationDockWidget_, |    connect(animationDockWidget_, | ||||||
|            &ui::AnimationDockWidget::DateTimeChanged, |            &ui::AnimationDockWidget::DateTimeChanged, | ||||||
|            timelineManager_.get(), |            timelineManager_.get(), | ||||||
|  | @ -961,21 +1038,16 @@ void MainWindowImpl::ConnectAnimationSignals() | ||||||
| 
 | 
 | ||||||
|    connect(timelineManager_.get(), |    connect(timelineManager_.get(), | ||||||
|            &manager::TimelineManager::SelectedTimeUpdated, |            &manager::TimelineManager::SelectedTimeUpdated, | ||||||
|            [this]() |  | ||||||
|            { |  | ||||||
|               for (auto map : maps_) |  | ||||||
|               { |  | ||||||
|                  map->update(); |  | ||||||
|               } |  | ||||||
|            }); |  | ||||||
|    connect(timelineManager_.get(), |  | ||||||
|            &manager::TimelineManager::VolumeTimeUpdated, |  | ||||||
|            [this](std::chrono::system_clock::time_point dateTime) |            [this](std::chrono::system_clock::time_point dateTime) | ||||||
|            { |            { | ||||||
|               volumeTime_ = dateTime; |               selectedTime_ = dateTime; | ||||||
|  | 
 | ||||||
|               for (auto map : maps_) |               for (auto map : maps_) | ||||||
|               { |               { | ||||||
|                  map->SelectTime(dateTime); |                  map->SelectTime(dateTime); | ||||||
|  |                  textEventManager_->SelectTime(dateTime); | ||||||
|  |                  QMetaObject::invokeMethod( | ||||||
|  |                     map, static_cast<void (QWidget::*)()>(&QWidget::update)); | ||||||
|               } |               } | ||||||
|            }); |            }); | ||||||
| 
 | 
 | ||||||
|  | @ -1055,10 +1127,29 @@ void MainWindowImpl::ConnectOtherSignals() | ||||||
|                  } |                  } | ||||||
|               } |               } | ||||||
|            }); |            }); | ||||||
|    connect(mainWindow_->ui->trackLocationCheckBox, |    connect( | ||||||
|            &QCheckBox::stateChanged, |       mainWindow_->ui->smoothRadarDataCheckBox, | ||||||
|  |       &QCheckBox::checkStateChanged, | ||||||
|       mainWindow_, |       mainWindow_, | ||||||
|            [this](int state) |       [this](Qt::CheckState state) | ||||||
|  |       { | ||||||
|  |          const bool smoothingEnabled = (state == Qt::CheckState::Checked); | ||||||
|  | 
 | ||||||
|  |          auto it = std::find(maps_.cbegin(), maps_.cend(), activeMap_); | ||||||
|  |          if (it != maps_.cend()) | ||||||
|  |          { | ||||||
|  |             const std::size_t i = std::distance(maps_.cbegin(), it); | ||||||
|  |             settings::MapSettings::Instance().smoothing_enabled(i).StageValue( | ||||||
|  |                smoothingEnabled); | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|  |          // Turn on smoothing
 | ||||||
|  |          activeMap_->SetSmoothingEnabled(smoothingEnabled); | ||||||
|  |       }); | ||||||
|  |    connect(mainWindow_->ui->trackLocationCheckBox, | ||||||
|  |            &QCheckBox::checkStateChanged, | ||||||
|  |            mainWindow_, | ||||||
|  |            [this](Qt::CheckState state) | ||||||
|            { |            { | ||||||
|               bool trackingEnabled = (state == Qt::CheckState::Checked); |               bool trackingEnabled = (state == Qt::CheckState::Checked); | ||||||
| 
 | 
 | ||||||
|  | @ -1068,22 +1159,37 @@ void MainWindowImpl::ConnectOtherSignals() | ||||||
|               // Turn on location tracking
 |               // Turn on location tracking
 | ||||||
|               positionManager_->TrackLocation(trackingEnabled); |               positionManager_->TrackLocation(trackingEnabled); | ||||||
|            }); |            }); | ||||||
|    connect(level2ProductsWidget_, |    connect( | ||||||
|  |       mainWindow_->ui->saveRadarProductsButton, | ||||||
|  |       &QAbstractButton::clicked, | ||||||
|  |       mainWindow_, | ||||||
|  |       [this]() | ||||||
|  |       { | ||||||
|  |          auto& mapSettings = settings::MapSettings::Instance(); | ||||||
|  |          for (std::size_t i = 0; i < maps_.size(); i++) | ||||||
|  |          { | ||||||
|  |             const auto& map = maps_.at(i); | ||||||
|  |             mapSettings.radar_product_group(i).StageValue( | ||||||
|  |                common::GetRadarProductGroupName(map->GetRadarProductGroup())); | ||||||
|  |             mapSettings.radar_product(i).StageValue(map->GetRadarProductName()); | ||||||
|  |          } | ||||||
|  |       }); | ||||||
|  |    connect( | ||||||
|  |       level2ProductsWidget_, | ||||||
|       &ui::Level2ProductsWidget::RadarProductSelected, |       &ui::Level2ProductsWidget::RadarProductSelected, | ||||||
|       mainWindow_, |       mainWindow_, | ||||||
|       [&](common::RadarProductGroup group, |       [&](common::RadarProductGroup group, | ||||||
|           const std::string&        productName, |           const std::string&        productName, | ||||||
|                int16_t                   productCode) { |           int16_t                   productCode) | ||||||
|               SelectRadarProduct(activeMap_, group, productName, productCode); |       { SelectRadarProduct(activeMap_, group, productName, productCode); }); | ||||||
|            }); |    connect( | ||||||
|    connect(level3ProductsWidget_, |       level3ProductsWidget_, | ||||||
|       &ui::Level3ProductsWidget::RadarProductSelected, |       &ui::Level3ProductsWidget::RadarProductSelected, | ||||||
|       mainWindow_, |       mainWindow_, | ||||||
|       [&](common::RadarProductGroup group, |       [&](common::RadarProductGroup group, | ||||||
|           const std::string&        productName, |           const std::string&        productName, | ||||||
|                int16_t                   productCode) { |           int16_t                   productCode) | ||||||
|               SelectRadarProduct(activeMap_, group, productName, productCode); |       { SelectRadarProduct(activeMap_, group, productName, productCode); }); | ||||||
|            }); |  | ||||||
|    connect(level2SettingsWidget_, |    connect(level2SettingsWidget_, | ||||||
|            &ui::Level2SettingsWidget::ElevationSelected, |            &ui::Level2SettingsWidget::ElevationSelected, | ||||||
|            mainWindow_, |            mainWindow_, | ||||||
|  | @ -1194,11 +1300,33 @@ void MainWindowImpl::ConnectOtherSignals() | ||||||
|            this, |            this, | ||||||
|            [this]() |            [this]() | ||||||
|            { |            { | ||||||
|               timeLabel_->setText(QString::fromStdString( |               timeLabel_->setText( | ||||||
|                  util::TimeString(std::chrono::system_clock::now()))); |                  QString::fromStdString(util::TimeString(util::time::now()))); | ||||||
|               timeLabel_->setVisible(true); |               timeLabel_->setVisible(true); | ||||||
|            }); |            }); | ||||||
|    clockTimer_.start(1000); |    clockTimer_.start(1000); | ||||||
|  | 
 | ||||||
|  |    auto& generalSettings = settings::GeneralSettings::Instance(); | ||||||
|  |    homeRadarConnection_ = | ||||||
|  |       generalSettings.default_radar_site().changed_signal().connect( | ||||||
|  |          [this]() | ||||||
|  |          { | ||||||
|  |             const std::shared_ptr<config::RadarSite> radarSite = | ||||||
|  |                activeMap_->GetRadarSite(); | ||||||
|  |             const std::string homeRadarSite = | ||||||
|  |                settings::GeneralSettings::Instance() | ||||||
|  |                   .default_radar_site() | ||||||
|  |                   .GetValue(); | ||||||
|  |             if (radarSite == nullptr) | ||||||
|  |             { | ||||||
|  |                mainWindow_->ui->saveRadarProductsButton->setVisible(false); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                mainWindow_->ui->saveRadarProductsButton->setVisible( | ||||||
|  |                   radarSite->id() == homeRadarSite); | ||||||
|  |             } | ||||||
|  |          }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::InitializeLayerDisplayActions() | void MainWindowImpl::InitializeLayerDisplayActions() | ||||||
|  | @ -1363,7 +1491,8 @@ void MainWindowImpl::SelectRadarProduct(map::MapWidget*           mapWidget, | ||||||
|       UpdateRadarProductSettings(); |       UpdateRadarProductSettings(); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    mapWidget->SelectRadarProduct(group, productName, productCode, volumeTime_); |    mapWidget->SelectRadarProduct( | ||||||
|  |       group, productName, productCode, selectedTime_); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::SetActiveMap(map::MapWidget* mapWidget) | void MainWindowImpl::SetActiveMap(map::MapWidget* mapWidget) | ||||||
|  | @ -1433,18 +1562,28 @@ void MainWindowImpl::UpdateRadarProductSettings() | ||||||
| { | { | ||||||
|    if (activeMap_->GetRadarProductGroup() == common::RadarProductGroup::Level2) |    if (activeMap_->GetRadarProductGroup() == common::RadarProductGroup::Level2) | ||||||
|    { |    { | ||||||
|       level2SettingsWidget_->UpdateSettings(activeMap_); |  | ||||||
|       level2SettingsGroup_->setVisible(true); |       level2SettingsGroup_->setVisible(true); | ||||||
|  |       // This should be done after setting visible for correct sizing
 | ||||||
|  |       level2SettingsWidget_->UpdateSettings(activeMap_); | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       level2SettingsGroup_->setVisible(false); |       level2SettingsGroup_->setVisible(false); | ||||||
|    } |    } | ||||||
|  | 
 | ||||||
|  |    mainWindow_->ui->smoothRadarDataCheckBox->setCheckState( | ||||||
|  |       activeMap_->GetSmoothingEnabled() ? Qt::CheckState::Checked : | ||||||
|  |                                           Qt::CheckState::Unchecked); | ||||||
|  | 
 | ||||||
|  |    mainWindow_->ui->actionRadarWireframe->setChecked( | ||||||
|  |       activeMap_->GetRadarWireframeEnabled()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::UpdateRadarSite() | void MainWindowImpl::UpdateRadarSite() | ||||||
| { | { | ||||||
|    std::shared_ptr<config::RadarSite> radarSite = activeMap_->GetRadarSite(); |    std::shared_ptr<config::RadarSite> radarSite = activeMap_->GetRadarSite(); | ||||||
|  |    const std::string                  homeRadarSite = | ||||||
|  |       settings::GeneralSettings::Instance().default_radar_site().GetValue(); | ||||||
| 
 | 
 | ||||||
|    if (radarSite != nullptr) |    if (radarSite != nullptr) | ||||||
|    { |    { | ||||||
|  | @ -1459,6 +1598,9 @@ void MainWindowImpl::UpdateRadarSite() | ||||||
|          radarSite->location_name().c_str()); |          radarSite->location_name().c_str()); | ||||||
| 
 | 
 | ||||||
|       timelineManager_->SetRadarSite(radarSite->id()); |       timelineManager_->SetRadarSite(radarSite->id()); | ||||||
|  | 
 | ||||||
|  |       mainWindow_->ui->saveRadarProductsButton->setVisible(radarSite->id() == | ||||||
|  |                                                            homeRadarSite); | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|  | @ -1466,12 +1608,15 @@ void MainWindowImpl::UpdateRadarSite() | ||||||
| 
 | 
 | ||||||
|       mainWindow_->ui->radarSiteValueLabel->setVisible(false); |       mainWindow_->ui->radarSiteValueLabel->setVisible(false); | ||||||
|       mainWindow_->ui->radarLocationLabel->setVisible(false); |       mainWindow_->ui->radarLocationLabel->setVisible(false); | ||||||
|  |       mainWindow_->ui->saveRadarProductsButton->setVisible(false); | ||||||
| 
 | 
 | ||||||
|       timelineManager_->SetRadarSite("?"); |       timelineManager_->SetRadarSite("?"); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    alertManager_->SetRadarSite(radarSite); |    alertManager_->SetRadarSite(radarSite); | ||||||
|    placefileManager_->SetRadarSite(radarSite); |    placefileManager_->SetRadarSite(radarSite); | ||||||
|  | 
 | ||||||
|  |    animationDockWidget_->UpdateTimeZone(activeMap_->GetDefaultTimeZone()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::UpdateVcp() | void MainWindowImpl::UpdateVcp() | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ public: | ||||||
|    void keyPressEvent(QKeyEvent* ev) override final; |    void keyPressEvent(QKeyEvent* ev) override final; | ||||||
|    void keyReleaseEvent(QKeyEvent* ev) override final; |    void keyReleaseEvent(QKeyEvent* ev) override final; | ||||||
|    void showEvent(QShowEvent* event) override; |    void showEvent(QShowEvent* event) override; | ||||||
|  |    void closeEvent(QCloseEvent* event) override; | ||||||
| 
 | 
 | ||||||
| signals: | signals: | ||||||
|    void ActiveMapMoved(double latitude, double longitude); |    void ActiveMapMoved(double latitude, double longitude); | ||||||
|  | @ -43,10 +44,12 @@ private slots: | ||||||
|    void on_actionRadarRange_triggered(bool checked); |    void on_actionRadarRange_triggered(bool checked); | ||||||
|    void on_actionRadarSites_triggered(bool checked); |    void on_actionRadarSites_triggered(bool checked); | ||||||
|    void on_actionPlacefileManager_triggered(); |    void on_actionPlacefileManager_triggered(); | ||||||
|  |    void on_actionMarkerManager_triggered(); | ||||||
|    void on_actionLayerManager_triggered(); |    void on_actionLayerManager_triggered(); | ||||||
|    void on_actionImGuiDebug_triggered(); |    void on_actionImGuiDebug_triggered(); | ||||||
|    void on_actionDumpLayerList_triggered(); |    void on_actionDumpLayerList_triggered(); | ||||||
|    void on_actionDumpRadarProductRecords_triggered(); |    void on_actionDumpRadarProductRecords_triggered(); | ||||||
|  |    void on_actionRadarWireframe_triggered(bool checked); | ||||||
|    void on_actionUserManual_triggered(); |    void on_actionUserManual_triggered(); | ||||||
|    void on_actionDiscord_triggered(); |    void on_actionDiscord_triggered(); | ||||||
|    void on_actionGitHubRepository_triggered(); |    void on_actionGitHubRepository_triggered(); | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ | ||||||
|      <x>0</x> |      <x>0</x> | ||||||
|      <y>0</y> |      <y>0</y> | ||||||
|      <width>1024</width> |      <width>1024</width> | ||||||
|      <height>33</height> |      <height>21</height> | ||||||
|     </rect> |     </rect> | ||||||
|    </property> |    </property> | ||||||
|    <widget class="QMenu" name="menuFile"> |    <widget class="QMenu" name="menuFile"> | ||||||
|  | @ -97,6 +97,8 @@ | ||||||
|     <addaction name="separator"/> |     <addaction name="separator"/> | ||||||
|     <addaction name="actionDumpLayerList"/> |     <addaction name="actionDumpLayerList"/> | ||||||
|     <addaction name="actionDumpRadarProductRecords"/> |     <addaction name="actionDumpRadarProductRecords"/> | ||||||
|  |     <addaction name="separator"/> | ||||||
|  |     <addaction name="actionRadarWireframe"/> | ||||||
|    </widget> |    </widget> | ||||||
|    <widget class="QMenu" name="menuTools"> |    <widget class="QMenu" name="menuTools"> | ||||||
|     <property name="title"> |     <property name="title"> | ||||||
|  | @ -104,6 +106,7 @@ | ||||||
|     </property> |     </property> | ||||||
|     <addaction name="actionPlacefileManager"/> |     <addaction name="actionPlacefileManager"/> | ||||||
|     <addaction name="actionLayerManager"/> |     <addaction name="actionLayerManager"/> | ||||||
|  |     <addaction name="actionMarkerManager"/> | ||||||
|    </widget> |    </widget> | ||||||
|    <addaction name="menuFile"/> |    <addaction name="menuFile"/> | ||||||
|    <addaction name="menuView"/> |    <addaction name="menuView"/> | ||||||
|  | @ -152,8 +155,8 @@ | ||||||
|          <rect> |          <rect> | ||||||
|           <x>0</x> |           <x>0</x> | ||||||
|           <y>0</y> |           <y>0</y> | ||||||
|           <width>190</width> |           <width>191</width> | ||||||
|           <height>686</height> |           <height>703</height> | ||||||
|          </rect> |          </rect> | ||||||
|         </property> |         </property> | ||||||
|         <layout class="QVBoxLayout" name="verticalLayout_6"> |         <layout class="QVBoxLayout" name="verticalLayout_6"> | ||||||
|  | @ -171,39 +174,25 @@ | ||||||
|          </property> |          </property> | ||||||
|          <item> |          <item> | ||||||
|           <widget class="QFrame" name="radarInfoFrame"> |           <widget class="QFrame" name="radarInfoFrame"> | ||||||
|            <property name="frameShape"> |  | ||||||
|             <enum>QFrame::Shape::StyledPanel</enum> |  | ||||||
|            </property> |  | ||||||
|            <property name="frameShadow"> |  | ||||||
|             <enum>QFrame::Shadow::Raised</enum> |  | ||||||
|            </property> |  | ||||||
|            <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0,0"> |            <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0,0"> | ||||||
|             <item row="0" column="2"> |             <item row="3" column="2" colspan="3"> | ||||||
|              <widget class="QLabel" name="radarSiteValueLabel"> |              <widget class="QLabel" name="vcpValueLabel"> | ||||||
|               <property name="sizePolicy"> |  | ||||||
|                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> |  | ||||||
|                 <horstretch>0</horstretch> |  | ||||||
|                 <verstretch>0</verstretch> |  | ||||||
|                </sizepolicy> |  | ||||||
|               </property> |  | ||||||
|               <property name="text"> |               <property name="text"> | ||||||
|                <string notr="true">KLSX</string> |                <string notr="true">35</string> | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|             <item row="3" column="0" colspan="2"> |             <item row="4" column="2" colspan="3"> | ||||||
|              <widget class="QLabel" name="vcpLabel"> |              <widget class="QLabel" name="vcpDescriptionLabel"> | ||||||
|               <property name="sizePolicy"> |  | ||||||
|                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> |  | ||||||
|                 <horstretch>0</horstretch> |  | ||||||
|                 <verstretch>0</verstretch> |  | ||||||
|                </sizepolicy> |  | ||||||
|               </property> |  | ||||||
|               <property name="toolTip"> |  | ||||||
|                <string>Volume Coverage Pattern</string> |  | ||||||
|               </property> |  | ||||||
|               <property name="text"> |               <property name="text"> | ||||||
|                <string>VCP</string> |                <string>Clear Air Mode</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|  |             <item row="1" column="2" colspan="3"> | ||||||
|  |              <widget class="QLabel" name="radarLocationLabel"> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">St. Louis, MO</string> | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|  | @ -268,34 +257,6 @@ | ||||||
|               </layout> |               </layout> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|             <item row="0" column="0" colspan="2"> |  | ||||||
|              <widget class="QLabel" name="radarSiteLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string>Radar Site</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="1" column="2" colspan="3"> |  | ||||||
|              <widget class="QLabel" name="radarLocationLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string notr="true">St. Louis, MO</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="3" column="2" colspan="3"> |  | ||||||
|              <widget class="QLabel" name="vcpValueLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string notr="true">35</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="4" column="2" colspan="3"> |  | ||||||
|              <widget class="QLabel" name="vcpDescriptionLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string>Clear Air Mode</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="0" column="3"> |             <item row="0" column="3"> | ||||||
|              <widget class="QToolButton" name="radarSiteSelectButton"> |              <widget class="QToolButton" name="radarSiteSelectButton"> | ||||||
|               <property name="maximumSize"> |               <property name="maximumSize"> | ||||||
|  | @ -309,6 +270,42 @@ | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|  |             <item row="3" column="0" colspan="2"> | ||||||
|  |              <widget class="QLabel" name="vcpLabel"> | ||||||
|  |               <property name="sizePolicy"> | ||||||
|  |                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> | ||||||
|  |                 <horstretch>0</horstretch> | ||||||
|  |                 <verstretch>0</verstretch> | ||||||
|  |                </sizepolicy> | ||||||
|  |               </property> | ||||||
|  |               <property name="toolTip"> | ||||||
|  |                <string>Volume Coverage Pattern</string> | ||||||
|  |               </property> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>VCP</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|  |             <item row="0" column="0" colspan="2"> | ||||||
|  |              <widget class="QLabel" name="radarSiteLabel"> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>Radar Site</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|  |             <item row="0" column="2"> | ||||||
|  |              <widget class="QLabel" name="radarSiteValueLabel"> | ||||||
|  |               <property name="sizePolicy"> | ||||||
|  |                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> | ||||||
|  |                 <horstretch>0</horstretch> | ||||||
|  |                 <verstretch>0</verstretch> | ||||||
|  |                </sizepolicy> | ||||||
|  |               </property> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">KLSX</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|            </layout> |            </layout> | ||||||
|           </widget> |           </widget> | ||||||
|          </item> |          </item> | ||||||
|  | @ -328,6 +325,13 @@ | ||||||
|             <item> |             <item> | ||||||
|              <widget class="QComboBox" name="mapStyleComboBox"/> |              <widget class="QComboBox" name="mapStyleComboBox"/> | ||||||
|             </item> |             </item> | ||||||
|  |             <item> | ||||||
|  |              <widget class="QCheckBox" name="smoothRadarDataCheckBox"> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>Smooth Radar Data</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|             <item> |             <item> | ||||||
|              <widget class="QCheckBox" name="trackLocationCheckBox"> |              <widget class="QCheckBox" name="trackLocationCheckBox"> | ||||||
|               <property name="text"> |               <property name="text"> | ||||||
|  | @ -335,6 +339,13 @@ | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|  |             <item> | ||||||
|  |              <widget class="QPushButton" name="saveRadarProductsButton"> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>Set As Default Products</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|            </layout> |            </layout> | ||||||
|           </widget> |           </widget> | ||||||
|          </item> |          </item> | ||||||
|  | @ -487,6 +498,23 @@ | ||||||
|     <string>&GPS Info</string> |     <string>&GPS Info</string> | ||||||
|    </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|  |   <action name="actionMarkerManager"> | ||||||
|  |    <property name="icon"> | ||||||
|  |     <iconset resource="../../../../scwx-qt.qrc"> | ||||||
|  |      <normaloff>:/res/icons/font-awesome-6/house-solid.svg</normaloff>:/res/icons/font-awesome-6/house-solid.svg</iconset> | ||||||
|  |    </property> | ||||||
|  |    <property name="text"> | ||||||
|  |     <string>Location &Marker Manager</string> | ||||||
|  |    </property> | ||||||
|  |   </action> | ||||||
|  |   <action name="actionRadarWireframe"> | ||||||
|  |    <property name="checkable"> | ||||||
|  |     <bool>true</bool> | ||||||
|  |    </property> | ||||||
|  |    <property name="text"> | ||||||
|  |     <string>Radar &Wireframe</string> | ||||||
|  |    </property> | ||||||
|  |   </action> | ||||||
|  </widget> |  </widget> | ||||||
|  <resources> |  <resources> | ||||||
|   <include location="../../../../scwx-qt.qrc"/> |   <include location="../../../../scwx-qt.qrc"/> | ||||||
|  |  | ||||||
							
								
								
									
										109
									
								
								scwx-qt/source/scwx/qt/main/process_validation.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,109 @@ | ||||||
|  | #include <scwx/qt/main/process_validation.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | #if defined(_WIN32) | ||||||
|  | #   include <scwx/qt/settings/general_settings.hpp> | ||||||
|  | 
 | ||||||
|  | #   include <wtypes.h> | ||||||
|  | #   include <Psapi.h> | ||||||
|  | 
 | ||||||
|  | #   include <boost/algorithm/string/predicate.hpp> | ||||||
|  | #   include <boost/locale.hpp> | ||||||
|  | #   include <fmt/ranges.h> | ||||||
|  | #   include <QCheckBox> | ||||||
|  | #   include <QMessageBox> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | namespace scwx::qt::main | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = "scwx::qt::main::process_validation"; | ||||||
|  | static const auto        logger_    = util::Logger::Create(logPrefix_); | ||||||
|  | 
 | ||||||
|  | void CheckProcessModules() | ||||||
|  | { | ||||||
|  | #if defined(_WIN32) | ||||||
|  |    HANDLE  process = GetCurrentProcess(); | ||||||
|  |    HMODULE modules[1024]; | ||||||
|  |    DWORD   cbNeeded = 0; | ||||||
|  | 
 | ||||||
|  |    std::vector<std::string> incompatibleDlls {}; | ||||||
|  |    std::vector<std::string> descriptions {}; | ||||||
|  | 
 | ||||||
|  |    auto& processModuleWarningsEnabled = | ||||||
|  |       settings::GeneralSettings::Instance().process_module_warnings_enabled(); | ||||||
|  | 
 | ||||||
|  |    if (EnumProcessModules(process, modules, sizeof(modules), &cbNeeded)) | ||||||
|  |    { | ||||||
|  |       std::uint32_t numModules = cbNeeded / sizeof(HMODULE); | ||||||
|  |       for (std::uint32_t i = 0; i < numModules; ++i) | ||||||
|  |       { | ||||||
|  |          char modulePath[MAX_PATH]; | ||||||
|  |          if (GetModuleFileNameExA(process, modules[i], modulePath, MAX_PATH)) | ||||||
|  |          { | ||||||
|  |             std::string path = modulePath; | ||||||
|  | 
 | ||||||
|  |             logger_->trace("DLL Found: {}", path); | ||||||
|  | 
 | ||||||
|  |             if (boost::algorithm::iends_with(path, "NahimicOSD.dll")) | ||||||
|  |             { | ||||||
|  |                std::string description = | ||||||
|  |                   QObject::tr( | ||||||
|  |                      "ASUS Sonic Studio injects a Nahimic driver, which causes " | ||||||
|  |                      "Supercell Wx to hang. It is suggested to disable the " | ||||||
|  |                      "Nahimic service, or to uninstall ASUS Sonic Studio and " | ||||||
|  |                      "the Nahimic driver.") | ||||||
|  |                      .toStdString(); | ||||||
|  | 
 | ||||||
|  |                logger_->warn("Incompatible DLL found: {}", path); | ||||||
|  |                logger_->warn("{}", description); | ||||||
|  | 
 | ||||||
|  |                // Only populate vectors for the message box if warnings are
 | ||||||
|  |                // enabled
 | ||||||
|  |                if (processModuleWarningsEnabled.GetValue()) | ||||||
|  |                { | ||||||
|  |                   incompatibleDlls.push_back(path); | ||||||
|  |                   descriptions.push_back(description); | ||||||
|  |                } | ||||||
|  |             } | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    if (!incompatibleDlls.empty()) | ||||||
|  |    { | ||||||
|  |       const std::string header = | ||||||
|  |          QObject::tr( | ||||||
|  |             "The following DLLs have been injected into the Supercell Wx " | ||||||
|  |             "process:") | ||||||
|  |             .toStdString(); | ||||||
|  |       const std::string defaultMessage = | ||||||
|  |          QObject::tr( | ||||||
|  |             "Supercell Wx is known to not run correctly with these DLLs " | ||||||
|  |             "injected. We suggest stopping or uninstalling these services if " | ||||||
|  |             "you experience crashes or unexpected behavior while using " | ||||||
|  |             "Supercell Wx.") | ||||||
|  |             .toStdString(); | ||||||
|  | 
 | ||||||
|  |       std::string message = fmt::format("{}\n\n{}\n\n{}\n\n{}", | ||||||
|  |                                         header, | ||||||
|  |                                         fmt::join(incompatibleDlls, "\n"), | ||||||
|  |                                         defaultMessage, | ||||||
|  |                                         fmt::join(descriptions, "\n")); | ||||||
|  | 
 | ||||||
|  |       QMessageBox dialog(QMessageBox::Icon::Warning, | ||||||
|  |                          QObject::tr("Supercell Wx"), | ||||||
|  |                          QString::fromStdString(message)); | ||||||
|  |       QCheckBox*  checkBox = | ||||||
|  |          new QCheckBox(QObject::tr("Don't show this message again"), &dialog); | ||||||
|  |       dialog.setCheckBox(checkBox); | ||||||
|  |       dialog.exec(); | ||||||
|  | 
 | ||||||
|  |       // Stage the result of the checkbox. This value will be committed on
 | ||||||
|  |       // shutdown.
 | ||||||
|  |       processModuleWarningsEnabled.StageValue(!checkBox->isChecked()); | ||||||
|  |    } | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace scwx::qt::main
 | ||||||
							
								
								
									
										8
									
								
								scwx-qt/source/scwx/qt/main/process_validation.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,8 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | namespace scwx::qt::main | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | void CheckProcessModules(); | ||||||
|  | 
 | ||||||
|  | } // namespace scwx::qt::main
 | ||||||
|  | @ -3,17 +3,12 @@ | ||||||
| #include <cstdint> | #include <cstdint> | ||||||
| #include <string> | #include <string> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::main | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace main |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | const std::uint32_t kBuildNumber_ {${build_number}u}; | ||||||
| const std::string   kCommitString_ {"${commit_string}"}; | const std::string   kCommitString_ {"${commit_string}"}; | ||||||
| const std::uint16_t kCopyrightYear_ {${copyright_year}u}; | const std::uint16_t kCopyrightYear_ {${copyright_year}u}; | ||||||
| const std::string   kVersionString_ {"${version_string}"}; | const std::string   kVersionString_ {"${version_string}"}; | ||||||
| 
 | 
 | ||||||
| } // namespace main
 | } // namespace scwx::qt::main
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -2,12 +2,13 @@ | ||||||
| #include <scwx/qt/manager/media_manager.hpp> | #include <scwx/qt/manager/media_manager.hpp> | ||||||
| #include <scwx/qt/manager/position_manager.hpp> | #include <scwx/qt/manager/position_manager.hpp> | ||||||
| #include <scwx/qt/manager/text_event_manager.hpp> | #include <scwx/qt/manager/text_event_manager.hpp> | ||||||
|  | #include <scwx/qt/config/radar_site.hpp> | ||||||
| #include <scwx/qt/settings/audio_settings.hpp> | #include <scwx/qt/settings/audio_settings.hpp> | ||||||
|  | #include <scwx/qt/settings/general_settings.hpp> | ||||||
| #include <scwx/qt/types/location_types.hpp> | #include <scwx/qt/types/location_types.hpp> | ||||||
| #include <scwx/qt/util/geographic_lib.hpp> | #include <scwx/qt/util/geographic_lib.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| #include <scwx/qt/config/radar_site.hpp> | #include <scwx/util/time.hpp> | ||||||
| #include <scwx/qt/settings/general_settings.hpp> |  | ||||||
| 
 | 
 | ||||||
| #include <boost/asio/post.hpp> | #include <boost/asio/post.hpp> | ||||||
| #include <boost/asio/thread_pool.hpp> | #include <boost/asio/thread_pool.hpp> | ||||||
|  | @ -138,8 +139,10 @@ common::Coordinate AlertManager::Impl::CurrentCoordinate( | ||||||
| void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, | void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, | ||||||
|                                      size_t messageIndex) const |                                      size_t messageIndex) const | ||||||
| { | { | ||||||
|  |    auto messages = textEventManager_->message_list(key); | ||||||
|  | 
 | ||||||
|    // Skip alert if there are more messages to be processed
 |    // Skip alert if there are more messages to be processed
 | ||||||
|    if (messageIndex + 1 < textEventManager_->message_count(key)) |    if (messages.empty() || messageIndex + 1 < messages.size()) | ||||||
|    { |    { | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
|  | @ -153,7 +156,7 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, | ||||||
|       audioSettings.alert_radius().GetValue()); |       audioSettings.alert_radius().GetValue()); | ||||||
|    std::string alertWFO = audioSettings.alert_wfo().GetValue(); |    std::string alertWFO = audioSettings.alert_wfo().GetValue(); | ||||||
| 
 | 
 | ||||||
|    auto message = textEventManager_->message_list(key).at(messageIndex); |    auto message = messages.at(messageIndex); | ||||||
| 
 | 
 | ||||||
|    for (auto& segment : message->segments()) |    for (auto& segment : message->segments()) | ||||||
|    { |    { | ||||||
|  | @ -170,7 +173,7 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, | ||||||
| 
 | 
 | ||||||
|       // If the event has ended or is inactive, or if the alert is not enabled,
 |       // If the event has ended or is inactive, or if the alert is not enabled,
 | ||||||
|       // skip it
 |       // skip it
 | ||||||
|       if (eventEnd < std::chrono::system_clock::now() || !alertActive || |       if (eventEnd < scwx::util::time::now() || !alertActive || | ||||||
|           !audioSettings.alert_enabled(phenomenon).GetValue()) |           !audioSettings.alert_enabled(phenomenon).GetValue()) | ||||||
|       { |       { | ||||||
|          continue; |          continue; | ||||||
|  |  | ||||||
|  | @ -155,7 +155,7 @@ void DownloadManager::Impl::DownloadSync( | ||||||
|             return !request->IsCanceled(); |             return !request->IsCanceled(); | ||||||
|          }), |          }), | ||||||
|       cpr::WriteCallback( |       cpr::WriteCallback( | ||||||
|          [&](std::string data, std::intptr_t /* userdata */) |          [&](const std::string_view& data, std::intptr_t /* userdata */) | ||||||
|          { |          { | ||||||
|             // Write file
 |             // Write file
 | ||||||
|             ofs << data; |             ofs << data; | ||||||
|  |  | ||||||
|  | @ -15,19 +15,17 @@ | ||||||
| #include <boost/container_hash/hash.hpp> | #include <boost/container_hash/hash.hpp> | ||||||
| #include <boost/unordered/unordered_flat_map.hpp> | #include <boost/unordered/unordered_flat_map.hpp> | ||||||
| #include <boost/unordered/unordered_flat_set.hpp> | #include <boost/unordered/unordered_flat_set.hpp> | ||||||
|  | #include <fmt/ranges.h> | ||||||
| #include <fontconfig/fontconfig.h> | #include <fontconfig/fontconfig.h> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::manager | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace manager |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| static const std::string logPrefix_ = "scwx::qt::manager::font_manager"; | static const std::string logPrefix_ = "scwx::qt::manager::font_manager"; | ||||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| 
 | 
 | ||||||
| static const std::string kFcTrueType_ {"TrueType"}; | static const std::string kFcTrueType_ {"TrueType"}; | ||||||
|  | static const std::string kFcOpenType_ {"CFF"}; | ||||||
| 
 | 
 | ||||||
| struct FontRecord | struct FontRecord | ||||||
| { | { | ||||||
|  | @ -36,15 +34,13 @@ struct FontRecord | ||||||
|    std::string filename_ {}; |    std::string filename_ {}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef std::pair<FontRecord, units::font_size::pixels<int>> FontRecordPair; |  | ||||||
| 
 |  | ||||||
| template<class Key> | template<class Key> | ||||||
| struct FontRecordHash; | struct FontRecordHash; | ||||||
| 
 | 
 | ||||||
| template<> | template<> | ||||||
| struct FontRecordHash<FontRecordPair> | struct FontRecordHash<FontRecord> | ||||||
| { | { | ||||||
|    size_t operator()(const FontRecordPair& x) const; |    size_t operator()(const FontRecord& x) const; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class FontManager::Impl | class FontManager::Impl | ||||||
|  | @ -69,6 +65,7 @@ public: | ||||||
| 
 | 
 | ||||||
|    const std::vector<char>& GetRawFontData(const std::string& filename); |    const std::vector<char>& GetRawFontData(const std::string& filename); | ||||||
| 
 | 
 | ||||||
|  |    static bool       CheckFontFormat(const FcChar8* format); | ||||||
|    static FontRecord MatchFontFile(const std::string&              family, |    static FontRecord MatchFontFile(const std::string&              family, | ||||||
|                                    const std::vector<std::string>& styles); |                                    const std::vector<std::string>& styles); | ||||||
| 
 | 
 | ||||||
|  | @ -78,20 +75,20 @@ public: | ||||||
| 
 | 
 | ||||||
|    std::shared_mutex imguiFontAtlasMutex_ {}; |    std::shared_mutex imguiFontAtlasMutex_ {}; | ||||||
| 
 | 
 | ||||||
|    std::uint64_t imguiFontsBuildCount_ {}; |    boost::unordered_flat_map<FontRecord, | ||||||
| 
 |  | ||||||
|    boost::unordered_flat_map<FontRecordPair, |  | ||||||
|                              std::shared_ptr<types::ImGuiFont>, |                              std::shared_ptr<types::ImGuiFont>, | ||||||
|                              FontRecordHash<FontRecordPair>> |                              FontRecordHash<FontRecord>> | ||||||
|                      imguiFonts_ {}; |                      imguiFonts_ {}; | ||||||
|    std::shared_mutex imguiFontsMutex_ {}; |    std::shared_mutex imguiFontsMutex_ {}; | ||||||
| 
 | 
 | ||||||
|    boost::unordered_flat_map<std::string, std::vector<char>> rawFontData_ {}; |    boost::unordered_flat_map<std::string, std::vector<char>> rawFontData_ {}; | ||||||
|    std::mutex rawFontDataMutex_ {}; |    std::mutex rawFontDataMutex_ {}; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<types::ImGuiFont> defaultFont_ {}; |    std::pair<std::shared_ptr<types::ImGuiFont>, units::font_size::pixels<float>> | ||||||
|  |       defaultFont_ {}; | ||||||
|    boost::unordered_flat_map<types::FontCategory, |    boost::unordered_flat_map<types::FontCategory, | ||||||
|                              std::shared_ptr<types::ImGuiFont>> |                              std::pair<std::shared_ptr<types::ImGuiFont>, | ||||||
|  |                                        units::font_size::pixels<float>>> | ||||||
|       fontCategoryImguiFontMap_ {}; |       fontCategoryImguiFontMap_ {}; | ||||||
|    boost::unordered_flat_map<types::FontCategory, QFont> |    boost::unordered_flat_map<types::FontCategory, QFont> | ||||||
|               fontCategoryQFontMap_ {}; |               fontCategoryQFontMap_ {}; | ||||||
|  | @ -136,13 +133,13 @@ void FontManager::Impl::ConnectSignals() | ||||||
|             }); |             }); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    QObject::connect( |    QObject::connect(&SettingsManager::Instance(), | ||||||
|       &SettingsManager::Instance(), |  | ||||||
|                     &SettingsManager::SettingsSaved, |                     &SettingsManager::SettingsSaved, | ||||||
|                     self_, |                     self_, | ||||||
|                     [this]() |                     [this]() | ||||||
|                     { |                     { | ||||||
|          std::scoped_lock lock {dirtyFontsMutex_, fontCategoryMutex_}; |                        const std::scoped_lock lock {dirtyFontsMutex_, | ||||||
|  |                                                     fontCategoryMutex_}; | ||||||
| 
 | 
 | ||||||
|                        for (auto fontCategory : dirtyFonts_) |                        for (auto fontCategory : dirtyFonts_) | ||||||
|                        { |                        { | ||||||
|  | @ -163,6 +160,22 @@ void FontManager::InitializeFonts() | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | units::font_size::pixels<float> | ||||||
|  | FontManager::ImFontSize(units::font_size::pixels<double> size) | ||||||
|  | { | ||||||
|  |    static constexpr units::font_size::pixels<int> kMinFontSize_ {8}; | ||||||
|  |    static constexpr units::font_size::pixels<int> kMaxFontSize_ {96}; | ||||||
|  | 
 | ||||||
|  |    // Only allow whole pixels, and clamp to 6-72 pt
 | ||||||
|  |    const units::font_size::pixels<double> pixels {size}; | ||||||
|  |    const units::font_size::pixels<int>    imFontSize { | ||||||
|  |       std::clamp(static_cast<int>(pixels.value()), | ||||||
|  |                  kMinFontSize_.value(), | ||||||
|  |                  kMaxFontSize_.value())}; | ||||||
|  | 
 | ||||||
|  |    return imFontSize; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void FontManager::Impl::UpdateImGuiFont(types::FontCategory fontCategory) | void FontManager::Impl::UpdateImGuiFont(types::FontCategory fontCategory) | ||||||
| { | { | ||||||
|    auto& textSettings = settings::TextSettings::Instance(); |    auto& textSettings = settings::TextSettings::Instance(); | ||||||
|  | @ -173,7 +186,8 @@ void FontManager::Impl::UpdateImGuiFont(types::FontCategory fontCategory) | ||||||
|       textSettings.font_point_size(fontCategory).GetValue()}; |       textSettings.font_point_size(fontCategory).GetValue()}; | ||||||
| 
 | 
 | ||||||
|    fontCategoryImguiFontMap_.insert_or_assign( |    fontCategoryImguiFontMap_.insert_or_assign( | ||||||
|       fontCategory, self_->LoadImGuiFont(family, {styles}, size)); |       fontCategory, | ||||||
|  |       std::make_pair(self_->LoadImGuiFont(family, {styles}), ImFontSize(size))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FontManager::Impl::UpdateQFont(types::FontCategory fontCategory) | void FontManager::Impl::UpdateQFont(types::FontCategory fontCategory) | ||||||
|  | @ -188,7 +202,13 @@ void FontManager::Impl::UpdateQFont(types::FontCategory fontCategory) | ||||||
|    QFont font = QFontDatabase::font(QString::fromStdString(family), |    QFont font = QFontDatabase::font(QString::fromStdString(family), | ||||||
|                                     QString::fromStdString(styles), |                                     QString::fromStdString(styles), | ||||||
|                                     static_cast<int>(size.value())); |                                     static_cast<int>(size.value())); | ||||||
|  | 
 | ||||||
|  | #if !defined(__APPLE__) | ||||||
|    font.setPointSizeF(size.value()); |    font.setPointSizeF(size.value()); | ||||||
|  | #else | ||||||
|  |    const units::font_size::pixels<double> pixelSize {size}; | ||||||
|  |    font.setPixelSize(static_cast<int>(pixelSize.value())); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|    fontCategoryQFontMap_.insert_or_assign(fontCategory, font); |    fontCategoryQFontMap_.insert_or_assign(fontCategory, font); | ||||||
| } | } | ||||||
|  | @ -198,11 +218,6 @@ std::shared_mutex& FontManager::imgui_font_atlas_mutex() | ||||||
|    return p->imguiFontAtlasMutex_; |    return p->imguiFontAtlasMutex_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::uint64_t FontManager::imgui_fonts_build_count() const |  | ||||||
| { |  | ||||||
|    return p->imguiFontsBuildCount_; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int FontManager::GetFontId(types::Font font) const | int FontManager::GetFontId(types::Font font) const | ||||||
| { | { | ||||||
|    auto it = p->fontIds_.find(font); |    auto it = p->fontIds_.find(font); | ||||||
|  | @ -213,7 +228,7 @@ int FontManager::GetFontId(types::Font font) const | ||||||
|    return -1; |    return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<types::ImGuiFont> | std::pair<std::shared_ptr<types::ImGuiFont>, units::font_size::pixels<float>> | ||||||
| FontManager::GetImGuiFont(types::FontCategory fontCategory) | FontManager::GetImGuiFont(types::FontCategory fontCategory) | ||||||
| { | { | ||||||
|    std::unique_lock lock {p->fontCategoryMutex_}; |    std::unique_lock lock {p->fontCategoryMutex_}; | ||||||
|  | @ -243,29 +258,21 @@ QFont FontManager::GetQFont(types::FontCategory fontCategory) | ||||||
| std::shared_ptr<types::ImGuiFont> | std::shared_ptr<types::ImGuiFont> | ||||||
| FontManager::LoadImGuiFont(const std::string&              family, | FontManager::LoadImGuiFont(const std::string&              family, | ||||||
|                            const std::vector<std::string>& styles, |                            const std::vector<std::string>& styles, | ||||||
|                            units::font_size::points<double> size, |  | ||||||
|                            bool                            loadIfNotFound) |                            bool                            loadIfNotFound) | ||||||
| { | { | ||||||
|    const std::string styleString = fmt::format("{}", fmt::join(styles, " ")); |    const std::string styleString = fmt::format("{}", fmt::join(styles, " ")); | ||||||
|    const std::string fontString = |    const std::string fontString  = fmt::format("{}:{}", family, styleString); | ||||||
|       fmt::format("{}-{}:{}", family, size.value(), styleString); |  | ||||||
| 
 | 
 | ||||||
|    logger_->debug("LoadFontResource: {}", fontString); |    logger_->debug("LoadFontResource: {}", fontString); | ||||||
| 
 | 
 | ||||||
|    FontRecord fontRecord = Impl::MatchFontFile(family, styles); |    FontRecord fontRecord = Impl::MatchFontFile(family, styles); | ||||||
| 
 | 
 | ||||||
|    // Only allow whole pixels, and clamp to 6-72 pt
 |  | ||||||
|    units::font_size::pixels<double> pixels {size}; |  | ||||||
|    units::font_size::pixels<int>    imFontSize { |  | ||||||
|       std::clamp(static_cast<int>(pixels.value()), 8, 96)}; |  | ||||||
|    auto imguiFontKey = std::make_pair(fontRecord, imFontSize); |  | ||||||
| 
 |  | ||||||
|    // Search for a loaded ImGui font
 |    // Search for a loaded ImGui font
 | ||||||
|    { |    { | ||||||
|       std::shared_lock imguiFontLock {p->imguiFontsMutex_}; |       std::shared_lock imguiFontLock {p->imguiFontsMutex_}; | ||||||
| 
 | 
 | ||||||
|       // Search for the associated ImGui font
 |       // Search for the associated ImGui font
 | ||||||
|       auto it = p->imguiFonts_.find(imguiFontKey); |       auto it = p->imguiFonts_.find(fontRecord); | ||||||
|       if (it != p->imguiFonts_.end()) |       if (it != p->imguiFonts_.end()) | ||||||
|       { |       { | ||||||
|          return it->second; |          return it->second; | ||||||
|  | @ -290,7 +297,7 @@ FontManager::LoadImGuiFont(const std::string&               family, | ||||||
| 
 | 
 | ||||||
|    // Search for the associated ImGui font again, to prevent loading the same
 |    // Search for the associated ImGui font again, to prevent loading the same
 | ||||||
|    // font twice
 |    // font twice
 | ||||||
|    auto it = p->imguiFonts_.find(imguiFontKey); |    auto it = p->imguiFonts_.find(fontRecord); | ||||||
|    if (it != p->imguiFonts_.end()) |    if (it != p->imguiFonts_.end()) | ||||||
|    { |    { | ||||||
|       return it->second; |       return it->second; | ||||||
|  | @ -301,25 +308,20 @@ FontManager::LoadImGuiFont(const std::string&               family, | ||||||
|    try |    try | ||||||
|    { |    { | ||||||
|       fontName = fmt::format( |       fontName = fmt::format( | ||||||
|          "{}:{}", |          "{}", std::filesystem::path(fontRecord.filename_).filename().string()); | ||||||
|          std::filesystem::path(fontRecord.filename_).filename().string(), |  | ||||||
|          imFontSize.value()); |  | ||||||
|    } |    } | ||||||
|    catch (const std::exception& ex) |    catch (const std::exception& ex) | ||||||
|    { |    { | ||||||
|       logger_->warn(ex.what()); |       logger_->warn(ex.what()); | ||||||
|       fontName = fmt::format("{}:{}", fontRecord.filename_, imFontSize.value()); |       fontName = fmt::format("{}", fontRecord.filename_); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // Create an ImGui font
 |    // Create an ImGui font
 | ||||||
|    std::shared_ptr<types::ImGuiFont> imguiFont = |    std::shared_ptr<types::ImGuiFont> imguiFont = | ||||||
|       std::make_shared<types::ImGuiFont>(fontName, rawFontData, imFontSize); |       std::make_shared<types::ImGuiFont>(fontName, rawFontData); | ||||||
| 
 | 
 | ||||||
|    // Store the ImGui font
 |    // Store the ImGui font
 | ||||||
|    p->imguiFonts_.insert_or_assign(imguiFontKey, imguiFont); |    p->imguiFonts_.insert_or_assign(fontRecord, imguiFont); | ||||||
| 
 |  | ||||||
|    // Increment ImGui font build count
 |  | ||||||
|    ++p->imguiFontsBuildCount_; |  | ||||||
| 
 | 
 | ||||||
|    // Return the ImGui font
 |    // Return the ImGui font
 | ||||||
|    return imguiFont; |    return imguiFont; | ||||||
|  | @ -456,6 +458,13 @@ void FontManager::Impl::FinalizeFontconfig() | ||||||
|    FcFini(); |    FcFini(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool FontManager::Impl::CheckFontFormat(const FcChar8* format) | ||||||
|  | { | ||||||
|  |    const std::string stdFormat = reinterpret_cast<const char*>(format); | ||||||
|  | 
 | ||||||
|  |    return stdFormat == kFcTrueType_ || stdFormat == kFcOpenType_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| FontRecord | FontRecord | ||||||
| FontManager::Impl::MatchFontFile(const std::string&              family, | FontManager::Impl::MatchFontFile(const std::string&              family, | ||||||
|                                  const std::vector<std::string>& styles) |                                  const std::vector<std::string>& styles) | ||||||
|  | @ -468,9 +477,7 @@ FontManager::Impl::MatchFontFile(const std::string&              family, | ||||||
| 
 | 
 | ||||||
|    FcPatternAddString( |    FcPatternAddString( | ||||||
|       pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(family.c_str())); |       pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(family.c_str())); | ||||||
|    FcPatternAddString(pattern, |    FcPatternAddBool(pattern, FC_SYMBOL, FcFalse); | ||||||
|                       FC_FONTFORMAT, |  | ||||||
|                       reinterpret_cast<const FcChar8*>(kFcTrueType_.c_str())); |  | ||||||
| 
 | 
 | ||||||
|    if (!styles.empty()) |    if (!styles.empty()) | ||||||
|    { |    { | ||||||
|  | @ -484,29 +491,55 @@ FontManager::Impl::MatchFontFile(const std::string&              family, | ||||||
|    FcDefaultSubstitute(pattern); |    FcDefaultSubstitute(pattern); | ||||||
| 
 | 
 | ||||||
|    // Find matching font
 |    // Find matching font
 | ||||||
|    FcResult   result; |    FcResult   result {}; | ||||||
|    FcPattern* match = FcFontMatch(nullptr, pattern, &result); |    FcFontSet* matches = FcFontSort(nullptr, pattern, FcFalse, nullptr, &result); | ||||||
|    FontRecord record {}; |    FontRecord record {}; | ||||||
| 
 | 
 | ||||||
|    if (match != nullptr) |    if (matches != nullptr) | ||||||
|    { |    { | ||||||
|       FcChar8* fcFamily; |       for (int i = 0; i < matches->nfont; i++) | ||||||
|       FcChar8* fcStyle; |       { | ||||||
|       FcChar8* fcFile; |          FcPattern* match = | ||||||
|  |             // Using C code requires pointer arithmetic
 | ||||||
|  |             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
 | ||||||
|  |             FcFontRenderPrepare(nullptr, pattern, matches->fonts[i]); | ||||||
|  |          if (match == nullptr) | ||||||
|  |          { | ||||||
|  |             continue; | ||||||
|  |          } | ||||||
|  |          FcChar8* fcFamily = nullptr; | ||||||
|  |          FcChar8* fcStyle  = nullptr; | ||||||
|  |          FcChar8* fcFile   = nullptr; | ||||||
|  |          FcChar8* fcFormat = nullptr; | ||||||
|  |          FcBool   fcSymbol = FcFalse; | ||||||
| 
 | 
 | ||||||
|          // Match was found, get properties
 |          // Match was found, get properties
 | ||||||
|       if (FcPatternGetString(match, FC_FAMILY, 0, &fcFamily) == FcResultMatch && |          if (FcPatternGetString(match, FC_FAMILY, 0, &fcFamily) == | ||||||
|           FcPatternGetString(match, FC_STYLE, 0, &fcStyle) == FcResultMatch && |                 FcResultMatch && | ||||||
|           FcPatternGetString(match, FC_FILE, 0, &fcFile) == FcResultMatch) |              FcPatternGetString(match, FC_STYLE, 0, &fcStyle) == | ||||||
|  |                 FcResultMatch && | ||||||
|  |              FcPatternGetString(match, FC_FILE, 0, &fcFile) == FcResultMatch && | ||||||
|  |              FcPatternGetBool(match, FC_SYMBOL, 0, &fcSymbol) == | ||||||
|  |                 FcResultMatch && | ||||||
|  |              FcPatternGetString(match, FC_FONTFORMAT, 0, &fcFormat) == | ||||||
|  |                 FcResultMatch && | ||||||
|  |              fcSymbol == FcFalse /*Must check fcSymbol manually*/ && | ||||||
|  |              CheckFontFormat(fcFormat)) | ||||||
|          { |          { | ||||||
|             record.family_   = reinterpret_cast<char*>(fcFamily); |             record.family_   = reinterpret_cast<char*>(fcFamily); | ||||||
|             record.style_    = reinterpret_cast<char*>(fcStyle); |             record.style_    = reinterpret_cast<char*>(fcStyle); | ||||||
|             record.filename_ = reinterpret_cast<char*>(fcFile); |             record.filename_ = reinterpret_cast<char*>(fcFile); | ||||||
| 
 | 
 | ||||||
|          logger_->debug("Found matching font: {}:{} ({})", |             logger_->debug("Found matching font: {}:{} ({}) {}", | ||||||
|                            record.family_, |                            record.family_, | ||||||
|                            record.style_, |                            record.style_, | ||||||
|                         record.filename_); |                            record.filename_, | ||||||
|  |                            fcSymbol); | ||||||
|  |             FcPatternDestroy(match); | ||||||
|  |             break; | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|  |          FcPatternDestroy(match); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  | @ -516,7 +549,7 @@ FontManager::Impl::MatchFontFile(const std::string&              family, | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // Cleanup
 |    // Cleanup
 | ||||||
|    FcPatternDestroy(match); |    FcFontSetDestroy(matches); | ||||||
|    FcPatternDestroy(pattern); |    FcPatternDestroy(pattern); | ||||||
| 
 | 
 | ||||||
|    return record; |    return record; | ||||||
|  | @ -528,13 +561,12 @@ FontManager& FontManager::Instance() | ||||||
|    return instance_; |    return instance_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| size_t FontRecordHash<FontRecordPair>::operator()(const FontRecordPair& x) const | size_t FontRecordHash<FontRecord>::operator()(const FontRecord& x) const | ||||||
| { | { | ||||||
|    size_t seed = 0; |    size_t seed = 0; | ||||||
|    boost::hash_combine(seed, x.first.family_); |    boost::hash_combine(seed, x.family_); | ||||||
|    boost::hash_combine(seed, x.first.style_); |    boost::hash_combine(seed, x.style_); | ||||||
|    boost::hash_combine(seed, x.first.filename_); |    boost::hash_combine(seed, x.filename_); | ||||||
|    boost::hash_combine(seed, x.second.value()); |  | ||||||
|    return seed; |    return seed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -545,6 +577,4 @@ bool operator==(const FontRecord& lhs, const FontRecord& rhs) | ||||||
|           lhs.filename_ == rhs.filename_; |           lhs.filename_ == rhs.filename_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace manager
 | } // namespace scwx::qt::manager
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -26,21 +26,22 @@ public: | ||||||
|    ~FontManager(); |    ~FontManager(); | ||||||
| 
 | 
 | ||||||
|    std::shared_mutex& imgui_font_atlas_mutex(); |    std::shared_mutex& imgui_font_atlas_mutex(); | ||||||
|    std::uint64_t      imgui_fonts_build_count() const; |  | ||||||
| 
 | 
 | ||||||
|    int GetFontId(types::Font font) const; |    int GetFontId(types::Font font) const; | ||||||
|    std::shared_ptr<types::ImGuiFont> |    std::pair<std::shared_ptr<types::ImGuiFont>, units::font_size::pixels<float>> | ||||||
|          GetImGuiFont(types::FontCategory fontCategory); |          GetImGuiFont(types::FontCategory fontCategory); | ||||||
|    QFont GetQFont(types::FontCategory fontCategory); |    QFont GetQFont(types::FontCategory fontCategory); | ||||||
|    std::shared_ptr<types::ImGuiFont> |    std::shared_ptr<types::ImGuiFont> | ||||||
|    LoadImGuiFont(const std::string&              family, |    LoadImGuiFont(const std::string&              family, | ||||||
|                  const std::vector<std::string>& styles, |                  const std::vector<std::string>& styles, | ||||||
|                  units::font_size::points<double> size, |  | ||||||
|                  bool                            loadIfNotFound = true); |                  bool                            loadIfNotFound = true); | ||||||
| 
 | 
 | ||||||
|    void LoadApplicationFont(types::Font font, const std::string& filename); |    void LoadApplicationFont(types::Font font, const std::string& filename); | ||||||
|    void InitializeFonts(); |    void InitializeFonts(); | ||||||
| 
 | 
 | ||||||
|  |    static units::font_size::pixels<float> | ||||||
|  |    ImFontSize(units::font_size::pixels<double> size); | ||||||
|  | 
 | ||||||
|    static FontManager& Instance(); |    static FontManager& Instance(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |  | ||||||
|  | @ -1,12 +1,14 @@ | ||||||
| #include <scwx/qt/manager/log_manager.hpp> | #include <scwx/qt/manager/log_manager.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
|  | #include <cstdlib> | ||||||
|  | #include <ctime> | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| #include <map> | #include <map> | ||||||
| #include <ranges> | #include <ranges> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| 
 | 
 | ||||||
| #include <boost/process/environment.hpp> | #include <boost/process/v1/environment.hpp> | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
| #include <spdlog/spdlog.h> | #include <spdlog/spdlog.h> | ||||||
| #include <QStandardPaths> | #include <QStandardPaths> | ||||||
|  | @ -57,6 +59,14 @@ void LogManager::InitializeLogFile() | ||||||
|       QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) |       QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) | ||||||
|          .toStdString(); |          .toStdString(); | ||||||
|    p->pid_     = boost::this_process::get_id(); |    p->pid_     = boost::this_process::get_id(); | ||||||
|  |    if (p->pid_ == 2) | ||||||
|  |    { | ||||||
|  |       // The pid == 2 means that this is likely a flatpak. We assign a random
 | ||||||
|  |       // number in this case to avoid overlap, scince it is always 2 in a
 | ||||||
|  |       // flatpak
 | ||||||
|  |       std::srand(std::time({})); | ||||||
|  |       p->pid_ = std::rand(); | ||||||
|  |    } | ||||||
|    p->logFile_ = fmt::format("{}/supercell-wx.{}.log", p->logPath_, p->pid_); |    p->logFile_ = fmt::format("{}/supercell-wx.{}.log", p->logPath_, p->pid_); | ||||||
| 
 | 
 | ||||||
|    // Create log directory if it doesn't exist
 |    // Create log directory if it doesn't exist
 | ||||||
|  |  | ||||||