mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 18:31:26 -10:00
Compare commits
427
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce28f60cf1 | ||
|
|
3e858b601e | ||
|
|
f2314970bb | ||
|
|
366c1a9d0b | ||
|
|
0594a487c8 | ||
|
|
f8733eab72 | ||
|
|
8dcc4a24e9 | ||
|
|
bf4d7a3114 | ||
|
|
5e8a4f754d | ||
|
|
d0a537ff82 | ||
|
|
e7c98d6d23 | ||
|
|
36e7598ceb | ||
|
|
0672bd94e9 | ||
|
|
c7792cd781 | ||
|
|
252392b26a | ||
|
|
65677542cb | ||
|
|
691bbca2b2 | ||
|
|
cd95b143a0 | ||
|
|
a360a1f5f1 | ||
|
|
d1119b2353 | ||
|
|
c37e1b1c96 | ||
|
|
fd6ca9dde9 | ||
|
|
fbb3a8f6a5 | ||
|
|
0e63d64647 | ||
|
|
de50f693ae | ||
|
|
6e9b31cb5a | ||
|
|
e316c28258 | ||
|
|
1ef528af5f | ||
|
|
e536413259 | ||
|
|
ccbe7efcbe | ||
|
|
1fcf51bd92 | ||
|
|
b9938b854f | ||
|
|
ad06cb1c5b | ||
|
|
b62a7fbe3d | ||
|
|
4011a0800d | ||
|
|
8f7c6a0ed8 | ||
|
|
9e719440c9 | ||
|
|
6692540cbf | ||
|
|
668fc18d5c | ||
|
|
a101e3cf77 | ||
|
|
dcce4a6538 | ||
|
|
7ce3217f17 | ||
|
|
33a1b1f8ca | ||
|
|
a29a97f39a | ||
|
|
8d40d7467e | ||
|
|
eb57482c1a | ||
|
|
50f083043b | ||
|
|
d02bd6ca04 | ||
|
|
22962afcde | ||
|
|
1f9c9a3673 | ||
|
|
f3922f35e8 | ||
|
|
bb5bfad828 | ||
|
|
18ac8425ee | ||
|
|
f6167bb89a | ||
|
|
c8ceb289ba | ||
|
|
9ea64627ab | ||
|
|
6e9ca36481 | ||
|
|
90dbdc4236 | ||
|
|
3a35f7ebe7 | ||
|
|
05f190b36c | ||
|
|
0924a392aa | ||
|
|
21db833dee | ||
|
|
86011f2669 | ||
|
|
2bd143e093 | ||
|
|
79d3077071 | ||
|
|
aacd14e1df | ||
|
|
43afcd5ea6 | ||
|
|
b98544d862 | ||
|
|
7867dc77bd | ||
|
|
426c227b68 | ||
|
|
612bdcf4df | ||
|
|
0d712d6fc0 | ||
|
|
62fa0c081b | ||
|
|
8035a2b32a | ||
|
|
f7f2c58746 | ||
|
|
7bf0fd137d | ||
|
|
6d818f1e3b | ||
|
|
e23b5533aa | ||
|
|
6b79571edc | ||
|
|
27f022b2f2 | ||
|
|
4578fbc900 | ||
|
|
bfde2144a2 | ||
|
|
1787f4457b | ||
|
|
be14c34f7d | ||
|
|
da66bd65da | ||
|
|
dc7aa86147 | ||
|
|
4bf743765c | ||
|
|
b4e3ebe085 | ||
|
|
ada432a1f3 | ||
|
|
25d796afe4 | ||
|
|
1a034031d1 | ||
|
|
23098666e2 | ||
|
|
5490751167 | ||
|
|
4bc9cf0846 | ||
|
|
dd9248fc22 | ||
|
|
c2ed03ca59 | ||
|
|
7491a82d74 | ||
|
|
2f0c0f1d6f | ||
|
|
3b231b375f | ||
|
|
07fb5bec0e | ||
|
|
e51815a933 | ||
|
|
ea6e503ea1 | ||
|
|
a381ecc607 | ||
|
|
125e47d749 | ||
|
|
d280800bce | ||
|
|
a1c9b108ed | ||
|
|
d7a06c893f | ||
|
|
3aa672c855 | ||
|
|
8acbe82aa0 | ||
|
|
5227e2e0c4 | ||
|
|
95baa85750 | ||
|
|
fb1ffd8413 | ||
|
|
f43732c5da | ||
|
|
8dbe0e7b8a | ||
|
|
3ad66b988d | ||
|
|
969759426a | ||
|
|
224503391f | ||
|
|
0edc6267aa | ||
|
|
def75287eb | ||
|
|
c427014fc2 | ||
|
|
99d140fb83 | ||
|
|
808e5bedd9 | ||
|
|
6dfd1ed0b8 | ||
|
|
369b90a156 | ||
|
|
7bb6a8ae86 | ||
|
|
7afb00e976 | ||
|
|
c4fe9e664f | ||
|
|
eda9f16294 | ||
|
|
f7dddc35d1 | ||
|
|
b8806e958d | ||
|
|
40cf32133f | ||
|
|
691ec74406 | ||
|
|
359886fee1 | ||
|
|
9b86d2f16d | ||
|
|
260f15624b | ||
|
|
6de870766a | ||
|
|
072e802863 | ||
|
|
2ca9d6672c | ||
|
|
7281e8d127 | ||
|
|
a730f30435 | ||
|
|
cd5f044217 | ||
|
|
8b90cda3f4 | ||
|
|
6b2ced4643 | ||
|
|
5ee051c55f | ||
|
|
ecc452088c | ||
|
|
841ae430c0 | ||
|
|
3f7ffdb6a0 | ||
|
|
737717fe3f | ||
|
|
a463ac19cf | ||
|
|
9d0ee6ab0d | ||
|
|
703269aa71 | ||
|
|
b7a0170cd1 | ||
|
|
6f263365af | ||
|
|
6435843c24 | ||
|
|
22ee5d5c15 | ||
|
|
5fadb12b0f | ||
|
|
e94c515ab8 | ||
|
|
d83ddeed0f | ||
|
|
3556d41b44 | ||
|
|
f2df96b4bb | ||
|
|
9eeb3307d0 | ||
|
|
a406b43876 | ||
|
|
c86802e9c1 | ||
|
|
5b4065bd53 | ||
|
|
5fd439fb60 | ||
|
|
2043f836ed | ||
|
|
4a3c7fc9a9 | ||
|
|
e0e3f7e7ac | ||
|
|
542d9741c4 | ||
|
|
68eef5949b | ||
|
|
7958670868 | ||
|
|
226ed40cec | ||
|
|
d454a74716 | ||
|
|
4ff96abd9e | ||
|
|
5bc1200731 | ||
|
|
b23dff91e7 | ||
|
|
3af831e0b7 | ||
|
|
bcae459b56 | ||
|
|
ff7d85a60f | ||
|
|
267fcfc6f8 | ||
|
|
8587bf768b | ||
|
|
535ff9f99a | ||
|
|
422ccaa514 | ||
|
|
a3e27f566f | ||
|
|
9ecb451efe | ||
|
|
e3d2c02f99 | ||
|
|
13170a235e | ||
|
|
5406445ed4 | ||
|
|
301b9453b6 | ||
|
|
cd32c2ce42 | ||
|
|
7b1b1113da | ||
|
|
1f32834d9d | ||
|
|
bee0742aa2 | ||
|
|
d336d395db | ||
|
|
1953bd9c49 | ||
|
|
e27cbe9517 | ||
|
|
4b5d4320f8 | ||
|
|
ed7f3e6880 | ||
|
|
980d2c2bcc | ||
|
|
17dfa0ddb9 | ||
|
|
5f511e34e3 | ||
|
|
31c8739ecd | ||
|
|
8e23c32b8c | ||
|
|
b628b665cf | ||
|
|
7a367b10ad | ||
|
|
09c885c4af | ||
|
|
9ac6060abd | ||
|
|
a34f37fa8d | ||
|
|
7645704ac2 | ||
|
|
b25e76cb65 | ||
|
|
a9cfd27455 | ||
|
|
110f609dea | ||
|
|
ba3ac66958 | ||
|
|
274366c8ad | ||
|
|
df285b7ae1 | ||
|
|
7eec846b3d | ||
|
|
25a9f6abe2 | ||
|
|
f0737f1b87 | ||
|
|
dbefa6d333 | ||
|
|
54c0680b2a | ||
|
|
058cec3d2c | ||
|
|
a73cc9bfce | ||
|
|
245ac3f6b3 | ||
|
|
ee6159c685 | ||
|
|
68f9d90629 | ||
|
|
2523218fdc | ||
|
|
b323760659 | ||
|
|
5a93f78933 | ||
|
|
e99341d79f | ||
|
|
54a188d46a | ||
|
|
f686046a1d | ||
|
|
61f8e0370b | ||
|
|
397125fc6e | ||
|
|
6f458d5398 | ||
|
|
1223808a14 | ||
|
|
19c4c6edba | ||
|
|
bfeb86f017 | ||
|
|
e7ded2b4cd | ||
|
|
b2d1da6701 | ||
|
|
d0086c31b8 | ||
|
|
d9786f8aae | ||
|
|
fe916eb7ce | ||
|
|
a476897963 | ||
|
|
e404f32c7b | ||
|
|
77a2f5345f | ||
|
|
41efb57879 | ||
|
|
729aa2f6f7 | ||
|
|
346ce5c975 | ||
|
|
d1d64a0afb | ||
|
|
94cd6cf8bb | ||
|
|
9b09818b49 | ||
|
|
1ab0d74939 | ||
|
|
474db9e184 | ||
|
|
36cb7a62d6 | ||
|
|
cb1f1e9c0b | ||
|
|
9dc291569f | ||
|
|
5da1a075ad | ||
|
|
ad05ce147e | ||
|
|
9a227de872 | ||
|
|
d4ca441449 | ||
|
|
4ea99eb461 | ||
|
|
e01dabeb59 | ||
|
|
27e80a3fff | ||
|
|
3ab8cb097c | ||
|
|
3721f8165d | ||
|
|
f94119d722 | ||
|
|
5e78054a66 | ||
|
|
cfe64748a4 | ||
|
|
7a281781e3 | ||
|
|
a859192587 | ||
|
|
fa49d05e0c | ||
|
|
d8ff77f57f | ||
|
|
fdc8c246f5 | ||
|
|
395aadba6b | ||
|
|
1625d86ad7 | ||
|
|
187d24c2f4 | ||
|
|
47ac8a56a0 | ||
|
|
72ccbff147 | ||
|
|
9960d4bc9f | ||
|
|
2334138b99 | ||
|
|
a0b7134b9b | ||
|
|
b20efdec80 | ||
|
|
b546dcf949 | ||
|
|
15329b9564 | ||
|
|
94bd1af5cd | ||
|
|
367f48cf2f | ||
|
|
eff00035fa | ||
|
|
ba2c2f03fb | ||
|
|
309bf0b3ea | ||
|
|
b62c49ec81 | ||
|
|
e34c82d7d1 | ||
|
|
67e00da79b | ||
|
|
8528bfe750 | ||
|
|
37c344a127 | ||
|
|
b5b922cbf0 | ||
|
|
1cbeae2cd9 | ||
|
|
4292303018 | ||
|
|
3ebdc51c48 | ||
|
|
6e8ab64523 | ||
|
|
1b04d9f22c | ||
|
|
4013cf6046 | ||
|
|
26df8e9a45 | ||
|
|
bb3e3eadfc | ||
|
|
b5e215a85c | ||
|
|
da4eeb3582 | ||
|
|
dc578c2479 | ||
|
|
3522f3be91 | ||
|
|
bd52d75ab9 | ||
|
|
a54dc0ded7 | ||
|
|
c076cd11f1 | ||
|
|
b42c7af847 | ||
|
|
5893ef836c | ||
|
|
9eeb7e7983 | ||
|
|
71fa18927c | ||
|
|
ae89ed2b9d | ||
|
|
24a4c0df6a | ||
|
|
a5f90ddcc1 | ||
|
|
3fe94fc3f4 | ||
|
|
f89d437506 | ||
|
|
86a8c1c6f5 | ||
|
|
f72fb68615 | ||
|
|
3447b76736 | ||
|
|
7dd52a4214 | ||
|
|
8671b9e2f7 | ||
|
|
b861989fb6 | ||
|
|
1c8a272eca | ||
|
|
221b0dc7ee | ||
|
|
0a5cf6ad9d | ||
|
|
2cb12b8ff7 | ||
|
|
9f173e8cd9 | ||
|
|
6588daaca5 | ||
|
|
9cd648a206 | ||
|
|
44c797f65b | ||
|
|
46b9c27dfe | ||
|
|
33e3b13d43 | ||
|
|
8351d4f623 | ||
|
|
e0443739bd | ||
|
|
80a206151c | ||
|
|
64a592d0d5 | ||
|
|
c30559a63a | ||
|
|
245cec5a34 | ||
|
|
ddedc1bd8e | ||
|
|
6b71812e7b | ||
|
|
844e9affea | ||
|
|
b69cdc08ee | ||
|
|
69d56172b0 | ||
|
|
9d2a89f778 | ||
|
|
adcc19085d | ||
|
|
faddde8307 | ||
|
|
0355d2b8d1 | ||
|
|
21f42ce47b | ||
|
|
574b1e6197 | ||
|
|
34e57d301a | ||
|
|
dc83e4f14a | ||
|
|
3c837b7e9a | ||
|
|
c7b77a5b24 | ||
|
|
5a58ff46f2 | ||
|
|
4145717363 | ||
|
|
eca583074a | ||
|
|
723bdcb9f1 | ||
|
|
cb4fe955ea | ||
|
|
ed83ed79ec | ||
|
|
02669338e8 | ||
|
|
6e86a3a035 | ||
|
|
4f8344c91e | ||
|
|
643d18c6f8 | ||
|
|
8dc481d034 | ||
|
|
3ba2193d3f | ||
|
|
8693fa37eb | ||
|
|
3764146957 | ||
|
|
50c923d397 | ||
|
|
617c903cbd | ||
|
|
b6903fbdf4 | ||
|
|
dc751a9c5d | ||
|
|
dff0b2acb4 | ||
|
|
ea10ac157f | ||
|
|
173a3d23e8 | ||
|
|
98e20c0979 | ||
|
|
db02a829aa | ||
|
|
cfe92a4d32 | ||
|
|
7f9a10a9a0 | ||
|
|
925e2e53f4 | ||
|
|
0e7f24bcac | ||
|
|
b2d85b8e2f | ||
|
|
e23409f5f8 | ||
|
|
381e45f483 | ||
|
|
2d2db58905 | ||
|
|
2b3da41a6d | ||
|
|
9da948be56 | ||
|
|
79454fb6c4 | ||
|
|
10ed12182c | ||
|
|
729e448fe5 | ||
|
|
96ae3d0608 | ||
|
|
55ed0a08f6 | ||
|
|
c017ef9b8a | ||
|
|
e071603ac0 | ||
|
|
e6792ab441 | ||
|
|
5d6c34c2ab | ||
|
|
17ad0e09dd | ||
|
|
a0c787aa83 | ||
|
|
ee27abf693 | ||
|
|
6bcd2f730c | ||
|
|
c8d78816b0 | ||
|
|
b53f3fc803 | ||
|
|
d1f0b9343f | ||
|
|
0b2d4768f3 | ||
|
|
42fc9891e3 | ||
|
|
bfd261a1d3 | ||
|
|
0c8564f085 | ||
|
|
6d08a90106 | ||
|
|
92ed875e69 | ||
|
|
1dc701270f | ||
|
|
41b10e4d40 | ||
|
|
f2d0bfdb31 | ||
|
|
6350a67e73 | ||
|
|
bfad425738 | ||
|
|
e387038cc3 | ||
|
|
52b7a3d198 | ||
|
|
b7045f1756 | ||
|
|
accb842ffa | ||
|
|
97adef1d87 | ||
|
|
bb6917ab3b | ||
|
|
861a9c9c4a | ||
|
|
d2d1d8f996 | ||
|
|
46530b78b7 | ||
|
|
cf3b5e8085 | ||
|
|
71ac62e395 |
No files matched your search
@@ -6,7 +6,7 @@ on:
|
||||
- 'nightly_*'
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -15,36 +15,17 @@ jobs:
|
||||
configuration: [FastDebug, Release]
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
submodules: true
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: gcc-5
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -64,7 +45,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linux-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/install/*.AppImage
|
||||
@@ -80,12 +61,12 @@ jobs:
|
||||
submodules: true
|
||||
fetch-depth: '0'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-Release
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-FastDebug
|
||||
path: builds
|
||||
@@ -183,7 +164,7 @@ jobs:
|
||||
shell: bash
|
||||
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: ${{ github.workspace }}/build/install/*
|
||||
@@ -203,12 +184,12 @@ jobs:
|
||||
submodules: true
|
||||
fetch-depth: '0'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
@@ -234,7 +215,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [FastDebug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
@@ -276,6 +257,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -284,23 +266,27 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Package build result
|
||||
working-directory: ./build/bin
|
||||
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
|
||||
# Ref: https://github.com/actions/runner-images/issues/2619
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mac-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
|
||||
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
|
||||
mac_zip:
|
||||
name: Build Mac distribution zip
|
||||
needs: build_mac
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout
|
||||
@@ -309,22 +295,24 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-Release
|
||||
name: mac-Release-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-FastDebug
|
||||
name: mac-FastDebug-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Unpack builds
|
||||
working-directory: ./builds
|
||||
run: |
|
||||
tar -xvzf macos-build-Release.tgz
|
||||
tar -xvzf macos-build-FastDebug.tgz
|
||||
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
|
||||
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
|
||||
- name: Create Distribution package
|
||||
working-directory: ./builds
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
|
||||
- name: Upload result package
|
||||
working-directory: ./builds
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
- 'release_*'
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
create_release:
|
||||
@@ -44,65 +44,19 @@ jobs:
|
||||
name: Linux
|
||||
needs: create_release # Don't run this job until create_release is done and successful
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# cache the Qt directory so we don't have to reinstall it every time
|
||||
# cache.inputs:
|
||||
# path - A list of files, directories, and wildcard patterns to cache and restore. See @actions/glob for supported patterns.
|
||||
# key - An explicit key for restoring and saving the cache
|
||||
# restore-keys - An ordered list of keys to use for restoring the cache if no cache hit occurred for key
|
||||
# cache.outputs:
|
||||
# cache-hit true when an exact match was found for the key, false otherwise.
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# installs Qt in the action workflow
|
||||
# install-qt-action.inputs:
|
||||
# version desired qt version to install
|
||||
# host Host platform of Qt, default to platform used by runs-on
|
||||
# target target platform of Qt, default to desktop
|
||||
# arch target architecture of Qt, only used for windows or android builds
|
||||
# dir root dir Qt will be installed to
|
||||
# install-deps if true, auto-install dependencies on linux. Default true
|
||||
# modules whitespace delimited list string of additional addon modules to install
|
||||
# archives whitespace delimited list string of Qt archives to install
|
||||
# cached if true, Don't download Qt but set ENVARs; use with cache.outputs.cache-hit
|
||||
# setup-python Set to false to skip using setup-python to find/download a valid python version
|
||||
# set-env if true, set ENVARs; default = false
|
||||
# aqtversion version of aqtinstall to use; default = 2.0.0
|
||||
# py7zrversion version of py7zr to use; default = 0.16.1
|
||||
# extra additional arguments to pass to aqinstall
|
||||
# ENVARS set:
|
||||
# Qt5_DIR / Qt6_DIR
|
||||
# Qt bin dir appended to PATH
|
||||
# QT_PLUGIN_PATH, QML2_IMPORT_PATH, PKG_CONFIG_PATH, LD_LIBRARY_PATH
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
# checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
|
||||
name: Checkout
|
||||
with:
|
||||
submodules: true # `true` to checkout submodules, `recursive` to recursively checkout submodules
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: gcc-5
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -122,7 +76,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
# Upload the url file for use with other runners
|
||||
# upload-artifact.inputs:
|
||||
# if-no-files-found=warn What to do if path fails to find any files.
|
||||
@@ -149,13 +103,13 @@ jobs:
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
# Grab the release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-Release
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
# Grab the debug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-FastDebug
|
||||
path: builds
|
||||
@@ -166,7 +120,7 @@ jobs:
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
|
||||
- name: Upload result package
|
||||
# Stash the result to artifact filespace
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.package_name }}
|
||||
path: ${{ steps.generate_package.outputs.package_path }}
|
||||
@@ -266,7 +220,7 @@ jobs:
|
||||
shell: bash
|
||||
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: ${{ github.workspace }}/build/install/*
|
||||
@@ -290,13 +244,13 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
@@ -311,13 +265,13 @@ jobs:
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Windows
|
||||
|
||||
- name: Upload result package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.package_name }}
|
||||
path: ${{ steps.generate_package.outputs.package_path }}
|
||||
|
||||
- name: Upload debug package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.debug_name }}
|
||||
path: ${{ steps.generate_package.outputs.debug_path }}
|
||||
@@ -336,7 +290,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [FastDebug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
name: Mac
|
||||
needs: create_release
|
||||
runs-on: macos-latest
|
||||
@@ -373,6 +327,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -381,23 +336,27 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Package build result
|
||||
working-directory: ./build/bin
|
||||
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
|
||||
# Ref: https://github.com/actions/runner-images/issues/2619
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mac-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
|
||||
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
|
||||
mac_zip:
|
||||
name: Build Mac distribution zip
|
||||
needs: build_mac
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout
|
||||
@@ -406,26 +365,28 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-Release
|
||||
name: mac-Release-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-FastDebug
|
||||
name: mac-FastDebug-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Unpack builds
|
||||
working-directory: ./builds
|
||||
run: |
|
||||
tar -xvzf macos-build-Release.tgz
|
||||
tar -xvzf macos-build-FastDebug.tgz
|
||||
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
|
||||
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
|
||||
- name: Create Distribution package
|
||||
id: generate_package
|
||||
working-directory: ./builds
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
|
||||
- name: Upload result package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.package_name }}
|
||||
path: ${{ steps.generate_package.outputs.package_path }}
|
||||
|
||||
@@ -24,12 +24,6 @@ jobs:
|
||||
name: Checkout
|
||||
with:
|
||||
submodules: true
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
- 'test/*'
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -15,22 +15,8 @@ jobs:
|
||||
configuration: [FastDebug, Release]
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
@@ -41,16 +27,11 @@ jobs:
|
||||
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
|
||||
# Override the revision string so that the builds are named correctly
|
||||
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: gcc-5
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -70,7 +51,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linux-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/install/*.AppImage
|
||||
@@ -87,12 +68,12 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-Release
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-FastDebug
|
||||
path: builds
|
||||
@@ -196,7 +177,7 @@ jobs:
|
||||
shell: bash
|
||||
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: ${{ github.workspace }}/build/install/*
|
||||
@@ -217,12 +198,12 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
@@ -248,7 +229,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [FastDebug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
@@ -289,6 +270,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -297,23 +279,27 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Package build result
|
||||
working-directory: ./build/bin
|
||||
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
|
||||
# Ref: https://github.com/actions/runner-images/issues/2619
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mac-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
|
||||
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
|
||||
mac_zip:
|
||||
name: Build Mac distribution zip
|
||||
needs: build_mac
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout
|
||||
@@ -322,22 +308,24 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-Release
|
||||
name: mac-Release-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-FastDebug
|
||||
name: mac-FastDebug-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Unpack builds
|
||||
working-directory: ./builds
|
||||
run: |
|
||||
tar -xvzf macos-build-Release.tgz
|
||||
tar -xvzf macos-build-FastDebug.tgz
|
||||
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
|
||||
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
|
||||
- name: Create Distribution package
|
||||
working-directory: ./builds
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
|
||||
- name: Upload result package
|
||||
working-directory: ./builds
|
||||
|
||||
@@ -6,42 +6,27 @@ on:
|
||||
- master
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [Debug, Release]
|
||||
compiler: [gcc-5, gcc-10]
|
||||
compiler: [gcc-5, gcc-13, clang-16]
|
||||
cmake_options: [""]
|
||||
include:
|
||||
# Also include configurations that check if the code compiles without the graphics backends
|
||||
- configuration: Debug
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
- configuration: Release
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
@@ -50,13 +35,22 @@ jobs:
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
|
||||
- name: Configure ccache
|
||||
run: |
|
||||
ccache --set-config=sloppiness=pch_defines,time_macros
|
||||
ccache -p
|
||||
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
CCACHE_PATH: /usr/local/bin/ccache
|
||||
ENABLE_QTFRED: ON
|
||||
Qt5_DIR: /qt/${{ env.QT_VERSION }}/gcc_64/lib/cmake/Qt5
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
run: LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja -k 20 all
|
||||
- name: Show CCache statistics
|
||||
run: ccache --show-stats
|
||||
@@ -3,41 +3,27 @@ name: Check a pull request
|
||||
on: [pull_request]
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [Debug, Release]
|
||||
compiler: [gcc-5, gcc-10, clang-9]
|
||||
compiler: [gcc-5, gcc-13, clang-16]
|
||||
cmake_options: [""]
|
||||
include:
|
||||
# Also include configurations that check if the code compiles without the graphics backends
|
||||
- configuration: Debug
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
- configuration: Release
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
@@ -47,17 +33,18 @@ jobs:
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
save: false # Caches are created by a separate job and only restored for PRs
|
||||
verbose: 1
|
||||
- name: Configure ccache
|
||||
run: ccache --set-config=sloppiness=pch_defines,time_macros
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
CCACHE_PATH: /usr/local/bin/ccache
|
||||
ENABLE_QTFRED: ON
|
||||
Qt5_DIR: /qt/${{ env.QT_VERSION }}/gcc_64/lib/cmake/Qt5
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -68,6 +55,8 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Show CCache statistics
|
||||
run: ccache --show-stats
|
||||
- name: Run Clang Tidy
|
||||
# Clang-tidy reuses the precompiled headers so this only makes sense for the clang compilers
|
||||
if: startsWith(matrix.compiler, 'clang-')
|
||||
@@ -182,7 +171,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [Debug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
cmake_options: [""]
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
@@ -210,7 +199,8 @@ jobs:
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}-${{ matrix.arch }}
|
||||
save: false # Caches are created by a separate job and only restored for PRs
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
@@ -223,6 +213,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -231,6 +222,7 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Run Clang Tidy
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
name: Weekly Coverity Scan for Freespace Open
|
||||
# adapted from code by "albert-github" on the doxygen repository
|
||||
# many thanks for figuring this out first so it could be less painful for us!
|
||||
|
||||
#This mode is for testing
|
||||
on: [push, pull_request]
|
||||
|
||||
# In production, push on a specific schedule
|
||||
#on:
|
||||
# schedule:
|
||||
# - cron: "5 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.12
|
||||
coverity_email: [email protected]
|
||||
coverity_token: ${{ secrets.COVERITY_TOKEN }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build FSO With Coverity Wrapper
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- { name: "GCC on ubuntu", os: ubuntu-latest, build_type: "Release" }
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive # `true` to checkout submodules, `recursive` to recursively checkout submodules
|
||||
|
||||
# pipe results of wget to a log file because it's very verbose and rarely fails
|
||||
- name: Install Coverity
|
||||
run: |
|
||||
wget -o wgetlog.txt -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=${{ env.coverity_token }}&project=scp-fs2open/fs2open.github.com" -O coverity_tool.tgz
|
||||
mkdir cov-scan
|
||||
tar ax -f coverity_tool.tgz --strip-components=1 -C cov-scan
|
||||
|
||||
- name: Setup Environment
|
||||
run: |
|
||||
echo "$(pwd)/cov-scan/bin" >> $GITHUB_PATH
|
||||
echo "NPROC=$(getconf _NPROCESSORS_ONLN)" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure CMake for FSO
|
||||
env:
|
||||
CONFIGURATION: Release
|
||||
compiler: gcc-5
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
|
||||
- name: Build FSO with Coverity Wrapper
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: Release
|
||||
run: cov-build --dir cov-int ninja -k 20 all
|
||||
|
||||
- name: Compress Results
|
||||
working-directory: ./build
|
||||
run: tar zcf cov-scan.tgz cov-int
|
||||
|
||||
#Comment this out when testing to keep from running into upload limits
|
||||
- name: Upload to Coverity
|
||||
run: |
|
||||
cd build
|
||||
curl --form token=${{ env.coverity_token }} --form email=${{ env.coverity_email }} --form [email protected] --form version="$(git rev-parse HEAD)" --form description="Automatic GHA scan" 'https://scan.coverity.com/builds?project=scp-fs2open/fs2open.github.com'
|
||||
+3
-14
@@ -47,20 +47,6 @@ endif()
|
||||
|
||||
PROJECT(FS2_Open LANGUAGES ${FSO_LANGUAGES})
|
||||
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
# Currently only GCC support ccache properly without generating additional warnings
|
||||
# Enable ccache on Mac even for clang
|
||||
if(CCACHE_PROGRAM AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR APPLE))
|
||||
if(NOT CMAKE_C_COMPILER_LAUNCHER)
|
||||
message(STATUS "Using ccache for C compilation: ${CCACHE_PROGRAM}")
|
||||
SET(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
||||
endif()
|
||||
if(NOT CMAKE_CXX_COMPILER_LAUNCHER)
|
||||
message(STATUS "Using ccache for C++ compilation: ${CCACHE_PROGRAM}")
|
||||
SET(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
||||
endif()
|
||||
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)
|
||||
@@ -141,6 +127,8 @@ OPTION(FSO_BUILD_WITH_OPENGL_DEBUG "Enables debug option for OpenGL" OFF)
|
||||
|
||||
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" OFF)
|
||||
|
||||
OPTION(FSO_BUILD_WITH_OPENXR_DEBUG "Enables debug option for OpenXR" OFF)
|
||||
|
||||
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
|
||||
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
|
||||
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
|
||||
@@ -154,6 +142,7 @@ mark_as_advanced(FORCE FSO_BUILD_WITH_FFMPEG)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL_DEBUG)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_VULKAN)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENXR_DEBUG)
|
||||
|
||||
# Include cotire file from https://github.com/sakra/cotire/
|
||||
include(cotire)
|
||||
|
||||
@@ -4,14 +4,13 @@ if [ "$COMPILER" = "gcc-5" ]; then
|
||||
export CC=gcc-5
|
||||
export CXX=g++-5
|
||||
fi
|
||||
if [ "$COMPILER" = "gcc-10" ]; then
|
||||
export CC=gcc-10
|
||||
export CXX=g++-10
|
||||
if [ "$COMPILER" = "gcc-13" ]; then
|
||||
export CC=gcc-13
|
||||
export CXX=g++-13
|
||||
fi
|
||||
if [ "$COMPILER" = "clang-9" ]; then
|
||||
# Work around bug in clang that uses the wrong installation directory: https://bugs.llvm.org/show_bug.cgi?id=47460
|
||||
export CC=$(readlink -f $(which clang-9))
|
||||
export CXX=$(readlink -f $(which clang++-9))
|
||||
if [ "$COMPILER" = "clang-16" ]; then
|
||||
export CC=clang-16
|
||||
export CXX=clang++-16
|
||||
fi
|
||||
|
||||
LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH
|
||||
@@ -34,6 +33,11 @@ if [[ "$COMPILER" =~ ^clang.*$ ]]; then
|
||||
CXXFLAGS="$CXXFLAGS -Qunused-arguments"
|
||||
fi
|
||||
|
||||
if [ ! "$CCACHE_PATH" = "" ]; then
|
||||
echo "Using ccache at $CCACHE_PATH"
|
||||
CMAKE_OPTIONS="$CMAKE_OPTIONS -DCMAKE_C_COMPILER_LAUNCHER=$CCACHE_PATH -DCMAKE_CXX_COMPILER_LAUNCHER=$CCACHE_PATH"
|
||||
fi
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
@@ -44,7 +48,11 @@ export LD_LIBRARY_PATH
|
||||
if [ "$RUNNER_OS" = "macOS" ]; then
|
||||
brew install ninja
|
||||
fi
|
||||
|
||||
# CMAKE_JOB_POOLS and CMAKE_JOB_POOL_LINK ensure that when using ninja, link operations are done sequentially
|
||||
# we have some build rules that do not play nice with parallel invocation and that fixes these issues
|
||||
|
||||
cmake -G Ninja -DFSO_FATAL_WARNINGS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON $CMAKE_OPTIONS $PLATFORM_CMAKE_OPTIONS \
|
||||
-DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DCMAKE_BUILD_TYPE=$CONFIGURATION \
|
||||
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=OFF \
|
||||
-DSHADERS_ENABLE_COMPILATION=ON ..
|
||||
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=${ENABLE_QTFRED:-OFF} \
|
||||
-DSHADERS_ENABLE_COMPILATION=ON -DCMAKE_JOB_POOLS=link=1 -DCMAKE_JOB_POOL_LINK=link ..
|
||||
@@ -26,11 +26,11 @@ elif [ "$OS" = "Windows" ]; then
|
||||
echo "debug_name=$(get_package_name)-debug-$ARCH-$SIMD.7z" >> $GITHUB_OUTPUT
|
||||
echo "debug_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z")" >> $GITHUB_OUTPUT
|
||||
elif [ "$OS" = "Mac" ]; then
|
||||
tar -cvzf "$(get_package_name)-builds-Mac.tar.gz" *.app
|
||||
tar -cvzf "$(get_package_name)-builds-Mac-$ARCH.tar.gz" *.app
|
||||
|
||||
echo "package_path=$(pwd)/$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_name=$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac.tar.gz")" >> $GITHUB_OUTPUT
|
||||
echo "package_path=$(pwd)/$(get_package_name)-builds-Mac-$ARCH.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_name=$(get_package_name)-builds-Mac-$ARCH.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac-$ARCH.tar.gz")" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Invalid OS: $OS"
|
||||
fi
|
||||
@@ -5,6 +5,13 @@ HERE=$(dirname "$SCRIPT")
|
||||
|
||||
export LD_LIBRARY_PATH=$(pwd)/bin/lib:$LD_LIBRARY_PATH
|
||||
|
||||
# if on mac and building for architecture that doesn't match host
|
||||
# then unittests will fail so we just need to skip it (for now)
|
||||
if [ "$RUNNER_OS" = "macOS" ] && [ "$ARCH" != "$(uname -m)" ]; then
|
||||
echo "Skipping tests due to architecture mismatch!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$CONFIGURATION" = "Debug"] && [[ "$RUNNER_OS" != "macOS" ]] ; then
|
||||
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
|
||||
--suppressions="$HERE/valgrind.supp" ./bin/unittests --gtest_shuffle
|
||||
|
||||
+9
-5
@@ -8,7 +8,8 @@ from file_list import ReleaseFile
|
||||
from util import retry_multi, GLOBAL_TIMEOUT
|
||||
|
||||
LINUX_KEY = "Linux"
|
||||
MACOSX_KEY = "Mac"
|
||||
MACOSX_X64_KEY = "Mac-x86_64"
|
||||
MACOSX_ARM64_KEY = "Mac-arm64"
|
||||
WIN32_SSE2_KEY = "Win32-SSE2"
|
||||
WIN64_SSE2_KEY = "Win64-SSE2"
|
||||
WIN32_AVX_KEY = "Win32-AVX"
|
||||
@@ -34,7 +35,8 @@ metadata = {
|
||||
|
||||
platforms = {
|
||||
LINUX_KEY: 'linux',
|
||||
MACOSX_KEY: 'macosx',
|
||||
MACOSX_X64_KEY: 'macosx',
|
||||
MACOSX_ARM64_KEY: 'macosx',
|
||||
WIN32_SSE2_KEY: 'windows',
|
||||
WIN64_SSE2_KEY: 'windows',
|
||||
WIN32_AVX_KEY: 'windows',
|
||||
@@ -43,7 +45,8 @@ platforms = {
|
||||
|
||||
envs = {
|
||||
LINUX_KEY: 'linux && x86_64', # Linux only has 64bit builds
|
||||
MACOSX_KEY: 'macosx',
|
||||
MACOSX_X64_KEY: 'macosx && x86_64',
|
||||
MACOSX_ARM64_KEY: 'macosx && arm64',
|
||||
WIN32_SSE2_KEY: 'windows',
|
||||
WIN64_SSE2_KEY: 'windows && x86_64',
|
||||
WIN32_AVX_KEY: 'windows && avx',
|
||||
@@ -135,7 +138,7 @@ def render_nebula_release(version, stability, files, config):
|
||||
'label': label,
|
||||
'properties': props,
|
||||
})
|
||||
elif group == MACOSX_KEY and fn.startswith(os.path.basename(fn) + '.app/'):
|
||||
elif group.startswith('Mac') and fn.startswith(os.path.basename(fn) + '.app/'):
|
||||
if 'qtfred' in fn:
|
||||
if '-FASTDBG' in fn:
|
||||
label = 'QtFRED Debug'
|
||||
@@ -148,7 +151,8 @@ def render_nebula_release(version, stability, files, config):
|
||||
label = None
|
||||
|
||||
props = {
|
||||
"x64": True, # All Mac builds are 64-bit
|
||||
"arm64": "arm64" in fn,
|
||||
"x64": "x64" in fn,
|
||||
"sse2": True, # There are no forced options on mac but 64-bit always implies SSE2 so we set that here
|
||||
"avx": False,
|
||||
"avx2": False,
|
||||
|
||||
@@ -53,8 +53,9 @@ Alternatively, if there is a package in your software repository then you should
|
||||
|
||||
|
||||
[img]https://scp.indiegames.us/img/mac-icon.png[/img] [color=green][size=12pt]macOS[/size][/color]
|
||||
[size=8pt]macOS 10.9+, 64-bit (Intel)[/size]
|
||||
${build(groups["Mac"].mainFile)}
|
||||
[size=8pt]macOS 10.9+[/size]
|
||||
[b]Intel (64-bit):[/b] ${build(groups["Mac"].subFiles["x86_64"])}
|
||||
[b]Apple Silicon:[/b] ${build(groups["Mac"].subFiles["arm64"])}
|
||||
|
||||
These builds are not signed and so by default will fail to launch. To run them simply right-click on the app, click open, then click open again on the security confirmation dialog. You should only have to do this once for each app.
|
||||
If running the game through Knossos or Knossos.NET this step should not be necessary.
|
||||
|
||||
@@ -7,3 +7,9 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
else()
|
||||
set(IS_64BIT FALSE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)")
|
||||
set(IS_ARM64 TRUE)
|
||||
else()
|
||||
set(IS_ARM64 FALSE)
|
||||
endif()
|
||||
@@ -22,6 +22,14 @@ SET(LIBRAY_DESTINATION "../Frameworks")
|
||||
|
||||
set(PLATFORM_MAC TRUE CACHE INTERNAL "" FORCE)
|
||||
|
||||
# Maybe override arm64 setting if we are compiling for different architecture
|
||||
# If not specified, or if it's a universal build, then this should do nothing
|
||||
if(CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
|
||||
set(IS_ARM64 TRUE)
|
||||
elseif(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
|
||||
set(IS_ARM64 FALSE)
|
||||
endif()
|
||||
|
||||
# Generate and don't strip debug symbols
|
||||
# These settings don't seem to generate debug symbols for code and Freespace2
|
||||
# so those settings are set manually in code and Freespace2's CMakeLists.txt files
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#cmakedefine SCP_HAVE_STD_MAX_ALIGN_T
|
||||
|
||||
#cmakedefine01 IS_64BIT
|
||||
#cmakedefine01 IS_ARM64
|
||||
|
||||
#cmakedefine01 SCP_HAVE_STRCASECMP
|
||||
#cmakedefine01 SCP_HAVE_STRNCASECMP
|
||||
|
||||
@@ -83,20 +83,41 @@ if(SUPPORTS_SHIFT_NEGATIVE_VALUE)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-shift-negative-value")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
|
||||
# Check if there is a user-set optimisation flag
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
|
||||
# If no user-set opt flag, set -O2 and -Og
|
||||
if ("${CXX_OPT_FLAG}" STREQUAL "")
|
||||
set(CXX_OPT_FLAG_RELEASE "-O2")
|
||||
set(CXX_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
|
||||
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
|
||||
endif()
|
||||
if ("${C_OPT_FLAG}" STREQUAL "")
|
||||
set(C_OPT_FLAG_RELEASE "-O2")
|
||||
set(C_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
|
||||
set(C_OPT_FLAG_DEBUG "${C_OPT_FLAG}")
|
||||
endif()
|
||||
|
||||
# Always use the base flags and add our compiler flags at the bacl
|
||||
set(CXX_FLAGS_RELEASE "${CXX_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-parameter")
|
||||
set(C_FLAGS_RELEASE "${C_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-parameter")
|
||||
|
||||
set(CXX_FLAGS_DEBUG "${CXX_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
set(C_FLAGS_DEBUG "${C_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
|
||||
# Always use the base flags and add our compiler flags at the back
|
||||
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${C_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS_DEBUG})
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "")
|
||||
|
||||
|
||||
@@ -113,19 +113,41 @@ if(SUPPORTS_STRINGOP_TRUNCATION)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-overflow")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
# Check if there is a user-set optimisation flag
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
|
||||
# If no user-set opt flag, set -O2 and -Og
|
||||
if ("${CXX_OPT_FLAG}" STREQUAL "")
|
||||
set(CXX_OPT_FLAG_RELEASE "-O2")
|
||||
set(CXX_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
|
||||
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
|
||||
endif()
|
||||
if ("${C_OPT_FLAG}" STREQUAL "")
|
||||
set(C_OPT_FLAG_RELEASE "-O2")
|
||||
set(C_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
|
||||
set(C_OPT_FLAG_DEBUG "${C_OPT_FLAG}")
|
||||
endif()
|
||||
|
||||
set(CXX_FLAGS_RELEASE "${CXX_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
set(C_FLAGS_RELEASE "${C_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
|
||||
set(CXX_FLAGS_DEBUG "${CXX_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
set(C_FLAGS_DEBUG "${C_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
|
||||
# Always use the base flags and add our compiler flags at the back
|
||||
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${C_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS_DEBUG})
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${LINKER_FLAGS}")
|
||||
|
||||
|
||||
+3
-1
@@ -35,7 +35,9 @@ ELSE()
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_VERSION_MAJOR}_${FSO_VERSION_MINOR}_${FSO_VERSION_BUILD}_${FSO_VERSION_REVISION_STR}")
|
||||
ENDIF()
|
||||
|
||||
IF(IS_64BIT)
|
||||
IF(IS_ARM64)
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_arm64")
|
||||
ELSEIF(IS_64BIT)
|
||||
# This is a 64-bit builds
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_x64")
|
||||
ENDIF()
|
||||
|
||||
@@ -25,6 +25,10 @@ if (FSO_BUILD_WITH_OPENGL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FSO_BUILD_WITH_OPENXR_DEBUG)
|
||||
add_definitions(-DFS_OPENXR_DEBUG)
|
||||
endif()
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC openal)
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
|
||||
@@ -75,6 +79,17 @@ target_link_libraries(code PUBLIC hidapi::hidapi)
|
||||
|
||||
target_link_libraries(code PUBLIC imgui)
|
||||
|
||||
IF(NOT APPLE)
|
||||
target_link_libraries(code PUBLIC OpenXR::openxr_loader)
|
||||
target_include_directories(code PUBLIC OpenXR::Headers)
|
||||
ENDIF()
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# On Linux, we need to access X11 window data.
|
||||
# On Windows, SDL already provides everything, so no need to do anything
|
||||
find_package(X11)
|
||||
target_link_libraries(code PUBLIC ${X11_LIBRARIES})
|
||||
ENDIF()
|
||||
|
||||
# Headers for standalone "gui" on UNIX
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${MONGOOSE_LIBS})
|
||||
|
||||
+3
-3
@@ -277,7 +277,7 @@ typedef struct ai_info {
|
||||
|
||||
// Probably become obsolete, to be replaced by path_start, path_cur, etc.
|
||||
waypoint_list *wp_list; // waypoint list being followed
|
||||
size_t wp_index; // waypoint index in list
|
||||
int wp_index; // waypoint index in list
|
||||
int wp_flags; // waypoint flags, see WPF_xxxx
|
||||
int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000
|
||||
|
||||
@@ -533,11 +533,11 @@ extern void ai_ignore_wing(object *ignorer, int wingnum);
|
||||
extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type);
|
||||
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
|
||||
extern void ai_do_default_behavior(object *obj);
|
||||
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
|
||||
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int start_index);
|
||||
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
|
||||
extern void ai_ship_destroy(int shipnum);
|
||||
extern vec3d ai_get_acc_limit(vec3d* vel_limit, const object* objp);
|
||||
extern void ai_turn_towards_vector(vec3d *dest, object *objp, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, vec3d* turnrate_mod = nullptr);
|
||||
extern void ai_turn_towards_vector(const vec3d *dest, object *objp, const vec3d *slide_vec, const vec3d *rel_pos, float bank_override, int flags, const vec3d *rvec = nullptr, const vec3d* turnrate_mod = nullptr);
|
||||
extern void init_ai_object(int objnum);
|
||||
extern void ai_init(void); // Call this one to parse ai.tbl.
|
||||
extern void ai_level_init(void); // Call before each level to reset AI
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace AI {
|
||||
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
|
||||
Target_own_team, // this attack goal is allowed to target friendlies
|
||||
Afterburn_hard, // afterburn as hard as possible to the goal
|
||||
Waypoints_in_reverse, // decrement instead of increment
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
|
||||
@@ -258,7 +258,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Glide Attack Percent:")) {
|
||||
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
@@ -271,7 +271,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Circle Strafe Percent:")) {
|
||||
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
@@ -284,7 +284,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Glide Strafe Percent:")) {
|
||||
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
@@ -297,7 +297,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Random Sidethrust Percent:")) {
|
||||
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
|
||||
+3
-4
@@ -538,8 +538,7 @@ bool ai_new_maybe_reposition_attack_subsys() {
|
||||
model_local_to_global_point(&geye, &ep->pnt, pm, 0, &Pl_objp->orient, &Pl_objp->pos);
|
||||
|
||||
// get world pos of subsystem
|
||||
polymodel* tgt_pm = model_get(Ship_info[Ships[target_objp->instance].ship_info_index].model_num);
|
||||
model_local_to_global_point(&gsubpos, &vmd_zero_vector, tgt_pm, aip->targeted_subsys->system_info->subobj_num, &En_objp->orient, &En_objp->pos);
|
||||
get_subsystem_pos(&gsubpos, target_objp, aip->targeted_subsys);
|
||||
|
||||
// you're in sight! shoot it!
|
||||
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 0))
|
||||
@@ -547,6 +546,7 @@ bool ai_new_maybe_reposition_attack_subsys() {
|
||||
|
||||
// not in sight, gotta get there
|
||||
vec3d* good_pos = nullptr;
|
||||
vec3d world_goal_pos;
|
||||
// For performance reasons we only recheck once a second, otherwise we reuse the last found target.
|
||||
if (timestamp_elapsed(aip->next_dynamic_path_check_time)) {
|
||||
vec3d tgt2pl = Pl_objp->pos - target_objp->pos;
|
||||
@@ -568,7 +568,6 @@ bool ai_new_maybe_reposition_attack_subsys() {
|
||||
vm_rot_point_around_line(&goal_pos, &tgt2pl, angle2goal, &vmd_zero_vector, &cross);
|
||||
|
||||
// then scale in (or out) towards our subsys
|
||||
vec3d world_goal_pos;
|
||||
float new_radius = ((subsys_dist - pl_dist) * (angle2goal / angle2subsys)) + pl_dist;
|
||||
vm_vec_copy_scale(&world_goal_pos, &goal_pos, new_radius / pl_dist);
|
||||
world_goal_pos += target_objp->pos;
|
||||
@@ -1842,7 +1841,7 @@ void ai_big_strafe()
|
||||
|
||||
/*
|
||||
if ( aip->goal_objnum != aip->target_objnum ) {
|
||||
Int3(); // what is going on here? - Get Alan
|
||||
UNREACHABLE("The goal objnum does not match the target objnum in ai_big_strafe(), please report to the SCP!"); // what is going on here? - Get Alan
|
||||
aip->mode = AIM_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
+250
-99
@@ -287,6 +287,15 @@ float AI_frametime;
|
||||
|
||||
char** Ai_class_names = NULL;
|
||||
|
||||
//used for good-primary-time
|
||||
typedef struct {
|
||||
object_ship_wing_point_team subject;
|
||||
object_ship_wing_point_team target;
|
||||
int weapon_index;
|
||||
} primary_fire_info;
|
||||
|
||||
static SCP_vector<primary_fire_info> Preferred_primary_info;
|
||||
|
||||
typedef struct {
|
||||
int team;
|
||||
int weapon_index;
|
||||
@@ -294,7 +303,7 @@ typedef struct {
|
||||
int ship_registry_index;
|
||||
} huge_fire_info;
|
||||
|
||||
SCP_vector<huge_fire_info> Ai_huge_fire_info;
|
||||
static SCP_vector<huge_fire_info> Ai_huge_fire_info;
|
||||
|
||||
int Ai_last_arrive_path; // index of ship_bay path used by last arrival from a fighter bay
|
||||
|
||||
@@ -386,10 +395,10 @@ int is_preferred_weapon(int weapon_num, object *firer_objp, object *target_objp)
|
||||
continue;
|
||||
|
||||
auto ship_entry = &Ship_registry[hfi->ship_registry_index];
|
||||
if (!ship_entry->objp)
|
||||
if (!ship_entry->has_objp())
|
||||
continue;
|
||||
|
||||
int signature = ship_entry->objp->signature;
|
||||
int signature = ship_entry->objp()->signature;
|
||||
|
||||
// sigatures, weapon_index, and team must match
|
||||
if ( (signature == target_signature) && (hfi->weapon_index == weapon_num) && (hfi->team == firer_team) )
|
||||
@@ -1001,6 +1010,9 @@ void ai_level_init()
|
||||
ai_init_secondary_info();
|
||||
|
||||
Ai_last_arrive_path=0;
|
||||
|
||||
// clear out the preferred primaries so that it doesn't persist between missions or between mission reloads
|
||||
Preferred_primary_info.clear();
|
||||
}
|
||||
|
||||
// BEGIN STEALTH
|
||||
@@ -1303,7 +1315,7 @@ void ai_compensate_for_retail_turning(vec3d* vel_limit, vec3d* acc_limit, float
|
||||
// If rvec != NULL, use it to match bank by calling vm_angular_move_matrix.
|
||||
// (rvec defaults to NULL)
|
||||
// optionally specified turnrate_mod contains multipliers for each component of the turnrate (RATE, so 0.5 = slower)
|
||||
void ai_turn_towards_vector(vec3d* dest, object* objp, vec3d* slide_vec, vec3d* rel_pos, float bank_override, int flags, vec3d* rvec, vec3d* turnrate_mod)
|
||||
void ai_turn_towards_vector(const vec3d* dest, object* objp, const vec3d* slide_vec, const vec3d* rel_pos, float bank_override, int flags, const vec3d* rvec, const vec3d* turnrate_mod)
|
||||
{
|
||||
matrix curr_orient;
|
||||
vec3d vel_in, vel_out, desired_fvec, src;
|
||||
@@ -1316,7 +1328,7 @@ void ai_turn_towards_vector(vec3d* dest, object* objp, vec3d* slide_vec, vec3d*
|
||||
// Don't allow a ship to turn if it has no engine strength.
|
||||
// AL 3-12-98: objp may not always be a ship!
|
||||
if ( (objp->type == OBJ_SHIP) && !(flags & AITTV_VIA_SEXP) ) {
|
||||
if (!Ships[objp->instance].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_get_subsystem_strength(&Ships[objp->instance], SUBSYSTEM_ENGINE) <= 0.0f)
|
||||
if (!Ships[objp->instance].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_subsystems_blown(&Ships[objp->instance], SUBSYSTEM_ENGINE))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2567,7 +2579,7 @@ void ai_attack_object(object* attacker, object* attacked, int ship_info_index)
|
||||
}
|
||||
|
||||
// don't abort a support call if you're disabled!
|
||||
if (ship_get_subsystem_strength(&Ships[attacker->instance], SUBSYSTEM_ENGINE) > 0.0f)
|
||||
if (!ship_subsystems_blown(&Ships[attacker->instance], SUBSYSTEM_ENGINE))
|
||||
ai_set_goal_abort_support_call(attacker, aip);
|
||||
|
||||
aip->ok_to_target_timestamp = timestamp(DELAY_TARGET_TIME); // No dynamic targeting for 7 seconds.
|
||||
@@ -2643,7 +2655,7 @@ void ai_evade_object(object *evader, object *evaded)
|
||||
Assert(Ships[evader->instance].ai_index != -1);
|
||||
|
||||
if (evaded == evader) {
|
||||
Int3(); // Bogus! Who tried to get me to evade myself! Trace out and fix!
|
||||
UNREACHABLE("Ship %s is trying to evade itself. Please report to the SCP!", Ships[evader->instance].ship_name); // Bogus! Who tried to get me to evade myself! Trace out and fix!
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3404,7 +3416,7 @@ void ai_dock_with_object(object *docker, int docker_index, object *dockee, int d
|
||||
aip->submode_start_time = Missiontime;
|
||||
break;
|
||||
default:
|
||||
Int3(); // Bogus dock_type.
|
||||
UNREACHABLE("Unknown dock type in ai_dock_with_object of %d. Please report to the SCP!", dock_type); // Bogus dock_type.
|
||||
}
|
||||
|
||||
// Goober5000 - we no longer need to set dock_path_index because it's easier to grab the path from the dockpoint
|
||||
@@ -3464,12 +3476,19 @@ void ai_dock_with_object(object *docker, int docker_index, object *dockee, int d
|
||||
|
||||
// Cause a ship to fly its waypoints.
|
||||
// flags tells:
|
||||
// WPF_REPEAT Set -> repeat waypoints.
|
||||
void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags)
|
||||
// WPF_REPEAT Set -> repeat waypoints.
|
||||
// WPF_BACKTRACK Go in reverse.
|
||||
void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int start_index)
|
||||
{
|
||||
ai_info *aip;
|
||||
Assert(wp_list != NULL);
|
||||
|
||||
if (start_index < 0 || start_index >= (int)wp_list->get_waypoints().size())
|
||||
{
|
||||
Warning(LOCATION, "Starting index for %s on '%s' is out of range!", Ships[objp->instance].ship_name, wp_list->get_name());
|
||||
start_index = (wp_flags & WPF_BACKTRACK) ? (int)wp_list->get_waypoints().size() - 1 : 0;
|
||||
}
|
||||
|
||||
aip = &Ai_info[Ships[objp->instance].ai_index];
|
||||
|
||||
if ( (aip->mode == AIM_WAYPOINTS) && (aip->wp_list == wp_list) )
|
||||
@@ -3477,7 +3496,7 @@ void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags)
|
||||
if (aip->wp_index == INVALID_WAYPOINT_POSITION)
|
||||
{
|
||||
Warning(LOCATION, "aip->wp_index should have been assigned already!");
|
||||
aip->wp_index = 0;
|
||||
aip->wp_index = start_index;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -3493,7 +3512,7 @@ void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags)
|
||||
aip->ai_flags.remove(AI::AI_Flags::Formation_object);
|
||||
|
||||
aip->wp_list = wp_list;
|
||||
aip->wp_index = 0;
|
||||
aip->wp_index = start_index;
|
||||
aip->wp_flags = wp_flags;
|
||||
aip->mode = AIM_WAYPOINTS;
|
||||
|
||||
@@ -3736,7 +3755,7 @@ void ai_update_aim(ai_info *aip)
|
||||
bool ai_willing_to_afterburn_hard(ai_info* aip) {
|
||||
return aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC ?
|
||||
The_mission.ai_profile->flags[AI::Profile_Flags::Dynamic_goals_afterburn_hard] :
|
||||
aip->goals[aip->active_goal].flags[AI::Goal_Flags::Afterburn_hard];
|
||||
(aip->active_goal > -1 && aip->goals[aip->active_goal].flags[AI::Goal_Flags::Afterburn_hard]);
|
||||
}
|
||||
|
||||
// pedal to the metal!!1!
|
||||
@@ -4485,9 +4504,6 @@ void ai_safety()
|
||||
aip->submode = AISS_2;
|
||||
aip->submode_start_time = Missiontime;
|
||||
break;
|
||||
case AISS_1a: // Pick a safe point because we just got whacked!
|
||||
Int3();
|
||||
break;
|
||||
case AISS_2:
|
||||
if (ai_safety_goto_spot(Pl_objp) < 25.0f) {
|
||||
aip->submode = AISS_3;
|
||||
@@ -4497,8 +4513,9 @@ void ai_safety()
|
||||
case AISS_3:
|
||||
ai_safety_circle_spot(Pl_objp);
|
||||
break;
|
||||
case AISS_1a: // Pick a safe point because we just got whacked!
|
||||
default:
|
||||
Int3(); // Illegal submode for ai_safety();
|
||||
UNREACHABLE("Bad AI submode for ai_safety mode of %d. Please report to the SCP!", aip->submode); // Illegal submode for ai_safety();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4510,7 +4527,7 @@ void ai_safety()
|
||||
// optionally returns true if Pl_objp's (pl_treat_as_ship_p) fly to order was issued to him directly,
|
||||
// or if the order was issued to his wing (returns false) (can be NULL, and result is only
|
||||
// valid if Pl_done_p was not NULL and was set true by function.
|
||||
void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl_treat_as_ship_p=NULL)
|
||||
void ai_fly_to_target_position(const vec3d* target_pos, bool* pl_done_p=NULL, bool* pl_treat_as_ship_p=NULL)
|
||||
{
|
||||
float dot, dist_to_goal;
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
@@ -4842,11 +4859,11 @@ void ai_waypoints()
|
||||
// sanity checking for stuff that should never happen
|
||||
if (aip->wp_index == INVALID_WAYPOINT_POSITION) {
|
||||
if (aip->wp_list == NULL) {
|
||||
Warning(LOCATION, "Waypoints should have been assigned already!");
|
||||
ai_start_waypoints(Pl_objp, &Waypoint_lists.front(), WPF_REPEAT);
|
||||
UNREACHABLE("Waypoints should have been assigned already!");
|
||||
ai_start_waypoints(Pl_objp, &Waypoint_lists.front(), WPF_REPEAT, 0);
|
||||
} else {
|
||||
Warning(LOCATION, "Waypoints should have been started already!");
|
||||
ai_start_waypoints(Pl_objp, aip->wp_list, WPF_REPEAT);
|
||||
UNREACHABLE("Waypoints should have been started already!");
|
||||
ai_start_waypoints(Pl_objp, aip->wp_list, WPF_REPEAT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4856,17 +4873,32 @@ void ai_waypoints()
|
||||
ai_fly_to_target_position(aip->wp_list->get_waypoints()[aip->wp_index].get_pos(), &done, &treat_as_ship);
|
||||
|
||||
if ( done ) {
|
||||
bool reached_end;
|
||||
// go on to next waypoint in path
|
||||
++aip->wp_index;
|
||||
if (aip->wp_flags & WPF_BACKTRACK) {
|
||||
--aip->wp_index;
|
||||
reached_end = (aip->wp_index == -1);
|
||||
} else {
|
||||
++aip->wp_index;
|
||||
reached_end = (aip->wp_index == (int)aip->wp_list->get_waypoints().size());
|
||||
}
|
||||
|
||||
if ( aip->wp_index == aip->wp_list->get_waypoints().size() ) {
|
||||
if (reached_end) {
|
||||
// have reached the last waypoint. Do I repeat?
|
||||
if ( aip->wp_flags & WPF_REPEAT ) {
|
||||
// go back to the start.
|
||||
aip->wp_index = 0;
|
||||
if (aip->wp_flags & WPF_BACKTRACK) {
|
||||
aip->wp_index = (int)aip->wp_list->get_waypoints().size() - 1;
|
||||
} else {
|
||||
aip->wp_index = 0;
|
||||
}
|
||||
} else {
|
||||
// stay on the last waypoint.
|
||||
--aip->wp_index;
|
||||
if (aip->wp_flags & WPF_BACKTRACK) {
|
||||
++aip->wp_index;
|
||||
} else {
|
||||
--aip->wp_index;
|
||||
}
|
||||
|
||||
// Log a message that the wing or ship reached his waypoint and
|
||||
// remove the goal from the AI goals of the ship pr wing, respectively.
|
||||
@@ -5459,6 +5491,61 @@ float G_collision_time;
|
||||
vec3d G_predicted_pos, G_fire_pos;
|
||||
|
||||
|
||||
/*
|
||||
* plieblang
|
||||
* Used by the good-primary-time sexp to store the info supplied from there
|
||||
* weapon_idx indexes into Weapon_info if the primary preference is being set
|
||||
*/
|
||||
void ai_set_or_clear_preferred_primary_weapon(bool set_it, const object_ship_wing_point_team *subject, const object_ship_wing_point_team *target, int weapon_idx)
|
||||
{
|
||||
// force the ai to reselect a primary instead of possibly waiting the normal elapsed time
|
||||
for (auto so : list_range(&Ship_obj_list))
|
||||
{
|
||||
auto subject_objp = &Objects[so->objnum];
|
||||
if (subject_objp->flags[Object::Object_Flags::Should_be_dead])
|
||||
continue;
|
||||
|
||||
auto subject_shipp = &Ships[subject_objp->instance];
|
||||
if (!subject->matches(subject_shipp))
|
||||
continue;
|
||||
|
||||
auto subject_aip = &Ai_info[subject_shipp->ai_index];
|
||||
if (subject_aip->target_objnum < 0)
|
||||
continue;
|
||||
|
||||
auto target_objp = &Objects[subject_aip->target_objnum];
|
||||
if (target_objp->type != OBJ_SHIP || !target->matches(&Ships[target_objp->instance]))
|
||||
continue;
|
||||
|
||||
// for AIs that match this subject-target pair, select a new primary immediately
|
||||
subject_aip->primary_select_timestamp = timestamp(1);
|
||||
}
|
||||
|
||||
if (set_it)
|
||||
{
|
||||
for (auto& ppi : Preferred_primary_info)
|
||||
{
|
||||
if (ppi.subject == *subject && ppi.target == *target)
|
||||
{
|
||||
ppi.weapon_index = weapon_idx;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// not found, so add a new entry
|
||||
Preferred_primary_info.push_back({ *subject, *target, weapon_idx });
|
||||
}
|
||||
else
|
||||
{
|
||||
Preferred_primary_info.erase(
|
||||
std::remove_if(Preferred_primary_info.begin(), Preferred_primary_info.end(), [&](const primary_fire_info& ppi) {
|
||||
return ppi.subject == *subject && ppi.target == *target;
|
||||
}), Preferred_primary_info.end()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//old version of this fuction, this will be useful for playing old missions and not having the new primary
|
||||
//selection code throw off the balance of the mission.
|
||||
// If:
|
||||
@@ -5544,6 +5631,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
|
||||
{
|
||||
// Pointer Set Up
|
||||
ship *shipp = &Ships[objp->instance];
|
||||
ship *other_shipp = nullptr;
|
||||
ship_weapon *swp = &shipp->weapons;
|
||||
|
||||
// Debugging
|
||||
@@ -5555,6 +5643,46 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool other_is_ship = (other_objp->type == OBJ_SHIP);
|
||||
|
||||
if (other_is_ship)
|
||||
{
|
||||
other_shipp = &Ships[other_objp->instance];
|
||||
|
||||
//if the good-primary-time sexp has been used, return that weapon immediately
|
||||
//if smart primary weapon selection isn't set, turning this override behavior off might not do anything
|
||||
//however this seems acceptable
|
||||
for (const auto &ppi : Preferred_primary_info)
|
||||
{
|
||||
if (ppi.subject.matches(shipp) && ppi.target.matches(other_shipp))
|
||||
{
|
||||
int weapon_idx = ppi.weapon_index;
|
||||
|
||||
//figure out what bank the weapon belongs to
|
||||
int bank_num = -1;
|
||||
for (int i = 0; i < MAX_SHIP_PRIMARY_BANKS; i++) {
|
||||
if (weapon_idx == swp->primary_bank_weapons[i]) {
|
||||
bank_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if it's a valid bank, set it and return
|
||||
if (bank_num != -1) {
|
||||
//forcing a ship to use a certain primary should prevent it from linking weapons
|
||||
shipp->flags.set(Ship::Ship_Flags::Force_primary_unlinking);
|
||||
|
||||
swp->current_primary_bank = bank_num;
|
||||
return bank_num;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we're not prioritizing a specific primary weapon
|
||||
shipp->flags.remove(Ship::Ship_Flags::Force_primary_unlinking);
|
||||
|
||||
|
||||
//not using the new AI, use the old version of this function instead.
|
||||
if (!(Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_primary_weapon_selection]))
|
||||
{
|
||||
@@ -5590,12 +5718,11 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
|
||||
}
|
||||
}
|
||||
|
||||
bool other_is_ship = (other_objp->type == OBJ_SHIP);
|
||||
float enemy_remaining_shield = get_shield_pct(other_objp);
|
||||
|
||||
if ( other_is_ship )
|
||||
{
|
||||
ship_info* other_sip = &Ship_info[Ships[other_objp->instance].ship_info_index];
|
||||
ship_info* other_sip = &Ship_info[other_shipp->ship_info_index];
|
||||
|
||||
if (other_sip->class_type >= 0 && Ship_types[other_sip->class_type].flags[Ship::Type_Info_Flags::Targeted_by_huge_Ignored_by_small_only]) {
|
||||
//Check if we have a capital+ weapon on board
|
||||
@@ -5611,7 +5738,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
|
||||
if (enemy_remaining_shield <= 0.05f || (wip->shield_factor * 1.33f > wip->armor_factor))
|
||||
{
|
||||
swp->current_primary_bank = i;
|
||||
nprintf(("AI", "%i: Ship %s selecting weapon %s (capital+) vs target %s\n", Framecount, Ships[objp->instance].ship_name, wip->name, Ships[other_objp->instance].ship_name));
|
||||
nprintf(("AI", "%i: Ship %s selecting weapon %s (capital+) vs target %s\n", Framecount, shipp->ship_name, wip->name, other_shipp->ship_name));
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -5649,7 +5776,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
|
||||
i_hullfactor_prev_bank = 0; // Just switch to the first one
|
||||
}
|
||||
swp->current_primary_bank = i_hullfactor_prev_bank; // Select the best weapon
|
||||
nprintf(("AI", "%i: Ship %s selecting weapon %s (no shields) vs target %s\n", Framecount, shipp->ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name, (other_is_ship ? Ships[other_objp->instance].ship_name : "non-ship") ));
|
||||
nprintf(("AI", "%i: Ship %s selecting weapon %s (no shields) vs target %s\n", Framecount, shipp->ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name, (other_is_ship ? other_shipp->ship_name : "non-ship") ));
|
||||
return i_hullfactor_prev_bank; // Return
|
||||
}
|
||||
|
||||
@@ -5771,6 +5898,11 @@ void set_primary_weapon_linkage(object *objp)
|
||||
|
||||
shipp->flags.remove(Ship::Ship_Flags::Primary_linked);
|
||||
|
||||
//bail if it's been included in a good-primary-time
|
||||
if (shipp->flags[Ship::Ship_Flags::Force_primary_unlinking]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// AL: ensure target is a ship!
|
||||
if ( (aip->target_objnum != -1) && (Objects[aip->target_objnum].type == OBJ_SHIP) ) {
|
||||
// If trying to destroy a big ship (i.e., not disable/disarm), always unleash all weapons
|
||||
@@ -6050,6 +6182,7 @@ int ai_fire_primary_weapon(object *objp)
|
||||
enemy_sip = NULL;
|
||||
}
|
||||
|
||||
//plieblang - added check for size of Preferred_primaries to force reevaluation if good-primary-time has been used in the meantime
|
||||
if ( (swp->current_primary_bank < 0) || (swp->current_primary_bank >= swp->num_primary_banks) || timestamp_elapsed(aip->primary_select_timestamp)) {
|
||||
Weapon::Info_Flags flags = Weapon::Info_Flags::NUM_VALUES;
|
||||
if ( aip->targeted_subsys != NULL ) {
|
||||
@@ -6057,7 +6190,7 @@ int ai_fire_primary_weapon(object *objp)
|
||||
}
|
||||
ai_select_primary_weapon(objp, enemy_objp, flags);
|
||||
ship_primary_changed(shipp); // AL: maybe send multiplayer information when AI ship changes primaries
|
||||
aip->primary_select_timestamp = timestamp(5 * 1000); // Maybe change primary weapon five seconds from now.
|
||||
aip->primary_select_timestamp = timestamp(5 * MILLISECONDS_PER_SECOND); // Maybe change primary weapon five seconds from now.
|
||||
}
|
||||
|
||||
//We can only check LoS if we have a target defined
|
||||
@@ -6132,7 +6265,7 @@ int ai_fire_primary_weapon(object *objp)
|
||||
int type;
|
||||
|
||||
type = aip->targeted_subsys->system_info->type;
|
||||
if (ship_get_subsystem_strength(&Ships[tobjp->instance], type) == 0.0f) {
|
||||
if (ship_subsystems_blown(&Ships[tobjp->instance], type)) {
|
||||
aip->target_objnum = -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -7721,8 +7854,8 @@ void ai_stealth_sweep()
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3();
|
||||
|
||||
UNREACHABLE("Bad submode in ai_steath_sweep of %d. Please report to the SCP!", aip->submode_parm0);
|
||||
break;
|
||||
}
|
||||
|
||||
// when close to goal_pt, update next goal pt
|
||||
@@ -8497,13 +8630,13 @@ void ai_cruiser_chase()
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
ai_info *aip = &Ai_info[shipp->ai_index];
|
||||
|
||||
Assertion(En_objp->type == OBJ_SHIP, "En_objp is of type %d which is illegal in ai_cruiser_chase. Please report to the SCP!", En_objp->type);
|
||||
if (En_objp->type != OBJ_SHIP) {
|
||||
Int3();
|
||||
return;
|
||||
}
|
||||
|
||||
Assertion(En_objp->instance > -1, "En_objp has a bad instance of %d which is illegal in ai_cruiser_chase. Please report to the SCP!", En_objp->instance);
|
||||
if (En_objp->instance < 0) {
|
||||
Int3();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8672,9 +8805,7 @@ void ai_chase()
|
||||
flagset<Ship::Ship_Flags> enemy_shipp_flags;
|
||||
int has_fired = -1;
|
||||
|
||||
if (aip->mode != AIM_CHASE) {
|
||||
Int3();
|
||||
}
|
||||
Assertion(aip->mode == AIM_CHASE, "ai_chase was called but the ship was not in the chase ai mode. It is in %d instead. This is a fundamental problem and needs to be reported to the SCP, right away!", aip->mode);
|
||||
|
||||
// by default we try to chase anything
|
||||
bool go_after_it = true;
|
||||
@@ -8806,38 +8937,40 @@ void ai_chase()
|
||||
// Set predicted_enemy_pos.
|
||||
// See if attacking a subsystem.
|
||||
weapon_info* wip = ai_get_weapon(&shipp->weapons);
|
||||
bool ballistic = !IS_VEC_NULL(&The_mission.gravity) && wip->gravity_const != 0.0f;
|
||||
if (aip->targeted_subsys != NULL && get_shield_pct(En_objp) < HULL_DAMAGE_THRESHOLD_PERCENT) {
|
||||
Assert(En_objp->type == OBJ_SHIP);
|
||||
vec3d target_pos;
|
||||
get_subsystem_pos(&target_pos, En_objp, aip->targeted_subsys);
|
||||
if (wip) {
|
||||
bool ballistic = !IS_VEC_NULL(&The_mission.gravity) && wip->gravity_const != 0.0f;
|
||||
if (aip->targeted_subsys != NULL && get_shield_pct(En_objp) < HULL_DAMAGE_THRESHOLD_PERCENT) {
|
||||
Assert(En_objp->type == OBJ_SHIP);
|
||||
vec3d target_pos;
|
||||
get_subsystem_pos(&target_pos, En_objp, aip->targeted_subsys);
|
||||
|
||||
if (!ballistic)
|
||||
predicted_enemy_pos = target_pos;
|
||||
else {
|
||||
vec3d gravity_vec = The_mission.gravity * wip->gravity_const;
|
||||
has_valid_ballistic_trajectory =
|
||||
physics_lead_ballistic_trajectory(&Pl_objp->pos, &target_pos, &aip->last_aim_enemy_vel, wip->max_speed, &gravity_vec, &predicted_enemy_pos);
|
||||
|
||||
if (has_valid_ballistic_trajectory)
|
||||
predicted_enemy_pos = Pl_objp->pos + predicted_enemy_pos * vm_vec_dist(&Pl_objp->pos, &target_pos);
|
||||
else
|
||||
if (!ballistic)
|
||||
predicted_enemy_pos = target_pos;
|
||||
}
|
||||
else {
|
||||
vec3d gravity_vec = The_mission.gravity * wip->gravity_const;
|
||||
has_valid_ballistic_trajectory =
|
||||
physics_lead_ballistic_trajectory(&Pl_objp->pos, &target_pos, &aip->last_aim_enemy_vel, wip->max_speed, &gravity_vec, &predicted_enemy_pos);
|
||||
|
||||
predicted_vec_to_enemy = real_vec_to_enemy;
|
||||
} else {
|
||||
if (!ballistic)
|
||||
set_predicted_enemy_pos(&predicted_enemy_pos, Pl_objp, &aip->last_aim_enemy_pos, &aip->last_aim_enemy_vel, aip);
|
||||
else {
|
||||
vec3d gravity_vec = The_mission.gravity * wip->gravity_const;
|
||||
has_valid_ballistic_trajectory =
|
||||
physics_lead_ballistic_trajectory(&Pl_objp->pos, &aip->last_aim_enemy_pos, &aip->last_aim_enemy_vel, wip->max_speed, &gravity_vec, &predicted_enemy_pos);
|
||||
|
||||
if (has_valid_ballistic_trajectory)
|
||||
predicted_enemy_pos = Pl_objp->pos + predicted_enemy_pos * vm_vec_dist(&Pl_objp->pos, &aip->last_aim_enemy_pos);
|
||||
else
|
||||
if (has_valid_ballistic_trajectory)
|
||||
predicted_enemy_pos = Pl_objp->pos + predicted_enemy_pos * vm_vec_dist(&Pl_objp->pos, &target_pos);
|
||||
else
|
||||
predicted_enemy_pos = target_pos;
|
||||
}
|
||||
|
||||
predicted_vec_to_enemy = real_vec_to_enemy;
|
||||
} else {
|
||||
if (!ballistic)
|
||||
set_predicted_enemy_pos(&predicted_enemy_pos, Pl_objp, &aip->last_aim_enemy_pos, &aip->last_aim_enemy_vel, aip);
|
||||
else {
|
||||
vec3d gravity_vec = The_mission.gravity * wip->gravity_const;
|
||||
has_valid_ballistic_trajectory =
|
||||
physics_lead_ballistic_trajectory(&Pl_objp->pos, &aip->last_aim_enemy_pos, &aip->last_aim_enemy_vel, wip->max_speed, &gravity_vec, &predicted_enemy_pos);
|
||||
|
||||
if (has_valid_ballistic_trajectory)
|
||||
predicted_enemy_pos = Pl_objp->pos + predicted_enemy_pos * vm_vec_dist(&Pl_objp->pos, &aip->last_aim_enemy_pos);
|
||||
else
|
||||
set_predicted_enemy_pos(&predicted_enemy_pos, Pl_objp, &aip->last_aim_enemy_pos, &aip->last_aim_enemy_vel, aip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9164,7 +9297,7 @@ void ai_chase()
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Int3(); // Impossible!
|
||||
UNREACHABLE("Somehow we changed a call to get a random number in ai_chase so it's not 0-4, please report to the SCP!"); // Impossible!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9690,7 +9823,7 @@ float dock_orient_and_approach(object *docker_objp, int docker_index, object *do
|
||||
|
||||
// Goober5000 - moved out here to save calculations
|
||||
if (dock_mode != DOA_DOCK_STAY)
|
||||
if (!Ships[docker_objp->instance].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_get_subsystem_strength(&Ships[docker_objp->instance], SUBSYSTEM_ENGINE) <= 0.0f)
|
||||
if (!Ships[docker_objp->instance].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_subsystems_blown(&Ships[docker_objp->instance], SUBSYSTEM_ENGINE))
|
||||
return 9999.9f;
|
||||
|
||||
// If dockee has moved much, then path will be recreated.
|
||||
@@ -10610,7 +10743,7 @@ void ai_big_guard()
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3(); // Illegal submode for Guard mode.
|
||||
UNREACHABLE("Illegal submode of %d for guard mode in ai_big_guard. Please report to the SCP!", aip->submode);
|
||||
// AL 06/03/97 comment out Int3() to allow milestone to get out the door
|
||||
aip->submode = AIS_GUARD_PATROL;
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -10639,7 +10772,7 @@ void ai_guard()
|
||||
guard_objp = &Objects[aip->guard_objnum];
|
||||
|
||||
if (guard_objp == Pl_objp) {
|
||||
Int3(); // This seems illegal. Why is a ship guarding itself?
|
||||
UNREACHABLE("The ship %s has been found to be guarding itself in ai_guard. Please report to the SCP!", shipp->ship_name); // This seems illegal. Why is a ship guarding itself?
|
||||
aip->guard_objnum = -1;
|
||||
return;
|
||||
}
|
||||
@@ -10818,7 +10951,7 @@ void ai_guard()
|
||||
|
||||
break;
|
||||
default:
|
||||
Int3(); // Illegal submode for Guard mode.
|
||||
UNREACHABLE("Illegal ai submode of %d for guard mode in ai_guard for ship %s. Pleae report to the SCP!", aip->submode, shipp->ship_name);
|
||||
// AL 06/03/97 comment out Int3() to allow milestone to get out the door
|
||||
aip->submode = AIS_GUARD_PATROL;
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -10962,7 +11095,7 @@ void ai_do_objects_repairing_stuff( object *repaired_objp, object *repair_objp,
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3(); // bogus type of repair info
|
||||
UNREACHABLE("Illegal repair info type of %d in ai_do_objects_repairing_stuff. Pleae report to the SCP!", how);
|
||||
}
|
||||
|
||||
// repair_objp might be NULL if we are cleaning up this mode because of the support ship
|
||||
@@ -10999,7 +11132,7 @@ void ai_do_objects_repairing_stuff( object *repaired_objp, object *repair_objp,
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3(); // bogus type of repair info
|
||||
UNREACHABLE("Illegal repair info type of %d in ai_do_objects_repairing_stuff. Pleae report to the SCP!", how);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11823,7 +11956,7 @@ void ai_dock()
|
||||
|
||||
default:
|
||||
{
|
||||
Int3(); // Error, bogus submode
|
||||
UNREACHABLE("Illegal dock submode of %d in ai_dock. Pleae report to the SCP!", aip->submode);
|
||||
}
|
||||
|
||||
} // end of switch statement
|
||||
@@ -12013,7 +12146,7 @@ void ai_process_subobjects(int objnum)
|
||||
}
|
||||
|
||||
// Deal with a ship with blown out engines.
|
||||
if (ship_get_subsystem_strength(shipp, SUBSYSTEM_ENGINE) == 0.0f) {
|
||||
if (ship_subsystems_blown(shipp, SUBSYSTEM_ENGINE)) {
|
||||
// Karajorma - if Player_use_ai is ever fixed to work on multiplayer it should be checked that any player ships
|
||||
// aren't under AI control here
|
||||
if ((!(objp->flags[Object::Object_Flags::Player_ship])) && (sip->is_fighter_bomber()) && !(shipp->flags[Ship::Ship_Flags::Dying])) {
|
||||
@@ -12077,7 +12210,7 @@ object *get_wing_leader(int wingnum)
|
||||
|
||||
// If this ship is disabled, try another ship in the wing.
|
||||
int n = 0;
|
||||
while (!Ships[ship_num].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_get_subsystem_strength(&Ships[ship_num], SUBSYSTEM_ENGINE) == 0.0f) {
|
||||
while (!Ships[ship_num].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_subsystems_blown(&Ships[ship_num], SUBSYSTEM_ENGINE)) {
|
||||
n++;
|
||||
|
||||
if (n >= wingp->current_count) {
|
||||
@@ -12477,7 +12610,6 @@ int ai_formation()
|
||||
}
|
||||
|
||||
if (aip->mode == AIM_WAYPOINTS) {
|
||||
|
||||
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_path_order_bug]){
|
||||
// skip if wing leader has no waypoint order or a different waypoint list
|
||||
if ((laip->mode != AIM_WAYPOINTS) || !(aip->wp_list == laip->wp_list)){
|
||||
@@ -12489,8 +12621,15 @@ int ai_formation()
|
||||
aip->wp_index = laip->wp_index;
|
||||
aip->wp_flags = laip->wp_flags;
|
||||
|
||||
if ((aip->wp_list != NULL) && (aip->wp_index == aip->wp_list->get_waypoints().size()))
|
||||
--aip->wp_index;
|
||||
if (aip->wp_list != nullptr) {
|
||||
if (aip->wp_flags & WPF_BACKTRACK) {
|
||||
if (aip->wp_index == -1)
|
||||
++aip->wp_index;
|
||||
} else {
|
||||
if (aip->wp_index == (int)aip->wp_list->get_waypoints().size())
|
||||
--aip->wp_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -12780,14 +12919,23 @@ void ai_do_repair_frame(object *objp, ai_info *aip, float frametime)
|
||||
repaired = ship_do_rearm_frame( objp, frametime ); // hook to do missile rearming
|
||||
|
||||
// See if fully repaired. If so, cause process to stop.
|
||||
if ( repaired && (repair_aip->submode == AIS_DOCK_4)) {
|
||||
|
||||
repair_aip->submode = AIS_UNDOCK_0;
|
||||
repair_aip->submode_start_time = Missiontime;
|
||||
|
||||
// if repairing player object -- tell him done with repair
|
||||
if ( !MULTIPLAYER_CLIENT ) {
|
||||
ai_do_objects_repairing_stuff( objp, &Objects[support_objnum], REPAIR_INFO_COMPLETE );
|
||||
if ( repaired ) {
|
||||
// We can repair ships without being docked, so only do this if we are docked
|
||||
if (repair_aip->submode == AIS_DOCK_4) {
|
||||
repair_aip->submode = AIS_UNDOCK_0;
|
||||
repair_aip->submode_start_time = Missiontime;
|
||||
// if repairing player object -- tell him done with repair
|
||||
if (!MULTIPLAYER_CLIENT) {
|
||||
ai_do_objects_repairing_stuff(objp, &Objects[support_objnum], REPAIR_INFO_COMPLETE);
|
||||
}
|
||||
}
|
||||
//If Repairing self
|
||||
else if (&Objects[support_objnum] == objp) { // Undocking ends the repair,
|
||||
// but since we don'tneed to do that in this case, end it here
|
||||
ai_do_objects_repairing_stuff(objp, &Objects[support_objnum], REPAIR_INFO_END);
|
||||
if (!MULTIPLAYER_CLIENT) {
|
||||
hud_support_view_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13398,8 +13546,8 @@ int ai_acquire_emerge_path(object *pl_objp, int parent_objnum, int allowed_path_
|
||||
Assertion(shipp->ai_index >= 0, "Arriving ship does not have a valid ai index. Has %d instead. Please report!", shipp->ai_index);
|
||||
ai_info *aip = &Ai_info[shipp->ai_index];
|
||||
|
||||
Assertion(parent_objnum > -1, "parent_objnum in ai_acquire_emerge_path was found to be %d, which is an invalid value. Please report to the SCP!", parent_objnum);
|
||||
if ( parent_objnum == -1 ) {
|
||||
Int3();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -14153,7 +14301,7 @@ void ai_maybe_depart(object *objp)
|
||||
if (!shipp->is_departing()) {
|
||||
if (sip->is_fighter_bomber()) {
|
||||
if (aip->warp_out_timestamp == 0) {
|
||||
//if (ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS) == 0.0f) {
|
||||
//if (ship_subsystems_blown(shipp, SUBSYSTEM_WEAPONS)) {
|
||||
// aip->warp_out_timestamp = timestamp(Random::next(10, 19) * 1000);
|
||||
//}
|
||||
} else if (timestamp_elapsed(aip->warp_out_timestamp)) {
|
||||
@@ -14258,7 +14406,7 @@ void ai_warp_out(object *objp)
|
||||
case AIS_WARP_5:
|
||||
break;
|
||||
default:
|
||||
Int3(); // Illegal submode for warping out.
|
||||
UNREACHABLE("Illegal ai submode of %d in ai_warp_out. Pleae report to the SCP!", aip->submode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14504,7 +14652,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos)
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
Int3(); // Illegal -- supposedly avoiding a shockwave, but neither ship nor weapon. What is it!?
|
||||
UNREACHABLE("aas_1 has been passed an invalid object type of %d, please report to the SCP!", objp->type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -14633,8 +14781,8 @@ void ai_maybe_self_destruct(object *objp, ai_info *aip)
|
||||
// mission would be broken.
|
||||
// Also, don't blow up the ship if it has a ship flag preventing this - Goober5000
|
||||
if ((Ship_info[shipp->ship_info_index].is_small_ship()) && (shipp->wingnum >= 0) && !(shipp->flags[Ship::Ship_Flags::No_disabled_self_destruct])) {
|
||||
if ((ship_get_subsystem_strength(shipp, SUBSYSTEM_ENGINE) <= 0.0f) ||
|
||||
(ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS) <= 0.0f)) {
|
||||
if ((ship_subsystems_blown(shipp, SUBSYSTEM_ENGINE)) ||
|
||||
(ship_subsystems_blown(shipp, SUBSYSTEM_WEAPONS))) {
|
||||
if (aip->self_destruct_timestamp < 0)
|
||||
aip->self_destruct_timestamp = timestamp(90 * 1000); // seconds until self-destruct
|
||||
} else {
|
||||
@@ -14768,7 +14916,7 @@ void validate_mode_submode(ai_info *aip)
|
||||
case SM_ATTACK_FOREVER:
|
||||
break;
|
||||
default:
|
||||
Int3();
|
||||
UNREACHABLE("validate_mode_submode found an illegal submode for AIM_CHASE of %d. Please report to the SCP!", aip->submode);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -14782,7 +14930,7 @@ void validate_mode_submode(ai_info *aip)
|
||||
case AIS_STRAFE_POSITION:
|
||||
break;
|
||||
default:
|
||||
Int3();
|
||||
UNREACHABLE("validate_mode_submode found an illegal submode for AIM_STRAFE of %d. Please report to the SCP!", aip->submode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -14811,6 +14959,9 @@ void ai_frame(int objnum)
|
||||
|
||||
//Default to glide OFF
|
||||
Pl_objp->phys_info.flags &= ~PF_GLIDING;
|
||||
|
||||
// turn off trigger down
|
||||
shipp->weapons.flags.remove(Ship::Weapon_Flags::Primary_trigger_down);
|
||||
|
||||
// warping out?
|
||||
if ((aip->mode == AIM_WARP_OUT) || (aip->ai_flags[AI::AI_Flags::Trying_unsuccessfully_to_warp]))
|
||||
@@ -15914,7 +16065,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
|
||||
objp_hitter = hit_objp;
|
||||
hitter_objnum = OBJ_INDEX(hit_objp);
|
||||
} else {
|
||||
Int3(); // Hmm, what kind of object hit this if not weapon or ship? Get MikeK.
|
||||
UNREACHABLE("ai_ship_hit has been passed an invalid object type of %d, please report to the SCP!", hit_objp->type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16393,8 +16544,8 @@ void ai_rearm_repair( object *objp, int docker_index, object *goal_objp, int doc
|
||||
// of a path_num associated with than dockbay (this is an index into polymodel->paths[])
|
||||
int ai_return_path_num_from_dockbay(object *dockee_objp, int dockbay_index)
|
||||
{
|
||||
if ( dockbay_index < 0 || dockee_objp == NULL ) {
|
||||
Int3(); // should never happen
|
||||
Assertion(dockbay_index > -1 && dockee_objp != nullptr, "ai_return_path_num_from_dockbay has been passed invalid docking info: %s dockbay index of %d, please report to the SCP!", dockee_objp == nullptr ? "null pointer dockee object and " : "", dockbay_index);
|
||||
if ( dockbay_index < 0 || dockee_objp == nullptr ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+63
-59
@@ -214,7 +214,7 @@ void ai_maybe_add_form_goal(wing* wingp)
|
||||
int wingnum;
|
||||
if (Netgame.type_flags & NG_TYPE_TEAM) {
|
||||
const ship_registry_entry* ship_regp = ship_registry_get(Ships[wingp->ship_index[j]].ship_name);
|
||||
wingnum = TVT_wings[ship_regp->p_objp->team];
|
||||
wingnum = TVT_wings[ship_regp->p_objp()->team];
|
||||
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
|
||||
} else {
|
||||
wingnum = Starting_wings[0];
|
||||
@@ -487,10 +487,12 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
|
||||
// these goals cannot be associated to wings, but can to a ship in a wing. So, we should find out
|
||||
// if the ship is in a wing so we can purge goals which might operate on that wing
|
||||
ship_index = ship_name_lookup(name);
|
||||
if ( ship_index == -1 ) {
|
||||
Int3(); // get allender -- this is sort of odd
|
||||
return;
|
||||
|
||||
Assertion(ship_index > -1, "Found a bad ship_index of %d in ai_goal_purge_invalid_goals, please report to the SCP!", ship_index); // get allender -- this is sort of odd
|
||||
if ( ship_index < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wingnum = Ships[ship_index].wingnum;
|
||||
|
||||
purge_goal = goal_list;
|
||||
@@ -726,7 +728,7 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
// from the mission goals (i.e. those goals which come from events) in that we don't
|
||||
// use sexpressions for goals from the player...so we enumerate all the parameters
|
||||
|
||||
void ai_add_goal_sub_player(int type, int mode, int submode, char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
|
||||
void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
|
||||
{
|
||||
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
|
||||
|
||||
@@ -813,7 +815,7 @@ int ai_goal_num(ai_goal *goals)
|
||||
}
|
||||
|
||||
|
||||
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, char *target_name, ai_goal *aigp )
|
||||
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, const char *target_name, ai_goal *aigp )
|
||||
{
|
||||
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
|
||||
|
||||
@@ -830,7 +832,7 @@ void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, ch
|
||||
aigp->priority = priority;
|
||||
}
|
||||
|
||||
void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip)
|
||||
void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char *shipname, ai_info *aip)
|
||||
{
|
||||
int empty_index;
|
||||
ai_goal *aigp;
|
||||
@@ -854,7 +856,7 @@ void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipn
|
||||
// is issued to ship or wing (from player), mode is AI_GOAL_*. submode is the submode the
|
||||
// ship should go into. shipname is the object of the action. aip is the ai_info pointer
|
||||
// of the ship receiving the order
|
||||
void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
|
||||
void ai_add_ship_goal_player( int type, int mode, int submode, const char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
|
||||
{
|
||||
int empty_index;
|
||||
ai_goal *aigp;
|
||||
@@ -875,7 +877,7 @@ void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, a
|
||||
|
||||
// adds a goal from the player to the given wing (which in turn will add it to the proper
|
||||
// ships in the wing
|
||||
void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum, const ai_lua_parameters& lua_target)
|
||||
void ai_add_wing_goal_player( int type, int mode, int submode, const char *shipname, int wingnum, const ai_lua_parameters& lua_target)
|
||||
{
|
||||
int i, empty_index;
|
||||
wing *wingp = &Wings[wingnum];
|
||||
@@ -899,7 +901,7 @@ void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, i
|
||||
|
||||
|
||||
// common routine to add a sexpression mission goal to the appropriate goal structure.
|
||||
void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char *actor_name )
|
||||
void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name )
|
||||
{
|
||||
int node, dummy, op;
|
||||
|
||||
@@ -913,22 +915,30 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
|
||||
switch (op) {
|
||||
|
||||
case OP_AI_WAYPOINTS_ONCE:
|
||||
case OP_AI_WAYPOINTS: {
|
||||
case OP_AI_WAYPOINTS:
|
||||
{
|
||||
int ref_type;
|
||||
bool is_nan, is_nan_forever;
|
||||
|
||||
ref_type = Sexp_nodes[CDR(node)].subtype;
|
||||
if (ref_type == SEXP_ATOM_STRING || ref_type == SEXP_ATOM_CONTAINER_DATA) { // referenced by name
|
||||
// save the waypoint path name -- the list will get resolved when the goal is checked
|
||||
// for achievability.
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
|
||||
Assertion(ref_type == SEXP_ATOM_STRING || ref_type == SEXP_ATOM_CONTAINER_DATA, "Found a bad ref_type in ai_add_goal_sub_sexp of %d. Please report to the SCP!", ref_type);
|
||||
|
||||
// referenced by name
|
||||
// save the waypoint path name -- the list will get resolved when the goal is checked
|
||||
// for achievability.
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
|
||||
|
||||
} else
|
||||
Int3();
|
||||
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
|
||||
aigp->ai_mode = AI_GOAL_WAYPOINTS;
|
||||
if ( op == OP_AI_WAYPOINTS_ONCE )
|
||||
aigp->ai_mode = AI_GOAL_WAYPOINTS_ONCE;
|
||||
if (CDDDDR(node) < 0)
|
||||
aigp->int_data = 0; // handle optional node separately because we don't subtract 1 here
|
||||
else
|
||||
aigp->int_data = eval_num(CDDDDR(node), is_nan, is_nan_forever) - 1;
|
||||
if (is_sexp_true(CDDDDDR(node)))
|
||||
aigp->flags.set(AI::Goal_Flags::Waypoints_in_reverse);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -990,9 +1000,9 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
|
||||
// this goal needs some extra setup
|
||||
// if this doesn't work, the goal will be immediately removed
|
||||
auto ship_entry = ship_registry_get(aigp->target_name);
|
||||
if (ship_entry && ship_entry->shipp)
|
||||
if (ship_entry && ship_entry->has_shipp())
|
||||
{
|
||||
auto target_aip = &Ai_info[ship_entry->shipp->ai_index];
|
||||
auto target_aip = &Ai_info[ship_entry->shipp()->ai_index];
|
||||
target_aip->ai_flags.set(AI::AI_Flags::Awaiting_repair);
|
||||
Assertion(aip != nullptr, "Must provide aip if assigning a rearm goal!");
|
||||
ai_goal_fixup_dockpoints( aip, aigp );
|
||||
@@ -1452,15 +1462,8 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
|
||||
int gindex;
|
||||
ai_goal *aigp;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Goober5000 - none of the goals act on the actor, as in ai_add_goal_sub_sexp
|
||||
if (!strcmp(name, Ships[aip->shipnum].ship_name))
|
||||
{
|
||||
// not good
|
||||
Int3();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Assertion(strcmp(name, Ships[aip->shipnum].ship_name) != 0, "The goals apply to the actor in ai_add_goal_ship_internal for ship %s, please report to the SCP!", name);
|
||||
|
||||
// find an empty slot to put this goal in.
|
||||
gindex = ai_goal_find_empty_slot( aip->goals, aip->active_goal );
|
||||
@@ -1511,7 +1514,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3(); // unsupported internal goal -- see Mike K or Mark A.
|
||||
UNREACHABLE("unsupported internal goal of %d found in ai_add_goal_ship_internal. Please report to the SCP", goal_type); // see Mike K or Mark A.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1589,7 +1592,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// if the wing target is valid then be sure to set the override bit so that it always
|
||||
// gets executed next
|
||||
if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING ) {
|
||||
if (!target_ship_entry || !target_ship_entry->shipp)
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp())
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
aigp->flags.set(AI::Goal_Flags::Goal_override);
|
||||
@@ -1649,7 +1652,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
|
||||
// can't determine the status of this goal if ship not valid
|
||||
// or we haven't found a valid subsystem index yet
|
||||
if ( !target_ship_entry || !target_ship_entry->shipp || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
|
||||
if ( !target_ship_entry || !target_ship_entry->has_shipp() || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
@@ -1658,13 +1661,13 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// as 0 so we can continue. (The subsystem name must be turned into an index into the ship's subsystems
|
||||
// for this goal to be valid).
|
||||
Assert ( aigp->ai_submode >= 0 );
|
||||
ssp = ship_get_indexed_subsys( target_ship_entry->shipp, aigp->ai_submode );
|
||||
ssp = ship_get_indexed_subsys( target_ship_entry->shipp(), aigp->ai_submode );
|
||||
if (ssp != NULL) {
|
||||
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
|
||||
status = (ssp->current_hits <= 0.0f) ? 1 : 0;
|
||||
} else {
|
||||
// not supposed to ever happen, but could if there is a mismatch between the table and model subsystems
|
||||
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, target_ship_entry->shipp->ship_name));
|
||||
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, target_ship_entry->shipp()->ship_name));
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
@@ -1677,11 +1680,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// destroyed when shipnum is valid
|
||||
|
||||
// can't determine the status of this goal if ship not valid
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
|
||||
status = 0;
|
||||
} else {
|
||||
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
|
||||
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
status = (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1693,11 +1696,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// destroyed when shipnum is valid
|
||||
|
||||
// can't determine the status of this goal if ship not valid
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
|
||||
status = 0;
|
||||
} else {
|
||||
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
|
||||
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
status = (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1725,8 +1728,8 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
|
||||
// fly-to-ship can potentially be determined
|
||||
if (aigp->ai_mode == AI_GOAL_FLY_TO_SHIP && target_ship_entry && target_ship_entry->objp) {
|
||||
auto dist = vm_vec_dist(&target_ship_entry->objp->pos, &objp->pos);
|
||||
if (aigp->ai_mode == AI_GOAL_FLY_TO_SHIP && target_ship_entry && target_ship_entry->has_objp()) {
|
||||
auto dist = vm_vec_dist(&target_ship_entry->objp()->pos, &objp->pos);
|
||||
if (dist < aigp->float_data) {
|
||||
return_val = ai_achievability::SATISFIED;
|
||||
status = 1;
|
||||
@@ -1840,9 +1843,9 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// Goober5000 - before doing anything else, check if this is a disarm goal for an arrived ship...
|
||||
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP || aigp->ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL))
|
||||
{
|
||||
if (target_ship_entry && target_ship_entry->shipp) {
|
||||
if (target_ship_entry && target_ship_entry->has_shipp()) {
|
||||
// if the ship has no turrets, we can't disarm it!
|
||||
if (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0)
|
||||
if (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_TURRET].type_count == 0)
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
} else {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
@@ -1876,8 +1879,8 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
|
||||
if (!(aigp->flags[AI::Goal_Flags::Dockee_index_valid])) {
|
||||
if (target_ship_entry && target_ship_entry->shipp) {
|
||||
int modelnum = Ship_info[target_ship_entry->shipp->ship_info_index].model_num;
|
||||
if (target_ship_entry && target_ship_entry->has_shipp()) {
|
||||
int modelnum = Ship_info[target_ship_entry->shipp()->ship_info_index].model_num;
|
||||
aigp->dockee.index = model_find_dock_name_index(modelnum, aigp->dockee.name);
|
||||
aigp->flags.set(AI::Goal_Flags::Dockee_index_valid);
|
||||
} else
|
||||
@@ -1894,11 +1897,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
return ai_achievability::NOT_KNOWN;
|
||||
|
||||
// we must also determine if we're prevented from docking for any reason
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
|
||||
}
|
||||
auto goal_objp = target_ship_entry->objp;
|
||||
auto goal_objp = target_ship_entry->objp();
|
||||
|
||||
// if the ship that I am supposed to dock with is docked with something else, then I need to put my goal on hold
|
||||
// [MK, 4/23/98: With Mark, we believe this fixes the problem of Comet refusing to warp out after docking with Omega.
|
||||
@@ -1947,9 +1950,9 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// might happen too, so err on the safe side. (Yay for emergent paragraph justification!)
|
||||
if ((aip->mode == AIM_DOCK) && (aip->submode >= AIS_UNDOCK_0))
|
||||
{
|
||||
if ( target_ship_entry && target_ship_entry->shipp ) {
|
||||
if ( target_ship_entry && target_ship_entry->has_objp() ) {
|
||||
// only put it on hold if it's someone other than the guy we're undocking from right now!!
|
||||
if (aip->goal_objnum != target_ship_entry->shipp->objnum)
|
||||
if (aip->goal_objnum != target_ship_entry->objnum)
|
||||
return ai_achievability::NOT_KNOWN;
|
||||
} else {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
@@ -1962,8 +1965,8 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// have fixed up the subsystem name (of the subsystem to destroy) into an index into
|
||||
// the ship's subsystem list
|
||||
if ( aigp->flags[AI::Goal_Flags::Subsys_needs_fixup] ) {
|
||||
if ( target_ship_entry && target_ship_entry->shipp ) {
|
||||
aigp->ai_submode = ship_find_subsys( target_ship_entry->shipp, aigp->docker.name );
|
||||
if ( target_ship_entry && target_ship_entry->has_shipp() ) {
|
||||
aigp->ai_submode = ship_find_subsys( target_ship_entry->shipp(), aigp->docker.name );
|
||||
aigp->flags.remove(AI::Goal_Flags::Subsys_needs_fixup);
|
||||
} else {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
@@ -1972,11 +1975,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
} else if ( ((aigp->ai_mode == AI_GOAL_IGNORE) || (aigp->ai_mode == AI_GOAL_IGNORE_NEW)) && (status == SHIP_STATUS_ARRIVED) ) {
|
||||
// for ignoring a ship, call the ai_ignore object function, then declare the goal satisfied
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_objp()) {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
|
||||
}
|
||||
auto ignored = target_ship_entry->objp;
|
||||
auto ignored = target_ship_entry->objp();
|
||||
|
||||
ai_ignore_object(objp, ignored, (aigp->ai_mode == AI_GOAL_IGNORE_NEW));
|
||||
|
||||
@@ -2030,22 +2033,22 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
if ( status == SHIP_STATUS_GONE )
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
if ( !target_ship_entry || !target_ship_entry->shipp ) {
|
||||
if ( !target_ship_entry || !target_ship_entry->has_shipp() ) {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
}
|
||||
|
||||
// if destination currently being repaired, then goal is still active
|
||||
if ( Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
|
||||
if ( Ai_info[target_ship_entry->shipp()->ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
|
||||
return ai_achievability::ACHIEVABLE;
|
||||
|
||||
// if the destination ship is dying or departing (but not completed yet), the mark goal as
|
||||
// not achievable.
|
||||
if ( target_ship_entry->shipp->is_dying_or_departing())
|
||||
if ( target_ship_entry->shipp()->is_dying_or_departing())
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
// if the destination object is no longer awaiting repair, then remove the item
|
||||
if ( !(Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
|
||||
if ( !(Ai_info[target_ship_entry->shipp()->ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
// not repairing anything means that he can do this goal!!!
|
||||
@@ -2060,7 +2063,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// if he is repairing something, he can satisfy his repair goal (his goal_objnum)
|
||||
// return GOAL_NOT_KNOWN which is kind of a hack which puts the goal on hold until it can be
|
||||
// satisfied.
|
||||
if ( aip->goal_objnum != target_ship_entry->shipp->objnum )
|
||||
if ( aip->goal_objnum != target_ship_entry->objnum )
|
||||
return ai_achievability::NOT_KNOWN;
|
||||
|
||||
return ai_achievability::ACHIEVABLE;
|
||||
@@ -2334,10 +2337,11 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
case AI_GOAL_WAYPOINTS: // do nothing for waypoints
|
||||
case AI_GOAL_WAYPOINTS_ONCE: {
|
||||
int flags = 0;
|
||||
|
||||
if ( current_goal->ai_mode == AI_GOAL_WAYPOINTS)
|
||||
if (current_goal->ai_mode == AI_GOAL_WAYPOINTS)
|
||||
flags |= WPF_REPEAT;
|
||||
ai_start_waypoints(objp, current_goal->wp_list, flags);
|
||||
if (current_goal->flags[AI::Goal_Flags::Waypoints_in_reverse])
|
||||
flags |= WPF_BACKTRACK;
|
||||
ai_start_waypoints(objp, current_goal->wp_list, flags, current_goal->int_data);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2544,7 +2548,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3();
|
||||
UNREACHABLE("unsupported goal of %d found in ai_process_mission_orders. Please report to the SCP", current_goal->ai_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -168,17 +168,17 @@ extern void ai_process_mission_orders( int objnum, ai_info *aip );
|
||||
extern int ai_goal_num(ai_goal *goals);
|
||||
|
||||
// adds goals to ships/wing through sexpressions
|
||||
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip);
|
||||
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char *shipname, ai_info *aip);
|
||||
extern void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip );
|
||||
extern void ai_add_wing_goal_sexp( int sexp, int type, wing *wingp );
|
||||
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char *actor_name);
|
||||
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name);
|
||||
|
||||
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
|
||||
extern void ai_remove_wing_goal_sexp( int sexp, wing *wingp );
|
||||
|
||||
// adds goals to ships/sings through player orders
|
||||
extern void ai_add_ship_goal_player(int type, int mode, int submode, char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
extern void ai_add_wing_goal_player(int type, int mode, int submode, char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
extern void ai_add_ship_goal_player(int type, int mode, int submode, const char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
extern void ai_add_wing_goal_player(int type, int mode, int submode, const char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
|
||||
extern void ai_remove_ship_goal( ai_info *aip, int index );
|
||||
extern void ai_clear_ship_goals( ai_info *aip );
|
||||
|
||||
+22
-16
@@ -97,29 +97,35 @@ SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only)
|
||||
return list;
|
||||
}
|
||||
|
||||
// Provides a list of general orders for mission saving. You can only get one kind
|
||||
// of list at a time. If onlyEnabled and onlyValid are both true, for example, you will get
|
||||
// a list of onlyEnabled orders. If you need a list of enabled orders that are also valid, you'll
|
||||
// need to get both lists separately and compare.
|
||||
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled, bool onlyValid, const SCP_string& category)
|
||||
{
|
||||
SCP_vector<SCP_string> list;
|
||||
|
||||
for (auto order : Lua_player_orders) {
|
||||
for (const auto& order : Lua_player_orders) {
|
||||
if (order.second.generalOrder) {
|
||||
bool add = false;
|
||||
|
||||
// Only enabled orders
|
||||
if (onlyEnabled && order.second.cur_enabled) {
|
||||
add = true;
|
||||
|
||||
// Only valid orders
|
||||
} else if (onlyValid && order.second.cur_valid) {
|
||||
add = true;
|
||||
|
||||
// Only orders that match the category requested
|
||||
} else if ((!category.empty()) && (order.second.category == category)) {
|
||||
add = true;
|
||||
|
||||
// All general orders
|
||||
} else {
|
||||
if (!onlyEnabled && !onlyValid && category.empty()) {
|
||||
add = true;
|
||||
} else {
|
||||
|
||||
// Only enabled orders
|
||||
if (onlyEnabled && order.second.cur_enabled) {
|
||||
add = true;
|
||||
|
||||
// Only valid orders
|
||||
} else if (onlyValid && order.second.cur_valid) {
|
||||
add = true;
|
||||
|
||||
// Only orders that match the category requested
|
||||
} else if ((!category.empty()) && (order.second.category == category)) {
|
||||
add = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (add) {
|
||||
@@ -161,7 +167,7 @@ void ai_lua_validate_general_order(int sexp_op, bool validity)
|
||||
}
|
||||
|
||||
void ai_lua_reset_general_orders() {
|
||||
for (auto order : Lua_player_orders) {
|
||||
for (const auto& order : Lua_player_orders) {
|
||||
ai_lua_enable_general_order(order.first, false);
|
||||
ai_lua_validate_general_order(order.first, false);
|
||||
}
|
||||
@@ -248,7 +254,7 @@ void ai_lua_start_general(int lua_sexp_id, int target_objnum)
|
||||
ai_info aip;
|
||||
aip.shipnum = -1;
|
||||
|
||||
if (target_objnum >= 0) {
|
||||
if (target_objnum >= 0 && Objects[target_objnum].type == OBJ_SHIP) {
|
||||
aip.lua_ai_target = {object_ship_wing_point_team(&Ships[Objects[target_objnum].instance]), {}};
|
||||
}
|
||||
|
||||
|
||||
+33
-49
@@ -72,29 +72,29 @@ const char* Turret_valid_types[NUM_TURRET_TYPES] = {
|
||||
};
|
||||
|
||||
typedef struct eval_enemy_obj_struct {
|
||||
int turret_parent_objnum; // parent of turret
|
||||
float weapon_travel_dist; // max targeting range of turret weapon
|
||||
int enemy_team_mask;
|
||||
int weapon_system_ok; // is the weapon subsystem of turret ship ok
|
||||
int eeo_flags;
|
||||
int turret_parent_objnum = -1; // parent of turret
|
||||
float weapon_travel_dist = 0.0f; // max targeting range of turret weapon
|
||||
int enemy_team_mask = 0;
|
||||
bool weapon_system_ok = false; // is the weapon subsystem of turret ship ok
|
||||
int eeo_flags = 0;
|
||||
|
||||
vec3d *tpos;
|
||||
vec3d *tvec;
|
||||
ship_subsys *turret_subsys;
|
||||
int current_enemy;
|
||||
const vec3d *tpos = nullptr;
|
||||
const vec3d *tvec = nullptr;
|
||||
const ship_subsys *turret_subsys = nullptr;
|
||||
int current_enemy = -1;
|
||||
|
||||
|
||||
float nearest_attacker_dist; // nearest ship
|
||||
int nearest_attacker_objnum;
|
||||
float nearest_attacker_dist = 99999.0f; // nearest ship
|
||||
int nearest_attacker_objnum = -1;
|
||||
|
||||
float nearest_homing_bomb_dist; // nearest homing bomb
|
||||
int nearest_homing_bomb_objnum;
|
||||
float nearest_homing_bomb_dist = 99999.0f; // nearest homing bomb
|
||||
int nearest_homing_bomb_objnum = -1;
|
||||
|
||||
float nearest_bomb_dist; // nearest non-homing bomb
|
||||
int nearest_bomb_objnum;
|
||||
float nearest_bomb_dist = 99999.0f; // nearest non-homing bomb
|
||||
int nearest_bomb_objnum = -1;
|
||||
|
||||
float nearest_dist; // nearest ship attacking this turret
|
||||
int nearest_objnum;
|
||||
float nearest_dist = 99999.0f; // nearest ship attacking this turret
|
||||
int nearest_objnum = -1;
|
||||
} eval_enemy_obj_struct;
|
||||
|
||||
// the current world orientation of the turret matrix, corresponding to its fvec and uvec defined in the model
|
||||
@@ -120,7 +120,7 @@ void turret_instance_find_world_orient(matrix* out_mat, int model_instance_num,
|
||||
*
|
||||
* @return 1 if objp is in fov of the specified turret. Otherwise return 0.
|
||||
*/
|
||||
bool object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist)
|
||||
bool object_in_turret_fov(const object *objp, const ship_subsys *ss, const vec3d *tvec, const vec3d *tpos, float dist)
|
||||
{
|
||||
vec3d v2e;
|
||||
float size_mod;
|
||||
@@ -215,7 +215,7 @@ int turret_select_best_weapon(ship_subsys *turret, object * /*target*/)
|
||||
/**
|
||||
* Returns true if all weapons in swp have the specified flag
|
||||
*/
|
||||
bool all_turret_weapons_have_flags(ship_weapon *swp, flagset<Weapon::Info_Flags> flags)
|
||||
bool all_turret_weapons_have_flags(const ship_weapon *swp, flagset<Weapon::Info_Flags> flags)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < swp->num_primary_banks; i++)
|
||||
@@ -232,7 +232,7 @@ bool all_turret_weapons_have_flags(ship_weapon *swp, flagset<Weapon::Info_Flags>
|
||||
return true;
|
||||
}
|
||||
|
||||
bool all_turret_weapons_have_flags(ship_weapon *swp, Weapon::Info_Flags flags)
|
||||
bool all_turret_weapons_have_flags(const ship_weapon *swp, Weapon::Info_Flags flags)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < swp->num_primary_banks; i++)
|
||||
@@ -253,7 +253,7 @@ bool all_turret_weapons_have_flags(ship_weapon *swp, Weapon::Info_Flags flags)
|
||||
* Returns true if any of the weapons in swp have flags
|
||||
*
|
||||
*/
|
||||
bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags)
|
||||
bool turret_weapon_has_flags(const ship_weapon *swp, Weapon::Info_Flags flags)
|
||||
{
|
||||
Assert(swp != NULL);
|
||||
|
||||
@@ -279,7 +279,7 @@ bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags)
|
||||
/**
|
||||
* Just gloms all the flags from all the weapons into one variable. More efficient if all you need to do is test for the existence of a flag.
|
||||
*/
|
||||
flagset<Weapon::Info_Flags> turret_weapon_aggregate_flags(ship_weapon *swp)
|
||||
flagset<Weapon::Info_Flags> turret_weapon_aggregate_flags(const ship_weapon *swp)
|
||||
{
|
||||
Assert(swp != NULL);
|
||||
|
||||
@@ -307,7 +307,7 @@ flagset<Weapon::Info_Flags> turret_weapon_aggregate_flags(ship_weapon *swp)
|
||||
* @note It might be a little faster to optimize based on WP_LASER should only appear in primaries
|
||||
* and WP_MISSILE in secondaries. but in the interest of future coding I leave it like this.
|
||||
*/
|
||||
bool turret_weapon_has_subtype(ship_weapon *swp, int subtype)
|
||||
bool turret_weapon_has_subtype(const ship_weapon *swp, int subtype)
|
||||
{
|
||||
Assert(swp != NULL);
|
||||
|
||||
@@ -492,7 +492,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
|
||||
{
|
||||
object *turret_parent_obj = &Objects[eeo->turret_parent_objnum];
|
||||
ship *shipp;
|
||||
ship_subsys *ss = eeo->turret_subsys;
|
||||
auto ss = eeo->turret_subsys;
|
||||
float dist, dist_comp;
|
||||
bool turret_has_no_target = false;
|
||||
|
||||
@@ -772,8 +772,6 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
|
||||
*/
|
||||
int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subsys, int enemy_team_mask, vec3d *tpos, vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag, bool flak_flag, bool laser_flag, bool missile_flag)
|
||||
{
|
||||
//float weapon_travel_dist;
|
||||
int weapon_system_ok;
|
||||
eval_enemy_obj_struct eeo;
|
||||
ship_weapon *swp = &turret_subsys->weapons;
|
||||
|
||||
@@ -788,10 +786,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
|
||||
// weapon_travel_dist=wip->lssm_lock_range;
|
||||
|
||||
// Set flag based on strength of weapons subsystem. If weapons subsystem is destroyed, don't let turrets fire at bombs
|
||||
weapon_system_ok = 0;
|
||||
if ( ship_get_subsystem_strength( &Ships[Objects[turret_parent_objnum].instance], SUBSYSTEM_WEAPONS ) > 0 ) {
|
||||
weapon_system_ok = 1;
|
||||
}
|
||||
bool weapon_system_ok = !ship_subsystems_blown(&Ships[Objects[turret_parent_objnum].instance], SUBSYSTEM_WEAPONS);
|
||||
|
||||
// Initialize eeo struct.
|
||||
eeo.turret_parent_objnum = turret_parent_objnum;
|
||||
@@ -823,18 +818,6 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
|
||||
eeo.tvec = tvec;
|
||||
eeo.turret_subsys = turret_subsys;
|
||||
|
||||
eeo.nearest_attacker_dist = 99999.0f;
|
||||
eeo.nearest_attacker_objnum = -1;
|
||||
|
||||
eeo.nearest_homing_bomb_dist = 99999.0f;
|
||||
eeo.nearest_homing_bomb_objnum = -1;
|
||||
|
||||
eeo.nearest_bomb_dist = 99999.0f;
|
||||
eeo.nearest_bomb_objnum = -1;
|
||||
|
||||
eeo.nearest_dist = 99999.0f;
|
||||
eeo.nearest_objnum = -1;
|
||||
|
||||
// here goes the new targeting priority setting
|
||||
int n_tgt_priorities;
|
||||
int priority_weapon_idx = -1;
|
||||
@@ -1064,7 +1047,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3(); //Means invalid number passed.
|
||||
UNREACHABLE("Invalid target type of %d sent to get_nearest_turret_objnum. Please report to the SCP!", turret_subsys->turret_targeting_order[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1171,9 +1154,9 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
|
||||
Assert( !((Objects[enemy_objnum].flags[Object::Object_Flags::Flak_protected]) && flak_flag) );
|
||||
Assert( !((Objects[enemy_objnum].flags[Object::Object_Flags::Laser_protected]) && laser_flag) );
|
||||
Assert( !((Objects[enemy_objnum].flags[Object::Object_Flags::Missile_protected]) && missile_flag) );
|
||||
Assertion(!Objects[enemy_objnum].flags[Object::Object_Flags::Protected], "find_turret_enemy selected an object of type %d %s that is protected, please report to the SCP!", Objects[enemy_objnum].type, Objects[enemy_objnum].type == OBJ_SHIP ? Ships[Objects[enemy_objnum].instance].ship_name : "");
|
||||
|
||||
if ( Objects[enemy_objnum].flags[Object::Object_Flags::Protected] ) {
|
||||
Int3();
|
||||
enemy_objnum = aip->target_objnum;
|
||||
}
|
||||
}
|
||||
@@ -1385,7 +1368,8 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
|
||||
set_predicted_enemy_pos_turret(predicted_enemy_pos, &gun_pos, objp, &enemy_point, &target_vel, wip->max_speed, ss->turret_time_enemy_in_range * (weapon_system_strength + 1.0f)/2.0f);
|
||||
else {
|
||||
vec3d shoot_vec;
|
||||
if (physics_lead_ballistic_trajectory(&gun_pos, &enemy_point, &target_vel, wip->max_speed, &The_mission.gravity, &shoot_vec)) {
|
||||
vec3d gravity_vec = The_mission.gravity * wip->gravity_const;
|
||||
if (physics_lead_ballistic_trajectory(&gun_pos, &enemy_point, &target_vel, wip->max_speed, &gravity_vec, &shoot_vec)) {
|
||||
*predicted_enemy_pos = gun_pos + shoot_vec * 1000.0f;
|
||||
} else {
|
||||
if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
|
||||
@@ -1578,7 +1562,7 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en
|
||||
if(stride <= 0){
|
||||
stride = 1;
|
||||
}
|
||||
int offset = (int)frand_range(0.0f, (float)(aifft_list_size % stride));
|
||||
int offset = Random::next((aifft_list_size % stride) + 1); // returns an offset in [0, size % stride] inclusive
|
||||
int idx;
|
||||
float dot_fov_modifier = 0.0f;
|
||||
|
||||
@@ -2869,7 +2853,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
|
||||
}
|
||||
}
|
||||
|
||||
bool turret_std_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
|
||||
bool turret_std_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod)
|
||||
{
|
||||
model_subsystem *tp = ss->system_info;
|
||||
float dot = vm_vec_dot(v2e, gvec);
|
||||
@@ -2879,7 +2863,7 @@ bool turret_std_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
|
||||
return false;
|
||||
}
|
||||
|
||||
bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
|
||||
bool turret_adv_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod)
|
||||
{
|
||||
model_subsystem *tp = ss->system_info;
|
||||
float dot = vm_vec_dot(v2e, gvec);
|
||||
@@ -2905,7 +2889,7 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
|
||||
return false;
|
||||
}
|
||||
|
||||
bool turret_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
|
||||
bool turret_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod)
|
||||
{
|
||||
bool in_fov = false;
|
||||
if (ss->system_info->turret_base_fov > -1.0f)
|
||||
|
||||
@@ -22,19 +22,19 @@ anim_instance *init_anim_instance(anim *ptr, int bpp)
|
||||
{
|
||||
anim_instance *inst;
|
||||
|
||||
Assertion(ptr, "Bad pointer in init_anim_instance(), please report to the SCP!");
|
||||
if (!ptr) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( ptr->flags & ANF_STREAMED ) {
|
||||
Assertion(ptr->file_offset > -1, "Bad file offset of %d in init_anim_instance(), please report to the SCP!", ptr->file_offset);
|
||||
if ( ptr->file_offset < 0 ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
Assertion(ptr->data, "Bad data in init_anim_instance(), please report to the SCP!");
|
||||
if ( !ptr->data ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-10
@@ -401,12 +401,12 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
vec3d rotvel;
|
||||
if ( Game_mode & GM_NORMAL ) {
|
||||
vm_vec_rand_vec_quick(&rotvel);
|
||||
vm_vec_scale(&rotvel, frand()/4.0f + 0.1f);
|
||||
vm_vec_scale(&rotvel, asip->rotational_vel_multiplier * (frand()/4.0f + 0.1f));
|
||||
objp->phys_info.rotvel = rotvel;
|
||||
vm_vec_rand_vec_quick(&objp->phys_info.vel);
|
||||
} else {
|
||||
static_randvec( rand_base++, &rotvel );
|
||||
vm_vec_scale(&rotvel, static_randf(rand_base++)/4.0f + 0.1f);
|
||||
vm_vec_scale(&rotvel, asip->rotational_vel_multiplier * (static_randf(rand_base++)/4.0f + 0.1f));
|
||||
objp->phys_info.rotvel = rotvel;
|
||||
static_randvec( rand_base++, &objp->phys_info.vel );
|
||||
}
|
||||
@@ -1332,10 +1332,9 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
|
||||
|
||||
// copy important data
|
||||
int copy_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d copy_p0, copy_p1;
|
||||
copy_p0 = *mc.p0;
|
||||
copy_p1 = *mc.p1;
|
||||
int orig_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d orig_p0 = *mc.p0;
|
||||
vec3d orig_p1 = *mc.p1;
|
||||
|
||||
// first test against the sphere - if this fails then don't do any submodel tests
|
||||
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
|
||||
@@ -1361,7 +1360,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
}
|
||||
|
||||
// Only check single submodel now, since children of moving submodels are handled as moving as well
|
||||
mc.flags = copy_flags | MC_SUBMODEL;
|
||||
mc.flags = orig_flags | MC_SUBMODEL;
|
||||
|
||||
// check each submodel in turn
|
||||
for (auto submodel: submodel_vector) {
|
||||
@@ -1406,9 +1405,9 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
}
|
||||
|
||||
// Now complete base model collision checks that do not take into account rotating submodels.
|
||||
mc.flags = copy_flags;
|
||||
*mc.p0 = copy_p0;
|
||||
*mc.p1 = copy_p1;
|
||||
mc.flags = orig_flags;
|
||||
mc.p0 = &orig_p0;
|
||||
mc.p1 = &orig_p1;
|
||||
mc.orient = &heavy_obj->orient;
|
||||
|
||||
// usual ship_ship collision test
|
||||
@@ -2239,6 +2238,10 @@ static void asteroid_parse_section()
|
||||
stuff_float(&asteroid_p->max_speed);
|
||||
}
|
||||
|
||||
if (optional_string("$Rotational Velocity Multiplier:")) {
|
||||
stuff_float(&asteroid_p->rotational_vel_multiplier);
|
||||
}
|
||||
|
||||
if(optional_string("$Damage Type:")) {
|
||||
char buf[NAME_LENGTH];
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
int num_detail_levels; // number of detail levels for this ship
|
||||
int detail_distance[MAX_ASTEROID_DETAIL_LEVELS]; // distance to change detail levels at
|
||||
float max_speed; // cap on speed for asteroid
|
||||
float rotational_vel_multiplier; // rotational velocity multiplier for asteroid --wookieejedi
|
||||
int damage_type_idx; //Damage type of the asteroid
|
||||
int damage_type_idx_sav; // stored value from table used to reset damage_type_idx
|
||||
float inner_rad; // radius within which maximum area effect damage is applied
|
||||
@@ -80,7 +81,8 @@ public:
|
||||
float gravity_const; // multiplier for mission gravity
|
||||
|
||||
asteroid_info( )
|
||||
: type(ASTEROID_TYPE_DEBRIS), num_detail_levels(0), max_speed(0), damage_type_idx(0),
|
||||
: type(ASTEROID_TYPE_DEBRIS), num_detail_levels(0), max_speed(0),
|
||||
rotational_vel_multiplier(1), damage_type_idx(0),
|
||||
damage_type_idx_sav( -1 ), inner_rad( 0 ), outer_rad( 0 ),
|
||||
damage( 0 ), blast( 0 ), initial_asteroid_strength( 0 ),
|
||||
fireball_radius_multiplier( -1 ), spawn_weight( 1 ), gravity_const( 0 )
|
||||
|
||||
@@ -869,7 +869,7 @@ void EndAutoPilot()
|
||||
Assert( CurrentNav >= 0 );
|
||||
|
||||
int goal = 0;
|
||||
char *goal_name = NULL;
|
||||
const char *goal_name = NULL;
|
||||
|
||||
if (Navs[CurrentNav].flags & NP_WAYPOINT)
|
||||
{
|
||||
|
||||
@@ -425,6 +425,7 @@ DCF(bm_used, "Shows BmpMan Slot Usage") {
|
||||
|
||||
SCP_stringstream text;
|
||||
text << "BmpMan Used Slots\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << none << ", NONE\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << pcx << ", PCX\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << user << ", User\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << tga << ", TGA\n";
|
||||
|
||||
@@ -681,6 +681,8 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
|
||||
} else {
|
||||
// Path type given?
|
||||
Assert( dir_type != CF_TYPE_ANY );
|
||||
if (dir_type == CF_TYPE_ANY)
|
||||
return NULL;
|
||||
|
||||
// Create the directory if necessary
|
||||
cf_create_directory(dir_type, location_flags);
|
||||
|
||||
@@ -1172,7 +1172,7 @@ void cf_build_file_list()
|
||||
}
|
||||
|
||||
Warning(LOCATION, "Some critical files might be shadowed! Please check the debug log for details.\n\n"
|
||||
"%lu file(s) detected, including:\n%s", count, shadowed.c_str());
|
||||
SIZE_T_ARG " file(s) detected, including:\n%s", count, shadowed.c_str());
|
||||
}
|
||||
|
||||
critical_shadowed.clear();
|
||||
|
||||
@@ -82,7 +82,7 @@ void SpawnShipCheat::runCheat() {
|
||||
if (ptr->system_info->type == SUBSYSTEM_TURRET)
|
||||
{
|
||||
ptr->weapons.flags.set(Ship::Weapon_Flags::Beam_Free);
|
||||
ptr->turret_next_fire_stamp = timestamp((int)frand_range(50.0f, 4000.0f));
|
||||
ptr->turret_next_fire_stamp = timestamp(Random::next(50, 4000));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "globalincs/version.h"
|
||||
#include "graphics/openxr.h"
|
||||
#include "graphics/shadows.h"
|
||||
#include "hud/hudconfig.h"
|
||||
#include "io/joy.h"
|
||||
@@ -196,6 +197,8 @@ Flag exe_params[] =
|
||||
{ "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
|
||||
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
|
||||
{ "-no_screenshake", "Disable screen shaking", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_screenshake", },
|
||||
{ "-vr", "Enable Virtual Reality Mode", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-vr", },
|
||||
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
|
||||
|
||||
//flag launcher text FSO on_flags off_flags category reference URL
|
||||
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
|
||||
@@ -219,6 +222,7 @@ Flag exe_params[] =
|
||||
|
||||
//flag launcher text FSO on_flags off_flags category reference URL
|
||||
{ "-no_set_gamma", "Disable setting of gamma", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_set_gamma", },
|
||||
{ "-no_ingame_options", "Disable using ingame options", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ingame_options", },
|
||||
{ "-nomovies", "Disable video playback", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomovies", },
|
||||
{ "-noparseerrors", "Disable parsing errors", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noparseerrors", },
|
||||
{ "-loadallweps", "Load all weapons, even those not used", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-loadallweps", },
|
||||
@@ -264,7 +268,6 @@ Flag exe_params[] =
|
||||
{ "-verify_vps", "Spew VP CRCs to vp_crcs.txt", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-verify_vps", },
|
||||
{ "-reparse_mainhall", "Reparse mainhall.tbl when loading halls", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-reparse_mainhall", },
|
||||
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
|
||||
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
|
||||
{ "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
|
||||
{ "-profile_frame_time","Profile frame time", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_time", },
|
||||
{ "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
|
||||
@@ -409,6 +412,7 @@ cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", nullptr, AT_NONE);
|
||||
cmdline_parm stretch_menu("-stretch_menu", nullptr, AT_NONE); // Cmdline_stretch_menu
|
||||
cmdline_parm capture_mouse("-capture_mouse", nullptr, AT_NONE); // Cmdline_capture_mouse
|
||||
cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
|
||||
cmdline_parm vr("-vr", nullptr, AT_NONE);
|
||||
cmdline_parm deadzone("-deadzone",
|
||||
"Sets the joystick deadzone. Integer value from 0 to 100 as a percentage of the joystick's range (100% would make the stick do nothing). Disables deadzone slider in the in-game Options menu.", AT_INT); //Cmdline_deadzone
|
||||
|
||||
@@ -419,6 +423,7 @@ int Cmdline_stretch_menu = 0;
|
||||
bool Cmdline_capture_mouse = false;
|
||||
int Cmdline_no_screenshake = 0;
|
||||
int Cmdline_deadzone = -1;
|
||||
bool Cmdline_enable_vr = false;
|
||||
|
||||
// Audio related
|
||||
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
|
||||
@@ -456,6 +461,7 @@ SCP_string Cmdline_lang;
|
||||
cmdline_parm loadallweapons_arg("-loadallweps", NULL, AT_NONE); // Cmdline_load_all_weapons
|
||||
cmdline_parm nomovies_arg("-nomovies", NULL, AT_NONE); // Cmdline_nomovies -- Allows video streaming
|
||||
cmdline_parm no_set_gamma_arg("-no_set_gamma", NULL, AT_NONE); // Cmdline_no_set_gamma
|
||||
cmdline_parm no_ingame_options_arg("-no_ingame_options", NULL, AT_NONE); // Cmdline_no_ingame_options
|
||||
cmdline_parm no_fbo_arg("-disable_fbo", NULL, AT_NONE); // Cmdline_no_fbo
|
||||
cmdline_parm no_pbo_arg("-disable_pbo", NULL, AT_NONE); // Cmdline_no_pbo
|
||||
cmdline_parm mipmap_arg("-mipmap", NULL, AT_NONE); // Cmdline_mipmap
|
||||
@@ -479,6 +485,7 @@ cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
|
||||
int Cmdline_load_all_weapons = 0;
|
||||
int Cmdline_nomovies = 0;
|
||||
int Cmdline_no_set_gamma = 0;
|
||||
bool Cmdline_no_ingame_options = false;
|
||||
int Cmdline_no_fbo = 0;
|
||||
int Cmdline_no_pbo = 0;
|
||||
int Cmdline_ati_color_swap = 0;
|
||||
@@ -513,7 +520,9 @@ cmdline_parm stats_arg("-stats", NULL, AT_NONE); // Cmdline_show_stats
|
||||
cmdline_parm save_render_targets_arg("-save_render_target", NULL, AT_NONE); // Cmdline_save_render_targets
|
||||
cmdline_parm window_arg("-window", NULL, AT_NONE); // Cmdline_window
|
||||
cmdline_parm fullscreen_window_arg("-fullscreen_window", "Fullscreen/borderless window (Windows only)", AT_NONE);
|
||||
cmdline_parm res_arg("-res", "Resolution, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm deprecated_res_arg("-res", "Deprecated, resolution, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm render_res_arg("-render_res", "Resolution, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm window_res_arg("-window_res", "Window resolution, formatted like 1600x900.", AT_STRING);
|
||||
cmdline_parm center_res_arg("-center_res", "Resolution of center monitor, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm verify_vps_arg("-verify_vps", NULL, AT_NONE); // Cmdline_verify_vps -- spew VP crcs to vp_crcs.txt
|
||||
cmdline_parm parse_cmdline_only(PARSE_COMMAND_LINE_STRING, "Ignore any cmdline_fso.cfg files", AT_NONE);
|
||||
@@ -551,6 +560,7 @@ int Cmdline_show_stats = 0;
|
||||
int Cmdline_save_render_targets = 0;
|
||||
int Cmdline_window = 0;
|
||||
int Cmdline_fullscreen_window = 0;
|
||||
tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res = tl::nullopt;
|
||||
char *Cmdline_res = 0;
|
||||
char *Cmdline_center_res = 0;
|
||||
int Cmdline_verify_vps = 0;
|
||||
@@ -1713,31 +1723,48 @@ bool SetCmdlineParams()
|
||||
// d3d windowed
|
||||
if(window_arg.found()) {
|
||||
// We need to set both values since we don't know if we are going to use the new config system
|
||||
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
|
||||
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
|
||||
Cmdline_window = 1;
|
||||
}
|
||||
|
||||
if ( fullscreen_window_arg.found( ) )
|
||||
{
|
||||
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
|
||||
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
|
||||
Cmdline_fullscreen_window = 1;
|
||||
Cmdline_window = 0; /* Make sure no-one sets both */
|
||||
}
|
||||
|
||||
if(res_arg.found()){
|
||||
Cmdline_res = res_arg.str();
|
||||
if(render_res_arg.found() || deprecated_res_arg.found()){
|
||||
if (render_res_arg.found()) {
|
||||
Cmdline_res = render_res_arg.str();
|
||||
}
|
||||
else {
|
||||
Cmdline_res = deprecated_res_arg.str();
|
||||
mprintf(("Deprecated -res argument. Use -render_res instead...\n"));
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
/*int width = 0;
|
||||
int height = 0;
|
||||
|
||||
if ( sscanf(Cmdline_res, "%dx%d", &width, &height) == 2 ) {
|
||||
if (sscanf(Cmdline_res, "%dx%d", &width, &height) == 2) {
|
||||
SCP_string override;
|
||||
sprintf(override, "{\"width\":%d,\"height\":%d}", width, height);
|
||||
options::OptionsManager::instance()->setOverride("Graphics.Resolution", override);
|
||||
} else {
|
||||
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".\n", Cmdline_res));
|
||||
Warning(LOCATION, "Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".\n", Cmdline_res);
|
||||
}*/
|
||||
}
|
||||
if(window_res_arg.found()){
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
if ( sscanf(window_res_arg.str(), "%dx%d", &width, &height) == 2 ) {
|
||||
Cmdline_window_res.emplace(static_cast<uint16_t>(width), static_cast<uint16_t>(height));
|
||||
} else {
|
||||
Warning(LOCATION, "Failed to parse -window_res parameter \"%s\". Must be in format \"<width>x<height>\".\n", window_res_arg.str());
|
||||
}
|
||||
}
|
||||
|
||||
if(center_res_arg.found()){
|
||||
Cmdline_center_res = center_res_arg.str();
|
||||
}
|
||||
@@ -1846,6 +1873,14 @@ bool SetCmdlineParams()
|
||||
}
|
||||
}
|
||||
|
||||
if (vr.found()) {
|
||||
Cmdline_enable_vr = true;
|
||||
if (fov_arg.found() || fov_cockpit_arg.found()) {
|
||||
Warning(LOCATION, "FoV Command line settings found. VR-Mode will override these with the HMD's native FoV...");
|
||||
}
|
||||
openxr_prepare();
|
||||
}
|
||||
|
||||
if (orb_radar.found())
|
||||
{
|
||||
Cmdline_orb_radar = 1;
|
||||
@@ -1901,6 +1936,10 @@ bool SetCmdlineParams()
|
||||
Cmdline_no_set_gamma = 1;
|
||||
}
|
||||
|
||||
if (no_ingame_options_arg.found()) {
|
||||
Cmdline_no_ingame_options = true;
|
||||
}
|
||||
|
||||
if(no_vsync_arg.found() )
|
||||
{
|
||||
Gr_enable_vsync = false;
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
* source.
|
||||
*
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FS_CMDLINE_HEADER_FILE
|
||||
#define FS_CMDLINE_HEADER_FILE
|
||||
|
||||
#include <tl/optional.hpp>
|
||||
|
||||
int parse_cmdline(int argc, char *argv[]);
|
||||
|
||||
@@ -46,6 +47,7 @@ extern int Cmdline_use_last_pilot;
|
||||
extern int Cmdline_window;
|
||||
extern int Cmdline_fullscreen_window;
|
||||
extern char *Cmdline_res;
|
||||
extern tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res;
|
||||
extern char *Cmdline_center_res;
|
||||
|
||||
|
||||
@@ -89,6 +91,7 @@ extern int Cmdline_stretch_menu;
|
||||
extern bool Cmdline_capture_mouse;
|
||||
extern int Cmdline_no_screenshake;
|
||||
extern int Cmdline_deadzone;
|
||||
extern bool Cmdline_enable_vr;
|
||||
|
||||
// Audio related
|
||||
extern int Cmdline_voice_recognition;
|
||||
@@ -111,6 +114,7 @@ extern SCP_string Cmdline_lang;
|
||||
extern int Cmdline_load_all_weapons;
|
||||
extern int Cmdline_nomovies; // WMC Toggles movie playing support
|
||||
extern int Cmdline_no_set_gamma;
|
||||
extern bool Cmdline_no_ingame_options;
|
||||
extern int Cmdline_no_fbo;
|
||||
extern int Cmdline_no_pbo;
|
||||
extern int Cmdline_mipmap;
|
||||
|
||||
@@ -264,11 +264,11 @@ void control_config_common_init_bindings() {
|
||||
(HUD_TARGETBOX_TOGGLE_WIREFRAME, KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, 1, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER)
|
||||
|
||||
// Custom Controls
|
||||
(CUSTOM_CONTROL_1, KEY_ALTED | KEY_SHIFTED | KEY_1, -1, COMPUTER_TAB, 0, "Custom Control 1", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_2, KEY_ALTED | KEY_SHIFTED | KEY_2, -1, COMPUTER_TAB, 0, "Custom Control 2", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_3, KEY_ALTED | KEY_SHIFTED | KEY_3, -1, COMPUTER_TAB, 0, "Custom Control 3", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_4, KEY_ALTED | KEY_SHIFTED | KEY_4, -1, COMPUTER_TAB, 0, "Custom Control 4", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_5, KEY_ALTED | KEY_SHIFTED | KEY_5, -1, COMPUTER_TAB, 0, "Custom Control 5", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_1, KEY_ALTED | KEY_SHIFTED | KEY_1, -1, COMPUTER_TAB, 1784, "Custom Control 1", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_2, KEY_ALTED | KEY_SHIFTED | KEY_2, -1, COMPUTER_TAB, 1785, "Custom Control 2", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_3, KEY_ALTED | KEY_SHIFTED | KEY_3, -1, COMPUTER_TAB, 1786, "Custom Control 3", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_4, KEY_ALTED | KEY_SHIFTED | KEY_4, -1, COMPUTER_TAB, 1787, "Custom Control 4", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_5, KEY_ALTED | KEY_SHIFTED | KEY_5, -1, COMPUTER_TAB, 1788, "Custom Control 5", CC_TYPE_TRIGGER, true)
|
||||
.end(); // Builder
|
||||
|
||||
// init default preset
|
||||
@@ -451,7 +451,7 @@ const char* Joy_button_text_french_u[] = {
|
||||
"Bouton 13", "Bouton 14", "Bouton 15", "Bouton 16", "Bouton 17", "Bouton 18",
|
||||
"Bouton 19", "Bouton 20", "Bouton 21", "Bouton 22", "Bouton 23", "Bouton 24",
|
||||
"Bouton 25", "Bouton 26", "Bouton 27", "Bouton 28", "Bouton 29", "Bouton 30",
|
||||
"Bouton 31", "Bouton 32", "Chapeau Arri\xc3\xa8""re", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
|
||||
"Bouton 31", "Bouton 32", ("Chapeau Arri\xc3\xa8""re"), "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
|
||||
};
|
||||
|
||||
const char* Joy_button_text_polish_u[] = {
|
||||
@@ -460,7 +460,7 @@ const char* Joy_button_text_polish_u[] = {
|
||||
"Przyc.13", "Przyc.14", "Przyc.15", "Przyc.16", "Przyc.17", "Przyc.18",
|
||||
"Przyc.19", "Przyc.20", "Przyc.21", "Przyc.22", "Przyc.23", "Przyc.24",
|
||||
"Przyc.25", "Przyc.26", "Przyc.27", "Przyc.28", "Przyc.29", "Przyc.30",
|
||||
"Przyc.31", "Przyc.32", "Hat Ty\xc5\x82", "Hat Prz\xc3\xb3""d", "Hat Lewo", "Hat Prawo"
|
||||
"Przyc.31", "Przyc.32", "Hat Ty\xc5\x82", ("Hat Prz\xc3\xb3""d"), "Hat Lewo", "Hat Prawo"
|
||||
};
|
||||
|
||||
const char* Joy_button_text_english_u[] = {
|
||||
|
||||
@@ -52,6 +52,7 @@ struct MovieProperties {
|
||||
FrameSize size;
|
||||
|
||||
float fps = -1.0f;
|
||||
float duration = 0.0f;
|
||||
|
||||
FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
|
||||
};
|
||||
|
||||
@@ -222,7 +222,6 @@ void cutscene_mark_viewable(const char* filename)
|
||||
|
||||
// change to lower case
|
||||
strlwr(file);
|
||||
int i = 0;
|
||||
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
|
||||
{
|
||||
// change the cutscene file name to lower case
|
||||
@@ -235,7 +234,6 @@ void cutscene_mark_viewable(const char* filename)
|
||||
cut->flags.set(Cutscene::Cutscene_Flags::Viewable);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
Warning(LOCATION, "Could not find cutscene '%s' in listing; cannot mark it viewable...", filename);
|
||||
|
||||
@@ -503,6 +503,7 @@ MovieProperties FFMPEGDecoder::getProperties() const
|
||||
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
|
||||
|
||||
props.fps = static_cast<float>(getFrameRate(m_status->videoStream, m_status->videoCodecCtx));
|
||||
props.duration = static_cast<float>(m_status->videoStream->duration * av_q2d(m_status->videoStream->time_base));
|
||||
|
||||
props.pixelFormat = getPixelFormat(getConversionFormat(m_status->videoCodecPars.pixel_format));
|
||||
|
||||
|
||||
@@ -926,10 +926,9 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
|
||||
|
||||
// copy important data
|
||||
int copy_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d copy_p0, copy_p1;
|
||||
copy_p0 = *mc.p0;
|
||||
copy_p1 = *mc.p1;
|
||||
int orig_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d orig_p0 = *mc.p0;
|
||||
vec3d orig_p1 = *mc.p1;
|
||||
|
||||
// first test against the sphere - if this fails then don't do any submodel tests
|
||||
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
|
||||
@@ -955,7 +954,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
}
|
||||
|
||||
// Only check single submodel now, since children of moving submodels are handled as moving as well
|
||||
mc.flags = copy_flags | MC_SUBMODEL;
|
||||
mc.flags = orig_flags | MC_SUBMODEL;
|
||||
|
||||
if (Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod > -1) {
|
||||
mc.lod = Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod;
|
||||
@@ -1005,9 +1004,9 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
}
|
||||
|
||||
// Now complete base model collision checks that do not take into account rotating submodels.
|
||||
mc.flags = copy_flags;
|
||||
*mc.p0 = copy_p0;
|
||||
*mc.p1 = copy_p1;
|
||||
mc.flags = orig_flags;
|
||||
mc.p0 = &orig_p0;
|
||||
mc.p1 = &orig_p1;
|
||||
mc.orient = &heavy_obj->orient;
|
||||
|
||||
// usual ship_ship collision test
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
in vec4 fragTexCoord;
|
||||
out vec4 fragOut0;
|
||||
|
||||
#ifdef COPY_ARRAY
|
||||
uniform sampler2DArray tex;
|
||||
#else
|
||||
uniform sampler2D tex;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef COPY_ARRAY
|
||||
fragOut0 = texture(tex, vec3(fragTexCoord.xy, 0));
|
||||
#else
|
||||
fragOut0 = texture(tex, fragTexCoord.xy);
|
||||
#endif
|
||||
}
|
||||
@@ -263,6 +263,9 @@ void main()
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
|
||||
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
|
||||
specColor *= alphaMult;
|
||||
}
|
||||
if(alphaGloss) glossData = specColor.a;
|
||||
if(gammaSpec) {
|
||||
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
|
||||
@@ -397,6 +400,11 @@ void main()
|
||||
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
|
||||
}
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
|
||||
//Since this is emissive, we need to premultiply it for intensity, and apply alpha to not replace existing emissive
|
||||
emissiveColor *= alphaMult;
|
||||
}
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
|
||||
vec3 finalFogColor = fogColor.rgb;
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
|
||||
|
||||
@@ -37,7 +37,6 @@ vec3 Uncharted2ToneMapping(vec3 hdr_color) // John Hable's filmic
|
||||
hdr_color = ((hdr_color * (A * hdr_color + C * B) + D * E) / (hdr_color * (A * hdr_color + B) + D * F)) - E / F;
|
||||
float white = ((W * (A * W + C * B) + D * E) / (W * (A * W + B) + D * F)) - E / F;
|
||||
hdr_color /= white;
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
|
||||
return hdr_color;
|
||||
}
|
||||
@@ -65,7 +64,6 @@ vec3 aces(vec3 hdr_color)
|
||||
hdr_color = aces_input * hdr_color;
|
||||
hdr_color = rtt_and_odt_fit(hdr_color);
|
||||
hdr_color = aces_output * hdr_color;
|
||||
hdr_color = linear_to_srgb(hdr_color);
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -79,7 +77,6 @@ vec3 aces_approx(vec3 hdr_color) // also filmic, higher contrast then Uncharted2
|
||||
hdr_color *= 0.6f;
|
||||
|
||||
hdr_color = clamp((hdr_color*(a*hdr_color+b))/(hdr_color*(c*hdr_color+d)+e), 0.0f, 1.0f);
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -96,7 +93,6 @@ vec3 rhj_lumaToneMapping(vec3 hdr_color) // reinhard_jodie
|
||||
float luma = dot(hdr_color, vec3(0.2126, 0.7152, 0.0722)); //dot products are a bit more expensive
|
||||
float toneMappedLuma = luma / (1.0 + luma);
|
||||
hdr_color *= toneMappedLuma / luma;
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -105,14 +101,12 @@ vec3 reinhard_extended(vec3 hdr_color)
|
||||
float max_white = 1.0;
|
||||
vec3 numerator = hdr_color * (1.0f + (hdr_color / vec3(max_white * max_white)));
|
||||
hdr_color = numerator / (1.0f + hdr_color);
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
vec3 linearToneMapping(vec3 hdr_color)
|
||||
{
|
||||
hdr_color = clamp(hdr_color, 0., 1.);
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -155,7 +149,7 @@ vec3 PPC_RGB( vec3 color ) {
|
||||
funswitch(color.g),
|
||||
funswitch(color.b));
|
||||
|
||||
return linear_to_srgb(color);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +168,7 @@ vec3 PPC( vec3 color ) {
|
||||
else {
|
||||
luma_tone = sh_offsetY;
|
||||
}
|
||||
return linear_to_srgb(color * luma_tone / luma);
|
||||
return color * luma_tone / luma;
|
||||
}
|
||||
|
||||
|
||||
@@ -213,5 +207,9 @@ void main()
|
||||
break;
|
||||
|
||||
}
|
||||
#ifdef LINEAR_OUT
|
||||
fragOut0 = vec4(color.rgb, 1.0);
|
||||
#else
|
||||
fragOut0 = vec4(linear_to_srgb(color.rgb), 1.0);
|
||||
#endif
|
||||
}
|
||||
@@ -11,7 +11,7 @@ $AI:
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Turrets attack this: YES
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Sentry Gun
|
||||
$Counts for Alone: YES
|
||||
@@ -32,7 +32,7 @@ $AI:
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Escape Pod
|
||||
$Praise Destruction: YES
|
||||
@@ -51,7 +51,7 @@ $AI:
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Turrets attack this: YES
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Cargo
|
||||
$Scannable: YES
|
||||
@@ -65,7 +65,7 @@ $Fog:
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Passive docks: ( "cargo" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Support
|
||||
$Counts for Alone: YES
|
||||
@@ -92,7 +92,7 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Active docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
;;WMC - Stealth ships always have another type, so this isn't used
|
||||
$Name: Stealth
|
||||
@@ -118,7 +118,7 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Fighter
|
||||
$Counts for Alone: YES
|
||||
@@ -146,7 +146,7 @@ $AI:
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Bomber
|
||||
$Counts for Alone: YES
|
||||
@@ -174,7 +174,7 @@ $AI:
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
|
||||
$Name: Fighter/bomber
|
||||
@@ -202,7 +202,7 @@ $AI:
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Transport
|
||||
$Counts for Alone: YES
|
||||
@@ -232,7 +232,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Freighter
|
||||
$Counts for Alone: YES
|
||||
@@ -264,7 +264,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: AWACS
|
||||
$Counts for Alone: YES
|
||||
@@ -294,7 +294,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Gas Miner
|
||||
$Counts for Alone: YES
|
||||
@@ -324,7 +324,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Cruiser
|
||||
$Counts for Alone: YES
|
||||
@@ -354,7 +354,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Corvette
|
||||
$Counts for Alone: YES
|
||||
@@ -384,7 +384,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Capital
|
||||
$Counts for Alone: YES
|
||||
@@ -414,7 +414,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Super Cap
|
||||
$Counts for Alone: YES
|
||||
@@ -442,7 +442,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Drydock
|
||||
$Counts for Alone: YES
|
||||
@@ -468,7 +468,7 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Knossos Device
|
||||
$Counts for Alone: YES
|
||||
@@ -492,6 +492,6 @@ $AI:
|
||||
+Passive docks: ( "support" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
#End
|
||||
@@ -113,7 +113,8 @@ const char *GS_event_text[] =
|
||||
"GS_EVENT_LAB",
|
||||
"GS_EVENT_PXO_HELP",
|
||||
"GS_EVENT_FICTION_VIEWER", // 65
|
||||
"GS_EVENT_SCRIPTING"
|
||||
"GS_EVENT_SCRIPTING",
|
||||
"GS_EVENT_SCRIPTING_MISSION"
|
||||
};
|
||||
//XSTR:ON
|
||||
|
||||
@@ -176,7 +177,8 @@ const char *GS_state_text[] =
|
||||
"GS_STATE_PXO_HELP", // 50
|
||||
"GS_STATE_START_GAME",
|
||||
"GS_STATE_FICTION_VIEWER",
|
||||
"GS_STATE_SCRIPTING"
|
||||
"GS_STATE_SCRIPTING",
|
||||
"GS_STATE_SCRIPTING_MISSION"
|
||||
};
|
||||
//XSTR:ON
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ enum GS_EVENT {
|
||||
GS_EVENT_PXO_HELP,
|
||||
GS_EVENT_FICTION_VIEWER,
|
||||
GS_EVENT_SCRIPTING,
|
||||
GS_EVENT_SCRIPTING_MISSION,
|
||||
|
||||
GS_NUM_EVENTS // Last one++
|
||||
};
|
||||
@@ -159,6 +160,7 @@ enum GS_STATE {
|
||||
GS_STATE_START_GAME,
|
||||
GS_STATE_FICTION_VIEWER,
|
||||
GS_STATE_SCRIPTING,
|
||||
GS_STATE_SCRIPTING_MISSION,
|
||||
|
||||
GS_NUM_STATES // Last one++
|
||||
};
|
||||
|
||||
@@ -340,7 +340,7 @@ void event_music_init()
|
||||
Warning(LOCATION, "Soundtrack file %s was not found with its specified extension, but another file %s exists in the modpack. Please update the extension and adjust audio specifications if necessary.", filename, res.name_ext.c_str());
|
||||
#endif
|
||||
|
||||
Warning(LOCATION, "One or more files in '%s' could not be loaded. The soundtrack will not be used.", soundtrack.name);
|
||||
Warning(LOCATION, "Soundtrack file %s was not found. The soundtrack '%s' will not be used.", filename, soundtrack.name);
|
||||
all_patterns_valid = false;
|
||||
break;
|
||||
}
|
||||
@@ -970,11 +970,13 @@ int event_music_friendly_arrival()
|
||||
// overlay
|
||||
if (Soundtracks[Current_soundtrack_num].flags & EMF_ALLIED_ARRIVAL_OVERLAY)
|
||||
{
|
||||
// Goober5000 - I didn't touch this part... for some reason, FS2 only has one
|
||||
// Goober5000 - This is how retail did it. For some reason, FS2 only has one
|
||||
// arrival music pattern, and this is it
|
||||
Assert(Patterns[SONG_AARV_1].handle >= 0 );
|
||||
audiostream_play(Patterns[SONG_AARV_1].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].samples_per_measure) );
|
||||
if (Patterns[SONG_AARV_1].handle >= 0)
|
||||
{
|
||||
audiostream_play(Patterns[SONG_AARV_1].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].samples_per_measure));
|
||||
}
|
||||
}
|
||||
// don't overlay
|
||||
else
|
||||
|
||||
@@ -191,8 +191,8 @@ class flagset {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool any_set() { return values.any(); }
|
||||
bool none_set() { return values.none(); }
|
||||
bool any_set() const { return values.any(); }
|
||||
bool none_set() const { return values.none(); }
|
||||
|
||||
void from_u64(std::uint64_t num) { values = (unsigned long) num; }
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ constexpr bool LoggingEnabled = false;
|
||||
// Disabling this functionality is dangerous, crazy values can run rampant unchecked, and the longer it's disabled
|
||||
// the more likely you are to have problems getting it working again.
|
||||
#if defined(NDEBUG)
|
||||
# define Assert(expr) do { ASSUME(expr); } while (false)
|
||||
# define Assert(expr) do { ASSUME(expr); (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
# define Assert(expr) do {\
|
||||
if (!(expr)) {\
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "debugconsole/console.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "io/timer.h"
|
||||
#include "nebula/neb.h"
|
||||
#include "options/Option.h"
|
||||
|
||||
@@ -34,12 +33,6 @@ float Cutscene_delta_time = 1.0f;
|
||||
//How far along a change is (0 to 1)
|
||||
float Cutscene_bars_progress = 1.0f;
|
||||
|
||||
//FADEIN STUFF
|
||||
shader Viewer_shader;
|
||||
FadeType Fade_type = FI_NONE;
|
||||
int Fade_start_timestamp = 0;
|
||||
int Fade_end_timestamp = 0;
|
||||
|
||||
// The detail level. Anything below zero draws simple models earlier than it
|
||||
// should. Anything above zero draws higher detail models longer than it should.
|
||||
// -2=lowest
|
||||
|
||||
@@ -59,19 +59,6 @@
|
||||
extern float Cutscene_bars_progress, Cutscene_delta_time;
|
||||
extern int Cutscene_bar_flags;
|
||||
|
||||
//-----Fadein stuff
|
||||
struct shader;
|
||||
extern shader Viewer_shader;
|
||||
|
||||
enum FadeType {
|
||||
FI_NONE,
|
||||
FI_FADEIN,
|
||||
FI_FADEOUT
|
||||
};
|
||||
extern FadeType Fade_type;
|
||||
extern int Fade_start_timestamp;
|
||||
extern int Fade_end_timestamp;
|
||||
|
||||
|
||||
typedef struct vei {
|
||||
angles_t angles; // Angles defining viewer location.
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do { } while (false)
|
||||
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
/*
|
||||
* NOTE: Assertion() can only use its proper functionality in compilers
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do {} while (false)
|
||||
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
/*
|
||||
* NOTE: Assertion() can only use its proper functionality in compilers
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do {} while (false)
|
||||
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
/*
|
||||
* NOTE: Assertion() can only use its proper functionality in compilers
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do { ASSUME(expr); } while (false)
|
||||
# define Assertion(expr, msg, ...) do { ASSUME(expr); (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
# define Assertion(expr, msg, ...) \
|
||||
do { \
|
||||
|
||||
@@ -25,6 +25,16 @@ bool SCP_vector_contains(SCP_vector<T>& vector, T item) {
|
||||
return std::find(vector.begin(), vector.end(), item) != vector.end();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool SCP_vector_inbounds(SCP_vector<T>& vector, int idx) {
|
||||
return ((idx >= 0) && (idx < static_cast<int>(vector.size())));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool SCP_vector_inbounds(SCP_vector<T>& vector, size_t idx) {
|
||||
return idx < vector.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using SCP_list = std::list<T, std::allocator<T>>;
|
||||
|
||||
|
||||
+54
-7
@@ -25,6 +25,7 @@
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "debugconsole/console.h"
|
||||
#include "executor/global_executors.h"
|
||||
#include "graphics/openxr.h"
|
||||
#include "graphics/paths/PathRenderer.h"
|
||||
#include "graphics/post_processing.h"
|
||||
#include "graphics/util/GPUMemoryHeap.h"
|
||||
@@ -265,6 +266,7 @@ static auto VideoDisplayOption = options::OptionBuilder<int>("Graphics.Display",
|
||||
.serializer(videodisplay_serializer)
|
||||
.enumerator(videodisplay_enumerator)
|
||||
.display(videodisplay_display)
|
||||
.flags({options::OptionFlags::ForceMultiValueSelection})
|
||||
.default_val(0)
|
||||
.change_listener(videodisplay_change)
|
||||
.importance(99)
|
||||
@@ -704,7 +706,7 @@ bool gr_resize_screen_pos(int *x, int *y, int *w, int *h, int resize_mode)
|
||||
*/
|
||||
bool gr_unsize_screen_pos(int *x, int *y, int *w, int *h, int resize_mode)
|
||||
{
|
||||
if ( resize_mode == GR_RESIZE_NONE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
|
||||
if ( resize_mode == GR_RESIZE_NONE || resize_mode == GR_RESIZE_REPLACE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1025,6 +1027,9 @@ void gr_close()
|
||||
return;
|
||||
}
|
||||
|
||||
if(Cmdline_enable_vr)
|
||||
openxr_close();
|
||||
|
||||
if (Gr_original_gamma_ramp != nullptr && os::getSDLMainWindow() != nullptr) {
|
||||
SDL_SetWindowGammaRamp(os::getSDLMainWindow(), Gr_original_gamma_ramp, (Gr_original_gamma_ramp + 256),
|
||||
(Gr_original_gamma_ramp + 512));
|
||||
@@ -1256,14 +1261,38 @@ static void init_colors()
|
||||
Gr_ta_alpha.scale = 17;
|
||||
}
|
||||
|
||||
static void gr_init_function_pointers(int mode) {
|
||||
gr_screen = {};
|
||||
|
||||
switch (mode) {
|
||||
case GR_OPENGL:
|
||||
#ifdef WITH_OPENGL
|
||||
gr_opengl_init_function_pointers();
|
||||
#else
|
||||
Error(LOCATION, "OpenGL renderer was requested but that was not compiled into this build.");
|
||||
#endif
|
||||
break;
|
||||
case GR_VULKAN:
|
||||
#ifdef WITH_VULKAN
|
||||
graphics::vulkan::initialize_function_pointers();
|
||||
#else
|
||||
Error(LOCATION, "Vulkan renderer was requested but that was not compiled into this build.");
|
||||
#endif
|
||||
break;
|
||||
case GR_STUB:
|
||||
gr_stub_init_function_pointers();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("Invalid graphics mode requested"); // Invalid graphics mode
|
||||
}
|
||||
}
|
||||
|
||||
static bool gr_init_sub(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int mode, int width, int height,
|
||||
int depth, float center_aspect_ratio)
|
||||
{
|
||||
int res = GR_1024;
|
||||
bool rc = false;
|
||||
|
||||
gr_screen = {};
|
||||
|
||||
float aspect_ratio = (float)width / (float)height;
|
||||
|
||||
if ( (((width == 640) && (height == 480)) || ((width == 1024) && (height == 768))) && (aspect_ratio == center_aspect_ratio) ) {
|
||||
@@ -1562,9 +1591,6 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
|
||||
depth = d_depth;
|
||||
}
|
||||
|
||||
if (Cmdline_vulkan)
|
||||
mode = GR_VULKAN;
|
||||
|
||||
// if we are in standalone mode then just use special defaults
|
||||
if (Is_standalone) {
|
||||
mode = GR_STUB;
|
||||
@@ -1574,6 +1600,8 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
|
||||
center_aspect_ratio = -1.0f;
|
||||
}
|
||||
|
||||
gr_init_function_pointers(mode);
|
||||
|
||||
if (gr_get_resolution_class(width, height) != GR_640) {
|
||||
// check for hi-res interface files so that we can verify our width/height is correct
|
||||
// if we don't have it then fall back to 640x480 mode instead
|
||||
@@ -1591,6 +1619,17 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
|
||||
}
|
||||
}
|
||||
|
||||
if (Cmdline_enable_vr) {
|
||||
float user_ar = i2fl(width) / i2fl(height);
|
||||
float xr_ar = openxr_preinit(user_ar);
|
||||
|
||||
if (MAX(user_ar, xr_ar) / MIN(user_ar, xr_ar) > 1.05f) {
|
||||
int newWidth = fl2i(i2fl(height) * xr_ar);
|
||||
mprintf(("User specified resolution does not match OpenXR HMD aspect ratio. Adjusting width from %dpx to %dpx.", width, newWidth));
|
||||
width = newWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// These compiler macros will force windowed mode at the specified resolution if
|
||||
// built in debug mode. This helps if you run with the debugger active as the
|
||||
// game won't be switching from fullscreen to minimized every time you hit a breakpoint or
|
||||
@@ -1709,6 +1748,9 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
|
||||
Shadow_quality = ShadowQuality::Disabled;
|
||||
}
|
||||
|
||||
if(Cmdline_enable_vr)
|
||||
openxr_init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2597,7 +2639,12 @@ void gr_flip(bool execute_scripting)
|
||||
uniform_buffer_managers_retire_buffers();
|
||||
|
||||
TRACE_SCOPE(tracing::PageFlip);
|
||||
gr_screen.gf_flip();
|
||||
|
||||
//Prevent a real page flip if OpenXR is on and claims that that wasn't the full image yet
|
||||
if (!gr_openxr_flip()) {
|
||||
gr_screen.gf_flip();
|
||||
gr_setup_frame();
|
||||
}
|
||||
}
|
||||
|
||||
void gr_print_timestamp(int x, int y, fix timestamp, int resize_mode)
|
||||
|
||||
@@ -203,6 +203,7 @@ enum shader_type {
|
||||
SDR_TYPE_VOLUMETRIC_FOG,
|
||||
SDR_TYPE_ROCKET_UI,
|
||||
SDR_TYPE_COPY,
|
||||
SDR_TYPE_COPY_WORLD,
|
||||
SDR_TYPE_MSAA_RESOLVE,
|
||||
|
||||
SDR_TYPE_POST_PROCESS_SMAA_EDGE,
|
||||
@@ -237,6 +238,10 @@ enum shader_type {
|
||||
#define SDR_FLAG_VOLUMETRICS_DO_EDGE_SMOOTHING (1<<0)
|
||||
#define SDR_FLAG_VOLUMETRICS_NOISE (1<<1)
|
||||
|
||||
#define SDR_FLAG_COPY_FROM_ARRAY (1 << 0)
|
||||
|
||||
#define SDR_FLAG_TONEMAPPING_LINEAR_OUT (1 << 0)
|
||||
|
||||
|
||||
enum class uniform_block_type {
|
||||
Lights = 0,
|
||||
@@ -697,6 +702,8 @@ typedef struct screen {
|
||||
// switch onscreen, offscreen
|
||||
std::function<void()> gf_flip;
|
||||
|
||||
std::function<void()> gf_setup_frame;
|
||||
|
||||
// sets the clipping region
|
||||
std::function<void(int x, int y, int w, int h, int resize_mode)> gf_set_clip;
|
||||
|
||||
@@ -912,6 +919,14 @@ typedef struct screen {
|
||||
std::function<void(int x, int y, int width, int height)> gf_set_viewport;
|
||||
|
||||
std::function<void(bool set_override)> gf_override_fog;
|
||||
|
||||
//OpenXR functions
|
||||
std::function<SCP_vector<const char*>()> gf_openxr_get_extensions;
|
||||
std::function<bool()> gf_openxr_test_capabilities;
|
||||
std::function<bool()> gf_openxr_create_session;
|
||||
std::function<int64_t(const SCP_vector<int64_t>&)> gf_openxr_get_swapchain_format;
|
||||
std::function<bool()> gf_openxr_acquire_swapchain_buffers;
|
||||
std::function<bool()> gf_openxr_flip;
|
||||
} screen;
|
||||
|
||||
// handy macro
|
||||
@@ -966,6 +981,7 @@ extern screen gr_screen;
|
||||
#define GR_RESIZE_MENU 3
|
||||
#define GR_RESIZE_MENU_ZOOMED 4
|
||||
#define GR_RESIZE_MENU_NO_OFFSET 5
|
||||
#define GR_RESIZE_REPLACE 6
|
||||
|
||||
void gr_set_screen_scale(int x, int y, int zoom_x = -1, int zoom_y = -1, int max_x = gr_screen.max_w, int max_y = gr_screen.max_h, int center_x = gr_screen.center_w, int center_y = gr_screen.center_h, bool force_stretch = false);
|
||||
void gr_reset_screen_scale();
|
||||
@@ -1011,6 +1027,10 @@ extern void gr_activate(int active);
|
||||
//#define gr_flip GR_CALL(gr_screen.gf_flip)
|
||||
void gr_flip(bool execute_scripting = true);
|
||||
|
||||
inline void gr_setup_frame() {
|
||||
gr_screen.gf_setup_frame();
|
||||
}
|
||||
|
||||
//#define gr_set_clip GR_CALL(gr_screen.gf_set_clip)
|
||||
inline void gr_set_clip(int x, int y, int w, int h, int resize_mode=GR_RESIZE_FULL)
|
||||
{
|
||||
@@ -1272,6 +1292,14 @@ inline void gr_sync_delete(gr_sync sync)
|
||||
gr_screen.gf_sync_delete(sync);
|
||||
}
|
||||
|
||||
//OpenXR
|
||||
#define gr_openxr_get_extensions GR_CALL(gr_screen.gf_openxr_get_extensions)
|
||||
#define gr_openxr_test_capabilities GR_CALL(gr_screen.gf_openxr_test_capabilities)
|
||||
#define gr_openxr_create_session GR_CALL(gr_screen.gf_openxr_create_session)
|
||||
#define gr_openxr_get_swapchain_format GR_CALL(gr_screen.gf_openxr_get_swapchain_format)
|
||||
#define gr_openxr_acquire_swapchain_buffers GR_CALL(gr_screen.gf_openxr_acquire_swapchain_buffers)
|
||||
#define gr_openxr_flip GR_CALL(gr_screen.gf_openxr_flip)
|
||||
|
||||
// color functions
|
||||
void gr_init_color(color *c, int r, int g, int b);
|
||||
void gr_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type = AC_TYPE_HUD );
|
||||
|
||||
@@ -734,7 +734,7 @@ void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool m
|
||||
}
|
||||
}
|
||||
|
||||
void generic_anim_render_ex(generic_anim* ga, float frametime, int x, int y, int w, int h, bool menu, const generic_extras* ge)
|
||||
void generic_anim_bitmap_set(generic_anim* ga, float frametime, const generic_extras* ge)
|
||||
{
|
||||
if ((ge != nullptr) && (ga->use_hud_color == true)) {
|
||||
Warning(LOCATION, "Monochrome generic anims can't use extra info (yet)");
|
||||
@@ -752,23 +752,8 @@ void generic_anim_render_ex(generic_anim* ga, float frametime, int x, int y, int
|
||||
generic_anim_render_fixed_frame_delay(ga, frametime, a);
|
||||
}
|
||||
|
||||
if (ga->num_frames > 0) {
|
||||
if (ga->num_frames > 0)
|
||||
ga->previous_frame = ga->current_frame;
|
||||
|
||||
if (ga->use_hud_color) {
|
||||
gr_aabitmap_ex(x, y, w, h, 0, 0, (menu ? GR_RESIZE_MENU : GR_RESIZE_FULL));
|
||||
}
|
||||
else {
|
||||
if (ge == nullptr) {
|
||||
gr_bitmap_ex(x, y, w, h, 0, 0, (menu ? GR_RESIZE_MENU : GR_RESIZE_FULL));
|
||||
}
|
||||
else if (ge->draw == true) {
|
||||
// currently only for lua streaminganim objects
|
||||
// and don't draw them unless requested...
|
||||
gr_bitmap_uv(x, y, w, h, ge->u0, ge->v0, ge->u1, ge->v1, ge->resize_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -91,6 +91,6 @@ int generic_anim_stream(generic_anim *ga, const bool cache = true);
|
||||
int generic_bitmap_load(generic_bitmap *gb);
|
||||
void generic_anim_unload(generic_anim *ga);
|
||||
void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool menu = false, const generic_extras *ge = nullptr);
|
||||
void generic_anim_render_ex(generic_anim* ga, float frametime, int x, int y, int w, int h, bool menu = false, const generic_extras* ge = nullptr);
|
||||
void generic_anim_bitmap_set(generic_anim* ga, float frametime, const generic_extras* ge = nullptr);
|
||||
void generic_anim_reset(generic_anim *ga);
|
||||
#endif
|
||||
@@ -18,6 +18,11 @@
|
||||
#include "bmpman/bm_internal.h"
|
||||
|
||||
|
||||
void gr_stub_setup_frame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint gr_stub_lock()
|
||||
{
|
||||
return 1;
|
||||
@@ -421,7 +426,37 @@ void gr_stub_delete_query_object(int /*obj*/)
|
||||
{
|
||||
}
|
||||
|
||||
bool gr_stub_init()
|
||||
SCP_vector<const char*> gr_stub_openxr_get_extensions()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool gr_stub_openxr_test_capabilities()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gr_stub_openxr_create_session()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t gr_stub_openxr_get_swapchain_format(const SCP_vector<int64_t>& /*allowed*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool gr_stub_openxr_acquire_swapchain_buffers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gr_stub_openxr_flip()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gr_stub_init()
|
||||
{
|
||||
if (gr_screen.res != GR_640) {
|
||||
gr_screen.res = GR_640;
|
||||
@@ -447,8 +482,13 @@ bool gr_stub_init()
|
||||
Gr_blue.mask = 0xff;
|
||||
Gr_t_blue = Gr_blue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void gr_stub_init_function_pointers() {
|
||||
// function pointers...
|
||||
gr_screen.gf_flip = gr_stub_flip;
|
||||
gr_screen.gf_setup_frame = gr_stub_setup_frame;
|
||||
gr_screen.gf_set_clip = gr_stub_set_clip;
|
||||
gr_screen.gf_reset_clip = gr_stub_reset_clip;
|
||||
|
||||
@@ -572,5 +612,10 @@ bool gr_stub_init()
|
||||
|
||||
gr_screen.gf_override_fog = [](bool /*b*/) {};
|
||||
|
||||
return true;
|
||||
gr_screen.gf_openxr_get_extensions = gr_stub_openxr_get_extensions;
|
||||
gr_screen.gf_openxr_test_capabilities = gr_stub_openxr_test_capabilities;
|
||||
gr_screen.gf_openxr_create_session = gr_stub_openxr_create_session;
|
||||
gr_screen.gf_openxr_get_swapchain_format = gr_stub_openxr_get_swapchain_format;
|
||||
gr_screen.gf_openxr_acquire_swapchain_buffers = gr_stub_openxr_acquire_swapchain_buffers;
|
||||
gr_screen.gf_openxr_flip = gr_stub_openxr_flip;
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
void gr_stub_init_function_pointers();
|
||||
bool gr_stub_init();
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "io/timer.h"
|
||||
#include "lighting/lighting.h"
|
||||
#include "lighting/lighting_profiles.h"
|
||||
#include "math/bitarray.h"
|
||||
@@ -43,6 +44,12 @@ struct gr_light
|
||||
int type;
|
||||
};
|
||||
|
||||
//FADEIN STUFF
|
||||
shader Viewer_shader;
|
||||
FadeType Fade_type = FadeType::FI_NONE;
|
||||
TIMESTAMP Fade_start_timestamp = TIMESTAMP::invalid();
|
||||
TIMESTAMP Fade_end_timestamp = TIMESTAMP::invalid();
|
||||
|
||||
// Variables
|
||||
SCP_vector<gr_light> gr_lights;
|
||||
graphics::model_light gr_light_uniforms[graphics::MAX_UNIFORM_LIGHTS];
|
||||
|
||||
@@ -5,6 +5,20 @@
|
||||
#include "lighting/lighting.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
|
||||
//-----Fadein stuff
|
||||
struct shader;
|
||||
extern shader Viewer_shader;
|
||||
|
||||
enum class FadeType {
|
||||
FI_NONE = 0,
|
||||
FI_FADEIN,
|
||||
FI_FADEOUT
|
||||
};
|
||||
extern FadeType Fade_type;
|
||||
extern TIMESTAMP Fade_start_timestamp;
|
||||
extern TIMESTAMP Fade_end_timestamp;
|
||||
|
||||
|
||||
//Variables
|
||||
extern int Num_active_gr_lights;
|
||||
|
||||
@@ -13,6 +27,7 @@ extern const float gr_light_zero[4];
|
||||
extern const float gr_light_emission[4];
|
||||
extern float gr_light_ambient[4];
|
||||
|
||||
|
||||
//Functions
|
||||
void gr_set_light(light *fs_light);
|
||||
void gr_reset_lighting();
|
||||
|
||||
@@ -6,11 +6,19 @@
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#if !defined __APPLE_CC__ && defined SCP_UNIX
|
||||
#include<glad/glad_glx.h>
|
||||
//Required because X defines none and always, which is used later
|
||||
#undef None
|
||||
#undef Always
|
||||
#endif
|
||||
|
||||
#include "gropengl.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "gropenglbmpman.h"
|
||||
#include "gropengldeferred.h"
|
||||
#include "gropengldraw.h"
|
||||
#include "gropenglopenxr.h"
|
||||
#include "gropenglpostprocessing.h"
|
||||
#include "gropenglquery.h"
|
||||
#include "gropenglshader.h"
|
||||
@@ -107,6 +115,18 @@ void gr_opengl_flip()
|
||||
if (!GL_initted)
|
||||
return;
|
||||
|
||||
if (Cmdline_window_res) {
|
||||
GL_state.BindFrameBuffer(0, GL_DRAW_FRAMEBUFFER);
|
||||
GL_state.BindFrameBuffer(Back_framebuffer, GL_READ_FRAMEBUFFER);
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glDrawBuffer(GL_BACK);
|
||||
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, Cmdline_window_res->first, Cmdline_window_res->second, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glDrawBuffer(GL_NONE);
|
||||
|
||||
GL_state.PopFramebufferState();
|
||||
}
|
||||
|
||||
if (Cmdline_gl_finish)
|
||||
glFinish();
|
||||
|
||||
@@ -123,6 +143,17 @@ void gr_opengl_flip()
|
||||
#endif
|
||||
}
|
||||
|
||||
void gr_opengl_setup_frame() {
|
||||
if (!GL_initted)
|
||||
return;
|
||||
|
||||
if (Cmdline_window_res) {
|
||||
GL_state.PushFramebufferState();
|
||||
GL_state.BindFrameBuffer(Back_framebuffer);
|
||||
glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
|
||||
}
|
||||
}
|
||||
|
||||
void gr_opengl_set_clip(int x, int y, int w, int h, int resize_mode)
|
||||
{
|
||||
// check for sanity of parameters
|
||||
@@ -134,7 +165,7 @@ void gr_opengl_set_clip(int x, int y, int w, int h, int resize_mode)
|
||||
y = 0;
|
||||
}
|
||||
|
||||
int to_resize = (resize_mode != GR_RESIZE_NONE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)));
|
||||
int to_resize = (resize_mode != GR_RESIZE_NONE && resize_mode != GR_RESIZE_REPLACE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)));
|
||||
|
||||
int max_w = ((to_resize) ? gr_screen.max_w_unscaled : gr_screen.max_w);
|
||||
int max_h = ((to_resize) ? gr_screen.max_h_unscaled : gr_screen.max_h);
|
||||
@@ -143,28 +174,30 @@ void gr_opengl_set_clip(int x, int y, int w, int h, int resize_mode)
|
||||
gr_unsize_screen_pos(&max_w, &max_h);
|
||||
}
|
||||
|
||||
if (x >= max_w) {
|
||||
x = max_w - 1;
|
||||
}
|
||||
if (resize_mode != GR_RESIZE_REPLACE) {
|
||||
if (x >= max_w) {
|
||||
x = max_w - 1;
|
||||
}
|
||||
|
||||
if (y >= max_h) {
|
||||
y = max_h - 1;
|
||||
}
|
||||
if (y >= max_h) {
|
||||
y = max_h - 1;
|
||||
}
|
||||
|
||||
if (x + w > max_w) {
|
||||
w = max_w - x;
|
||||
}
|
||||
if (x + w > max_w) {
|
||||
w = max_w - x;
|
||||
}
|
||||
|
||||
if (y + h > max_h) {
|
||||
h = max_h - y;
|
||||
}
|
||||
if (y + h > max_h) {
|
||||
h = max_h - y;
|
||||
}
|
||||
|
||||
if (w > max_w) {
|
||||
w = max_w;
|
||||
}
|
||||
if (w > max_w) {
|
||||
w = max_w;
|
||||
}
|
||||
|
||||
if (h > max_h) {
|
||||
h = max_h;
|
||||
if (h > max_h) {
|
||||
h = max_h;
|
||||
}
|
||||
}
|
||||
|
||||
gr_screen.offset_x_unscaled = x;
|
||||
@@ -901,9 +934,10 @@ int opengl_init_display_device()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void opengl_setup_function_pointers()
|
||||
void gr_opengl_init_function_pointers()
|
||||
{
|
||||
gr_screen.gf_flip = gr_opengl_flip;
|
||||
gr_screen.gf_setup_frame = gr_opengl_setup_frame;
|
||||
gr_screen.gf_set_clip = gr_opengl_set_clip;
|
||||
gr_screen.gf_reset_clip = gr_opengl_reset_clip;
|
||||
|
||||
@@ -1032,6 +1066,13 @@ void opengl_setup_function_pointers()
|
||||
|
||||
gr_screen.gf_override_fog = gr_opengl_override_fog;
|
||||
|
||||
gr_screen.gf_openxr_get_extensions = gr_opengl_openxr_get_extensions;
|
||||
gr_screen.gf_openxr_test_capabilities = gr_opengl_openxr_test_capabilities;
|
||||
gr_screen.gf_openxr_create_session = gr_opengl_openxr_create_session;
|
||||
gr_screen.gf_openxr_get_swapchain_format = gr_opengl_openxr_get_swapchain_format;
|
||||
gr_screen.gf_openxr_acquire_swapchain_buffers = gr_opengl_openxr_acquire_swapchain_buffers;
|
||||
gr_screen.gf_openxr_flip = gr_opengl_openxr_flip;
|
||||
|
||||
// NOTE: All function pointers here should have a Cmdline_nohtl check at the top
|
||||
// if they shouldn't be run in non-HTL mode, Don't keep separate entries.
|
||||
// *****************************************************************************
|
||||
@@ -1230,6 +1271,12 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
|
||||
Error(LOCATION, "Failed to load OpenGL!");
|
||||
}
|
||||
|
||||
#if !defined __APPLE_CC__ && defined SCP_UNIX
|
||||
if (!gladLoadGLXLoader(GL_context->getLoaderFunction(), nullptr, 0)) {
|
||||
Error(LOCATION, "Failed to load GLX!");
|
||||
}
|
||||
#endif
|
||||
|
||||
// version check
|
||||
GL_version = (GLVersion.major * 10) + GLVersion.minor;
|
||||
|
||||
@@ -1262,11 +1309,6 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// this MUST be done before any other gr_opengl_* or
|
||||
// opengl_* function calls!!
|
||||
opengl_setup_function_pointers();
|
||||
|
||||
mprintf(( " OpenGL Vendor : %s\n", glGetString(GL_VENDOR) ));
|
||||
mprintf(( " OpenGL Renderer : %s\n", glGetString(GL_RENDERER) ));
|
||||
mprintf(( " OpenGL Version : %s\n", glGetString(GL_VERSION) ));
|
||||
@@ -1346,11 +1388,15 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
|
||||
Gr_current_green = &Gr_green;
|
||||
Gr_current_alpha = &Gr_alpha;
|
||||
|
||||
|
||||
gr_setup_frame();
|
||||
gr_opengl_reset_clip();
|
||||
gr_opengl_clear();
|
||||
gr_opengl_flip();
|
||||
gr_setup_frame();
|
||||
gr_opengl_clear();
|
||||
gr_opengl_flip();
|
||||
gr_setup_frame();
|
||||
gr_opengl_clear();
|
||||
|
||||
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &GL_max_elements_vertices);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/grinternal.h"
|
||||
|
||||
void gr_opengl_init_function_pointers();
|
||||
bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps);
|
||||
void gr_opengl_cleanup(bool closing, int minimize=1);
|
||||
int opengl_check_for_errors(const char *err_at = NULL);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
|
||||
#include "gropengldeferred.h"
|
||||
#include "globalincs/vmallocator.h"
|
||||
|
||||
#include "ShaderProgram.h"
|
||||
#include "gropengldraw.h"
|
||||
@@ -170,11 +171,42 @@ void gr_opengl_deferred_lighting_end()
|
||||
GL_state.ColorMask(true, true, true, false);
|
||||
}
|
||||
|
||||
static GLuint deferred_light_cylinder_vbo = 0;
|
||||
static GLuint deferred_light_cylinder_ibo = 0;
|
||||
static GLushort deferred_light_cylinder_vcount = 0;
|
||||
static GLuint deferred_light_cylinder_icount = 0;
|
||||
|
||||
static GLuint deferred_light_sphere_vbo = 0;
|
||||
static GLuint deferred_light_sphere_ibo = 0;
|
||||
static GLushort deferred_light_sphere_vcount = 0;
|
||||
static GLuint deferred_light_sphere_icount = 0;
|
||||
|
||||
extern SCP_vector<light> Lights;
|
||||
extern int Num_lights;
|
||||
namespace ltp = lighting_profiles;
|
||||
using namespace ltp;
|
||||
static bool override_fog = false;
|
||||
graphics::deferred_light_data*
|
||||
|
||||
// common conversion operations to translate a game light data structure into a render-ready light uniform.
|
||||
prepare_light_uniforms(light& l, graphics::util::UniformAligner& uniformAligner)
|
||||
{
|
||||
graphics::deferred_light_data* light_data = uniformAligner.addTypedElement<graphics::deferred_light_data>();
|
||||
|
||||
light_data->lightType = static_cast<int>(l.type);
|
||||
|
||||
vec3d diffuse;
|
||||
diffuse.xyz.x = l.r * l.intensity;
|
||||
diffuse.xyz.y = l.g * l.intensity;
|
||||
diffuse.xyz.z = l.b * l.intensity;
|
||||
|
||||
light_data->diffuseLightColor = diffuse;
|
||||
|
||||
// Set a default value for all lights. Only the first directional light will change this.
|
||||
light_data->enable_shadows = false;
|
||||
light_data->sourceRadius = l.source_radius;
|
||||
return light_data;
|
||||
}
|
||||
|
||||
void gr_opengl_deferred_lighting_finish()
|
||||
{
|
||||
@@ -188,8 +220,8 @@ void gr_opengl_deferred_lighting_finish()
|
||||
GL_state.SetAlphaBlendMode(ALPHA_BLEND_ADDITIVE);
|
||||
gr_zbuffer_set(GR_ZBUFF_NONE);
|
||||
|
||||
//GL_state.DepthFunc(GL_GREATER);
|
||||
//GL_state.DepthMask(GL_FALSE);
|
||||
// GL_state.DepthFunc(GL_GREATER);
|
||||
// GL_state.DepthMask(GL_FALSE);
|
||||
|
||||
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_DEFERRED_LIGHTING, 0));
|
||||
|
||||
@@ -214,7 +246,7 @@ void gr_opengl_deferred_lighting_finish()
|
||||
if (Shadow_quality != ShadowQuality::Disabled) {
|
||||
GL_state.Texture.Enable(4, GL_TEXTURE_2D_ARRAY, Shadow_map_texture);
|
||||
}
|
||||
|
||||
|
||||
// We need to use stable sorting here to make sure that the relative ordering of the same light types is the same as
|
||||
// the rest of the code. Otherwise the shadow mapping would be applied while rendering the wrong light which would
|
||||
// lead to flickering lights in some circumstances
|
||||
@@ -225,19 +257,43 @@ void gr_opengl_deferred_lighting_finish()
|
||||
size_t num_data_elements = Lights.size();
|
||||
|
||||
// Get a uniform buffer for our data
|
||||
auto buffer = gr_get_uniform_buffer(uniform_block_type::Lights, num_data_elements);
|
||||
auto& uniformAligner = buffer.aligner();
|
||||
auto light_buffer = gr_get_uniform_buffer(uniform_block_type::Lights, num_data_elements);
|
||||
auto& light_uniform_aligner = light_buffer.aligner();
|
||||
auto matrix_buffer = gr_get_uniform_buffer(uniform_block_type::Matrices, num_data_elements);
|
||||
auto& matrix_uniform_aligner = matrix_buffer.aligner();
|
||||
|
||||
// This is the light which is responsible for shadows and volumetric nebula lighting
|
||||
const light* global_light = nullptr;
|
||||
vec3d global_light_diffuse;
|
||||
|
||||
// To allow reduced bind calls, we sort lights into subsets based on rendering methods.
|
||||
// It might seem optimal to create these subsets as lights are added, or some other method,
|
||||
// but this keeps the graphics implementation methods better contained and profiling currently
|
||||
// (dec 2023) shows negligable cost of doing it this way.
|
||||
SCP_vector<light> full_frame_lights = SCP_vector<light>();
|
||||
SCP_vector<light> sphere_lights = SCP_vector<light>();
|
||||
SCP_vector<light> cylinder_lights = SCP_vector<light>();
|
||||
for (auto& l : Lights) {
|
||||
switch (l.type) {
|
||||
case Light_Type::Directional:
|
||||
full_frame_lights.push_back(l);
|
||||
break;
|
||||
case Light_Type::Cone:
|
||||
FALLTHROUGH;
|
||||
case Light_Type::Point:
|
||||
sphere_lights.push_back(l);
|
||||
break;
|
||||
case Light_Type::Tube:
|
||||
cylinder_lights.push_back(l);
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
GR_DEBUG_SCOPE("Build buffer data");
|
||||
|
||||
auto lp = ltp::current();
|
||||
|
||||
auto header = uniformAligner.getHeader<deferred_global_data>();
|
||||
auto header = light_uniform_aligner.getHeader<deferred_global_data>();
|
||||
if (Shadow_quality != ShadowQuality::Disabled) {
|
||||
// Avoid this overhead when we are not going to use these values
|
||||
header->shadow_mv_matrix = Shadow_view_matrix_light;
|
||||
@@ -258,133 +314,178 @@ void gr_opengl_deferred_lighting_finish()
|
||||
|
||||
// Only the first directional light uses shaders so we need to know when we already saw that light
|
||||
bool first_directional = true;
|
||||
for (auto& l : Lights) {
|
||||
auto light_data = uniformAligner.addTypedElement<deferred_light_data>();
|
||||
|
||||
light_data->lightType = static_cast<int>(l.type);
|
||||
for (auto& l : full_frame_lights) {
|
||||
auto light_data = prepare_light_uniforms(l, light_uniform_aligner);
|
||||
if (Shadow_quality != ShadowQuality::Disabled) {
|
||||
light_data->enable_shadows = first_directional ? 1 : 0;
|
||||
}
|
||||
|
||||
vec3d diffuse;
|
||||
diffuse.xyz.x = l.r * l.intensity;
|
||||
diffuse.xyz.y = l.g * l.intensity;
|
||||
diffuse.xyz.z = l.b * l.intensity;
|
||||
// Global light direction should match shadow light direction
|
||||
if (first_directional) {
|
||||
global_light = &l;
|
||||
global_light_diffuse = light_data->diffuseLightColor;
|
||||
}
|
||||
|
||||
light_data->diffuseLightColor = diffuse;
|
||||
vec4 light_dir;
|
||||
light_dir.xyzw.x = -l.vec.xyz.x;
|
||||
light_dir.xyzw.y = -l.vec.xyz.y;
|
||||
light_dir.xyzw.z = -l.vec.xyz.z;
|
||||
light_dir.xyzw.w = 0.0f;
|
||||
vec4 view_dir;
|
||||
|
||||
// Set a default value for all lights. Only the first directional light will change this.
|
||||
light_data->enable_shadows = false;
|
||||
light_data->sourceRadius = l.source_radius;
|
||||
vm_vec_transform(&view_dir, &light_dir, &gr_view_matrix);
|
||||
|
||||
switch (l.type) {
|
||||
case Light_Type::Directional:
|
||||
if (Shadow_quality != ShadowQuality::Disabled) {
|
||||
light_data->enable_shadows = first_directional ? 1 : 0;
|
||||
}
|
||||
light_data->lightDir.xyz.x = view_dir.xyzw.x;
|
||||
light_data->lightDir.xyz.y = view_dir.xyzw.y;
|
||||
light_data->lightDir.xyz.z = view_dir.xyzw.z;
|
||||
|
||||
// Global light direction should match shadow light direction
|
||||
if (first_directional) {
|
||||
global_light = &l;
|
||||
global_light_diffuse = diffuse;
|
||||
}
|
||||
|
||||
vec4 light_dir;
|
||||
light_dir.xyzw.x = -l.vec.xyz.x;
|
||||
light_dir.xyzw.y = -l.vec.xyz.y;
|
||||
light_dir.xyzw.z = -l.vec.xyz.z;
|
||||
light_dir.xyzw.w = 0.0f;
|
||||
vec4 view_dir;
|
||||
first_directional = false;
|
||||
}
|
||||
for (auto& l : sphere_lights) {
|
||||
auto light_data = prepare_light_uniforms(l, light_uniform_aligner);
|
||||
|
||||
vm_vec_transform(&view_dir, &light_dir, &gr_view_matrix);
|
||||
|
||||
light_data->lightDir.xyz.x = view_dir.xyzw.x;
|
||||
light_data->lightDir.xyz.y = view_dir.xyzw.y;
|
||||
light_data->lightDir.xyz.z = view_dir.xyzw.z;
|
||||
|
||||
first_directional = false;
|
||||
break;
|
||||
case Light_Type::Cone:
|
||||
if (l.type == Light_Type::Cone) {
|
||||
light_data->dualCone = l.dual_cone ? 1.0f : 0.0f;
|
||||
light_data->coneAngle = l.cone_angle;
|
||||
light_data->coneInnerAngle = l.cone_inner_angle;
|
||||
light_data->coneDir = l.vec2;
|
||||
FALLTHROUGH;
|
||||
case Light_Type::Point: {
|
||||
float rad = (Lighting_mode == lighting_mode::COCKPIT) ? lp->cockpit_light_radius_modifier.handle(MAX(l.rada, l.radb)) : MAX(l.rada, l.radb);
|
||||
light_data->lightRadius = rad;
|
||||
//A small padding factor is added to guard against potentially clipping the edges of the light with facets of the volume mesh.
|
||||
light_data->scale.xyz.x = rad * 1.05f;
|
||||
light_data->scale.xyz.y = rad * 1.05f;
|
||||
light_data->scale.xyz.z = rad * 1.05f;
|
||||
break;
|
||||
}
|
||||
case Light_Type::Tube: {
|
||||
float rad = (Lighting_mode == lighting_mode::COCKPIT) ? lp->cockpit_light_radius_modifier.handle(l.radb) : l.radb;
|
||||
|
||||
light_data->lightRadius = rad;
|
||||
light_data->lightType = LT_TUBE;
|
||||
|
||||
vec3d a;
|
||||
vm_vec_sub(&a, &l.vec, &l.vec2);
|
||||
auto length = vm_vec_mag(&a);
|
||||
//Tube light volumes must be extended past the length of their requested light vector
|
||||
//to allow smooth fall-off from all angles. Since the light volume starts at the mesh
|
||||
//origin we must extend it here. Later the position will be adjusted as well.
|
||||
length += light_data->lightRadius * 2.0f;
|
||||
|
||||
//A small padding factor is added to guard against potentially clipping the edges of the light with facets of the volume mesh.
|
||||
light_data->scale.xyz.x = rad * 1.05f;
|
||||
light_data->scale.xyz.y = rad * 1.05f;
|
||||
light_data->scale.xyz.z = length;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
float rad = (Lighting_mode == lighting_mode::COCKPIT)
|
||||
? lp->cockpit_light_radius_modifier.handle(MAX(l.rada, l.radb))
|
||||
: MAX(l.rada, l.radb);
|
||||
light_data->lightRadius = rad;
|
||||
// A small padding factor is added to guard against potentially clipping the edges of the light with facets
|
||||
// of the volume mesh.
|
||||
light_data->scale.xyz.x = rad * 1.05f;
|
||||
light_data->scale.xyz.y = rad * 1.05f;
|
||||
light_data->scale.xyz.z = rad * 1.05f;
|
||||
}
|
||||
for (auto& l : cylinder_lights) {
|
||||
auto light_data = prepare_light_uniforms(l, light_uniform_aligner);
|
||||
float rad =
|
||||
(Lighting_mode == lighting_mode::COCKPIT) ? lp->cockpit_light_radius_modifier.handle(l.radb) : l.radb;
|
||||
|
||||
light_data->lightRadius = rad;
|
||||
light_data->lightType = LT_TUBE;
|
||||
|
||||
vec3d a;
|
||||
vm_vec_sub(&a, &l.vec, &l.vec2);
|
||||
auto length = vm_vec_mag(&a);
|
||||
// Tube light volumes must be extended past the length of their requested light vector
|
||||
// to allow smooth fall-off from all angles. Since the light volume starts at the mesh
|
||||
// origin we must extend it here. Later the position will be adjusted as well.
|
||||
length += light_data->lightRadius * 2.0f;
|
||||
|
||||
// A small padding factor is added to guard against potentially clipping the edges of the light with facets
|
||||
// of the volume mesh.
|
||||
light_data->scale.xyz.x = rad * 1.05f;
|
||||
light_data->scale.xyz.y = rad * 1.05f;
|
||||
light_data->scale.xyz.z = length;
|
||||
}
|
||||
// Uniform data has been assembled, upload it to the GPU and issue the draw calls
|
||||
buffer.submitData();
|
||||
light_buffer.submitData();
|
||||
}
|
||||
{
|
||||
for (size_t i = 0; i<full_frame_lights.size(); i++) {
|
||||
// just keeping things aligned really.
|
||||
matrix_uniform_aligner.addTypedElement<graphics::matrix_uniforms>();
|
||||
}
|
||||
for (auto& l : sphere_lights) {
|
||||
auto matrix_data = matrix_uniform_aligner.addTypedElement<graphics::matrix_uniforms>();
|
||||
g3_start_instance_matrix(&l.vec, &vmd_identity_matrix, true);
|
||||
matrix_data->modelViewMatrix = gr_model_view_matrix;
|
||||
matrix_data->projMatrix = gr_projection_matrix;
|
||||
g3_done_instance(true);
|
||||
}
|
||||
for (auto& l : cylinder_lights ) {
|
||||
auto matrix_data = matrix_uniform_aligner.addTypedElement<graphics::matrix_uniforms>();
|
||||
vec3d dir, newPos;
|
||||
matrix orient;
|
||||
vm_vec_sub(&dir, &l.vec, &l.vec2);
|
||||
vm_vector_2_matrix(&orient, &dir, nullptr, nullptr);
|
||||
// Tube light volumes must be extended past the length of their requested light vector
|
||||
// to allow smooth fall-off from all angles. Since the light volume starts at the mesh
|
||||
// origin we must extend it, which has been done above, and then move it backwards one radius.
|
||||
vm_vec_normalize(&dir);
|
||||
vm_vec_scale_sub(&newPos, &l.vec2, &dir, l.radb);
|
||||
|
||||
g3_start_instance_matrix(&newPos, &orient, true);
|
||||
matrix_data->modelViewMatrix = gr_model_view_matrix;
|
||||
matrix_data->projMatrix = gr_projection_matrix;
|
||||
g3_done_instance(true);
|
||||
}
|
||||
matrix_buffer.submitData();
|
||||
}
|
||||
{
|
||||
GR_DEBUG_SCOPE("Render light geometry");
|
||||
gr_bind_uniform_buffer(uniform_block_type::DeferredGlobals, buffer.getBufferOffset(0),
|
||||
sizeof(graphics::deferred_global_data), buffer.bufferHandle());
|
||||
gr_bind_uniform_buffer(uniform_block_type::DeferredGlobals,
|
||||
light_buffer.getBufferOffset(0),
|
||||
sizeof(graphics::deferred_global_data),
|
||||
light_buffer.bufferHandle());
|
||||
gr_bind_uniform_buffer(uniform_block_type::Matrices,
|
||||
matrix_buffer.getBufferOffset(0),
|
||||
sizeof(graphics::matrix_uniforms),
|
||||
matrix_buffer.bufferHandle());
|
||||
|
||||
size_t element_index = 0;
|
||||
for (auto& l : Lights) {
|
||||
GR_DEBUG_SCOPE("Deferred apply single light");
|
||||
vertex_layout vertex_declare;
|
||||
vertex_declare.add_vertex_component(vertex_format_data::POSITION3, sizeof(float) * 3, 0);
|
||||
|
||||
switch (l.type) {
|
||||
case Light_Type::Directional:
|
||||
gr_bind_uniform_buffer(uniform_block_type::Lights, buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::deferred_light_data), buffer.bufferHandle());
|
||||
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
++element_index;
|
||||
break;
|
||||
case Light_Type::Cone:
|
||||
case Light_Type::Point:
|
||||
gr_bind_uniform_buffer(uniform_block_type::Lights, buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::deferred_light_data), buffer.bufferHandle());
|
||||
gr_opengl_draw_deferred_light_sphere(&l.vec);
|
||||
++element_index;
|
||||
break;
|
||||
case Light_Type::Tube:
|
||||
gr_bind_uniform_buffer(uniform_block_type::Lights, buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::deferred_light_data), buffer.bufferHandle());
|
||||
for (size_t i = 0; i<full_frame_lights.size(); i++) {
|
||||
GR_DEBUG_SCOPE("Deferred apply single dir light");
|
||||
|
||||
vec3d dir, newPos;
|
||||
matrix orient;
|
||||
vm_vec_sub(&dir, &l.vec, &l.vec2);
|
||||
vm_vector_2_matrix(&orient, &dir, nullptr, nullptr);
|
||||
//Tube light volumes must be extended past the length of their requested light vector
|
||||
//to allow smooth fall-off from all angles. Since the light volume starts at the mesh
|
||||
//origin we must extend it, which has been done above, and then move it backwards one radius.
|
||||
vm_vec_normalize(&dir);
|
||||
vm_vec_scale_sub(&newPos, &l.vec2, &dir, l.radb);
|
||||
gr_opengl_draw_deferred_light_cylinder(&newPos, &orient);
|
||||
++element_index;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
gr_bind_uniform_buffer(uniform_block_type::Lights,
|
||||
light_buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::deferred_light_data),
|
||||
light_buffer.bufferHandle());
|
||||
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
++element_index;
|
||||
}
|
||||
if (!sphere_lights.empty()) {
|
||||
opengl_bind_vertex_layout(vertex_declare, deferred_light_sphere_vbo, deferred_light_sphere_ibo);
|
||||
}
|
||||
for (size_t i = 0; i<sphere_lights.size(); i++) {
|
||||
|
||||
gr_bind_uniform_buffer(uniform_block_type::Lights,
|
||||
light_buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::deferred_light_data),
|
||||
light_buffer.bufferHandle());
|
||||
gr_bind_uniform_buffer(uniform_block_type::Matrices,
|
||||
matrix_buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::matrix_uniforms),
|
||||
matrix_buffer.bufferHandle());
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES,
|
||||
0,
|
||||
deferred_light_sphere_vcount,
|
||||
deferred_light_sphere_icount,
|
||||
GL_UNSIGNED_SHORT,
|
||||
0);
|
||||
opengl_draw_sphere();
|
||||
++element_index;
|
||||
}
|
||||
if (!cylinder_lights.empty()) {
|
||||
opengl_bind_vertex_layout(vertex_declare, deferred_light_cylinder_vbo, deferred_light_cylinder_ibo);
|
||||
}
|
||||
for (size_t i = 0; i<cylinder_lights.size(); i++) {
|
||||
gr_bind_uniform_buffer(uniform_block_type::Lights,
|
||||
light_buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::deferred_light_data),
|
||||
light_buffer.bufferHandle());
|
||||
gr_bind_uniform_buffer(uniform_block_type::Matrices,
|
||||
matrix_buffer.getAlignerElementOffset(element_index),
|
||||
sizeof(graphics::matrix_uniforms),
|
||||
matrix_buffer.bufferHandle());
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES,
|
||||
0,
|
||||
deferred_light_cylinder_vcount,
|
||||
deferred_light_cylinder_icount,
|
||||
GL_UNSIGNED_SHORT,
|
||||
0);
|
||||
|
||||
++element_index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,11 +636,6 @@ void gr_opengl_draw_deferred_light_sphere(const vec3d *position)
|
||||
}
|
||||
|
||||
|
||||
static GLuint deferred_light_cylinder_vbo = 0;
|
||||
static GLuint deferred_light_cylinder_ibo = 0;
|
||||
static GLushort deferred_light_cylinder_vcount = 0;
|
||||
static GLuint deferred_light_cylinder_icount = 0;
|
||||
|
||||
void gr_opengl_deferred_light_cylinder_init(int segments) // Generate a VBO of a cylinder of radius and height 1.0f, based on code at http://www.ogre3d.org/tikiwiki/ManualSphereMeshes
|
||||
{
|
||||
unsigned int nVertex = (segments + 1) * 2 * 3 + 6; // Can someone verify this?
|
||||
@@ -656,11 +752,6 @@ void gr_opengl_deferred_light_cylinder_init(int segments) // Generate a VBO of a
|
||||
Vertices = nullptr;
|
||||
}
|
||||
|
||||
static GLuint deferred_light_sphere_vbo = 0;
|
||||
static GLuint deferred_light_sphere_ibo = 0;
|
||||
static GLushort deferred_light_sphere_vcount = 0;
|
||||
static GLuint deferred_light_sphere_icount = 0;
|
||||
|
||||
void gr_opengl_deferred_light_sphere_init(int rings, int segments) // Generate a VBO of a sphere of radius 1.0f, based on code at http://www.ogre3d.org/tikiwiki/ManualSphereMeshes
|
||||
{
|
||||
unsigned int nVertex = (rings + 1) * (segments+1) * 3;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/util/UniformAligner.h"
|
||||
#include "graphics/util/uniform_structs.h"
|
||||
#include "lighting/lighting.h"
|
||||
|
||||
void gr_opengl_deferred_init();
|
||||
|
||||
@@ -9,6 +12,7 @@ void gr_opengl_deferred_lighting_begin(bool clearNonColorBufs = false);
|
||||
void gr_opengl_deferred_lighting_msaa();
|
||||
void gr_opengl_deferred_lighting_end();
|
||||
void gr_opengl_deferred_lighting_finish();
|
||||
graphics::deferred_light_data* prepare_light_uniforms(light& l, graphics::util::UniformAligner& uniformAligner);
|
||||
|
||||
void gr_opengl_deferred_light_sphere_init(int rings, int segments);
|
||||
void gr_opengl_deferred_light_cylinder_init(int segments);
|
||||
|
||||
@@ -50,6 +50,10 @@ GLuint Scene_depth_texture_ms;
|
||||
GLuint Cockpit_depth_texture;
|
||||
GLuint Scene_stencil_buffer;
|
||||
|
||||
GLuint Back_framebuffer;
|
||||
GLuint Back_texture;
|
||||
GLuint Back_depth_texture;
|
||||
|
||||
GLuint Distortion_framebuffer = 0;
|
||||
GLuint Distortion_texture[2];
|
||||
int Distortion_switch = 0;
|
||||
@@ -525,6 +529,53 @@ void opengl_setup_scene_textures()
|
||||
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
if (Cmdline_window_res) {
|
||||
//Gen Framebuffer
|
||||
glGenFramebuffers(1, &Back_framebuffer);
|
||||
GL_state.BindFrameBuffer(Back_framebuffer);
|
||||
opengl_set_object_label(GL_FRAMEBUFFER, Back_framebuffer, "Backbuffer");
|
||||
|
||||
// setup main render texture
|
||||
|
||||
// setup high dynamic range color texture
|
||||
glGenTextures(1, &Back_texture);
|
||||
|
||||
GL_state.Texture.SetActiveUnit(0);
|
||||
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
||||
GL_state.Texture.Enable(Back_texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, gr_screen.max_w, gr_screen.max_h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Back_texture, 0);
|
||||
opengl_set_object_label(GL_TEXTURE, Back_texture, "Backbuffer texture");
|
||||
|
||||
glGenTextures(1, &Back_depth_texture);
|
||||
|
||||
GL_state.Texture.SetActiveUnit(0);
|
||||
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
||||
GL_state.Texture.Enable(Back_depth_texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, gr_screen.max_w, gr_screen.max_h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
opengl_set_object_label(GL_TEXTURE, Back_depth_texture, "Backbuffer depth texture");
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, Back_depth_texture, 0);
|
||||
gr_zbuffer_set(GR_ZBUFF_FULL);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
//Setup thruster distortion framebuffer
|
||||
if (Gr_framebuffer_effects.any_set())
|
||||
{
|
||||
|
||||
@@ -38,6 +38,9 @@ extern GLuint Scene_depth_texture_ms;
|
||||
extern GLuint Cockpit_depth_texture;
|
||||
extern GLuint Scene_stencil_buffer;
|
||||
|
||||
extern GLuint Back_framebuffer;
|
||||
extern GLuint Back_texture;
|
||||
|
||||
void gr_opengl_update_distortion();
|
||||
|
||||
void gr_opengl_sphere(material *material_def, float rad);
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
#include "gropenglopenxr.h"
|
||||
|
||||
#include "io/cursor.h"
|
||||
#include "io/mouse.h"
|
||||
#include "graphics/matrix.h"
|
||||
#include "graphics/opengl/gropengl.h"
|
||||
#include "graphics/opengl/gropengldraw.h"
|
||||
#include "graphics/opengl/gropenglshader.h"
|
||||
#include "graphics/opengl/gropenglstate.h"
|
||||
#include "graphics/opengl/ShaderProgram.h"
|
||||
#include "osapi/osapi.h"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#define XR_USE_PLATFORM_WIN32
|
||||
#include <unknwn.h>
|
||||
|
||||
#elif defined __APPLE_CC__
|
||||
|
||||
//Not supported
|
||||
|
||||
#elif defined SCP_UNIX
|
||||
|
||||
#define XR_USE_PLATFORM_XLIB
|
||||
#include<X11/Xlib.h>
|
||||
#include<glad/glad_glx.h>
|
||||
|
||||
#endif
|
||||
|
||||
#define XR_USE_GRAPHICS_API_OPENGL
|
||||
#include "graphics/openxr_internal.h"
|
||||
|
||||
#include <SDL_syswm.h>
|
||||
|
||||
#ifndef __APPLE_CC__
|
||||
|
||||
//SETUP FUNCTIONS OGL
|
||||
SCP_vector<const char*> gr_opengl_openxr_get_extensions() {
|
||||
return { XR_KHR_OPENGL_ENABLE_EXTENSION_NAME };
|
||||
}
|
||||
|
||||
|
||||
bool gr_opengl_openxr_test_capabilities() {
|
||||
XrGraphicsRequirementsOpenGLKHR requirements{
|
||||
XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR,
|
||||
nullptr,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
if (openxr_callExtensionFunction<PFN_xrGetOpenGLGraphicsRequirementsKHR>("xrGetOpenGLGraphicsRequirementsKHR", xr_instance, xr_system, &requirements) != XR_SUCCESS) {
|
||||
mprintf(("Failed to query OpenXR graphics requirements!\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requirements.minApiVersionSupported > XR_MAKE_VERSION(GLVersion.major, GLVersion.minor, 0)) {
|
||||
mprintf(("System doesn't meet OpenXR graphics requirements (min %" PRIu64 ", available %" PRIu64 ")!\n", requirements.minApiVersionSupported, static_cast<XrVersion>(XR_MAKE_VERSION(GLVersion.major, GLVersion.minor, 0))));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
bool gr_opengl_openxr_create_session() {
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
SDL_GetWindowWMInfo(os::getSDLMainWindow(), &wmInfo);
|
||||
|
||||
XrGraphicsBindingOpenGLWin32KHR graphicsBinding{
|
||||
XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
|
||||
nullptr,
|
||||
wmInfo.info.win.hdc,
|
||||
(HGLRC) SDL_GL_GetCurrentContext() //uuuuuugly, and not technically allowed by the standard, but this "opaque" SDL_GLContext type is just the hGLRC on Win32
|
||||
};
|
||||
|
||||
XrSessionCreateInfo sessionCreateInfo{
|
||||
XR_TYPE_SESSION_CREATE_INFO,
|
||||
&graphicsBinding,
|
||||
0,
|
||||
xr_system
|
||||
};
|
||||
|
||||
XrResult sessionInit = xrCreateSession(xr_instance, &sessionCreateInfo, &xr_session);
|
||||
if (sessionInit != XR_SUCCESS) {
|
||||
mprintf(("Failed to create OpenXR session with code %d\n", static_cast<int>(sessionInit)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#elif defined SCP_UNIX
|
||||
bool gr_opengl_openxr_create_session() {
|
||||
SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
SDL_GetWindowWMInfo(os::getSDLMainWindow(), &wmInfo);
|
||||
|
||||
XWindowAttributes wa;
|
||||
XGetWindowAttributes(wmInfo.info.x11.display, wmInfo.info.x11.window, &wa);
|
||||
|
||||
GLXContext glxcontext = (GLXContext) SDL_GL_GetCurrentContext(); //uuuuuugly, and not technically allowed by the standard, but this "opaque" SDL_GLContext type is just the GLXContext on X11
|
||||
|
||||
int glxfbconfigid, glxscreenid, nfbconfigs;
|
||||
glXQueryContext(wmInfo.info.x11.display, glxcontext, GLX_FBCONFIG_ID, &glxfbconfigid);
|
||||
glXQueryContext(wmInfo.info.x11.display, glxcontext, GLX_SCREEN, &glxscreenid);
|
||||
|
||||
const int fbconfigattrs[] = {GLX_FBCONFIG_ID, glxfbconfigid, None};
|
||||
GLXFBConfig* fbconfigs = glXChooseFBConfig(wmInfo.info.x11.display, glxscreenid, fbconfigattrs, &nfbconfigs);
|
||||
|
||||
if (nfbconfigs < 1) {
|
||||
mprintf(("Unable to find Linux FBConfig for OpenXR!\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
XrGraphicsBindingOpenGLXlibKHR graphicsBinding {
|
||||
XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR,
|
||||
nullptr,
|
||||
wmInfo.info.x11.display,
|
||||
static_cast<uint32_t>(XVisualIDFromVisual(wa.visual)),
|
||||
fbconfigs[0],
|
||||
glXGetCurrentDrawable(),
|
||||
glxcontext
|
||||
};
|
||||
|
||||
XrSessionCreateInfo sessionCreateInfo {
|
||||
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO,
|
||||
sessionCreateInfo.next = &graphicsBinding,
|
||||
sessionCreateInfo.createFlags = 0,
|
||||
sessionCreateInfo.systemId = xr_system
|
||||
};
|
||||
|
||||
XrResult sessionInit = xrCreateSession(xr_instance, &sessionCreateInfo, &xr_session);
|
||||
if (sessionInit != XR_SUCCESS) {
|
||||
mprintf(("Failed to create OpenXR session with code %d\n", static_cast<int>(sessionInit)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
int64_t gr_opengl_openxr_get_swapchain_format(const SCP_vector<int64_t>& allowed) {
|
||||
//We prefer whatever our backbuffer is
|
||||
if (std::find(allowed.cbegin(), allowed.cend(), GL_RGBA16F) != allowed.cend())
|
||||
return GL_RGBA16F;
|
||||
|
||||
//Otherwise, Fallback
|
||||
return allowed.front();
|
||||
}
|
||||
|
||||
//PIPELINE FUNCTIONS OGL
|
||||
std::array<SCP_vector<XrSwapchainImageOpenGLKHR>, 2> swapchainImages;
|
||||
|
||||
GLuint xr_fbo;
|
||||
GLuint xr_swap_tex;
|
||||
|
||||
bool gr_opengl_openxr_acquire_swapchain_buffers() {
|
||||
// create framebuffer
|
||||
glGenFramebuffers(1, &xr_fbo);
|
||||
GL_state.BindFrameBuffer(xr_fbo);
|
||||
opengl_set_object_label(GL_FRAMEBUFFER, xr_fbo, "XR Swapchain");
|
||||
|
||||
//While blitting from the backbuffer is fine for the 3d-scenes, when we render a flat scene, we need to bind the backbuffer as a texture.
|
||||
//Since that doesn't work, we need an intermediary. Not pretty, but it doesn't need to be for the flat scenes
|
||||
glGenTextures(1, &xr_swap_tex);
|
||||
|
||||
GL_state.Texture.SetActiveUnit(0);
|
||||
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
|
||||
GL_state.Texture.Enable(xr_swap_tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, gr_screen.max_w, gr_screen.max_h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, xr_swap_tex, 0);
|
||||
opengl_set_object_label(GL_TEXTURE, xr_swap_tex, "XR Swap Texture");
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
uint32_t imageCount = 0;
|
||||
|
||||
XrResult swapchainAcq = xrEnumerateSwapchainImages(xr_swapchains[i]->swapchain, 0, &imageCount, nullptr);
|
||||
if (swapchainAcq != XR_SUCCESS) {
|
||||
mprintf(("Failed to acquire OpenXR swapchain %d with code %d\n", i, static_cast<int>(swapchainAcq)));
|
||||
return false;
|
||||
}
|
||||
|
||||
swapchainImages[i] = SCP_vector<XrSwapchainImageOpenGLKHR>(imageCount, { XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR, nullptr, 0 });
|
||||
|
||||
swapchainAcq = xrEnumerateSwapchainImages(xr_swapchains[i]->swapchain, imageCount, &imageCount, (XrSwapchainImageBaseHeader*)swapchainImages[i].data());
|
||||
if (swapchainAcq != XR_SUCCESS) {
|
||||
mprintf(("Failed to acquire OpenXR swapchain %d with code %d\n", i, static_cast<int>(swapchainAcq)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gr_opengl_openxr_flip() {
|
||||
if (!openxr_enabled())
|
||||
return false;
|
||||
|
||||
static bool was_multiframe = false;
|
||||
|
||||
//If a stereoscopic frame has started, we're good. Otherwise, this is a normal frame that still needs to be OpenXR-Initialized
|
||||
//In addition, since we don't actually blit one backbuffer per eye in monoframe mode, we need to make a copy of it to a readable texture now.
|
||||
if (xr_stage == OpenXRFBStage::NONE) {
|
||||
openxr_start_frame();
|
||||
|
||||
GR_DEBUG_SCOPE("XR Blit");
|
||||
|
||||
GL_state.PushFramebufferState();
|
||||
GL_state.BindFrameBuffer(Cmdline_window_res ? Back_framebuffer : 0, GL_READ_FRAMEBUFFER);
|
||||
GL_state.BindFrameBuffer(xr_fbo, GL_DRAW_FRAMEBUFFER);
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, xr_swap_tex, 0);
|
||||
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_BACK);
|
||||
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, gr_screen.max_w, gr_screen.max_h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glDrawBuffer(GL_NONE);
|
||||
|
||||
GL_state.PopFramebufferState();
|
||||
|
||||
if (was_multiframe) {
|
||||
openxr_reset_offset();
|
||||
was_multiframe = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
was_multiframe = true;
|
||||
|
||||
uint32_t startFrame = xr_stage == OpenXRFBStage::SECOND ? 1 : 0;
|
||||
uint32_t endFrame = xr_stage == OpenXRFBStage::FIRST ? 1 : 2;
|
||||
|
||||
for (uint32_t i = startFrame; i < endFrame; i++) {
|
||||
XrSwapchain swapchain = xr_swapchains[i]->swapchain;
|
||||
|
||||
XrSwapchainImageAcquireInfo acquireImageInfo {
|
||||
XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO,
|
||||
nullptr
|
||||
};
|
||||
uint32_t activeIndex;
|
||||
xrAcquireSwapchainImage(swapchain, &acquireImageInfo, &activeIndex);
|
||||
|
||||
XrSwapchainImageWaitInfo waitImageInfo{
|
||||
waitImageInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO,
|
||||
nullptr,
|
||||
waitImageInfo.timeout = std::numeric_limits<int64_t>::max()
|
||||
};
|
||||
xrWaitSwapchainImage(swapchain, &waitImageInfo);
|
||||
|
||||
const XrSwapchainImageOpenGLKHR& image = swapchainImages[i][activeIndex];
|
||||
|
||||
//Monoframe mode: We only have one image that FSO just tried to flip. We have it in a readable texture which we'll now render as a flat plane in a fake 3D scene directly to the swapchain
|
||||
if (xr_stage == OpenXRFBStage::NONE) {
|
||||
GR_DEBUG_SCOPE("XR Plane");
|
||||
|
||||
GL_state.PushFramebufferState();
|
||||
GL_state.BindFrameBuffer(xr_fbo);
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, image.image, 0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
GL_state.Texture.Enable(0, GL_TEXTURE_2D, xr_swap_tex);
|
||||
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_COPY_WORLD, 0));
|
||||
Current_shader->program->Uniforms.setTextureUniform("tex", 0);
|
||||
|
||||
const auto& pos = xr_views[i].pose.position;
|
||||
const auto& ori = xr_views[i].pose.orientation;
|
||||
vec3d position{{ { pos.x, pos.y, -pos.z } }};
|
||||
position -= xr_offset;
|
||||
matrix orientation;
|
||||
vm_quaternion_to_matrix(&orientation, ori.x, ori.y, -ori.z, -ori.w);
|
||||
|
||||
gr_set_clip(0, 0, xr_swapchains[i]->width, xr_swapchains[i]->height, GR_RESIZE_REPLACE);
|
||||
gr_set_proj_matrix(asymmetric_fov {
|
||||
xr_views[i].fov.angleLeft,
|
||||
xr_views[i].fov.angleRight,
|
||||
xr_views[i].fov.angleUp,
|
||||
xr_views[i].fov.angleDown
|
||||
}, i2fl(xr_swapchains[i]->width) / i2fl(xr_swapchains[i]->height), 0.01f, 1000);
|
||||
gr_set_view_matrix(&position, &orientation);
|
||||
|
||||
glViewport(0, 0, xr_swapchains[i]->width, xr_swapchains[i]->height);
|
||||
GL_state.ScissorTest(GL_FALSE);
|
||||
GL_state.SetZbufferType(gr_zbuffer_type::ZBUFFER_TYPE_NONE);
|
||||
|
||||
GLfloat v[4][5] = {
|
||||
{
|
||||
-2.0f * gr_screen.clip_aspect, -2.0f, 4, 0, 0
|
||||
},
|
||||
{
|
||||
2.0f * gr_screen.clip_aspect, -2.0f, 4, 1, 0
|
||||
},
|
||||
{
|
||||
2.0f * gr_screen.clip_aspect, 2.0f, 4, 1, 1
|
||||
},
|
||||
{
|
||||
-2.0f * gr_screen.clip_aspect, 2.0f, 4, 0, 1
|
||||
}
|
||||
};
|
||||
|
||||
vertex_layout vert_def;
|
||||
vert_def.add_vertex_component(vertex_format_data::POSITION3, sizeof(GLfloat) * 5, 0);
|
||||
vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(GLfloat) * 5, sizeof(GLfloat) * 3);
|
||||
|
||||
gr_matrix_set_uniforms();
|
||||
gr_set_clear_color(20, 20, 20);
|
||||
gr_clear();
|
||||
gr_set_clear_color(0, 0, 0);
|
||||
opengl_render_primitives_immediate(PRIM_TYPE_TRIFAN, &vert_def, 4, v, sizeof(v));
|
||||
|
||||
//And if we have a curser, it also needs to be put onscreen manually
|
||||
if (io::mouse::CursorManager::get()->isCursorShown()) {
|
||||
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_COPY_WORLD, SDR_FLAG_COPY_FROM_ARRAY));
|
||||
Current_shader->program->Uniforms.setTextureUniform("tex", 0);
|
||||
|
||||
float u_scale, v_scale;
|
||||
uint32_t array_index;
|
||||
int mouse_bm = io::mouse::CursorManager::get()->getCurrentCursor()->getBitmapHandle();
|
||||
int mousex, mousey, mousew, mouseh;
|
||||
|
||||
bm_get_info(mouse_bm, &mousew, &mouseh);
|
||||
gr_opengl_tcache_set(mouse_bm, TCACHE_TYPE_INTERFACE, &u_scale, &v_scale, &array_index);
|
||||
|
||||
mouse_get_pos(&mousex, &mousey);
|
||||
float mouse_unscaled_x = i2fl(mousex) / i2fl(gr_screen.max_w) * 2.0f - 1.0f;
|
||||
float mouse_unscaled_y = i2fl(mousey) / i2fl(gr_screen.max_h) * -2.0f + 1.0f;
|
||||
float mouse_unscaled_w = i2fl(mousew) / i2fl(gr_screen.max_w);
|
||||
float mouse_unscaled_h = i2fl(mouseh) / i2fl(gr_screen.max_h);
|
||||
|
||||
float left = 2.0f * gr_screen.clip_aspect * mouse_unscaled_x;
|
||||
float right = left + 4.0f * gr_screen.clip_aspect * mouse_unscaled_w;
|
||||
float top = 2.0f * mouse_unscaled_y;
|
||||
float bottom = top - 4.0f * mouse_unscaled_h;
|
||||
|
||||
GLfloat vmouse[4][5] = {
|
||||
{
|
||||
left, bottom, 4, 0, 1
|
||||
},
|
||||
{
|
||||
right, bottom, 4, 1, 1
|
||||
},
|
||||
{
|
||||
right, top, 4, 1, 0
|
||||
},
|
||||
{
|
||||
left, top, 4, 0, 0
|
||||
}
|
||||
};
|
||||
opengl_render_primitives_immediate(PRIM_TYPE_TRIFAN, &vert_def, 4, vmouse, sizeof(vmouse));
|
||||
}
|
||||
|
||||
gr_end_proj_matrix();
|
||||
gr_end_view_matrix();
|
||||
gr_reset_clip();
|
||||
glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
|
||||
|
||||
GL_state.Texture.Enable(0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
|
||||
GL_state.PopFramebufferState();
|
||||
}
|
||||
//If we are in stereo mode, we just need to take the current backbuffer and blit it to the proper swapchain target
|
||||
else {
|
||||
GR_DEBUG_SCOPE("XR Blit");
|
||||
|
||||
GL_state.PushFramebufferState();
|
||||
GL_state.BindFrameBuffer(Cmdline_window_res ? Back_framebuffer : 0, GL_READ_FRAMEBUFFER);
|
||||
GL_state.BindFrameBuffer(xr_fbo, GL_DRAW_FRAMEBUFFER);
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, image.image, 0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_BACK);
|
||||
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, xr_swapchains[i]->width, xr_swapchains[i]->height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
|
||||
GL_state.PopFramebufferState();
|
||||
}
|
||||
|
||||
XrSwapchainImageReleaseInfo releaseImageInfo {
|
||||
XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO,
|
||||
nullptr
|
||||
};
|
||||
|
||||
xrReleaseSwapchainImage(swapchain, &releaseImageInfo);
|
||||
}
|
||||
|
||||
switch (xr_stage) {
|
||||
case OpenXRFBStage::FIRST:
|
||||
//We just rendered the first part of a stereo image. We now need to follow up with another one for the other eye
|
||||
xr_stage = OpenXRFBStage::SECOND;
|
||||
return true;
|
||||
case OpenXRFBStage::SECOND:
|
||||
case OpenXRFBStage::NONE:
|
||||
//We just rendered the second part of a stereo image or a mono image. Barring further instruction, the next image may be mono again.
|
||||
//Also, since that means we're done with whatever we just rendered, finish this frame
|
||||
xr_stage = OpenXRFBStage::NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
XrCompositionLayerProjectionView projectedViews[2];
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
projectedViews[i].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
||||
projectedViews[i].next = nullptr;
|
||||
projectedViews[i].pose = xr_views[i].pose;
|
||||
projectedViews[i].fov = xr_views[i].fov;
|
||||
projectedViews[i].subImage = {
|
||||
xr_swapchains[i]->swapchain,
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ (int32_t)xr_swapchains[i]->width, (int32_t)xr_swapchains[i]->height }
|
||||
},
|
||||
0
|
||||
};
|
||||
}
|
||||
|
||||
XrCompositionLayerProjection layer {
|
||||
XR_TYPE_COMPOSITION_LAYER_PROJECTION,
|
||||
nullptr,
|
||||
0,
|
||||
xr_space,
|
||||
2,
|
||||
projectedViews
|
||||
};
|
||||
auto pLayer = (const XrCompositionLayerBaseHeader*)&layer;
|
||||
|
||||
XrFrameEndInfo frameEndInfo {
|
||||
XR_TYPE_FRAME_END_INFO,
|
||||
nullptr,
|
||||
xr_state.predictedDisplayTime,
|
||||
XR_ENVIRONMENT_BLEND_MODE_OPAQUE,
|
||||
0,
|
||||
nullptr
|
||||
};
|
||||
|
||||
if (xr_state.shouldRender) {
|
||||
frameEndInfo.layerCount = 1;
|
||||
frameEndInfo.layers = &pLayer;
|
||||
}
|
||||
|
||||
xrEndFrame(xr_session, &frameEndInfo);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
//Stubs for Mac, as linking with OpenXR causes issues there.
|
||||
|
||||
SCP_vector<const char*> gr_opengl_openxr_get_extensions() { return SCP_vector<const char*>{}; }
|
||||
|
||||
bool gr_opengl_openxr_test_capabilities() { return false; }
|
||||
|
||||
bool gr_opengl_openxr_create_session() { return false; }
|
||||
|
||||
int64_t gr_opengl_openxr_get_swapchain_format(const SCP_vector<int64_t>& allowed) { return 0; }
|
||||
|
||||
bool gr_opengl_openxr_acquire_swapchain_buffers() { return false; }
|
||||
|
||||
bool gr_opengl_openxr_flip() { return false; }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
SCP_vector<const char*> gr_opengl_openxr_get_extensions();
|
||||
bool gr_opengl_openxr_test_capabilities();
|
||||
bool gr_opengl_openxr_create_session();
|
||||
int64_t gr_opengl_openxr_get_swapchain_format(const SCP_vector<int64_t>& allowed);
|
||||
bool gr_opengl_openxr_acquire_swapchain_buffers();
|
||||
bool gr_opengl_openxr_flip();
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "def_files/def_files.h"
|
||||
#include "graphics/grinternal.h"
|
||||
#include "graphics/openxr.h"
|
||||
#include "graphics/util/uniform_structs.h"
|
||||
#include "io/timer.h"
|
||||
#include "lighting/lighting.h"
|
||||
@@ -66,7 +67,7 @@ void opengl_post_pass_tonemap()
|
||||
GR_DEBUG_SCOPE("Tonemapping");
|
||||
TRACE_SCOPE(tracing::Tonemapping);
|
||||
|
||||
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_TONEMAPPING, 0));
|
||||
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_TONEMAPPING, openxr_enabled() ? SDR_FLAG_TONEMAPPING_LINEAR_OUT : 0));
|
||||
|
||||
Current_shader->program->Uniforms.setTextureUniform("tex", 0);
|
||||
|
||||
|
||||
@@ -155,6 +155,9 @@ static opengl_shader_type_t GL_shader_types[] = {
|
||||
{ SDR_TYPE_COPY, "post-v.sdr", "copy-f.sdr", nullptr,
|
||||
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "Texture copy", false },
|
||||
|
||||
{ SDR_TYPE_COPY_WORLD, "passthrough-v.sdr", "copy-f.sdr", nullptr,
|
||||
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "Texture copy world space", false },
|
||||
|
||||
{ SDR_TYPE_MSAA_RESOLVE, "post-v.sdr", "msaa-f.sdr", nullptr,
|
||||
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "MSAA resolve shader", false },
|
||||
|
||||
@@ -207,7 +210,11 @@ static opengl_shader_variant_t GL_shader_variants[] = {
|
||||
|
||||
{SDR_TYPE_VOLUMETRIC_FOG, false, SDR_FLAG_VOLUMETRICS_DO_EDGE_SMOOTHING, "DO_EDGE_SMOOTHING", {}, "Perform costly edge smoothing lookups"},
|
||||
|
||||
{SDR_TYPE_VOLUMETRIC_FOG, false, SDR_FLAG_VOLUMETRICS_NOISE, "NOISE", {}, "Add noise to volumetrics"}
|
||||
{SDR_TYPE_VOLUMETRIC_FOG, false, SDR_FLAG_VOLUMETRICS_NOISE, "NOISE", {}, "Add noise to volumetrics"},
|
||||
|
||||
{SDR_TYPE_COPY_WORLD, false, SDR_FLAG_COPY_FROM_ARRAY, "COPY_ARRAY", {}, "Expects to copy from an array texture"},
|
||||
|
||||
{SDR_TYPE_POST_PROCESS_TONEMAPPING, false, SDR_FLAG_TONEMAPPING_LINEAR_OUT, "LINEAR_OUT", {}, "Will make the tonemapper output in linear color space and not in sRGB"}
|
||||
};
|
||||
|
||||
static const int GL_num_shader_variants = sizeof(GL_shader_variants) / sizeof(opengl_shader_variant_t);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#define BMPMAN_INTERNAL
|
||||
#include "gropenglstate.h"
|
||||
#include "gropengltexture.h"
|
||||
#include "gropengldraw.h"
|
||||
#include "bmpman/bm_internal.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
@@ -1704,8 +1705,13 @@ int opengl_set_render_target( int slot, int face, int is_static )
|
||||
}
|
||||
}
|
||||
|
||||
GL_state.BindFrameBuffer(0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
if(Cmdline_window_res) {
|
||||
GL_state.BindFrameBuffer(Back_framebuffer);
|
||||
}
|
||||
else {
|
||||
GL_state.BindFrameBuffer(0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
// done with this render target so lets move on
|
||||
render_target = NULL;
|
||||
|
||||
@@ -0,0 +1,548 @@
|
||||
#include "openxr_internal.h"
|
||||
|
||||
#include "camera/camera.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "globalincs/version.h"
|
||||
#include "mod_table/mod_table.h"
|
||||
#include "render/3d.h"
|
||||
#include "starfield/starfield.h"
|
||||
|
||||
std::unique_ptr<star[]> Stars_XRBuffer;
|
||||
|
||||
#ifndef __APPLE_CC__
|
||||
|
||||
#define XR_MAKE_VERSION_SHORT(major, minor, patch) \
|
||||
((((major) & 0x3ffU) << 20) | (((minor) & 0x3ffU) << 10) | ((patch) & 0x3ffU))
|
||||
|
||||
bool openxr_req = false;
|
||||
bool openxr_initialized = false;
|
||||
bool openxr_recieve = false;
|
||||
|
||||
XrInstance xr_instance;
|
||||
XrSystemId xr_system;
|
||||
XrSession xr_session;
|
||||
XrSpace xr_space;
|
||||
XrTime xr_time;
|
||||
XrDebugUtilsMessengerEXT xr_debugMessenger;
|
||||
std::array<std::unique_ptr<XrSwapchainHandler>, 2> xr_swapchains;
|
||||
std::array<XrView, 2> xr_views;
|
||||
std::array<XrViewConfigurationView, 2> xr_configurationviews;
|
||||
vec3d xr_offset = ZERO_VECTOR;
|
||||
XrFrameState xr_state;
|
||||
OpenXRFBStage xr_stage = OpenXRFBStage::NONE;
|
||||
float xr_scale = 1.0f;
|
||||
|
||||
#if !defined(NDEBUG) && defined(FS_OPENXR_DEBUG)
|
||||
static XrBool32 handleXRError(XrDebugUtilsMessageSeverityFlagsEXT severity, XrDebugUtilsMessageTypeFlagsEXT type, const XrDebugUtilsMessengerCallbackDataEXT* callbackData, void* /*userData*/) {
|
||||
SCP_string message;
|
||||
switch (type)
|
||||
{
|
||||
case XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT:
|
||||
message = "OpenXR: general\n%s";
|
||||
break;
|
||||
case XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT:
|
||||
message = "OpenXR: validation\n%s";
|
||||
break;
|
||||
case XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT:
|
||||
message = "OpenXR: performance\n%s";
|
||||
break;
|
||||
case XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT:
|
||||
message = "OpenXR: conformance\n%s";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (severity)
|
||||
{
|
||||
case XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
|
||||
case XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
|
||||
Information(LOCATION, message.c_str(), callbackData->message);
|
||||
break;
|
||||
case XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
|
||||
Warning(LOCATION, message.c_str(), callbackData->message);
|
||||
break;
|
||||
case XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
|
||||
Error(LOCATION, message.c_str(), callbackData->message);
|
||||
break;
|
||||
}
|
||||
|
||||
return XR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void openxr_prepare(float hudscale) {
|
||||
Hud_global_scale = hudscale;
|
||||
openxr_req = true;
|
||||
}
|
||||
|
||||
static bool openxr_init_instance() {
|
||||
auto extensions = gr_openxr_get_extensions();
|
||||
|
||||
const gameversion::version& fso_version = gameversion::get_executable_version();
|
||||
const gameversion::version& mod_version(Mod_version);
|
||||
|
||||
#if !defined(NDEBUG) && defined(FS_OPENXR_DEBUG)
|
||||
extensions.emplace_back("XR_EXT_debug_utils");
|
||||
#endif
|
||||
|
||||
XrInstanceCreateInfo instanceCreateInfo {
|
||||
XR_TYPE_INSTANCE_CREATE_INFO,
|
||||
nullptr,
|
||||
0,
|
||||
XrApplicationInfo {
|
||||
"", //Modname
|
||||
//Mod version. Should not contain negative numbers or only 0's.
|
||||
XR_MAKE_VERSION_SHORT(mod_version.major < 1 ? 1U : static_cast<uint32_t>(mod_version.major),
|
||||
mod_version.minor < 0 ? 0U : static_cast<uint32_t>(mod_version.minor),
|
||||
mod_version.build < 0 ? 0U : static_cast<uint32_t>(mod_version.build)),
|
||||
"FreeSpace Open",
|
||||
XR_MAKE_VERSION_SHORT(static_cast<uint32_t>(fso_version.major), static_cast<uint32_t>(fso_version.minor), static_cast<uint32_t>(fso_version.build)),
|
||||
XR_CURRENT_API_VERSION
|
||||
},
|
||||
0,
|
||||
nullptr,
|
||||
static_cast<uint32_t>(extensions.size()),
|
||||
extensions.data()
|
||||
};
|
||||
|
||||
strncpy_s(instanceCreateInfo.applicationInfo.applicationName, Mod_title.empty() ? "FreeSpace Open" : Mod_title.c_str(), XR_MAX_APPLICATION_NAME_SIZE);
|
||||
|
||||
XrResult create = xrCreateInstance(&instanceCreateInfo, &xr_instance);
|
||||
if (create != XR_SUCCESS) {
|
||||
if (create == XR_ERROR_EXTENSION_NOT_PRESENT) {
|
||||
//This is to be expected to be one of THE common issue cases, since not all OpenXR runtimes, notably WMR, don't supply the OpenGL extensions
|
||||
ReleaseWarning(LOCATION, "The OpenXR runtime does not support the required backend! Try to use a different OpenXR runtime.");
|
||||
}
|
||||
|
||||
mprintf(("Failed to create OpenXR instance with code %d\n", static_cast<int>(create)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) && defined(FS_OPENXR_DEBUG)
|
||||
XrDebugUtilsMessengerCreateInfoEXT debugMessengerCreateInfo {
|
||||
XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||
nullptr,
|
||||
XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||
XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT,
|
||||
(PFN_xrDebugUtilsMessengerCallbackEXT)(&handleXRError),
|
||||
nullptr
|
||||
};
|
||||
|
||||
openxr_callExtensionFunction<PFN_xrCreateDebugUtilsMessengerEXT>("xrCreateDebugUtilsMessengerEXT", xr_instance, &debugMessengerCreateInfo, &xr_debugMessenger);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool openxr_init_system() {
|
||||
XrSystemGetInfo systemGetInfo {
|
||||
XR_TYPE_SYSTEM_GET_INFO,
|
||||
nullptr,
|
||||
XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY
|
||||
};
|
||||
|
||||
XrResult systemInit = xrGetSystem(xr_instance, &systemGetInfo, &xr_system);
|
||||
if (systemInit != XR_SUCCESS) {
|
||||
mprintf(("Failed to create OpenXR system with code %d\n", static_cast<int>(systemInit)));
|
||||
xr_system = XR_NULL_SYSTEM_ID;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool openxr_init_configuration_views() {
|
||||
uint32_t configurationViewsCount = static_cast<uint32_t>(xr_configurationviews.size());
|
||||
for (auto& configView : xr_configurationviews)
|
||||
configView = { XR_TYPE_VIEW_CONFIGURATION_VIEW, nullptr, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
if (xrEnumerateViewConfigurationViews(xr_instance, xr_system, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, configurationViewsCount, &configurationViewsCount, xr_configurationviews.data()) != XR_SUCCESS) {
|
||||
mprintf(("Failed to find OpenXR configuration views for stereo displays!\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool openxr_init_swapchains() {
|
||||
uint32_t formatCount = 0;
|
||||
if (xrEnumerateSwapchainFormats(xr_session, 0, &formatCount, nullptr) != XR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SCP_vector<int64_t> formats(formatCount);
|
||||
if (xrEnumerateSwapchainFormats(xr_session, formatCount, &formatCount, formats.data()) != XR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t chosenFormat = gr_openxr_get_swapchain_format(formats);
|
||||
|
||||
std::array<XrSwapchain, 2> swapchains;
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
XrSwapchainCreateInfo swapchainCreateInfo {
|
||||
XR_TYPE_SWAPCHAIN_CREATE_INFO,
|
||||
nullptr,
|
||||
0,
|
||||
XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT,
|
||||
chosenFormat,
|
||||
1,
|
||||
xr_configurationviews[i].recommendedImageRectWidth,
|
||||
xr_configurationviews[i].recommendedImageRectHeight,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
};
|
||||
|
||||
XrResult swapchainInit = xrCreateSwapchain(xr_session, &swapchainCreateInfo, &swapchains[i]);
|
||||
if (swapchainInit != XR_SUCCESS) {
|
||||
mprintf(("Failed to create OpenXR swapchain %d with code %d\n", i, static_cast<int>(swapchainInit)));
|
||||
return false;
|
||||
}
|
||||
|
||||
xr_swapchains[i].reset(new XrSwapchainHandler {
|
||||
swapchains[i],
|
||||
chosenFormat,
|
||||
xr_configurationviews[i].recommendedImageRectWidth,
|
||||
xr_configurationviews[i].recommendedImageRectHeight
|
||||
});
|
||||
}
|
||||
|
||||
if (!gr_openxr_acquire_swapchain_buffers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool openxr_init_space() {
|
||||
XrReferenceSpaceCreateInfo spaceCreateInfo {
|
||||
XR_TYPE_REFERENCE_SPACE_CREATE_INFO,
|
||||
nullptr,
|
||||
XR_REFERENCE_SPACE_TYPE_LOCAL,
|
||||
XrPosef{ XrQuaternionf{ 0, 0, 0, 1 }, XrVector3f{ 0, 0, 0 } },
|
||||
};
|
||||
|
||||
if (xrCreateReferenceSpace(xr_session, &spaceCreateInfo, &xr_space) != XR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void openxr_init_post() {
|
||||
XrViewLocateInfo viewLocateInfo {
|
||||
XR_TYPE_VIEW_LOCATE_INFO,
|
||||
nullptr,
|
||||
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
|
||||
xr_time,
|
||||
xr_space
|
||||
};
|
||||
|
||||
XrViewState viewState {
|
||||
XR_TYPE_VIEW_STATE,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
xr_views.fill({ XR_TYPE_VIEW, nullptr, XrPosef{}, XrFovf{} });
|
||||
uint32_t views;
|
||||
xrLocateViews(
|
||||
xr_session,
|
||||
&viewLocateInfo,
|
||||
&viewState,
|
||||
2,
|
||||
&views,
|
||||
xr_views.data()
|
||||
);
|
||||
|
||||
openxr_reset_offset();
|
||||
|
||||
vec3d xr_offset_debug {{ {
|
||||
(xr_views[0].pose.position.x - xr_views[1].pose.position.x) * xr_scale,
|
||||
(xr_views[0].pose.position.y - xr_views[1].pose.position.y) * xr_scale,
|
||||
(xr_views[0].pose.position.z - xr_views[1].pose.position.z) * xr_scale} }};
|
||||
|
||||
mprintf(("OpenXR HMD data:\n\tLeft Res: %dx%d\n\tLeft FoV (l|r|t|b): %f, %f, %f, %f\n\tRight Res: %dx%d\n\tRight FoV (l|r|t|b): %f, %f, %f, %f\n\tIPD: %f\n",
|
||||
xr_swapchains[0]->width, xr_swapchains[0]->height,
|
||||
xr_views[0].fov.angleLeft, xr_views[0].fov.angleRight, xr_views[0].fov.angleUp, xr_views[0].fov.angleDown,
|
||||
xr_swapchains[1]->width, xr_swapchains[1]->height,
|
||||
xr_views[1].fov.angleLeft, xr_views[1].fov.angleRight, xr_views[1].fov.angleUp, xr_views[1].fov.angleDown,
|
||||
vm_vec_mag(&xr_offset_debug)));
|
||||
|
||||
VIEWER_ZOOM_DEFAULT = COCKPIT_ZOOM_DEFAULT = asymmetric_fov {
|
||||
xr_views[0].fov.angleLeft + xr_views[1].fov.angleLeft,
|
||||
xr_views[0].fov.angleRight + xr_views[1].fov.angleRight,
|
||||
xr_views[0].fov.angleUp + xr_views[1].fov.angleUp,
|
||||
xr_views[0].fov.angleDown + xr_views[1].fov.angleDown
|
||||
} * (1.0f / (2.0f * PROJ_FOV_FACTOR));
|
||||
}
|
||||
|
||||
float openxr_preinit(float req_ar, float scale) {
|
||||
xr_scale = scale;
|
||||
|
||||
mprintf(("Attempting to pre-initialize OpenXR...\n"));
|
||||
|
||||
if (!openxr_init_instance()) {
|
||||
openxr_req = false;
|
||||
return req_ar;
|
||||
}
|
||||
|
||||
if (!openxr_init_system()) {
|
||||
openxr_req = false;
|
||||
return req_ar;
|
||||
}
|
||||
|
||||
if (!openxr_init_configuration_views()) {
|
||||
openxr_req = false;
|
||||
return req_ar;
|
||||
}
|
||||
|
||||
return i2fl(xr_configurationviews[0].recommendedImageRectWidth) / i2fl(xr_configurationviews[0].recommendedImageRectHeight);
|
||||
}
|
||||
|
||||
void openxr_init() {
|
||||
if (!openxr_req)
|
||||
return;
|
||||
|
||||
mprintf(("Attempting to initialize OpenXR and get a session...\n"));
|
||||
|
||||
if (!gr_openxr_test_capabilities())
|
||||
return;
|
||||
|
||||
//Non OpenGL backends, like vulkan, may need to query certain extensions to be enabled here as well
|
||||
|
||||
if (!gr_openxr_create_session())
|
||||
return;
|
||||
|
||||
if (!openxr_init_swapchains())
|
||||
return;
|
||||
|
||||
if (!openxr_init_space())
|
||||
return;
|
||||
|
||||
openxr_initialized = true;
|
||||
|
||||
mprintf(("OpenXR initialized!\n"));
|
||||
|
||||
while (openxr_initialized && !openxr_recieve) {
|
||||
os_poll();
|
||||
}
|
||||
|
||||
mprintf(("OpenXR recieving!\n"));
|
||||
|
||||
openxr_init_post();
|
||||
}
|
||||
|
||||
void openxr_close() {
|
||||
xrDestroySpace(xr_space);
|
||||
for (auto& sc : xr_swapchains)
|
||||
sc.release();
|
||||
xrDestroySession(xr_session);
|
||||
|
||||
#if !defined(NDEBUG) && defined(FS_OPENXR_DEBUG)
|
||||
openxr_callExtensionFunction<PFN_xrDestroyDebugUtilsMessengerEXT>("xrDestroyDebugUtilsMessengerEXT", xr_debugMessenger);
|
||||
#endif
|
||||
|
||||
xrDestroyInstance(xr_instance);
|
||||
}
|
||||
|
||||
bool openxr_enabled() {
|
||||
return openxr_initialized && openxr_recieve;
|
||||
}
|
||||
|
||||
bool openxr_requested() {
|
||||
return openxr_req;
|
||||
}
|
||||
|
||||
void openxr_reset_offset() {
|
||||
xr_offset = ZERO_VECTOR;
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
const auto& pos = xr_views[i].pose.position;
|
||||
xr_offset += vec3d{ { {pos.x * xr_scale, pos.y * xr_scale, pos.z * -xr_scale} } };
|
||||
}
|
||||
xr_offset /= 2;
|
||||
}
|
||||
|
||||
void openxr_start_mission() {
|
||||
if (!openxr_initialized)
|
||||
return;
|
||||
|
||||
openxr_reset_offset();
|
||||
|
||||
if (!static_cast<bool>(Stars_XRBuffer))
|
||||
Stars_XRBuffer = make_unique<star[]>(MAX_STARS);
|
||||
|
||||
extern std::unique_ptr<star[]> Stars;
|
||||
std::copy(Stars.get(), Stars.get() + MAX_STARS, Stars_XRBuffer.get());
|
||||
}
|
||||
|
||||
void openxr_poll() {
|
||||
if (!openxr_initialized)
|
||||
return;
|
||||
|
||||
XrEventDataBuffer eventData{
|
||||
XR_TYPE_EVENT_DATA_BUFFER,
|
||||
nullptr,
|
||||
{0}
|
||||
};
|
||||
|
||||
XrResult result = xrPollEvent(xr_instance, &eventData);
|
||||
if (result == XR_EVENT_UNAVAILABLE) {
|
||||
//No event
|
||||
}
|
||||
else if (result != XR_SUCCESS) {
|
||||
openxr_initialized = false;
|
||||
openxr_close();
|
||||
}
|
||||
else {
|
||||
switch (eventData.type)
|
||||
{
|
||||
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
|
||||
openxr_initialized = false;
|
||||
openxr_close();
|
||||
break;
|
||||
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
|
||||
{
|
||||
auto event = (XrEventDataSessionStateChanged*)&eventData;
|
||||
|
||||
xr_time = event->time;
|
||||
|
||||
switch (event->state)
|
||||
{
|
||||
case XR_SESSION_STATE_IDLE:
|
||||
openxr_recieve = false;
|
||||
break;
|
||||
case XR_SESSION_STATE_READY:
|
||||
{
|
||||
XrSessionBeginInfo sessionBeginInfo{
|
||||
XR_TYPE_SESSION_BEGIN_INFO,
|
||||
nullptr,
|
||||
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO
|
||||
};
|
||||
|
||||
if (xrBeginSession(xr_session, &sessionBeginInfo) != XR_SUCCESS) {
|
||||
openxr_initialized = false;
|
||||
openxr_close();
|
||||
}
|
||||
}
|
||||
/*fallthrough*/
|
||||
case XR_SESSION_STATE_SYNCHRONIZED:
|
||||
case XR_SESSION_STATE_VISIBLE:
|
||||
case XR_SESSION_STATE_FOCUSED:
|
||||
openxr_recieve = true;
|
||||
break;
|
||||
case XR_SESSION_STATE_STOPPING:
|
||||
xrEndSession(xr_session);
|
||||
/*fallthrough*/
|
||||
case XR_SESSION_STATE_LOSS_PENDING:
|
||||
case XR_SESSION_STATE_EXITING:
|
||||
openxr_initialized = false;
|
||||
openxr_close();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpenXRTrackingInfo openxr_start_stereo_frame() {
|
||||
if (!openxr_initialized)
|
||||
return OpenXRTrackingInfo{};
|
||||
|
||||
xr_stage = OpenXRFBStage::FIRST;
|
||||
|
||||
openxr_start_frame();
|
||||
|
||||
OpenXRTrackingInfo info{};
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
const auto& pos = xr_views[i].pose.position;
|
||||
const auto& ori = xr_views[i].pose.orientation;
|
||||
info.eyes[i].offset = vec3d{{ {pos.x * xr_scale, pos.y * xr_scale, pos.z * -xr_scale} }} - xr_offset;
|
||||
vm_quaternion_to_matrix(&info.eyes[i].orientation, ori.x, ori.y, -ori.z, -ori.w);
|
||||
info.eyes[i].zoom = asymmetric_fov{ xr_views[i].fov.angleLeft, xr_views[i].fov.angleRight, xr_views[i].fov.angleUp, xr_views[i].fov.angleDown } * (1.0f / PROJ_FOV_FACTOR);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
//Internal Helper functions
|
||||
|
||||
void openxr_start_frame() {
|
||||
XrFrameWaitInfo frameWaitInfo {
|
||||
XR_TYPE_FRAME_WAIT_INFO,
|
||||
nullptr
|
||||
};
|
||||
xr_state = XrFrameState {
|
||||
XR_TYPE_FRAME_STATE,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
xrWaitFrame(xr_session, &frameWaitInfo, &xr_state);
|
||||
|
||||
XrViewLocateInfo viewLocateInfo {
|
||||
XR_TYPE_VIEW_LOCATE_INFO,
|
||||
nullptr,
|
||||
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
|
||||
xr_state.predictedDisplayTime,
|
||||
xr_space
|
||||
};
|
||||
|
||||
xr_time = xr_state.predictedDisplayTime;
|
||||
|
||||
XrViewState viewState {
|
||||
XR_TYPE_VIEW_STATE,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
xr_views.fill({ XR_TYPE_VIEW, nullptr, XrPosef{}, XrFovf{} });
|
||||
|
||||
uint32_t views;
|
||||
xrLocateViews(
|
||||
xr_session,
|
||||
&viewLocateInfo,
|
||||
&viewState,
|
||||
2,
|
||||
&views,
|
||||
xr_views.data()
|
||||
);
|
||||
|
||||
XrFrameBeginInfo beginFrameInfo{ XR_TYPE_FRAME_BEGIN_INFO, nullptr };
|
||||
xrBeginFrame(xr_session, &beginFrameInfo);
|
||||
}
|
||||
|
||||
#else
|
||||
//Stubs for Mac, as linking with OpenXR causes issues there.
|
||||
|
||||
void openxr_prepare(float hudscale) {}
|
||||
|
||||
float openxr_preinit(float req_ar, float scale) {
|
||||
mprintf(("Cannot create OpenXR session on macOS.\n"));
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void openxr_init() {}
|
||||
|
||||
void openxr_close() {}
|
||||
|
||||
void openxr_poll() {}
|
||||
|
||||
void openxr_start_mission() {}
|
||||
|
||||
bool openxr_enabled() { return false; }
|
||||
|
||||
bool openxr_requested() { return false; }
|
||||
|
||||
OpenXRTrackingInfo openxr_start_stereo_frame() { return OpenXRTrackingInfo{}; }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "camera/camera.h"
|
||||
|
||||
struct OpenXRTrackingInfo {
|
||||
struct OpenXREyeInfo {
|
||||
vec3d offset;
|
||||
matrix orientation;
|
||||
fov_t zoom; //zoom, not fov! difference of a factor of PROJ_FOV_FACTOR
|
||||
};
|
||||
std::array<OpenXREyeInfo, 2> eyes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Performs required Setup actions for OpenXR before actually trying to initialize the graphics
|
||||
* @param hudscale Sets the scale at which the HUD is rendered. May need to be tweakable to make the hud visible to players with small FoV
|
||||
*/
|
||||
void openxr_prepare(float hudscale = 0.5f);
|
||||
|
||||
/**
|
||||
* @brief Initializes the OpenXR API and opens the XR system
|
||||
* @param req_ar The aspect ratio as specified by the user resolution
|
||||
* @param scale Controls the scale of the OpenXR coordinates. This mainly affects eye distance and how far real movement translates to ingame movement
|
||||
* @returns the expected aspect ratio of the swapchain
|
||||
*/
|
||||
float openxr_preinit(float req_ar, float scale = 1.0f);
|
||||
|
||||
/**
|
||||
* @brief Opens an OpenXR session to the point that we can render. As this waits for OpenXR, this may take a while
|
||||
*/
|
||||
void openxr_init();
|
||||
|
||||
/**
|
||||
* @brief Shuts down OpenXR and cleans up memory
|
||||
*/
|
||||
void openxr_close();
|
||||
|
||||
/**
|
||||
* @brief Polls OpenXR state. Does NOT poll HMD position!
|
||||
*/
|
||||
void openxr_poll();
|
||||
|
||||
/**
|
||||
* @brief Grabs the last known HMD position and sets it as the zero-state (whereever the specified eyepoint is in mission / ship), as well as initializing buffers for the mission
|
||||
*/
|
||||
void openxr_start_mission();
|
||||
|
||||
/**
|
||||
* @brief Polls whether OpenXR is active and can render
|
||||
*/
|
||||
bool openxr_enabled();
|
||||
|
||||
/**
|
||||
* @brief Polls whether OpenXR is requested to start. Required if you need to poll for OpenXR during some initialization where it might not yet be running
|
||||
*/
|
||||
bool openxr_requested();
|
||||
|
||||
/**
|
||||
* @brief Polls HMD position and sets up the OpenXR state machine to wait for and accept two frames, one for each eye.
|
||||
* You must ensure that after calling this, the next two gr_flip() calls correspond to the frames for each eye!
|
||||
* @returns The HMD tracking data including position and rotation in FSO coordinates.
|
||||
*/
|
||||
OpenXRTrackingInfo openxr_start_stereo_frame();
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
//Don't include this file unless you know what you are doing and need to _directly_ interface with OpenXR
|
||||
|
||||
#include "openxr.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <tl/optional.hpp>
|
||||
|
||||
#ifndef __APPLE_CC__
|
||||
|
||||
#include <openxr/openxr.h>
|
||||
#include <openxr/openxr_platform.h>
|
||||
|
||||
struct XrSwapchainHandler {
|
||||
XrSwapchain swapchain;
|
||||
int64_t format;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
~XrSwapchainHandler() {
|
||||
xrDestroySwapchain(swapchain);
|
||||
}
|
||||
};
|
||||
|
||||
extern bool openxr_initialized; //is true if initialization was successfull. Does NOT imply that we can render right now!
|
||||
extern XrInstance xr_instance;
|
||||
extern XrSystemId xr_system;
|
||||
extern XrSession xr_session;
|
||||
extern XrSpace xr_space;
|
||||
extern XrTime xr_time; //The last known time something happened. May be the last state change or the (predicted) time of the last frame
|
||||
extern std::array<std::unique_ptr<XrSwapchainHandler>, 2> xr_swapchains;
|
||||
extern std::array<XrView, 2> xr_views;
|
||||
extern XrFrameState xr_state;
|
||||
extern vec3d xr_offset;
|
||||
|
||||
enum class OpenXRFBStage { NONE, FIRST, SECOND };
|
||||
extern OpenXRFBStage xr_stage; //State machine tracker for rendering. Needed since OpenXR needs to be able to tell whether this is a stereoscopic frame or not whenever the code flips
|
||||
|
||||
void openxr_start_frame();
|
||||
void openxr_reset_offset();
|
||||
|
||||
template<typename openxr_fnc, typename... arg_t>
|
||||
tl::optional<typename std::result_of<openxr_fnc(arg_t...)>::type> openxr_callExtensionFunction(const char* const name, arg_t&&... args) {
|
||||
openxr_fnc func;
|
||||
|
||||
if (xrGetInstanceProcAddr(xr_instance, name, (PFN_xrVoidFunction*)&func) != XR_SUCCESS) {
|
||||
return tl::nullopt;
|
||||
}
|
||||
|
||||
return func(std::forward<arg_t>(args)...);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -344,12 +344,7 @@ namespace
|
||||
stuff_string(lang_name, F_NAME, LCL_LANG_NAME_LEN + 1);
|
||||
|
||||
// find language and set the index, or if not found move to the next one
|
||||
for (auto i = 0; i < (int)Lcl_languages.size(); ++i) {
|
||||
if (!strcmp(Lcl_languages[i].lang_name, lang_name)) {
|
||||
lang_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lang_idx = lcl_find_lang_index_by_name(lang_name);
|
||||
|
||||
if (lang_idx == -1) {
|
||||
Warning(LOCATION, "Ignoring invalid language (%s) specified by font (%s); not built-in or in strings.tbl",
|
||||
|
||||
@@ -89,7 +89,7 @@ void convert_model_material(model_uniform_data* data_out,
|
||||
if (material.is_alpha_mult_active())
|
||||
data_out->flags |= MODEL_SDR_FLAG_ALPHA_MULT;
|
||||
|
||||
if (material.get_animated_effect() > 0) {
|
||||
if (material.get_animated_effect() >= 0) {
|
||||
data_out->anim_timer = material.get_animated_effect_time();
|
||||
data_out->effect_num = material.get_animated_effect();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ namespace {
|
||||
std::unique_ptr<VulkanRenderer> renderer_instance;
|
||||
}
|
||||
|
||||
void initialize_function_pointers() {
|
||||
init_stub_pointers();
|
||||
}
|
||||
|
||||
bool initialize(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
|
||||
{
|
||||
renderer_instance.reset(new VulkanRenderer(std::move(graphicsOps)));
|
||||
@@ -22,8 +26,6 @@ bool initialize(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
|
||||
return false;
|
||||
}
|
||||
|
||||
init_stub_pointers();
|
||||
|
||||
gr_screen.gf_flip = []() {
|
||||
renderer_instance->flip();
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace vulkan {
|
||||
|
||||
class VulkanRenderer;
|
||||
|
||||
void initialize_function_pointers();
|
||||
bool initialize(std::unique_ptr<os::GraphicsOperations>&& graphicsOps);
|
||||
|
||||
VulkanRenderer* getRendererInstance();
|
||||
|
||||
@@ -15,6 +15,8 @@ gr_buffer_handle stub_create_buffer(BufferType, BufferUsageHint)
|
||||
return gr_buffer_handle::invalid();
|
||||
}
|
||||
|
||||
void stub_setup_frame() {}
|
||||
|
||||
void stub_delete_buffer(gr_buffer_handle /*handle*/) {}
|
||||
|
||||
int stub_preload(int /*bitmap_num*/, int /*is_aabitmap*/) { return 0; }
|
||||
@@ -232,11 +234,24 @@ std::uint64_t stub_get_query_value(int /*obj*/) { return 0; }
|
||||
|
||||
void stub_delete_query_object(int /*obj*/) {}
|
||||
|
||||
SCP_vector<const char*> stub_openxr_get_extensions() { return {}; }
|
||||
|
||||
bool stub_openxr_test_capabilities() { return false; }
|
||||
|
||||
bool stub_openxr_create_session() { return false; }
|
||||
|
||||
int64_t stub_openxr_get_swapchain_format(const SCP_vector<int64_t>& /*allowed*/) { return 0; }
|
||||
|
||||
bool stub_openxr_acquire_swapchain_buffers() { return false; }
|
||||
|
||||
bool stub_openxr_flip() { return false; }
|
||||
|
||||
} // namespace
|
||||
|
||||
void init_stub_pointers()
|
||||
{
|
||||
// function pointers...
|
||||
gr_screen.gf_setup_frame = stub_setup_frame;
|
||||
gr_screen.gf_set_clip = stub_set_clip;
|
||||
gr_screen.gf_reset_clip = stub_reset_clip;
|
||||
|
||||
@@ -353,6 +368,13 @@ void init_stub_pointers()
|
||||
gr_screen.gf_sync_delete = [](gr_sync /*sync*/) {};
|
||||
|
||||
gr_screen.gf_set_viewport = [](int /*x*/, int /*y*/, int /*width*/, int /*height*/) {};
|
||||
|
||||
gr_screen.gf_openxr_get_extensions = stub_openxr_get_extensions;
|
||||
gr_screen.gf_openxr_test_capabilities = stub_openxr_test_capabilities;
|
||||
gr_screen.gf_openxr_create_session = stub_openxr_create_session;
|
||||
gr_screen.gf_openxr_get_swapchain_format = stub_openxr_get_swapchain_format;
|
||||
gr_screen.gf_openxr_acquire_swapchain_buffers = stub_openxr_acquire_swapchain_buffers;
|
||||
gr_screen.gf_openxr_flip = stub_openxr_flip;
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
+14
-7
@@ -15,6 +15,7 @@
|
||||
#include "freespace.h"
|
||||
#include "gamesnd/eventmusic.h"
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "graphics/openxr.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "hud/hud.h"
|
||||
@@ -1178,9 +1179,9 @@ bool HudGauge::canRender()
|
||||
if (render_for_cockpit_toggle > 0) {
|
||||
if ((Viewer_mode & VM_CHASE) && (render_for_cockpit_toggle == 2)) {
|
||||
return true;
|
||||
} else if (cockpitActive && (render_for_cockpit_toggle == 2)) {
|
||||
} else if (Cockpit_active && (render_for_cockpit_toggle == 2)) {
|
||||
return false;
|
||||
} else if (!cockpitActive && (render_for_cockpit_toggle == 1)) {
|
||||
} else if (!Cockpit_active && (render_for_cockpit_toggle == 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1865,6 +1866,9 @@ void hud_render_gauges(int cockpit_display_num)
|
||||
}
|
||||
}
|
||||
|
||||
//Since we render things twice in VR mode, frametime needs to be halved for HUD, as the HUD uses the frametime to advance ANI's and crucially, the missile lock...
|
||||
float frametime = openxr_enabled() ? flFrametime * 0.5f : flFrametime;
|
||||
|
||||
// Check if this ship has its own HUD gauges.
|
||||
if ( sip->hud_enabled ) {
|
||||
num_gauges = sip->hud_gauges.size();
|
||||
@@ -1877,7 +1881,7 @@ void hud_render_gauges(int cockpit_display_num)
|
||||
sip->hud_gauges[j]->preprocess();
|
||||
}
|
||||
|
||||
sip->hud_gauges[j]->onFrame(flFrametime);
|
||||
sip->hud_gauges[j]->onFrame(frametime);
|
||||
|
||||
if ( !sip->hud_gauges[j]->setupRenderCanvas(render_target) ) {
|
||||
continue;
|
||||
@@ -1891,7 +1895,7 @@ void hud_render_gauges(int cockpit_display_num)
|
||||
|
||||
sip->hud_gauges[j]->resetClip();
|
||||
sip->hud_gauges[j]->setFont();
|
||||
sip->hud_gauges[j]->render(flFrametime);
|
||||
sip->hud_gauges[j]->render(frametime);
|
||||
}
|
||||
} else {
|
||||
num_gauges = default_hud_gauges.size();
|
||||
@@ -1901,7 +1905,7 @@ void hud_render_gauges(int cockpit_display_num)
|
||||
|
||||
default_hud_gauges[j]->preprocess();
|
||||
|
||||
default_hud_gauges[j]->onFrame(flFrametime);
|
||||
default_hud_gauges[j]->onFrame(frametime);
|
||||
|
||||
if ( !default_hud_gauges[j]->canRender() ) {
|
||||
continue;
|
||||
@@ -1911,7 +1915,7 @@ void hud_render_gauges(int cockpit_display_num)
|
||||
|
||||
default_hud_gauges[j]->resetClip();
|
||||
default_hud_gauges[j]->setFont();
|
||||
default_hud_gauges[j]->render(flFrametime);
|
||||
default_hud_gauges[j]->render(frametime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3775,7 +3779,7 @@ void HUD_get_nose_coordinates(int *x, int *y)
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
|
||||
vm_vec_scale_add(&p0, &Player_obj->pos, &Player_obj->orient.vec.fvec, 10000.0f);
|
||||
vm_vec_scale_add(&p0, &Player_obj->pos, &Player_obj->orient.vec.fvec, 1000.0f);
|
||||
g3_rotate_vertex(&v0, &p0);
|
||||
|
||||
if (v0.codes == 0) {
|
||||
@@ -3833,6 +3837,7 @@ void hud_save_restore_camera_data(int save)
|
||||
{
|
||||
static vec3d save_view_position;
|
||||
static fov_t save_view_zoom;
|
||||
static fov_t save_proj_fov;
|
||||
static matrix save_view_matrix;
|
||||
static matrix save_eye_matrix;
|
||||
static vec3d save_eye_position;
|
||||
@@ -3840,6 +3845,7 @@ void hud_save_restore_camera_data(int save)
|
||||
if ( save ) {
|
||||
save_view_position = View_position;
|
||||
save_view_zoom = View_zoom;
|
||||
save_proj_fov = Proj_fov;
|
||||
save_view_matrix = View_matrix;
|
||||
save_eye_matrix = Eye_matrix;
|
||||
save_eye_position = Eye_position;
|
||||
@@ -3848,6 +3854,7 @@ void hud_save_restore_camera_data(int save)
|
||||
// restore global view variables
|
||||
View_position = save_view_position;
|
||||
View_zoom = save_view_zoom;
|
||||
Proj_fov = save_proj_fov;
|
||||
View_matrix = save_view_matrix;
|
||||
Eye_matrix = save_eye_matrix;
|
||||
Eye_position = save_eye_position;
|
||||
|
||||
@@ -103,11 +103,6 @@ extern int HUD_color_alpha;
|
||||
|
||||
extern color HUD_color_debug;
|
||||
|
||||
// Values used "wiggle" the HUD. In the 2D HUD case, the clip region accounts
|
||||
// for these, but for the 3d-type hud stuff, you need to add these in manually.
|
||||
extern float HUD_offset_x;
|
||||
extern float HUD_offset_y;
|
||||
|
||||
// the offset of the player's view vector and the ship forward vector in pixels (Swifty)
|
||||
extern int HUD_nose_x;
|
||||
extern int HUD_nose_y;
|
||||
|
||||
@@ -357,7 +357,7 @@ void ssm_create(object *target, vec3d *start, size_t ssm_index, ssm_firing_info
|
||||
ssm.sinfo.start_pos.resize(count);
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
ssm.sinfo.delay_stamp[idx] = _timestamp(200 + (int)frand_range(-199.0f, 1000.0f));
|
||||
ssm.sinfo.delay_stamp[idx] = _timestamp(200 + Random::next(-199, 1000));
|
||||
ssm_get_random_start_pos(&ssm.sinfo.start_pos[idx], start, &dir, ssm_index);
|
||||
}
|
||||
|
||||
|
||||
@@ -672,7 +672,7 @@ void HudGaugeBrackets::renderBoundingBrackets(int x1, int y1, int x2, int y2, in
|
||||
break;
|
||||
case OBJ_JUMP_NODE:
|
||||
for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
|
||||
if(jnp->GetSCPObject() == t_objp)
|
||||
if(jnp->GetSCPObjectNumber() == target_objnum)
|
||||
break;
|
||||
}
|
||||
tinfo_name = jnp->GetDisplayName();
|
||||
|
||||
@@ -616,7 +616,7 @@ void hud_config_init_ui(bool API_Access, int x, int y, int w)
|
||||
// can't find a better one. Need to get the furthest right and bottom
|
||||
// pixels to be rendered to calculate the percent change. That is then
|
||||
// used to rescale each gauge correctly for the rendering size and position. - Mjn
|
||||
for (auto gauge : HC_gauge_regions[gr_screen.res]) {
|
||||
for (const auto& gauge : HC_gauge_regions[gr_screen.res]) {
|
||||
if (!stricmp(gauge.filename, NOX("none"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+14
-7
@@ -125,25 +125,32 @@ void update_ets(object* objp, float fl_frametime)
|
||||
// This will translate to 71% max speed at 50% engines, and 31% max speed at 10% engines
|
||||
//
|
||||
|
||||
float engine_aggregate_strength;
|
||||
float effective_engine_strength;
|
||||
float actual_engine_strength;
|
||||
if (ship_p->flags[Ship::Ship_Flags::Maneuver_despite_engines]) {
|
||||
// Pretend our strength is 100% when this flag is active
|
||||
engine_aggregate_strength = 1.0f;
|
||||
effective_engine_strength = 1.0f;
|
||||
actual_engine_strength = 1.0f;
|
||||
} else {
|
||||
engine_aggregate_strength = ship_get_subsystem_strength(ship_p, SUBSYSTEM_ENGINE);
|
||||
effective_engine_strength = ship_get_subsystem_strength(ship_p, SUBSYSTEM_ENGINE);
|
||||
|
||||
// very annoying, but ship_get_subsystem_strength will typically cap at no lower than 15% strength reported
|
||||
// causing the condition below to possibly erroneously believe the engine strength isn't changing while being
|
||||
// repaired below that threshold. use the ACTUAL strength for this check
|
||||
actual_engine_strength = ship_get_subsystem_strength(ship_p, SUBSYSTEM_ENGINE, false, true);
|
||||
}
|
||||
|
||||
// only update max speed if engine_aggregate_strength has changed
|
||||
// which helps minimize amount of overrides to max speed
|
||||
if (engine_aggregate_strength != ship_p->prev_engine_aggregate_strength) {
|
||||
if (actual_engine_strength != ship_p->prev_engine_strength) {
|
||||
ets_update_max_speed(objp);
|
||||
ship_p->prev_engine_aggregate_strength = engine_aggregate_strength;
|
||||
ship_p->prev_engine_strength = actual_engine_strength;
|
||||
|
||||
// check if newly updated max speed should be reduced due to engine damage
|
||||
// don't let engine strength affect max speed when playing on lowest skill level
|
||||
if ((objp != Player_obj) || (Game_skill_level > 0)) {
|
||||
if (engine_aggregate_strength < SHIP_MIN_ENGINES_FOR_FULL_SPEED) {
|
||||
objp->phys_info.max_vel.xyz.z *= fl_sqrt(engine_aggregate_strength);
|
||||
if (effective_engine_strength < SHIP_MIN_ENGINES_FOR_FULL_SPEED) {
|
||||
objp->phys_info.max_vel.xyz.z *= fl_sqrt(effective_engine_strength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,7 +1583,7 @@ void hud_do_lock_indicators(float frametime)
|
||||
lock_slot->target_in_lock_cone = false;
|
||||
}
|
||||
|
||||
if ( !lock_slot->locked && wip->trigger_lock && !(swp->flags[Ship::Weapon_Flags::Trigger_Lock]) ) {
|
||||
if ( !lock_slot->locked && wip->trigger_lock && !(swp->flags[Ship::Weapon_Flags::Secondary_trigger_down]) ) {
|
||||
// only reset locks that are not locked if this is a trigger dependent weapon
|
||||
// and player isn't holding down trigger
|
||||
ship_clear_lock(lock_slot);
|
||||
|
||||
+15
-5
@@ -645,7 +645,7 @@ void hud_add_msg_to_scrollback(const char *text, int source, int t)
|
||||
}
|
||||
|
||||
// create the new node for the vector
|
||||
line_node newLine = {t, source, 0, 1, w, ""};
|
||||
line_node newLine = {t, The_mission.HUD_timer_padding, source, 0, 1, w, ""};
|
||||
newLine.text = text;
|
||||
|
||||
Msg_scrollback_vec.push_back(newLine);
|
||||
@@ -853,7 +853,7 @@ void hud_initialize_scrollback_lines()
|
||||
char* text = c_text;
|
||||
|
||||
char* split = split_str_once(text, max_width);
|
||||
Msg_scrollback_lines.push_back({node_msg.time, node_msg.source, node_msg.x, 1, node_msg.underline_width, text});
|
||||
Msg_scrollback_lines.push_back({node_msg.time, The_mission.HUD_timer_padding, node_msg.source, node_msg.x, 1, node_msg.underline_width, text});
|
||||
|
||||
while (split != nullptr) {
|
||||
text = split;
|
||||
@@ -864,7 +864,7 @@ void hud_initialize_scrollback_lines()
|
||||
if (split == nullptr)
|
||||
offset = height / 3;
|
||||
|
||||
Msg_scrollback_lines.push_back({0, node_msg.source, node_msg.x, offset, 0, text});
|
||||
Msg_scrollback_lines.push_back({0, 0, node_msg.source, node_msg.x, offset, 0, text});
|
||||
}
|
||||
} else {
|
||||
node_msg.y = height / 3;
|
||||
@@ -1214,12 +1214,22 @@ void HudGaugeTalkingHead::render(float frametime)
|
||||
int hx = tablePosX + Anim_offsets[0];
|
||||
int hy = tablePosY + Anim_offsets[1];
|
||||
|
||||
if (gr_screen.rendering_to_texture != -1)
|
||||
if (gr_screen.rendering_to_texture != -1) {
|
||||
gr_set_screen_scale(canvas_w, canvas_h, -1, -1, target_w, target_h, target_w, target_h, true);
|
||||
hx += gr_screen.offset_x_unscaled;
|
||||
hy += gr_screen.offset_y_unscaled;
|
||||
}
|
||||
else
|
||||
gr_set_screen_scale(base_w, base_h);
|
||||
|
||||
generic_anim_render_ex(head_anim,frametime, hx, hy, Anim_size[0], Anim_size[1]);
|
||||
generic_anim_bitmap_set(head_anim, frametime);
|
||||
bitmap_rect_list brl = bitmap_rect_list(hx, hy, Anim_size[0], Anim_size[1]);
|
||||
|
||||
if (head_anim->use_hud_color)
|
||||
gr_aabitmap_list(&brl, 1, GR_RESIZE_FULL);
|
||||
else
|
||||
gr_bitmap_list(&brl, 1, GR_RESIZE_FULL);
|
||||
|
||||
gr_reset_screen_scale();
|
||||
|
||||
// draw title
|
||||
|
||||
@@ -38,6 +38,7 @@ typedef struct HUD_message_data {
|
||||
|
||||
typedef struct line_node {
|
||||
fix time; // timestamp when message was added
|
||||
int timer_padding; // the mission timer padding, in seconds, at the time the message was added
|
||||
int source; // who/what the source of the message was (for color coding)
|
||||
int x;
|
||||
int y;
|
||||
|
||||
+18
-6
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "graphics/font.h" //for gr_force_fit_string
|
||||
#include "graphics/openxr.h"
|
||||
#include "hud/hud.h"
|
||||
#include "hud/hudbrackets.h"
|
||||
#include "hud/hudconfig.h" // for retrieving user's hud config
|
||||
@@ -41,6 +42,7 @@ extern bool Ships_inited; //Need this
|
||||
|
||||
float Hud_unit_multiplier = 1.0f; //Backslash
|
||||
float Hud_speed_multiplier = 1.0f; //The E
|
||||
float Hud_global_scale = 1.0f;
|
||||
|
||||
// Goober5000
|
||||
int Hud_reticle_style = HUD_RETICLE_STYLE_FS2;
|
||||
@@ -1212,12 +1214,12 @@ void adjust_for_multimonitor(int *base_res, bool set_position, int *coords)
|
||||
float scale_w = (float)gr_screen.center_w / (float)base_res[0];
|
||||
float scale_h = (float)gr_screen.center_h / (float)base_res[1];
|
||||
|
||||
base_res[0] = fl2ir(base_res[0] * ((float)gr_screen.max_w / (float)gr_screen.center_w));
|
||||
base_res[1] = fl2ir(base_res[1] * ((float)gr_screen.max_h / (float)gr_screen.center_h));
|
||||
base_res[0] = fl2ir(base_res[0] * ((float)gr_screen.max_w / (float)gr_screen.center_w / Hud_global_scale));
|
||||
base_res[1] = fl2ir(base_res[1] * ((float)gr_screen.max_h / (float)gr_screen.center_h / Hud_global_scale));
|
||||
|
||||
if (set_position) {
|
||||
coords[0] += fl2ir(gr_screen.center_offset_x / scale_w);
|
||||
coords[1] += fl2ir(gr_screen.center_offset_y / scale_h);
|
||||
coords[0] += fl2ir(gr_screen.center_offset_x / scale_w + ((1.0f - Hud_global_scale) * 0.5f * (float)base_res[0]));
|
||||
coords[1] += fl2ir(gr_screen.center_offset_y / scale_h + ((1.0f - Hud_global_scale) * 0.5f * (float)base_res[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1387,6 +1389,11 @@ std::unique_ptr<T> gauge_load_common(gauge_settings* settings, T* preAllocated =
|
||||
instance->lockConfigColor(lock_color);
|
||||
}
|
||||
|
||||
if (openxr_requested()) {
|
||||
//In this case, we must always slew every hud gauge, no matter what.
|
||||
instance->initSlew(true);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -1396,11 +1403,11 @@ void gauge_assign_common(const gauge_settings* settings, std::unique_ptr<T>&& hu
|
||||
for (auto ship_index = settings->ship_idx->begin(); ship_index != settings->ship_idx->end(); ++ship_index) {
|
||||
std::unique_ptr<T> instance(new T());
|
||||
*instance = *hud_gauge;
|
||||
Ship_info[*ship_index].hud_gauges.push_back(move(instance));
|
||||
Ship_info[*ship_index].hud_gauges.push_back(std::move(instance));
|
||||
}
|
||||
// Previous instance goes out of scope here and is destructed
|
||||
} else {
|
||||
default_hud_gauges.push_back(move(hud_gauge));
|
||||
default_hud_gauges.push_back(std::move(hud_gauge));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3708,6 +3715,7 @@ void load_gauge_directives(gauge_settings* settings)
|
||||
char fname_middle[MAX_FILENAME_LEN] = "directives2";
|
||||
char fname_bottom[MAX_FILENAME_LEN] = "directives3";
|
||||
int bottom_bg_offset = 0;
|
||||
int key_line_x_offset = 0;
|
||||
|
||||
settings->origin[0] = 0.0f;
|
||||
settings->origin[1] = 0.5f;
|
||||
@@ -3756,6 +3764,9 @@ void load_gauge_directives(gauge_settings* settings)
|
||||
if ( optional_string("Max Line Width:") ) {
|
||||
stuff_int(&max_line_width);
|
||||
}
|
||||
if (optional_string("Key Line X Offset:")) {
|
||||
stuff_int(&key_line_x_offset);
|
||||
}
|
||||
|
||||
hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
|
||||
hud_gauge->initMiddleFrameOffsetY(middle_frame_offset_y);
|
||||
@@ -3764,6 +3775,7 @@ void load_gauge_directives(gauge_settings* settings)
|
||||
hud_gauge->initTextStartOffsets(text_start_offsets[0], text_start_offsets[1]);
|
||||
hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
|
||||
hud_gauge->initMaxLineWidth(max_line_width);
|
||||
hud_gauge->initKeyLineXOffset(key_line_x_offset);
|
||||
|
||||
gauge_assign_common(settings, std::move(hud_gauge));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
extern int Num_custom_gauges;
|
||||
extern float Hud_unit_multiplier;
|
||||
extern float Hud_speed_multiplier;
|
||||
extern float Hud_global_scale;
|
||||
|
||||
#define NUM_HUD_RETICLE_STYLES 2
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ void hud_squadmsg_start()
|
||||
if (scripting::hooks::OnHudCommMenuOpened->isActive())
|
||||
{
|
||||
auto paramList = scripting::hook_param_list(scripting::hook_param("Player", 'o', Player_obj));
|
||||
scripting::hooks::OnHudCommMenuOpened->run(paramList);
|
||||
scripting::hooks::OnHudCommMenuOpened->run(std::move(paramList));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ void hud_squadmsg_end()
|
||||
if (scripting::hooks::OnHudCommMenuClosed->isActive())
|
||||
{
|
||||
auto paramList = scripting::hook_param_list(scripting::hook_param("Player", 'o', Player_obj));
|
||||
scripting::hooks::OnHudCommMenuClosed->run(paramList);
|
||||
scripting::hooks::OnHudCommMenuClosed->run(std::move(paramList));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1754,8 +1754,9 @@ int turret_compare_func(const eval_next_turret *p1, const eval_next_turret *p2)
|
||||
}
|
||||
}
|
||||
|
||||
extern bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags);
|
||||
extern bool turret_weapon_has_subtype(ship_weapon *swp, int subtype);
|
||||
extern bool turret_weapon_has_flags(const ship_weapon *swp, Weapon::Info_Flags flags);
|
||||
extern bool turret_weapon_has_subtype(const ship_weapon *swp, int subtype);
|
||||
|
||||
// target the next/prev live turret on the current target
|
||||
// auto_advance from hud_update_closest_turret
|
||||
void hud_target_live_turret(int next_flag, int auto_advance, int only_player_target)
|
||||
|
||||
Loaded 100 of 676 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user