mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
Compare commits
571
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
131d22c82a | ||
|
|
b848823a2f | ||
|
|
04b0f5bb75 | ||
|
|
fdbba84a5b | ||
|
|
079ad97987 | ||
|
|
7ae276fe6a | ||
|
|
45ddc8ac44 | ||
|
|
6fa422c5e7 | ||
|
|
35c830062d | ||
|
|
243a5bb473 | ||
|
|
09abbe1789 | ||
|
|
ad52278a67 | ||
|
|
e0a9c88241 | ||
|
|
f45dcfc09a | ||
|
|
2036ebd3a0 | ||
|
|
469270d4b6 | ||
|
|
e59df5d83c | ||
|
|
880e03e5d1 | ||
|
|
c1196f8286 | ||
|
|
40cd9e4c07 | ||
|
|
a90e480b61 | ||
|
|
142ae846f4 | ||
|
|
7a827dcb0e | ||
|
|
619cb607d0 | ||
|
|
56c34eee6d | ||
|
|
379031534d | ||
|
|
64b08f51c0 | ||
|
|
adfa12a706 | ||
|
|
d71a589b0f | ||
|
|
5118d94d5d | ||
|
|
17179d5b0b | ||
|
|
bd3632d1bf | ||
|
|
eeed22b91a | ||
|
|
48873185ce | ||
|
|
e28ebc2a6c | ||
|
|
dcac9e7223 | ||
|
|
0b4ca71eba | ||
|
|
24c3c439d5 | ||
|
|
706973cb6b | ||
|
|
91a5bfa74a | ||
|
|
2721c452c4 | ||
|
|
1030e29ef7 | ||
|
|
8f06e338a4 | ||
|
|
d1a6b48beb | ||
|
|
ce8fc0a373 | ||
|
|
991f131376 | ||
|
|
ed7917cb26 | ||
|
|
e6e6288423 | ||
|
|
48a6361586 | ||
|
|
8a2faa8b99 | ||
|
|
7d139f9e80 | ||
|
|
cf93aa43c5 | ||
|
|
89e3533106 | ||
|
|
a3f9febdc4 | ||
|
|
3c738312de | ||
|
|
363d6d3ba0 | ||
|
|
5578825bf3 | ||
|
|
9b5710e8c3 | ||
|
|
b527dd5449 | ||
|
|
175668e2bb | ||
|
|
cbf3052094 | ||
|
|
3507cf96d1 | ||
|
|
e624f6c1a8 | ||
|
|
371aad8f8c | ||
|
|
cb3fd31db4 | ||
|
|
e2e7eac0c6 | ||
|
|
80faaf88b0 | ||
|
|
fb0f7dd7de | ||
|
|
62aae9d793 | ||
|
|
15663a3551 | ||
|
|
6df837e7f3 | ||
|
|
512d08e443 | ||
|
|
504abeb305 | ||
|
|
2ae2f2910c | ||
|
|
3b4fbde8e6 | ||
|
|
2d01cd2366 | ||
|
|
2beb136ecf | ||
|
|
c728cc40b2 | ||
|
|
d13ddb387f | ||
|
|
666c177dec | ||
|
|
d5ba2369a2 | ||
|
|
7bf7a8fc66 | ||
|
|
a3d2320f0a | ||
|
|
9d352ddc5f | ||
|
|
299e584284 | ||
|
|
4f22b12ec6 | ||
|
|
57985b5f1a | ||
|
|
513115ceeb | ||
|
|
95acebfce8 | ||
|
|
ca5605cfb4 | ||
|
|
ea4e5f222d | ||
|
|
538afc73a2 | ||
|
|
16560326e7 | ||
|
|
68372b18a2 | ||
|
|
c6abe74f06 | ||
|
|
f1c79c2ca7 | ||
|
|
7944eda1cb | ||
|
|
1571caa95e | ||
|
|
9f97ea909a | ||
|
|
7469558e97 | ||
|
|
6747c630af | ||
|
|
d80d8dd08e | ||
|
|
5ebf806c72 | ||
|
|
6d2d092cc6 | ||
|
|
cafee9c66a | ||
|
|
8fc281c7be | ||
|
|
8cae09bfe8 | ||
|
|
5c5e48847e | ||
|
|
ae17e3f4b7 | ||
|
|
ebfc904e52 | ||
|
|
f3a3ed982f | ||
|
|
fabf05454b | ||
|
|
d309644e53 | ||
|
|
63b21893df | ||
|
|
81f4c03364 | ||
|
|
3668ce67d5 | ||
|
|
28ddf7d8d2 | ||
|
|
b2d427fb00 | ||
|
|
3a4d5788a8 | ||
|
|
7e3ca7eb46 | ||
|
|
95620e5de6 | ||
|
|
ae738abcf5 | ||
|
|
e3c815c194 | ||
|
|
daca57de4c | ||
|
|
5650199b04 | ||
|
|
b1e392be2f | ||
|
|
9f0e21f941 | ||
|
|
5258066545 | ||
|
|
f740583547 | ||
|
|
fd92813198 | ||
|
|
fc87b129ac | ||
|
|
d5509411de | ||
|
|
a1d7ec7855 | ||
|
|
7d3bc7fc58 | ||
|
|
6ed82d88a9 | ||
|
|
8b49ebf323 | ||
|
|
4bcc85e963 | ||
|
|
55c1c3ce9d | ||
|
|
2bddcf8344 | ||
|
|
235391154e | ||
|
|
1c5bf39e8d | ||
|
|
0b3ff5e698 | ||
|
|
5c0e88dd60 | ||
|
|
1498367e48 | ||
|
|
a8747b7b93 | ||
|
|
dadf58f6b1 | ||
|
|
e9a642673c | ||
|
|
42fbc92d73 | ||
|
|
6141fc7f73 | ||
|
|
c1fd6e7026 | ||
|
|
9114d94e0c | ||
|
|
235234ea66 | ||
|
|
512887482a | ||
|
|
04fd9679bd | ||
|
|
07a2f5a155 | ||
|
|
85874105e3 | ||
|
|
248b70b780 | ||
|
|
f05a50f57b | ||
|
|
a5fc5e322d | ||
|
|
91c4884fd3 | ||
|
|
eaad5a01a2 | ||
|
|
905417b866 | ||
|
|
5061a112db | ||
|
|
b7981c0ce4 | ||
|
|
c0328bb4f5 | ||
|
|
dd2074d91d | ||
|
|
e7a8adb367 | ||
|
|
809ac2300d | ||
|
|
8ea179781a | ||
|
|
77768b3328 | ||
|
|
873162690d | ||
|
|
5c5ce5e66a | ||
|
|
7d54dd9a05 | ||
|
|
eb322476b2 | ||
|
|
aadb22c9f1 | ||
|
|
d4b0dc9cc2 | ||
|
|
b7e703553b | ||
|
|
6b97dcfe60 | ||
|
|
8099bb737b | ||
|
|
91d6d90c9b | ||
|
|
e5e5d14108 | ||
|
|
4fa43ed639 | ||
|
|
1ace8b3abc | ||
|
|
520e532c56 | ||
|
|
9a9e088861 | ||
|
|
39f24bce23 | ||
|
|
3dd9bc8aef | ||
|
|
03aa479efc | ||
|
|
31931777bc | ||
|
|
59d0c561d6 | ||
|
|
ca55f4ea9c | ||
|
|
8c223afcd0 | ||
|
|
4dc8c57d3c | ||
|
|
82f74d570b | ||
|
|
8df4835d51 | ||
|
|
5a5dbd0df2 | ||
|
|
cc876f8bc3 | ||
|
|
45d09fd49b | ||
|
|
6fcdabeb45 | ||
|
|
2e632467f4 | ||
|
|
5c599fa9ee | ||
|
|
6b654ce38a | ||
|
|
2cba774a33 | ||
|
|
32fec00e97 | ||
|
|
66c9baf893 | ||
|
|
1c04be91bb | ||
|
|
6d52cab0a4 | ||
|
|
aa60a639fb | ||
|
|
dfd9fe7610 | ||
|
|
ef0c6b5c78 | ||
|
|
a3f493d8c1 | ||
|
|
b6981875a5 | ||
|
|
7c1147541d | ||
|
|
be9a881cb5 | ||
|
|
8f2aec3b9a | ||
|
|
78abbf89e6 | ||
|
|
4de3451d6c | ||
|
|
8f5f77fa42 | ||
|
|
354246caf4 | ||
|
|
4797b29311 | ||
|
|
2e0253e301 | ||
|
|
0d188fe076 | ||
|
|
c463709399 | ||
|
|
25357ce8a2 | ||
|
|
9953c6a7c4 | ||
|
|
1db36b7ba5 | ||
|
|
77b6648d22 | ||
|
|
09ca5d3dd6 | ||
|
|
942f72d09a | ||
|
|
ee27db60de | ||
|
|
66c0d27270 | ||
|
|
206364a113 | ||
|
|
ac9547d610 | ||
|
|
6534c0a3f6 | ||
|
|
cdeeee688d | ||
|
|
8b5f257d0d | ||
|
|
b2652e0628 | ||
|
|
2eea0a6eb1 | ||
|
|
67c67548fd | ||
|
|
12e45e88fa | ||
|
|
e2129355bf | ||
|
|
857582a980 | ||
|
|
c4dd593dd7 | ||
|
|
30404d4b04 | ||
|
|
c8e3e01ca0 | ||
|
|
16ed58f403 | ||
|
|
5ac2571efa | ||
|
|
7dfa5b5739 | ||
|
|
0178374b98 | ||
|
|
738e4a8153 | ||
|
|
1a4181fb67 | ||
|
|
85c2b3a7f0 | ||
|
|
508b8a176b | ||
|
|
ca313ae17f | ||
|
|
87bb2cbcc7 | ||
|
|
9e673ff7fe | ||
|
|
126b6718db | ||
|
|
b0fc182fab | ||
|
|
158292afba | ||
|
|
e334c1f736 | ||
|
|
f6fa053d94 | ||
|
|
4e24fba7fa | ||
|
|
0ea638f520 | ||
|
|
d75ec93484 | ||
|
|
468a9f280a | ||
|
|
69f4fa60f5 | ||
|
|
95ed536225 | ||
|
|
96d3eebad9 | ||
|
|
3b21b2469f | ||
|
|
cbe1d20fcc | ||
|
|
3d3bbb5dc4 | ||
|
|
4c5b1c679b | ||
|
|
65941e2e84 | ||
|
|
538adf1bf6 | ||
|
|
a6d8b6b5fa | ||
|
|
7fb5f08530 | ||
|
|
ffad093153 | ||
|
|
6a73d8f9d0 | ||
|
|
a0a88128ef | ||
|
|
6fad19c8bc | ||
|
|
119b5d662b | ||
|
|
0b612c2f1a | ||
|
|
8aee62b818 | ||
|
|
1314b8634a | ||
|
|
b557985e90 | ||
|
|
4f43a2edf3 | ||
|
|
6083c89b45 | ||
|
|
eefba9159a | ||
|
|
8fed2fcfe3 | ||
|
|
d149dd18b5 | ||
|
|
a7d624f82d | ||
|
|
aaab3fa03b | ||
|
|
0d51cb0d14 | ||
|
|
1c56d9f497 | ||
|
|
dfc8cd1168 | ||
|
|
ccaa766474 | ||
|
|
741c28d785 | ||
|
|
d73a21a579 | ||
|
|
5b8f4343a3 | ||
|
|
310785a961 | ||
|
|
9029aad64d | ||
|
|
acc018507b | ||
|
|
25698b4534 | ||
|
|
a2f6897c43 | ||
|
|
0777f24f08 | ||
|
|
ed45baa843 | ||
|
|
13ff2ec907 | ||
|
|
e795327a3f | ||
|
|
3c238d61e2 | ||
|
|
2d3e7e54e8 | ||
|
|
8ba05c1c3d | ||
|
|
277962974c | ||
|
|
eab5b8b40a | ||
|
|
842554e237 | ||
|
|
563dc35dea | ||
|
|
3fc6958f88 | ||
|
|
a886a1659c | ||
|
|
99f69c903e | ||
|
|
830fd70f9e | ||
|
|
c4ff34970f | ||
|
|
f216b8bf7f | ||
|
|
0ec2c7fef0 | ||
|
|
1f70fb2bf2 | ||
|
|
304a6a3a0d | ||
|
|
ec6bea233b | ||
|
|
9e495d7f94 | ||
|
|
0344fd6e35 | ||
|
|
b8b7d41786 | ||
|
|
3410822d9d | ||
|
|
aea63832ed | ||
|
|
1ee1886a9a | ||
|
|
c0a8ceb48f | ||
|
|
6bdbbd5c40 | ||
|
|
c66839a9bf | ||
|
|
40ba3162dc | ||
|
|
e81547ae88 | ||
|
|
7577018bd3 | ||
|
|
2181512949 | ||
|
|
dff5e4c21d | ||
|
|
d7ea260607 | ||
|
|
7f7ed74bd6 | ||
|
|
0df6c22216 | ||
|
|
e8ab065bde | ||
|
|
f79b83c60b | ||
|
|
3ab6e43254 | ||
|
|
abbef793fc | ||
|
|
bd85f61971 | ||
|
|
47967cb72a | ||
|
|
7f56037369 | ||
|
|
659828c213 | ||
|
|
2c4884595e | ||
|
|
1621bd169b | ||
|
|
c496a08ab1 | ||
|
|
012e37afb9 | ||
|
|
4fc1183622 | ||
|
|
1eaa67bb5b | ||
|
|
bf74f29634 | ||
|
|
6159e13162 | ||
|
|
1bd09a91d3 | ||
|
|
8cf0e8eb1d | ||
|
|
2dcb75057c | ||
|
|
d95f173f26 | ||
|
|
47b21f6792 | ||
|
|
5ec8896c4a | ||
|
|
560b49158b | ||
|
|
c109dc6aca | ||
|
|
581e5b0242 | ||
|
|
ace3fc619e | ||
|
|
7d418d50ce | ||
|
|
ebd24341d4 | ||
|
|
e8c80dbefc | ||
|
|
68e19a19c5 | ||
|
|
f780d9e22a | ||
|
|
c5117cf55e | ||
|
|
f9704ebd89 | ||
|
|
5f7721f300 | ||
|
|
3c0eec27de | ||
|
|
4648721674 | ||
|
|
ae4a7319e5 | ||
|
|
3c7f7f9df0 | ||
|
|
e11250f7e8 | ||
|
|
24dec72f41 | ||
|
|
89c36b68c7 | ||
|
|
e66d9d1246 | ||
|
|
789135516e | ||
|
|
91b61d446f | ||
|
|
8e5aafb6e5 | ||
|
|
cb0080bfc1 | ||
|
|
a03180c46e | ||
|
|
a18fdd2112 | ||
|
|
7c81ac1d86 | ||
|
|
bc7414c403 | ||
|
|
a7418d6dde | ||
|
|
f83c2e9cdc | ||
|
|
965a327630 | ||
|
|
c9bb3f4caa | ||
|
|
3e1b020bf5 | ||
|
|
60d6aaccec | ||
|
|
18a957e8bf | ||
|
|
ad7bddfd41 | ||
|
|
a90d859891 | ||
|
|
9b1e9600ce | ||
|
|
07a806e01f | ||
|
|
ccd33eb50f | ||
|
|
1805c77f7c | ||
|
|
481ebec316 | ||
|
|
99d8b19ee8 | ||
|
|
5adc3216df | ||
|
|
55f39e088d | ||
|
|
71b572b7f4 | ||
|
|
c1908669d9 | ||
|
|
a9d25fd18d | ||
|
|
72c5d17739 | ||
|
|
ecf10d8227 | ||
|
|
8ab448dd70 | ||
|
|
ea53cff723 | ||
|
|
407888641c | ||
|
|
ac554f24c2 | ||
|
|
56670b2ed7 | ||
|
|
7e26955853 | ||
|
|
c085eef9a0 | ||
|
|
8061125d84 | ||
|
|
93b1c0df17 | ||
|
|
41f889e55d | ||
|
|
7d92178777 | ||
|
|
ac69bd5712 | ||
|
|
d6b6ea715a | ||
|
|
8c59b06b59 | ||
|
|
e59d31d66e | ||
|
|
19c01563ca | ||
|
|
80f1f50582 | ||
|
|
a057e111ba | ||
|
|
b45998b58d | ||
|
|
472a3f09f7 | ||
|
|
d6c4ff374c | ||
|
|
b14c12befa | ||
|
|
2d7606740a | ||
|
|
1712a42807 | ||
|
|
f811d7591f | ||
|
|
7e9f0c8e6f | ||
|
|
255814dd4f | ||
|
|
e076aa6990 | ||
|
|
16d48fbf1b | ||
|
|
937de9355b | ||
|
|
947b25e2cc | ||
|
|
e6f92f316a | ||
|
|
f65de9bb43 | ||
|
|
956e908b6e | ||
|
|
0442c1c6ac | ||
|
|
1a3b14316d | ||
|
|
350e8a2cf5 | ||
|
|
4cd9993640 | ||
|
|
41137fedbd | ||
|
|
52901e7351 | ||
|
|
8236a7d7f8 | ||
|
|
70e63dcf6c | ||
|
|
557ff6be1d | ||
|
|
95896e6ec7 | ||
|
|
e6acd9a313 | ||
|
|
c1cb978687 | ||
|
|
51698af1b0 | ||
|
|
9d3659cf88 | ||
|
|
3eddce06dd | ||
|
|
9c75a2178c | ||
|
|
d26253c5f8 | ||
|
|
6b5cac174a | ||
|
|
1f39915a5e | ||
|
|
d60306288b | ||
|
|
305e71e290 | ||
|
|
befe668c8b | ||
|
|
25e87fb8a0 | ||
|
|
9a11f232f6 | ||
|
|
49a37ccf91 | ||
|
|
ee8d03b4cf | ||
|
|
16b80faaaf | ||
|
|
0f7810fdb4 | ||
|
|
f85dfbb048 | ||
|
|
96ed407dd7 | ||
|
|
cd7cf82430 | ||
|
|
cff16f7b0b | ||
|
|
1a08bfa3e7 | ||
|
|
dbc52e2aa7 | ||
|
|
b1725bae76 | ||
|
|
4b10c61a5f | ||
|
|
c18220048d | ||
|
|
08b8c1d768 | ||
|
|
0f6a61894a | ||
|
|
3345aee144 | ||
|
|
207d3e6eba | ||
|
|
8be0a19a98 | ||
|
|
b517a47f81 | ||
|
|
4afd5d9d1c | ||
|
|
7eaff0e63f | ||
|
|
755df8c38b | ||
|
|
8357964e53 | ||
|
|
e10b431735 | ||
|
|
be5d7cc2cd | ||
|
|
2e016ccffb | ||
|
|
4305649a64 | ||
|
|
27c971a92b | ||
|
|
1e1c8c7cb8 | ||
|
|
94bb727ebe | ||
|
|
884259fc14 | ||
|
|
0b6a3115a7 | ||
|
|
ec6a786654 | ||
|
|
a3744d8818 | ||
|
|
5dc0c0d98d | ||
|
|
ad6551cf38 | ||
|
|
1cdc0840be | ||
|
|
e7f619d65e | ||
|
|
3ddc93fd9d | ||
|
|
6b32bdb732 | ||
|
|
cabc6f6412 | ||
|
|
164e20ef96 | ||
|
|
d18b97014e | ||
|
|
abdf713944 | ||
|
|
24a3369e9d | ||
|
|
cb94183629 | ||
|
|
7ecfa209ca | ||
|
|
22105d1e3e | ||
|
|
588659a367 | ||
|
|
423d14c24a | ||
|
|
2f44c3242f | ||
|
|
1167a4edcb | ||
|
|
862010b4e0 | ||
|
|
95dff1dacf | ||
|
|
bc38232f3a | ||
|
|
a29708ea89 | ||
|
|
baeb9ac78b | ||
|
|
211b9c9d71 | ||
|
|
4c05a103fa | ||
|
|
540e52ffbc | ||
|
|
0fc55babaf | ||
|
|
4ce085cd49 | ||
|
|
3edb4575d3 | ||
|
|
26af516704 | ||
|
|
668dccf925 | ||
|
|
acdf88fdeb | ||
|
|
577c49eedb | ||
|
|
9cd3d80b81 | ||
|
|
e8316662b8 | ||
|
|
6a82c1eee7 | ||
|
|
a309cb51b1 | ||
|
|
af60cefbd5 | ||
|
|
8e2b1f354a | ||
|
|
1d3ee16198 | ||
|
|
cb7f2a5dfd | ||
|
|
18a621764c | ||
|
|
22c7e31c8a | ||
|
|
00ff9e8751 | ||
|
|
ba26f6e221 | ||
|
|
ed01e155f6 | ||
|
|
cd110bb2c1 | ||
|
|
2c30dbcda6 | ||
|
|
160d49fa82 | ||
|
|
431ad4144f | ||
|
|
2555d11427 | ||
|
|
e1882fc314 | ||
|
|
2804b5d9d3 | ||
|
|
2bbe201130 | ||
|
|
bbbc08fa87 | ||
|
|
a8def1e1b3 | ||
|
|
987a442dd6 | ||
|
|
09d39da97c | ||
|
|
0a2e6f581b | ||
|
|
98cde8f21f | ||
|
|
9d22d75ba8 | ||
|
|
df095e6bdf | ||
|
|
243f7f7ce8 | ||
|
|
32b6696162 | ||
|
|
ac8befa4e6 |
No files matched your search
+22
@@ -0,0 +1,22 @@
|
||||
---
|
||||
Checks: "-*,\
|
||||
modernize-*,\
|
||||
-modernize-raw-string-literal,\
|
||||
-modernize-use-using,\
|
||||
performance-*,\
|
||||
-performance-type-promotion-in-math-fn,\
|
||||
misc-*,\
|
||||
-misc-macro-parentheses,\
|
||||
-misc-misplaced-widening-cast,\
|
||||
-misc-static-assert,\
|
||||
"
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
|
||||
AnalyzeTemporaryDtors: false
|
||||
CheckOptions:
|
||||
- key: 'misc-assert-side-effect.AssertMacros'
|
||||
value: 'assert,Assert,Assertion'
|
||||
- key: 'modernize-use-emplace.ContainersWithPushBack'
|
||||
value: 'std::vector;std::deque;std::list;SCP_vector;SCP_deque;SCP_list'
|
||||
...
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
|
||||
build:
|
||||
image: teaci/msys$$arch
|
||||
pull: true
|
||||
shell: mingw$$arch
|
||||
commands:
|
||||
- git submodule update --init --recursive
|
||||
- if [ $$arch = 32 ]; then target=i686; fi
|
||||
- if [ $$arch = 64 ]; then target=x86_64; fi
|
||||
- pacman -S --needed --noconfirm --noprogressbar mingw-w64-${target}-pkg-config mingw-w64-${target}-cmake
|
||||
- mkdir build && cd build
|
||||
- cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=$$CONFIGURATION -DFSO_USE_SPEECH=OFF -DFSO_USE_VOICEREC=OFF -DFSO_FATAL_WARNINGS=ON -DFSO_BUILD_FRED2=OFF ..
|
||||
- make -j$(nproc) all
|
||||
|
||||
matrix:
|
||||
arch:
|
||||
- 64
|
||||
- 32
|
||||
CONFIGURATION:
|
||||
- Debug
|
||||
- Release
|
||||
@@ -256,3 +256,7 @@ CMakeSettings.json
|
||||
|
||||
# Weird files created by Linux
|
||||
.fuse_hidden*
|
||||
|
||||
# This gets ignored by one of the rules above for some reason...
|
||||
!/code/scripting/lua/LuaConvert.h
|
||||
!/code/debugconsole/
|
||||
+45
-12
@@ -3,7 +3,8 @@ sudo: required
|
||||
dist: trusty
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/cmake
|
||||
- $HOME/cmake-3.8
|
||||
- $HOME/.ccache
|
||||
addons:
|
||||
apt:
|
||||
packages: &global_deps
|
||||
@@ -16,6 +17,7 @@ addons:
|
||||
- libjansson-dev
|
||||
- libsdl2-dev
|
||||
- valgrind
|
||||
- qt57base
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "scp-fs2open/fs2open.github.com"
|
||||
@@ -69,19 +71,36 @@ matrix:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-5
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=clang-3.6 CXX=clang++-3.6
|
||||
env: CONFIGURATION="Debug" CC=gcc-7 CXX=g++-7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- clang-3.6
|
||||
- libc++-dev
|
||||
- g++-7
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- clang-tidy-4.0
|
||||
- libc++-dev
|
||||
script:
|
||||
- ./ci/travis/script.sh
|
||||
- ./ci/travis/clang_tidy.sh
|
||||
- os: osx
|
||||
env: CONFIGURATION="Debug"
|
||||
|
||||
@@ -91,19 +110,32 @@ matrix:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-5
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=clang-3.6 CXX=clang++-3.6
|
||||
env: CONFIGURATION="Release" CC=gcc-7 CXX=g++-7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- clang-3.6
|
||||
- libc++-dev
|
||||
- g++-7
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- libc++-dev
|
||||
- os: osx
|
||||
env: CONFIGURATION="Release"
|
||||
before_install:
|
||||
@@ -117,8 +149,9 @@ before_install:
|
||||
- "./ci/travis/before_install.sh"
|
||||
install:
|
||||
- "./ci/travis/install.sh"
|
||||
- export PATH=$HOME/cmake/bin:$PATH
|
||||
- export PATH=$HOME/cmake-3.6/bin:$PATH
|
||||
before_script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi
|
||||
- "./ci/travis/before_script.sh"
|
||||
script:
|
||||
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
|
||||
+19
-6
@@ -40,6 +40,14 @@ set(CMAKE_CONFIGURATION_TYPES Debug Release FastDebug CACHE STRING "Available co
|
||||
|
||||
PROJECT(FS2_Open)
|
||||
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
# Currently only GCC support ccache properly without generating additional warnings
|
||||
if(CCACHE_PROGRAM AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
message(STATUS "Using ccache for compilation: ${CCACHE_PROGRAM}")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_PROGRAM}")
|
||||
endif()
|
||||
|
||||
IF(CMAKE_CROSSCOMPILING)
|
||||
SET(IMPORT_EXE_DIR "IMPORT_EXE_DIR-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to binary directory of a cmake build for the real OS")
|
||||
INCLUDE(${IMPORT_EXE_DIR}/ImportExecutables.cmake)
|
||||
@@ -85,7 +93,7 @@ OPTION(FSO_BUILD_TESTS "Build unit tests" OFF)
|
||||
|
||||
OPTION(FSO_DEVELOPMENT_MODE "Generate binaries in development mode, only use if you know what you're doing!" OFF)
|
||||
|
||||
OPTION(FSO_BUILD_WXFRED2 "Build wxFRED2 binary" OFF)
|
||||
OPTION(FSO_BUILD_QTFRED "Build qtFRED2 binary" OFF)
|
||||
|
||||
IF(WIN32 OR APPLE)
|
||||
# On windows and mac the default should be to always build the included libraries
|
||||
@@ -108,6 +116,8 @@ SET(FSO_RUN_ARGUMENTS "" CACHE STRING "Additional arguments passed to a generate
|
||||
|
||||
option(FSO_INSTALL_DEBUG_FILES "Install some debug files (currently only PDB files on windows)" OFF)
|
||||
|
||||
option(ENABLE_COTIRE "Enable cotire for faster compilation. Enabled by default." ON)
|
||||
|
||||
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
|
||||
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
|
||||
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
|
||||
@@ -115,6 +125,7 @@ MARK_AS_ADVANCED(FORCE FSO_USE_LUAJIT)
|
||||
MARK_AS_ADVANCED(FORCE FSO_DEVELOPMENT_MODE)
|
||||
MARK_AS_ADVANCED(FORCE FSO_FATAL_WARNINGS)
|
||||
mark_as_advanced(FORCE FSO_INSTALL_DEBUG_FILES)
|
||||
mark_as_advanced(FORCE ENABLE_COTIRE)
|
||||
|
||||
# Include cotire file from https://github.com/sakra/cotire/
|
||||
include(cotire)
|
||||
@@ -134,6 +145,8 @@ if(FSO_BUILD_APPIMAGE)
|
||||
include(appimage)
|
||||
endif()
|
||||
|
||||
include(clang-tidy)
|
||||
|
||||
# This includes source code for some tools, either used in the build or also for something else
|
||||
ADD_SUBDIRECTORY(tools)
|
||||
|
||||
@@ -147,9 +160,9 @@ IF(FSO_BUILD_FRED2)
|
||||
ADD_SUBDIRECTORY(fred2)
|
||||
ENDIF(FSO_BUILD_FRED2)
|
||||
|
||||
IF(FSO_BUILD_WXFRED2)
|
||||
ADD_SUBDIRECTORY(wxfred2)
|
||||
ENDIF(FSO_BUILD_WXFRED2)
|
||||
IF(FSO_BUILD_QTFRED)
|
||||
ADD_SUBDIRECTORY(qtfred)
|
||||
ENDIF()
|
||||
|
||||
if(FSO_BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
@@ -176,12 +189,12 @@ include(doxygen)
|
||||
|
||||
# Print used options to log
|
||||
IF (WIN32)
|
||||
message(STATUS "Building FRED2: ${FSO_BUILD_FRED2}")
|
||||
message(STATUS "Using text to speech: ${FSO_USE_SPEECH}")
|
||||
message(STATUS "Using voice recogition: ${FSO_USE_VOICEREC}")
|
||||
message(STATUS "Building FRED2: ${FSO_BUILD_FRED2}")
|
||||
elseif(UNIX)
|
||||
message(STATUS "Building AppImage: ${FSO_BUILD_APPIMAGE}")
|
||||
ENDIF()
|
||||
message(STATUS "Building FSO tools: ${FSO_BUILD_TOOLS}")
|
||||
message(STATUS "Building wxFRED: ${FSO_BUILD_WXFRED2}")
|
||||
message(STATUS "Building qtFRED: ${FSO_BUILD_QTFRED}")
|
||||
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
|
||||
+5
-2
@@ -1,4 +1,5 @@
|
||||
version: 1.0.0.{build}
|
||||
image: Visual Studio 2015
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
@@ -6,11 +7,13 @@ clone_depth: 10
|
||||
environment:
|
||||
matrix:
|
||||
- BuildID: 0
|
||||
CMAKE_GENERATOR: Visual Studio 12 2013
|
||||
PlatformToolset: v120_xp
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
PlatformToolset: v140_xp
|
||||
QT_DIR: C:\Qt\5.9.5\msvc2015
|
||||
- BuildID: 1
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
|
||||
PlatformToolset: v140_xp
|
||||
QT_DIR: C:\Qt\5.9.5\msvc2015_64
|
||||
before_build:
|
||||
- git submodule update --init --recursive
|
||||
build_script:
|
||||
|
||||
@@ -4,6 +4,7 @@ class BuildConfig {
|
||||
[string]$PackageType
|
||||
[string]$Toolset
|
||||
[string]$SimdType
|
||||
[string]$QtDir
|
||||
[Bool]$SourcePackage
|
||||
}
|
||||
|
||||
@@ -13,6 +14,7 @@ $NightlyConfigurations = @(
|
||||
PackageType="Win64";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
},
|
||||
[BuildConfig]@{
|
||||
@@ -20,6 +22,7 @@ $NightlyConfigurations = @(
|
||||
PackageType="Win32";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
)
|
||||
@@ -29,6 +32,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win32";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015";
|
||||
SourcePackage=$true;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
@@ -36,6 +40,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win32-AVX";
|
||||
Toolset="v140_xp";
|
||||
SimdType="AVX";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
@@ -43,6 +48,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win64";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
@@ -50,6 +56,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win64-AVX";
|
||||
Toolset="v140_xp";
|
||||
SimdType="AVX";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
)
|
||||
@@ -141,6 +148,7 @@ if ($DeployBuild) {
|
||||
Push-AppveyorArtifact "$($PackageName)-builds-$($buildConfig.PackageType).zip"
|
||||
} else {
|
||||
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="ON" -DFSO_BUILD_TESTS="ON" -DMSVC_SIMD_INSTRUCTIONS=SSE2 `
|
||||
-DFSO_BUILD_QTFRED=ON -DQT5_INSTALL_ROOT="$env:QT_DIR" -DFSO_BUILD_FRED2="ON" `
|
||||
-G "$Env:CMAKE_GENERATOR" -T "$Env:PlatformToolset" ..
|
||||
|
||||
cmake --build . --config "$Env:CONFIGURATION" -- /verbosity:minimal
|
||||
|
||||
@@ -20,7 +20,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
|
||||
export CXXFLAGS
|
||||
export CFLAGS
|
||||
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON"
|
||||
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
|
||||
if [ "$BUILD_DEPLOYMENT" = true ]; then
|
||||
for config in $BUILD_CONFIGS
|
||||
do
|
||||
@@ -32,12 +32,12 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
cd ..
|
||||
done
|
||||
else
|
||||
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON ..
|
||||
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=ON ..
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
if [ "$BUILD_DEPLOYMENT" = true ]; then
|
||||
cmake -G "Xcode" -DFSO_FATAL_WARNINGS=ON -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_INSTALL_PREFIX="/tmp/release" ..
|
||||
else
|
||||
cmake -G "Xcode" ..
|
||||
cmake -G "Xcode" $CMAKE_OPTIONS ..
|
||||
fi
|
||||
fi
|
||||
@@ -49,7 +49,7 @@ if ([ "$RELEASE_BUILD" = true ] || [ "$NIGHTLY_BUILD" = true ] || [ "$TEST_BUILD
|
||||
fi
|
||||
|
||||
if [ "$BUILD_DEPLOYMENT" = true ]; then
|
||||
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc.*$ ]])); then
|
||||
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc-5.*$ ]])); then
|
||||
echo "Skipping non-release compiler";
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
Executable
+141
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
r"""
|
||||
ClangTidy Diff Checker
|
||||
======================
|
||||
|
||||
This script reads input from a unified diff, runs clang-tidy on all changed
|
||||
files and outputs clang-tidy warnings in changed lines only. This is useful to
|
||||
detect clang-tidy regressions in the lines touched by a specific patch.
|
||||
Example usage for git/svn users:
|
||||
|
||||
git diff -U0 HEAD^ | clang-tidy-diff.py -p1
|
||||
svn diff --diff-cmd=diff -x-U0 | \
|
||||
clang-tidy-diff.py -fix -checks=-*,modernize-use-override
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=
|
||||
'Run clang-tidy against changed files, and '
|
||||
'output diagnostics only for modified '
|
||||
'lines.')
|
||||
parser.add_argument('-clang-tidy-binary', metavar='PATH',
|
||||
default='clang-tidy',
|
||||
help='path to clang-tidy binary')
|
||||
parser.add_argument('-p', metavar='NUM', default=0,
|
||||
help='strip the smallest prefix containing P slashes')
|
||||
parser.add_argument('-regex', metavar='PATTERN', default=None,
|
||||
help='custom pattern selecting file paths to check '
|
||||
'(case sensitive, overrides -iregex)')
|
||||
parser.add_argument('-iregex', metavar='PATTERN', default=
|
||||
r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)',
|
||||
help='custom pattern selecting file paths to check '
|
||||
'(case insensitive, overridden by -regex)')
|
||||
|
||||
parser.add_argument('-fix', action='store_true', default=False,
|
||||
help='apply suggested fixes')
|
||||
parser.add_argument('-checks',
|
||||
help='checks filter, when not specified, use clang-tidy '
|
||||
'default',
|
||||
default='')
|
||||
parser.add_argument('-path', dest='build_path',
|
||||
help='Path used to read a compile command database.')
|
||||
parser.add_argument('-extra-arg', dest='extra_arg',
|
||||
action='append', default=[],
|
||||
help='Additional argument to append to the compiler '
|
||||
'command line.')
|
||||
parser.add_argument('-extra-arg-before', dest='extra_arg_before',
|
||||
action='append', default=[],
|
||||
help='Additional argument to prepend to the compiler '
|
||||
'command line.')
|
||||
parser.add_argument('-quiet', action='store_true', default=False,
|
||||
help='Run clang-tidy in quiet mode')
|
||||
clang_tidy_args = []
|
||||
argv = sys.argv[1:]
|
||||
if '--' in argv:
|
||||
clang_tidy_args.extend(argv[argv.index('--'):])
|
||||
argv = argv[:argv.index('--')]
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
# Extract changed lines for each file.
|
||||
filename = None
|
||||
lines_by_file = {}
|
||||
for line in sys.stdin:
|
||||
match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line)
|
||||
if match:
|
||||
filename = match.group(2)
|
||||
if filename == None:
|
||||
continue
|
||||
|
||||
if args.regex is not None:
|
||||
if not re.match('^%s$' % args.regex, filename):
|
||||
continue
|
||||
else:
|
||||
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
|
||||
continue
|
||||
|
||||
match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
|
||||
if match:
|
||||
start_line = int(match.group(1))
|
||||
line_count = 1
|
||||
if match.group(3):
|
||||
line_count = int(match.group(3))
|
||||
if line_count == 0:
|
||||
continue
|
||||
end_line = start_line + line_count - 1;
|
||||
lines_by_file.setdefault(filename, []).append([start_line, end_line])
|
||||
|
||||
if len(lines_by_file) == 0:
|
||||
print("No relevant changes found.")
|
||||
sys.exit(0)
|
||||
|
||||
line_filter_json = json.dumps(
|
||||
[{"name" : name, "lines" : lines_by_file[name]} for name in lines_by_file],
|
||||
separators = (',', ':'))
|
||||
|
||||
quote = "";
|
||||
if sys.platform == 'win32':
|
||||
line_filter_json=re.sub(r'"', r'"""', line_filter_json)
|
||||
else:
|
||||
quote = "'";
|
||||
|
||||
# Run clang-tidy on files containing changes.
|
||||
command = [args.clang_tidy_binary]
|
||||
command.append('-line-filter=' + quote + line_filter_json + quote)
|
||||
if args.fix:
|
||||
command.append('-fix')
|
||||
if args.checks != '':
|
||||
command.append('-checks=' + quote + args.checks + quote)
|
||||
if args.quiet:
|
||||
command.append('-quiet')
|
||||
if args.build_path is not None:
|
||||
command.append('-p=%s' % args.build_path)
|
||||
command.extend(lines_by_file.keys())
|
||||
for arg in args.extra_arg:
|
||||
command.append('-extra-arg=%s' % arg)
|
||||
for arg in args.extra_arg_before:
|
||||
command.append('-extra-arg-before=%s' % arg)
|
||||
command.extend(clang_tidy_args)
|
||||
|
||||
sys.exit(subprocess.call(' '.join(command), shell=True))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if ! git rev-list $TRAVIS_COMMIT_RANGE 2>1 >/dev/null; then
|
||||
echo "\$TRAVIS_COMMIT_RANGE ($TRAVIS_COMMIT_RANGE) is not valid for this build (probably caused by a rebase)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$TRAVIS_BUILD_DIR"
|
||||
|
||||
echo "Running clang-tidy on changed files"
|
||||
git diff -U0 --no-color $TRAVIS_COMMIT_RANGE | \
|
||||
$TRAVIS_BUILD_DIR/ci/travis/clang-tidy-diff.py -path "$TRAVIS_BUILD_DIR/build" -p1 \
|
||||
-regex 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$|tools/.*' \
|
||||
-clang-tidy-binary /usr/bin/clang-tidy-4.0 2>/dev/null | \
|
||||
tee clang-tidy-output.txt
|
||||
|
||||
if [[ -n $(grep "warning: " clang-tidy-output.txt) ]] || [[ -n $(grep "error: " clang-tidy-output.txt) ]]; then
|
||||
echo "Errors or warnings were detected in the clang-tidy output!"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\033[1;32m\xE2\x9C\x93 passed:\033[0m clang-tidy test succeeded";
|
||||
fi
|
||||
@@ -4,16 +4,14 @@ set -ex
|
||||
|
||||
FILENAME=
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ ! -d "$HOME/cmake/bin" ]; then
|
||||
if [ ! -d "$HOME/cmake-3.8/bin" ]; then
|
||||
# If the cache does not currently contain CMake then download and install it
|
||||
FILENAME=cmake-3.4.3-Linux-x86_64
|
||||
mkdir -p $HOME/cmake-3.8/
|
||||
|
||||
mkdir -p $HOME/cmake/
|
||||
|
||||
wget -O /tmp/cmake.tar.gz --no-check-certificate https://www.cmake.org/files/v3.4/$FILENAME.tar.gz
|
||||
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake/ --strip-components=1
|
||||
wget -O /tmp/cmake.tar.gz --no-check-certificate https://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz
|
||||
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake-3.8/ --strip-components=1
|
||||
fi
|
||||
export PATH=$HOME/cmake/bin:$PATH
|
||||
export PATH=$HOME/cmake-3.8/bin:$PATH
|
||||
|
||||
cd $HOME
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ set -e
|
||||
cd build
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
ninja all
|
||||
ninja -k 20 all
|
||||
|
||||
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
|
||||
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
option(ENABLE_CLANG_TIDY "Enable source code checking using clang-tidy" OFF)
|
||||
|
||||
find_program(
|
||||
CLANG_TIDY_EXE
|
||||
NAMES "clang-tidy"
|
||||
DOC "Path to clang-tidy executable"
|
||||
)
|
||||
|
||||
function(enable_clang_tidy target)
|
||||
# Not enabled in this configuration
|
||||
endfunction()
|
||||
|
||||
if(NOT ENABLE_CLANG_TIDY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CLANG_TIDY_EXE}")
|
||||
message(SEND_ERROR "clang-tidy: Could not find clang-tidy executable (value of variable is \"${CLANG_TIDY_EXE}\".")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.6.0")
|
||||
message(SEND_ERROR "Clang-tidy support requires CMake 3.6")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "clang-tidy: Using \"${CLANG_TIDY_EXE}\"")
|
||||
|
||||
function(enable_clang_tidy target)
|
||||
SET(TIDY_OPTIONS "${CLANG_TIDY_EXE}")
|
||||
if(FSO_FATAL_WARNINGS)
|
||||
set(TIDY_OPTIONS "${TIDY_OPTIONS};-warnings-as-errors=*")
|
||||
endif()
|
||||
|
||||
set_target_properties(${target} PROPERTIES CXX_CLANG_TIDY "${TIDY_OPTIONS}")
|
||||
endfunction()
|
||||
|
||||
@@ -41,5 +41,8 @@ CHECK_FUNCTION_EXISTS(strlwr HAVE_STRLWR)
|
||||
|
||||
CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
|
||||
|
||||
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
|
||||
check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF)
|
||||
|
||||
set(PLATFORM_CHECK_HEADER "${GENERATED_SOURCE_DIR}/platformChecks.h")
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/platformChecks.h.in "${PLATFORM_CHECK_HEADER}")
|
||||
@@ -25,4 +25,7 @@
|
||||
#cmakedefine01 HAVE_CHAR32_T
|
||||
#cmakedefine01 HAVE_UNICODE_CHAR_LITERAL
|
||||
|
||||
#cmakedefine01 HAVE_SNPRINTF
|
||||
#cmakedefine01 HAVE__SNPRINTF
|
||||
|
||||
#endif // __PLATFORM_CHECKS_H__
|
||||
@@ -73,14 +73,12 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-char-subscripts")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
|
||||
|
||||
check_cxx_compiler_flag(-Wshift-negative-value SUPPORTS_SHIFT_NEGATIVE_VALUE)
|
||||
if(SUPPORTS_SHIFT_NEGATIVE_VALUE)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-shift-negative-value")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable")
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
|
||||
|
||||
|
||||
@@ -85,9 +85,7 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered")
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
|
||||
|
||||
@@ -105,6 +103,7 @@ set(CMAKE_EXE_LINKER_FLAGS "")
|
||||
|
||||
IF (MINGW)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
|
||||
target_compile_definitions(compiler INTERFACE __USE_MINGW_ANSI_STDIO=1)
|
||||
ENDIF(MINGW)
|
||||
|
||||
if (SANITIZE_FLAGS)
|
||||
@@ -131,4 +130,4 @@ if (FSO_FATAL_WARNINGS)
|
||||
endif()
|
||||
|
||||
# Always define this to make sure that the fixed width format macros are available
|
||||
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
|
||||
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS=1)
|
||||
+34
-4
@@ -10,7 +10,7 @@ FUNCTION(ADD_IMPORTED_LIB NAME INCLUDES LIBS)
|
||||
|
||||
target_link_libraries(${NAME} INTERFACE "${LIBS}")
|
||||
|
||||
target_include_directories(${NAME} INTERFACE "${INCLUDES}")
|
||||
target_include_directories(${NAME} SYSTEM INTERFACE "${INCLUDES}")
|
||||
ENDFUNCTION(ADD_IMPORTED_LIB)
|
||||
|
||||
MACRO(PKG_CONFIG_LIB_RESOLVE NAME OUTVAR)
|
||||
@@ -141,10 +141,12 @@ macro(set_if_not_defined VAR VALUE)
|
||||
endmacro(set_if_not_defined)
|
||||
|
||||
macro(configure_cotire target)
|
||||
# Disable unity build as it doesn't work well for us
|
||||
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
|
||||
if(ENABLE_COTIRE)
|
||||
# Disable unity build as it doesn't work well for us
|
||||
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
|
||||
|
||||
cotire(${target})
|
||||
cotire(${target})
|
||||
endif()
|
||||
endmacro(configure_cotire)
|
||||
|
||||
macro(add_target_copy_files)
|
||||
@@ -195,3 +197,31 @@ function(suppress_warnings _target)
|
||||
target_compile_options(${_target} PRIVATE "-w")
|
||||
endif()
|
||||
endfunction(suppress_warnings)
|
||||
|
||||
|
||||
function(list_target_dependencies _target _out_var)
|
||||
set(out_list)
|
||||
set(work_libs ${_target})
|
||||
list(LENGTH work_libs libs_length)
|
||||
|
||||
while(libs_length GREATER 0)
|
||||
list(GET work_libs 0 current)
|
||||
list(REMOVE_AT work_libs 0)
|
||||
list(APPEND out_list ${current})
|
||||
|
||||
get_target_property(current_libs ${current} INTERFACE_LINK_LIBRARIES)
|
||||
|
||||
if(current_libs)
|
||||
foreach(lib ${current_libs})
|
||||
if (TARGET ${lib})
|
||||
list(APPEND work_libs ${lib})
|
||||
endif (TARGET ${lib})
|
||||
endforeach(lib)
|
||||
endif(current_libs)
|
||||
|
||||
list(LENGTH work_libs libs_length)
|
||||
endwhile(libs_length GREATER 0)
|
||||
|
||||
list(REMOVE_DUPLICATES out_list)
|
||||
set(${_out_var} ${out_list} PARENT_SCOPE)
|
||||
endfunction(list_target_dependencies)
|
||||
+17
-1
@@ -37,6 +37,8 @@ TARGET_LINK_LIBRARIES(code PUBLIC compiler)
|
||||
|
||||
target_link_libraries(code PUBLIC md5)
|
||||
|
||||
enable_clang_tidy(code)
|
||||
|
||||
IF (FSO_USE_SPEECH)
|
||||
find_package(Speech REQUIRED)
|
||||
target_link_libraries(code PUBLIC speech)
|
||||
@@ -55,7 +57,21 @@ IF(FSO_BUILD_TOOLS)
|
||||
ADD_SUBDIRECTORY(cfileextractor)
|
||||
ENDIF(FSO_BUILD_TOOLS)
|
||||
|
||||
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "prefix_header.h")
|
||||
if (ENABLE_COTIRE)
|
||||
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h")
|
||||
else()
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/FI ${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
ELSE()
|
||||
MESSAGE("Unknown compiler for global includes. This will probably break the build.")
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
include(util)
|
||||
configure_cotire(code)
|
||||
|
||||
@@ -498,7 +498,8 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
}
|
||||
|
||||
// find next valid option
|
||||
skip_to_start_of_string_either("$", "#");
|
||||
if (!skip_to_start_of_string_either("$", "#"))
|
||||
break;
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -714,7 +714,7 @@ extern void maybe_cheat_fire_synaptic(object *objp, ai_info *aip);
|
||||
// dist_to_enemy => distance (in m) to attack point on current target
|
||||
// dot_to_enemy => dot product between fvec of Pl_objp and vector from Pl_objp to attack point
|
||||
//
|
||||
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *firing_pos, vec3d *enemy_pos, vec3d *enemy_vel)
|
||||
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d * /*firing_pos*/, vec3d * /*enemy_pos*/, vec3d * /*enemy_vel*/)
|
||||
{
|
||||
ai_info *aip;
|
||||
ship_weapon *swp;
|
||||
@@ -1153,7 +1153,7 @@ void ai_big_chase()
|
||||
}
|
||||
}
|
||||
|
||||
void ai_big_ship(object *objp)
|
||||
void ai_big_ship(object * /*objp*/)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
@@ -1228,7 +1228,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
|
||||
|
||||
// check to see if Pl_objp has gotten too close to attacking point.. if so, break off by entering
|
||||
// AIS_STRAFE_RETREAT
|
||||
int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
|
||||
int ai_big_strafe_maybe_retreat(float /*dist*/, vec3d *target_pos)
|
||||
{
|
||||
ai_info *aip;
|
||||
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
|
||||
@@ -1704,7 +1704,7 @@ void ai_big_strafe()
|
||||
//
|
||||
// Check if weapon_objnum was fired by Pl_objp's target, and whether Pl_objp's target is a big ship, if
|
||||
// so, enter AIM_STRAFE
|
||||
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int consider_target_only)
|
||||
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int /*consider_target_only*/)
|
||||
{
|
||||
ai_info *aip;
|
||||
ship_info *sip;
|
||||
|
||||
+20
-20
@@ -68,7 +68,7 @@
|
||||
#include "weapon/swarm.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include <map>
|
||||
#include <limits.h>
|
||||
#include <climits>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -1132,7 +1132,7 @@ void ai_update_danger_weapon(int attacked_objnum, int weapon_objnum)
|
||||
|
||||
// If rvec != NULL, use it to match bank by calling vm_matrix_interpolate.
|
||||
// (rvec defaults to NULL)
|
||||
void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
|
||||
void ai_turn_towards_vector(vec3d *dest, object *objp, float /*frametime*/, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
|
||||
{
|
||||
matrix curr_orient;
|
||||
vec3d vel_in, vel_out, desired_fvec, src;
|
||||
@@ -3453,7 +3453,7 @@ float compute_time_to_enemy(float dist_to_enemy, object *pobjp)
|
||||
// incorrect, not having been divided by distance.
|
||||
// If *dot is > 0.0f, then tts is computed. This is the time it will take object
|
||||
// *objp to get to *pos, assuming it moves right at it.
|
||||
void fds_aux(float *dot, float *tts, vec3d *pos, float dtime, object *objp)
|
||||
void fds_aux(float *dot, float *tts, vec3d *pos, float /*dtime*/, object *objp)
|
||||
{
|
||||
vec3d v2s;
|
||||
|
||||
@@ -5234,7 +5234,7 @@ vec3d G_predicted_pos, G_fire_pos;
|
||||
// Else
|
||||
// Select Any ol' weapon.
|
||||
// Returns primary_bank index.
|
||||
int ai_select_primary_weapon_OLD(object *objp, object *other_objp, Weapon::Info_Flags flags)
|
||||
int ai_select_primary_weapon_OLD(object *objp, object * /*other_objp*/, Weapon::Info_Flags flags)
|
||||
{
|
||||
ship *shipp = &Ships[objp->instance];
|
||||
ship_weapon *swp = &shipp->weapons;
|
||||
@@ -6052,7 +6052,7 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip)
|
||||
// Fire a secondary weapon.
|
||||
// Maybe choose to fire a different one.
|
||||
// priority1 and priority2 are optional parameters with defaults = -1
|
||||
int ai_fire_secondary_weapon(object *objp, int priority1, int priority2)
|
||||
int ai_fire_secondary_weapon(object *objp, int /*priority1*/, int /*priority2*/)
|
||||
{
|
||||
ship_weapon *swp;
|
||||
ship *shipp;
|
||||
@@ -6546,7 +6546,7 @@ void ai_chase_ct()
|
||||
/**
|
||||
* ATTACK submode handler for chase mode.
|
||||
*/
|
||||
void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float dist_to_enemy)
|
||||
void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float /*dist_to_enemy*/)
|
||||
{
|
||||
vec3d _pep;
|
||||
float dot_to_enemy, dot_from_enemy;
|
||||
@@ -6755,7 +6755,7 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d
|
||||
|
||||
// Pl_objp (aip) tries to get behind En_objp.
|
||||
// New on 2/21/98: If this ship can move backwards and slide, maybe do that to get behind.
|
||||
void get_behind_ship(ai_info *aip, ship_info *sip, float dist_to_enemy)
|
||||
void get_behind_ship(ai_info *aip, ship_info *sip, float /*dist_to_enemy*/)
|
||||
{
|
||||
vec3d new_pos;
|
||||
float dot;
|
||||
@@ -10839,7 +10839,7 @@ void ai_dock()
|
||||
|
||||
if (aip->submode == AIS_DOCK_3) {
|
||||
// Play a ship docking attach sound
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DOCK_ATTACH), &Pl_objp->pos, &View_position );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DOCK_ATTACH), &Pl_objp->pos, &View_position );
|
||||
|
||||
// start the dock animation
|
||||
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKED, docker_index, 1);
|
||||
@@ -10966,7 +10966,7 @@ void ai_dock()
|
||||
ai_find_path(Pl_objp, OBJ_INDEX(goal_objp), path_num, 0);
|
||||
|
||||
// Play a ship docking detach sound
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DOCK_DETACH), &Pl_objp->pos, &View_position );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DOCK_DETACH), &Pl_objp->pos, &View_position );
|
||||
|
||||
aip->submode = AIS_UNDOCK_1;
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -10986,7 +10986,7 @@ void ai_dock()
|
||||
// play the depart sound, but only once, since this mode is called multiple times per frame
|
||||
if ( !(aigp->flags[AI::Goal_Flags::Depart_sound_played]))
|
||||
{
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DOCK_DEPART), &Pl_objp->pos, &View_position );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DOCK_DEPART), &Pl_objp->pos, &View_position );
|
||||
aigp->flags.set(AI::Goal_Flags::Depart_sound_played);
|
||||
}
|
||||
|
||||
@@ -11385,7 +11385,7 @@ float gwlr_1(object *objp, ai_info *aip)
|
||||
/**
|
||||
* Compute the largest radius of a ship forming on *objp's wing.
|
||||
*/
|
||||
float gwlr_object_1(object *objp, ai_info *aip)
|
||||
float gwlr_object_1(object *objp, ai_info * /*aip*/)
|
||||
{
|
||||
float max_radius;
|
||||
object *o;
|
||||
@@ -12191,7 +12191,7 @@ void ai_maybe_launch_cmeasure(object *objp, ai_info *aip)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
void ai_preprocess_ignore_objnum(object *objp, ai_info *aip)
|
||||
void ai_preprocess_ignore_objnum(object * /*objp*/, ai_info *aip)
|
||||
{
|
||||
if (aip->ai_flags[AI::AI_Flags::Temporary_ignore])
|
||||
{
|
||||
@@ -13024,7 +13024,7 @@ void ai_execute_behavior(ai_info *aip)
|
||||
ship *shipp = &Ships[aip->shipnum];
|
||||
ship_info *sip = &Ship_info[shipp->ship_info_index];
|
||||
|
||||
if (strnicmp(shipp->ship_name, INSTRUCTOR_SHIP_NAME, strlen(INSTRUCTOR_SHIP_NAME))) {
|
||||
if (strnicmp(shipp->ship_name, INSTRUCTOR_SHIP_NAME, strlen(INSTRUCTOR_SHIP_NAME)) != 0) {
|
||||
if (sip->is_big_or_huge()) {
|
||||
aip->mode = AIM_NONE;
|
||||
} else {
|
||||
@@ -13441,7 +13441,7 @@ void ai_warp_out(object *objp)
|
||||
|
||||
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
|
||||
// Return nearest one.
|
||||
int ai_find_shockwave_weapon(object *objp, ai_info *aip)
|
||||
int ai_find_shockwave_weapon(object *objp, ai_info * /*aip*/)
|
||||
{
|
||||
missile_obj *mo;
|
||||
float nearest_dist = 999999.9f;
|
||||
@@ -13507,7 +13507,7 @@ void ai_announce_ship_dying(object *dying_objp)
|
||||
|
||||
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
|
||||
// Return nearest one.
|
||||
int ai_find_shockwave_ship(object *objp, ai_info *aip)
|
||||
int ai_find_shockwave_ship(object *objp, ai_info * /*aip*/)
|
||||
{
|
||||
ship_obj *so;
|
||||
float nearest_dist = 999999.9f;
|
||||
@@ -14158,7 +14158,7 @@ void ai_frame(int objnum)
|
||||
}
|
||||
}
|
||||
|
||||
void ai_control_info_check( object *obj, ai_info *aip )
|
||||
void ai_control_info_check( object * /*obj*/, ai_info *aip )
|
||||
{
|
||||
if(aip->ai_override_flags.none_set())
|
||||
return;
|
||||
@@ -14797,7 +14797,7 @@ int firing_aspect_seeking_bomb(object *objp)
|
||||
// *objp collided with big ship *big_objp at global point *collide_pos
|
||||
// Make it fly away from the collision point.
|
||||
// collision_normal is NULL, when a collision is imminent and we just want to bug out.
|
||||
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal)
|
||||
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d * /*collide_pos*/, vec3d *collision_normal)
|
||||
{
|
||||
ai_info *aip;
|
||||
|
||||
@@ -14888,7 +14888,7 @@ void ai_update_lethality(object *pship_obj, object *other_obj, float damage)
|
||||
/**
|
||||
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp at point *hitpos.
|
||||
*/
|
||||
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal)
|
||||
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shield_quadrant*/, vec3d *hit_normal)
|
||||
{
|
||||
int hitter_objnum = -2;
|
||||
object *objp_hitter = NULL;
|
||||
@@ -15190,7 +15190,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_
|
||||
// the parameter 'method' is used to tell is this ship was destroyed or it departed normally.
|
||||
// This function will get called in either case, and there are things that should be done if
|
||||
// the ship actually gets destroyed which shouldn't get done if it departed.
|
||||
void ai_ship_destroy(int shipnum, Ship::Exit_Flags method)
|
||||
void ai_ship_destroy(int shipnum, Ship::Exit_Flags /*method*/)
|
||||
{
|
||||
int objnum;
|
||||
object *other_objp;
|
||||
@@ -15510,7 +15510,7 @@ int ai_return_path_num_from_dockbay(object *dockee_objp, int dockbay_index)
|
||||
/**
|
||||
* Actually go ahead and fire the synaptics.
|
||||
*/
|
||||
void cheat_fire_synaptic(object *objp, ship *shipp, ai_info *aip)
|
||||
void cheat_fire_synaptic(object *objp, ship *shipp, ai_info * /*aip*/)
|
||||
{
|
||||
ship_weapon *swp;
|
||||
swp = &shipp->weapons;
|
||||
|
||||
+3
-3
@@ -414,7 +414,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
|
||||
if ( purge_ai_mode == AI_GOAL_CHASE_SHIP_CLASS ) {
|
||||
// if the target of the purge goal is the same class of ship we are concerned about, then we have a match;
|
||||
// if it is not, then we can continue (see standard ship check below)
|
||||
if ( stricmp(purge_goal->target_name, Ship_info[Ships[ship_index].ship_info_index].name) )
|
||||
if ( stricmp(purge_goal->target_name, Ship_info[Ships[ship_index].ship_info_index].name) != 0 )
|
||||
continue;
|
||||
}
|
||||
// standard goals operating on either wings or ships
|
||||
@@ -426,7 +426,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
|
||||
// don't match, we can continue; if the wing is valid, don't process if the wing numbers
|
||||
// are different.
|
||||
if ( purge_wing == -1 ) {
|
||||
if ( stricmp(purge_goal->target_name, name ) )
|
||||
if ( stricmp(purge_goal->target_name, name ) != 0 )
|
||||
continue;
|
||||
} else if ( purge_wing != wingnum )
|
||||
continue;
|
||||
@@ -1263,7 +1263,7 @@ void ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
|
||||
// this name can be a shipname or a wingname)
|
||||
// docker_point and dockee_point are used for the AI_GOAL_DOCK command to tell two ships where to dock
|
||||
// immediate means to process this order right away
|
||||
void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate )
|
||||
void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*docker_point*/, int /*dockee_point*/, int immediate )
|
||||
{
|
||||
int gindex;
|
||||
ai_goal *aigp;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "weapon/swarm.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <climits>
|
||||
|
||||
|
||||
// How close a turret has to be point at its target before it
|
||||
@@ -243,7 +243,7 @@ int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
|
||||
* @note All non-negative return values are expressed in what I like to call "widx"s.
|
||||
* @return -1 if unable to find a weapon for the target at all.
|
||||
*/
|
||||
int turret_select_best_weapon(ship_subsys *turret, object *target)
|
||||
int turret_select_best_weapon(ship_subsys *turret, object * /*target*/)
|
||||
{
|
||||
//TODO: Fill this out with extraodinary gun-picking algorithms
|
||||
if(turret->weapons.num_primary_banks > 0)
|
||||
@@ -2048,7 +2048,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
|
||||
}
|
||||
}
|
||||
|
||||
if ( wip->launch_snd != -1 ) {
|
||||
if ( wip->launch_snd.isValid() ) {
|
||||
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
|
||||
if ( parent_objnum != OBJ_INDEX(Player_obj) || (turret->flags[Ship::Subsystem_Flags::Play_sound_for_player]) ) {
|
||||
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), turret_pos, &View_position );
|
||||
@@ -2135,7 +2135,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
|
||||
}
|
||||
|
||||
// maybe sound
|
||||
if ( Weapon_info[tsi->weapon_class].launch_snd != -1 ) {
|
||||
if ( Weapon_info[tsi->weapon_class].launch_snd.isValid() ) {
|
||||
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
|
||||
if ( tsi->parent_objnum != OBJ_INDEX(Player_obj) ) {
|
||||
snd_play_3d( gamesnd_get_game_sound(Weapon_info[tsi->weapon_class].launch_snd), &turret_pos, &View_position );
|
||||
|
||||
@@ -274,9 +274,9 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
percent_through = instance->time_elapsed / time;
|
||||
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD)
|
||||
new_frame_num = instance->start_at - 1 + fl2i(percent_through * n_frames + 0.5f);
|
||||
new_frame_num = instance->start_at - 1 + (int) lround(percent_through * n_frames);
|
||||
else
|
||||
new_frame_num = instance->start_at - 1 - fl2i(percent_through * n_frames + 0.5f);
|
||||
new_frame_num = instance->start_at - 1 - (int) lround(percent_through * n_frames);
|
||||
|
||||
frame_save = instance->frame_num;
|
||||
|
||||
|
||||
+39
-101
@@ -76,7 +76,7 @@ float Asteroid_icon_closeup_zoom;
|
||||
/**
|
||||
* Force updating of pair stuff for asteroid *objp.
|
||||
*/
|
||||
void asteroid_update_collide(object *objp)
|
||||
static void asteroid_update_collide(object *objp)
|
||||
{
|
||||
// Asteroid has wrapped, update collide objnum and flags
|
||||
Asteroids[objp->instance].collide_objnum = -1;
|
||||
@@ -87,7 +87,7 @@ void asteroid_update_collide(object *objp)
|
||||
/**
|
||||
* Clear out the ::Asteroid_obj_list
|
||||
*/
|
||||
void asteroid_obj_list_init()
|
||||
static void asteroid_obj_list_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -101,7 +101,7 @@ void asteroid_obj_list_init()
|
||||
* Add a node from the Asteroid_obj_list.
|
||||
* Only called from ::weapon_create()
|
||||
*/
|
||||
int asteroid_obj_list_add(int objnum)
|
||||
static int asteroid_obj_list_add(int objnum)
|
||||
{
|
||||
int index;
|
||||
|
||||
@@ -123,7 +123,7 @@ int asteroid_obj_list_add(int objnum)
|
||||
* Remove a node from the Asteroid_obj_list.
|
||||
* Only called from ::weapon_delete()
|
||||
*/
|
||||
void asteroid_obj_list_remove(object * obj)
|
||||
static void asteroid_obj_list_remove(object * obj)
|
||||
{
|
||||
int index = obj->instance;
|
||||
|
||||
@@ -138,7 +138,7 @@ void asteroid_obj_list_remove(object * obj)
|
||||
/**
|
||||
* Prevent speed from getting too huge so it's hard to catch up to an asteroid.
|
||||
*/
|
||||
float asteroid_cap_speed(int asteroid_info_index, float speed)
|
||||
static float asteroid_cap_speed(int asteroid_info_index, float speed)
|
||||
{
|
||||
float max, double_max;
|
||||
|
||||
@@ -164,7 +164,7 @@ float asteroid_cap_speed(int asteroid_info_index, float speed)
|
||||
* Sum together the following: 1 inside x, 2 inside y, 4 inside z
|
||||
* inside only when sum = 7
|
||||
*/
|
||||
int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, float delta)
|
||||
static int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, float delta)
|
||||
{
|
||||
Assert(asfieldp->has_inner_bound);
|
||||
|
||||
@@ -188,7 +188,7 @@ int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, floa
|
||||
* Check if asteroid is within inner bound
|
||||
* @return 0 if not inside or no inner bound, 1 if inside inner bound
|
||||
*/
|
||||
int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
|
||||
static int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
|
||||
|
||||
if (!asfieldp->has_inner_bound) {
|
||||
return 0;
|
||||
@@ -202,7 +202,7 @@ int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
|
||||
*
|
||||
* Moves to the other side of the inner box a distance delta from edge of box
|
||||
*/
|
||||
void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
|
||||
static void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
|
||||
{
|
||||
if (!asteroid_in_inner_bound(asfieldp, pos, 0)) {
|
||||
return;
|
||||
@@ -446,7 +446,7 @@ void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
|
||||
/**
|
||||
* Load in an asteroid model
|
||||
*/
|
||||
void asteroid_load(int asteroid_info_index, int asteroid_subtype)
|
||||
static void asteroid_load(int asteroid_info_index, int asteroid_subtype)
|
||||
{
|
||||
int i;
|
||||
asteroid_info *asip;
|
||||
@@ -487,26 +487,12 @@ void asteroid_load(int asteroid_info_index, int asteroid_subtype)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomly choose a debris model within the current group
|
||||
*/
|
||||
int get_debris_from_same_group(int index) {
|
||||
int group_base, group_offset;
|
||||
|
||||
group_base = (index / NUM_DEBRIS_SIZES) * NUM_DEBRIS_SIZES;
|
||||
group_offset = index - group_base;
|
||||
|
||||
// group base + offset
|
||||
// offset is formed by adding 1 or 2 (since 3 in model group) and mapping back in the 0-2 range
|
||||
return group_base + ((group_offset + rand()%(NUM_DEBRIS_SIZES-1) + 1) % NUM_DEBRIS_SIZES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a weight that depends on asteroid size.
|
||||
*
|
||||
* The weight is then used to determine the frequencty of different sizes of ship debris
|
||||
*/
|
||||
int get_debris_weight(int ship_debris_index)
|
||||
static int get_debris_weight(int ship_debris_index)
|
||||
{
|
||||
int size = ship_debris_index % NUM_DEBRIS_SIZES;
|
||||
switch (size)
|
||||
@@ -626,7 +612,7 @@ void asteroid_create_all()
|
||||
}
|
||||
|
||||
/**
|
||||
* Init asteriod system for the level, called from ::game_level_init()
|
||||
* Init asteroid system for the level, called from ::game_level_init()
|
||||
*/
|
||||
void asteroid_level_init()
|
||||
{
|
||||
@@ -645,7 +631,7 @@ void asteroid_level_init()
|
||||
*
|
||||
* @return !0 if asteroid should be wrapped, 0 otherwise.
|
||||
*/
|
||||
int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
|
||||
static int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
|
||||
{
|
||||
if ( MULTIPLAYER_CLIENT )
|
||||
return 0;
|
||||
@@ -690,7 +676,7 @@ int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
|
||||
/**
|
||||
* Wrap an asteroid from one end of the asteroid field to the other
|
||||
*/
|
||||
void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
|
||||
static void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
|
||||
{
|
||||
if (objp->pos.xyz.x < asfieldp->min_bound.xyz.x) {
|
||||
objp->pos.xyz.x = asfieldp->max_bound.xyz.x + (objp->pos.xyz.x - asfieldp->min_bound.xyz.x);
|
||||
@@ -727,7 +713,7 @@ void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
|
||||
*
|
||||
* @return !0 if this asteroid is a target for any ship, otherwise return 0
|
||||
*/
|
||||
int asteroid_is_targeted(object *objp)
|
||||
static int asteroid_is_targeted(object *objp)
|
||||
{
|
||||
ship_obj *so;
|
||||
object *ship_objp;
|
||||
@@ -748,7 +734,7 @@ int asteroid_is_targeted(object *objp)
|
||||
/**
|
||||
* Create an asteroid that will hit object *objp in delta_time seconds
|
||||
*/
|
||||
void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_time)
|
||||
static void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_time)
|
||||
{
|
||||
vec3d predicted_center_pos;
|
||||
vec3d rand_vec;
|
||||
@@ -776,7 +762,7 @@ void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_tim
|
||||
*
|
||||
* @param count asteroids already targeted on
|
||||
*/
|
||||
void maybe_throw_asteroid(int count)
|
||||
static void maybe_throw_asteroid(int count)
|
||||
{
|
||||
if (!timestamp_elapsed(Next_asteroid_throw)) {
|
||||
return;
|
||||
@@ -850,7 +836,7 @@ void asteroid_delete( object * obj )
|
||||
* See if we should reposition the asteroid.
|
||||
* Only reposition if oustide the bounding volume and the player isn't looking towards the asteroid.
|
||||
*/
|
||||
void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
|
||||
static void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
|
||||
{
|
||||
// passive field does not wrap
|
||||
if (asfieldp->field_type == FT_PASSIVE) {
|
||||
@@ -903,7 +889,7 @@ void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
|
||||
}
|
||||
}
|
||||
|
||||
void lerp(float *goal, float f1, float f2, float scale)
|
||||
static void lerp(float *goal, float f1, float f2, float scale)
|
||||
{
|
||||
*goal = (f2 - f1) * scale + f1;
|
||||
}
|
||||
@@ -1207,7 +1193,7 @@ void asteroid_render(object * obj, model_draw_list *scene)
|
||||
/**
|
||||
* Create a normalized vector generally in the direction from *hitpos to other_obj->pos
|
||||
*/
|
||||
void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
|
||||
static void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
|
||||
{
|
||||
vec3d tvec, rand_vec;
|
||||
int count = 0;
|
||||
@@ -1229,7 +1215,7 @@ void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
|
||||
/**
|
||||
* Return multiplier on asteroid radius for fireball
|
||||
*/
|
||||
float asteroid_get_fireball_scale_multiplier(int num)
|
||||
static float asteroid_get_fireball_scale_multiplier(int num)
|
||||
{
|
||||
if (Asteroids[num].flags & AF_USED) {
|
||||
asteroid_info *asip = &Asteroid_info[Asteroids[num].asteroid_type];
|
||||
@@ -1258,7 +1244,7 @@ float asteroid_get_fireball_scale_multiplier(int num)
|
||||
* Create asteroid explosion
|
||||
* @return expected time for explosion anim to last, in seconds
|
||||
*/
|
||||
float asteroid_create_explosion(object *objp)
|
||||
static float asteroid_create_explosion(object *objp)
|
||||
{
|
||||
int fireball_objnum;
|
||||
float explosion_life, fireball_scale_multiplier;
|
||||
@@ -1290,23 +1276,23 @@ float asteroid_create_explosion(object *objp)
|
||||
/**
|
||||
* Play sound when asteroid explodes
|
||||
*/
|
||||
void asteriod_explode_sound(object *objp, int type, int play_loud)
|
||||
static void asteroid_explode_sound(object *objp, int type, int play_loud)
|
||||
{
|
||||
int sound_index = -1;
|
||||
gamesnd_id sound_index;
|
||||
float range_factor = 1.0f; // how many times sound should traver farther than normal
|
||||
|
||||
if (type % NUM_DEBRIS_SIZES <= 1)
|
||||
{
|
||||
sound_index = SND_ASTEROID_EXPLODE_SMALL;
|
||||
sound_index = gamesnd_id(GameSounds::ASTEROID_EXPLODE_SMALL);
|
||||
range_factor = 5.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sound_index = SND_ASTEROID_EXPLODE_LARGE;
|
||||
sound_index = gamesnd_id(GameSounds::ASTEROID_EXPLODE_LARGE);
|
||||
range_factor = 10.0f;
|
||||
}
|
||||
|
||||
Assert(sound_index != -1);
|
||||
Assert(sound_index.isValid());
|
||||
|
||||
if ( !play_loud ) {
|
||||
range_factor = 1.0f;
|
||||
@@ -1318,9 +1304,9 @@ void asteriod_explode_sound(object *objp, int type, int play_loud)
|
||||
/**
|
||||
* Do the area effect for an asteroid exploding
|
||||
*
|
||||
* @param asteroid_objp object pointer to asteriod causing explosion
|
||||
* @param asteroid_objp object pointer to asteroid causing explosion
|
||||
*/
|
||||
void asteroid_do_area_effect(object *asteroid_objp)
|
||||
static void asteroid_do_area_effect(object *asteroid_objp)
|
||||
{
|
||||
object *ship_objp;
|
||||
float damage, blast;
|
||||
@@ -1382,7 +1368,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
|
||||
|
||||
explosion_life = asteroid_create_explosion(pasteroid_obj);
|
||||
|
||||
asteriod_explode_sound(pasteroid_obj, asp->asteroid_type, play_loud_collision);
|
||||
asteroid_explode_sound(pasteroid_obj, asp->asteroid_type, play_loud_collision);
|
||||
asteroid_do_area_effect(pasteroid_obj);
|
||||
|
||||
asp->final_death_time = timestamp( fl2i(explosion_life*1000.0f)/5 ); // Wait till 30% of vclip time before breaking the asteroid up.
|
||||
@@ -1432,35 +1418,6 @@ void asteroid_level_close()
|
||||
DCF_BOOL2(asteroids, Asteroids_enabled, "enables or disables asteroids", "Usage: asteroids [bool]\nTurns asteroid system on/off. If nothing passed, then toggles it.\n");
|
||||
|
||||
|
||||
void hud_target_asteroid()
|
||||
{
|
||||
int i;
|
||||
int start_index = 0, end_index = MAX_ASTEROIDS;
|
||||
|
||||
if (Player_ai->target_objnum != -1) {
|
||||
if (Objects[Player_ai->target_objnum].type == OBJ_ASTEROID) {
|
||||
start_index = Objects[Player_ai->target_objnum].instance+1;
|
||||
end_index = start_index-1;
|
||||
if (end_index < 0)
|
||||
end_index = MAX_ASTEROIDS;
|
||||
}
|
||||
}
|
||||
|
||||
i = start_index;
|
||||
while (i != end_index) {
|
||||
if (i == MAX_ASTEROIDS)
|
||||
i = 0;
|
||||
|
||||
if (Asteroids[i].flags & AF_USED) {
|
||||
Assert(Objects[Asteroids[i].objnum].type == OBJ_ASTEROID);
|
||||
set_target_objnum( Player_ai, Asteroids[i].objnum);
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of active asteroids
|
||||
*/
|
||||
@@ -1473,7 +1430,7 @@ int asteroid_count()
|
||||
* See if asteroid should split up.
|
||||
* We delay splitting up to allow the explosion animation to play for a bit.
|
||||
*/
|
||||
void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
static void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
{
|
||||
asteroid *asp;
|
||||
asteroid_info *asip;
|
||||
@@ -1595,26 +1552,7 @@ void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
}
|
||||
}
|
||||
|
||||
int asteroid_get_random_in_cone(vec3d *pos, vec3d *dir, float ang, int danger)
|
||||
{
|
||||
int idx;
|
||||
vec3d asteroid_dir;
|
||||
|
||||
// just pick the first asteroid which satisfies our condition
|
||||
for(idx=0; idx<Num_asteroids; idx++){
|
||||
vm_vec_sub(&asteroid_dir, &Objects[Asteroids[idx].objnum].pos, pos);
|
||||
vm_vec_normalize_quick(&asteroid_dir);
|
||||
|
||||
// if it satisfies the condition
|
||||
if(vm_vec_dot(dir, &asteroid_dir) >= ang){
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc, bool lazy = false)
|
||||
static void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc, bool lazy = false)
|
||||
{
|
||||
float asteroid_ray_dist;
|
||||
vec3d asteroid_fvec, terminus;
|
||||
@@ -1656,7 +1594,7 @@ void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc
|
||||
*
|
||||
* @return !0 if the asteroid will collide with the escort
|
||||
*/
|
||||
int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
|
||||
static int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
|
||||
{
|
||||
mc_info mc;
|
||||
mc_info_init(&mc);
|
||||
@@ -1674,7 +1612,7 @@ int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
|
||||
* Warn if asteroid on collision path with ship
|
||||
* @return !0 if we should warn about asteroid hitting ship, otherwise return 0
|
||||
*/
|
||||
int asteroid_valid_ship_to_warn_collide(ship *shipp)
|
||||
static int asteroid_valid_ship_to_warn_collide(ship *shipp)
|
||||
{
|
||||
if ( !(Ship_info[shipp->ship_info_index].is_big_or_huge()) ) {
|
||||
return 0;
|
||||
@@ -1696,7 +1634,7 @@ int asteroid_valid_ship_to_warn_collide(ship *shipp)
|
||||
* See if asteroid will collide with a large ship on the escort list in the next
|
||||
* ASTEROID_MIN_COLLIDE_TIME seconds.
|
||||
*/
|
||||
void asteroid_update_collide_flag(object *asteroid_objp)
|
||||
static void asteroid_update_collide_flag(object *asteroid_objp)
|
||||
{
|
||||
int i, num_escorts, escort_objnum, will_collide=0;
|
||||
ship *escort_shipp;
|
||||
@@ -1735,7 +1673,7 @@ void asteroid_update_collide_flag(object *asteroid_objp)
|
||||
/**
|
||||
* Ensure that the collide objnum for the asteroid is still valid
|
||||
*/
|
||||
void asteroid_verify_collide_objnum(asteroid *asp)
|
||||
static void asteroid_verify_collide_objnum(asteroid *asp)
|
||||
{
|
||||
if ( asp->collide_objnum >= 0 ) {
|
||||
if ( Objects[asp->collide_objnum].signature != asp->collide_objsig ) {
|
||||
@@ -1815,7 +1753,7 @@ float asteroid_time_to_impact(object *asteroid_objp)
|
||||
/**
|
||||
* Read in a single asteroid section from asteroid.tbl
|
||||
*/
|
||||
void asteroid_parse_section(asteroid_info *asip)
|
||||
static void asteroid_parse_section(asteroid_info *asip)
|
||||
{
|
||||
required_string("$Name:");
|
||||
stuff_string(asip->name, F_NAME, NAME_LENGTH);
|
||||
@@ -1915,7 +1853,7 @@ to do with the debris of ships that explode, however these
|
||||
are the same debris and asteroids that get flung at a ship
|
||||
that is being protected.
|
||||
*/
|
||||
void asteroid_parse_tbl()
|
||||
static void asteroid_parse_tbl()
|
||||
{
|
||||
char impact_ani_file[MAX_FILENAME_LEN];
|
||||
|
||||
@@ -2066,7 +2004,7 @@ void asteroid_parse_tbl()
|
||||
/**
|
||||
* Return number of asteroids expected to collide with a ship.
|
||||
*/
|
||||
int count_incident_asteroids()
|
||||
static int count_incident_asteroids()
|
||||
{
|
||||
object *asteroid_objp;
|
||||
int count;
|
||||
@@ -2090,7 +2028,7 @@ int count_incident_asteroids()
|
||||
* Pick object to throw asteroids at.
|
||||
* Pick any capital or big ship inside the bounds of the asteroid field.
|
||||
*/
|
||||
int set_asteroid_throw_objnum()
|
||||
static int set_asteroid_throw_objnum()
|
||||
{
|
||||
if (Asteroid_field.num_initial_asteroids < 1)
|
||||
return -1;
|
||||
|
||||
@@ -163,7 +163,6 @@ int asteroid_collide_objnum(object *asteroid_objp);
|
||||
float asteroid_time_to_impact(object *asteroid_objp);
|
||||
void asteroid_show_brackets();
|
||||
void asteroid_target_closest_danger();
|
||||
int asteroid_get_random_in_cone(vec3d *pos, vec3d *dir, float ang, int danger = 0);
|
||||
|
||||
// need to extern for multiplayer
|
||||
void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec);
|
||||
|
||||
@@ -1231,7 +1231,7 @@ void send_autopilot_msg(char *msg, char *snd)
|
||||
audio_handle = -1;
|
||||
}
|
||||
|
||||
if (msg[0] != '\0' && strcmp(msg, "none"))
|
||||
if (msg[0] != '\0' && strcmp(msg, "none") != 0)
|
||||
change_message("autopilot builtin message", msg, -1, 0);
|
||||
|
||||
// load sound
|
||||
@@ -1246,7 +1246,7 @@ void send_autopilot_msg(char *msg, char *snd)
|
||||
audiostream_play(audio_handle, (Master_event_music_volume * aav_music_volume), 0);
|
||||
}
|
||||
|
||||
if (msg[0] != '\0' && strcmp(msg, "none"))
|
||||
if (msg[0] != '\0' && strcmp(msg, "none") != 0)
|
||||
message_training_queue("autopilot builtin message", timestamp(0), 5); // display message for five seconds
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,16 @@
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* @brief Container class for graphics API specific bitmap data
|
||||
*/
|
||||
class gr_bitmap_info {
|
||||
public:
|
||||
virtual ~gr_bitmap_info() = 0;
|
||||
};
|
||||
|
||||
union bm_extra_info {
|
||||
struct {
|
||||
// Stuff needed for animations
|
||||
@@ -90,17 +100,35 @@ struct bitmap_entry {
|
||||
#endif
|
||||
};
|
||||
|
||||
extern bitmap_entry* bm_bitmaps;
|
||||
struct bitmap_slot {
|
||||
bitmap_entry entry;
|
||||
|
||||
gr_bitmap_info* gr_info = nullptr;
|
||||
};
|
||||
|
||||
// image specific lock functions
|
||||
void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_dds( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_png( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_apng( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_jpg( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_pcx( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_tga( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
|
||||
const size_t BM_BLOCK_SIZE = 4096;
|
||||
|
||||
extern SCP_vector<std::array<bitmap_slot, BM_BLOCK_SIZE>> bm_blocks;
|
||||
|
||||
bitmap_slot* bm_get_slot(int handle, bool separate_ani_frames = true);
|
||||
|
||||
inline bitmap_entry* bm_get_entry(int handle, bool separate_ani_frames = true) {
|
||||
return &bm_get_slot(handle, separate_ani_frames)->entry;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* bm_get_gr_info(int handle, bool separate_ani_frames = true) {
|
||||
return static_cast<T*>(bm_get_slot(handle, separate_ani_frames)->gr_info);
|
||||
}
|
||||
|
||||
#endif // __BM_INTERNAL_H__
|
||||
+794
-723
File diff suppressed because it is too large.
Load diff
+33
-49
@@ -32,23 +32,6 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief How many bitmaps the game can handle by default
|
||||
*
|
||||
* @attention MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's proper use even the
|
||||
* largest missions should stay under this number. With the largest retail missions and wasteful content we should
|
||||
* still have about 20% of the slots free. If it still goes over then it's something the artists need to fix.
|
||||
* For instance the Terran Mara fighter, with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone.
|
||||
* 111 of those is just for the glowmaps. This number can be greatly reduced if the number of ani frames for another
|
||||
* LOD than LOD0 has fewer or no ani frames. A 37 frame glow ani for LOD2 is little more than a waste of resources.
|
||||
* Future reports of texture corruption should be initially approached with content as the cause and not code.
|
||||
* If anything we could/should reduce MAX_BITMAPS in the future. Where it's at now should accomidate even the
|
||||
* largest mods. -- Taylor
|
||||
*/
|
||||
#define DEFAULT_MAX_BITMAPS 4750
|
||||
|
||||
extern int MAX_BITMAPS;
|
||||
|
||||
// Flag positions for bitmap.flags
|
||||
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
|
||||
#define BMP_AABITMAP (1<<0) //!< antialiased bitmap
|
||||
@@ -115,6 +98,10 @@ struct bitmap
|
||||
*/
|
||||
};
|
||||
|
||||
// Forward definition for the graphics API
|
||||
struct bitmap_entry;
|
||||
struct bitmap_slot;
|
||||
|
||||
extern size_t bm_texture_ram; //!< how many bytes of textures are used.
|
||||
|
||||
extern int Bm_paging; //!< Bool type that indicates if BMPMAN is currently paging.
|
||||
@@ -143,22 +130,6 @@ void bm_init();
|
||||
*/
|
||||
void bm_close();
|
||||
|
||||
/**
|
||||
* Gets the cache slot of the bitmap indexed by handle.
|
||||
*
|
||||
* @details if the bitmap is an ani, gets the first frame
|
||||
*
|
||||
* @returns The cache slot index of the bitmap if handle is valid
|
||||
*
|
||||
* @note If the handle is invalid, an Assert() fails
|
||||
*/
|
||||
int bm_get_cache_slot(int bitmap_id, int separate_ani_frames);
|
||||
|
||||
/**
|
||||
* @brief Gets the next available bitmap slot.
|
||||
*/
|
||||
int bm_get_next_handle();
|
||||
|
||||
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0)
|
||||
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1)
|
||||
#define BMP_FLAG_CUBEMAP (1<<2)
|
||||
@@ -412,13 +383,6 @@ void bm_get_filename(int bitmapnum, char *filename);
|
||||
*/
|
||||
const char *bm_get_filename(int handle);
|
||||
|
||||
/**
|
||||
* @brief Loads all data for all bitmaps that have been requested to be loaded
|
||||
*
|
||||
* @note This function is not defined.
|
||||
*/
|
||||
void bm_gfx_load_all();
|
||||
|
||||
/**
|
||||
* @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
|
||||
*
|
||||
@@ -437,15 +401,6 @@ void bm_unload_all();
|
||||
*/
|
||||
void bm_get_palette(int handle, ubyte *pal, char *name);
|
||||
|
||||
/**
|
||||
* @brief Hack to get a pixel from a bitmap
|
||||
*
|
||||
* @details only works good in 8bpp mode
|
||||
*
|
||||
* @note This function is not defined.
|
||||
*/
|
||||
void bm_gfx_get_pixel(int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
|
||||
*
|
||||
@@ -741,4 +696,33 @@ int bm_get_array_index(const int handle);
|
||||
*/
|
||||
int bmpman_count_bitmaps();
|
||||
|
||||
/**
|
||||
* @brief Counts how many slots are available to the bmpman system
|
||||
*
|
||||
* Since the number of slots is dynamic now, this should be used for determining the total amount of available slots at
|
||||
* the moment.
|
||||
*
|
||||
* @warning This is entirely for debugging and logging purposes. It should not be used in actual engine code.
|
||||
*
|
||||
* @return The number of available slots
|
||||
*/
|
||||
int bmpman_count_available_slots();
|
||||
|
||||
/**
|
||||
* @brief Checks if the given filename is a valid effect or texture file name
|
||||
*
|
||||
* @note At least one of @c single_frame or @c animation must be true since the result would make no sense otherwise. It
|
||||
* is also valid to set both parmeters to @c true.
|
||||
*
|
||||
* @todo This currently just tries to load the file but could be improved by not actually loading the file in the future.
|
||||
*
|
||||
* @param file The file name to check
|
||||
* @param single_frame If set to @c true then single frames are valid files
|
||||
* @param animation If set to @c true then animations are valid files
|
||||
* @return @c true if the file name is valid, @c false otherwise
|
||||
*/
|
||||
bool bm_validate_filename(const SCP_string& file, bool single_frame, bool animation);
|
||||
|
||||
SDL_Surface* bm_to_sdl_surface(int handle);
|
||||
|
||||
#endif
|
||||
@@ -245,12 +245,12 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
|
||||
set_rotation(&temp_matrix, in_rotation_time, in_rotation_acceleration_time, in_rotation_deceleration_time);
|
||||
}
|
||||
|
||||
void camera::set_rotation_velocity(angles *in_rotation_rate, float in_acceleration_time)
|
||||
void camera::set_rotation_velocity(angles * /*in_rotation_rate*/, float /*in_acceleration_time*/)
|
||||
{
|
||||
Error(LOCATION, "This function is disabled until further notice.");
|
||||
}
|
||||
|
||||
void camera::do_frame(float in_frametime)
|
||||
void camera::do_frame(float /*in_frametime*/)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -802,7 +802,7 @@ void subtitle::clone(const subtitle &sub)
|
||||
post_shaded = sub.post_shaded;
|
||||
}
|
||||
|
||||
const subtitle &subtitle::operator=(const subtitle &sub)
|
||||
subtitle& subtitle::operator=(const subtitle &sub)
|
||||
{
|
||||
if (this != &sub) {
|
||||
if (image_id != -1) {
|
||||
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
~subtitle();
|
||||
|
||||
subtitle(const subtitle &sub) { clone(sub); }
|
||||
const subtitle &operator=(const subtitle &sub);
|
||||
subtitle& operator=(const subtitle &sub);
|
||||
|
||||
void do_frame(float frametime);
|
||||
bool is_post_shaded( ) { return post_shaded; }
|
||||
|
||||
+122
-85
@@ -10,10 +10,10 @@
|
||||
|
||||
#define _CFILE_INTERNAL
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -48,50 +48,56 @@ char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
//
|
||||
// Please make sure extensions are all lower-case, or we'll break unix compatibility
|
||||
//
|
||||
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
// What type this is Path Extensions Parent type
|
||||
{ CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID },
|
||||
// Root must be index 1!!
|
||||
{ CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT },
|
||||
{ CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT },
|
||||
{ CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
|
||||
{ CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS },
|
||||
{ CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS },
|
||||
{ CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA },
|
||||
{ CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4", CF_TYPE_DATA },
|
||||
{ CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA },
|
||||
{ CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
|
||||
{ CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
|
||||
{ CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA }, //clr=cached color
|
||||
{ CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA },
|
||||
{ CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA },
|
||||
{ CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA },
|
||||
{ CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA },
|
||||
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
// What type this is Path Extensions Parent
|
||||
// type
|
||||
{CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID},
|
||||
// Root must be index 1!!
|
||||
{CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT},
|
||||
{CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT},
|
||||
{CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA},
|
||||
{CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA},
|
||||
{CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA},
|
||||
{CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA},
|
||||
{CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS},
|
||||
{CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS},
|
||||
{CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA},
|
||||
{CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg",
|
||||
CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg",
|
||||
CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg",
|
||||
CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE},
|
||||
{CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA},
|
||||
{CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt", CF_TYPE_DATA},
|
||||
{CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA},
|
||||
{CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA},
|
||||
{CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA},
|
||||
{CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA},
|
||||
{CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds",
|
||||
CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds",
|
||||
CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css",
|
||||
CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA}, // clr=cached color
|
||||
{CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA},
|
||||
{CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA},
|
||||
{CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA},
|
||||
{CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA},
|
||||
{CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA},
|
||||
{CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA},
|
||||
{CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA},
|
||||
};
|
||||
|
||||
|
||||
#define CFILE_STACK_MAX 8
|
||||
|
||||
int cfile_inited = 0;
|
||||
@@ -110,6 +116,7 @@ static const char *Cfile_cdrom_dir = NULL;
|
||||
static int cfget_cfile_block();
|
||||
static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE * fp, int type);
|
||||
static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, size_t offset, size_t size);
|
||||
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const void* data, size_t size, int dir_type);
|
||||
|
||||
#if defined _WIN32
|
||||
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type);
|
||||
@@ -466,7 +473,7 @@ char *cf_add_ext(const char *filename, const char *ext)
|
||||
size_t elen = strlen(ext);
|
||||
Assert(flen < MAX_PATH_LEN);
|
||||
strcpy_s(path, filename);
|
||||
if ((flen < 4) || stricmp(path + flen - elen, ext)) {
|
||||
if ((flen < 4) || stricmp(path + flen - elen, ext) != 0) {
|
||||
Assert(flen + elen < MAX_PATH_LEN);
|
||||
strcat_s(path, ext);
|
||||
}
|
||||
@@ -560,7 +567,7 @@ void cf_attrib(const char *filename, int set, int clear, int dir_type)
|
||||
fclose(fp);
|
||||
|
||||
DWORD z = GetFileAttributes(longname);
|
||||
SetFileAttributes(longname, z | set & ~clear);
|
||||
SetFileAttributes(longname, z | (set & ~clear));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -685,7 +692,7 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
Assert( mode != NULL );
|
||||
|
||||
// Can only open read-only binary files in memory mapped mode.
|
||||
if ( (type & CFILE_MEMORY_MAPPED) && strcmp(mode,"rb") ) {
|
||||
if ( (type & CFILE_MEMORY_MAPPED) && strcmp(mode,"rb") != 0 ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
@@ -764,16 +771,16 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
char copy_file_path[MAX_PATH_LEN]; // FIX change in memory from cf_find_file_location
|
||||
strcpy_s(copy_file_path, file_path);
|
||||
|
||||
|
||||
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize ) ) {
|
||||
const void* file_data = nullptr;
|
||||
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize, &file_data ) ) {
|
||||
|
||||
// Fount it, now create a cfile out of it
|
||||
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, longname));
|
||||
|
||||
if ( type & CFILE_MEMORY_MAPPED ) {
|
||||
|
||||
// Can't open memory mapped files out of pack files
|
||||
if ( offset == 0 ) {
|
||||
// Can't open memory mapped files out of pack or memory files
|
||||
if ( offset == 0 && file_data != nullptr ) {
|
||||
#if defined _WIN32
|
||||
HANDLE hFile;
|
||||
|
||||
@@ -791,18 +798,8 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
FILE *fp = fopen( longname, "rb" );
|
||||
|
||||
if ( fp ) {
|
||||
if ( offset ) {
|
||||
// Found it in a pack file
|
||||
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size );
|
||||
} else {
|
||||
// Found it in a normal file
|
||||
return cf_open_fill_cfblock(source, line, fp, dir_type);
|
||||
}
|
||||
}
|
||||
// since cfopen_special already has all the code to handle the opening we can just use that here
|
||||
return _cfopen_special(source, line, longname, mode, size, offset, file_data, dir_type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -821,7 +818,7 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
// returns: success ==> address of CFILE structure
|
||||
// error ==> NULL
|
||||
//
|
||||
CFILE *_cfopen_special(const char* source, int line, const char *file_path, const char *mode, const size_t size, const size_t offset, int dir_type)
|
||||
CFILE *_cfopen_special(const char* source, int line, const char *file_path, const char *mode, const size_t size, const size_t offset, const void* data, int dir_type)
|
||||
{
|
||||
if ( !cfile_inited) {
|
||||
Int3();
|
||||
@@ -837,19 +834,27 @@ CFILE *_cfopen_special(const char* source, int line, const char *file_path, cons
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// "file_path" should already be a fully qualified path, so just try to open it
|
||||
FILE *fp = fopen( file_path, "rb" );
|
||||
|
||||
if ( !fp )
|
||||
return NULL;
|
||||
|
||||
if ( offset ) {
|
||||
// it's in a pack file
|
||||
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size);
|
||||
} else {
|
||||
// it's a normal file
|
||||
return cf_open_fill_cfblock(source, line, fp, dir_type);
|
||||
// In-Memory files are a bit different from normal files so we need to handle them separately
|
||||
if (data != nullptr) {
|
||||
return cf_open_memory_fill_cfblock(source, line, data, size, dir_type);
|
||||
}
|
||||
else {
|
||||
// "file_path" should already be a fully qualified path, so just try to open it
|
||||
FILE *fp = fopen(file_path, "rb");
|
||||
|
||||
if (fp) {
|
||||
if (offset) {
|
||||
// Found it in a pack file
|
||||
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size);
|
||||
}
|
||||
else {
|
||||
// Found it in a normal file
|
||||
return cf_open_fill_cfblock(source, line, fp, dir_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -923,7 +928,7 @@ int cfclose( CFILE * cfile )
|
||||
cb = &Cfile_block_list[cfile->id];
|
||||
|
||||
result = 0;
|
||||
if ( cb->data ) {
|
||||
if ( cb->data && cb->mem_mapped ) {
|
||||
// close memory mapped file
|
||||
#if defined _WIN32
|
||||
result = UnmapViewOfFile((void*)cb->data);
|
||||
@@ -937,7 +942,8 @@ int cfclose( CFILE * cfile )
|
||||
// FIXME: result is wrong after munmap() but it is successful
|
||||
//result = munmap(cb->data, cb->data_length);
|
||||
//Assert(result);
|
||||
munmap(cb->data, cb->data_length);
|
||||
// This const_cast is safe since the pointer returned by mmap was also non-const
|
||||
munmap(const_cast<void*>(cb->data), cb->data_length);
|
||||
if ( cb->fp != NULL)
|
||||
result = fclose(cb->fp);
|
||||
#endif
|
||||
@@ -997,6 +1003,7 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int t
|
||||
cfp->id = cfile_block_index;
|
||||
cfp->version = 0;
|
||||
cfbp->data = NULL;
|
||||
cfbp->mem_mapped = false;
|
||||
cfbp->fp = fp;
|
||||
cfbp->dir_type = type;
|
||||
cfbp->max_read_len = 0;
|
||||
@@ -1039,6 +1046,7 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int
|
||||
cfp->version = 0;
|
||||
cfbp->data = NULL;
|
||||
cfbp->fp = fp;
|
||||
cfbp->mem_mapped = false;
|
||||
cfbp->dir_type = type;
|
||||
cfbp->max_read_len = 0;
|
||||
|
||||
@@ -1084,6 +1092,7 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp
|
||||
cfp->version = 0;
|
||||
cfbp->max_read_len = 0;
|
||||
cfbp->fp = NULL;
|
||||
cfbp->mem_mapped = true;
|
||||
#if defined _WIN32
|
||||
cfbp->hInFile = hFile;
|
||||
#endif
|
||||
@@ -1118,6 +1127,37 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp
|
||||
}
|
||||
}
|
||||
|
||||
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const void* data, size_t size, int dir_type)
|
||||
{
|
||||
int cfile_block_index;
|
||||
|
||||
cfile_block_index = cfget_cfile_block();
|
||||
if ( cfile_block_index == -1 ) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
CFILE *cfp;
|
||||
Cfile_block *cfbp;
|
||||
cfbp = &Cfile_block_list[cfile_block_index];
|
||||
|
||||
cfp = &Cfile_list[cfile_block_index];
|
||||
cfp->id = cfile_block_index;
|
||||
cfp->version = 0;
|
||||
cfbp->max_read_len = 0;
|
||||
cfbp->fp = NULL;
|
||||
cfbp->mem_mapped = false;
|
||||
cfbp->dir_type = dir_type;
|
||||
|
||||
cfbp->source_file = source;
|
||||
cfbp->line_num = line;
|
||||
|
||||
cf_init_lowlevel_read_code(cfp, 0, size, 0 );
|
||||
cfbp->data = data;
|
||||
|
||||
return cfp;
|
||||
}
|
||||
}
|
||||
|
||||
int cf_get_dir_type(CFILE *cfile)
|
||||
{
|
||||
return Cfile_block_list[cfile->id].dir_type;
|
||||
@@ -1128,7 +1168,7 @@ int cf_get_dir_type(CFILE *cfile)
|
||||
//
|
||||
//
|
||||
|
||||
void *cf_returndata(CFILE *cfile)
|
||||
const void *cf_returndata(CFILE *cfile)
|
||||
{
|
||||
Assert(cfile != NULL);
|
||||
Cfile_block *cb;
|
||||
@@ -1419,9 +1459,7 @@ int cfilelength( CFILE * cfile )
|
||||
cb = &Cfile_block_list[cfile->id];
|
||||
|
||||
// TODO: return length of memory mapped file
|
||||
Assert( !cb->data );
|
||||
|
||||
Assert(cb->fp != NULL);
|
||||
Assert( !cb->mem_mapped );
|
||||
|
||||
// cb->size gets set at cfopen
|
||||
|
||||
@@ -1520,7 +1558,6 @@ int cfputc(int c, CFILE *cfile)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// cfputs() writes a string to a file
|
||||
//
|
||||
// returns: success ==> non-negative value
|
||||
|
||||
+9
-12
@@ -13,7 +13,7 @@
|
||||
#define __CFILE_H__
|
||||
|
||||
|
||||
#include <time.h>
|
||||
#include <ctime>
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include <stdexcept>
|
||||
@@ -140,7 +140,7 @@ CFILE *_cfopen(const char* source_file, int line, const char *filename, const ch
|
||||
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
|
||||
// NOTE: only supports reading files!!
|
||||
CFILE *_cfopen_special(const char* source_file, int line, const char *file_path, const char *mode,
|
||||
const size_t size, const size_t offset, int dir_type = CF_TYPE_ANY);
|
||||
const size_t size, const size_t offset, const void* data, int dir_type = CF_TYPE_ANY);
|
||||
#define cfopen_special(...) _cfopen_special(LOCATION, __VA_ARGS__) // Pass source location to the function
|
||||
|
||||
// Flush the open file buffer
|
||||
@@ -216,7 +216,7 @@ char *cfgets(char *buf, int n, CFILE *cfile);
|
||||
int cfeof(CFILE *cfile);
|
||||
|
||||
// Return the data pointer associated with the CFILE structure (for memory mapped files)
|
||||
void *cf_returndata(CFILE *cfile);
|
||||
const void *cf_returndata(CFILE *cfile);
|
||||
|
||||
// get the 2 byte checksum of the passed filename - return 0 if operation failed, 1 if succeeded
|
||||
int cf_chksum_short(const char *filename, ushort *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
|
||||
@@ -326,7 +326,7 @@ void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_
|
||||
// size - File size
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns 0.
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false);
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false, const void** data_out = nullptr);
|
||||
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
|
||||
@@ -340,7 +340,7 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns -1, else returns offset into ext_list.
|
||||
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
|
||||
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false);
|
||||
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false, const void** data_out = nullptr);
|
||||
|
||||
// Functions to change directories
|
||||
int cfile_chdir(const char *dir);
|
||||
@@ -365,16 +365,13 @@ namespace cfile
|
||||
{
|
||||
}
|
||||
|
||||
cfile_error(const std::string &excuse) : m_excuse(excuse)
|
||||
explicit cfile_error(const std::string &excuse) : m_excuse(excuse)
|
||||
{
|
||||
}
|
||||
|
||||
~cfile_error() throw()
|
||||
{
|
||||
}
|
||||
~cfile_error() SCP_NOEXCEPT override {}
|
||||
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
const char *what() const SCP_NOEXCEPT override {
|
||||
return m_excuse.c_str();
|
||||
}
|
||||
|
||||
@@ -385,7 +382,7 @@ namespace cfile
|
||||
class max_read_length : public cfile_error
|
||||
{
|
||||
public:
|
||||
max_read_length(const std::string &excuse) : cfile_error(excuse)
|
||||
explicit max_read_length(const std::string &excuse) : cfile_error(excuse)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+59
-41
@@ -11,9 +11,9 @@
|
||||
|
||||
#define _CFILE_INTERNAL
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
@@ -74,18 +74,13 @@ int cfeof(CFILE *cfile)
|
||||
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
|
||||
cb = &Cfile_block_list[cfile->id];
|
||||
|
||||
int result;
|
||||
|
||||
result = 0;
|
||||
|
||||
// cfeof() not supported for memory-mapped files
|
||||
Assert( !cb->data );
|
||||
|
||||
Assert(cb->fp != NULL);
|
||||
int result = 0;
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
auto raw_position = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(raw_position == cb->raw_position);
|
||||
if (cb->fp) {
|
||||
auto raw_position = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(raw_position == cb->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cb->raw_position >= cb->size ) {
|
||||
@@ -109,14 +104,11 @@ int cftell( CFILE * cfile )
|
||||
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
|
||||
cb = &Cfile_block_list[cfile->id];
|
||||
|
||||
// Doesn't work for memory mapped files
|
||||
Assert( !cb->data );
|
||||
|
||||
Assert(cb->fp != NULL);
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
auto raw_position = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(raw_position == cb->raw_position);
|
||||
if (cb->fp) {
|
||||
auto raw_position = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(raw_position == cb->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The rest of the code still uses ints, do an overflow check to detect cases where this fails
|
||||
@@ -141,8 +133,7 @@ int cfseek( CFILE *cfile, int offset, int where )
|
||||
|
||||
|
||||
// TODO: seek to offset in memory mapped file
|
||||
Assert( !cb->data );
|
||||
Assert( cb->fp != NULL );
|
||||
Assert( !cb->mem_mapped );
|
||||
|
||||
size_t goal_position;
|
||||
|
||||
@@ -166,14 +157,22 @@ int cfseek( CFILE *cfile, int offset, int where )
|
||||
// Make sure we don't seek beyond the end of the file
|
||||
CAP(goal_position, cb->lib_offset, cb->lib_offset + cb->size);
|
||||
|
||||
int result = fseek(cb->fp, (long)goal_position, SEEK_SET );
|
||||
Assertion(goal_position >= cb->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cb->lib_offset);
|
||||
int result = 0;
|
||||
|
||||
if (cb->fp) {
|
||||
// If we have a file pointer we can also seek in that file
|
||||
result = fseek(cb->fp, (long)goal_position, SEEK_SET );
|
||||
Assertion(goal_position >= cb->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cb->lib_offset);
|
||||
}
|
||||
// If we only have a data pointer this will do all the work
|
||||
cb->raw_position = goal_position - cb->lib_offset;
|
||||
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(tmp_offset==cb->raw_position);
|
||||
if (cb->fp) {
|
||||
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(tmp_offset == cb->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
@@ -197,13 +196,6 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
|
||||
Cfile_block *cb = &Cfile_block_list[cfile->id];
|
||||
|
||||
// cfread() not supported for memory-mapped files
|
||||
if(cb->data != NULL)
|
||||
{
|
||||
Warning(LOCATION, "Writing is not supported for mem-mapped files");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (cb->raw_position+size) > cb->size ) {
|
||||
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
|
||||
size = cb->size - cb->raw_position;
|
||||
@@ -222,15 +214,24 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
}
|
||||
}
|
||||
|
||||
size_t bytes_read = fread( buf, 1, size, cb->fp );
|
||||
size_t bytes_read;
|
||||
if (cb->data != nullptr) {
|
||||
// This is a file from memory
|
||||
bytes_read = size;
|
||||
memcpy(buf, reinterpret_cast<const char*>(cb->data) + cb->raw_position, size);
|
||||
} else {
|
||||
bytes_read = fread( buf, 1, size, cb->fp );
|
||||
}
|
||||
if ( bytes_read > 0 ) {
|
||||
cb->raw_position += bytes_read;
|
||||
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
|
||||
}
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(tmp_offset==cb->raw_position);
|
||||
if (cb->fp) {
|
||||
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(tmp_offset==cb->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (int)(bytes_read / elsize);
|
||||
@@ -254,14 +255,31 @@ int cfread_lua_number(double *buf, CFILE *cfile)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long orig_pos = ftell(cb->fp);
|
||||
int items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
|
||||
cb->raw_position += ftell(cb->fp)-orig_pos;
|
||||
size_t advance = 0;
|
||||
int items_read;
|
||||
if (cb->fp) {
|
||||
long orig_pos = ftell(cb->fp);
|
||||
items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
|
||||
advance = (size_t) (ftell(cb->fp)-orig_pos);
|
||||
} else {
|
||||
int read;
|
||||
// %n returns the number of bytes currently read so we append that to the scan format at the end so it will return
|
||||
// how many bytes we have consumed
|
||||
items_read = sscanf(reinterpret_cast<const char*>(cb->data), LUA_NUMBER_SCAN "%n", buf, &read);
|
||||
if (items_read == 2) {
|
||||
// We need to correct the items read counter since we read one additional item
|
||||
items_read = 1;
|
||||
}
|
||||
advance = (size_t) read;
|
||||
}
|
||||
cb->raw_position += advance;
|
||||
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(tmp_offset==cb->raw_position);
|
||||
if (cb->fp) {
|
||||
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
|
||||
Assert(tmp_offset==cb->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
return items_read;
|
||||
|
||||
@@ -26,7 +26,8 @@ typedef struct Cfile_block {
|
||||
int type; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
|
||||
int dir_type; // directory location
|
||||
FILE *fp; // File pointer if opening an individual file
|
||||
void *data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
|
||||
const void *data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
|
||||
bool mem_mapped; // Flag for memory mapped files (if data is not null and this is false it means that it's an embedded file)
|
||||
#ifdef _WIN32
|
||||
HANDLE hInFile; // Handle from CreateFile()
|
||||
HANDLE hMapFile; // Handle from CreateFileMapping()
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+141
-30
@@ -9,10 +9,10 @@
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -37,12 +37,16 @@
|
||||
#include "cfile/cfilesystem.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "def_files/def_files.h"
|
||||
#include "localization/localize.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "parse/parselo.h"
|
||||
|
||||
#define CF_ROOTTYPE_PATH 0
|
||||
#define CF_ROOTTYPE_PACK 1
|
||||
enum CfileRootType {
|
||||
CF_ROOTTYPE_PATH = 0,
|
||||
CF_ROOTTYPE_PACK = 1,
|
||||
CF_ROOTTYPE_MEMORY = 2,
|
||||
};
|
||||
|
||||
// for a defined and specifically set location to get/send pilot/campaign files
|
||||
SCP_string Pilot_file_path;
|
||||
@@ -53,8 +57,8 @@ SCP_string Pilot_file_path;
|
||||
// specifying cd-rom tree
|
||||
// searching for pack files on CD-rom tree
|
||||
typedef struct cf_root {
|
||||
char path[CF_MAX_PATHNAME_LENGTH]; // Contains something like c:\projects\freespace or c:\projects\freespace\freespace.vp
|
||||
int roottype; // CF_ROOTTYPE_PATH = Path, CF_ROOTTYPE_PACK =Pack file
|
||||
char path[CF_MAX_PATHNAME_LENGTH]; // Contains something like c:\projects\freespace or c:\projects\freespace\freespace.vp
|
||||
int roottype; // CF_ROOTTYPE_PATH = Path, CF_ROOTTYPE_PACK =Pack file, CF_ROOTTYPE_MEMORY=In memory
|
||||
} cf_root;
|
||||
|
||||
// convenient type for sorting (see cf_build_pack_list())
|
||||
@@ -79,13 +83,14 @@ static int Num_path_roots = 0;
|
||||
|
||||
// Created by searching all roots in order. This means Files is then sorted by precedence.
|
||||
typedef struct cf_file {
|
||||
char name_ext[CF_MAX_FILENAME_LENGTH]; // Filename and extension
|
||||
int root_index; // Where in Roots this is located
|
||||
int pathtype_index; // Where in Paths this is located
|
||||
time_t write_time; // When it was last written
|
||||
int size; // How big it is in bytes
|
||||
int pack_offset; // For pack files, where it is at. 0 if not in a pack file. This can be used to tell if in a pack file.
|
||||
char* real_name; // For real files, the full path
|
||||
char name_ext[CF_MAX_FILENAME_LENGTH]; // Filename and extension
|
||||
int root_index; // Where in Roots this is located
|
||||
int pathtype_index; // Where in Paths this is located
|
||||
time_t write_time; // When it was last written
|
||||
int size; // How big it is in bytes
|
||||
int pack_offset; // For pack files, where it is at. 0 if not in a pack file. This can be used to tell if in a pack file.
|
||||
char* real_name; // For real files, the full path
|
||||
const void* data; // For in-memory files, the data pointer
|
||||
} cf_file;
|
||||
|
||||
#define CF_NUM_FILES_PER_BLOCK 512
|
||||
@@ -510,6 +515,11 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
|
||||
}
|
||||
|
||||
// The final root is the in-memory root
|
||||
root = cf_create_root();
|
||||
memset(root->path, 0, sizeof(root->path));
|
||||
root->roottype = CF_ROOTTYPE_MEMORY;
|
||||
|
||||
}
|
||||
|
||||
// Given a lower case list of file extensions
|
||||
@@ -639,7 +649,7 @@ void cf_search_root_path(int root_index)
|
||||
struct dirent *dir = nullptr;
|
||||
while ((dir = readdir (parentDirP)) != nullptr) {
|
||||
|
||||
if (stricmp(search_name, dir->d_name)) {
|
||||
if (stricmp(search_name, dir->d_name) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -836,7 +846,48 @@ void cf_search_root_pack(int root_index)
|
||||
mprintf(( "%i files\n", num_files ));
|
||||
}
|
||||
|
||||
void cf_search_memory_root(int root_index) {
|
||||
int num_files = 0;
|
||||
mprintf(( "Searching memory root ... " ));
|
||||
|
||||
auto default_files = defaults_get_all();
|
||||
for (auto& default_file : default_files) {
|
||||
// Pure built in files have an empty path_type string
|
||||
if (strlen(default_file.path_type) <= 0) {
|
||||
// Ignore pure builtin files. They should only be accessible with defaults_get_file
|
||||
continue;
|
||||
}
|
||||
|
||||
int pathtype = -1;
|
||||
for (int i = 0; i < CF_MAX_PATH_TYPES; ++i) {
|
||||
if (Pathtypes[i].path == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(Pathtypes[i].path, default_file.path_type)) {
|
||||
pathtype = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assertion(pathtype != -1, "Default file '%s%s%s' does not use a valid path type!",
|
||||
default_file.path_type,
|
||||
DIR_SEPARATOR_STR,
|
||||
default_file.filename);
|
||||
|
||||
cf_file *file = cf_create_file();
|
||||
|
||||
strcpy_s( file->name_ext, default_file.filename );
|
||||
file->root_index = root_index;
|
||||
file->pathtype_index = pathtype;
|
||||
file->write_time = time(nullptr); // Just assume that memory files were last written to just now
|
||||
file->size = (int)default_file.size;
|
||||
file->data = default_file.data;
|
||||
|
||||
num_files++;
|
||||
}
|
||||
|
||||
mprintf(( "%i files\n", num_files ));
|
||||
}
|
||||
|
||||
void cf_build_file_list()
|
||||
{
|
||||
@@ -851,6 +902,8 @@ void cf_build_file_list()
|
||||
cf_search_root_path(i);
|
||||
} else if ( root->roottype == CF_ROOTTYPE_PACK ) {
|
||||
cf_search_root_pack(i);
|
||||
} else if (root->roottype == CF_ROOTTYPE_MEMORY) {
|
||||
cf_search_memory_root(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,7 +985,7 @@ void cf_free_secondary_filelist()
|
||||
*
|
||||
* @return If not found returns 0.
|
||||
*/
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize )
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out )
|
||||
{
|
||||
int i;
|
||||
uint ui;
|
||||
@@ -1067,8 +1120,16 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
if (offset)
|
||||
*offset = (size_t)f->pack_offset;
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->pack_offset < 1) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy( pack_filename, f->real_name, max_out );
|
||||
} else {
|
||||
@@ -1092,8 +1153,16 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
if (offset)
|
||||
*offset = (size_t)f->pack_offset;
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->pack_offset < 1) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy( pack_filename, f->real_name, max_out );
|
||||
} else {
|
||||
@@ -1132,7 +1201,7 @@ extern char *stristr(char *str, const char *substr);
|
||||
*
|
||||
* @return If not found returns -1, else returns offset into ext_list.
|
||||
*/
|
||||
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize )
|
||||
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out)
|
||||
{
|
||||
int cur_ext, i;
|
||||
uint ui;
|
||||
@@ -1217,6 +1286,9 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
if (size)
|
||||
*size = findstruct.size;
|
||||
|
||||
if (data_out)
|
||||
*data_out = nullptr;
|
||||
|
||||
_findclose(findhandle);
|
||||
|
||||
if (offset)
|
||||
@@ -1235,6 +1307,9 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
if (size)
|
||||
*size = filelength( fileno(fp) );
|
||||
|
||||
if (data_out)
|
||||
*data_out = nullptr;
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (offset)
|
||||
@@ -1284,7 +1359,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
continue;
|
||||
|
||||
// ... check that we match the base filename
|
||||
if ( strnicmp(f->name_ext, filespec, filespec_len) )
|
||||
if ( strnicmp(f->name_ext, filespec, filespec_len) != 0 )
|
||||
continue;
|
||||
|
||||
// ... make sure that it's one of our supported types
|
||||
@@ -1334,15 +1409,25 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
if (offset)
|
||||
*offset = f->pack_offset;
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->pack_offset < 1) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
}
|
||||
else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy( pack_filename, f->real_name, max_out );
|
||||
} else {
|
||||
strncpy(pack_filename, f->real_name, max_out);
|
||||
}
|
||||
else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
strncpy( pack_filename, r->path, max_out );
|
||||
strncpy(pack_filename, r->path, max_out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1362,15 +1447,25 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
if (offset)
|
||||
*offset = f->pack_offset;
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->pack_offset < 1) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
}
|
||||
else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy( pack_filename, f->real_name, max_out );
|
||||
} else {
|
||||
strncpy(pack_filename, f->real_name, max_out);
|
||||
}
|
||||
else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
strncpy( pack_filename, r->path, max_out );
|
||||
strncpy(pack_filename, r->path, max_out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1432,6 +1527,7 @@ int cf_matches_spec(const char *filespec, const char *filename)
|
||||
int (*Get_file_list_filter)(const char *filename) = NULL;
|
||||
const char *Get_file_list_child = NULL;
|
||||
int Skip_packfile_search = 0;
|
||||
bool Skip_memory_files = false;
|
||||
|
||||
static bool verify_file_list_child()
|
||||
{
|
||||
@@ -1635,6 +1731,11 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Skip_memory_files && f->data != nullptr) {
|
||||
// If we want to skip memory files and this is a memory file then ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
|
||||
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
|
||||
|
||||
@@ -1847,6 +1948,11 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Skip_memory_files && f->data != nullptr) {
|
||||
// If we want to skip memory files and this is a memory file then ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
|
||||
|
||||
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
|
||||
@@ -2067,6 +2173,11 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Skip_memory_files && f->data != nullptr) {
|
||||
// If we want to skip memory files and this is a memory file then ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
|
||||
|
||||
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
|
||||
@@ -2183,7 +2294,7 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if the result would be too long (invalid result)
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool localize )
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool /*localize*/ )
|
||||
{
|
||||
#ifdef SCP_UNIX
|
||||
if ( filename && strpbrk(filename,"/") ) {
|
||||
|
||||
+35
-20
@@ -39,8 +39,8 @@
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include <jansson.h>
|
||||
@@ -160,7 +160,6 @@ Flag exe_params[] =
|
||||
{ "-noenv", "Disable environment maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-env", },
|
||||
{ "-nomotiondebris", "Disable motion debris", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
|
||||
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
|
||||
{ "-missile_lighting", "Apply lighting to missiles" , true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missile_lighting", },
|
||||
{ "-nonormal", "Disable normal maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-normal" },
|
||||
{ "-no_emissive_light", "Disable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_emissive_light" },
|
||||
{ "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-height" },
|
||||
@@ -216,7 +215,6 @@ Flag exe_params[] =
|
||||
{ "-use_gldrawelements","Don't use glDrawRangeElements", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-use_gldrawelements", },
|
||||
{ "-old_collision", "Use old collision detection system", true, EASY_DEFAULT, EASY_ALL_ON, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-old_collision", },
|
||||
{ "-gl_finish", "Fix input lag on some ATI+Linux systems", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gl_finish", },
|
||||
{ "-no_batching", "Disable batched model rendering", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
|
||||
{ "-no_geo_effects", "Disable geometry shader for effects", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
|
||||
{ "-set_cpu_affinity", "Sets processor affinity to config value", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
|
||||
{ "-nograb", "Disables mouse grabbing", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nograb", },
|
||||
@@ -315,7 +313,6 @@ cmdline_parm spec_static_arg("-spec_static", "Adjusts suns contribution to specu
|
||||
cmdline_parm spec_point_arg("-spec_point", "Adjusts laser weapons contribution to specular highlights", AT_FLOAT);
|
||||
cmdline_parm spec_tube_arg("-spec_tube", "Adjusts beam weapons contribution to specular highlights", AT_FLOAT);
|
||||
cmdline_parm ambient_factor_arg("-ambient_factor", "Adjusts ambient light applied to all parts of a ship", AT_INT); // Cmdline_ambient_factor
|
||||
cmdline_parm missile_lighting_arg("-missile_lighting", NULL, AT_NONE); // Cmdline_missile_lighting
|
||||
cmdline_parm env("-noenv", NULL, AT_NONE); // Cmdline_env
|
||||
cmdline_parm glow_arg("-noglow", NULL, AT_NONE); // Cmdline_glow -- use Bobs glow code
|
||||
cmdline_parm nomotiondebris_arg("-nomotiondebris", NULL, AT_NONE); // Cmdline_nomotiondebris -- Removes those ugly floating rocks -C
|
||||
@@ -333,10 +330,10 @@ cmdline_parm fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-9), requires -post
|
||||
cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
|
||||
cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
|
||||
cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
|
||||
cmdline_parm no_batching("-no_batching", NULL, AT_NONE);
|
||||
cmdline_parm shadow_quality_arg("-shadow_quality", NULL, AT_INT);
|
||||
cmdline_parm enable_shadows_arg("-enable_shadows", NULL, AT_NONE);
|
||||
cmdline_parm no_deferred_lighting_arg("-no_deferred", NULL, AT_NONE); // Cmdline_no_deferred
|
||||
cmdline_parm anisotropy_level_arg("-anisotropic_filter", NULL, AT_INT);
|
||||
|
||||
float Cmdline_clip_dist = Default_min_draw_distance;
|
||||
float Cmdline_fov = 0.75f;
|
||||
@@ -344,7 +341,6 @@ float Cmdline_ogl_spec = 80.0f;
|
||||
int Cmdline_ambient_factor = 128;
|
||||
int Cmdline_env = 1;
|
||||
int Cmdline_mipmap = 0;
|
||||
int Cmdline_missile_lighting = 0;
|
||||
int Cmdline_glow = 1;
|
||||
int Cmdline_nomotiondebris = 0;
|
||||
int Cmdline_noscalevid = 0;
|
||||
@@ -361,10 +357,10 @@ int Cmdline_fxaa_preset = 6;
|
||||
extern int Fxaa_preset_last_frame;
|
||||
bool Cmdline_fb_explosions = 0;
|
||||
bool Cmdline_fb_thrusters = false;
|
||||
bool Cmdline_no_batching = false;
|
||||
extern bool ls_force_off;
|
||||
int Cmdline_shadow_quality = 0;
|
||||
int Cmdline_no_deferred_lighting = 0;
|
||||
int Cmdline_aniso_level = 0;
|
||||
|
||||
// Game Speed related
|
||||
cmdline_parm cache_bitmaps_arg("-cache_bitmaps", NULL, AT_NONE); // Cmdline_cache_bitmaps
|
||||
@@ -508,6 +504,7 @@ char *Cmdline_start_mission = NULL;
|
||||
int Cmdline_old_collision_sys = 0;
|
||||
int Cmdline_dis_collisions = 0;
|
||||
int Cmdline_dis_weapons = 0;
|
||||
bool Cmdline_output_sexp_info = false;
|
||||
int Cmdline_noparseerrors = 0;
|
||||
#ifdef Allow_NoWarn
|
||||
int Cmdline_nowarn = 0; // turn warnings off in FRED
|
||||
@@ -548,6 +545,7 @@ cmdline_parm deprecated_jpgtga_arg("-jpgtga", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_missile_lighting_arg("-missile_lighting", "Deprecated", AT_NONE);
|
||||
|
||||
int Cmdline_deprecated_spec = 0;
|
||||
int Cmdline_deprecated_glow = 0;
|
||||
@@ -557,6 +555,7 @@ int Cmdline_deprecated_tbp = 0;
|
||||
int Cmdline_deprecated_jpgtga = 0;
|
||||
int Cmdline_deprecated_nohtl = 0;
|
||||
bool Cmdline_deprecated_brief_lighting = 0;
|
||||
bool Cmdline_deprecated_missile_lighting = false;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
|
||||
@@ -622,6 +621,11 @@ void cmdline_debug_print_cmdline()
|
||||
{
|
||||
mprintf(("Deprecated flag '-brief_lighting' found. Please remove from your cmdline.\n"));
|
||||
}
|
||||
|
||||
if (Cmdline_deprecated_missile_lighting)
|
||||
{
|
||||
mprintf(("Deprecated flag '-missile_lighting' found. Please remove from your cmdline.\n"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -814,7 +818,7 @@ void os_validate_parms(int argc, char *argv[])
|
||||
size_t sp = 0;
|
||||
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
|
||||
// don't output deprecated flags
|
||||
if (stricmp("deprecated", parmp->help)) {
|
||||
if (stricmp("deprecated", parmp->help) != 0) {
|
||||
sp = strlen(parmp->name);
|
||||
if (parmp->arg_type != AT_NONE) {
|
||||
atp = strlen(cmdline_arg_types[parmp->arg_type]);
|
||||
@@ -1163,7 +1167,7 @@ bool cmdline_parm::has_param() {
|
||||
#ifdef SCP_UNIX
|
||||
// Return a vector with all filesystem names of "parent/dir" relative to parent.
|
||||
// dir must not contain a slash.
|
||||
static SCP_vector<SCP_string> unix_get_single_dir_names(SCP_string parent, SCP_string dir)
|
||||
static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent, const SCP_string& dir)
|
||||
{
|
||||
SCP_vector<SCP_string> ret;
|
||||
|
||||
@@ -1186,7 +1190,7 @@ static SCP_vector<SCP_string> unix_get_single_dir_names(SCP_string parent, SCP_s
|
||||
|
||||
// Return a vector with all filesystem names of "parent/dir" relative to parent.
|
||||
// Recurses to deal with slashes in dir.
|
||||
static SCP_vector<SCP_string> unix_get_dir_names(SCP_string parent, SCP_string dir)
|
||||
static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const SCP_string& dir)
|
||||
{
|
||||
size_t slash = dir.find_first_of("/\\");
|
||||
|
||||
@@ -1387,6 +1391,15 @@ static json_t* json_get_v1() {
|
||||
|
||||
json_object_set_new(openal_obj, "capture_devices", capture_array);
|
||||
}
|
||||
{
|
||||
auto efx_support_obj = json_object();
|
||||
|
||||
for (auto& pair : openal_info.efx_support) {
|
||||
json_object_set_new(efx_support_obj, pair.first.c_str(), json_boolean(pair.second));
|
||||
}
|
||||
|
||||
json_object_set_new(openal_obj, "efx_support", efx_support_obj);
|
||||
}
|
||||
|
||||
json_object_set_new(root, "openal", openal_obj);
|
||||
}
|
||||
@@ -1890,7 +1903,7 @@ bool SetCmdlineParams()
|
||||
Output_scripting_meta = true;
|
||||
|
||||
if (output_sexp_arg.found() ) {
|
||||
output_sexps("sexps.html");
|
||||
Cmdline_output_sexp_info = true;
|
||||
}
|
||||
|
||||
if ( no_pbo_arg.found() )
|
||||
@@ -1982,9 +1995,6 @@ bool SetCmdlineParams()
|
||||
if ( rearm_timer_arg.found() )
|
||||
Cmdline_rearm_timer = 1;
|
||||
|
||||
if ( missile_lighting_arg.found() )
|
||||
Cmdline_missile_lighting = 1;
|
||||
|
||||
if ( save_render_targets_arg.found() )
|
||||
Cmdline_save_render_targets = 1;
|
||||
|
||||
@@ -2019,11 +2029,6 @@ bool SetCmdlineParams()
|
||||
Cmdline_fb_thrusters = true;
|
||||
}
|
||||
|
||||
if ( no_batching.found() )
|
||||
{
|
||||
Cmdline_no_batching = true;
|
||||
}
|
||||
|
||||
if ( postprocess_arg.found() )
|
||||
{
|
||||
Cmdline_postprocess = 1;
|
||||
@@ -2059,6 +2064,11 @@ bool SetCmdlineParams()
|
||||
Cmdline_no_deferred_lighting = 1;
|
||||
}
|
||||
|
||||
if (anisotropy_level_arg.found())
|
||||
{
|
||||
Cmdline_aniso_level = anisotropy_level_arg.get_int();
|
||||
}
|
||||
|
||||
if (frame_profile_write_file.found())
|
||||
{
|
||||
Cmdline_profile_write_file = true;
|
||||
@@ -2144,6 +2154,11 @@ bool SetCmdlineParams()
|
||||
Cmdline_deprecated_brief_lighting = 1;
|
||||
}
|
||||
|
||||
if (deprecated_missile_lighting_arg.found())
|
||||
{
|
||||
Cmdline_deprecated_missile_lighting = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ extern float static_point_factor;
|
||||
extern float static_tube_factor;
|
||||
extern int Cmdline_ambient_factor;
|
||||
extern int Cmdline_env;
|
||||
extern int Cmdline_missile_lighting;
|
||||
extern int Cmdline_glow;
|
||||
extern int Cmdline_nomotiondebris;
|
||||
extern int Cmdline_noscalevid; // disables fit-to-window for movies - taylor
|
||||
@@ -77,10 +76,10 @@ extern bool Cmdline_fxaa;
|
||||
extern int Cmdline_fxaa_preset;
|
||||
extern bool Cmdline_fb_explosions;
|
||||
extern bool Cmdline_fb_thrusters;
|
||||
extern bool Cmdline_no_batching;
|
||||
extern int Cmdline_shadow_quality;
|
||||
extern int Cmdline_no_deferred_lighting;
|
||||
extern int Cmdline_no_emissive;
|
||||
extern int Cmdline_aniso_level;
|
||||
|
||||
// Game Speed related
|
||||
extern int Cmdline_cache_bitmaps;
|
||||
@@ -145,6 +144,7 @@ extern char *Cmdline_start_mission;
|
||||
extern int Cmdline_old_collision_sys;
|
||||
extern int Cmdline_dis_collisions;
|
||||
extern int Cmdline_dis_weapons;
|
||||
extern bool Cmdline_output_sexp_info;
|
||||
extern int Cmdline_noparseerrors;
|
||||
extern int Cmdline_extra_warn;
|
||||
extern int Cmdline_bmpman_usage;
|
||||
|
||||
@@ -92,7 +92,7 @@ void cmeasure_maybe_alert_success(object *objp)
|
||||
|
||||
if ( objp->parent == OBJ_INDEX(Player_obj) ) {
|
||||
hud_start_text_flash(XSTR("Evaded", 1430), 800);
|
||||
snd_play(gamesnd_get_game_sound(ship_get_sound(Player_obj, SND_MISSILE_EVADED_POPUP)));
|
||||
snd_play(gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::MISSILE_EVADED_POPUP)));
|
||||
} else if ( Objects[objp->parent].flags[Object::Object_Flags::Player_ship] ) {
|
||||
send_countermeasure_success_packet( objp->parent );
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ DCF_BOOL(show_controls_info, Show_controls_info);
|
||||
|
||||
static int Axes_origin[JOY_NUM_AXES];
|
||||
|
||||
static int joy_get_unscaled_reading(int raw, int axn)
|
||||
static int joy_get_unscaled_reading(int raw)
|
||||
{
|
||||
int rng;
|
||||
|
||||
@@ -615,7 +615,7 @@ int control_config_undo_last()
|
||||
int i, z, tab;
|
||||
|
||||
if (!Config_item_undo) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -664,7 +664,7 @@ int control_config_undo_last()
|
||||
free_undo_block();
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -715,7 +715,7 @@ int control_config_remove_binding()
|
||||
config_item_undo *ptr;
|
||||
|
||||
if (Selected_line < 0) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -723,7 +723,7 @@ int control_config_remove_binding()
|
||||
if (z & JOY_AXIS) {
|
||||
z &= ~JOY_AXIS;
|
||||
if (Axis_map_to[z] < 0) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -731,13 +731,13 @@ int control_config_remove_binding()
|
||||
Axis_map_to[z] = -1;
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
Selected_item = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((Control_config[z].joy_id < 0) && (Control_config[z].key_id < 0)) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -755,7 +755,7 @@ int control_config_remove_binding()
|
||||
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
Selected_item = -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -766,7 +766,7 @@ int control_config_clear_other()
|
||||
config_item_undo *ptr;
|
||||
|
||||
if (Selected_line < 0) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -776,7 +776,7 @@ int control_config_clear_other()
|
||||
|
||||
z &= ~JOY_AXIS;
|
||||
if (Axis_map_to[z] < 0) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -787,7 +787,7 @@ int control_config_clear_other()
|
||||
}
|
||||
|
||||
if (!total) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -808,7 +808,7 @@ int control_config_clear_other()
|
||||
}
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -820,12 +820,12 @@ int control_config_clear_other()
|
||||
}
|
||||
}
|
||||
if (!total) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((Control_config[z].joy_id < 0) && (Control_config[z].key_id < 0)) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -850,7 +850,7 @@ int control_config_clear_other()
|
||||
}
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -867,7 +867,7 @@ int control_config_clear_all()
|
||||
}
|
||||
|
||||
if (!total) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -888,7 +888,7 @@ int control_config_clear_all()
|
||||
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_RESET_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::RESET_PRESSED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -945,7 +945,7 @@ int control_config_do_reset()
|
||||
}
|
||||
|
||||
if (!total && !cycling_presets) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -981,7 +981,7 @@ int control_config_do_reset()
|
||||
|
||||
control_config_conflict_check();
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_RESET_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::RESET_PRESSED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1026,10 +1026,10 @@ void control_config_scroll_screen_up()
|
||||
}
|
||||
|
||||
Selected_item = -1;
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
|
||||
} else {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,10 +1042,10 @@ void control_config_scroll_line_up()
|
||||
}
|
||||
|
||||
Selected_item = -1;
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
|
||||
} else {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1059,10 +1059,10 @@ void control_config_scroll_screen_down()
|
||||
}
|
||||
|
||||
Selected_item = -1;
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
|
||||
} else {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1076,10 +1076,10 @@ void control_config_scroll_line_down()
|
||||
}
|
||||
|
||||
Selected_item = -1;
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
|
||||
} else {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,13 +1091,13 @@ void control_config_toggle_modifier(int bit)
|
||||
Assert(!(z & JOY_AXIS));
|
||||
k = Control_config[z].key_id;
|
||||
if (k < 0) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
control_config_bind_key(z, k ^ bit);
|
||||
control_config_conflict_check();
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
}
|
||||
|
||||
void control_config_toggle_invert()
|
||||
@@ -1118,7 +1118,7 @@ void control_config_do_bind()
|
||||
game_flush();
|
||||
// if ((Selected_line < 0) || (Cc_lines[Selected_line].cc_index & JOY_AXIS)) {
|
||||
if (Selected_line < 0) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1142,7 +1142,7 @@ void control_config_do_bind()
|
||||
Search_mode = 0;
|
||||
Last_key = -1;
|
||||
Axis_override = -1;
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
}
|
||||
|
||||
void control_config_do_search()
|
||||
@@ -1166,7 +1166,7 @@ void control_config_do_search()
|
||||
Binding_mode = 0;
|
||||
Search_mode = 1;
|
||||
Last_key = -1;
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
}
|
||||
|
||||
void control_config_do_cancel(int fail = 0)
|
||||
@@ -1189,9 +1189,9 @@ void control_config_do_cancel(int fail = 0)
|
||||
|
||||
Binding_mode = Search_mode = 0;
|
||||
if (fail){
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
} else {
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1206,13 +1206,13 @@ int control_config_accept()
|
||||
}
|
||||
|
||||
if (i < NUM_TABS) {
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
|
||||
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
|
||||
gamesnd_play_iface(SND_COMMIT_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1237,7 +1237,7 @@ void control_config_button_pressed(int n)
|
||||
Tab = n;
|
||||
Scroll_offset = Selected_line = 0;
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
|
||||
break;
|
||||
|
||||
case BIND_BUTTON:
|
||||
@@ -1250,17 +1250,17 @@ void control_config_button_pressed(int n)
|
||||
|
||||
case SHIFT_TOGGLE:
|
||||
control_config_toggle_modifier(KEY_SHIFTED);
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
break;
|
||||
|
||||
case ALT_TOGGLE:
|
||||
control_config_toggle_modifier(KEY_ALTED);
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
break;
|
||||
|
||||
case INVERT_AXIS:
|
||||
control_config_toggle_invert();
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
break;
|
||||
|
||||
case SCROLL_UP_BUTTON:
|
||||
@@ -1281,7 +1281,7 @@ void control_config_button_pressed(int n)
|
||||
|
||||
case HELP_BUTTON:
|
||||
launch_context_help();
|
||||
gamesnd_play_iface(SND_HELP_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::HELP_PRESSED);
|
||||
break;
|
||||
|
||||
case RESET_BUTTON:
|
||||
@@ -1799,7 +1799,7 @@ void control_config_do_frame(float frametime)
|
||||
|
||||
Scroll_offset = Selected_line = 0;
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
|
||||
break;
|
||||
|
||||
case KEY_TAB: // activate next tab
|
||||
@@ -1810,7 +1810,7 @@ void control_config_do_frame(float frametime)
|
||||
|
||||
Scroll_offset = Selected_line = 0;
|
||||
control_config_list_prepare();
|
||||
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
|
||||
break;
|
||||
|
||||
case KEY_LEFT:
|
||||
@@ -1825,7 +1825,7 @@ void control_config_do_frame(float frametime)
|
||||
}
|
||||
}
|
||||
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
break;
|
||||
|
||||
case KEY_RIGHT:
|
||||
@@ -1837,7 +1837,7 @@ void control_config_do_frame(float frametime)
|
||||
} else if (Selected_item > 1) {
|
||||
Selected_item = -1;
|
||||
}
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
break;
|
||||
|
||||
case KEY_BACKSP: // undo
|
||||
@@ -1873,7 +1873,7 @@ void control_config_do_frame(float frametime)
|
||||
Selected_item = 1;
|
||||
}
|
||||
|
||||
gamesnd_play_iface(SND_USER_SELECT);
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
}
|
||||
|
||||
if (List_buttons[i].double_clicked()) {
|
||||
@@ -2379,7 +2379,7 @@ void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr)
|
||||
|
||||
*ta = 0;
|
||||
if (Axis_map_to[3] >= 0) {
|
||||
*ta = joy_get_unscaled_reading(axes_values[Axis_map_to[3]], Axis_map_to[3]);
|
||||
*ta = joy_get_unscaled_reading(axes_values[Axis_map_to[3]]);
|
||||
}
|
||||
|
||||
*tr = 0;
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "controlconfig/controlsconfig.h"
|
||||
@@ -201,7 +201,7 @@ config_item Control_config[CCFG_MAX + 1] = {
|
||||
|
||||
const char *Scan_code_text_german[] = {
|
||||
"", "Esc", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab",
|
||||
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab", // NOLINT
|
||||
"Q", "W", "E", "R", "T", "Z", "U", "I",
|
||||
"O", "P", "\x9A", "+", "Eingabe", "Strg Links", "A", "S",
|
||||
|
||||
@@ -251,8 +251,8 @@ const char *Joy_button_text_german[] = {
|
||||
};
|
||||
|
||||
const char *Scan_code_text_french[] = {
|
||||
"", "\x90""chap", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0", "-", "=", "Fl\x82""che Ret.", "Tab",
|
||||
"", "\x90""chap", "1", "2", "3", "4", "5", "6", // NOLINT
|
||||
"7", "8", "9", "0", "-", "=", "Fl\x82""che Ret.", "Tab", // NOLINT
|
||||
"Q", "W", "E", "R", "T", "Y", "U", "I",
|
||||
"O", "P", "[", "]", "Entr\x82""e", "Ctrl Gauche", "A", "S",
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ class Decoder {
|
||||
* @brief Returns the properties of the video
|
||||
* @return The properties
|
||||
*/
|
||||
virtual MovieProperties getProperties() = 0;
|
||||
virtual MovieProperties getProperties() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Starts decoding the video
|
||||
@@ -116,9 +116,9 @@ class Decoder {
|
||||
* @brief Determines if the video has audio
|
||||
* @return @c true if audio is included in the video
|
||||
*/
|
||||
virtual bool hasAudio() = 0;
|
||||
virtual bool hasAudio() const = 0;
|
||||
|
||||
virtual bool hasSubtitles() = 0;
|
||||
virtual bool hasSubtitles() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Ends decoding of the video file
|
||||
|
||||
+12
-12
@@ -286,10 +286,10 @@ void cutscenes_screen_scroll_line_up()
|
||||
if (Selected_line)
|
||||
{
|
||||
Selected_line--;
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
|
||||
} else
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
|
||||
if (Selected_line < Scroll_offset)
|
||||
Scroll_offset = Selected_line;
|
||||
@@ -302,10 +302,10 @@ void cutscenes_screen_scroll_line_down()
|
||||
if (Selected_line < (int) Cutscene_list.size() - 1)
|
||||
{
|
||||
Selected_line++;
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
|
||||
} else
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
|
||||
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
|
||||
if (Selected_line >= Scroll_offset + h)
|
||||
@@ -328,11 +328,11 @@ void cutscenes_screen_scroll_screen_up()
|
||||
Selected_line--;
|
||||
}
|
||||
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
|
||||
} else
|
||||
{
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,10 +349,10 @@ void cutscenes_screen_scroll_screen_down()
|
||||
Selected_line = Scroll_offset;
|
||||
}
|
||||
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
||||
} else
|
||||
{
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,17 +361,17 @@ int cutscenes_screen_button_pressed(int n)
|
||||
switch (n)
|
||||
{
|
||||
case TECH_DATABASE_BUTTON:
|
||||
gamesnd_play_iface(SND_SWITCH_SCREENS);
|
||||
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
||||
gameseq_post_event(GS_EVENT_TECH_MENU);
|
||||
return 1;
|
||||
|
||||
case SIMULATOR_BUTTON:
|
||||
gamesnd_play_iface(SND_SWITCH_SCREENS);
|
||||
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
||||
gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
|
||||
return 1;
|
||||
|
||||
case CREDITS_BUTTON:
|
||||
gamesnd_play_iface(SND_SWITCH_SCREENS);
|
||||
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
||||
gameseq_post_event(GS_EVENT_CREDITS);
|
||||
return 1;
|
||||
|
||||
@@ -388,7 +388,7 @@ int cutscenes_screen_button_pressed(int n)
|
||||
break;
|
||||
|
||||
case EXIT_BUTTON:
|
||||
gamesnd_play_iface(SND_COMMIT_PRESSED);
|
||||
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
|
||||
gameseq_post_event(GS_EVENT_MAIN_MENU);
|
||||
game_flush();
|
||||
break;
|
||||
|
||||
@@ -55,6 +55,9 @@ int resample_convert(SwrContext* ctx, uint8_t** output,
|
||||
#ifdef WITH_LIBAV
|
||||
return avresample_convert(ctx, output, out_plane_size, out_samples, input, in_plane_size, in_samples);
|
||||
#else
|
||||
(void)out_plane_size;
|
||||
(void)in_plane_size;
|
||||
|
||||
return swr_convert(ctx, output, out_samples, (const uint8_t**) input, in_samples);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ class AudioDecoder: public FFMPEGStreamDecoder<AudioFrame> {
|
||||
public:
|
||||
explicit AudioDecoder(DecoderStatus* status);
|
||||
|
||||
virtual ~AudioDecoder();
|
||||
~AudioDecoder() override;
|
||||
|
||||
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
|
||||
void decodePacket(AVPacket* packet) override;
|
||||
|
||||
virtual void finishDecoding() SCP_OVERRIDE;
|
||||
void finishDecoding() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "cutscene/ffmpeg/VideoDecoder.h"
|
||||
#include "cutscene/ffmpeg/SubtitleDecoder.h"
|
||||
|
||||
#include "FFMPEGDecoder.h"
|
||||
#include "localization/localize.h"
|
||||
|
||||
using namespace libs::ffmpeg;
|
||||
@@ -39,6 +40,8 @@ const char* CHECKED_EXTENSIONS[] = {
|
||||
"mve"
|
||||
};
|
||||
|
||||
const char *CHECKED_SUBT_EXTENSIONS[] = {"srt"};
|
||||
|
||||
double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
|
||||
auto fps = av_q2d(av_stream_get_r_frame_rate(stream));
|
||||
|
||||
@@ -55,48 +58,48 @@ double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
|
||||
return fps;
|
||||
}
|
||||
|
||||
CodecContextParameters getCodecParameters(AVStream* stream) {
|
||||
CodecContextParameters getCodecParameters(AVStream *stream) {
|
||||
CodecContextParameters paras;
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
|
||||
paras.width = stream->codecpar->width;
|
||||
paras.height = stream->codecpar->height;
|
||||
paras.width = stream->codecpar->width;
|
||||
paras.height = stream->codecpar->height;
|
||||
paras.pixel_format = (AVPixelFormat)stream->codecpar->format;
|
||||
|
||||
paras.channel_layout = stream->codecpar->channel_layout;
|
||||
paras.sample_rate = stream->codecpar->sample_rate;
|
||||
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
|
||||
paras.sample_rate = stream->codecpar->sample_rate;
|
||||
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
|
||||
|
||||
paras.codec_id = stream->codecpar->codec_id;
|
||||
paras.codec_id = stream->codecpar->codec_id;
|
||||
#else
|
||||
paras.width = stream->codec->width;
|
||||
paras.height = stream->codec->height;
|
||||
paras.width = stream->codec->width;
|
||||
paras.height = stream->codec->height;
|
||||
paras.pixel_format = stream->codec->pix_fmt;
|
||||
|
||||
paras.channel_layout = stream->codec->channel_layout;
|
||||
paras.sample_rate = stream->codec->sample_rate;
|
||||
paras.audio_format = stream->codec->sample_fmt;
|
||||
paras.sample_rate = stream->codec->sample_rate;
|
||||
paras.audio_format = stream->codec->sample_fmt;
|
||||
|
||||
paras.codec_id = stream->codec->codec_id;
|
||||
paras.codec_id = stream->codec->codec_id;
|
||||
#endif
|
||||
return paras;
|
||||
return paras;
|
||||
}
|
||||
|
||||
SCP_string normalizeLanguage(const char* langauge_name) {
|
||||
if (!stricmp(langauge_name, "eng")) {
|
||||
return "English";
|
||||
}
|
||||
if (!stricmp(langauge_name, "ger")) {
|
||||
return "German";
|
||||
}
|
||||
if (!stricmp(langauge_name, "spa")) {
|
||||
return "Spanish";
|
||||
}
|
||||
SCP_string normalizeLanguage(const char *langauge_name) {
|
||||
if (!stricmp(langauge_name, "eng")) {
|
||||
return "English";
|
||||
}
|
||||
if (!stricmp(langauge_name, "ger")) {
|
||||
return "German";
|
||||
}
|
||||
if (!stricmp(langauge_name, "spa")) {
|
||||
return "Spanish";
|
||||
}
|
||||
|
||||
// Print to log so that we can find the actual value more easily later
|
||||
mprintf(("FFmpeg log: Found unknown language value '%s'!\n", langauge_name));
|
||||
// Print to log so that we can find the actual value more easily later
|
||||
mprintf(("FFmpeg log: Found unknown language value '%s'!\n", langauge_name));
|
||||
|
||||
// Default to english for everything else
|
||||
return "English";
|
||||
// Default to english for everything else
|
||||
return "English";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +146,8 @@ std::unique_ptr<InputStream> openStream(const SCP_string& name) {
|
||||
return input;
|
||||
}
|
||||
|
||||
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream) {
|
||||
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &stream,
|
||||
std::unique_ptr<InputStream> &subt) {
|
||||
std::unique_ptr<DecoderStatus> status(new DecoderStatus());
|
||||
|
||||
auto ctx = stream->m_ctx->ctx();
|
||||
@@ -165,7 +169,7 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
|
||||
if (audioStream < 0) {
|
||||
if (audioStream == AVERROR_STREAM_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: No audio stream found in file!\n"));
|
||||
} else if (videoStream == AVERROR_DECODER_NOT_FOUND) {
|
||||
} else if (audioStream == AVERROR_DECODER_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: Codec for audio stream could not be found!\n"));
|
||||
} else {
|
||||
mprintf(("FFmpeg: Unknown error while finding audio stream!\n"));
|
||||
@@ -180,26 +184,50 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
|
||||
status->audioStream = ctx->streams[audioStream];
|
||||
}
|
||||
|
||||
auto& current_language = Lcl_languages[Lcl_current_lang];
|
||||
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
|
||||
auto test_stream = ctx->streams[i];
|
||||
if (subt) {
|
||||
auto subtCtx = subt->m_ctx->ctx();
|
||||
|
||||
auto& pars = test_stream->codecpar;
|
||||
|
||||
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
|
||||
continue;
|
||||
}
|
||||
AVDictionaryEntry* tag = nullptr;
|
||||
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
|
||||
continue;
|
||||
auto subtStream = av_find_best_stream(subtCtx, AVMEDIA_TYPE_SUBTITLE, -1, -1, nullptr, 0);
|
||||
if (subtStream < 0) {
|
||||
if (subtStream == AVERROR_STREAM_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: No subtitle stream found in subtitle file!\n"));
|
||||
} else if (subtStream == AVERROR_DECODER_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: Codec for subtitle stream could not be found!\n"));
|
||||
} else {
|
||||
mprintf(("FFmpeg: Unknown error while finding subtitle stream!\n"));
|
||||
}
|
||||
} else {
|
||||
status->subtitleStream = subtCtx->streams[subtStream];
|
||||
status->externalSubtitles = true;
|
||||
status->subtitleStreamIndex = subtStream;
|
||||
}
|
||||
}
|
||||
|
||||
auto normalized_language = normalizeLanguage(tag->value);
|
||||
if (status->subtitleStream == nullptr) {
|
||||
// We don't have an external subtitle stream or loading from that file has failed
|
||||
auto ¤t_language = Lcl_languages[Lcl_current_lang];
|
||||
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
|
||||
auto test_stream = ctx->streams[i];
|
||||
|
||||
if (!stricmp(normalized_language.c_str(), current_language.lang_name)) {
|
||||
status->subtitleStreamIndex = i;
|
||||
status->subtitleStream = test_stream;
|
||||
break;
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
|
||||
auto &pars = test_stream->codecpar;
|
||||
|
||||
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
AVDictionaryEntry *tag = nullptr;
|
||||
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto normalized_language = normalizeLanguage(tag->value);
|
||||
|
||||
if (!stricmp(normalized_language.c_str(), current_language.lang_name)) {
|
||||
status->subtitleStreamIndex = i;
|
||||
status->subtitleStream = test_stream;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,36 +289,37 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
|
||||
status->audioCodec->name ? status->audioCodec->name : "<Unknown>"));
|
||||
}
|
||||
|
||||
if (status->subtitleStreamIndex >= 0) {
|
||||
// Not really sure if this makes sense for subtitles but it shouldn't break anything...
|
||||
status->subtitleCodecPars = getCodecParameters(status->subtitleStream);
|
||||
if (status->subtitleStream != nullptr) {
|
||||
// Not really sure if this makes sense for subtitles but it shouldn't break anything...
|
||||
status->subtitleCodecPars = getCodecParameters(status->subtitleStream);
|
||||
|
||||
status->subtitleCodec = avcodec_find_decoder(status->subtitleCodecPars.codec_id);
|
||||
status->subtitleCodec = avcodec_find_decoder(status->subtitleCodecPars.codec_id);
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
|
||||
status->subtitleCodecCtx = avcodec_alloc_context3(status->subtitleCodec);
|
||||
status->subtitleCodecCtx = avcodec_alloc_context3(status->subtitleCodec);
|
||||
|
||||
err = avcodec_parameters_to_context(status->subtitleCodecCtx, status->subtitleStream->codecpar);
|
||||
if (err < 0) {
|
||||
char errorStr[512];
|
||||
av_strerror(err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
|
||||
return nullptr;
|
||||
}
|
||||
err = avcodec_parameters_to_context(status->subtitleCodecCtx, status->subtitleStream->codecpar);
|
||||
if (err < 0) {
|
||||
char errorStr[512];
|
||||
av_strerror(err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
status->subtitleCodecCtx = status->subtitleStream->codec;
|
||||
status->subtitleCodecCtx = status->subtitleStream->codec;
|
||||
#endif
|
||||
|
||||
err = avcodec_open2(status->subtitleCodecCtx, status->subtitleCodec, nullptr);
|
||||
if (err < 0) {
|
||||
char errorStr[512];
|
||||
av_strerror(err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to open subtitle codec! Error: %s\n", errorStr));
|
||||
}
|
||||
err = avcodec_open2(status->subtitleCodecCtx, status->subtitleCodec, nullptr);
|
||||
if (err < 0) {
|
||||
char errorStr[512];
|
||||
av_strerror(err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to open subtitle codec! Error: %s\n", errorStr));
|
||||
}
|
||||
|
||||
mprintf(("FFmpeg: Using subtitle codec %s (%s).\n", status->subtitleCodec->long_name ? status->subtitleCodec->long_name : "<Unknown>",
|
||||
status->subtitleCodec->name ? status->subtitleCodec->name : "<Unknown>"));
|
||||
}
|
||||
mprintf(("FFmpeg: Using subtitle codec %s (%s).\n",
|
||||
status->subtitleCodec->long_name ? status->subtitleCodec->long_name : "<Unknown>",
|
||||
status->subtitleCodec->name ? status->subtitleCodec->name : "<Unknown>"));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -310,6 +339,27 @@ std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string &name) {
|
||||
auto ¤t_language = Lcl_languages[Lcl_current_lang];
|
||||
|
||||
for (auto ext : CHECKED_SUBT_EXTENSIONS) {
|
||||
SCP_string fileName;
|
||||
if (strlen(current_language.lang_ext) == 0) {
|
||||
fileName = name + "." + ext;
|
||||
} else {
|
||||
fileName = name + "-" + current_language.lang_ext + "." + ext;
|
||||
}
|
||||
|
||||
auto input = openStream(fileName);
|
||||
|
||||
if (input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
|
||||
@@ -329,8 +379,10 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto subt = openSubtitleStream(movieName);
|
||||
|
||||
// We now have a valid input stream, try to find the correct streams
|
||||
auto status = initializeStatus(input);
|
||||
auto status = initializeStatus(input, subt);
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
@@ -340,11 +392,12 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
|
||||
|
||||
// We're done, now just put the pointer into this
|
||||
std::swap(m_input, input);
|
||||
std::swap(m_subtitleInput, subt);
|
||||
std::swap(m_status, status);
|
||||
return true;
|
||||
}
|
||||
|
||||
MovieProperties FFMPEGDecoder::getProperties() {
|
||||
MovieProperties FFMPEGDecoder::getProperties() const {
|
||||
MovieProperties props;
|
||||
props.size.width = static_cast<size_t>(m_status->videoCodecPars.width);
|
||||
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
|
||||
@@ -358,14 +411,22 @@ void FFMPEGDecoder::startDecoding() {
|
||||
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
|
||||
|
||||
std::unique_ptr<AudioDecoder> audioDecoder;
|
||||
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
|
||||
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
|
||||
|
||||
if (hasAudio()) {
|
||||
audioDecoder.reset(new AudioDecoder(m_status.get()));
|
||||
}
|
||||
if (hasSubtitles()) {
|
||||
subtitleDecoder.reset(new SubtitleDecoder(m_status.get()));
|
||||
}
|
||||
if (hasSubtitles()) {
|
||||
subtitleDecoder.reset(new SubtitleDecoder(m_status.get()));
|
||||
}
|
||||
|
||||
std::unique_ptr<std::thread> subtitle_thread;
|
||||
if (hasExternalSubtitle()) {
|
||||
// Start a new thread for the subtitles since otherwise we would need to make sure that neither of the input
|
||||
// streames starves while the other waits for more space in the queues
|
||||
subtitle_thread.reset(
|
||||
new std::thread([this, &subtitleDecoder]() { runSubtitleDecoder(subtitleDecoder.get()); }));
|
||||
}
|
||||
|
||||
auto ctx = m_input->m_ctx->ctx();
|
||||
AVPacket packet;
|
||||
@@ -373,13 +434,13 @@ void FFMPEGDecoder::startDecoding() {
|
||||
auto read_err = av_read_frame(ctx, &packet);
|
||||
AVPacketScope scope(&packet);
|
||||
|
||||
if (avio_feof(ctx->pb) != 0) {
|
||||
// EOF!!
|
||||
break;
|
||||
} else if (read_err < 0) {
|
||||
if (read_err < 0) {
|
||||
if (read_err == AVERROR_EOF) {
|
||||
// Finished reading -> break out of loop
|
||||
break;
|
||||
} else if (avio_feof(ctx->pb) != 0) {
|
||||
// Also EOF!
|
||||
break;
|
||||
} else {
|
||||
// Some kind of other error, try to continue reading
|
||||
char errorStr[512];
|
||||
@@ -406,13 +467,13 @@ void FFMPEGDecoder::startDecoding() {
|
||||
pushAudioData(std::move(ptr));
|
||||
}
|
||||
} else if (subtitleDecoder && packet.stream_index == m_status->subtitleStreamIndex) {
|
||||
subtitleDecoder->decodePacket(&packet);
|
||||
subtitleDecoder->decodePacket(&packet);
|
||||
|
||||
SubtitleFramePtr ptr;
|
||||
while((ptr = subtitleDecoder->getFrame()) != nullptr) {
|
||||
pushSubtitleData(std::move(ptr));
|
||||
}
|
||||
}
|
||||
SubtitleFramePtr ptr;
|
||||
while ((ptr = subtitleDecoder->getFrame()) != nullptr) {
|
||||
pushSubtitleData(std::move(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDecoding()) {
|
||||
@@ -432,16 +493,18 @@ void FFMPEGDecoder::startDecoding() {
|
||||
}
|
||||
}
|
||||
|
||||
if (subtitle_thread) {
|
||||
subtitle_thread->join();
|
||||
}
|
||||
|
||||
stopDecoder();
|
||||
}
|
||||
|
||||
bool FFMPEGDecoder::hasAudio() {
|
||||
return m_status->audioStreamIndex >= 0;
|
||||
}
|
||||
bool FFMPEGDecoder::hasAudio() const { return m_status->audioStreamIndex >= 0; }
|
||||
|
||||
bool FFMPEGDecoder::hasSubtitles() {
|
||||
return m_status->subtitleStreamIndex >= 0;
|
||||
}
|
||||
bool FFMPEGDecoder::hasSubtitles() const { return m_status->subtitleStream != nullptr; }
|
||||
|
||||
bool FFMPEGDecoder::hasExternalSubtitle() const { return m_status->externalSubtitles; }
|
||||
|
||||
void FFMPEGDecoder::close() {
|
||||
if (m_status) {
|
||||
@@ -452,6 +515,55 @@ void FFMPEGDecoder::close() {
|
||||
// This will delete the InputStream pointer and free all data
|
||||
m_input = nullptr;
|
||||
}
|
||||
|
||||
if (m_subtitleInput) {
|
||||
m_subtitleInput = nullptr;
|
||||
}
|
||||
}
|
||||
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder *decoder) {
|
||||
auto ctx = m_subtitleInput->m_ctx->ctx();
|
||||
AVPacket packet;
|
||||
|
||||
while (isDecoding()) {
|
||||
auto read_err = av_read_frame(ctx, &packet);
|
||||
AVPacketScope scope(&packet);
|
||||
|
||||
if (read_err < 0) {
|
||||
if (read_err == AVERROR_EOF) {
|
||||
// Finished reading -> break out of loop
|
||||
break;
|
||||
} else if (avio_feof(ctx->pb) != 0) {
|
||||
// Also EOF!
|
||||
break;
|
||||
} else {
|
||||
// Some kind of other error, try to continue reading
|
||||
char errorStr[512];
|
||||
av_strerror(read_err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to read frame! Error: %s\n", errorStr));
|
||||
|
||||
// Skip packet
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.stream_index == m_status->subtitleStreamIndex) {
|
||||
decoder->decodePacket(&packet);
|
||||
|
||||
SubtitleFramePtr ptr;
|
||||
while ((ptr = decoder->getFrame()) != nullptr) {
|
||||
pushSubtitleData(std::move(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isDecoding()) {
|
||||
// If we are still alive then read the last frames from the decoders
|
||||
decoder->finishDecoding();
|
||||
|
||||
SubtitleFramePtr ptr;
|
||||
while ((ptr = decoder->getFrame()) != nullptr) {
|
||||
pushSubtitleData(std::move(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,28 +8,36 @@ struct InputStream;
|
||||
|
||||
struct DecoderStatus;
|
||||
|
||||
class SubtitleDecoder;
|
||||
|
||||
class FFMPEGDecoder: public Decoder {
|
||||
private:
|
||||
std::unique_ptr<InputStream> m_input;
|
||||
|
||||
std::unique_ptr<InputStream> m_subtitleInput;
|
||||
|
||||
std::unique_ptr<DecoderStatus> m_status;
|
||||
|
||||
public:
|
||||
bool hasExternalSubtitle() const;
|
||||
|
||||
void runSubtitleDecoder(SubtitleDecoder *decoder);
|
||||
|
||||
public:
|
||||
FFMPEGDecoder();
|
||||
|
||||
virtual ~FFMPEGDecoder();
|
||||
~FFMPEGDecoder() override;
|
||||
|
||||
bool initialize(const SCP_string& fileName) SCP_OVERRIDE;
|
||||
bool initialize(const SCP_string& fileName) override;
|
||||
|
||||
MovieProperties getProperties() SCP_OVERRIDE;
|
||||
MovieProperties getProperties() const override;
|
||||
|
||||
void startDecoding() SCP_OVERRIDE;
|
||||
void startDecoding() override;
|
||||
|
||||
bool hasAudio() SCP_OVERRIDE;
|
||||
bool hasAudio() const override;
|
||||
|
||||
bool hasSubtitles() SCP_OVERRIDE;
|
||||
bool hasSubtitles() const override;
|
||||
|
||||
void close() SCP_OVERRIDE;
|
||||
void close() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,25 @@ void SubtitleDecoder::decodePacket(AVPacket* packet) {
|
||||
}
|
||||
}
|
||||
void SubtitleDecoder::finishDecoding() {
|
||||
// Handle those decoders that have a delay
|
||||
AVPacket nullPacket;
|
||||
memset(&nullPacket, 0, sizeof(nullPacket));
|
||||
nullPacket.data = nullptr;
|
||||
nullPacket.size = 0;
|
||||
|
||||
AVSubtitle subtitle;
|
||||
while (true) {
|
||||
int finishedFrame = 1;
|
||||
auto err = avcodec_decode_subtitle2(m_status->subtitleCodecCtx, &subtitle, &finishedFrame, &nullPacket);
|
||||
|
||||
if (err < 0 || !finishedFrame) {
|
||||
break;
|
||||
}
|
||||
|
||||
pushSubtitleFrame(&nullPacket, &subtitle);
|
||||
|
||||
avsubtitle_free(&subtitle);
|
||||
}
|
||||
}
|
||||
void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle) {
|
||||
if (subtitle->format != 1) {
|
||||
|
||||
@@ -10,11 +10,11 @@ class SubtitleDecoder: public FFMPEGStreamDecoder<SubtitleFrame> {
|
||||
public:
|
||||
explicit SubtitleDecoder(DecoderStatus* status);
|
||||
|
||||
virtual ~SubtitleDecoder();
|
||||
~SubtitleDecoder() override;
|
||||
|
||||
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
|
||||
void decodePacket(AVPacket* packet) override;
|
||||
|
||||
virtual void finishDecoding() SCP_OVERRIDE;
|
||||
void finishDecoding() override;
|
||||
void pushSubtitleFrame(AVPacket* subtitle, AVSubtitle* pSubtitle);
|
||||
};
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ class FFMPEGVideoFrame: public VideoFrame {
|
||||
FFMPEGVideoFrame() : frame(nullptr) {
|
||||
}
|
||||
|
||||
virtual ~FFMPEGVideoFrame() {
|
||||
~FFMPEGVideoFrame() override {
|
||||
if (frame != nullptr) {
|
||||
av_freep(&frame->data[0]);
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
virtual DataPointers getDataPointers() {
|
||||
DataPointers getDataPointers() override {
|
||||
DataPointers ptrs;
|
||||
ptrs.y = frame->data[0];
|
||||
ptrs.u = frame->data[1];
|
||||
|
||||
@@ -15,11 +15,11 @@ class VideoDecoder: public FFMPEGStreamDecoder<VideoFrame> {
|
||||
public:
|
||||
explicit VideoDecoder(DecoderStatus* status);
|
||||
|
||||
virtual ~VideoDecoder();
|
||||
~VideoDecoder() override;
|
||||
|
||||
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
|
||||
void decodePacket(AVPacket* packet) override;
|
||||
|
||||
virtual void finishDecoding() SCP_OVERRIDE;
|
||||
void finishDecoding() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ struct DecoderStatus {
|
||||
AVCodec* audioCodec = nullptr;
|
||||
AVCodecContext* audioCodecCtx = nullptr;
|
||||
|
||||
// Subtitles are a bit different since they max come from a different file
|
||||
bool externalSubtitles = false;
|
||||
int subtitleStreamIndex = -1;
|
||||
AVStream* subtitleStream = nullptr;
|
||||
CodecContextParameters subtitleCodecPars;
|
||||
|
||||
@@ -74,7 +74,7 @@ static void debris_start_death_roll(object *debris_obj, debris *debris_p)
|
||||
|
||||
// only play debris destroy sound if hull piece and it has been around for at least 2 seconds
|
||||
if ( Missiontime > debris_p->time_started + 2*F1_0 ) {
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_MISSILE_IMPACT1), &debris_obj->pos, &View_position, debris_obj->radius );
|
||||
snd_play_3d( gamesnd_get_game_sound(gamesnd_id(GameSounds::MISSILE_IMPACT1)), &debris_obj->pos, &View_position, debris_obj->radius );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ void debris_process_post(object * obj, float frame_time)
|
||||
radar_plot_object( obj );
|
||||
|
||||
if ( timestamp_elapsed(db->sound_delay) ) {
|
||||
obj_snd_assign(objnum, SND_DEBRIS, &vmd_zero_vector, 0);
|
||||
obj_snd_assign(objnum, GameSounds::DEBRIS, &vmd_zero_vector, 0);
|
||||
db->sound_delay = 0;
|
||||
}
|
||||
} else {
|
||||
@@ -324,19 +324,19 @@ void debris_process_post(object * obj, float frame_time)
|
||||
//Play a sound effect
|
||||
if ( lifetime > 750 ) {
|
||||
// 1.00 second effect
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_05), &snd_pos, &View_position, obj->radius );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_05), &snd_pos, &View_position, obj->radius );
|
||||
} else if ( lifetime > 500 ) {
|
||||
// 0.75 second effect
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_04), &snd_pos, &View_position, obj->radius );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_04), &snd_pos, &View_position, obj->radius );
|
||||
} else if ( lifetime > 250 ) {
|
||||
// 0.50 second effect
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_03), &snd_pos, &View_position, obj->radius );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_03), &snd_pos, &View_position, obj->radius );
|
||||
} else if ( lifetime > 100 ) {
|
||||
// 0.25 second effect
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_02), &snd_pos, &View_position, obj->radius );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_02), &snd_pos, &View_position, obj->radius );
|
||||
} else {
|
||||
// 0.10 second effect
|
||||
snd_play_3d( gamesnd_get_game_sound(SND_DEBRIS_ARC_01), &snd_pos, &View_position, obj->radius );
|
||||
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_01), &snd_pos, &View_position, obj->radius );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -693,7 +693,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
* Alas, poor debris_obj got whacked. Fortunately, we know who did it, where and how hard, so we
|
||||
* can do something about it.
|
||||
*/
|
||||
void debris_hit(object *debris_obj, object *other_obj, vec3d *hitpos, float damage)
|
||||
void debris_hit(object *debris_obj, object * /*other_obj*/, vec3d *hitpos, float damage)
|
||||
{
|
||||
debris *debris_p = &Debris[debris_obj->instance];
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ void dc_do_command(SCP_string *cmd_str)
|
||||
try {
|
||||
dc_commands[i]->func(); // Run the command!
|
||||
|
||||
} catch (errParseString err) {
|
||||
} catch (const errParseString& err) {
|
||||
dc_printf("Require string(s) not found: \n");
|
||||
for (uint j = 0; j < err.expected_tokens.size(); ++j) {
|
||||
dc_printf("%i: %s\n", j, err.expected_tokens[j].c_str());
|
||||
@@ -170,7 +170,7 @@ void dc_do_command(SCP_string *cmd_str)
|
||||
|
||||
dc_printf("Found '%s' instead\n", err.found_token.c_str());
|
||||
|
||||
} catch (errParse err) {
|
||||
} catch (const errParse& err) {
|
||||
dc_printf("Invalid argument. Expected %s, found '%s'\n", token_str[err.expected_type], err.found_token.c_str());
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <limits.h>
|
||||
#include <climits>
|
||||
|
||||
|
||||
// ========================= LOCALS =========================
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
#include <nebula/neb.h>
|
||||
#include <utility>
|
||||
#include "decals/decals.h"
|
||||
|
||||
#include "graphics/2d.h"
|
||||
#include "graphics/decal_draw_list.h"
|
||||
#include "graphics/util/uniform_structs.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "tracing/tracing.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class DecalDefinition {
|
||||
SCP_string _name;
|
||||
|
||||
SCP_string _diffuseFilename;
|
||||
bool _loopDiffuse = true;
|
||||
|
||||
SCP_string _glowFilename;
|
||||
bool _loopGlow = true;
|
||||
|
||||
SCP_string _normalMapFilename;
|
||||
bool _loopNormal = true;
|
||||
|
||||
int _diffuseBitmap = -1;
|
||||
int _glowBitmap = -1;
|
||||
int _normalBitmap = -1;
|
||||
|
||||
public:
|
||||
explicit DecalDefinition(SCP_string name) : _name(std::move(name)) {
|
||||
}
|
||||
|
||||
~DecalDefinition() {
|
||||
if (_diffuseBitmap >= 0) {
|
||||
bm_release(_diffuseBitmap);
|
||||
}
|
||||
if (_glowBitmap >= 0) {
|
||||
bm_release(_glowBitmap);
|
||||
}
|
||||
if (_normalBitmap >= 0) {
|
||||
bm_release(_normalBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
// Disallow copying
|
||||
DecalDefinition(const DecalDefinition&) = delete;
|
||||
DecalDefinition& operator=(const DecalDefinition&) = delete;
|
||||
|
||||
// Move constructor and operator
|
||||
DecalDefinition(DecalDefinition&& other) SCP_NOEXCEPT {
|
||||
*this = std::move(other); // Use operator implementation
|
||||
}
|
||||
DecalDefinition& operator=(DecalDefinition&& other) SCP_NOEXCEPT {
|
||||
std::swap(_name, other._name);
|
||||
|
||||
std::swap(_diffuseFilename, other._diffuseFilename);
|
||||
std::swap(_glowFilename, other._glowFilename);
|
||||
std::swap(_normalMapFilename, other._normalMapFilename);
|
||||
|
||||
std::swap(_diffuseBitmap, other._diffuseBitmap);
|
||||
std::swap(_glowBitmap, other._glowBitmap);
|
||||
std::swap(_normalBitmap, other._normalBitmap);
|
||||
|
||||
std::swap(_loopDiffuse, other._loopDiffuse);
|
||||
std::swap(_loopGlow, other._loopGlow);
|
||||
std::swap(_loopNormal, other._loopNormal);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void parse() {
|
||||
if (optional_string("+Diffuse:")) {
|
||||
stuff_string(_diffuseFilename, F_FILESPEC);
|
||||
|
||||
if (!bm_validate_filename(_diffuseFilename, true, true)) {
|
||||
error_display(0, "Animation '%s' is not valid!", _diffuseFilename.c_str());
|
||||
_diffuseFilename = "";
|
||||
}
|
||||
|
||||
if (optional_string("+Loop:")) {
|
||||
stuff_boolean(&_loopDiffuse);
|
||||
}
|
||||
}
|
||||
if (optional_string("+Glow:")) {
|
||||
stuff_string(_glowFilename, F_FILESPEC);
|
||||
|
||||
if (!bm_validate_filename(_glowFilename, true, true)) {
|
||||
error_display(0, "Animation '%s' is not valid!", _glowFilename.c_str());
|
||||
_glowFilename = "";
|
||||
}
|
||||
|
||||
if (optional_string("+Loop:")) {
|
||||
stuff_boolean(&_loopGlow);
|
||||
}
|
||||
}
|
||||
if (optional_string("+Normal:")) {
|
||||
stuff_string(_normalMapFilename, F_FILESPEC);
|
||||
|
||||
if (!bm_validate_filename(_normalMapFilename, true, true)) {
|
||||
error_display(0, "Animation '%s' is not valid!", _normalMapFilename.c_str());
|
||||
_normalMapFilename = "";
|
||||
}
|
||||
|
||||
if (optional_string("+Loop:")) {
|
||||
stuff_boolean(&_loopNormal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadBitmaps() {
|
||||
if (_diffuseBitmap == -1 && VALID_FNAME(_diffuseFilename)) {
|
||||
_diffuseBitmap = bm_load_either(_diffuseFilename.c_str());
|
||||
if (_diffuseBitmap == -1) {
|
||||
Warning(LOCATION,
|
||||
"Bitmap '%s' failed to load for decal definition %s!",
|
||||
_diffuseFilename.c_str(),
|
||||
_name.c_str());
|
||||
}
|
||||
}
|
||||
if (_glowBitmap == -1 && VALID_FNAME(_glowFilename)) {
|
||||
_glowBitmap = bm_load_either(_glowFilename.c_str());
|
||||
if (_glowBitmap == -1) {
|
||||
Warning(LOCATION,
|
||||
"Bitmap '%s' failed to load for decal definition %s!",
|
||||
_glowFilename.c_str(),
|
||||
_name.c_str());
|
||||
}
|
||||
}
|
||||
if (_normalBitmap == -1 && VALID_FNAME(_normalMapFilename)) {
|
||||
_normalBitmap = bm_load_either(_normalMapFilename.c_str());
|
||||
if (_normalBitmap == -1) {
|
||||
Warning(LOCATION,
|
||||
"Bitmap '%s' failed to load for decal definition %s!",
|
||||
_normalMapFilename.c_str(),
|
||||
_name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pageIn() {
|
||||
if (_diffuseBitmap >= 0) {
|
||||
bm_page_in_texture(_diffuseBitmap);
|
||||
}
|
||||
if (_glowBitmap >= 0) {
|
||||
bm_page_in_texture(_glowBitmap);
|
||||
}
|
||||
if (_normalBitmap >= 0) {
|
||||
bm_page_in_texture(_normalBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
bool bitmapsLoaded() {
|
||||
// Since both bitmap types are optional we need to check if either is loaded to determine if any bitmap is loaded
|
||||
return _diffuseBitmap >= 0 || _glowBitmap >= 0 || _normalBitmap >= 0;
|
||||
}
|
||||
|
||||
const SCP_string& getName() const {
|
||||
return _name;
|
||||
}
|
||||
int getDiffuseBitmap() const {
|
||||
return _diffuseBitmap;
|
||||
}
|
||||
int getGlowBitmap() const {
|
||||
return _glowBitmap;
|
||||
}
|
||||
int getNormalBitmap() const {
|
||||
return _normalBitmap;
|
||||
}
|
||||
bool isDiffuseLooping() const {
|
||||
return _loopDiffuse;
|
||||
}
|
||||
bool isGlowLooping() const {
|
||||
return _loopGlow;
|
||||
}
|
||||
bool isNormalLooping() const {
|
||||
return _loopNormal;
|
||||
}
|
||||
};
|
||||
|
||||
SCP_vector<DecalDefinition> decalDefinitions;
|
||||
|
||||
// Variable to indicate if the system is able to work correctly on the current system
|
||||
bool decal_system_active = true;
|
||||
|
||||
void parse_decals_table(const char* filename) {
|
||||
try {
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Decals");
|
||||
|
||||
while (optional_string("$Decal:")) {
|
||||
SCP_string name;
|
||||
stuff_string(name, F_NAME);
|
||||
|
||||
DecalDefinition def(name);
|
||||
def.parse();
|
||||
|
||||
decalDefinitions.push_back(std::move(def));
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
} catch (const parse::ParseException& e) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gr_is_capable(CAPABILITY_DEFERRED_LIGHTING)) {
|
||||
// we need deferred lighting
|
||||
decal_system_active = false;
|
||||
mprintf(("Note: Decal system has been disabled due to lack of deferred lighting.\n"));
|
||||
}
|
||||
if (!gr_is_capable(CAPABILITY_NORMAL_MAP)) {
|
||||
// We need normal mapping for the full feature range
|
||||
decal_system_active = false;
|
||||
mprintf(("Note: Decal system has been disabled due to lack of normal mapping.\n"));
|
||||
}
|
||||
if (!gr_is_capable(CAPABILITY_SEPARATE_BLEND_FUNCTIONS)) {
|
||||
// WWe need separate blending functions for different color buffers
|
||||
decal_system_active = false;
|
||||
mprintf(("Note: Decal system has been disabled due to lack of separate color buffer blend functions.\n"));
|
||||
}
|
||||
}
|
||||
|
||||
struct Decal {
|
||||
int definition_handle = -1;
|
||||
object_h object;
|
||||
int submodel = -1;
|
||||
|
||||
float creation_time = -1.0f; //!< The mission time at which this decal was created
|
||||
float lifetime = -1.0f; //!< The time this decal is active. When negative it never expires
|
||||
|
||||
vec3d position = vmd_zero_vector;
|
||||
vec3d scale;
|
||||
matrix orientation = vmd_identity_matrix;
|
||||
|
||||
Decal() {
|
||||
vm_vec_make(&scale, 1.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
if (!object.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lifetime > 0.0f) {
|
||||
if (f2fl(Missiontime) >= creation_time + lifetime) {
|
||||
// Decal has expired
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto objp = object.objp;
|
||||
if (objp->type == OBJ_SHIP) {
|
||||
auto shipp = &Ships[objp->instance];
|
||||
auto model_instance = model_get_instance(shipp->model_instance_num);
|
||||
|
||||
Assertion(submodel >= 0 && submodel < model_get(object_get_model(objp))->n_models,
|
||||
"Invalid submodel number detected!");
|
||||
auto smi = &model_instance->submodel[submodel];
|
||||
|
||||
if (smi->blown_off) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
SCP_vector<Decal> active_decals;
|
||||
|
||||
bool required_string_if_new(const char* token, bool new_entry) {
|
||||
if (!new_entry) {
|
||||
return optional_string(token) == 1;
|
||||
}
|
||||
|
||||
required_string(token);
|
||||
return true;
|
||||
}
|
||||
|
||||
float clamp(float x, float min, float max) {
|
||||
return std::min(std::max(x, min), max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Produces a smoothstep value as specified by the GLSL specification
|
||||
* @param edge0
|
||||
* @param edge1
|
||||
* @param x
|
||||
* @return
|
||||
*/
|
||||
float smoothstep(float edge0, float edge1, float x) {
|
||||
auto t = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
|
||||
return t * t * (3.0f - 2.0f * t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace decals {
|
||||
|
||||
void initialize() {
|
||||
decalDefinitions.clear();
|
||||
graphics::decal_draw_list::globalInit();
|
||||
|
||||
parse_modular_table(NOX("*-dcl.tbm"), parse_decals_table);
|
||||
}
|
||||
void shutdown() {
|
||||
graphics::decal_draw_list::globalShutdown();
|
||||
|
||||
// Free allocated resources
|
||||
decalDefinitions.clear();
|
||||
}
|
||||
|
||||
int getDecalConfig(const SCP_string& name) {
|
||||
int index = 0;
|
||||
for (auto& def : decalDefinitions) {
|
||||
if (!stricmp(def.getName().c_str(), name.c_str())) {
|
||||
return index;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
|
||||
SCP_string name;
|
||||
stuff_string(name, F_NAME);
|
||||
|
||||
auto decalRef = getDecalConfig(name);
|
||||
|
||||
if (decalRef < 0) {
|
||||
error_display(0, "Decal definition '%s' is unknown!", name.c_str());
|
||||
}
|
||||
dest_info.definition_handle = decalRef;
|
||||
|
||||
if (required_string_if_new("+Radius:", is_new_entry)) {
|
||||
stuff_float(&dest_info.radius);
|
||||
|
||||
if (dest_info.radius <= 0.0f) {
|
||||
error_display(0, "Invalid radius of %f! Must be a positive number.", dest_info.radius);
|
||||
dest_info.radius = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (required_string_if_new("+Lifetime:", is_new_entry)) {
|
||||
if (optional_string("Eternal")) {
|
||||
dest_info.lifetime = util::UniformFloatRange(-1.0f);
|
||||
} else {
|
||||
// Require at least a small lifetime so that the calculations don't have to deal with div-by-zero
|
||||
dest_info.lifetime = util::parseUniformRange(0.0001f);
|
||||
}
|
||||
}
|
||||
}
|
||||
void loadBitmaps(const creation_info& info) {
|
||||
if (!decal_system_active) {
|
||||
return;
|
||||
}
|
||||
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
|
||||
if (info.definition_handle < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
|
||||
"Invalid decal handle detected!");
|
||||
|
||||
auto& def = decalDefinitions[info.definition_handle];
|
||||
|
||||
def.loadBitmaps();
|
||||
}
|
||||
void pageInDecal(const creation_info& info) {
|
||||
if (!decal_system_active) {
|
||||
return;
|
||||
}
|
||||
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
|
||||
if (info.definition_handle < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
|
||||
"Invalid decal handle detected!");
|
||||
|
||||
decalDefinitions[info.definition_handle].pageIn();
|
||||
}
|
||||
|
||||
void initializeMission() {
|
||||
active_decals.clear();
|
||||
}
|
||||
|
||||
matrix4 getDecalTransform(Decal& decal) {
|
||||
Assertion(decal.object.objp->type == OBJ_SHIP, "Only ships are currently supported for decals!");
|
||||
|
||||
auto objp = decal.object.objp;
|
||||
auto ship = &Ships[objp->instance];
|
||||
|
||||
vec3d worldPos;
|
||||
model_instance_find_world_point(&worldPos,
|
||||
&decal.position,
|
||||
ship->model_instance_num,
|
||||
decal.submodel,
|
||||
&objp->orient,
|
||||
&objp->pos);
|
||||
|
||||
vec3d worldDir;
|
||||
model_instance_find_world_dir(&worldDir,
|
||||
&decal.orientation.vec.fvec,
|
||||
ship->model_instance_num,
|
||||
decal.submodel,
|
||||
&objp->orient);
|
||||
|
||||
vec3d worldUp;
|
||||
model_instance_find_world_dir(&worldUp,
|
||||
&decal.orientation.vec.fvec,
|
||||
ship->model_instance_num,
|
||||
decal.submodel,
|
||||
&objp->orient);
|
||||
|
||||
matrix worldOrient;
|
||||
vm_vector_2_matrix(&worldOrient, &worldDir, &worldUp);
|
||||
|
||||
// Apply scaling
|
||||
worldOrient.a2d[0][0] *= decal.scale.xyz.x;
|
||||
worldOrient.a2d[0][1] *= decal.scale.xyz.x;
|
||||
worldOrient.a2d[0][2] *= decal.scale.xyz.x;
|
||||
worldOrient.a2d[1][0] *= decal.scale.xyz.y;
|
||||
worldOrient.a2d[1][1] *= decal.scale.xyz.y;
|
||||
worldOrient.a2d[1][2] *= decal.scale.xyz.y;
|
||||
worldOrient.a2d[2][0] *= decal.scale.xyz.z;
|
||||
worldOrient.a2d[2][1] *= decal.scale.xyz.z;
|
||||
worldOrient.a2d[2][2] *= decal.scale.xyz.z;
|
||||
|
||||
matrix4 mat4;
|
||||
vm_matrix4_set_transform(&mat4, &worldOrient, &worldPos);
|
||||
|
||||
return mat4;
|
||||
}
|
||||
|
||||
void renderAll() {
|
||||
if (!decal_system_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear out any invalid decals
|
||||
for (auto iter = active_decals.begin(); iter != active_decals.end(); ++iter) {
|
||||
if (!iter->isValid()) {
|
||||
// if we're sitting on the very last element, popping-back will invalidate the iterator!
|
||||
if (iter + 1 == active_decals.end()) {
|
||||
active_decals.pop_back();
|
||||
break;
|
||||
}
|
||||
|
||||
*iter = active_decals.back();
|
||||
active_decals.pop_back();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (active_decals.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
graphics::decal_draw_list draw_list;
|
||||
auto mission_time = f2fl(Missiontime);
|
||||
|
||||
for (auto& decal : active_decals) {
|
||||
int diffuse_bm = -1;
|
||||
int glow_bm = -1;
|
||||
int normal_bm = -1;
|
||||
|
||||
Assertion(decal.definition_handle >= 0 && decal.definition_handle < (int) decalDefinitions.size(),
|
||||
"Invalid decal handle detected!");
|
||||
auto& decalDef = decalDefinitions[decal.definition_handle];
|
||||
|
||||
auto decal_time = mission_time - decal.creation_time;
|
||||
auto progress = decal_time / decal.lifetime;
|
||||
|
||||
float alpha = 1.0f;
|
||||
if (progress > 0.8) {
|
||||
// Fade the decal out for the last 20% of its lifetime
|
||||
alpha = 1.0f - smoothstep(0.8f, 1.0f, progress);
|
||||
}
|
||||
|
||||
if (decalDef.getDiffuseBitmap() >= 0) {
|
||||
diffuse_bm = decalDef.getDiffuseBitmap()
|
||||
+ bm_get_anim_frame(decalDef.getDiffuseBitmap(), decal_time, 0.0f, decalDef.isDiffuseLooping());
|
||||
}
|
||||
|
||||
if (decalDef.getGlowBitmap() >= 0) {
|
||||
glow_bm = decalDef.getGlowBitmap()
|
||||
+ bm_get_anim_frame(decalDef.getGlowBitmap(), decal_time, 0.0f, decalDef.isGlowLooping());
|
||||
}
|
||||
|
||||
if (decalDef.getNormalBitmap() >= 0) {
|
||||
normal_bm = decalDef.getNormalBitmap()
|
||||
+ bm_get_anim_frame(decalDef.getNormalBitmap(), decal_time, 0.0f, decalDef.isNormalLooping());
|
||||
}
|
||||
|
||||
draw_list.add_decal(diffuse_bm, glow_bm, normal_bm, decal_time, getDecalTransform(decal), alpha);
|
||||
}
|
||||
|
||||
draw_list.render();
|
||||
}
|
||||
void
|
||||
addDecal(creation_info& info, object* host, int submodel, const vec3d& local_pos, const matrix& local_orient) {
|
||||
if (!decal_system_active) {
|
||||
return;
|
||||
}
|
||||
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
|
||||
if (info.definition_handle < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
|
||||
"Invalid decal handle detected!");
|
||||
auto& def = decalDefinitions[info.definition_handle];
|
||||
|
||||
if (!def.bitmapsLoaded()) {
|
||||
// If this decal was never used before then the bitmaps are not loaded so we need to do that here.
|
||||
def.loadBitmaps();
|
||||
}
|
||||
|
||||
Decal newDecal;
|
||||
newDecal.definition_handle = info.definition_handle;
|
||||
newDecal.object = object_h(host);
|
||||
newDecal.submodel = submodel;
|
||||
newDecal.creation_time = f2fl(Missiontime);
|
||||
newDecal.lifetime = info.lifetime.next();
|
||||
|
||||
newDecal.position = local_pos;
|
||||
newDecal.orientation = local_orient;
|
||||
newDecal.scale.xyz.x = info.radius;
|
||||
newDecal.scale.xyz.y = info.radius;
|
||||
newDecal.scale.xyz.z = info.radius;
|
||||
|
||||
active_decals.push_back(newDecal);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include "object/object.h"
|
||||
|
||||
#include "utils/RandomRange.h"
|
||||
|
||||
namespace decals {
|
||||
|
||||
/**
|
||||
* @brief A reference to a decal definition
|
||||
*/
|
||||
typedef int DecalReference;
|
||||
|
||||
/**
|
||||
* @brief A structure containing all information for creating a decal
|
||||
*/
|
||||
struct creation_info {
|
||||
DecalReference definition_handle = -1;
|
||||
float radius = -1.0f;
|
||||
util::UniformFloatRange lifetime = ::util::UniformFloatRange(-1.0f);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initializes the global state of the decal system. Call once at game init.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
|
||||
/**
|
||||
* @brief Parses the information for a decal reference
|
||||
*
|
||||
* @details This function expects that the initial token has already been consumed by the parse system.
|
||||
*
|
||||
* @param dest_info The creation information struct to parse the information into
|
||||
* @param is_new_entry Set to @c false if the currently parsed object used +nocreate
|
||||
*/
|
||||
void parseDecalReference(creation_info& dest_info, bool is_new_entry = true);
|
||||
|
||||
/**
|
||||
* @brief Loads the bitmaps specified by the creation info into texture memory
|
||||
*
|
||||
* This should be called when the bitmaps of the object using this decal are loaded.
|
||||
*
|
||||
* @param info The creation information containing the decal definition handle
|
||||
*/
|
||||
void loadBitmaps(const creation_info& info);
|
||||
|
||||
/**
|
||||
* @brief Page in the bitmap data of the specified creation information. Needs to be called after loadBitmaps
|
||||
* @param info The information to page in
|
||||
*/
|
||||
void pageInDecal(const creation_info& info);
|
||||
|
||||
/**
|
||||
* @brief Shut down the decal system. Must be called from game_shutdown
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* @brief Initialize the decal system for the mission. Must be called before every mission is started
|
||||
*/
|
||||
void initializeMission();
|
||||
|
||||
/**
|
||||
* @brief Renders all currently active decals and removes invalid decals from the active list.
|
||||
*/
|
||||
void renderAll();
|
||||
|
||||
/**
|
||||
* @brief Creates a new decal on the specified object at the specified location
|
||||
*
|
||||
* @param info The decal to create
|
||||
* @param host The object host on which to create this decal. Must be a ship.
|
||||
* @param submodel The submodel of the object model on which to create the decal.
|
||||
* @param local_pos The position in the frame of reference of the submodel at which the decal should be created.
|
||||
* @param local_orient The orientation of the decal in the frame of reference of the submodel. The forward vector of the
|
||||
* orientation should look along the direction
|
||||
*/
|
||||
void addDecal(creation_info& info,
|
||||
object* host,
|
||||
int submodel,
|
||||
const vec3d& local_pos,
|
||||
const matrix& local_orient);
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
#ControlConfigOverride
|
||||
#End
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
|
||||
#include "gamma.sdr"
|
||||
|
||||
in vec4 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
out vec4 fragOut0;
|
||||
uniform sampler2DArray baseMap;
|
||||
uniform float intensity;
|
||||
#define SRGB_GAMMA 2.2
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 baseColor = texture(baseMap, fragTexCoord.xyz);
|
||||
|
||||
baseColor.rgb = pow(baseColor.rgb, vec3(SRGB_GAMMA));
|
||||
vec4 blendColor = vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a);
|
||||
baseColor.rgb = srgb_to_linear(baseColor.rgb);
|
||||
vec4 blendColor = vec4(srgb_to_linear(fragColor.rgb), fragColor.a);
|
||||
|
||||
fragOut0 = baseColor * blendColor * intensity;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,180 @@
|
||||
|
||||
// NOTE: The technique and some of this code is based on this tutorial:
|
||||
// http://martindevans.me/game-development/2015/02/27/Drawing-Stuff-On-Other-Stuff-With-Deferred-Screenspace-Decals/
|
||||
|
||||
#include "lighting.sdr"
|
||||
#include "normals.sdr"
|
||||
#include "gamma.sdr"
|
||||
|
||||
out vec4 fragOut0; // Diffuse buffer
|
||||
out vec4 fragOut1; // Normal buffer
|
||||
out vec4 fragOut2; // Emissive buffer
|
||||
|
||||
uniform sampler2D gDepthBuffer;
|
||||
uniform sampler2D gNormalBuffer;
|
||||
|
||||
uniform sampler2DArray diffuseMap;
|
||||
uniform sampler2DArray glowMap;
|
||||
uniform sampler2DArray normalMap;
|
||||
|
||||
layout (std140) uniform decalGlobalData {
|
||||
mat4 viewMatrix;
|
||||
mat4 projMatrix;
|
||||
mat4 invViewMatrix;
|
||||
mat4 invProjMatrix;
|
||||
|
||||
vec3 ambientLight;
|
||||
|
||||
vec2 viewportSize;
|
||||
};
|
||||
layout (std140) uniform decalInfoData {
|
||||
mat4 model_matrix;
|
||||
mat4 inv_model_matrix;
|
||||
|
||||
vec3 decal_direction;
|
||||
float normal_angle_cutoff;
|
||||
|
||||
int diffuse_index;
|
||||
int glow_index;
|
||||
int normal_index;
|
||||
float angle_fade_start;
|
||||
|
||||
float alpha_scale;
|
||||
int diffuse_blend_mode;
|
||||
int glow_blend_mode;
|
||||
};
|
||||
|
||||
vec3 computeViewPosition(vec2 textureCoord) {
|
||||
vec4 clipSpaceLocation;
|
||||
vec2 normalizedCoord = textureCoord / viewportSize;
|
||||
|
||||
clipSpaceLocation.xy = normalizedCoord * 2.0f - 1.0f;
|
||||
clipSpaceLocation.z = texelFetch(gDepthBuffer, ivec2(textureCoord), 0).r * 2.0f - 1.0f;
|
||||
clipSpaceLocation.w = 1.0f;
|
||||
|
||||
vec4 homogenousLocation = invProjMatrix * clipSpaceLocation;
|
||||
|
||||
return homogenousLocation.xyz / homogenousLocation.w;
|
||||
}
|
||||
|
||||
vec3 getPixelNormal(vec3 frag_position, vec2 tex_coord, inout float alpha, out vec3 binormal, out vec3 tangent) {
|
||||
#ifdef USE_NORMAL_MAP
|
||||
// If we can then we just use the existing normal buffer
|
||||
vec3 normal = texelFetch(gNormalBuffer, ivec2(tex_coord), 0).xyz;
|
||||
|
||||
// If we use the normal map then we don't really need these values so we don't need to compute them here
|
||||
binormal = vec3(0.0);
|
||||
tangent = vec3(0.0);
|
||||
#else
|
||||
// Use some fancy screen-space derivates to determine the normal of the current pixel by looking at the surrounding pixels
|
||||
vec3 pos_dx = dFdx(frag_position);
|
||||
vec3 pos_dy = dFdy(frag_position);
|
||||
|
||||
vec3 normal = normalize(cross(pos_dx, pos_dy));
|
||||
|
||||
binormal = normalize(pos_dx);
|
||||
tangent = normalize(pos_dy);
|
||||
#endif
|
||||
|
||||
//Calculate angle between surface normal and decal direction
|
||||
float angle = acos(dot(normal, decal_direction));
|
||||
|
||||
if (angle > normal_angle_cutoff) {
|
||||
// The angle between surface normal and decal direction is too big
|
||||
discard;
|
||||
}
|
||||
|
||||
// Make a smooth alpha transition leading up to an edge
|
||||
alpha = alpha * (1 - smoothstep(angle_fade_start, normal_angle_cutoff, angle));
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
vec2 getDecalTexCoord(vec3 view_pos, inout float alpha) {
|
||||
vec4 object_pos = inv_model_matrix * invViewMatrix * vec4(view_pos, 1.0);
|
||||
|
||||
bvec3 invalidComponents = greaterThan(abs(object_pos.xyz), vec3(0.5));
|
||||
bvec4 nanComponents = isnan(object_pos); // nan can happen some times if we have an infinite depth value
|
||||
|
||||
if (any(invalidComponents) || any(nanComponents)) {
|
||||
// Fragment is out of the box
|
||||
discard;
|
||||
}
|
||||
|
||||
// Fade out the texture when it gets close to the top or bottom of the decal box
|
||||
alpha = alpha * (1.0 - smoothstep(0.4, 0.5, abs(object_pos.z)));
|
||||
|
||||
return object_pos.xy + 0.5;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 frag_position = computeViewPosition(gl_FragCoord.xy);
|
||||
|
||||
float alpha = alpha_scale;
|
||||
vec2 tex_coord = getDecalTexCoord(frag_position, alpha);
|
||||
|
||||
vec3 binormal;
|
||||
vec3 tangent;
|
||||
vec3 normal = getPixelNormal(frag_position, gl_FragCoord.xy, alpha, binormal, tangent);
|
||||
|
||||
vec4 diffuse_out = vec4(0.0);
|
||||
vec4 emissive_out = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec3 normal_out = vec3(0.0);
|
||||
|
||||
if (diffuse_index >= 0) {
|
||||
// We have a valid diffuse map
|
||||
vec4 color = texture(diffuseMap, vec3(tex_coord, float(diffuse_index)));
|
||||
|
||||
color.rgb = srgb_to_linear(color.rgb);
|
||||
|
||||
if (diffuse_blend_mode == 0) {
|
||||
// Normal alpha blending
|
||||
diffuse_out = vec4(color.rgb, color.a * alpha);
|
||||
} else {
|
||||
// Additive blending
|
||||
diffuse_out = vec4(color.rgb * alpha, 1.0);
|
||||
}
|
||||
|
||||
// The main model shader applies ambient lighting by drawing the ambient part of the texture into the emissive
|
||||
// texture. We do the same here to make sure the decal material is applied correctly
|
||||
if (glow_blend_mode == 0) {
|
||||
// Normal alpha blending
|
||||
emissive_out = vec4(color.rgb * ambientLight, color.a * alpha);
|
||||
} else {
|
||||
// Additive blending
|
||||
emissive_out = vec4(alpha * color.rgb * ambientLight, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (glow_index >= 0) {
|
||||
// We have a valid diffuse map
|
||||
vec4 color = texture(glowMap, vec3(tex_coord, float(glow_index)));
|
||||
|
||||
color.rgb = srgb_to_linear(color.rgb) * GLOW_MAP_SRGB_MULTIPLIER;
|
||||
|
||||
color.rgb *= GLOW_MAP_INTENSITY;
|
||||
|
||||
if (glow_blend_mode == 0) {
|
||||
// Normal alpha blending
|
||||
emissive_out = vec4(color.rgb + emissive_out.rgb * emissive_out.a, color.a * alpha);
|
||||
} else {
|
||||
// Additive blending
|
||||
emissive_out.rgb += color.rgb * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
if (normal_index >= 0) {
|
||||
vec3 decalNormal = unpackNormal(texture(normalMap, vec3(tex_coord, float(normal_index))).ag);
|
||||
|
||||
mat3 tangentToView;
|
||||
tangentToView[0] = tangent;
|
||||
tangentToView[1] = binormal;
|
||||
tangentToView[2] = normal;
|
||||
|
||||
normal_out = tangentToView * decalNormal * alpha;
|
||||
}
|
||||
|
||||
fragOut0 = diffuse_out;
|
||||
fragOut1 = vec4(normal_out, 0.0);
|
||||
fragOut2 = emissive_out;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
in vec4 vertPosition;
|
||||
|
||||
layout (std140) uniform decalGlobalData {
|
||||
mat4 viewMatrix;
|
||||
mat4 projMatrix;
|
||||
mat4 invViewMatrix;
|
||||
mat4 invProjMatrix;
|
||||
|
||||
vec3 ambientLight;
|
||||
|
||||
vec2 viewportSize;
|
||||
};
|
||||
layout (std140) uniform decalInfoData {
|
||||
mat4 model_matrix;
|
||||
mat4 inv_model_matrix;
|
||||
|
||||
vec3 decal_direction;
|
||||
float normal_angle_cutoff;
|
||||
|
||||
int diffuse_index;
|
||||
int glow_index;
|
||||
int normal_index;
|
||||
float angle_fade_start;
|
||||
|
||||
float alpha_scale;
|
||||
int diffuse_blend_mode;
|
||||
int glow_blend_mode;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = projMatrix * viewMatrix * model_matrix * vertPosition;
|
||||
}
|
||||
+7
-3
@@ -1,6 +1,10 @@
|
||||
|
||||
#include "gamma.sdr"
|
||||
|
||||
in vec4 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
out vec4 fragOut0;
|
||||
|
||||
uniform sampler2DArray baseMap;
|
||||
uniform int baseMapIndex;
|
||||
uniform int alphaTexture;
|
||||
@@ -8,12 +12,12 @@ uniform int noTexturing;
|
||||
uniform int srgb;
|
||||
uniform float intensity;
|
||||
uniform float alphaThreshold;
|
||||
#define SRGB_GAMMA 2.2
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 baseColor = texture(baseMap, vec3(fragTexCoord.xy, float(baseMapIndex)));
|
||||
if(alphaThreshold > baseColor.a) discard;
|
||||
baseColor.rgb = (srgb == 1) ? pow(baseColor.rgb, vec3(SRGB_GAMMA)) : baseColor.rgb;
|
||||
vec4 blendColor = (srgb == 1) ? vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a) : fragColor;
|
||||
baseColor.rgb = (srgb == 1) ? srgb_to_linear(baseColor.rgb) : baseColor.rgb;
|
||||
vec4 blendColor = (srgb == 1) ? vec4(srgb_to_linear(fragColor.rgb), fragColor.a) : fragColor;
|
||||
fragOut0 = mix(mix(baseColor * blendColor, vec4(blendColor.rgb, baseColor.r * blendColor.a), float(alphaTexture)), blendColor, float(noTexturing)) * intensity;
|
||||
}
|
||||
+3
-1
@@ -2,10 +2,12 @@ out vec4 fragOut0;
|
||||
out vec4 fragOut1;
|
||||
out vec4 fragOut2;
|
||||
out vec4 fragOut3;
|
||||
out vec4 fragOut4;
|
||||
void main()
|
||||
{
|
||||
fragOut0 = vec4(0.0, 0.0, 0.0, 1.0); // color
|
||||
fragOut1 = vec4(0.0, 0.0, -1000000.0, 1.0); // position
|
||||
fragOut2 = vec4(0.0, 0.0, 0.0, 1.0); // normal
|
||||
fragOut3 = vec4(0.0, 0.0, 0.0, 0.0); // specular
|
||||
}
|
||||
fragOut4 = vec4(0.0, 0.0, 0.0, 1.0); // emissive
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,138 @@
|
||||
|
||||
#include "lighting.sdr"
|
||||
|
||||
#include "shadows.sdr"
|
||||
|
||||
in vec3 beamVec;
|
||||
in vec3 lightPosition;
|
||||
out vec4 fragOut0;
|
||||
|
||||
uniform sampler2D ColorBuffer;
|
||||
uniform sampler2D NormalBuffer;
|
||||
uniform sampler2D PositionBuffer;
|
||||
uniform sampler2D SpecBuffer;
|
||||
uniform sampler2DArray shadow_map;
|
||||
|
||||
layout (std140) uniform globalDeferredData {
|
||||
mat4 shadow_mv_matrix;
|
||||
mat4 shadow_proj_matrix[4];
|
||||
|
||||
mat4 inv_view_matrix;
|
||||
|
||||
float veryneardist;
|
||||
float neardist;
|
||||
float middist;
|
||||
float fardist;
|
||||
|
||||
float specFactor;
|
||||
float invScreenWidth;
|
||||
float invScreenHeight;
|
||||
};
|
||||
|
||||
layout (std140) uniform lightData {
|
||||
vec3 diffuseLightColor;
|
||||
float coneAngle;
|
||||
|
||||
vec3 specLightColor;
|
||||
float coneInnerAngle;
|
||||
|
||||
vec3 coneDir;
|
||||
bool dualCone;
|
||||
|
||||
vec3 scale;
|
||||
float lightRadius;
|
||||
|
||||
vec3 lightDir;
|
||||
int lightType;
|
||||
|
||||
bool enable_shadows;
|
||||
};
|
||||
|
||||
void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation)
|
||||
{
|
||||
if (lightType == LT_DIRECTIONAL) {
|
||||
lightDir = normalize(lightPosition);
|
||||
attenuation = 1.0;
|
||||
} else {
|
||||
// Positional light source
|
||||
lightDir = lightPosition - position.xyz;
|
||||
float dist = length(lightDir);
|
||||
attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0);
|
||||
|
||||
if(dist > lightRadius && lightType != LT_TUBE) {
|
||||
discard;
|
||||
}
|
||||
|
||||
if (lightType == LT_TUBE) { // Tube light
|
||||
float beamLength = length(beamVec);
|
||||
vec3 beamDir = beamVec / beamLength;
|
||||
// Get nearest point on line
|
||||
float neardist = clamp(dot(lightDir, beamDir), 0.0, beamLength);
|
||||
// Move back from the endpoint of the beam along the beam by the distance we calculated
|
||||
vec3 nearest = lightPosition - beamDir * neardist;
|
||||
lightDir = nearest - position.xyz;
|
||||
dist = length(lightDir);
|
||||
if(dist > lightRadius) {
|
||||
discard;
|
||||
}
|
||||
} else if (lightType == LT_CONE) {
|
||||
float coneDot = dot(normalize(-lightDir), coneDir);
|
||||
if(dualCone) {
|
||||
if(abs(coneDot) < coneAngle) {
|
||||
discard;
|
||||
} else {
|
||||
attenuation *= smoothstep(coneAngle, coneInnerAngle, abs(coneDot));
|
||||
}
|
||||
} else {
|
||||
if (coneDot < coneAngle) {
|
||||
discard;
|
||||
} else {
|
||||
attenuation *= smoothstep(coneAngle, coneInnerAngle, coneDot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lightDir = normalize(lightDir);
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight);
|
||||
vec3 position = texture(PositionBuffer, screenPos).xyz;
|
||||
|
||||
if(abs(dot(position, position)) < 0.1)
|
||||
discard;
|
||||
|
||||
vec3 color = texture(ColorBuffer, screenPos).rgb;
|
||||
vec4 normalData = texture(NormalBuffer, screenPos);
|
||||
vec4 specColor = texture(SpecBuffer, screenPos);
|
||||
// The vector in the normal buffer could be longer than the unit vector since decal rendering only adds to the normal buffer
|
||||
vec3 normal = normalize(normalData.xyz);
|
||||
float gloss = normalData.a;
|
||||
float fresnel = specColor.a;
|
||||
vec3 eyeDir = normalize(-position);
|
||||
|
||||
vec3 lightDir;
|
||||
float attenuation;
|
||||
|
||||
GetLightInfo(position, lightDir, attenuation);
|
||||
|
||||
if (enable_shadows) {
|
||||
vec4 fragShadowPos = shadow_mv_matrix * inv_view_matrix * vec4(position, 1.0);
|
||||
vec4 fragShadowUV[4];
|
||||
fragShadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, fragShadowPos);
|
||||
fragShadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, fragShadowPos);
|
||||
fragShadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, fragShadowPos);
|
||||
fragShadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, fragShadowPos);
|
||||
|
||||
attenuation *= getShadowValue(shadow_map, -position.z, fragShadowPos.z, fragShadowUV, fardist, middist,
|
||||
neardist, veryneardist);
|
||||
}
|
||||
|
||||
vec3 halfVec = normalize(lightDir + eyeDir);
|
||||
float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0);
|
||||
vec4 fragmentColor = vec4(color * (diffuseLightColor * NdotL * attenuation), 1.0);
|
||||
fragmentColor.rgb += computeLighting(specColor.rgb, lightDir, normal.xyz, halfVec, eyeDir, gloss, fresnel, NdotL).rgb * specLightColor * attenuation;
|
||||
fragOut0 = max(fragmentColor, vec4(0.0));
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
#include "lighting.sdr"
|
||||
|
||||
in vec4 vertPosition;
|
||||
uniform mat4 modelViewMatrix;
|
||||
uniform mat4 projMatrix;
|
||||
|
||||
layout (std140) uniform lightData {
|
||||
vec3 diffuseLightColor;
|
||||
float coneAngle;
|
||||
|
||||
vec3 specLightColor;
|
||||
float coneInnerAngle;
|
||||
|
||||
vec3 coneDir;
|
||||
bool dualCone;
|
||||
|
||||
vec3 scale;
|
||||
float lightRadius;
|
||||
|
||||
vec3 lightDir;
|
||||
int lightType;
|
||||
|
||||
bool enable_shadows;
|
||||
};
|
||||
|
||||
out vec3 lightPosition;
|
||||
out vec3 beamVec;
|
||||
void main()
|
||||
{
|
||||
if (lightType == LT_DIRECTIONAL) {
|
||||
gl_Position = vec4(vertPosition.xyz, 1.0);
|
||||
lightPosition = lightDir;
|
||||
} else {
|
||||
gl_Position = projMatrix * modelViewMatrix * vec4(vertPosition.xyz * scale, 1.0);
|
||||
lightPosition = modelViewMatrix[3].xyz;
|
||||
if(lightType == LT_TUBE)
|
||||
beamVec = vec3(modelViewMatrix * vec4(0.0, 0.0, -scale.z, 0.0));
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
+6
-3
@@ -1,3 +1,6 @@
|
||||
|
||||
#include "gamma.sdr"
|
||||
|
||||
uniform sampler2DArray baseMap;
|
||||
uniform sampler2D depthMap;
|
||||
uniform float window_width;
|
||||
@@ -12,12 +15,12 @@ in vec4 fragPosition;
|
||||
in vec4 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
out vec4 fragOut0;
|
||||
#define SRGB_GAMMA 2.2
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 fragmentColor = texture(baseMap, fragTexCoord.xyz);
|
||||
fragmentColor.rgb = mix(fragmentColor.rgb, pow(fragmentColor.rgb, vec3(SRGB_GAMMA)), float(srgb));
|
||||
fragmentColor *= mix(fragColor, vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a), float(srgb));
|
||||
fragmentColor.rgb = mix(fragmentColor.rgb, srgb_to_linear(fragmentColor.rgb), float(srgb));
|
||||
fragmentColor *= mix(fragColor, vec4(srgb_to_linear(fragColor.rgb), fragColor.a), float(srgb));
|
||||
vec2 offset = vec2(fragRadius * abs(0.5 - fragTexCoord.x) * 2.0, fragRadius * abs(0.5 - fragTexCoord.y) * 2.0);
|
||||
float offset_len = length(offset);
|
||||
if ( offset_len > fragRadius ) {
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,34 @@
|
||||
|
||||
#include "gamma.sdr"
|
||||
|
||||
in vec4 fragTexCoord;
|
||||
out vec4 fragOut0;
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D depth_tex;
|
||||
|
||||
uniform float fog_start;
|
||||
uniform float fog_scale;
|
||||
uniform vec3 fog_color;
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color_in = texture(tex, fragTexCoord.xy);
|
||||
|
||||
// If the scene is in fog then we change the color we operate on based on the depth of the pixel
|
||||
float depth_val = texture(depth_tex, fragTexCoord.xy).x;
|
||||
// Transform depth value from [-1, 1] to [0, 1]
|
||||
float depth_normalized = 2.0 * depth_val - 1.0;
|
||||
// Now we compute the depth value in projection space using the clipping plane information
|
||||
float view_depth = 2.0 * zNear * zFar / (zFar + zNear - depth_normalized * (zFar - zNear));
|
||||
|
||||
// This is the same formula that is also used by the main shader
|
||||
float fog_dist = isinf(view_depth) ? 1.0 : clamp((view_depth - fog_start) * 0.75 * fog_scale, 0.0, 1.0);
|
||||
|
||||
vec3 finalFogColor = srgb_to_linear(fog_color);
|
||||
|
||||
fragOut0.rgb = mix(color_in.rgb, finalFogColor, fog_dist);
|
||||
fragOut0.a = 1.0;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,29 @@
|
||||
|
||||
const float SRGB_GAMMA = 2.2;
|
||||
const float SRGB_GAMMA_INVERSE = 1.0 / SRGB_GAMMA;
|
||||
|
||||
float srgb_to_linear(float val) {
|
||||
return pow(val, SRGB_GAMMA);
|
||||
}
|
||||
vec2 srgb_to_linear(vec2 val) {
|
||||
return pow(val, vec2(SRGB_GAMMA));
|
||||
}
|
||||
vec3 srgb_to_linear(vec3 val) {
|
||||
return pow(val, vec3(SRGB_GAMMA));
|
||||
}
|
||||
vec4 srgb_to_linear(vec4 val) {
|
||||
return pow(val, vec4(SRGB_GAMMA));
|
||||
}
|
||||
|
||||
float linear_to_srgb(float val) {
|
||||
return pow(val, SRGB_GAMMA_INVERSE);
|
||||
}
|
||||
vec2 linear_to_srgb(vec2 val) {
|
||||
return pow(val, vec2(SRGB_GAMMA_INVERSE));
|
||||
}
|
||||
vec3 linear_to_srgb(vec3 val) {
|
||||
return pow(val, vec3(SRGB_GAMMA_INVERSE));
|
||||
}
|
||||
vec4 linear_to_srgb(vec4 val) {
|
||||
return pow(val, vec4(SRGB_GAMMA_INVERSE));
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
const int LT_DIRECTIONAL = 0; // A light like a sun
|
||||
const int LT_POINT = 1; // A point light, like an explosion
|
||||
const int LT_TUBE = 2; // A tube light, like a fluorescent light
|
||||
const int LT_CONE = 3; // A cone light, like a flood light
|
||||
|
||||
const float SPEC_INTENSITY_POINT = 5.3 ;// Point light
|
||||
const float SPEC_INTENSITY_DIRECTIONAL = 3.0 ;// Directional light
|
||||
const float SPECULAR_FACTOR = 1.75;
|
||||
const float SPECULAR_ALPHA = 0.1;
|
||||
const float SPEC_FACTOR_NO_SPEC_MAP = 0.6;
|
||||
const float ENV_ALPHA_FACTOR = 0.3;
|
||||
const float GLOW_MAP_INTENSITY = 1.5;
|
||||
const float AMBIENT_LIGHT_BOOST = 1.0;
|
||||
const float GLOW_MAP_SRGB_MULTIPLIER = 3.0;
|
||||
|
||||
vec3 FresnelSchlick(vec3 specColor, vec3 light, vec3 halfVec)
|
||||
{
|
||||
return specColor + (vec3(1.0) - specColor) * pow(1.0 - clamp(dot(light, halfVec), 0.0, 1.0), 5.0);
|
||||
}
|
||||
|
||||
vec3 SpecularBlinnPhong(vec3 specColor, vec3 light, vec3 normal, vec3 halfVec, float specPower, float fresnel, float dotNL)
|
||||
{
|
||||
return mix(specColor, FresnelSchlick(specColor, light, halfVec), fresnel) * ((specPower + 2.0) / 8.0 ) * pow(clamp(dot(normal, halfVec), 0.0, 1.0), specPower) * dotNL;
|
||||
}
|
||||
|
||||
vec3 SpecularGGX(vec3 specColor, vec3 light, vec3 normal, vec3 halfVec, vec3 view, float gloss, float fresnelFactor, float dotNL)
|
||||
{
|
||||
float roughness = clamp(1.0f - gloss, 0.0f, 1.0f);
|
||||
float alpha = roughness * roughness;
|
||||
|
||||
float dotNH = clamp(dot(normal, halfVec), 0.0f, 1.0f);
|
||||
float dotNV = clamp(dot(normal, view), 0.0f, 1.0f);
|
||||
|
||||
float alphaSqr = alpha * alpha;
|
||||
float pi = 3.14159f;
|
||||
float denom = dotNH * dotNH * (alphaSqr - 1.0f) + 1.0f;
|
||||
float distribution = alphaSqr / (pi * denom * denom);
|
||||
|
||||
vec3 fresnel = mix(specColor, FresnelSchlick(specColor, light, halfVec), fresnelFactor);
|
||||
|
||||
float alphaPrime = roughness + 1.0f;
|
||||
float k = alphaPrime * alphaPrime / 8.0f;
|
||||
float g1vNL = 1.0f / (dotNL * (1.0f - k) + k);
|
||||
float g1vNV = 1.0f / (dotNV * (1.0f - k) + k);
|
||||
float visibility = g1vNL * g1vNV;
|
||||
|
||||
return distribution * fresnel * visibility * dotNL;
|
||||
}
|
||||
|
||||
vec3 computeLighting(vec3 specColor, vec3 light, vec3 normal, vec3 halfVec, vec3 view, float gloss, float fresnelFactor, float dotNL)
|
||||
{
|
||||
#ifdef FLAG_LIGHT_MODEL_BLINN_PHONG
|
||||
return SpecularBlinnPhong(specColor, light, normal, halfVec, 32, fresnelFactor, dotNL);
|
||||
#else
|
||||
return SpecularGGX(specColor, light, normal, halfVec, view, gloss, fresnelFactor, dotNL);
|
||||
#endif
|
||||
}
|
||||
File renamed without changes.
@@ -1,3 +1,8 @@
|
||||
|
||||
#include "shadows.sdr"
|
||||
#include "lighting.sdr"
|
||||
#include "gamma.sdr"
|
||||
|
||||
#define MAX_LIGHTS 8
|
||||
#define LT_DIRECTIONAL 0
|
||||
#define LT_POINT 1
|
||||
@@ -91,6 +96,30 @@ layout (std140) uniform modelData {
|
||||
int sMiscmapIndex;
|
||||
};
|
||||
|
||||
in VertexOutput {
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vec3 envReflect;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
mat3 tangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
#ifdef FLAG_SHADOWS
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#endif
|
||||
} vertIn;
|
||||
|
||||
#ifdef FLAG_DIFFUSE_MAP
|
||||
uniform sampler2DArray sBasemap;
|
||||
#endif
|
||||
@@ -102,18 +131,13 @@ uniform sampler2DArray sSpecmap;
|
||||
#endif
|
||||
#ifdef FLAG_ENV_MAP
|
||||
uniform samplerCube sEnvmap;
|
||||
in vec3 fragEnvReflect;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
uniform sampler2DArray sNormalmap;
|
||||
in mat3 fragTangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_AMBIENT_MAP
|
||||
uniform sampler2DArray sAmbientmap;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
in float fragFogDist;
|
||||
#endif
|
||||
#ifdef FLAG_ANIMATED
|
||||
uniform sampler2D sFramebuffer;
|
||||
#endif
|
||||
@@ -124,150 +148,39 @@ vec2 teamMask = vec2(0.0, 0.0);
|
||||
uniform sampler2DArray sMiscmap;
|
||||
#endif
|
||||
#ifdef FLAG_SHADOWS
|
||||
in vec4 fragShadowUV[4];
|
||||
in vec4 fragShadowPos;
|
||||
uniform sampler2DArray shadow_map;
|
||||
#endif
|
||||
#define SPEC_INTENSITY_POINT 5.3 // Point light
|
||||
#define SPEC_INTENSITY_DIRECTIONAL 3.0 // Directional light
|
||||
#define SPECULAR_FACTOR 1.75
|
||||
#define SPEC_FACTOR_NO_SPEC_MAP 0.6
|
||||
#define ENV_ALPHA_FACTOR 0.3
|
||||
#define GLOW_MAP_INTENSITY 1.5
|
||||
#define AMBIENT_LIGHT_BOOST 1.0
|
||||
#define VARIANCE_SHADOW_SCALE 1000000.0
|
||||
#define VARIANCE_SHADOW_SCALE_INV 1.0/VARIANCE_SHADOW_SCALE
|
||||
#define SRGB_GAMMA 2.2
|
||||
in vec4 fragPosition;
|
||||
in vec3 fragNormal;
|
||||
in vec4 fragTexCoord;
|
||||
|
||||
out vec4 fragOut0;
|
||||
out vec4 fragOut1;
|
||||
out vec4 fragOut2;
|
||||
out vec4 fragOut3;
|
||||
out vec4 fragOut4;
|
||||
|
||||
#ifdef FLAG_SHADOWS
|
||||
vec2 sampleShadowMap(vec2 uv, vec2 offset_uv, int cascade, float shadowMapSizeInv)
|
||||
{
|
||||
return texture(shadow_map, vec3(uv + offset_uv * shadowMapSizeInv, float(cascade))).xy;
|
||||
}
|
||||
|
||||
float computeShadowFactor(vec2 moments, float bias)
|
||||
{
|
||||
float shadow = 1.0;
|
||||
if((moments.x - bias) > fragShadowPos.z)
|
||||
{
|
||||
// variance shadow mapping using Chebychev's Formula
|
||||
float variance = moments.y * VARIANCE_SHADOW_SCALE - moments.x * moments.x;
|
||||
float mD = moments.x - bias - fragShadowPos.z;
|
||||
shadow = variance / (variance + mD * mD);
|
||||
shadow = clamp(shadow, 0.0, 1.0);
|
||||
}
|
||||
return shadow;
|
||||
}
|
||||
|
||||
float sampleNoPCF(int cascade)
|
||||
{
|
||||
return computeShadowFactor(sampleShadowMap(fragShadowUV[cascade].xy, vec2(0.0, 0.0), cascade, 1.0/1024.0), 0.05);
|
||||
}
|
||||
|
||||
float samplePoissonPCF(int cascade)
|
||||
{
|
||||
if(cascade > 3 || cascade < 0) return 1.0;
|
||||
vec2 poissonDisc[16];
|
||||
poissonDisc[0] = vec2(-0.76275, -0.3432573);
|
||||
poissonDisc[1] = vec2(-0.5226235, -0.8277544);
|
||||
poissonDisc[2] = vec2(-0.3780261, 0.01528688);
|
||||
poissonDisc[3] = vec2(-0.7742821, 0.4245702);
|
||||
poissonDisc[4] = vec2(0.04196143, -0.02622231);
|
||||
poissonDisc[5] = vec2(-0.2974772, -0.4722782);
|
||||
poissonDisc[6] = vec2(-0.516093, 0.71495);
|
||||
poissonDisc[7] = vec2(-0.3257416, 0.3910343);
|
||||
poissonDisc[8] = vec2(0.2705966, 0.6670476);
|
||||
poissonDisc[9] = vec2(0.4918377, 0.1853267);
|
||||
poissonDisc[10] = vec2(0.4428544, -0.6251478);
|
||||
poissonDisc[11] = vec2(-0.09204347, 0.9267113);
|
||||
poissonDisc[12] = vec2(0.391505, -0.2558275);
|
||||
poissonDisc[13] = vec2(0.05605913, -0.7570801);
|
||||
poissonDisc[14] = vec2(0.81772, -0.02475523);
|
||||
poissonDisc[15] = vec2(0.6890262, 0.5191521);
|
||||
float maxUVOffset[4];
|
||||
maxUVOffset[0] = 1.0/300.0;
|
||||
maxUVOffset[1] = 1.0/250.0;
|
||||
maxUVOffset[2] = 1.0/200.0;
|
||||
maxUVOffset[3] = 1.0/200.0;
|
||||
vec2 sum = sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[0], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[1], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[2], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[3], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[4], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[5], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[6], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[7], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[8], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[9], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[10], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[11], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[12], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[13], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[14], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(fragShadowUV[cascade].xy, poissonDisc[15], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
return computeShadowFactor(sum, 0.1);
|
||||
}
|
||||
float getShadowValue()
|
||||
{
|
||||
// Valathil's Shadows
|
||||
float depth = -fragPosition.z;
|
||||
int cascade = 4;
|
||||
cascade -= int(step(depth, fardist));
|
||||
cascade -= int(step(depth, middist));
|
||||
cascade -= int(step(depth, neardist));
|
||||
cascade -= int(step(depth, veryneardist));
|
||||
float cascade_start_dist[5];
|
||||
cascade_start_dist[0] = 0.0;
|
||||
cascade_start_dist[1] = veryneardist;
|
||||
cascade_start_dist[2] = neardist;
|
||||
cascade_start_dist[3] = middist;
|
||||
cascade_start_dist[4] = fardist;
|
||||
if(cascade > 3 || cascade < 0) return 1.0;
|
||||
float dist_threshold = (cascade_start_dist[cascade+1] - cascade_start_dist[cascade])*0.2;
|
||||
if(cascade_start_dist[cascade+1] - dist_threshold > depth)
|
||||
return samplePoissonPCF(cascade);
|
||||
return mix(samplePoissonPCF(cascade), samplePoissonPCF(cascade+1), smoothstep(cascade_start_dist[cascade+1] - dist_threshold, cascade_start_dist[cascade+1], depth));
|
||||
}
|
||||
#endif
|
||||
vec3 FresnelLazarovEnv(vec3 specColor, vec3 view, vec3 normal, float gloss)
|
||||
{
|
||||
// Fresnel for environment lighting
|
||||
// Equation referenced from Dimitar Lazarov's presentation titled Physically Based Rendering in Call of Duty: Black Ops
|
||||
return specColor + (vec3(1.0) - specColor) * pow(1.0 - clamp(dot(view, normal), 0.0, 1.0), 5.0) / (4.0 - 3.0 * gloss);
|
||||
}
|
||||
vec3 FresnelSchlick(vec3 specColor, vec3 light, vec3 halfVec)
|
||||
{
|
||||
return specColor + (vec3(1.0) - specColor) * pow(1.0 - clamp(dot(light, halfVec), 0.0, 1.0), 5.0);
|
||||
}
|
||||
vec3 SpecularBlinnPhong(vec3 specColor, vec3 light, vec3 normal, vec3 halfVec, float specPower, float fresnel, float dotNL)
|
||||
{
|
||||
return mix(specColor, FresnelSchlick(specColor, light, halfVec), fresnel) * ((specPower + 2.0) / 8.0 ) * pow(clamp(dot(normal, halfVec), 0.0, 1.0), specPower) * dotNL;
|
||||
}
|
||||
#ifdef FLAG_LIGHT
|
||||
|
||||
void GetLightInfo(int i, out vec3 lightDir, out float attenuation)
|
||||
{
|
||||
lightDir = normalize(lights[i].position.xyz);
|
||||
attenuation = 1.0;
|
||||
if (lights[i].light_type != LT_DIRECTIONAL) {
|
||||
// Positional light source
|
||||
float dist = distance(lights[i].position.xyz, fragPosition.xyz);
|
||||
lightDir = (lights[i].position.xyz - fragPosition.xyz);
|
||||
float dist = distance(lights[i].position.xyz, vertIn.position.xyz);
|
||||
lightDir = (lights[i].position.xyz - vertIn.position.xyz);
|
||||
|
||||
if (lights[i].light_type == LT_TUBE) { // Tube light
|
||||
float beamlength = length(lights[i].direction);
|
||||
vec3 beamDir = normalize(lights[i].direction);
|
||||
// Get nearest point on line
|
||||
float neardist = dot(fragPosition.xyz - lights[i].position.xyz, beamDir);
|
||||
float neardist = dot(vertIn.position.xyz - lights[i].position.xyz, beamDir);
|
||||
// Move back from the endpoint of the beam along the beam by the distance we calculated
|
||||
vec3 nearest = lights[i].position.xyz - beamDir * abs(neardist);
|
||||
lightDir = nearest - fragPosition.xyz;
|
||||
lightDir = nearest - vertIn.position.xyz;
|
||||
dist = length(lightDir);
|
||||
}
|
||||
|
||||
@@ -277,7 +190,7 @@ void GetLightInfo(int i, out vec3 lightDir, out float attenuation)
|
||||
}
|
||||
vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial, float gloss, float fresnel, float shadow, float aoFactor)
|
||||
{
|
||||
vec3 eyeDir = vec3(normalize(-fragPosition).xyz);
|
||||
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
|
||||
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactor; // ambientFactor^2 due to legacy OpenGL compatibility behavior
|
||||
vec3 lightDiffuse = vec3(0.0, 0.0, 0.0);
|
||||
vec3 lightSpecular = vec3(0.0, 0.0, 0.0);
|
||||
@@ -292,25 +205,33 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
|
||||
// gather light params
|
||||
GetLightInfo(i, lightDir, attenuation);
|
||||
vec3 halfVec = normalize(lightDir + eyeDir);
|
||||
float NdotL = max(dot(normal, lightDir), 0.0);
|
||||
float NdotL = clamp(dot(normal, lightDir), 0.0f, 1.0f);
|
||||
// Ambient, Diffuse, and Specular
|
||||
lightDiffuse += (lights[i].diffuse_color.rgb * diffuseFactor * NdotL * attenuation) * shadow;
|
||||
lightSpecular += lights[i].spec_color * SpecularBlinnPhong(specularMaterial, lightDir, normal, halfVec, exp2(10.0 * gloss + 1.0), fresnel, NdotL) * attenuation * shadow;
|
||||
lightSpecular += lights[i].spec_color * computeLighting(specularMaterial, lightDir, normal, halfVec, eyeDir, gloss, fresnel, NdotL) * attenuation * shadow;
|
||||
}
|
||||
return diffuseMaterial * (lightAmbient + lightDiffuse) + lightSpecular;
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
if(vertIn.notVisible >= 0.9) { discard; }
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
// need depth and depth squared for variance shadow maps
|
||||
fragOut0 = vec4(fragPosition.z, fragPosition.z * fragPosition.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
|
||||
return;
|
||||
fragOut0 = vec4(vertIn.position.z, vertIn.position.z * vertIn.position.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
|
||||
if (true) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
vec3 eyeDir = vec3(normalize(-fragPosition).xyz);
|
||||
vec2 texCoord = fragTexCoord.xy;
|
||||
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
|
||||
vec2 texCoord = vertIn.texCoord.xy;
|
||||
vec4 baseColor = color;
|
||||
vec4 specColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 emissiveColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
float fresnelFactor = 0.0;
|
||||
float glossData = 0.6;
|
||||
#ifdef FLAG_LIGHT
|
||||
@@ -322,14 +243,14 @@ void main()
|
||||
// green is cavity occlusion factor which only affects diffuse and specular lighting.
|
||||
aoFactors = texture(sAmbientmap, vec3(texCoord, float(sAmbientmapIndex))).xy;
|
||||
#endif
|
||||
vec3 unitNormal = normalize(fragNormal);
|
||||
vec3 unitNormal = normalize(vertIn.normal);
|
||||
vec3 normal = unitNormal;
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
// Normal map - convert from DXT5nm
|
||||
vec2 normalSample;
|
||||
normal.rg = normalSample = (texture(sNormalmap, vec3(texCoord, float(sNormalmapIndex))).ag * 2.0) - 1.0;
|
||||
normal.b = clamp(sqrt(1.0 - dot(normal.rg, normal.rg)), 0.0001, 1.0);
|
||||
normal = fragTangentMatrix * normal;
|
||||
normal = vertIn.tangentMatrix * normal;
|
||||
float norm = length(normal);
|
||||
// prevent breaking of normal maps
|
||||
if (norm > 0.0)
|
||||
@@ -339,7 +260,7 @@ void main()
|
||||
#endif
|
||||
|
||||
#ifdef FLAG_ANIMATED
|
||||
vec2 distort = vec2(cos(fragPosition.x*fragPosition.w*0.005+anim_timer*20.0)*sin(fragPosition.y*fragPosition.w*0.005),sin(fragPosition.x*fragPosition.w*0.005+anim_timer*20.0)*cos(fragPosition.y*fragPosition.w*0.005))*0.03;
|
||||
vec2 distort = vec2(cos(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005),sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*cos(vertIn.position.y*vertIn.position.w*0.005))*0.03;
|
||||
#endif
|
||||
|
||||
#ifdef FLAG_DIFFUSE_MAP
|
||||
@@ -358,7 +279,7 @@ void main()
|
||||
#endif
|
||||
specColor = vec4(baseColor.rgb * SPEC_FACTOR_NO_SPEC_MAP, glossData);
|
||||
#ifdef FLAG_HDR
|
||||
baseColor.rgb = pow(baseColor.rgb, vec3(SRGB_GAMMA));
|
||||
baseColor.rgb = srgb_to_linear(baseColor.rgb);
|
||||
#endif
|
||||
#ifdef FLAG_SPEC_MAP
|
||||
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
|
||||
@@ -368,10 +289,10 @@ void main()
|
||||
fresnelFactor = 1.0;
|
||||
}
|
||||
if(gammaSpec) {
|
||||
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
|
||||
#ifdef FLAG_HDR
|
||||
specColor.rgb = pow(specColor.rgb, vec3(SRGB_GAMMA));
|
||||
specColor.rgb = srgb_to_linear(specColor.rgb);
|
||||
#endif
|
||||
specColor.rgb = max(specColor.rgb, vec3(0.04)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
|
||||
fresnelFactor = 1.0;
|
||||
}
|
||||
#endif
|
||||
@@ -381,62 +302,90 @@ void main()
|
||||
#ifdef FLAG_TEAMCOLOR
|
||||
vec4 teamMask = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
teamMask = texture(sMiscmap, vec3(texCoord, float(sMiscmapIndex)));
|
||||
vec3 base = max(base_color - vec3(0.5), vec3(0.0));
|
||||
vec3 stripe = max(stripe_color - vec3(0.5), vec3(0.0));
|
||||
baseColor.rgb += (base * teamMask.x) + (stripe * teamMask.y);
|
||||
baseColor.rgb = max(baseColor.rgb, vec3(0.0));
|
||||
//For team colors applied to a diffuse or spec map, we assume that the base color of the diffuse
|
||||
//at this point is vec3(0.5). To get accurate results, we subtract 0.5 from the team colors
|
||||
vec3 team_color = ((base_color - vec3(0.5)) * teamMask.x) + ((stripe_color - vec3(0.5)) * teamMask.y);
|
||||
vec3 team_color_glow = (base_color * teamMask.b) + (stripe_color * teamMask.a);
|
||||
|
||||
#ifdef FLAG_HDR
|
||||
team_color = srgb_to_linear(team_color);
|
||||
team_color_glow = srgb_to_linear(team_color_glow) * GLOW_MAP_SRGB_MULTIPLIER;
|
||||
#endif
|
||||
|
||||
baseColor.rgb += team_color;
|
||||
baseColor.rgb = max(baseColor.rgb, vec3(0.0)); // We need to make sure that nothing here ever goes negative
|
||||
specColor.rgb += team_color;
|
||||
specColor.rgb = max(specColor.rgb, vec3(0.03));
|
||||
#endif
|
||||
#endif
|
||||
float shadow = 1.0;
|
||||
#ifdef FLAG_SHADOWS
|
||||
shadow = getShadowValue();
|
||||
#endif
|
||||
#ifdef FLAG_LIGHT
|
||||
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
|
||||
#else
|
||||
#ifdef FLAG_SPEC_MAP
|
||||
// Lights aren't applied when we are rendering to the G-buffers since that gets handled later
|
||||
#ifdef FLAG_DEFERRED
|
||||
#ifdef FLAG_LIGHT
|
||||
// Ambient lighting still needs to be done since that counts as an "emissive" color
|
||||
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactors.x; // ambientFactor^2 due to legacy OpenGL compatibility behavior
|
||||
emissiveColor.rgb += baseColor.rgb * lightAmbient;
|
||||
#else
|
||||
#ifdef FLAG_SPEC_MAP
|
||||
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
|
||||
#endif
|
||||
// If there is no lighting then we copy the color data so far into the
|
||||
emissiveColor.rgb += baseColor.rgb;
|
||||
#endif
|
||||
#else
|
||||
#ifdef FLAG_LIGHT
|
||||
float shadow = 1.0;
|
||||
#ifdef FLAG_SHADOWS
|
||||
shadow = getShadowValue(shadow_map, -vertIn.position.z, vertIn.shadowPos.z, vertIn.shadowUV, fardist, middist, neardist, veryneardist);
|
||||
#endif
|
||||
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
|
||||
#else
|
||||
#ifdef FLAG_SPEC_MAP
|
||||
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vec3 envReflectNM = fragEnvReflect;
|
||||
vec3 envReflectNM = vertIn.envReflect;
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
envReflectNM += vec3(normalSample, 0.0);
|
||||
envReflectNM += vec3(normalSample, 0.0);
|
||||
envReflectNM = normalize(envReflectNM);
|
||||
#endif
|
||||
float mip = (envGloss) ? (1.0 - glossData) * 7.0 : 0.0;
|
||||
vec4 envColour = textureLod(sEnvmap, envReflectNM, mip);
|
||||
vec4 envColour = textureLod(sEnvmap, envReflectNM, mip);
|
||||
#ifdef FLAG_HDR
|
||||
envColour.rgb = pow(envColour.rgb, vec3(SRGB_GAMMA));
|
||||
envColour.rgb = srgb_to_linear(envColour.rgb);
|
||||
#endif
|
||||
envColour.rgb *= (envGloss) ? 1.0 : specColor.a;
|
||||
baseColor.rgb += envColour.rgb * FresnelLazarovEnv(specColor.rgb, eyeDir, normal, glossData);
|
||||
emissiveColor.rgb += envColour.rgb * FresnelLazarovEnv(specColor.rgb, eyeDir, normal, glossData);
|
||||
#endif
|
||||
#ifdef FLAG_GLOW_MAP
|
||||
vec3 glowColor = texture(sGlowmap, vec3(texCoord, float(sGlowmapIndex))).rgb;
|
||||
if(overrideGlow) glowColor = glowClr;
|
||||
#ifdef FLAG_HDR
|
||||
glowColor = pow(glowColor, vec3(SRGB_GAMMA)) * 3.0f;
|
||||
glowColor = srgb_to_linear(glowColor) * GLOW_MAP_SRGB_MULTIPLIER;
|
||||
#endif
|
||||
#ifdef FLAG_MISC_MAP
|
||||
#ifdef FLAG_TEAMCOLOR
|
||||
float glowColorLuminance = dot(glowColor, vec3(0.299, 0.587, 0.114));
|
||||
glowColor = team_glow_enabled ? mix((base * teamMask.b) + (stripe * teamMask.a), glowColor, clamp(glowColorLuminance - teamMask.b - teamMask.a, 0.0, 1.0)) : glowColor;
|
||||
glowColor = team_glow_enabled ? mix(max(team_color_glow, vec3(0.0)), glowColor, clamp(glowColorLuminance - teamMask.b - teamMask.a, 0.0, 1.0)) : glowColor;
|
||||
#endif
|
||||
#endif
|
||||
baseColor.rgb += glowColor * GLOW_MAP_INTENSITY;
|
||||
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
|
||||
#endif
|
||||
|
||||
#ifdef FLAG_FOG
|
||||
vec3 finalFogColor = fogColor.rgb;
|
||||
#ifdef FLAG_HDR
|
||||
finalFogColor = pow(finalFogColor, vec3(SRGB_GAMMA));
|
||||
finalFogColor = srgb_to_linear(finalFogColor);
|
||||
#endif
|
||||
#ifdef FLAG_DIFFUSE_MAP
|
||||
if(blend_alpha == 1) finalFogColor *= baseColor.a;
|
||||
#endif
|
||||
baseColor.rgb = mix(baseColor.rgb, finalFogColor, fragFogDist);
|
||||
specColor.rgb *= fragFogDist;
|
||||
// This code will only be used by the forward renderer so we apply the fog effect to both the emissive and the base
|
||||
// color.
|
||||
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, vertIn.fogDist);
|
||||
emissiveColor.rgb = vec3(0.0); // Zero the emissive color since it has already been added by the previous line
|
||||
specColor.rgb *= vertIn.fogDist;
|
||||
#endif
|
||||
|
||||
#ifdef FLAG_DIFFUSE_MAP
|
||||
@@ -447,38 +396,41 @@ void main()
|
||||
#ifdef FLAG_ANIMATED
|
||||
if (effect_num == 0) {
|
||||
float shinefactor = 1.0/(1.0 + pow(abs((fract(abs(texCoord.x))-anim_timer) * 1000.0), 2.0)) * 1000.0;
|
||||
baseColor.rgb = baseColor.rgb + vec3(shinefactor);
|
||||
emissiveColor.rgb += vec3(shinefactor);
|
||||
baseColor.a = baseColor.a * clamp(shinefactor * (fract(abs(texCoord.x))-anim_timer) * -10000.0,0.0,1.0);
|
||||
}
|
||||
if (effect_num == 1) {
|
||||
float shinefactor = 1.0/(1.0 + pow(abs(fragPosition.y-anim_timer), 2.0));
|
||||
baseColor.rgb = baseColor.rgb + vec3(shinefactor);
|
||||
#ifdef FLAG_LIGHT
|
||||
baseColor.a = baseColor.a;
|
||||
#else
|
||||
float shinefactor = 1.0/(1.0 + pow(abs(vertIn.position.y-anim_timer), 2.0));
|
||||
emissiveColor.rgb += vec3(shinefactor);
|
||||
#ifndef FLAG_LIGHT
|
||||
// ATI Wireframe fix *grumble*
|
||||
baseColor.a = clamp((fragPosition.y-anim_timer) * 10000.0,0.0,1.0);
|
||||
baseColor.a = clamp((vertIn.position.y-anim_timer) * 10000.0,0.0,1.0);
|
||||
#endif
|
||||
}
|
||||
if (effect_num == 2) {
|
||||
vec2 screenPos = gl_FragCoord.xy * vec2(vpwidth,vpheight);
|
||||
baseColor.a = baseColor.a;
|
||||
float cloak_interp = (sin(fragPosition.x*fragPosition.w*0.005+anim_timer*20.0)*sin(fragPosition.y*fragPosition.w*0.005)*0.5)-0.5;
|
||||
float cloak_interp = (sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005)*0.5)-0.5;
|
||||
#ifdef FLAG_LIGHT
|
||||
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
|
||||
#else
|
||||
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*fragNormal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
|
||||
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*vertIn.normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_ALPHA
|
||||
float normViewOffset = dot(vec3(0.0, 0.0, 1.0), normal);
|
||||
baseColor.a = smoothstep(min(normalAlphaMinMax.x, normalAlphaMinMax.y), max(normalAlphaMinMax.x, normalAlphaMinMax.y), clamp(normalAlphaMinMax.x > normalAlphaMinMax.y ? normViewOffset : 1.0 - normViewOffset, 0.0, 1.0));
|
||||
#endif
|
||||
#ifndef FLAG_DEFERRED
|
||||
// emissive colors won't be added later when we are using forward rendering so we need to do that here
|
||||
baseColor.rgb += emissiveColor.rgb;
|
||||
#endif
|
||||
fragOut0 = baseColor;
|
||||
#ifdef FLAG_DEFERRED
|
||||
fragOut1 = vec4(fragPosition.xyz, 1.0);
|
||||
fragOut1 = vec4(vertIn.position.xyz, 1.0);
|
||||
fragOut2 = vec4(normal, glossData);
|
||||
fragOut3 = vec4(specColor.rgb, fresnelFactor);
|
||||
fragOut4 = emissiveColor;
|
||||
#endif
|
||||
}
|
||||
@@ -96,33 +96,104 @@ layout (std140) uniform modelData {
|
||||
int sMiscmapIndex;
|
||||
};
|
||||
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
in float geoInstance[];
|
||||
in VertexOutput {
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vec3 envReflect;
|
||||
#endif
|
||||
in vec3 geoNormal[];
|
||||
in vec4 geoTexCoord[];
|
||||
out vec4 fragPosition;
|
||||
out vec3 fragNormal;
|
||||
out vec4 fragTexCoord;
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
mat3 tangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
float instance;
|
||||
#endif
|
||||
#else
|
||||
vec4 position;
|
||||
#endif
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
#ifdef FLAG_SHADOWS
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#endif
|
||||
} vertIn[];
|
||||
|
||||
out VertexOutput {
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vec3 envReflect;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
mat3 tangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
#ifdef FLAG_SHADOWS
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#endif
|
||||
} vertOut;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
int instanceID = gl_InvocationID;
|
||||
#else
|
||||
int instanceID = int(geoInstance[0]);
|
||||
int instanceID = int(vertIn[0].instance);
|
||||
#endif
|
||||
for(int vert = 0; vert < gl_in.length(); vert++)
|
||||
{
|
||||
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
|
||||
if(gl_Position.z < -1.0)
|
||||
gl_Position.z = -1.0;
|
||||
fragPosition = gl_in[vert].gl_Position;
|
||||
fragNormal = geoNormal[vert];
|
||||
fragTexCoord = geoTexCoord[vert];
|
||||
vertOut.position = gl_in[vert].gl_Position;
|
||||
vertOut.normal = vertIn[vert].normal;
|
||||
vertOut.texCoord = vertIn[vert].texCoord;
|
||||
|
||||
gl_Layer = instanceID;
|
||||
#if defined(FLAG_CLIP) || defined(FLAG_TRANSFORM)
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vertOut.envReflect = vertIn[vert].envReflect;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
vertOut.fogDist = vertIn[vert].fogDist;
|
||||
#endif
|
||||
#ifdef FLAG_SHADOWS
|
||||
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
|
||||
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
|
||||
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
|
||||
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
|
||||
vertOut.shadowPos = vertIn[vert].shadowPos;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
vertOut.notVisible = vertIn[vert].notVisible;
|
||||
#endif
|
||||
#ifdef FLAG_CLIP
|
||||
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
|
||||
#endif
|
||||
#else
|
||||
#if defined(FLAG_CLIP) || defined(FLAG_TRANSFORM)
|
||||
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
|
||||
#endif
|
||||
#endif
|
||||
EmitVertex();
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
#extension GL_ARB_gpu_shader5: enable
|
||||
|
||||
#include "shadows.sdr"
|
||||
|
||||
in vec4 vertPosition;
|
||||
in vec4 vertTexCoord;
|
||||
in vec3 vertNormal;
|
||||
in vec4 vertTangent;
|
||||
in float vertModelID;
|
||||
|
||||
#define MAX_LIGHTS 8
|
||||
|
||||
struct model_light {
|
||||
@@ -91,38 +99,40 @@ layout (std140) uniform modelData {
|
||||
int sMiscmapIndex;
|
||||
};
|
||||
|
||||
in vec4 vertPosition;
|
||||
in vec4 vertTexCoord;
|
||||
in vec3 vertNormal;
|
||||
in vec4 vertTangent;
|
||||
in float vertModelID;
|
||||
#ifdef FLAG_ENV_MAP
|
||||
out vec3 fragEnvReflect;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
out mat3 fragTangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
out float fragFogDist;
|
||||
#endif
|
||||
#ifdef FLAG_TRANSFORM
|
||||
uniform samplerBuffer transform_tex;
|
||||
#endif
|
||||
|
||||
out VertexOutput {
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vec3 envReflect;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
mat3 tangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
out float geoInstance;
|
||||
#endif
|
||||
out vec3 geoNormal;
|
||||
out vec4 geoTexCoord;
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
float instance;
|
||||
#endif
|
||||
#else
|
||||
out vec4 fragPosition;
|
||||
out vec3 fragNormal;
|
||||
out vec4 fragTexCoord;
|
||||
vec4 position;
|
||||
#endif
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
#ifdef FLAG_SHADOWS
|
||||
out vec4 fragShadowUV[4];
|
||||
out vec4 fragShadowPos;
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#endif
|
||||
} vertOut;
|
||||
|
||||
#ifdef FLAG_TRANSFORM
|
||||
#define TEXELS_PER_MATRIX 4
|
||||
void getModelTransform(inout mat4 transform, out bool invisible, int id, int matrix_offset)
|
||||
@@ -135,18 +145,6 @@ void getModelTransform(inout mat4 transform, out bool invisible, int id, int mat
|
||||
transform[3].w = 1.0;
|
||||
}
|
||||
#endif
|
||||
#ifdef FLAG_SHADOWS
|
||||
vec4 transformToShadowMap(int i, vec4 pos)
|
||||
{
|
||||
vec4 shadow_proj;
|
||||
shadow_proj = shadow_proj_matrix[i] * pos;
|
||||
shadow_proj += 1.0;
|
||||
shadow_proj *= 0.5;
|
||||
shadow_proj.w = shadow_proj.z;
|
||||
shadow_proj.z = float(i);
|
||||
return shadow_proj;
|
||||
}
|
||||
#endif
|
||||
void main()
|
||||
{
|
||||
vec4 position;
|
||||
@@ -154,12 +152,20 @@ void main()
|
||||
vec4 texCoord;
|
||||
mat4 orient = mat4(1.0);
|
||||
mat4 scale = mat4(1.0);
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
bool clipModel;
|
||||
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
|
||||
vertOut.notVisible = clipModel ? 1.0 : 0.0;
|
||||
#endif
|
||||
#else
|
||||
#ifdef FLAG_TRANSFORM
|
||||
bool clipModel;
|
||||
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
|
||||
#else
|
||||
bool clipModel = false;
|
||||
#endif
|
||||
#endif
|
||||
texCoord = textureMatrix * vertTexCoord;
|
||||
vec4 vertex = vertPosition;
|
||||
#ifdef FLAG_THRUSTER
|
||||
@@ -172,15 +178,13 @@ void main()
|
||||
position = modelViewMatrix * orient * vertex;
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
gl_Position = position;
|
||||
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
#ifdef APPLE
|
||||
geoInstance = float(gl_InstanceIDARB);
|
||||
#else
|
||||
geoInstance = float(gl_InstanceID);
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
#ifdef APPLE
|
||||
vertOut.instance = float(gl_InstanceIDARB);
|
||||
#else
|
||||
vertOut.instance = float(gl_InstanceID);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
gl_Position = projMatrix * position;
|
||||
#endif
|
||||
@@ -188,26 +192,34 @@ void main()
|
||||
gl_Position.xy += (mat3(projMatrix) * normal.xyz).xy * gl_Position.z * extrudeWidth;
|
||||
#endif
|
||||
#ifdef FLAG_SHADOWS
|
||||
fragShadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
|
||||
fragShadowUV[0] = transformToShadowMap(0, fragShadowPos);
|
||||
fragShadowUV[1] = transformToShadowMap(1, fragShadowPos);
|
||||
fragShadowUV[2] = transformToShadowMap(2, fragShadowPos);
|
||||
fragShadowUV[3] = transformToShadowMap(3, fragShadowPos);
|
||||
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
|
||||
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
|
||||
vertOut.shadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, shadowPos);
|
||||
vertOut.shadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, shadowPos);
|
||||
vertOut.shadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, shadowPos);
|
||||
vertOut.shadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, shadowPos);
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
// Setup stuff for normal maps
|
||||
vec3 t = normalize(mat3(modelViewMatrix) * mat3(orient) * vertTangent.xyz);
|
||||
vec3 b = cross(normal, t) * vertTangent.w;
|
||||
fragTangentMatrix = mat3(t, b, normal);
|
||||
vertOut.tangentMatrix = mat3(t, b, normal);
|
||||
#endif
|
||||
#ifdef FLAG_ENV_MAP
|
||||
// Environment mapping reflection vector.
|
||||
fragEnvReflect = reflect(normalize(position.xyz), normal);
|
||||
fragEnvReflect = vec3(envMatrix * vec4(fragEnvReflect, 0.0));
|
||||
vec3 envReflect = reflect(normalize(position.xyz), normal);
|
||||
vertOut.envReflect = vec3(envMatrix * vec4(envReflect, 0.0));
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
fragFogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
|
||||
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
if(use_clip_plane) {
|
||||
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
|
||||
} else {
|
||||
gl_ClipDistance[0] = 1.0;
|
||||
}
|
||||
#else
|
||||
#ifdef FLAG_CLIP
|
||||
if (clipModel) {
|
||||
gl_ClipDistance[0] = -1.0;
|
||||
@@ -219,12 +231,13 @@ void main()
|
||||
#elif defined(FLAG_TRANSFORM)
|
||||
gl_ClipDistance[0] = clipModel ? -1.0 : 1.0;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef FLAG_SHADOW_MAP
|
||||
fragPosition = position;
|
||||
fragNormal = normal;
|
||||
fragTexCoord = texCoord;
|
||||
vertOut.position = position;
|
||||
vertOut.normal = normal;
|
||||
vertOut.texCoord = texCoord;
|
||||
#else
|
||||
geoNormal = normal;
|
||||
geoTexCoord = texCoord;
|
||||
vertOut.normal = normal;
|
||||
vertOut.texCoord = texCoord;
|
||||
#endif
|
||||
}
|
||||
@@ -52,9 +52,6 @@ float strokeMask() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// The value the distance field has when the pixel is exactly on the edge. This needs to match the values in fontstash.h!
|
||||
const float ON_EDGE_DISTANCE = 180.0 / 255.0;
|
||||
|
||||
void main(void) {
|
||||
vec4 result;
|
||||
float scissor = scissorMask(fpos);
|
||||
@@ -93,16 +90,6 @@ void main(void) {
|
||||
vec4 color = texture(nvg_tex, vec3(ftcoord, float(texArrayIndex)));
|
||||
if (texType == 1) color = vec4(color.xyz*color.w,color.w); if (texType == 2) color = vec4(color.x); color *= scissor;
|
||||
result = color * innerCol;
|
||||
} else if (type == 4) { // Distance vector text
|
||||
vec4 color = texture(nvg_tex, vec3(ftcoord, float(texArrayIndex)));
|
||||
float dist = color.r;
|
||||
|
||||
float width = fwidth(dist) / 2.0;
|
||||
float alpha = smoothstep(ON_EDGE_DISTANCE - width, ON_EDGE_DISTANCE + width, dist);
|
||||
|
||||
color = innerCol * alpha;
|
||||
|
||||
result = color * scissor;
|
||||
}
|
||||
outColor = result;
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,12 @@
|
||||
|
||||
/**
|
||||
* @brief Unpacks a DXT5nm encoded normal
|
||||
* @param normal_sample The Alpha and Green channel of the DXT5 texture
|
||||
* @return The unpacked normal
|
||||
*/
|
||||
vec3 unpackNormal(vec2 normal_sample) {
|
||||
vec3 normal;
|
||||
normal.xy = normal_sample * 2.0 - 1.0;
|
||||
normal.z = sqrt(1 - normal_sample.x * normal_sample.x - normal_sample.y * normal_sample.y);
|
||||
return normal;
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
|
||||
#include "gamma.sdr"
|
||||
|
||||
in vec4 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
out vec4 fragOut0;
|
||||
uniform sampler2D baseMap;
|
||||
uniform int noTexturing;
|
||||
uniform int srgb;
|
||||
#define SRGB_GAMMA 2.2
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 baseColor = texture(baseMap, fragTexCoord.xy);
|
||||
|
||||
baseColor.rgb = (srgb == 1) ? pow(baseColor.rgb, vec3(SRGB_GAMMA)) : baseColor.rgb;
|
||||
vec4 blendColor = (srgb == 1) ? vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a) : fragColor;
|
||||
baseColor.rgb = (srgb == 1) ? srgb_to_linear(baseColor.rgb) : baseColor.rgb;
|
||||
vec4 blendColor = (srgb == 1) ? vec4(srgb_to_linear(fragColor.rgb), fragColor.a) : fragColor;
|
||||
fragOut0 = mix(baseColor * blendColor, blendColor, float(noTexturing));
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,105 @@
|
||||
|
||||
const float VARIANCE_SHADOW_SCALE = 1000000.0;
|
||||
const float VARIANCE_SHADOW_SCALE_INV = 1.0/VARIANCE_SHADOW_SCALE;
|
||||
|
||||
vec2 sampleShadowMap(sampler2DArray shadow_map, vec2 uv, vec2 offset_uv, int cascade, float shadowMapSizeInv)
|
||||
{
|
||||
return texture(shadow_map, vec3(uv + offset_uv * shadowMapSizeInv, float(cascade))).xy;
|
||||
}
|
||||
|
||||
float computeShadowFactor(float shadowDepth, vec2 moments, float bias)
|
||||
{
|
||||
float shadow = 1.0;
|
||||
if((moments.x - bias) > shadowDepth)
|
||||
{
|
||||
// variance shadow mapping using Chebychev's Formula
|
||||
float variance = moments.y * VARIANCE_SHADOW_SCALE - moments.x * moments.x;
|
||||
float mD = moments.x - bias - shadowDepth;
|
||||
shadow = variance / (variance + mD * mD);
|
||||
shadow = clamp(shadow, 0.0, 1.0);
|
||||
}
|
||||
return shadow;
|
||||
}
|
||||
|
||||
float sampleNoPCF(sampler2DArray shadow_map, float shadowDepth, int cascade, vec4 shadowUV[4])
|
||||
{
|
||||
return computeShadowFactor(shadowDepth, sampleShadowMap(shadow_map, shadowUV[cascade].xy, vec2(0.0, 0.0), cascade, 1.0/1024.0), 0.05);
|
||||
}
|
||||
|
||||
float samplePoissonPCF(sampler2DArray shadow_map, float shadowDepth, int cascade, vec4 shadowUV[4])
|
||||
{
|
||||
if(cascade > 3 || cascade < 0) return 1.0;
|
||||
vec2 poissonDisc[16];
|
||||
poissonDisc[0] = vec2(-0.76275, -0.3432573);
|
||||
poissonDisc[1] = vec2(-0.5226235, -0.8277544);
|
||||
poissonDisc[2] = vec2(-0.3780261, 0.01528688);
|
||||
poissonDisc[3] = vec2(-0.7742821, 0.4245702);
|
||||
poissonDisc[4] = vec2(0.04196143, -0.02622231);
|
||||
poissonDisc[5] = vec2(-0.2974772, -0.4722782);
|
||||
poissonDisc[6] = vec2(-0.516093, 0.71495);
|
||||
poissonDisc[7] = vec2(-0.3257416, 0.3910343);
|
||||
poissonDisc[8] = vec2(0.2705966, 0.6670476);
|
||||
poissonDisc[9] = vec2(0.4918377, 0.1853267);
|
||||
poissonDisc[10] = vec2(0.4428544, -0.6251478);
|
||||
poissonDisc[11] = vec2(-0.09204347, 0.9267113);
|
||||
poissonDisc[12] = vec2(0.391505, -0.2558275);
|
||||
poissonDisc[13] = vec2(0.05605913, -0.7570801);
|
||||
poissonDisc[14] = vec2(0.81772, -0.02475523);
|
||||
poissonDisc[15] = vec2(0.6890262, 0.5191521);
|
||||
float maxUVOffset[4];
|
||||
maxUVOffset[0] = 1.0/300.0;
|
||||
maxUVOffset[1] = 1.0/250.0;
|
||||
maxUVOffset[2] = 1.0/200.0;
|
||||
maxUVOffset[3] = 1.0/200.0;
|
||||
vec2 sum = sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[0], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[1], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[2], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[3], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[4], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[5], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[6], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[7], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[8], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[9], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[10], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[11], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[12], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[13], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[14], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
sum += sampleShadowMap(shadow_map, shadowUV[cascade].xy, poissonDisc[15], cascade, maxUVOffset[cascade])*(1.0/16.0);
|
||||
return computeShadowFactor(shadowDepth, sum, 0.1);
|
||||
}
|
||||
|
||||
float getShadowValue(sampler2DArray shadow_map, float depth, float shadowDepth, vec4 shadowUV[4], float fardist,
|
||||
float middist, float neardist, float veryneardist)
|
||||
{
|
||||
// Valathil's Shadows
|
||||
int cascade = 4;
|
||||
cascade -= int(step(depth, fardist));
|
||||
cascade -= int(step(depth, middist));
|
||||
cascade -= int(step(depth, neardist));
|
||||
cascade -= int(step(depth, veryneardist));
|
||||
float cascade_start_dist[5];
|
||||
cascade_start_dist[0] = 0.0;
|
||||
cascade_start_dist[1] = veryneardist;
|
||||
cascade_start_dist[2] = neardist;
|
||||
cascade_start_dist[3] = middist;
|
||||
cascade_start_dist[4] = fardist;
|
||||
if(cascade > 3 || cascade < 0) return 1.0;
|
||||
float dist_threshold = (cascade_start_dist[cascade+1] - cascade_start_dist[cascade])*0.2;
|
||||
if(cascade_start_dist[cascade+1] - dist_threshold > depth)
|
||||
return samplePoissonPCF(shadow_map, shadowDepth, cascade, shadowUV);
|
||||
return mix(samplePoissonPCF(shadow_map, shadowDepth, cascade, shadowUV), samplePoissonPCF(shadow_map, shadowDepth, cascade+1, shadowUV),
|
||||
smoothstep(cascade_start_dist[cascade+1] - dist_threshold, cascade_start_dist[cascade+1], depth));
|
||||
}
|
||||
|
||||
vec4 transformToShadowMap(mat4 shadow_proj_matrix, int i, vec4 pos)
|
||||
{
|
||||
vec4 shadow_proj;
|
||||
shadow_proj = shadow_proj_matrix * pos;
|
||||
shadow_proj += 1.0;
|
||||
shadow_proj *= 0.5;
|
||||
shadow_proj.w = shadow_proj.z;
|
||||
shadow_proj.z = float(i);
|
||||
return shadow_proj;
|
||||
}
|
||||
+5
-3
@@ -1,3 +1,6 @@
|
||||
|
||||
#include "gamma.sdr"
|
||||
|
||||
in vec4 fragImpactUV;
|
||||
in float fragNormOffset;
|
||||
uniform vec4 color;
|
||||
@@ -5,15 +8,14 @@ uniform sampler2DArray shieldMap;
|
||||
uniform int shieldMapIndex;
|
||||
uniform int srgb;
|
||||
out vec4 fragOut0;
|
||||
#define SRGB_GAMMA 2.2
|
||||
#define EMISSIVE_GAIN 2.0
|
||||
void main()
|
||||
{
|
||||
if(fragNormOffset < 0.0) discard;
|
||||
if(fragImpactUV.x < 0.0 || fragImpactUV.x > 1.0 || fragImpactUV.y < 0.0 || fragImpactUV.y > 1.0) discard;
|
||||
vec4 shieldColor = texture(shieldMap, vec3(fragImpactUV.xy, float(shieldMapIndex)));
|
||||
shieldColor.rgb = (srgb == 1) ? pow(shieldColor.rgb, vec3(SRGB_GAMMA)) * EMISSIVE_GAIN : shieldColor.rgb;
|
||||
shieldColor.rgb = (srgb == 1) ? srgb_to_linear(shieldColor.rgb) * EMISSIVE_GAIN : shieldColor.rgb;
|
||||
vec4 blendColor = color;
|
||||
blendColor.rgb = (srgb == 1) ? pow(blendColor.rgb, vec3(SRGB_GAMMA)) * EMISSIVE_GAIN : blendColor.rgb;
|
||||
blendColor.rgb = (srgb == 1) ? srgb_to_linear(blendColor.rgb) * EMISSIVE_GAIN : blendColor.rgb;
|
||||
fragOut0 = shieldColor * blendColor;
|
||||
}
|
||||
Loaded 100 of 793 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user