mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-28 12:40:06 +00:00
Merge branch 'feature/pplLauncherSetting' of git@gitlab.com:BPengu1n/openmw.git
This commit is contained in:
commit
89ad315f65
@ -210,6 +210,7 @@ Ubuntu_GCC_Debug:
|
|||||||
CCACHE_SIZE: 3G
|
CCACHE_SIZE: 3G
|
||||||
CMAKE_BUILD_TYPE: Debug
|
CMAKE_BUILD_TYPE: Debug
|
||||||
CMAKE_CXX_FLAGS_DEBUG: -O0
|
CMAKE_CXX_FLAGS_DEBUG: -O0
|
||||||
|
BUILD_SHARED_LIBS: 1
|
||||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||||
timeout: 2h
|
timeout: 2h
|
||||||
|
|
||||||
@ -520,19 +521,19 @@ Ubuntu_GCC_integration_tests_asan:
|
|||||||
- build/OpenMW-*.dmg
|
- build/OpenMW-*.dmg
|
||||||
- "build/**/*.log"
|
- "build/**/*.log"
|
||||||
|
|
||||||
macOS13_Xcode14_arm64:
|
macOS14_Xcode15_arm64:
|
||||||
extends: .MacOS
|
extends: .MacOS
|
||||||
image: macos-12-xcode-14
|
image: macos-14-xcode-15
|
||||||
tags:
|
tags:
|
||||||
- saas-macos-medium-m1
|
- saas-macos-medium-m1
|
||||||
cache:
|
cache:
|
||||||
key: macOS12_Xcode14_arm64.v4
|
key: macOS14_Xcode15_arm64.v1
|
||||||
variables:
|
variables:
|
||||||
CCACHE_SIZE: 3G
|
CCACHE_SIZE: 3G
|
||||||
|
|
||||||
.Windows_Ninja_Base:
|
.Windows_Ninja_Base:
|
||||||
tags:
|
tags:
|
||||||
- windows
|
- saas-windows-medium-amd64
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
before_script:
|
before_script:
|
||||||
@ -569,60 +570,54 @@ macOS13_Xcode14_arm64:
|
|||||||
- $env:CCACHE_BASEDIR = Get-Location
|
- $env:CCACHE_BASEDIR = Get-Location
|
||||||
- $env:CCACHE_DIR = "$(Get-Location)\ccache"
|
- $env:CCACHE_DIR = "$(Get-Location)\ccache"
|
||||||
- New-Item -Type Directory -Force -Path $env:CCACHE_DIR
|
- New-Item -Type Directory -Force -Path $env:CCACHE_DIR
|
||||||
- New-Item -Type File -Force -Path MSVC2019_64_Ninja\.cmake\api\v1\query\codemodel-v2
|
- New-Item -Type File -Force -Path MSVC2022_64_Ninja\.cmake\api\v1\query\codemodel-v2
|
||||||
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N -b -t -C $multiview -E
|
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2022 -k -V -N -b -t -C $multiview -E
|
||||||
- Get-Volume
|
- Get-Volume
|
||||||
- cd MSVC2019_64_Ninja
|
- cd MSVC2022_64_Ninja
|
||||||
- .\ActivateMSVC.ps1
|
- .\ActivateMSVC.ps1
|
||||||
- cmake --build . --config $config
|
- cmake --build . --config $config
|
||||||
- ccache --show-stats
|
- ccache --show-stats -v
|
||||||
- cd $config
|
- cd $config
|
||||||
- echo "CI_COMMIT_REF_NAME ${CI_COMMIT_REF_NAME}`nCI_JOB_ID ${CI_JOB_ID}`nCI_COMMIT_SHA ${CI_COMMIT_SHA}" | Out-File -Encoding UTF8 CI-ID.txt
|
- echo "CI_COMMIT_REF_NAME ${CI_COMMIT_REF_NAME}`nCI_JOB_ID ${CI_JOB_ID}`nCI_COMMIT_SHA ${CI_COMMIT_SHA}" | Out-File -Encoding UTF8 CI-ID.txt
|
||||||
- $artifactDirectory = "$(Make-SafeFileName("${CI_PROJECT_NAMESPACE}"))/$(Make-SafeFileName("${CI_COMMIT_REF_NAME}"))/$(Make-SafeFileName("${CI_COMMIT_SHORT_SHA}-${CI_JOB_ID}"))/"
|
- $artifactDirectory = "$(Make-SafeFileName("${CI_PROJECT_NAMESPACE}"))/$(Make-SafeFileName("${CI_COMMIT_REF_NAME}"))/$(Make-SafeFileName("${CI_COMMIT_SHORT_SHA}-${CI_JOB_ID}"))/"
|
||||||
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
||||||
- |
|
- |
|
||||||
if (Get-ChildItem -Recurse *.pdb) {
|
if (Get-ChildItem -Recurse *.pdb) {
|
||||||
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
||||||
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
||||||
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
||||||
}
|
}
|
||||||
Push-Location ..
|
Push-Location ..
|
||||||
..\CI\Store-Symbols.ps1
|
..\CI\Store-Symbols.ps1
|
||||||
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
||||||
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp --recursive --exclude * --include *.ex_ --include *.dl_ --include *.pd_ .\SymStore s3://openmw-sym
|
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp --recursive --exclude * --include *.ex_ --include *.dl_ --include *.pd_ .\SymStore s3://openmw-sym
|
||||||
}
|
}
|
||||||
7z a -tzip "..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_sym_store.zip"))" '.\SymStore\*' $config\CI-ID.txt
|
7z a -tzip "..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_sym_store.zip"))" '.\SymStore\*' $config\CI-ID.txt
|
||||||
Pop-Location
|
Pop-Location
|
||||||
Get-ChildItem -Recurse *.pdb | Remove-Item
|
Get-ChildItem -Recurse *.pdb | Remove-Item
|
||||||
}
|
}
|
||||||
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
||||||
- |
|
- |
|
||||||
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
||||||
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
||||||
}
|
}
|
||||||
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
||||||
after_script:
|
after_script:
|
||||||
- Get-Volume
|
- Get-Volume
|
||||||
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
||||||
cache:
|
cache:
|
||||||
key: ninja-v8
|
key: ninja-2022-v9
|
||||||
paths:
|
paths:
|
||||||
- ccache
|
- ccache
|
||||||
- deps
|
- deps
|
||||||
- MSVC2019_64_Ninja/deps/Qt
|
- MSVC2022_64_Ninja/deps/Qt
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
paths:
|
paths:
|
||||||
- "*.zip"
|
- "*.zip"
|
||||||
- "*.log"
|
- "*.log"
|
||||||
- MSVC2019_64_Ninja/*.log
|
- MSVC2022_64_Ninja/*.log
|
||||||
- MSVC2019_64_Ninja/*/*.log
|
- MSVC2022_64_Ninja/**/*.log
|
||||||
- MSVC2019_64_Ninja/*/*/*.log
|
|
||||||
- MSVC2019_64_Ninja/*/*/*/*.log
|
|
||||||
- MSVC2019_64_Ninja/*/*/*/*/*.log
|
|
||||||
- MSVC2019_64_Ninja/*/*/*/*/*/*.log
|
|
||||||
- MSVC2019_64_Ninja/*/*/*/*/*/*/*.log
|
|
||||||
- MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log
|
|
||||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||||
timeout: 2h
|
timeout: 2h
|
||||||
|
|
||||||
@ -655,7 +650,7 @@ macOS13_Xcode14_arm64:
|
|||||||
|
|
||||||
.Windows_MSBuild_Base:
|
.Windows_MSBuild_Base:
|
||||||
tags:
|
tags:
|
||||||
- windows
|
- saas-windows-medium-amd64
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
before_script:
|
before_script:
|
||||||
@ -665,7 +660,6 @@ macOS13_Xcode14_arm64:
|
|||||||
- choco source disable -n=chocolatey
|
- choco source disable -n=chocolatey
|
||||||
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
- choco install git --force --params "/GitAndUnixToolsOnPath" -y
|
||||||
- choco install 7zip -y
|
- choco install 7zip -y
|
||||||
- choco install ccache -y
|
|
||||||
- choco install vswhere -y
|
- choco install vswhere -y
|
||||||
- choco install python -y
|
- choco install python -y
|
||||||
- choco install awscli -y
|
- choco install awscli -y
|
||||||
@ -688,62 +682,51 @@ macOS13_Xcode14_arm64:
|
|||||||
- $time = (Get-Date -Format "HH:mm:ss")
|
- $time = (Get-Date -Format "HH:mm:ss")
|
||||||
- echo ${time}
|
- echo ${time}
|
||||||
- echo "started by ${GITLAB_USER_NAME}"
|
- echo "started by ${GITLAB_USER_NAME}"
|
||||||
- $env:CCACHE_BASEDIR = Get-Location
|
- New-Item -Type File -Force -Path MSVC2022_64\.cmake\api\v1\query\codemodel-v2
|
||||||
- $env:CCACHE_DIR = "$(Get-Location)\ccache"
|
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2022 -k -V -b -t -C $multiview -E
|
||||||
- New-Item -Type Directory -Force -Path $env:CCACHE_DIR
|
- cd MSVC2022_64
|
||||||
- New-Item -Type File -Force -Path MSVC2019_64\.cmake\api\v1\query\codemodel-v2
|
|
||||||
- sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -b -t -C $multiview -E
|
|
||||||
- cd MSVC2019_64
|
|
||||||
- Get-Volume
|
- Get-Volume
|
||||||
- cmake --build . --config $config
|
- cmake --build . --config $config
|
||||||
- ccache --show-stats
|
|
||||||
- cd $config
|
- cd $config
|
||||||
- echo "CI_COMMIT_REF_NAME ${CI_COMMIT_REF_NAME}`nCI_JOB_ID ${CI_JOB_ID}`nCI_COMMIT_SHA ${CI_COMMIT_SHA}" | Out-File -Encoding UTF8 CI-ID.txt
|
- echo "CI_COMMIT_REF_NAME ${CI_COMMIT_REF_NAME}`nCI_JOB_ID ${CI_JOB_ID}`nCI_COMMIT_SHA ${CI_COMMIT_SHA}" | Out-File -Encoding UTF8 CI-ID.txt
|
||||||
- $artifactDirectory = "$(Make-SafeFileName("${CI_PROJECT_NAMESPACE}"))/$(Make-SafeFileName("${CI_COMMIT_REF_NAME}"))/$(Make-SafeFileName("${CI_COMMIT_SHORT_SHA}-${CI_JOB_ID}"))/"
|
- $artifactDirectory = "$(Make-SafeFileName("${CI_PROJECT_NAMESPACE}"))/$(Make-SafeFileName("${CI_COMMIT_REF_NAME}"))/$(Make-SafeFileName("${CI_COMMIT_SHORT_SHA}-${CI_JOB_ID}"))/"
|
||||||
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
||||||
- |
|
- |
|
||||||
if (Get-ChildItem -Recurse *.pdb) {
|
if (Get-ChildItem -Recurse *.pdb) {
|
||||||
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
||||||
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
||||||
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
||||||
}
|
}
|
||||||
Push-Location ..
|
Push-Location ..
|
||||||
..\CI\Store-Symbols.ps1
|
..\CI\Store-Symbols.ps1
|
||||||
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
||||||
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp --recursive --exclude * --include *.ex_ --include *.dl_ --include *.pd_ .\SymStore s3://openmw-sym
|
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp --recursive --exclude * --include *.ex_ --include *.dl_ --include *.pd_ .\SymStore s3://openmw-sym
|
||||||
}
|
}
|
||||||
7z a -tzip "..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_sym_store.zip"))" '.\SymStore\*' $config\CI-ID.txt
|
7z a -tzip "..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_sym_store.zip"))" '.\SymStore\*' $config\CI-ID.txt
|
||||||
Pop-Location
|
Pop-Location
|
||||||
Get-ChildItem -Recurse *.pdb | Remove-Item
|
Get-ChildItem -Recurse *.pdb | Remove-Item
|
||||||
}
|
}
|
||||||
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
||||||
- |
|
- |
|
||||||
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
if (Test-Path env:AWS_ACCESS_KEY_ID) {
|
||||||
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
aws --endpoint-url https://rgw.ctrl-c.liu.se s3 cp "..\..\$(Make-SafeFileName("OpenMW_MSVC2022_64_${config}_${CI_COMMIT_REF_NAME}.zip"))" s3://openmw-artifacts/${artifactDirectory}
|
||||||
}
|
}
|
||||||
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
||||||
after_script:
|
after_script:
|
||||||
- Get-Volume
|
- Get-Volume
|
||||||
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
||||||
cache:
|
cache:
|
||||||
key: msbuild-v8
|
key: msbuild-2022-v9
|
||||||
paths:
|
paths:
|
||||||
- ccache
|
|
||||||
- deps
|
- deps
|
||||||
- MSVC2019_64/deps/Qt
|
- MSVC2022_64/deps/Qt
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
paths:
|
paths:
|
||||||
- "*.zip"
|
- "*.zip"
|
||||||
- "*.log"
|
- "*.log"
|
||||||
- MSVC2019_64/*.log
|
- MSVC2022_64/*.log
|
||||||
- MSVC2019_64/*/*.log
|
- MSVC2022_64/**/*.log
|
||||||
- MSVC2019_64/*/*/*.log
|
|
||||||
- MSVC2019_64/*/*/*/*.log
|
|
||||||
- MSVC2019_64/*/*/*/*/*.log
|
|
||||||
- MSVC2019_64/*/*/*/*/*/*.log
|
|
||||||
- MSVC2019_64/*/*/*/*/*/*/*.log
|
|
||||||
- MSVC2019_64/*/*/*/*/*/*/*/*.log
|
|
||||||
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
# When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks.
|
||||||
timeout: 2h
|
timeout: 2h
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ Programmers
|
|||||||
Nicolay Korslund - Project leader 2008-2010
|
Nicolay Korslund - Project leader 2008-2010
|
||||||
scrawl - Top contributor
|
scrawl - Top contributor
|
||||||
|
|
||||||
|
AbduSharif
|
||||||
Adam Hogan (aurix)
|
Adam Hogan (aurix)
|
||||||
Aesylwinn
|
Aesylwinn
|
||||||
aegis
|
aegis
|
||||||
@ -79,6 +80,7 @@ Programmers
|
|||||||
Eduard Cot (trombonecot)
|
Eduard Cot (trombonecot)
|
||||||
Eli2
|
Eli2
|
||||||
Emanuel Guével (potatoesmaster)
|
Emanuel Guével (potatoesmaster)
|
||||||
|
Epoch
|
||||||
Eris Caffee (eris)
|
Eris Caffee (eris)
|
||||||
eroen
|
eroen
|
||||||
escondida
|
escondida
|
||||||
@ -187,6 +189,7 @@ Programmers
|
|||||||
pkubik
|
pkubik
|
||||||
PLkolek
|
PLkolek
|
||||||
PlutonicOverkill
|
PlutonicOverkill
|
||||||
|
Qlonever
|
||||||
Radu-Marius Popovici (rpopovici)
|
Radu-Marius Popovici (rpopovici)
|
||||||
Rafael Moura (dhustkoder)
|
Rafael Moura (dhustkoder)
|
||||||
Randy Davin (Kindi)
|
Randy Davin (Kindi)
|
||||||
|
50
CHANGELOG.md
50
CHANGELOG.md
@ -33,6 +33,8 @@
|
|||||||
Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load
|
Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load
|
||||||
Bug #6025: Subrecords cannot overlap records
|
Bug #6025: Subrecords cannot overlap records
|
||||||
Bug #6027: Collisionshape becomes spiderweb-like when the mesh is too complex
|
Bug #6027: Collisionshape becomes spiderweb-like when the mesh is too complex
|
||||||
|
Bug #6146: Lua command `actor:setEquipment` doesn't trigger mwscripts when equipping or unequipping a scripted item
|
||||||
|
Bug #6156: 1ft Charm or Sound magic effect vfx doesn't work properly
|
||||||
Bug #6190: Unintuitive sun specularity time of day dependence
|
Bug #6190: Unintuitive sun specularity time of day dependence
|
||||||
Bug #6222: global map cell size can crash openmw if set to too high a value
|
Bug #6222: global map cell size can crash openmw if set to too high a value
|
||||||
Bug #6313: Followers with high Fight can turn hostile
|
Bug #6313: Followers with high Fight can turn hostile
|
||||||
@ -44,9 +46,11 @@
|
|||||||
Bug #6657: Distant terrain tiles become black when using FWIW mod
|
Bug #6657: Distant terrain tiles become black when using FWIW mod
|
||||||
Bug #6661: Saved games that have no preview screenshot cause issues or crashes
|
Bug #6661: Saved games that have no preview screenshot cause issues or crashes
|
||||||
Bug #6716: mwscript comparison operator handling is too restrictive
|
Bug #6716: mwscript comparison operator handling is too restrictive
|
||||||
|
Bug #6723: "Turn to movement direction" makes the player rotate wildly with COLLADA
|
||||||
Bug #6754: Beast to Non-beast transformation mod is not working on OpenMW
|
Bug #6754: Beast to Non-beast transformation mod is not working on OpenMW
|
||||||
Bug #6758: Main menu background video can be stopped by opening the options menu
|
Bug #6758: Main menu background video can be stopped by opening the options menu
|
||||||
Bug #6807: Ultimate Galleon is not working properly
|
Bug #6807: Ultimate Galleon is not working properly
|
||||||
|
Bug #6846: Launcher only works with default config paths
|
||||||
Bug #6893: Lua: Inconsistent behavior with actors affected by Disable and SetDelete commands
|
Bug #6893: Lua: Inconsistent behavior with actors affected by Disable and SetDelete commands
|
||||||
Bug #6894: Added item combines with equipped stack instead of creating a new unequipped stack
|
Bug #6894: Added item combines with equipped stack instead of creating a new unequipped stack
|
||||||
Bug #6932: Creatures flee from my followers and we have to chase after them
|
Bug #6932: Creatures flee from my followers and we have to chase after them
|
||||||
@ -56,6 +60,7 @@
|
|||||||
Bug #6973: Fade in happens after the scene load and is shown
|
Bug #6973: Fade in happens after the scene load and is shown
|
||||||
Bug #6974: Only harmful effects are reflected
|
Bug #6974: Only harmful effects are reflected
|
||||||
Bug #6977: Sun damage implementation does not match research
|
Bug #6977: Sun damage implementation does not match research
|
||||||
|
Bug #6985: Issues with Magic Cards numbers readability
|
||||||
Bug #6986: Sound magic effect does not make noise
|
Bug #6986: Sound magic effect does not make noise
|
||||||
Bug #6987: Set/Mod Blindness should not darken the screen
|
Bug #6987: Set/Mod Blindness should not darken the screen
|
||||||
Bug #6992: Crossbow reloading doesn't look the same as in Morrowind
|
Bug #6992: Crossbow reloading doesn't look the same as in Morrowind
|
||||||
@ -71,12 +76,15 @@
|
|||||||
Bug #7084: Resurrecting an actor doesn't take into account base record changes
|
Bug #7084: Resurrecting an actor doesn't take into account base record changes
|
||||||
Bug #7088: Deleting last save game of last character doesn't clear character name/details
|
Bug #7088: Deleting last save game of last character doesn't clear character name/details
|
||||||
Bug #7092: BSA archives from higher priority directories don't take priority
|
Bug #7092: BSA archives from higher priority directories don't take priority
|
||||||
|
Bug #7102: Some HQ Creatures mod models can hit the 8 texture slots limit with 0.48
|
||||||
Bug #7103: Multiple paths pointing to the same plugin but with different cases lead to automatically removed config entries
|
Bug #7103: Multiple paths pointing to the same plugin but with different cases lead to automatically removed config entries
|
||||||
Bug #7122: Teleportation to underwater should cancel active water walking effect
|
Bug #7122: Teleportation to underwater should cancel active water walking effect
|
||||||
Bug #7131: MyGUI log spam when post processing HUD is open
|
Bug #7131: MyGUI log spam when post processing HUD is open
|
||||||
Bug #7134: Saves with an invalid last generated RefNum can be loaded
|
Bug #7134: Saves with an invalid last generated RefNum can be loaded
|
||||||
Bug #7163: Myar Aranath: Wheat breaks the GUI
|
Bug #7163: Myar Aranath: Wheat breaks the GUI
|
||||||
|
Bug #7168: Fix average scene luminance
|
||||||
Bug #7172: Current music playlist continues playing indefinitely if next playlist is empty
|
Bug #7172: Current music playlist continues playing indefinitely if next playlist is empty
|
||||||
|
Bug #7202: Post-processing normals for terrain, water randomly stop rendering
|
||||||
Bug #7204: Missing actor scripts freeze the game
|
Bug #7204: Missing actor scripts freeze the game
|
||||||
Bug #7229: Error marker loading failure is not handled
|
Bug #7229: Error marker loading failure is not handled
|
||||||
Bug #7243: Supporting loading external files from VFS from esm files
|
Bug #7243: Supporting loading external files from VFS from esm files
|
||||||
@ -93,24 +101,29 @@
|
|||||||
Bug #7415: Unbreakable lock discrepancies
|
Bug #7415: Unbreakable lock discrepancies
|
||||||
Bug #7416: Modpccrimelevel is different from vanilla
|
Bug #7416: Modpccrimelevel is different from vanilla
|
||||||
Bug #7428: AutoCalc flag is not used to calculate enchantment costs
|
Bug #7428: AutoCalc flag is not used to calculate enchantment costs
|
||||||
|
Bug #7447: OpenMW-CS: Dragging a cell of a different type (from the initial type) into the 3D view crashes OpenMW-CS
|
||||||
Bug #7450: Evading obstacles does not work for actors missing certain animations
|
Bug #7450: Evading obstacles does not work for actors missing certain animations
|
||||||
Bug #7459: Icons get stacked on the cursor when picking up multiple items simultaneously
|
Bug #7459: Icons get stacked on the cursor when picking up multiple items simultaneously
|
||||||
Bug #7472: Crash when enchanting last projectiles
|
Bug #7472: Crash when enchanting last projectiles
|
||||||
Bug #7475: Equipping a constant effect item doesn't update the magic menu
|
Bug #7475: Equipping a constant effect item doesn't update the magic menu
|
||||||
Bug #7502: Data directories dialog (0.48.0) forces adding subdirectory instead of intended directory
|
Bug #7502: Data directories dialog (0.48.0) forces adding subdirectory instead of intended directory
|
||||||
Bug #7505: Distant terrain does not support sample size greater than cell size
|
Bug #7505: Distant terrain does not support sample size greater than cell size
|
||||||
|
Bug #7535: Bookart paths for textures in OpenMW vs vanilla Morrowind
|
||||||
Bug #7553: Faction reaction loading is incorrect
|
Bug #7553: Faction reaction loading is incorrect
|
||||||
Bug #7557: Terrain::ChunkManager::createChunk is called twice for the same position, lod on initial loading
|
Bug #7557: Terrain::ChunkManager::createChunk is called twice for the same position, lod on initial loading
|
||||||
Bug #7573: Drain Fatigue can't bring fatigue below zero by default
|
Bug #7573: Drain Fatigue can't bring fatigue below zero by default
|
||||||
Bug #7585: Difference in interior lighting between OpenMW with legacy lighting method enabled and vanilla Morrowind
|
Bug #7585: Difference in interior lighting between OpenMW with legacy lighting method enabled and vanilla Morrowind
|
||||||
|
Bug #7587: Quick load related crash
|
||||||
Bug #7603: Scripts menu size is not updated properly
|
Bug #7603: Scripts menu size is not updated properly
|
||||||
Bug #7604: Goblins Grunt becomes idle once injured
|
Bug #7604: Goblins Grunt becomes idle once injured
|
||||||
Bug #7609: ForceGreeting should not open dialogue for werewolves
|
Bug #7609: ForceGreeting should not open dialogue for werewolves
|
||||||
Bug #7611: Beast races' idle animations slide after turning or jumping in place
|
Bug #7611: Beast races' idle animations slide after turning or jumping in place
|
||||||
Bug #7617: The death prompt asks the player if they wanted to load the character's last created save
|
Bug #7617: The death prompt asks the player if they wanted to load the character's last created save
|
||||||
Bug #7619: Long map notes may get cut off
|
Bug #7619: Long map notes may get cut off
|
||||||
|
Bug #7623: Incorrect placement of the script info in the engraved ring of healing tooltip
|
||||||
Bug #7630: Charm can be cast on creatures
|
Bug #7630: Charm can be cast on creatures
|
||||||
Bug #7631: Cannot trade with/talk to Creeper or Mudcrab Merchant when they're fleeing
|
Bug #7631: Cannot trade with/talk to Creeper or Mudcrab Merchant when they're fleeing
|
||||||
|
Bug #7633: Groundcover should ignore non-geometry Drawables
|
||||||
Bug #7636: Animations bug out when switching between 1st and 3rd person, while playing a scripted animation
|
Bug #7636: Animations bug out when switching between 1st and 3rd person, while playing a scripted animation
|
||||||
Bug #7637: Actors can sometimes move while playing scripted animations
|
Bug #7637: Actors can sometimes move while playing scripted animations
|
||||||
Bug #7639: NPCs don't use hand-to-hand if their other melee skills were damaged during combat
|
Bug #7639: NPCs don't use hand-to-hand if their other melee skills were damaged during combat
|
||||||
@ -128,30 +141,51 @@
|
|||||||
Bug #7679: Scene luminance value flashes when toggling shaders
|
Bug #7679: Scene luminance value flashes when toggling shaders
|
||||||
Bug #7685: Corky sometimes doesn't follow Llovyn Andus
|
Bug #7685: Corky sometimes doesn't follow Llovyn Andus
|
||||||
Bug #7712: Casting doesn't support spells and enchantments with no effects
|
Bug #7712: Casting doesn't support spells and enchantments with no effects
|
||||||
|
Bug #7721: CS: Special Chars Not Allowed in IDs
|
||||||
Bug #7723: Assaulting vampires and werewolves shouldn't be a crime
|
Bug #7723: Assaulting vampires and werewolves shouldn't be a crime
|
||||||
Bug #7724: Guards don't help vs werewolves
|
Bug #7724: Guards don't help vs werewolves
|
||||||
Bug #7733: Launcher shows incorrect data paths when there's two plugins with the same name
|
Bug #7733: Launcher shows incorrect data paths when there's two plugins with the same name
|
||||||
Bug #7742: Governing attribute training limit should use the modified attribute
|
Bug #7742: Governing attribute training limit should use the modified attribute
|
||||||
|
Bug #7753: Editor: Actors Don't Scale According to Their Race
|
||||||
Bug #7758: Water walking is not taken into account to compute path cost on the water
|
Bug #7758: Water walking is not taken into account to compute path cost on the water
|
||||||
Bug #7761: Rain and ambient loop sounds are mutually exclusive
|
Bug #7761: Rain and ambient loop sounds are mutually exclusive
|
||||||
|
Bug #7763: Bullet shape loading problems, assorted
|
||||||
Bug #7765: OpenMW-CS: Touch Record option is broken
|
Bug #7765: OpenMW-CS: Touch Record option is broken
|
||||||
Bug #7769: Sword of the Perithia: Broken NPCs
|
Bug #7769: Sword of the Perithia: Broken NPCs
|
||||||
Bug #7770: Sword of the Perithia: Script execution failure
|
Bug #7770: Sword of the Perithia: Script execution failure
|
||||||
Bug #7780: Non-ASCII texture paths in NIF files don't work
|
Bug #7780: Non-ASCII texture paths in NIF files don't work
|
||||||
Bug #7785: OpenMW-CS initialising Skill and Attribute fields to 0 instead of -1 on non-FortifyStat spells
|
Bug #7785: OpenMW-CS initialising Skill and Attribute fields to 0 instead of -1 on non-FortifyStat spells
|
||||||
|
Bug #7794: Fleeing NPCs name tooltip doesn't appear
|
||||||
Bug #7796: Absorbed enchantments don't restore magicka
|
Bug #7796: Absorbed enchantments don't restore magicka
|
||||||
|
Bug #7823: Game crashes when launching it.
|
||||||
|
Bug #7832: Ingredient tooltips show magnitude for Fortify Maximum Magicka effect
|
||||||
|
Bug #7840: First run of the launcher doesn't save viewing distance as the default value
|
||||||
|
Bug #7841: Editor: "Dirty" water heights are saved in modified CELLs
|
||||||
|
Bug #7859: AutoCalc flag is not used to calculate potion value
|
||||||
|
Bug #7861: OpenMW-CS: Incorrect DIAL's type in INFO records
|
||||||
|
Bug #7872: Region sounds use wrong odds
|
||||||
|
Bug #7886: Equip and unequip animations can't share the animation track section
|
||||||
|
Bug #7887: Editor: Mismatched reported script data size and actual data size causes a crash during save
|
||||||
|
Bug #7898: Editor: Invalid reference scales are allowed
|
||||||
|
Bug #7899: Editor: Doors can't be unlocked
|
||||||
|
Bug #7901: Editor: Teleport-related fields shouldn't be editable if a ref does not teleport
|
||||||
|
Bug #7908: Key bindings names in the settings menu are layout-specific
|
||||||
|
Bug #7943: Using "addSoulGem" and "dropSoulGem" commands to creatures works only with "Weapon & Shield" flagged ones
|
||||||
Feature #2566: Handle NAM9 records for manual cell references
|
Feature #2566: Handle NAM9 records for manual cell references
|
||||||
Feature #3537: Shader-based water ripples
|
Feature #3537: Shader-based water ripples
|
||||||
Feature #5173: Support for NiFogProperty
|
Feature #5173: Support for NiFogProperty
|
||||||
Feature #5492: Let rain and snow collide with statics
|
Feature #5492: Let rain and snow collide with statics
|
||||||
Feature #6149: Dehardcode Lua API_REVISION
|
Feature #5926: Refraction based on water depth
|
||||||
|
Feature #5944: Option to use camera as sound listener
|
||||||
Feature #6152: Playing music via lua scripts
|
Feature #6152: Playing music via lua scripts
|
||||||
Feature #6188: Specular lighting from point light sources
|
Feature #6188: Specular lighting from point light sources
|
||||||
Feature #6411: Support translations in openmw-launcher
|
Feature #6411: Support translations in openmw-launcher
|
||||||
Feature #6447: Add LOD support to Object Paging
|
Feature #6447: Add LOD support to Object Paging
|
||||||
Feature #6491: Add support for Qt6
|
Feature #6491: Add support for Qt6
|
||||||
Feature #6556: Lua API for sounds
|
Feature #6556: Lua API for sounds
|
||||||
|
Feature #6679: Design a custom Input Action API
|
||||||
Feature #6726: Lua API for creating new objects
|
Feature #6726: Lua API for creating new objects
|
||||||
|
Feature #6727: Lua API for records of all object types
|
||||||
Feature #6864: Lua file access API
|
Feature #6864: Lua file access API
|
||||||
Feature #6922: Improve launcher appearance
|
Feature #6922: Improve launcher appearance
|
||||||
Feature #6933: Support high-resolution cursor textures
|
Feature #6933: Support high-resolution cursor textures
|
||||||
@ -164,16 +198,19 @@
|
|||||||
Feature #7125: Remembering console commands between sessions
|
Feature #7125: Remembering console commands between sessions
|
||||||
Feature #7129: Add support for non-adaptive VSync
|
Feature #7129: Add support for non-adaptive VSync
|
||||||
Feature #7130: Ability to set MyGUI logging verbosity
|
Feature #7130: Ability to set MyGUI logging verbosity
|
||||||
|
Feature #7142: MWScript Lua API
|
||||||
Feature #7148: Optimize string literal lookup in mwscript
|
Feature #7148: Optimize string literal lookup in mwscript
|
||||||
|
Feature #7161: OpenMW-CS: Make adding and filtering TopicInfos easier
|
||||||
Feature #7194: Ori to show texture paths
|
Feature #7194: Ori to show texture paths
|
||||||
Feature #7214: Searching in the in-game console
|
Feature #7214: Searching in the in-game console
|
||||||
Feature #7284: Searching in the console with regex and toggleable case-sensitivity
|
Feature #7248: Searching in the console with regex and toggleable case-sensitivity
|
||||||
Feature #7468: Factions API for Lua
|
Feature #7468: Factions API for Lua
|
||||||
Feature #7477: NegativeLight Magic Effect flag
|
Feature #7477: NegativeLight Magic Effect flag
|
||||||
Feature #7499: OpenMW-CS: Generate record filters by drag & dropping cell content to the filters field
|
Feature #7499: OpenMW-CS: Generate record filters by drag & dropping cell content to the filters field
|
||||||
Feature #7546: Start the game on Fredas
|
Feature #7546: Start the game on Fredas
|
||||||
Feature #7554: Controller binding for tab for menu navigation
|
Feature #7554: Controller binding for tab for menu navigation
|
||||||
Feature #7568: Uninterruptable scripted music
|
Feature #7568: Uninterruptable scripted music
|
||||||
|
Feature #7590: [Lua] Ability to deserialize YAML data from scripts
|
||||||
Feature #7606: Launcher: allow Shift-select in Archives tab
|
Feature #7606: Launcher: allow Shift-select in Archives tab
|
||||||
Feature #7608: Make the missing dependencies warning when loading a savegame more helpful
|
Feature #7608: Make the missing dependencies warning when loading a savegame more helpful
|
||||||
Feature #7618: Show the player character's health in the save details
|
Feature #7618: Show the player character's health in the save details
|
||||||
@ -183,11 +220,20 @@
|
|||||||
Feature #7652: Sort inactive post processing shaders list properly
|
Feature #7652: Sort inactive post processing shaders list properly
|
||||||
Feature #7698: Implement sAbsorb, sDamage, sDrain, sFortify and sRestore
|
Feature #7698: Implement sAbsorb, sDamage, sDrain, sFortify and sRestore
|
||||||
Feature #7709: Improve resolution selection in Launcher
|
Feature #7709: Improve resolution selection in Launcher
|
||||||
|
Feature #7777: Support external Bethesda material files (BGSM/BGEM)
|
||||||
Feature #7792: Support Timescale Clouds
|
Feature #7792: Support Timescale Clouds
|
||||||
Feature #7795: Support MaxNumberRipples INI setting
|
Feature #7795: Support MaxNumberRipples INI setting
|
||||||
Feature #7805: Lua Menu context
|
Feature #7805: Lua Menu context
|
||||||
|
Feature #7860: Lua: Expose NPC AI settings (fight, alarm, flee)
|
||||||
|
Feature #7875: Disable MyGUI windows snapping
|
||||||
|
Feature #7914: Do not allow to move GUI windows out of screen
|
||||||
|
Feature #7923: Don't show non-existent higher ranks for factions with fewer than 9 ranks
|
||||||
|
Feature #7932: Support two-channel normal maps
|
||||||
Task #5896: Do not use deprecated MyGUI properties
|
Task #5896: Do not use deprecated MyGUI properties
|
||||||
|
Task #6085: Replace boost::filesystem with std::filesystem
|
||||||
|
Task #6149: Dehardcode Lua API_REVISION
|
||||||
Task #6624: Drop support for saves made prior to 0.45
|
Task #6624: Drop support for saves made prior to 0.45
|
||||||
|
Task #7048: Get rid of std::bind
|
||||||
Task #7113: Move from std::atoi to std::from_char
|
Task #7113: Move from std::atoi to std::from_char
|
||||||
Task #7117: Replace boost::scoped_array with std::vector
|
Task #7117: Replace boost::scoped_array with std::vector
|
||||||
Task #7151: Do not use std::strerror to get errno error message
|
Task #7151: Do not use std::strerror to get errno error message
|
||||||
|
@ -22,7 +22,7 @@ declare -a CMAKE_CONF_OPTS=(
|
|||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
-DCMAKE_INSTALL_PREFIX=install
|
-DCMAKE_INSTALL_PREFIX=install
|
||||||
-DBUILD_SHARED_LIBS=OFF
|
-DBUILD_SHARED_LIBS="${BUILD_SHARED_LIBS:-OFF}"
|
||||||
-DUSE_SYSTEM_TINYXML=ON
|
-DUSE_SYSTEM_TINYXML=ON
|
||||||
-DOPENMW_USE_SYSTEM_RECASTNAVIGATION=ON
|
-DOPENMW_USE_SYSTEM_RECASTNAVIGATION=ON
|
||||||
-DOPENMW_CXX_FLAGS="-Werror -Werror=implicit-fallthrough" # flags specific to OpenMW project
|
-DOPENMW_CXX_FLAGS="-Werror -Werror=implicit-fallthrough" # flags specific to OpenMW project
|
||||||
|
@ -347,6 +347,26 @@ add_qt_style_dlls() {
|
|||||||
QT_STYLES[$CONFIG]="${QT_STYLES[$CONFIG]} $@"
|
QT_STYLES[$CONFIG]="${QT_STYLES[$CONFIG]} $@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare -A QT_IMAGEFORMATS
|
||||||
|
QT_IMAGEFORMATS["Release"]=""
|
||||||
|
QT_IMAGEFORMATS["Debug"]=""
|
||||||
|
QT_IMAGEFORMATS["RelWithDebInfo"]=""
|
||||||
|
add_qt_image_dlls() {
|
||||||
|
local CONFIG=$1
|
||||||
|
shift
|
||||||
|
QT_IMAGEFORMATS[$CONFIG]="${QT_IMAGEFORMATS[$CONFIG]} $@"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare -A QT_ICONENGINES
|
||||||
|
QT_ICONENGINES["Release"]=""
|
||||||
|
QT_ICONENGINES["Debug"]=""
|
||||||
|
QT_ICONENGINES["RelWithDebInfo"]=""
|
||||||
|
add_qt_icon_dlls() {
|
||||||
|
local CONFIG=$1
|
||||||
|
shift
|
||||||
|
QT_ICONENGINES[$CONFIG]="${QT_ICONENGINES[$CONFIG]} $@"
|
||||||
|
}
|
||||||
|
|
||||||
if [ -z $PLATFORM ]; then
|
if [ -z $PLATFORM ]; then
|
||||||
PLATFORM="$(uname -m)"
|
PLATFORM="$(uname -m)"
|
||||||
fi
|
fi
|
||||||
@ -528,8 +548,12 @@ if ! [ -z $UNITY_BUILD ]; then
|
|||||||
add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
|
add_cmake_opts "-DOPENMW_UNITY_BUILD=True"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [ -z $USE_CCACHE ]; then
|
if [ -n "$USE_CCACHE" ]; then
|
||||||
add_cmake_opts "-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
|
if [ -n "$NMAKE" ] || [ -n "$NINJA" ]; then
|
||||||
|
add_cmake_opts "-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DPRECOMPILE_HEADERS_WITH_MSVC=OFF"
|
||||||
|
else
|
||||||
|
echo "Ignoring -C (CCache) as it is incompatible with Visual Studio CMake generators"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# turn on LTO by default
|
# turn on LTO by default
|
||||||
@ -549,7 +573,7 @@ ICU_VER="70_1"
|
|||||||
LUAJIT_VER="v2.1.0-beta3-452-g7a0cf5fd"
|
LUAJIT_VER="v2.1.0-beta3-452-g7a0cf5fd"
|
||||||
LZ4_VER="1.9.2"
|
LZ4_VER="1.9.2"
|
||||||
OPENAL_VER="1.23.0"
|
OPENAL_VER="1.23.0"
|
||||||
QT_VER="5.15.2"
|
QT_VER="6.6.2"
|
||||||
|
|
||||||
OSG_ARCHIVE_NAME="OSGoS 3.6.5"
|
OSG_ARCHIVE_NAME="OSGoS 3.6.5"
|
||||||
OSG_ARCHIVE="OSGoS-3.6.5-123-g68c5c573d-msvc${OSG_MSVC_YEAR}-win${BITS}"
|
OSG_ARCHIVE="OSGoS-3.6.5-123-g68c5c573d-msvc${OSG_MSVC_YEAR}-win${BITS}"
|
||||||
@ -880,7 +904,7 @@ printf "Qt ${QT_VER}... "
|
|||||||
printf "Exists. "
|
printf "Exists. "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
pushd "$DEPS" > /dev/null
|
pushd "$DEPS" > /dev/null
|
||||||
AQT_VERSION="v3.1.7"
|
AQT_VERSION="v3.1.12"
|
||||||
if ! [ -f "aqt_x64-${AQT_VERSION}.exe" ]; then
|
if ! [ -f "aqt_x64-${AQT_VERSION}.exe" ]; then
|
||||||
download "aqt ${AQT_VERSION}"\
|
download "aqt ${AQT_VERSION}"\
|
||||||
"https://github.com/miurahr/aqtinstall/releases/download/${AQT_VERSION}/aqt_x64.exe" \
|
"https://github.com/miurahr/aqtinstall/releases/download/${AQT_VERSION}/aqt_x64.exe" \
|
||||||
@ -901,6 +925,9 @@ printf "Qt ${QT_VER}... "
|
|||||||
echo Done.
|
echo Done.
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
QT_MAJOR_VER=$(echo "${QT_VER}" | awk -F '[.]' '{printf "%d", $1}')
|
||||||
|
QT_MINOR_VER=$(echo "${QT_VER}" | awk -F '[.]' '{printf "%d", $2}')
|
||||||
|
|
||||||
cd $QT_SDK
|
cd $QT_SDK
|
||||||
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
for CONFIGURATION in ${CONFIGURATIONS[@]}; do
|
||||||
if [ $CONFIGURATION == "Debug" ]; then
|
if [ $CONFIGURATION == "Debug" ]; then
|
||||||
@ -908,13 +935,24 @@ printf "Qt ${QT_VER}... "
|
|||||||
else
|
else
|
||||||
DLLSUFFIX=""
|
DLLSUFFIX=""
|
||||||
fi
|
fi
|
||||||
if [ "${QT_VER:0:1}" -eq "6" ]; then
|
|
||||||
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,OpenGLWidgets,Widgets}${DLLSUFFIX}.dll
|
if [ "${QT_MAJOR_VER}" -eq 6 ]; then
|
||||||
|
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_MAJOR_VER}"{Core,Gui,Network,OpenGL,OpenGLWidgets,Widgets,Svg}${DLLSUFFIX}.dll
|
||||||
|
|
||||||
|
# Since Qt 6.7.0 plugin is called "qmodernwindowsstyle"
|
||||||
|
if [ "${QT_MINOR_VER}" -ge 7 ]; then
|
||||||
|
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qmodernwindowsstyle${DLLSUFFIX}.dll"
|
||||||
|
else
|
||||||
|
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll
|
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_MAJOR_VER}"{Core,Gui,Network,OpenGL,Widgets,Svg}${DLLSUFFIX}.dll
|
||||||
|
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
||||||
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
add_qt_image_dlls $CONFIGURATION "$(pwd)/plugins/imageformats/qsvg${DLLSUFFIX}.dll"
|
||||||
|
add_qt_icon_dlls $CONFIGURATION "$(pwd)/plugins/iconengines/qsvgicon${DLLSUFFIX}.dll"
|
||||||
done
|
done
|
||||||
echo Done.
|
echo Done.
|
||||||
}
|
}
|
||||||
@ -1109,6 +1147,20 @@ fi
|
|||||||
cp "$DLL" "${DLL_PREFIX}styles"
|
cp "$DLL" "${DLL_PREFIX}styles"
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
|
echo "- Qt Image Format DLLs..."
|
||||||
|
mkdir -p ${DLL_PREFIX}imageformats
|
||||||
|
for DLL in ${QT_IMAGEFORMATS[$CONFIGURATION]}; do
|
||||||
|
echo " $(basename $DLL)"
|
||||||
|
cp "$DLL" "${DLL_PREFIX}imageformats"
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
echo "- Qt Icon Engine DLLs..."
|
||||||
|
mkdir -p ${DLL_PREFIX}iconengines
|
||||||
|
for DLL in ${QT_ICONENGINES[$CONFIGURATION]}; do
|
||||||
|
echo " $(basename $DLL)"
|
||||||
|
cp "$DLL" "${DLL_PREFIX}iconengines"
|
||||||
|
done
|
||||||
|
echo
|
||||||
done
|
done
|
||||||
#fi
|
#fi
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ set -o pipefail
|
|||||||
|
|
||||||
LUPDATE="${LUPDATE:-lupdate}"
|
LUPDATE="${LUPDATE:-lupdate}"
|
||||||
|
|
||||||
${LUPDATE:?} apps/wizard -ts files/lang/wizard_*.ts
|
${LUPDATE:?} -locations none apps/wizard -ts files/lang/wizard_*.ts
|
||||||
${LUPDATE:?} apps/launcher -ts files/lang/launcher_*.ts
|
${LUPDATE:?} -locations none apps/launcher -ts files/lang/launcher_*.ts
|
||||||
${LUPDATE:?} components/contentselector components/process -ts files/lang/components_*.ts
|
${LUPDATE:?} -locations none components/contentselector components/process -ts files/lang/components_*.ts
|
||||||
|
|
||||||
! (git diff --name-only | grep -q "^") || (echo -e "\033[0;31mBuild a 'translations' CMake target to update Qt localization for these files:\033[0;0m"; git diff --name-only | xargs -i echo -e "\033[0;31m{}\033[0;0m"; exit -1)
|
! (git diff --name-only | grep -q "^") || (echo -e "\033[0;31mBuild a 'translations' CMake target to update Qt localization for these files:\033[0;0m"; git diff --name-only | xargs -i echo -e "\033[0;31m{}\033[0;0m"; exit -1)
|
||||||
|
@ -20,6 +20,7 @@ apps/openmw_test_suite/lua/test_storage.cpp
|
|||||||
apps/openmw_test_suite/lua/test_ui_content.cpp
|
apps/openmw_test_suite/lua/test_ui_content.cpp
|
||||||
apps/openmw_test_suite/lua/test_utilpackage.cpp
|
apps/openmw_test_suite/lua/test_utilpackage.cpp
|
||||||
apps/openmw_test_suite/lua/test_inputactions.cpp
|
apps/openmw_test_suite/lua/test_inputactions.cpp
|
||||||
|
apps/openmw_test_suite/lua/test_yaml.cpp
|
||||||
apps/openmw_test_suite/misc/test_endianness.cpp
|
apps/openmw_test_suite/misc/test_endianness.cpp
|
||||||
apps/openmw_test_suite/misc/test_resourcehelpers.cpp
|
apps/openmw_test_suite/misc/test_resourcehelpers.cpp
|
||||||
apps/openmw_test_suite/misc/test_stringops.cpp
|
apps/openmw_test_suite/misc/test_stringops.cpp
|
||||||
|
@ -36,7 +36,7 @@ declare -rA GROUPED_DEPS=(
|
|||||||
libsdl2-dev libqt5opengl5-dev qttools5-dev qttools5-dev-tools libopenal-dev
|
libsdl2-dev libqt5opengl5-dev qttools5-dev qttools5-dev-tools libopenal-dev
|
||||||
libunshield-dev libtinyxml-dev libbullet-dev liblz4-dev libpng-dev libjpeg-dev
|
libunshield-dev libtinyxml-dev libbullet-dev liblz4-dev libpng-dev libjpeg-dev
|
||||||
libluajit-5.1-dev librecast-dev libsqlite3-dev ca-certificates libicu-dev
|
libluajit-5.1-dev librecast-dev libsqlite3-dev ca-certificates libicu-dev
|
||||||
libyaml-cpp-dev
|
libyaml-cpp-dev libqt5svg5 libqt5svg5-dev
|
||||||
"
|
"
|
||||||
|
|
||||||
# These dependencies can alternatively be built and linked statically.
|
# These dependencies can alternatively be built and linked statically.
|
||||||
|
122
CMakeLists.txt
122
CMakeLists.txt
@ -19,6 +19,14 @@ if(OPENMW_GL4ES_MANUAL_INIT)
|
|||||||
add_definitions(-DOPENMW_GL4ES_MANUAL_INIT)
|
add_definitions(-DOPENMW_GL4ES_MANUAL_INIT)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (APPLE OR WIN32)
|
||||||
|
set(DEPLOY_QT_TRANSLATIONS_DEFAULT ON)
|
||||||
|
else ()
|
||||||
|
set(DEPLOY_QT_TRANSLATIONS_DEFAULT OFF)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
option(DEPLOY_QT_TRANSLATIONS "Deploy standard Qt translations to resources folder. Needed when OpenMW applications are deployed with Qt libraries" ${DEPLOY_QT_TRANSLATIONS_DEFAULT})
|
||||||
|
|
||||||
# Apps and tools
|
# Apps and tools
|
||||||
option(BUILD_OPENMW "Build OpenMW" ON)
|
option(BUILD_OPENMW "Build OpenMW" ON)
|
||||||
option(BUILD_LAUNCHER "Build Launcher" ON)
|
option(BUILD_LAUNCHER "Build Launcher" ON)
|
||||||
@ -36,6 +44,7 @@ option(BUILD_BENCHMARKS "Build benchmarks with Google Benchmark" OFF)
|
|||||||
option(BUILD_NAVMESHTOOL "Build navmesh tool" ON)
|
option(BUILD_NAVMESHTOOL "Build navmesh tool" ON)
|
||||||
option(BUILD_BULLETOBJECTTOOL "Build Bullet object tool" ON)
|
option(BUILD_BULLETOBJECTTOOL "Build Bullet object tool" ON)
|
||||||
option(BUILD_OPENCS_TESTS "Build OpenMW Construction Set tests" OFF)
|
option(BUILD_OPENCS_TESTS "Build OpenMW Construction Set tests" OFF)
|
||||||
|
option(PRECOMPILE_HEADERS_WITH_MSVC "Precompile most common used headers with MSVC (alternative to ccache)" ON)
|
||||||
|
|
||||||
set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 and up.
|
set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 and up.
|
||||||
|
|
||||||
@ -72,7 +81,7 @@ message(STATUS "Configuring OpenMW...")
|
|||||||
set(OPENMW_VERSION_MAJOR 0)
|
set(OPENMW_VERSION_MAJOR 0)
|
||||||
set(OPENMW_VERSION_MINOR 49)
|
set(OPENMW_VERSION_MINOR 49)
|
||||||
set(OPENMW_VERSION_RELEASE 0)
|
set(OPENMW_VERSION_RELEASE 0)
|
||||||
set(OPENMW_LUA_API_REVISION 53)
|
set(OPENMW_LUA_API_REVISION 59)
|
||||||
set(OPENMW_POSTPROCESSING_API_REVISION 1)
|
set(OPENMW_POSTPROCESSING_API_REVISION 1)
|
||||||
|
|
||||||
set(OPENMW_VERSION_COMMITHASH "")
|
set(OPENMW_VERSION_COMMITHASH "")
|
||||||
@ -81,7 +90,7 @@ set(OPENMW_VERSION_COMMITDATE "")
|
|||||||
|
|
||||||
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||||
|
|
||||||
set(OPENMW_DOC_BASEURL "https://openmw.readthedocs.io/en/stable/")
|
set(OPENMW_DOC_BASEURL "https://openmw.readthedocs.io/en/")
|
||||||
|
|
||||||
set(GIT_CHECKOUT FALSE)
|
set(GIT_CHECKOUT FALSE)
|
||||||
if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
||||||
@ -182,6 +191,22 @@ if (MSVC)
|
|||||||
add_compile_options(/bigobj)
|
add_compile_options(/bigobj)
|
||||||
|
|
||||||
add_compile_options(/Zc:__cplusplus)
|
add_compile_options(/Zc:__cplusplus)
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_LAUNCHER OR CMAKE_C_COMPILER_LAUNCHER)
|
||||||
|
if (CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
|
message(STATUS "A compiler launcher was specified, but will be unused by the current generator (${CMAKE_GENERATOR})")
|
||||||
|
else()
|
||||||
|
foreach (config_lower ${CMAKE_CONFIGURATION_TYPES})
|
||||||
|
string(TOUPPER "${config_lower}" config)
|
||||||
|
if (CMAKE_C_COMPILER_LAUNCHER STREQUAL "ccache")
|
||||||
|
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_${config} "${CMAKE_C_FLAGS_${config}}")
|
||||||
|
endif()
|
||||||
|
if (CMAKE_CXX_COMPILER_LAUNCHER STREQUAL "ccache")
|
||||||
|
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_${config} "${CMAKE_CXX_FLAGS_${config}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set up common paths
|
# Set up common paths
|
||||||
@ -209,7 +234,7 @@ else()
|
|||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
option(USE_DEBUG_CONSOLE "whether a debug console should be enabled for debug builds, if false debug output is redirected to Visual Studio output" ON)
|
option(USE_DEBUG_CONSOLE "Whether a console should be displayed if OpenMW isn't launched from the command line. Does not affect the Release configuration." ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
@ -224,9 +249,9 @@ find_package(LZ4 REQUIRED)
|
|||||||
if (USE_QT)
|
if (USE_QT)
|
||||||
find_package(QT REQUIRED COMPONENTS Core NAMES Qt6 Qt5)
|
find_package(QT REQUIRED COMPONENTS Core NAMES Qt6 Qt5)
|
||||||
if (QT_VERSION_MAJOR VERSION_EQUAL 5)
|
if (QT_VERSION_MAJOR VERSION_EQUAL 5)
|
||||||
find_package(Qt5 5.15 COMPONENTS Core Widgets Network OpenGL LinguistTools REQUIRED)
|
find_package(Qt5 5.15 COMPONENTS Core Widgets Network OpenGL LinguistTools Svg REQUIRED)
|
||||||
else()
|
else()
|
||||||
find_package(Qt6 COMPONENTS Core Widgets Network OpenGL OpenGLWidgets LinguistTools REQUIRED)
|
find_package(Qt6 COMPONENTS Core Widgets Network OpenGL OpenGLWidgets LinguistTools Svg REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "Using Qt${QT_VERSION}")
|
message(STATUS "Using Qt${QT_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
@ -685,9 +710,8 @@ if (WIN32)
|
|||||||
if (USE_DEBUG_CONSOLE AND BUILD_OPENMW)
|
if (USE_DEBUG_CONSOLE AND BUILD_OPENMW)
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
|
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
|
||||||
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_CONSOLE>)
|
|
||||||
elseif (BUILD_OPENMW)
|
elseif (BUILD_OPENMW)
|
||||||
# Turn off debug console, debug output will be written to visual studio output instead
|
# Turn off implicit console, you won't see stdout unless launching OpenMW from a command line shell or look at openmw.log
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS")
|
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS")
|
||||||
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS")
|
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS")
|
||||||
endif()
|
endif()
|
||||||
@ -710,67 +734,66 @@ if (WIN32)
|
|||||||
)
|
)
|
||||||
|
|
||||||
foreach(d ${WARNINGS_DISABLE})
|
foreach(d ${WARNINGS_DISABLE})
|
||||||
set(WARNINGS "${WARNINGS} /wd${d}")
|
list(APPEND WARNINGS "/wd${d}")
|
||||||
endforeach(d)
|
endforeach(d)
|
||||||
|
|
||||||
if(OPENMW_MSVC_WERROR)
|
if(OPENMW_MSVC_WERROR)
|
||||||
set(WARNINGS "${WARNINGS} /WX")
|
list(APPEND WARNINGS "/WX")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(components PRIVATE ${WARNINGS})
|
||||||
set_target_properties(osg-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(osg-ffmpeg-videoplayer PRIVATE ${WARNINGS})
|
||||||
|
|
||||||
if (MSVC_VERSION GREATER_EQUAL 1915 AND MSVC_VERSION LESS 1920)
|
if (MSVC_VERSION GREATER_EQUAL 1915 AND MSVC_VERSION LESS 1920)
|
||||||
target_compile_definitions(components INTERFACE _ENABLE_EXTENDED_ALIGNED_STORAGE)
|
target_compile_definitions(components INTERFACE _ENABLE_EXTENDED_ALIGNED_STORAGE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_BSATOOL)
|
if (BUILD_BSATOOL)
|
||||||
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(bsatool PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_ESMTOOL)
|
if (BUILD_ESMTOOL)
|
||||||
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(esmtool PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_ESSIMPORTER)
|
if (BUILD_ESSIMPORTER)
|
||||||
set_target_properties(openmw-essimporter PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw-essimporter PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_LAUNCHER)
|
if (BUILD_LAUNCHER)
|
||||||
set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw-launcher PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_MWINIIMPORTER)
|
if (BUILD_MWINIIMPORTER)
|
||||||
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw-iniimporter PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_OPENCS)
|
if (BUILD_OPENCS)
|
||||||
set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw-cs PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_OPENMW)
|
if (BUILD_OPENMW)
|
||||||
set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_WIZARD)
|
if (BUILD_WIZARD)
|
||||||
set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw-wizard PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_UNITTESTS)
|
if (BUILD_UNITTESTS)
|
||||||
set_target_properties(openmw_test_suite PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw_test_suite PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_BENCHMARKS)
|
if (BUILD_BENCHMARKS)
|
||||||
set_target_properties(openmw_detournavigator_navmeshtilescache_benchmark PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw_detournavigator_navmeshtilescache_benchmark PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_NAVMESHTOOL)
|
if (BUILD_NAVMESHTOOL)
|
||||||
set_target_properties(openmw-navmeshtool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
target_compile_options(openmw-navmeshtool PRIVATE ${WARNINGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_BULLETOBJECTTOOL)
|
if (BUILD_BULLETOBJECTTOOL)
|
||||||
set(WARNINGS "${WARNINGS} ${MT_BUILD}")
|
target_compile_options(openmw-bulletobjecttool PRIVATE ${WARNINGS} ${MT_BUILD})
|
||||||
set_target_properties(openmw-bulletobjecttool PROPERTIES COMPILE_FLAGS "${WARNINGS}")
|
|
||||||
endif()
|
endif()
|
||||||
endif(MSVC)
|
endif(MSVC)
|
||||||
|
|
||||||
@ -802,6 +825,18 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE)
|
|||||||
get_filename_component(QT_QMACSTYLE_PLUGIN_NAME "${QT_QMACSTYLE_PLUGIN_PATH}" NAME)
|
get_filename_component(QT_QMACSTYLE_PLUGIN_NAME "${QT_QMACSTYLE_PLUGIN_PATH}" NAME)
|
||||||
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
||||||
|
|
||||||
|
get_property(QT_QSVG_PLUGIN_PATH TARGET Qt${QT_VERSION_MAJOR}::QSvgPlugin PROPERTY LOCATION_RELEASE)
|
||||||
|
get_filename_component(QT_QSVG_PLUGIN_DIR "${QT_QSVG_PLUGIN_PATH}" DIRECTORY)
|
||||||
|
get_filename_component(QT_QSVG_PLUGIN_GROUP "${QT_QSVG_PLUGIN_DIR}" NAME)
|
||||||
|
get_filename_component(QT_QSVG_PLUGIN_NAME "${QT_QSVG_PLUGIN_PATH}" NAME)
|
||||||
|
configure_file("${QT_QSVG_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_QSVG_PLUGIN_GROUP}/${QT_QSVG_PLUGIN_NAME}" COPYONLY)
|
||||||
|
|
||||||
|
get_property(QT_QSVG_ICON_PLUGIN_PATH TARGET Qt${QT_VERSION_MAJOR}::QSvgIconPlugin PROPERTY LOCATION_RELEASE)
|
||||||
|
get_filename_component(QT_QSVG_ICON_PLUGIN_DIR "${QT_QSVG_ICON_PLUGIN_PATH}" DIRECTORY)
|
||||||
|
get_filename_component(QT_QSVG_ICON_PLUGIN_GROUP "${QT_QSVG_ICON_PLUGIN_DIR}" NAME)
|
||||||
|
get_filename_component(QT_QSVG_ICON_PLUGIN_NAME "${QT_QSVG_ICON_PLUGIN_PATH}" NAME)
|
||||||
|
configure_file("${QT_QSVG_ICON_PLUGIN_PATH}" "${APP_BUNDLE_DIR}/Contents/PlugIns/${QT_QSVG_ICON_PLUGIN_GROUP}/${QT_QSVG_ICON_PLUGIN_NAME}" COPYONLY)
|
||||||
|
|
||||||
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${APP_BUNDLE_DIR}/Contents/Resources/qt.conf" COPYONLY)
|
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${APP_BUNDLE_DIR}/Contents/Resources/qt.conf" COPYONLY)
|
||||||
|
|
||||||
if (BUILD_OPENCS)
|
if (BUILD_OPENCS)
|
||||||
@ -809,6 +844,8 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE)
|
|||||||
set(OPENCS_BUNDLE_NAME "${OPENCS_BUNDLE_NAME_TMP}.app")
|
set(OPENCS_BUNDLE_NAME "${OPENCS_BUNDLE_NAME_TMP}.app")
|
||||||
configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
configure_file("${QT_COCOA_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_COCOA_PLUGIN_GROUP}/${QT_COCOA_PLUGIN_NAME}" COPYONLY)
|
||||||
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
configure_file("${QT_QMACSTYLE_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QMACSTYLE_PLUGIN_GROUP}/${QT_QMACSTYLE_PLUGIN_NAME}" COPYONLY)
|
||||||
|
configure_file("${QT_QSVG_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QSVG_PLUGIN_GROUP}/${QT_QSVG_PLUGIN_NAME}" COPYONLY)
|
||||||
|
configure_file("${QT_QSVG_ICON_PLUGIN_PATH}" "${OPENCS_BUNDLE_NAME}/Contents/PlugIns/${QT_QSVG_ICON_PLUGIN_GROUP}/${QT_QSVG_ICON_PLUGIN_NAME}" COPYONLY)
|
||||||
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${OPENCS_BUNDLE_NAME}/Contents/Resources/qt.conf" COPYONLY)
|
configure_file("${OpenMW_SOURCE_DIR}/files/mac/qt.conf" "${OPENCS_BUNDLE_NAME}/Contents/Resources/qt.conf" COPYONLY)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@ -1082,30 +1119,30 @@ if (USE_QT)
|
|||||||
file(GLOB COMPONENTS_TS_FILES ${CMAKE_SOURCE_DIR}/files/lang/components_*.ts)
|
file(GLOB COMPONENTS_TS_FILES ${CMAKE_SOURCE_DIR}/files/lang/components_*.ts)
|
||||||
get_target_property(QT_LUPDATE_EXECUTABLE Qt::lupdate IMPORTED_LOCATION)
|
get_target_property(QT_LUPDATE_EXECUTABLE Qt::lupdate IMPORTED_LOCATION)
|
||||||
add_custom_target(translations
|
add_custom_target(translations
|
||||||
COMMAND ${QT_LUPDATE_EXECUTABLE} ${CMAKE_SOURCE_DIR}/components/contentselector ${CMAKE_SOURCE_DIR}/components/process -ts ${COMPONENTS_TS_FILES}
|
COMMAND ${QT_LUPDATE_EXECUTABLE} -locations none ${CMAKE_SOURCE_DIR}/components/contentselector ${CMAKE_SOURCE_DIR}/components/process -ts ${COMPONENTS_TS_FILES}
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/components
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/components
|
||||||
VERBATIM
|
VERBATIM
|
||||||
COMMAND_EXPAND_LISTS
|
COMMAND_EXPAND_LISTS
|
||||||
|
|
||||||
COMMAND ${QT_LUPDATE_EXECUTABLE} ${CMAKE_SOURCE_DIR}/apps/wizard -ts ${WIZARD_TS_FILES}
|
COMMAND ${QT_LUPDATE_EXECUTABLE} -locations none ${CMAKE_SOURCE_DIR}/apps/wizard -ts ${WIZARD_TS_FILES}
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/apps/wizard
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/apps/wizard
|
||||||
VERBATIM
|
VERBATIM
|
||||||
COMMAND_EXPAND_LISTS
|
COMMAND_EXPAND_LISTS
|
||||||
|
|
||||||
COMMAND ${QT_LUPDATE_EXECUTABLE} ${CMAKE_SOURCE_DIR}/apps/launcher -ts ${LAUNCHER_TS_FILES}
|
COMMAND ${QT_LUPDATE_EXECUTABLE} -locations none ${CMAKE_SOURCE_DIR}/apps/launcher -ts ${LAUNCHER_TS_FILES}
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/apps/launcher
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/apps/launcher
|
||||||
VERBATIM
|
VERBATIM
|
||||||
COMMAND_EXPAND_LISTS)
|
COMMAND_EXPAND_LISTS)
|
||||||
|
|
||||||
if (BUILD_LAUNCHER OR BUILD_WIZARD)
|
if (BUILD_LAUNCHER OR BUILD_WIZARD)
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(QT_TRANSLATIONS_PATH "${APP_BUNDLE_DIR}/Contents/Resources/resources/translations")
|
set(QT_OPENMW_TRANSLATIONS_PATH "${APP_BUNDLE_DIR}/Contents/Resources/resources/translations")
|
||||||
else ()
|
else ()
|
||||||
get_generator_is_multi_config(multi_config)
|
get_generator_is_multi_config(multi_config)
|
||||||
if (multi_config)
|
if (multi_config)
|
||||||
set(QT_TRANSLATIONS_PATH "${OpenMW_BINARY_DIR}/$<CONFIG>/resources/translations")
|
set(QT_OPENMW_TRANSLATIONS_PATH "${OpenMW_BINARY_DIR}/$<CONFIG>/resources/translations")
|
||||||
else ()
|
else ()
|
||||||
set(QT_TRANSLATIONS_PATH "${OpenMW_BINARY_DIR}/resources/translations")
|
set(QT_OPENMW_TRANSLATIONS_PATH "${OpenMW_BINARY_DIR}/resources/translations")
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@ -1121,9 +1158,30 @@ if (USE_QT)
|
|||||||
|
|
||||||
qt_add_translation(QM_FILES ${TS_FILES} OPTIONS -silent)
|
qt_add_translation(QM_FILES ${TS_FILES} OPTIONS -silent)
|
||||||
|
|
||||||
|
if (DEPLOY_QT_TRANSLATIONS)
|
||||||
|
# Once we set a Qt 6.2.0 as a minimum required version, we may use "qtpaths --qt-query" instead.
|
||||||
|
get_target_property(QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
|
||||||
|
execute_process(COMMAND "${QT_QMAKE_EXECUTABLE}" -query QT_INSTALL_TRANSLATIONS
|
||||||
|
OUTPUT_VARIABLE QT_TRANSLATIONS_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
|
foreach(QM_FILE ${QM_FILES})
|
||||||
|
get_filename_component(QM_BASENAME ${QM_FILE} NAME)
|
||||||
|
string(REGEX REPLACE "[^_]+_(.*)\\.qm" "\\1" LANG_NAME ${QM_BASENAME})
|
||||||
|
if (EXISTS "${QT_TRANSLATIONS_DIR}/qtbase_${LANG_NAME}.qm")
|
||||||
|
set(QM_FILES ${QM_FILES} "${QT_TRANSLATIONS_DIR}/qtbase_${LANG_NAME}.qm")
|
||||||
|
elseif (EXISTS "${QT_TRANSLATIONS_DIR}/qt_${LANG_NAME}.qm")
|
||||||
|
set(QM_FILES ${QM_FILES} "${QT_TRANSLATIONS_DIR}/qt_${LANG_NAME}.qm")
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR "Qt translations for '${LANG_NAME}' locale are not found in the '${QT_TRANSLATIONS_DIR}' folder.")
|
||||||
|
endif ()
|
||||||
|
endforeach(QM_FILE)
|
||||||
|
|
||||||
|
list(REMOVE_DUPLICATES QM_FILES)
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_custom_target(qm-files
|
add_custom_target(qm-files
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${QT_TRANSLATIONS_PATH}
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${QT_OPENMW_TRANSLATIONS_PATH}
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QM_FILES} ${QT_TRANSLATIONS_PATH}
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QM_FILES} ${QT_OPENMW_TRANSLATIONS_PATH}
|
||||||
DEPENDS ${QM_FILES}
|
DEPENDS ${QM_FILES}
|
||||||
COMMENT "Copy *.qm files to resources folder")
|
COMMENT "Copy *.qm files to resources folder")
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -20,7 +20,7 @@ Font Licenses:
|
|||||||
Current Status
|
Current Status
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
The main quests in Morrowind, Tribunal and Bloodmoon are all completable. Some issues with side quests are to be expected (but rare). Check the [bug tracker](https://gitlab.com/OpenMW/openmw/issues?label_name%5B%5D=1.0) for a list of issues we need to resolve before the "1.0" release. Even before the "1.0" release however, OpenMW boasts some new [features](https://wiki.openmw.org/index.php?title=Features), such as improved graphics and user interfaces.
|
The main quests in Morrowind, Tribunal and Bloodmoon are all completable. Some issues with side quests are to be expected (but rare). Check the [bug tracker](https://gitlab.com/OpenMW/openmw/-/issues/?milestone_title=openmw-1.0) for a list of issues we need to resolve before the "1.0" release. Even before the "1.0" release however, OpenMW boasts some new [features](https://wiki.openmw.org/index.php?title=Features), such as improved graphics and user interfaces.
|
||||||
|
|
||||||
Pre-existing modifications created for the original Morrowind engine can be hit-and-miss. The OpenMW script compiler performs more thorough error-checking than Morrowind does, meaning that a mod created for Morrowind may not necessarily run in OpenMW. Some mods also rely on quirky behaviour or engine bugs in order to work. We are considering such compatibility issues on a case-by-case basis - in some cases adding a workaround to OpenMW may be feasible, in other cases fixing the mod will be the only option. If you know of any mods that work or don't work, feel free to add them to the [Mod status](https://wiki.openmw.org/index.php?title=Mod_status) wiki page.
|
Pre-existing modifications created for the original Morrowind engine can be hit-and-miss. The OpenMW script compiler performs more thorough error-checking than Morrowind does, meaning that a mod created for Morrowind may not necessarily run in OpenMW. Some mods also rely on quirky behaviour or engine bugs in order to work. We are considering such compatibility issues on a case-by-case basis - in some cases adding a workaround to OpenMW may be feasible, in other cases fixing the mod will be the only option. If you know of any mods that work or don't work, feel free to add them to the [Mod status](https://wiki.openmw.org/index.php?title=Mod_status) wiki page.
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ if (UNIX AND NOT APPLE)
|
|||||||
target_link_libraries(openmw_detournavigator_navmeshtilescache_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(openmw_detournavigator_navmeshtilescache_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw_detournavigator_navmeshtilescache_benchmark PRIVATE <algorithm>)
|
target_precompile_headers(openmw_detournavigator_navmeshtilescache_benchmark PRIVATE <algorithm>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ namespace
|
|||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
const auto& key = keys[n++ % keys.size()];
|
const auto& key = keys[n++ % keys.size()];
|
||||||
const auto result = cache.get(key.mAgentBounds, key.mTilePosition, key.mRecastMesh);
|
auto result = cache.get(key.mAgentBounds, key.mTilePosition, key.mRecastMesh);
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ namespace
|
|||||||
while (state.KeepRunning())
|
while (state.KeepRunning())
|
||||||
{
|
{
|
||||||
const auto& key = keys[n++ % keys.size()];
|
const auto& key = keys[n++ % keys.size()];
|
||||||
const auto result = cache.set(
|
auto result = cache.set(
|
||||||
key.mAgentBounds, key.mTilePosition, key.mRecastMesh, std::make_unique<PreparedNavMeshData>());
|
key.mAgentBounds, key.mTilePosition, key.mRecastMesh, std::make_unique<PreparedNavMeshData>());
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ if (UNIX AND NOT APPLE)
|
|||||||
target_link_libraries(openmw_esm_refid_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(openmw_esm_refid_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw_esm_refid_benchmark PRIVATE <algorithm>)
|
target_precompile_headers(openmw_esm_refid_benchmark PRIVATE <algorithm>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ if (UNIX AND NOT APPLE)
|
|||||||
target_link_libraries(openmw_settings_access_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(openmw_settings_access_benchmark ${CMAKE_THREAD_LIBS_INIT})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw_settings_access_benchmark PRIVATE <algorithm>)
|
target_precompile_headers(openmw_settings_access_benchmark PRIVATE <algorithm>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace
|
|||||||
{
|
{
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
static const float v = Settings::Manager::getFloat("sky blending start", "Fog");
|
static float v = Settings::Manager::getFloat("sky blending start", "Fog");
|
||||||
benchmark::DoNotOptimize(v);
|
benchmark::DoNotOptimize(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,8 +47,8 @@ namespace
|
|||||||
{
|
{
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
static const float v1 = Settings::Manager::getFloat("near clip", "Camera");
|
static float v1 = Settings::Manager::getFloat("near clip", "Camera");
|
||||||
static const bool v2 = Settings::Manager::getBool("transparent postpass", "Post Processing");
|
static bool v2 = Settings::Manager::getBool("transparent postpass", "Post Processing");
|
||||||
benchmark::DoNotOptimize(v1);
|
benchmark::DoNotOptimize(v1);
|
||||||
benchmark::DoNotOptimize(v2);
|
benchmark::DoNotOptimize(v2);
|
||||||
}
|
}
|
||||||
@ -58,9 +58,9 @@ namespace
|
|||||||
{
|
{
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
static const float v1 = Settings::Manager::getFloat("near clip", "Camera");
|
static float v1 = Settings::Manager::getFloat("near clip", "Camera");
|
||||||
static const bool v2 = Settings::Manager::getBool("transparent postpass", "Post Processing");
|
static bool v2 = Settings::Manager::getBool("transparent postpass", "Post Processing");
|
||||||
static const int v3 = Settings::Manager::getInt("reflection detail", "Water");
|
static int v3 = Settings::Manager::getInt("reflection detail", "Water");
|
||||||
benchmark::DoNotOptimize(v1);
|
benchmark::DoNotOptimize(v1);
|
||||||
benchmark::DoNotOptimize(v2);
|
benchmark::DoNotOptimize(v2);
|
||||||
benchmark::DoNotOptimize(v3);
|
benchmark::DoNotOptimize(v3);
|
||||||
@ -71,7 +71,8 @@ namespace
|
|||||||
{
|
{
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
benchmark::DoNotOptimize(Settings::fog().mSkyBlendingStart.get());
|
float v = Settings::fog().mSkyBlendingStart.get();
|
||||||
|
benchmark::DoNotOptimize(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +80,10 @@ namespace
|
|||||||
{
|
{
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
benchmark::DoNotOptimize(Settings::postProcessing().mTransparentPostpass.get());
|
bool v1 = Settings::postProcessing().mTransparentPostpass.get();
|
||||||
benchmark::DoNotOptimize(Settings::camera().mNearClip.get());
|
float v2 = Settings::camera().mNearClip.get();
|
||||||
|
benchmark::DoNotOptimize(v1);
|
||||||
|
benchmark::DoNotOptimize(v2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,9 +91,12 @@ namespace
|
|||||||
{
|
{
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
benchmark::DoNotOptimize(Settings::postProcessing().mTransparentPostpass.get());
|
bool v1 = Settings::postProcessing().mTransparentPostpass.get();
|
||||||
benchmark::DoNotOptimize(Settings::camera().mNearClip.get());
|
float v2 = Settings::camera().mNearClip.get();
|
||||||
benchmark::DoNotOptimize(Settings::water().mReflectionDetail.get());
|
int v3 = Settings::water().mReflectionDetail.get();
|
||||||
|
benchmark::DoNotOptimize(v1);
|
||||||
|
benchmark::DoNotOptimize(v2);
|
||||||
|
benchmark::DoNotOptimize(v3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||||||
target_link_libraries(bsatool gcov)
|
target_link_libraries(bsatool gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(bsatool PRIVATE
|
target_precompile_headers(bsatool PRIVATE
|
||||||
<filesystem>
|
<filesystem>
|
||||||
<fstream>
|
<fstream>
|
||||||
|
@ -329,17 +329,19 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
switch (bsaVersion)
|
switch (bsaVersion)
|
||||||
{
|
{
|
||||||
case Bsa::BSAVER_COMPRESSED:
|
case Bsa::BsaVersion::Unknown:
|
||||||
return call<Bsa::CompressedBSAFile>(info);
|
break;
|
||||||
case Bsa::BSAVER_BA2_GNRL:
|
case Bsa::BsaVersion::Uncompressed:
|
||||||
return call<Bsa::BA2GNRLFile>(info);
|
|
||||||
case Bsa::BSAVER_BA2_DX10:
|
|
||||||
return call<Bsa::BA2DX10File>(info);
|
|
||||||
case Bsa::BSAVER_UNCOMPRESSED:
|
|
||||||
return call<Bsa::BSAFile>(info);
|
return call<Bsa::BSAFile>(info);
|
||||||
default:
|
case Bsa::BsaVersion::Compressed:
|
||||||
throw std::runtime_error("Unrecognised BSA archive");
|
return call<Bsa::CompressedBSAFile>(info);
|
||||||
|
case Bsa::BsaVersion::BA2GNRL:
|
||||||
|
return call<Bsa::BA2GNRLFile>(info);
|
||||||
|
case Bsa::BsaVersion::BA2DX10:
|
||||||
|
return call<Bsa::BA2DX10File>(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("Unrecognised BSA archive");
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ if (WIN32)
|
|||||||
install(TARGETS openmw-bulletobjecttool RUNTIME DESTINATION ".")
|
install(TARGETS openmw-bulletobjecttool RUNTIME DESTINATION ".")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw-bulletobjecttool PRIVATE
|
target_precompile_headers(openmw-bulletobjecttool PRIVATE
|
||||||
<string>
|
<string>
|
||||||
<vector>
|
<vector>
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <components/files/multidircollection.hpp>
|
#include <components/files/multidircollection.hpp>
|
||||||
#include <components/misc/strings/conversion.hpp>
|
#include <components/misc/strings/conversion.hpp>
|
||||||
#include <components/platform/platform.hpp>
|
#include <components/platform/platform.hpp>
|
||||||
|
#include <components/resource/bgsmfilemanager.hpp>
|
||||||
#include <components/resource/bulletshape.hpp>
|
#include <components/resource/bulletshape.hpp>
|
||||||
#include <components/resource/bulletshapemanager.hpp>
|
#include <components/resource/bulletshapemanager.hpp>
|
||||||
#include <components/resource/foreachbulletobject.hpp>
|
#include <components/resource/foreachbulletobject.hpp>
|
||||||
@ -146,7 +147,9 @@ namespace
|
|||||||
dataDirs.insert(dataDirs.begin(), resDir / "vfs");
|
dataDirs.insert(dataDirs.begin(), resDir / "vfs");
|
||||||
const Files::Collections fileCollections(dataDirs);
|
const Files::Collections fileCollections(dataDirs);
|
||||||
const auto& archives = variables["fallback-archive"].as<StringsVector>();
|
const auto& archives = variables["fallback-archive"].as<StringsVector>();
|
||||||
const auto& contentFiles = variables["content"].as<StringsVector>();
|
StringsVector contentFiles{ "builtin.omwscripts" };
|
||||||
|
const auto& configContentFiles = variables["content"].as<StringsVector>();
|
||||||
|
contentFiles.insert(contentFiles.end(), configContentFiles.begin(), configContentFiles.end());
|
||||||
|
|
||||||
Fallback::Map::init(variables["fallback"].as<Fallback::FallbackMap>().mMap);
|
Fallback::Map::init(variables["fallback"].as<Fallback::FallbackMap>().mMap);
|
||||||
|
|
||||||
@ -171,7 +174,8 @@ namespace
|
|||||||
constexpr double expiryDelay = 0;
|
constexpr double expiryDelay = 0;
|
||||||
Resource::ImageManager imageManager(&vfs, expiryDelay);
|
Resource::ImageManager imageManager(&vfs, expiryDelay);
|
||||||
Resource::NifFileManager nifFileManager(&vfs, &encoder.getStatelessEncoder());
|
Resource::NifFileManager nifFileManager(&vfs, &encoder.getStatelessEncoder());
|
||||||
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, expiryDelay);
|
Resource::BgsmFileManager bgsmFileManager(&vfs, expiryDelay);
|
||||||
|
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, &bgsmFileManager, expiryDelay);
|
||||||
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager, expiryDelay);
|
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager, expiryDelay);
|
||||||
|
|
||||||
Resource::forEachBulletObject(
|
Resource::forEachBulletObject(
|
||||||
|
@ -25,7 +25,7 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||||||
target_link_libraries(esmtool gcov)
|
target_link_libraries(esmtool gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(esmtool PRIVATE
|
target_precompile_headers(esmtool PRIVATE
|
||||||
<fstream>
|
<fstream>
|
||||||
<string>
|
<string>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "labels.hpp"
|
#include "labels.hpp"
|
||||||
|
|
||||||
|
#include <components/esm3/dialoguecondition.hpp>
|
||||||
|
#include <components/esm3/loadalch.hpp>
|
||||||
#include <components/esm3/loadbody.hpp>
|
#include <components/esm3/loadbody.hpp>
|
||||||
#include <components/esm3/loadcell.hpp>
|
#include <components/esm3/loadcell.hpp>
|
||||||
#include <components/esm3/loadcont.hpp>
|
#include <components/esm3/loadcont.hpp>
|
||||||
@ -571,13 +573,14 @@ std::string_view enchantTypeLabel(int idx)
|
|||||||
|
|
||||||
std::string_view ruleFunction(int idx)
|
std::string_view ruleFunction(int idx)
|
||||||
{
|
{
|
||||||
if (idx >= 0 && idx <= 72)
|
if (idx >= ESM::DialogueCondition::Function_FacReactionLowest
|
||||||
|
&& idx <= ESM::DialogueCondition::Function_PcWerewolfKills)
|
||||||
{
|
{
|
||||||
static constexpr std::string_view ruleFunctions[] = {
|
static constexpr std::string_view ruleFunctions[] = {
|
||||||
"Reaction Low",
|
"Lowest Faction Reaction",
|
||||||
"Reaction High",
|
"Highest Faction Reaction",
|
||||||
"Rank Requirement",
|
"Rank Requirement",
|
||||||
"NPC? Reputation",
|
"NPC Reputation",
|
||||||
"Health Percent",
|
"Health Percent",
|
||||||
"Player Reputation",
|
"Player Reputation",
|
||||||
"NPC Level",
|
"NPC Level",
|
||||||
@ -647,6 +650,7 @@ std::string_view ruleFunction(int idx)
|
|||||||
"Flee",
|
"Flee",
|
||||||
"Should Attack",
|
"Should Attack",
|
||||||
"Werewolf",
|
"Werewolf",
|
||||||
|
"Werewolf Kills",
|
||||||
};
|
};
|
||||||
return ruleFunctions[idx];
|
return ruleFunctions[idx];
|
||||||
}
|
}
|
||||||
@ -987,3 +991,16 @@ std::string recordFlags(uint32_t flags)
|
|||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string potionFlags(int flags)
|
||||||
|
{
|
||||||
|
std::string properties;
|
||||||
|
if (flags == 0)
|
||||||
|
properties += "[None] ";
|
||||||
|
if (flags & ESM::Potion::Autocalc)
|
||||||
|
properties += "Autocalc ";
|
||||||
|
if (flags & (0xFFFFFFFF ^ ESM::Enchantment::Autocalc))
|
||||||
|
properties += "Invalid ";
|
||||||
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
@ -60,6 +60,7 @@ std::string itemListFlags(int flags);
|
|||||||
std::string lightFlags(int flags);
|
std::string lightFlags(int flags);
|
||||||
std::string magicEffectFlags(int flags);
|
std::string magicEffectFlags(int flags);
|
||||||
std::string npcFlags(int flags);
|
std::string npcFlags(int flags);
|
||||||
|
std::string potionFlags(int flags);
|
||||||
std::string raceFlags(int flags);
|
std::string raceFlags(int flags);
|
||||||
std::string spellFlags(int flags);
|
std::string spellFlags(int flags);
|
||||||
std::string weaponFlags(int flags);
|
std::string weaponFlags(int flags);
|
||||||
|
@ -57,112 +57,82 @@ namespace
|
|||||||
std::cout << " Cell Name: " << p.mCellName << std::endl;
|
std::cout << " Cell Name: " << p.mCellName << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ruleString(const ESM::DialInfo::SelectStruct& ss)
|
std::string ruleString(const ESM::DialogueCondition& ss)
|
||||||
{
|
{
|
||||||
std::string rule = ss.mSelectRule;
|
std::string_view type_str = "INVALID";
|
||||||
|
std::string_view func_str;
|
||||||
|
|
||||||
if (rule.length() < 5)
|
switch (ss.mFunction)
|
||||||
return "INVALID";
|
|
||||||
|
|
||||||
char type = rule[1];
|
|
||||||
char indicator = rule[2];
|
|
||||||
|
|
||||||
std::string type_str = "INVALID";
|
|
||||||
std::string func_str = Misc::StringUtils::format("INVALID=%s", rule.substr(1, 3));
|
|
||||||
int func = Misc::StringUtils::toNumeric<int>(rule.substr(2, 2), 0);
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case '1':
|
case ESM::DialogueCondition::Function_Global:
|
||||||
type_str = "Function";
|
type_str = "Global";
|
||||||
func_str = std::string(ruleFunction(func));
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '2':
|
case ESM::DialogueCondition::Function_Local:
|
||||||
if (indicator == 's')
|
type_str = "Local";
|
||||||
type_str = "Global short";
|
func_str = ss.mVariable;
|
||||||
else if (indicator == 'l')
|
|
||||||
type_str = "Global long";
|
|
||||||
else if (indicator == 'f')
|
|
||||||
type_str = "Global float";
|
|
||||||
break;
|
break;
|
||||||
case '3':
|
case ESM::DialogueCondition::Function_Journal:
|
||||||
if (indicator == 's')
|
type_str = "Journal";
|
||||||
type_str = "Local short";
|
func_str = ss.mVariable;
|
||||||
else if (indicator == 'l')
|
|
||||||
type_str = "Local long";
|
|
||||||
else if (indicator == 'f')
|
|
||||||
type_str = "Local float";
|
|
||||||
break;
|
break;
|
||||||
case '4':
|
case ESM::DialogueCondition::Function_Item:
|
||||||
if (indicator == 'J')
|
type_str = "Item count";
|
||||||
type_str = "Journal";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '5':
|
case ESM::DialogueCondition::Function_Dead:
|
||||||
if (indicator == 'I')
|
type_str = "Dead";
|
||||||
type_str = "Item type";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '6':
|
case ESM::DialogueCondition::Function_NotId:
|
||||||
if (indicator == 'D')
|
type_str = "Not ID";
|
||||||
type_str = "NPC Dead";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '7':
|
case ESM::DialogueCondition::Function_NotFaction:
|
||||||
if (indicator == 'X')
|
type_str = "Not Faction";
|
||||||
type_str = "Not ID";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '8':
|
case ESM::DialogueCondition::Function_NotClass:
|
||||||
if (indicator == 'F')
|
type_str = "Not Class";
|
||||||
type_str = "Not Faction";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case '9':
|
case ESM::DialogueCondition::Function_NotRace:
|
||||||
if (indicator == 'C')
|
type_str = "Not Race";
|
||||||
type_str = "Not Class";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case ESM::DialogueCondition::Function_NotCell:
|
||||||
if (indicator == 'R')
|
type_str = "Not Cell";
|
||||||
type_str = "Not Race";
|
func_str = ss.mVariable;
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case ESM::DialogueCondition::Function_NotLocal:
|
||||||
if (indicator == 'L')
|
type_str = "Not Local";
|
||||||
type_str = "Not Cell";
|
func_str = ss.mVariable;
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
if (indicator == 's')
|
|
||||||
type_str = "Not Local";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
type_str = "Function";
|
||||||
|
func_str = ruleFunction(ss.mFunction);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the variable name to the function string if any.
|
std::string_view oper_str = "??";
|
||||||
if (type != '1')
|
switch (ss.mComparison)
|
||||||
func_str = rule.substr(5);
|
|
||||||
|
|
||||||
// In the previous switch, we assumed that the second char was X
|
|
||||||
// for all types not qual to one. If this wasn't true, go back to
|
|
||||||
// the error message.
|
|
||||||
if (type != '1' && rule[3] != 'X')
|
|
||||||
func_str = Misc::StringUtils::format("INVALID=%s", rule.substr(1, 3));
|
|
||||||
|
|
||||||
char oper = rule[4];
|
|
||||||
std::string oper_str = "??";
|
|
||||||
switch (oper)
|
|
||||||
{
|
{
|
||||||
case '0':
|
case ESM::DialogueCondition::Comp_Eq:
|
||||||
oper_str = "==";
|
oper_str = "==";
|
||||||
break;
|
break;
|
||||||
case '1':
|
case ESM::DialogueCondition::Comp_Ne:
|
||||||
oper_str = "!=";
|
oper_str = "!=";
|
||||||
break;
|
break;
|
||||||
case '2':
|
case ESM::DialogueCondition::Comp_Gt:
|
||||||
oper_str = "> ";
|
oper_str = "> ";
|
||||||
break;
|
break;
|
||||||
case '3':
|
case ESM::DialogueCondition::Comp_Ge:
|
||||||
oper_str = ">=";
|
oper_str = ">=";
|
||||||
break;
|
break;
|
||||||
case '4':
|
case ESM::DialogueCondition::Comp_Ls:
|
||||||
oper_str = "< ";
|
oper_str = "< ";
|
||||||
break;
|
break;
|
||||||
case '5':
|
case ESM::DialogueCondition::Comp_Le:
|
||||||
oper_str = "<=";
|
oper_str = "<=";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -170,7 +140,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << ss.mValue;
|
std::visit([&](auto value) { stream << value; }, ss.mValue);
|
||||||
|
|
||||||
std::string result
|
std::string result
|
||||||
= Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str());
|
= Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str());
|
||||||
@ -180,22 +150,23 @@ namespace
|
|||||||
void printEffectList(const ESM::EffectList& effects)
|
void printEffectList(const ESM::EffectList& effects)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const ESM::ENAMstruct& effect : effects.mList)
|
for (const ESM::IndexedENAMstruct& effect : effects.mList)
|
||||||
{
|
{
|
||||||
std::cout << " Effect[" << i << "]: " << magicEffectLabel(effect.mEffectID) << " (" << effect.mEffectID
|
std::cout << " Effect[" << i << "]: " << magicEffectLabel(effect.mData.mEffectID) << " ("
|
||||||
<< ")" << std::endl;
|
<< effect.mData.mEffectID << ")" << std::endl;
|
||||||
if (effect.mSkill != -1)
|
if (effect.mData.mSkill != -1)
|
||||||
std::cout << " Skill: " << skillLabel(effect.mSkill) << " (" << (int)effect.mSkill << ")"
|
std::cout << " Skill: " << skillLabel(effect.mData.mSkill) << " (" << (int)effect.mData.mSkill << ")"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
if (effect.mAttribute != -1)
|
if (effect.mData.mAttribute != -1)
|
||||||
std::cout << " Attribute: " << attributeLabel(effect.mAttribute) << " (" << (int)effect.mAttribute
|
std::cout << " Attribute: " << attributeLabel(effect.mData.mAttribute) << " ("
|
||||||
<< ")" << std::endl;
|
<< (int)effect.mData.mAttribute << ")" << std::endl;
|
||||||
std::cout << " Range: " << rangeTypeLabel(effect.mRange) << " (" << effect.mRange << ")" << std::endl;
|
std::cout << " Range: " << rangeTypeLabel(effect.mData.mRange) << " (" << effect.mData.mRange << ")"
|
||||||
|
<< std::endl;
|
||||||
// Area is always zero if range type is "Self"
|
// Area is always zero if range type is "Self"
|
||||||
if (effect.mRange != ESM::RT_Self)
|
if (effect.mData.mRange != ESM::RT_Self)
|
||||||
std::cout << " Area: " << effect.mArea << std::endl;
|
std::cout << " Area: " << effect.mData.mArea << std::endl;
|
||||||
std::cout << " Duration: " << effect.mDuration << std::endl;
|
std::cout << " Duration: " << effect.mData.mDuration << std::endl;
|
||||||
std::cout << " Magnitude: " << effect.mMagnMin << "-" << effect.mMagnMax << std::endl;
|
std::cout << " Magnitude: " << effect.mData.mMagnMin << "-" << effect.mData.mMagnMax << std::endl;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,7 +450,7 @@ namespace EsmTool
|
|||||||
std::cout << " Script: " << mData.mScript << std::endl;
|
std::cout << " Script: " << mData.mScript << std::endl;
|
||||||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||||
std::cout << " AutoCalc: " << mData.mData.mAutoCalc << std::endl;
|
std::cout << " Flags: " << potionFlags(mData.mData.mFlags) << std::endl;
|
||||||
printEffectList(mData.mEffects);
|
printEffectList(mData.mEffects);
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
@ -612,7 +583,6 @@ namespace EsmTool
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
std::cout << " Map Color: " << Misc::StringUtils::format("0x%08X", mData.mMapColor) << std::endl;
|
std::cout << " Map Color: " << Misc::StringUtils::format("0x%08X", mData.mMapColor) << std::endl;
|
||||||
std::cout << " Water Level Int: " << mData.mWaterInt << std::endl;
|
|
||||||
std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
|
std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
@ -722,9 +692,6 @@ namespace EsmTool
|
|||||||
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
||||||
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
||||||
std::cout << " AI Alarm:" << (int)mData.mAiData.mAlarm << std::endl;
|
std::cout << " AI Alarm:" << (int)mData.mAiData.mAlarm << std::endl;
|
||||||
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
|
||||||
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
|
||||||
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
|
||||||
std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
|
std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
|
||||||
|
|
||||||
for (const ESM::AIPackage& package : mData.mAiPackage.mList)
|
for (const ESM::AIPackage& package : mData.mAiPackage.mList)
|
||||||
@ -843,10 +810,9 @@ namespace EsmTool
|
|||||||
|
|
||||||
std::cout << " Quest Status: " << questStatusLabel(mData.mQuestStatus) << " (" << mData.mQuestStatus << ")"
|
std::cout << " Quest Status: " << questStatusLabel(mData.mQuestStatus) << " (" << mData.mQuestStatus << ")"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout << " Unknown1: " << mData.mData.mUnknown1 << std::endl;
|
std::cout << " Type: " << dialogTypeLabel(mData.mData.mType) << std::endl;
|
||||||
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
|
|
||||||
|
|
||||||
for (const ESM::DialInfo::SelectStruct& rule : mData.mSelects)
|
for (const auto& rule : mData.mSelects)
|
||||||
std::cout << " Select Rule: " << ruleString(rule) << std::endl;
|
std::cout << " Select Rule: " << ruleString(rule) << std::endl;
|
||||||
|
|
||||||
if (!mData.mResultScript.empty())
|
if (!mData.mResultScript.empty())
|
||||||
@ -901,9 +867,6 @@ namespace EsmTool
|
|||||||
if (const ESM::Land::LandData* data = mData.getLandData(mData.mDataTypes))
|
if (const ESM::Land::LandData* data = mData.getLandData(mData.mDataTypes))
|
||||||
{
|
{
|
||||||
std::cout << " Height Offset: " << data->mHeightOffset << std::endl;
|
std::cout << " Height Offset: " << data->mHeightOffset << std::endl;
|
||||||
// Lots of missing members.
|
|
||||||
std::cout << " Unknown1: " << data->mUnk1 << std::endl;
|
|
||||||
std::cout << " Unknown2: " << static_cast<unsigned>(data->mUnk2) << std::endl;
|
|
||||||
}
|
}
|
||||||
mData.unloadData();
|
mData.unloadData();
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
@ -1115,9 +1078,6 @@ namespace EsmTool
|
|||||||
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
|
||||||
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
std::cout << " AI Flee:" << (int)mData.mAiData.mFlee << std::endl;
|
||||||
std::cout << " AI Alarm:" << (int)mData.mAiData.mAlarm << std::endl;
|
std::cout << " AI Alarm:" << (int)mData.mAiData.mAlarm << std::endl;
|
||||||
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
|
|
||||||
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
|
|
||||||
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
|
|
||||||
std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
|
std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
|
||||||
|
|
||||||
for (const ESM::AIPackage& package : mData.mAiPackage.mList)
|
for (const ESM::AIPackage& package : mData.mAiPackage.mList)
|
||||||
@ -1144,7 +1104,6 @@ namespace EsmTool
|
|||||||
std::cout << " Coordinates: (" << point.mX << "," << point.mY << "," << point.mZ << ")" << std::endl;
|
std::cout << " Coordinates: (" << point.mX << "," << point.mY << "," << point.mZ << ")" << std::endl;
|
||||||
std::cout << " Auto-Generated: " << (int)point.mAutogenerated << std::endl;
|
std::cout << " Auto-Generated: " << (int)point.mAutogenerated << std::endl;
|
||||||
std::cout << " Connections: " << (int)point.mConnectionNum << std::endl;
|
std::cout << " Connections: " << (int)point.mConnectionNum << std::endl;
|
||||||
std::cout << " Unknown: " << point.mUnknown << std::endl;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ if (WIN32)
|
|||||||
INSTALL(TARGETS openmw-essimporter RUNTIME DESTINATION ".")
|
INSTALL(TARGETS openmw-essimporter RUNTIME DESTINATION ".")
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw-essimporter PRIVATE
|
target_precompile_headers(openmw-essimporter PRIVATE
|
||||||
<algorithm>
|
<algorithm>
|
||||||
<filesystem>
|
<filesystem>
|
||||||
|
@ -232,7 +232,7 @@ namespace ESSImport
|
|||||||
esm.skip(4);
|
esm.skip(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
esm.getExact(nam8, 32);
|
esm.getT(nam8);
|
||||||
|
|
||||||
newcell.mFogOfWar.reserve(16 * 16);
|
newcell.mFogOfWar.reserve(16 * 16);
|
||||||
for (int x = 0; x < 16; ++x)
|
for (int x = 0; x < 16; ++x)
|
||||||
|
@ -1,10 +1,30 @@
|
|||||||
#include "importcellref.hpp"
|
#include "importcellref.hpp"
|
||||||
|
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
|
#include <components/misc/concepts.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
template <Misc::SameAsWithoutCvref<ACDT> T>
|
||||||
|
void decompose(T&& v, const auto& f)
|
||||||
|
{
|
||||||
|
f(v.mUnknown, v.mFlags, v.mBreathMeter, v.mUnknown2, v.mDynamic, v.mUnknown3, v.mAttributes, v.mMagicEffects,
|
||||||
|
v.mUnknown4, v.mGoldPool, v.mCountDown, v.mUnknown5);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Misc::SameAsWithoutCvref<ACSC> T>
|
||||||
|
void decompose(T&& v, const auto& f)
|
||||||
|
{
|
||||||
|
f(v.mUnknown1, v.mFlags, v.mUnknown2, v.mCorpseClearCountdown, v.mUnknown3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Misc::SameAsWithoutCvref<ANIS> T>
|
||||||
|
void decompose(T&& v, const auto& f)
|
||||||
|
{
|
||||||
|
f(v.mGroupIndex, v.mUnknown, v.mTime);
|
||||||
|
}
|
||||||
|
|
||||||
void CellRef::load(ESM::ESMReader& esm)
|
void CellRef::load(ESM::ESMReader& esm)
|
||||||
{
|
{
|
||||||
@ -45,14 +65,9 @@ namespace ESSImport
|
|||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
ESM::CellRef::loadData(esm, isDeleted);
|
ESM::CellRef::loadData(esm, isDeleted);
|
||||||
|
|
||||||
mActorData.mHasACDT
|
mActorData.mHasACDT = esm.getOptionalComposite("ACDT", mActorData.mACDT);
|
||||||
= esm.getHNOT("ACDT", mActorData.mACDT.mUnknown, mActorData.mACDT.mFlags, mActorData.mACDT.mBreathMeter,
|
|
||||||
mActorData.mACDT.mUnknown2, mActorData.mACDT.mDynamic, mActorData.mACDT.mUnknown3,
|
|
||||||
mActorData.mACDT.mAttributes, mActorData.mACDT.mMagicEffects, mActorData.mACDT.mUnknown4,
|
|
||||||
mActorData.mACDT.mGoldPool, mActorData.mACDT.mCountDown, mActorData.mACDT.mUnknown5);
|
|
||||||
|
|
||||||
mActorData.mHasACSC = esm.getHNOT("ACSC", mActorData.mACSC.mUnknown1, mActorData.mACSC.mFlags,
|
mActorData.mHasACSC = esm.getOptionalComposite("ACSC", mActorData.mACSC);
|
||||||
mActorData.mACSC.mUnknown2, mActorData.mACSC.mCorpseClearCountdown, mActorData.mACSC.mUnknown3);
|
|
||||||
|
|
||||||
if (esm.isNextSub("ACSL"))
|
if (esm.isNextSub("ACSL"))
|
||||||
esm.skipHSubSize(112);
|
esm.skipHSubSize(112);
|
||||||
@ -127,8 +142,7 @@ namespace ESSImport
|
|||||||
if (esm.isNextSub("ND3D"))
|
if (esm.isNextSub("ND3D"))
|
||||||
esm.skipHSub();
|
esm.skipHSub();
|
||||||
|
|
||||||
mActorData.mHasANIS
|
mActorData.mHasANIS = esm.getOptionalComposite("ANIS", mActorData.mANIS);
|
||||||
= esm.getHNOT("ANIS", mActorData.mANIS.mGroupIndex, mActorData.mANIS.mUnknown, mActorData.mANIS.mTime);
|
|
||||||
|
|
||||||
if (esm.isNextSub("LVCR"))
|
if (esm.isNextSub("LVCR"))
|
||||||
{
|
{
|
||||||
@ -146,7 +160,7 @@ namespace ESSImport
|
|||||||
// I've seen DATA *twice* on a creature record, and with the exact same content too! weird
|
// I've seen DATA *twice* on a creature record, and with the exact same content too! weird
|
||||||
// alarmvoi0000.ess
|
// alarmvoi0000.ess
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i)
|
||||||
esm.getHNOT("DATA", mPos.pos, mPos.rot);
|
esm.getOptionalComposite("DATA", mPos);
|
||||||
|
|
||||||
mDeleted = 0;
|
mDeleted = 0;
|
||||||
if (esm.isNextSub("DELE"))
|
if (esm.isNextSub("DELE"))
|
||||||
|
@ -135,7 +135,7 @@ namespace ESSImport
|
|||||||
sub.mFileOffset = esm.getFileOffset();
|
sub.mFileOffset = esm.getFileOffset();
|
||||||
sub.mName = esm.retSubName().toString();
|
sub.mName = esm.retSubName().toString();
|
||||||
sub.mData.resize(esm.getSubSize());
|
sub.mData.resize(esm.getSubSize());
|
||||||
esm.getExact(&sub.mData[0], sub.mData.size());
|
esm.getExact(sub.mData.data(), sub.mData.size());
|
||||||
rec.mSubrecords.push_back(sub);
|
rec.mSubrecords.push_back(sub);
|
||||||
}
|
}
|
||||||
file.mRecords.push_back(rec);
|
file.mRecords.push_back(rec);
|
||||||
|
@ -83,7 +83,7 @@ target_link_libraries(openmw-launcher
|
|||||||
components_qt
|
components_qt
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(openmw-launcher Qt::Widgets Qt::Core)
|
target_link_libraries(openmw-launcher Qt::Widgets Qt::Core Qt::Svg)
|
||||||
|
|
||||||
if (BUILD_WITH_CODE_COVERAGE)
|
if (BUILD_WITH_CODE_COVERAGE)
|
||||||
target_compile_options(openmw-launcher PRIVATE --coverage)
|
target_compile_options(openmw-launcher PRIVATE --coverage)
|
||||||
@ -94,7 +94,7 @@ if(USE_QT)
|
|||||||
set_property(TARGET openmw-launcher PROPERTY AUTOMOC ON)
|
set_property(TARGET openmw-launcher PROPERTY AUTOMOC ON)
|
||||||
endif(USE_QT)
|
endif(USE_QT)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw-launcher PRIVATE
|
target_precompile_headers(openmw-launcher PRIVATE
|
||||||
<boost/program_options/options_description.hpp>
|
<boost/program_options/options_description.hpp>
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ Launcher::DataFilesPage::DataFilesPage(const Files::ConfigurationManager& cfg, C
|
|||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
setObjectName("DataFilesPage");
|
setObjectName("DataFilesPage");
|
||||||
mSelector = new ContentSelectorView::ContentSelector(ui.contentSelectorWidget, /*showOMWScripts=*/true);
|
mSelector = new ContentSelectorView::ContentSelector(ui.contentSelectorWidget, /*showOMWScripts=*/true);
|
||||||
const QString encoding = mGameSettings.value("encoding", "win1252");
|
const QString encoding = mGameSettings.value("encoding", { "win1252" }).value;
|
||||||
mSelector->setEncoding(encoding);
|
mSelector->setEncoding(encoding);
|
||||||
|
|
||||||
QVector<std::pair<QString, QString>> languages = { { "English", tr("English") }, { "French", tr("French") },
|
QVector<std::pair<QString, QString>> languages = { { "English", tr("English") }, { "French", tr("French") },
|
||||||
@ -163,11 +163,11 @@ Launcher::DataFilesPage::DataFilesPage(const Files::ConfigurationManager& cfg, C
|
|||||||
connect(ui.directoryInsertButton, &QPushButton::released, this, [this]() { this->addSubdirectories(false); });
|
connect(ui.directoryInsertButton, &QPushButton::released, this, [this]() { this->addSubdirectories(false); });
|
||||||
connect(ui.directoryUpButton, &QPushButton::released, this, [this]() { this->moveDirectory(-1); });
|
connect(ui.directoryUpButton, &QPushButton::released, this, [this]() { this->moveDirectory(-1); });
|
||||||
connect(ui.directoryDownButton, &QPushButton::released, this, [this]() { this->moveDirectory(1); });
|
connect(ui.directoryDownButton, &QPushButton::released, this, [this]() { this->moveDirectory(1); });
|
||||||
connect(ui.directoryRemoveButton, &QPushButton::released, this, [this]() { this->removeDirectory(); });
|
connect(ui.directoryRemoveButton, &QPushButton::released, this, &DataFilesPage::removeDirectory);
|
||||||
connect(ui.archiveUpButton, &QPushButton::released, this, [this]() { this->moveArchives(-1); });
|
connect(ui.archiveUpButton, &QPushButton::released, this, [this]() { this->moveArchives(-1); });
|
||||||
connect(ui.archiveDownButton, &QPushButton::released, this, [this]() { this->moveArchives(1); });
|
connect(ui.archiveDownButton, &QPushButton::released, this, [this]() { this->moveArchives(1); });
|
||||||
connect(
|
connect(ui.directoryListWidget->model(), &QAbstractItemModel::rowsMoved, this, &DataFilesPage::sortDirectories);
|
||||||
ui.directoryListWidget->model(), &QAbstractItemModel::rowsMoved, this, [this]() { this->sortDirectories(); });
|
connect(ui.archiveListWidget->model(), &QAbstractItemModel::rowsMoved, this, &DataFilesPage::sortArchives);
|
||||||
|
|
||||||
buildView();
|
buildView();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
@ -271,65 +271,79 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
|||||||
ui.archiveListWidget->clear();
|
ui.archiveListWidget->clear();
|
||||||
ui.directoryListWidget->clear();
|
ui.directoryListWidget->clear();
|
||||||
|
|
||||||
QStringList directories = mLauncherSettings.getDataDirectoryList(contentModelName);
|
QList<Config::SettingValue> directories = mGameSettings.getDataDirs();
|
||||||
if (directories.isEmpty())
|
QStringList contentModelDirectories = mLauncherSettings.getDataDirectoryList(contentModelName);
|
||||||
directories = mGameSettings.getDataDirs();
|
if (!contentModelDirectories.isEmpty())
|
||||||
|
{
|
||||||
|
directories.erase(std::remove_if(directories.begin(), directories.end(),
|
||||||
|
[&](const Config::SettingValue& dir) { return mGameSettings.isUserSetting(dir); }),
|
||||||
|
directories.end());
|
||||||
|
for (const auto& dir : contentModelDirectories)
|
||||||
|
directories.push_back({ dir });
|
||||||
|
}
|
||||||
|
|
||||||
mDataLocal = mGameSettings.getDataLocal();
|
mDataLocal = mGameSettings.getDataLocal();
|
||||||
if (!mDataLocal.isEmpty())
|
if (!mDataLocal.isEmpty())
|
||||||
directories.insert(0, mDataLocal);
|
directories.insert(0, { mDataLocal });
|
||||||
|
|
||||||
const auto& globalDataDir = mGameSettings.getGlobalDataDir();
|
const auto& resourcesVfs = mGameSettings.getResourcesVfs();
|
||||||
if (!globalDataDir.empty())
|
if (!resourcesVfs.isEmpty())
|
||||||
directories.insert(0, Files::pathToQString(globalDataDir));
|
directories.insert(0, { resourcesVfs });
|
||||||
|
|
||||||
std::unordered_set<QString> visitedDirectories;
|
std::unordered_set<QString> visitedDirectories;
|
||||||
for (const QString& currentDir : directories)
|
for (const Config::SettingValue& currentDir : directories)
|
||||||
{
|
{
|
||||||
// normalize user supplied directories: resolve symlink, convert to native separator, make absolute
|
if (!visitedDirectories.insert(currentDir.value).second)
|
||||||
const QString canonicalDirPath = QDir(QDir::cleanPath(currentDir)).canonicalPath();
|
|
||||||
|
|
||||||
if (!visitedDirectories.insert(canonicalDirPath).second)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// add new achives files presents in current directory
|
// add new achives files presents in current directory
|
||||||
addArchivesFromDir(currentDir);
|
addArchivesFromDir(currentDir.value);
|
||||||
|
|
||||||
QString tooltip;
|
QStringList tooltip;
|
||||||
|
|
||||||
// add content files presents in current directory
|
// add content files presents in current directory
|
||||||
mSelector->addFiles(currentDir, mNewDataDirs.contains(canonicalDirPath));
|
mSelector->addFiles(currentDir.value, mNewDataDirs.contains(currentDir.value));
|
||||||
|
|
||||||
// add current directory to list
|
// add current directory to list
|
||||||
ui.directoryListWidget->addItem(currentDir);
|
ui.directoryListWidget->addItem(currentDir.originalRepresentation);
|
||||||
auto row = ui.directoryListWidget->count() - 1;
|
auto row = ui.directoryListWidget->count() - 1;
|
||||||
auto* item = ui.directoryListWidget->item(row);
|
auto* item = ui.directoryListWidget->item(row);
|
||||||
|
item->setData(Qt::UserRole, QVariant::fromValue(currentDir));
|
||||||
|
|
||||||
|
if (currentDir.value != currentDir.originalRepresentation)
|
||||||
|
tooltip << tr("Resolved as %1").arg(currentDir.value);
|
||||||
|
|
||||||
// Display new content with custom formatting
|
// Display new content with custom formatting
|
||||||
if (mNewDataDirs.contains(canonicalDirPath))
|
if (mNewDataDirs.contains(currentDir.value))
|
||||||
{
|
{
|
||||||
tooltip += tr("Will be added to the current profile");
|
tooltip << tr("Will be added to the current profile");
|
||||||
QFont font = item->font();
|
QFont font = item->font();
|
||||||
font.setBold(true);
|
font.setBold(true);
|
||||||
font.setItalic(true);
|
font.setItalic(true);
|
||||||
item->setFont(font);
|
item->setFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deactivate data-local and global data directory: they are always included
|
// deactivate data-local and resources/vfs: they are always included
|
||||||
if (currentDir == mDataLocal || Files::pathFromQString(currentDir) == globalDataDir)
|
// same for ones from non-user config files
|
||||||
|
if (currentDir.value == mDataLocal || currentDir.value == resourcesVfs
|
||||||
|
|| !mGameSettings.isUserSetting(currentDir))
|
||||||
{
|
{
|
||||||
auto flags = item->flags();
|
auto flags = item->flags();
|
||||||
item->setFlags(flags & ~(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled));
|
item->setFlags(flags & ~(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled));
|
||||||
|
if (currentDir.value == mDataLocal)
|
||||||
|
tooltip << tr("This is the data-local directory and cannot be disabled");
|
||||||
|
else if (currentDir.value == resourcesVfs)
|
||||||
|
tooltip << tr("This directory is part of OpenMW and cannot be disabled");
|
||||||
|
else
|
||||||
|
tooltip << tr("This directory is enabled in an openmw.cfg other than the user one");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a "data file" icon if the directory contains a content file
|
// Add a "data file" icon if the directory contains a content file
|
||||||
if (mSelector->containsDataFiles(currentDir))
|
if (mSelector->containsDataFiles(currentDir.value))
|
||||||
{
|
{
|
||||||
item->setIcon(QIcon(":/images/openmw-plugin.png"));
|
item->setIcon(QIcon(":/images/openmw-plugin.png"));
|
||||||
if (!tooltip.isEmpty())
|
|
||||||
tooltip += "\n";
|
|
||||||
|
|
||||||
tooltip += tr("Contains content file(s)");
|
tooltip << tr("Contains content file(s)");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -339,19 +353,26 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
|||||||
auto emptyIcon = QIcon(pixmap);
|
auto emptyIcon = QIcon(pixmap);
|
||||||
item->setIcon(emptyIcon);
|
item->setIcon(emptyIcon);
|
||||||
}
|
}
|
||||||
item->setToolTip(tooltip);
|
item->setToolTip(tooltip.join('\n'));
|
||||||
}
|
}
|
||||||
mSelector->sortFiles();
|
mSelector->sortFiles();
|
||||||
|
|
||||||
QStringList selectedArchives = mLauncherSettings.getArchiveList(contentModelName);
|
QList<Config::SettingValue> selectedArchives = mGameSettings.getArchiveList();
|
||||||
if (selectedArchives.isEmpty())
|
QStringList contentModelSelectedArchives = mLauncherSettings.getArchiveList(contentModelName);
|
||||||
selectedArchives = mGameSettings.getArchiveList();
|
if (contentModelSelectedArchives.isEmpty())
|
||||||
|
{
|
||||||
|
selectedArchives.erase(std::remove_if(selectedArchives.begin(), selectedArchives.end(),
|
||||||
|
[&](const Config::SettingValue& dir) { return mGameSettings.isUserSetting(dir); }),
|
||||||
|
selectedArchives.end());
|
||||||
|
for (const auto& dir : contentModelSelectedArchives)
|
||||||
|
selectedArchives.push_back({ dir });
|
||||||
|
}
|
||||||
|
|
||||||
// sort and tick BSA according to profile
|
// sort and tick BSA according to profile
|
||||||
int row = 0;
|
int row = 0;
|
||||||
for (const auto& archive : selectedArchives)
|
for (const auto& archive : selectedArchives)
|
||||||
{
|
{
|
||||||
const auto match = ui.archiveListWidget->findItems(archive, Qt::MatchExactly);
|
const auto match = ui.archiveListWidget->findItems(archive.value, Qt::MatchExactly);
|
||||||
if (match.isEmpty())
|
if (match.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
const auto name = match[0]->text();
|
const auto name = match[0]->text();
|
||||||
@ -359,9 +380,25 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
|||||||
ui.archiveListWidget->takeItem(oldrow);
|
ui.archiveListWidget->takeItem(oldrow);
|
||||||
ui.archiveListWidget->insertItem(row, name);
|
ui.archiveListWidget->insertItem(row, name);
|
||||||
ui.archiveListWidget->item(row)->setCheckState(Qt::Checked);
|
ui.archiveListWidget->item(row)->setCheckState(Qt::Checked);
|
||||||
|
ui.archiveListWidget->item(row)->setData(Qt::UserRole, QVariant::fromValue(archive));
|
||||||
|
if (!mGameSettings.isUserSetting(archive))
|
||||||
|
{
|
||||||
|
auto flags = ui.archiveListWidget->item(row)->flags();
|
||||||
|
ui.archiveListWidget->item(row)->setFlags(
|
||||||
|
flags & ~(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled));
|
||||||
|
ui.archiveListWidget->item(row)->setToolTip(
|
||||||
|
tr("This archive is enabled in an openmw.cfg other than the user one"));
|
||||||
|
}
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList nonUserContent;
|
||||||
|
for (const auto& content : mGameSettings.getContentList())
|
||||||
|
{
|
||||||
|
if (!mGameSettings.isUserSetting(content))
|
||||||
|
nonUserContent.push_back(content.value);
|
||||||
|
}
|
||||||
|
mSelector->setNonUserContent(nonUserContent);
|
||||||
mSelector->setProfileContent(mLauncherSettings.getContentListFiles(contentModelName));
|
mSelector->setProfileContent(mLauncherSettings.getContentListFiles(contentModelName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +426,19 @@ void Launcher::DataFilesPage::saveSettings(const QString& profile)
|
|||||||
{
|
{
|
||||||
fileNames.append(item->fileName());
|
fileNames.append(item->fileName());
|
||||||
}
|
}
|
||||||
mLauncherSettings.setContentList(profileName, dirList, selectedArchivePaths(), fileNames);
|
QStringList dirNames;
|
||||||
|
for (const auto& dir : dirList)
|
||||||
|
{
|
||||||
|
if (mGameSettings.isUserSetting(dir))
|
||||||
|
dirNames.push_back(dir.originalRepresentation);
|
||||||
|
}
|
||||||
|
QStringList archiveNames;
|
||||||
|
for (const auto& archive : selectedArchivePaths())
|
||||||
|
{
|
||||||
|
if (mGameSettings.isUserSetting(archive))
|
||||||
|
archiveNames.push_back(archive.originalRepresentation);
|
||||||
|
}
|
||||||
|
mLauncherSettings.setContentList(profileName, dirNames, archiveNames, fileNames);
|
||||||
mGameSettings.setContentList(dirList, selectedArchivePaths(), fileNames);
|
mGameSettings.setContentList(dirList, selectedArchivePaths(), fileNames);
|
||||||
|
|
||||||
QString language(mSelector->languageBox()->currentData().toString());
|
QString language(mSelector->languageBox()->currentData().toString());
|
||||||
@ -398,38 +447,38 @@ void Launcher::DataFilesPage::saveSettings(const QString& profile)
|
|||||||
|
|
||||||
if (language == QLatin1String("Polish"))
|
if (language == QLatin1String("Polish"))
|
||||||
{
|
{
|
||||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1250"));
|
mGameSettings.setValue(QLatin1String("encoding"), { "win1250" });
|
||||||
}
|
}
|
||||||
else if (language == QLatin1String("Russian"))
|
else if (language == QLatin1String("Russian"))
|
||||||
{
|
{
|
||||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1251"));
|
mGameSettings.setValue(QLatin1String("encoding"), { "win1251" });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252"));
|
mGameSettings.setValue(QLatin1String("encoding"), { "win1252" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList Launcher::DataFilesPage::selectedDirectoriesPaths() const
|
QList<Config::SettingValue> Launcher::DataFilesPage::selectedDirectoriesPaths() const
|
||||||
{
|
{
|
||||||
QStringList dirList;
|
QList<Config::SettingValue> dirList;
|
||||||
for (int i = 0; i < ui.directoryListWidget->count(); ++i)
|
for (int i = 0; i < ui.directoryListWidget->count(); ++i)
|
||||||
{
|
{
|
||||||
const QListWidgetItem* item = ui.directoryListWidget->item(i);
|
const QListWidgetItem* item = ui.directoryListWidget->item(i);
|
||||||
if (item->flags() & Qt::ItemIsEnabled)
|
if (item->flags() & Qt::ItemIsEnabled)
|
||||||
dirList.append(item->text());
|
dirList.append(qvariant_cast<Config::SettingValue>(item->data(Qt::UserRole)));
|
||||||
}
|
}
|
||||||
return dirList;
|
return dirList;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList Launcher::DataFilesPage::selectedArchivePaths() const
|
QList<Config::SettingValue> Launcher::DataFilesPage::selectedArchivePaths() const
|
||||||
{
|
{
|
||||||
QStringList archiveList;
|
QList<Config::SettingValue> archiveList;
|
||||||
for (int i = 0; i < ui.archiveListWidget->count(); ++i)
|
for (int i = 0; i < ui.archiveListWidget->count(); ++i)
|
||||||
{
|
{
|
||||||
const QListWidgetItem* item = ui.archiveListWidget->item(i);
|
const QListWidgetItem* item = ui.archiveListWidget->item(i);
|
||||||
if (item->checkState() == Qt::Checked)
|
if (item->checkState() == Qt::Checked)
|
||||||
archiveList.append(item->text());
|
archiveList.append(qvariant_cast<Config::SettingValue>(item->data(Qt::UserRole)));
|
||||||
}
|
}
|
||||||
return archiveList;
|
return archiveList;
|
||||||
}
|
}
|
||||||
@ -583,7 +632,20 @@ void Launcher::DataFilesPage::on_cloneProfileAction_triggered()
|
|||||||
if (profile.isEmpty())
|
if (profile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mLauncherSettings.setContentList(profile, selectedDirectoriesPaths(), selectedArchivePaths(), selectedFilePaths());
|
const auto& dirList = selectedDirectoriesPaths();
|
||||||
|
QStringList dirNames;
|
||||||
|
for (const auto& dir : dirList)
|
||||||
|
{
|
||||||
|
if (mGameSettings.isUserSetting(dir))
|
||||||
|
dirNames.push_back(dir.originalRepresentation);
|
||||||
|
}
|
||||||
|
QStringList archiveNames;
|
||||||
|
for (const auto& archive : selectedArchivePaths())
|
||||||
|
{
|
||||||
|
if (mGameSettings.isUserSetting(archive))
|
||||||
|
archiveNames.push_back(archive.originalRepresentation);
|
||||||
|
}
|
||||||
|
mLauncherSettings.setContentList(profile, dirNames, archiveNames, selectedFilePaths());
|
||||||
addProfile(profile, true);
|
addProfile(profile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,6 +712,9 @@ void Launcher::DataFilesPage::addSubdirectories(bool append)
|
|||||||
if (!ui.directoryListWidget->findItems(rootPath, Qt::MatchFixedString).isEmpty())
|
if (!ui.directoryListWidget->findItems(rootPath, Qt::MatchFixedString).isEmpty())
|
||||||
return;
|
return;
|
||||||
ui.directoryListWidget->addItem(rootPath);
|
ui.directoryListWidget->addItem(rootPath);
|
||||||
|
auto row = ui.directoryListWidget->count() - 1;
|
||||||
|
auto* item = ui.directoryListWidget->item(row);
|
||||||
|
item->setData(Qt::UserRole, QVariant::fromValue(Config::SettingValue{ rootPath }));
|
||||||
mNewDataDirs.push_back(rootPath);
|
mNewDataDirs.push_back(rootPath);
|
||||||
refreshDataFilesView();
|
refreshDataFilesView();
|
||||||
return;
|
return;
|
||||||
@ -679,8 +744,11 @@ void Launcher::DataFilesPage::addSubdirectories(bool append)
|
|||||||
const auto* dir = select.dirListWidget->item(i);
|
const auto* dir = select.dirListWidget->item(i);
|
||||||
if (dir->checkState() == Qt::Checked)
|
if (dir->checkState() == Qt::Checked)
|
||||||
{
|
{
|
||||||
ui.directoryListWidget->insertItem(selectedRow++, dir->text());
|
ui.directoryListWidget->insertItem(selectedRow, dir->text());
|
||||||
|
auto* item = ui.directoryListWidget->item(selectedRow);
|
||||||
|
item->setData(Qt::UserRole, QVariant::fromValue(Config::SettingValue{ dir->text() }));
|
||||||
mNewDataDirs.push_back(dir->text());
|
mNewDataDirs.push_back(dir->text());
|
||||||
|
++selectedRow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,6 +770,21 @@ void Launcher::DataFilesPage::sortDirectories()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Launcher::DataFilesPage::sortArchives()
|
||||||
|
{
|
||||||
|
// Ensure disabled entries (aka ones from non-user config files) are always at the top.
|
||||||
|
for (auto i = 1; i < ui.archiveListWidget->count(); ++i)
|
||||||
|
{
|
||||||
|
if (!(ui.archiveListWidget->item(i)->flags() & Qt::ItemIsEnabled)
|
||||||
|
&& (ui.archiveListWidget->item(i - 1)->flags() & Qt::ItemIsEnabled))
|
||||||
|
{
|
||||||
|
const auto item = ui.archiveListWidget->takeItem(i);
|
||||||
|
ui.archiveListWidget->insertItem(i - 1, item);
|
||||||
|
ui.archiveListWidget->setCurrentRow(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Launcher::DataFilesPage::moveDirectory(int step)
|
void Launcher::DataFilesPage::moveDirectory(int step)
|
||||||
{
|
{
|
||||||
int selectedRow = ui.directoryListWidget->currentRow();
|
int selectedRow = ui.directoryListWidget->currentRow();
|
||||||
@ -784,9 +867,8 @@ bool Launcher::DataFilesPage::moveArchive(QListWidgetItem* listItem, int step)
|
|||||||
if (selectedRow == -1 || newRow < 0 || newRow > ui.archiveListWidget->count() - 1)
|
if (selectedRow == -1 || newRow < 0 || newRow > ui.archiveListWidget->count() - 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QListWidgetItem* item = ui.archiveListWidget->takeItem(selectedRow);
|
QListWidgetItem* item = ui.archiveListWidget->takeItem(selectedRow);
|
||||||
|
ui.archiveListWidget->insertItem(newRow, item);
|
||||||
addArchive(item->text(), item->checkState(), newRow);
|
|
||||||
ui.archiveListWidget->setCurrentRow(newRow);
|
ui.archiveListWidget->setCurrentRow(newRow);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -797,6 +879,7 @@ void Launcher::DataFilesPage::addArchive(const QString& name, Qt::CheckState sel
|
|||||||
row = ui.archiveListWidget->count();
|
row = ui.archiveListWidget->count();
|
||||||
ui.archiveListWidget->insertItem(row, name);
|
ui.archiveListWidget->insertItem(row, name);
|
||||||
ui.archiveListWidget->item(row)->setCheckState(selected);
|
ui.archiveListWidget->item(row)->setCheckState(selected);
|
||||||
|
ui.archiveListWidget->item(row)->setData(Qt::UserRole, QVariant::fromValue(Config::SettingValue{ name }));
|
||||||
if (mKnownArchives.filter(name).isEmpty()) // XXX why contains doesn't work here ???
|
if (mKnownArchives.filter(name).isEmpty()) // XXX why contains doesn't work here ???
|
||||||
{
|
{
|
||||||
auto item = ui.archiveListWidget->item(row);
|
auto item = ui.archiveListWidget->item(row);
|
||||||
@ -819,7 +902,7 @@ void Launcher::DataFilesPage::addArchivesFromDir(const QString& path)
|
|||||||
for (const auto& fileinfo : dir.entryInfoList(archiveFilter))
|
for (const auto& fileinfo : dir.entryInfoList(archiveFilter))
|
||||||
{
|
{
|
||||||
const auto absPath = fileinfo.absoluteFilePath();
|
const auto absPath = fileinfo.absoluteFilePath();
|
||||||
if (Bsa::BSAFile::detectVersion(Files::pathFromQString(absPath)) == Bsa::BSAVER_UNKNOWN)
|
if (Bsa::BSAFile::detectVersion(Files::pathFromQString(absPath)) == Bsa::BsaVersion::Unknown)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto fileName = fileinfo.fileName();
|
const auto fileName = fileinfo.fileName();
|
||||||
|
@ -25,6 +25,7 @@ namespace ContentSelectorView
|
|||||||
namespace Config
|
namespace Config
|
||||||
{
|
{
|
||||||
class GameSettings;
|
class GameSettings;
|
||||||
|
struct SettingValue;
|
||||||
class LauncherSettings;
|
class LauncherSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ namespace Launcher
|
|||||||
void updateCloneProfileOkButton(const QString& text);
|
void updateCloneProfileOkButton(const QString& text);
|
||||||
void addSubdirectories(bool append);
|
void addSubdirectories(bool append);
|
||||||
void sortDirectories();
|
void sortDirectories();
|
||||||
|
void sortArchives();
|
||||||
void removeDirectory();
|
void removeDirectory();
|
||||||
void moveArchives(int step);
|
void moveArchives(int step);
|
||||||
void moveDirectory(int step);
|
void moveDirectory(int step);
|
||||||
@ -146,8 +148,8 @@ namespace Launcher
|
|||||||
* @return the file paths of all selected content files
|
* @return the file paths of all selected content files
|
||||||
*/
|
*/
|
||||||
QStringList selectedFilePaths() const;
|
QStringList selectedFilePaths() const;
|
||||||
QStringList selectedArchivePaths() const;
|
QList<Config::SettingValue> selectedArchivePaths() const;
|
||||||
QStringList selectedDirectoriesPaths() const;
|
QList<Config::SettingValue> selectedDirectoriesPaths() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,9 +37,9 @@ Launcher::ImportPage::ImportPage(const Files::ConfigurationManager& cfg, Config:
|
|||||||
// Detect Morrowind configuration files
|
// Detect Morrowind configuration files
|
||||||
QStringList iniPaths;
|
QStringList iniPaths;
|
||||||
|
|
||||||
for (const QString& path : mGameSettings.getDataDirs())
|
for (const auto& path : mGameSettings.getDataDirs())
|
||||||
{
|
{
|
||||||
QDir dir(path);
|
QDir dir(path.value);
|
||||||
dir.setPath(dir.canonicalPath()); // Resolve symlinks
|
dir.setPath(dir.canonicalPath()); // Resolve symlinks
|
||||||
|
|
||||||
if (dir.exists(QString("Morrowind.ini")))
|
if (dir.exists(QString("Morrowind.ini")))
|
||||||
@ -125,7 +125,7 @@ void Launcher::ImportPage::on_importerButton_clicked()
|
|||||||
arguments.append(QString("--fonts"));
|
arguments.append(QString("--fonts"));
|
||||||
|
|
||||||
arguments.append(QString("--encoding"));
|
arguments.append(QString("--encoding"));
|
||||||
arguments.append(mGameSettings.value(QString("encoding"), QString("win1252")));
|
arguments.append(mGameSettings.value(QString("encoding"), { "win1252" }).value);
|
||||||
arguments.append(QString("--ini"));
|
arguments.append(QString("--ini"));
|
||||||
arguments.append(settingsComboBox->currentText());
|
arguments.append(settingsComboBox->currentText());
|
||||||
arguments.append(QString("--cfg"));
|
arguments.append(QString("--cfg"));
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QTranslator>
|
|
||||||
|
|
||||||
#include <boost/program_options/options_description.hpp>
|
#include <boost/program_options/options_description.hpp>
|
||||||
#include <boost/program_options/variables_map.hpp>
|
#include <boost/program_options/variables_map.hpp>
|
||||||
@ -9,6 +8,7 @@
|
|||||||
#include <components/debug/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/files/qtconversion.hpp>
|
#include <components/files/qtconversion.hpp>
|
||||||
|
#include <components/l10n/qttranslations.hpp>
|
||||||
#include <components/platform/platform.hpp>
|
#include <components/platform/platform.hpp>
|
||||||
|
|
||||||
#ifdef MAC_OS_X_VERSION_MIN_REQUIRED
|
#ifdef MAC_OS_X_VERSION_MIN_REQUIRED
|
||||||
@ -41,16 +41,7 @@ int runLauncher(int argc, char* argv[])
|
|||||||
resourcesPath = Files::pathToQString(variables["resources"].as<Files::MaybeQuotedPath>().u8string());
|
resourcesPath = Files::pathToQString(variables["resources"].as<Files::MaybeQuotedPath>().u8string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internationalization
|
l10n::installQtTranslations(app, "launcher", resourcesPath);
|
||||||
QString locale = QLocale::system().name().section('_', 0, 0);
|
|
||||||
|
|
||||||
QTranslator appTranslator;
|
|
||||||
appTranslator.load(resourcesPath + "/translations/launcher_" + locale + ".qm");
|
|
||||||
app.installTranslator(&appTranslator);
|
|
||||||
|
|
||||||
QTranslator componentsAppTranslator;
|
|
||||||
componentsAppTranslator.load(resourcesPath + "/translations/components_" + locale + ".qm");
|
|
||||||
app.installTranslator(&componentsAppTranslator);
|
|
||||||
|
|
||||||
Launcher::MainDialog mainWin(configurationManager);
|
Launcher::MainDialog mainWin(configurationManager);
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ bool Launcher::MainDialog::setupLauncherSettings()
|
|||||||
if (!QFile::exists(path))
|
if (!QFile::exists(path))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Log(Debug::Verbose) << "Loading config file: " << path.toUtf8().constData();
|
Log(Debug::Info) << "Loading config file: " << path.toUtf8().constData();
|
||||||
|
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
@ -320,7 +320,7 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||||||
|
|
||||||
QFile file;
|
QFile file;
|
||||||
|
|
||||||
auto loadFile = [&](const QString& path, bool (Config::GameSettings::*reader)(QTextStream&, bool),
|
auto loadFile = [&](const QString& path, bool (Config::GameSettings::*reader)(QTextStream&, const QString&, bool),
|
||||||
bool ignoreContent = false) -> std::optional<bool> {
|
bool ignoreContent = false) -> std::optional<bool> {
|
||||||
file.setFileName(path);
|
file.setFileName(path);
|
||||||
if (file.exists())
|
if (file.exists())
|
||||||
@ -337,7 +337,7 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||||||
QTextStream stream(&file);
|
QTextStream stream(&file);
|
||||||
Misc::ensureUtf8Encoding(stream);
|
Misc::ensureUtf8Encoding(stream);
|
||||||
|
|
||||||
(mGameSettings.*reader)(stream, ignoreContent);
|
(mGameSettings.*reader)(stream, QFileInfo(path).dir().path(), ignoreContent);
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -349,29 +349,24 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||||||
if (!loadFile(Files::getUserConfigPathQString(mCfgMgr), &Config::GameSettings::readUserFile))
|
if (!loadFile(Files::getUserConfigPathQString(mCfgMgr), &Config::GameSettings::readUserFile))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Now the rest - priority: user > local > global
|
for (const auto& path : Files::getActiveConfigPathsQString(mCfgMgr))
|
||||||
if (auto result = loadFile(Files::getLocalConfigPathQString(mCfgMgr), &Config::GameSettings::readFile, true))
|
|
||||||
{
|
{
|
||||||
// Load global if local wasn't found
|
Log(Debug::Info) << "Loading config file: " << path.toUtf8().constData();
|
||||||
if (!*result && !loadFile(Files::getGlobalConfigPathQString(mCfgMgr), &Config::GameSettings::readFile, true))
|
if (!loadFile(path, &Config::GameSettings::readFile))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return false;
|
|
||||||
if (!loadFile(Files::getUserConfigPathQString(mCfgMgr), &Config::GameSettings::readFile))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Launcher::MainDialog::setupGameData()
|
bool Launcher::MainDialog::setupGameData()
|
||||||
{
|
{
|
||||||
QStringList dataDirs;
|
bool foundData = false;
|
||||||
|
|
||||||
// Check if the paths actually contain data files
|
// Check if the paths actually contain data files
|
||||||
for (const QString& path3 : mGameSettings.getDataDirs())
|
for (const auto& path3 : mGameSettings.getDataDirs())
|
||||||
{
|
{
|
||||||
QDir dir(path3);
|
QDir dir(path3.value);
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters << "*.esp"
|
filters << "*.esp"
|
||||||
<< "*.esm"
|
<< "*.esm"
|
||||||
@ -379,10 +374,13 @@ bool Launcher::MainDialog::setupGameData()
|
|||||||
<< "*.omwaddon";
|
<< "*.omwaddon";
|
||||||
|
|
||||||
if (!dir.entryList(filters).isEmpty())
|
if (!dir.entryList(filters).isEmpty())
|
||||||
dataDirs.append(path3);
|
{
|
||||||
|
foundData = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataDirs.isEmpty())
|
if (!foundData)
|
||||||
{
|
{
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle(tr("Error detecting Morrowind installation"));
|
msgBox.setWindowTitle(tr("Error detecting Morrowind installation"));
|
||||||
|
@ -193,8 +193,10 @@ bool Launcher::SettingsPage::loadSettings()
|
|||||||
loadSettingBool(Settings::game().mSmoothMovement, *smoothMovementCheckBox);
|
loadSettingBool(Settings::game().mSmoothMovement, *smoothMovementCheckBox);
|
||||||
loadSettingBool(Settings::game().mPlayerMovementIgnoresAnimation, *playerMovementIgnoresAnimationCheckBox);
|
loadSettingBool(Settings::game().mPlayerMovementIgnoresAnimation, *playerMovementIgnoresAnimationCheckBox);
|
||||||
|
|
||||||
distantLandCheckBox->setCheckState(
|
connect(distantLandCheckBox, &QCheckBox::toggled, this, &SettingsPage::slotDistantLandToggled);
|
||||||
Settings::terrain().mDistantTerrain && Settings::terrain().mObjectPaging ? Qt::Checked : Qt::Unchecked);
|
bool distantLandEnabled = Settings::terrain().mDistantTerrain && Settings::terrain().mObjectPaging;
|
||||||
|
distantLandCheckBox->setCheckState(distantLandEnabled ? Qt::Checked : Qt::Unchecked);
|
||||||
|
slotDistantLandToggled(distantLandEnabled);
|
||||||
|
|
||||||
loadSettingBool(Settings::terrain().mObjectPagingActiveGrid, *activeGridObjectPagingCheckBox);
|
loadSettingBool(Settings::terrain().mObjectPagingActiveGrid, *activeGridObjectPagingCheckBox);
|
||||||
viewingDistanceComboBox->setValue(convertToCells(Settings::camera().mViewingDistance));
|
viewingDistanceComboBox->setValue(convertToCells(Settings::camera().mViewingDistance));
|
||||||
@ -244,6 +246,11 @@ bool Launcher::SettingsPage::loadSettings()
|
|||||||
int shadowResIndex = shadowResolutionComboBox->findText(QString::number(shadowRes));
|
int shadowResIndex = shadowResolutionComboBox->findText(QString::number(shadowRes));
|
||||||
if (shadowResIndex != -1)
|
if (shadowResIndex != -1)
|
||||||
shadowResolutionComboBox->setCurrentIndex(shadowResIndex);
|
shadowResolutionComboBox->setCurrentIndex(shadowResIndex);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shadowResolutionComboBox->addItem(QString::number(shadowRes));
|
||||||
|
shadowResolutionComboBox->setCurrentIndex(shadowResolutionComboBox->count() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
connect(shadowDistanceCheckBox, &QCheckBox::toggled, this, &SettingsPage::slotShadowDistLimitToggled);
|
connect(shadowDistanceCheckBox, &QCheckBox::toggled, this, &SettingsPage::slotShadowDistLimitToggled);
|
||||||
|
|
||||||
@ -295,6 +302,7 @@ bool Launcher::SettingsPage::loadSettings()
|
|||||||
hrtfProfileSelectorComboBox->setCurrentIndex(hrtfProfileIndex);
|
hrtfProfileSelectorComboBox->setCurrentIndex(hrtfProfileIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loadSettingBool(Settings::sound().mCameraListener, *cameraListenerCheckBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface Changes
|
// Interface Changes
|
||||||
@ -338,7 +346,7 @@ bool Launcher::SettingsPage::loadSettings()
|
|||||||
{
|
{
|
||||||
loadSettingBool(Settings::input().mGrabCursor, *grabCursorCheckBox);
|
loadSettingBool(Settings::input().mGrabCursor, *grabCursorCheckBox);
|
||||||
|
|
||||||
bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1;
|
bool skipMenu = mGameSettings.value("skip-menu").value.toInt() == 1;
|
||||||
if (skipMenu)
|
if (skipMenu)
|
||||||
{
|
{
|
||||||
skipMenuCheckBox->setCheckState(Qt::Checked);
|
skipMenuCheckBox->setCheckState(Qt::Checked);
|
||||||
@ -346,8 +354,8 @@ bool Launcher::SettingsPage::loadSettings()
|
|||||||
startDefaultCharacterAtLabel->setEnabled(skipMenu);
|
startDefaultCharacterAtLabel->setEnabled(skipMenu);
|
||||||
startDefaultCharacterAtField->setEnabled(skipMenu);
|
startDefaultCharacterAtField->setEnabled(skipMenu);
|
||||||
|
|
||||||
startDefaultCharacterAtField->setText(mGameSettings.value("start"));
|
startDefaultCharacterAtField->setText(mGameSettings.value("start").value);
|
||||||
runScriptAfterStartupField->setText(mGameSettings.value("script-run"));
|
runScriptAfterStartupField->setText(mGameSettings.value("script-run").value);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -492,6 +500,9 @@ void Launcher::SettingsPage::saveSettings()
|
|||||||
Settings::sound().mHrtf.set(hrtfProfileSelectorComboBox->currentText().toStdString());
|
Settings::sound().mHrtf.set(hrtfProfileSelectorComboBox->currentText().toStdString());
|
||||||
else
|
else
|
||||||
Settings::sound().mHrtf.set({});
|
Settings::sound().mHrtf.set({});
|
||||||
|
|
||||||
|
const bool cCameraListener = cameraListenerCheckBox->checkState() != Qt::Unchecked;
|
||||||
|
Settings::sound().mCameraListener.set(cCameraListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface Changes
|
// Interface Changes
|
||||||
@ -532,17 +543,17 @@ void Launcher::SettingsPage::saveSettings()
|
|||||||
saveSettingBool(*grabCursorCheckBox, Settings::input().mGrabCursor);
|
saveSettingBool(*grabCursorCheckBox, Settings::input().mGrabCursor);
|
||||||
|
|
||||||
int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked;
|
int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked;
|
||||||
if (skipMenu != mGameSettings.value("skip-menu").toInt())
|
if (skipMenu != mGameSettings.value("skip-menu").value.toInt())
|
||||||
mGameSettings.setValue("skip-menu", QString::number(skipMenu));
|
mGameSettings.setValue("skip-menu", { QString::number(skipMenu) });
|
||||||
|
|
||||||
QString startCell = startDefaultCharacterAtField->text();
|
QString startCell = startDefaultCharacterAtField->text();
|
||||||
if (startCell != mGameSettings.value("start"))
|
if (startCell != mGameSettings.value("start").value)
|
||||||
{
|
{
|
||||||
mGameSettings.setValue("start", startCell);
|
mGameSettings.setValue("start", { startCell });
|
||||||
}
|
}
|
||||||
QString scriptRun = runScriptAfterStartupField->text();
|
QString scriptRun = runScriptAfterStartupField->text();
|
||||||
if (scriptRun != mGameSettings.value("script-run"))
|
if (scriptRun != mGameSettings.value("script-run").value)
|
||||||
mGameSettings.setValue("script-run", scriptRun);
|
mGameSettings.setValue("script-run", { scriptRun });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,9 +592,16 @@ void Launcher::SettingsPage::slotShadowDistLimitToggled(bool checked)
|
|||||||
fadeStartSpinBox->setEnabled(checked);
|
fadeStartSpinBox->setEnabled(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Launcher::SettingsPage::slotDistantLandToggled(bool checked)
|
||||||
|
{
|
||||||
|
activeGridObjectPagingCheckBox->setEnabled(checked);
|
||||||
|
objectPagingMinSizeComboBox->setEnabled(checked);
|
||||||
|
}
|
||||||
|
|
||||||
void Launcher::SettingsPage::slotLightTypeCurrentIndexChanged(int index)
|
void Launcher::SettingsPage::slotLightTypeCurrentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
lightsMaximumDistanceSpinBox->setEnabled(index != 0);
|
lightsMaximumDistanceSpinBox->setEnabled(index != 0);
|
||||||
|
lightFadeMultiplierSpinBox->setEnabled(index != 0);
|
||||||
lightsMaxLightsSpinBox->setEnabled(index != 0);
|
lightsMaxLightsSpinBox->setEnabled(index != 0);
|
||||||
lightsBoundingSphereMultiplierSpinBox->setEnabled(index != 0);
|
lightsBoundingSphereMultiplierSpinBox->setEnabled(index != 0);
|
||||||
lightsMinimumInteriorBrightnessSpinBox->setEnabled(index != 0);
|
lightsMinimumInteriorBrightnessSpinBox->setEnabled(index != 0);
|
||||||
|
@ -33,6 +33,7 @@ namespace Launcher
|
|||||||
void slotPostProcessToggled(bool checked);
|
void slotPostProcessToggled(bool checked);
|
||||||
void slotSkyBlendingToggled(bool checked);
|
void slotSkyBlendingToggled(bool checked);
|
||||||
void slotShadowDistLimitToggled(bool checked);
|
void slotShadowDistLimitToggled(bool checked);
|
||||||
|
void slotDistantLandToggled(bool checked);
|
||||||
void slotLightTypeCurrentIndexChanged(int index);
|
void slotLightTypeCurrentIndexChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p>note: content files that are not part of current Content List are <span style=" font-style:italic;font-weight: bold">highlighted</span></p></body></html></string>
|
<string><html><head/><body><p>Note: content files that are not part of current Content List are <span style=" font-style:italic;font-weight: bold">highlighted</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -160,7 +160,7 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p>note: directories that are not part of current Content List are <span style=" font-style:italic;font-weight: bold">highlighted</span></p></body></html></string>
|
<string><html><head/><body><p>Note: directories that are not part of current Content List are <span style=" font-style:italic;font-weight: bold">highlighted</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -251,7 +251,7 @@
|
|||||||
<item row="1" column="0" colspan="2">
|
<item row="1" column="0" colspan="2">
|
||||||
<widget class="QLabel" name="archiveNoteLabel">
|
<widget class="QLabel" name="archiveNoteLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p>note: archives that are not part of current Content List are <span style=" font-style:italic;font-weight: bold">highlighted</span></p></body></html></string>
|
<string><html><head/><body><p>Note: archives that are not part of current Content List are <span style=" font-style:italic;font-weight: bold">highlighted</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -305,7 +305,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="navMeshRemoveUnusedTilesCheckBox">
|
<widget class="QCheckBox" name="navMeshRemoveUnusedTilesCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Remove unused tiles</string>
|
<string>Remove Unused Tiles</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -317,7 +317,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="navMeshMaxSizeLabel">
|
<widget class="QLabel" name="navMeshMaxSizeLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max size</string>
|
<string>Max Size</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="windowModeLabel">
|
<widget class="QLabel" name="windowModeLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Window mode</string>
|
<string>Window Mode</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -111,14 +111,14 @@
|
|||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QCheckBox" name="framerateLimitCheckBox">
|
<widget class="QCheckBox" name="framerateLimitCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Framerate limit</string>
|
<string>Framerate Limit</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="windowBorderCheckBox">
|
<widget class="QCheckBox" name="windowBorderCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Window border</string>
|
<string>Window Border</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -207,14 +207,14 @@
|
|||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="antiAliasingLabel">
|
<widget class="QLabel" name="antiAliasingLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Anti-aliasing</string>
|
<string>Anti-Aliasing</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="vSyncLabel">
|
<widget class="QLabel" name="vSyncLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Vertical synchronization</string>
|
<string>Vertical Synchronization</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="importerLabel">
|
<widget class="QLabel" name="importerLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>File to import settings from:</string>
|
<string>File to Import Settings From:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -73,7 +73,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="addonsCheckBox">
|
<widget class="QCheckBox" name="addonsCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Import add-on and plugin selection (creates a new Content List)</string>
|
<string>Import Add-on and Plugin Selection</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -88,7 +88,7 @@ so OpenMW provides another set of fonts to avoid these issues. These fonts use T
|
|||||||
to default Morrowind fonts. Check this box if you still prefer original fonts over OpenMW ones or if you use custom bitmap fonts.</string>
|
to default Morrowind fonts. Check this box if you still prefer original fonts over OpenMW ones or if you use custom bitmap fonts.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Import bitmap fonts setup</string>
|
<string>Import Bitmap Fonts</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<string><html><head/><body><p>Give actors an ability to swim over the water surface when they follow other actor independently from their ability to swim. Has effect only when nav mesh building is enabled.</p></body></html></string>
|
<string><html><head/><body><p>Give actors an ability to swim over the water surface when they follow other actor independently from their ability to swim. Has effect only when nav mesh building is enabled.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Always allow actors to follow over water</string>
|
<string>Always Allow Actors to Follow over Water</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -49,7 +49,7 @@
|
|||||||
<string><html><head/><body><p>Make disposition change of merchants caused by trading permanent.</p></body></html></string>
|
<string><html><head/><body><p>Make disposition change of merchants caused by trading permanent.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Permanent barter disposition changes</string>
|
<string>Permanent Barter Disposition Changes</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
<string><html><head/><body><p>Don't use race weight in NPC movement speed calculations.</p></body></html></string>
|
<string><html><head/><body><p>Don't use race weight in NPC movement speed calculations.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Racial variation in speed fix</string>
|
<string>Racial Variation in Speed Fix</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -69,7 +69,7 @@
|
|||||||
<string><html><head/><body><p>Stops combat with NPCs affected by Calm spells every frame -- like in Morrowind without the MCP.</p></body></html></string>
|
<string><html><head/><body><p>Stops combat with NPCs affected by Calm spells every frame -- like in Morrowind without the MCP.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Classic Calm spells behavior</string>
|
<string>Classic Calm Spells Behavior</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -79,7 +79,7 @@
|
|||||||
<string><html><head/><body><p>If enabled NPCs apply evasion maneuver to avoid collisions with others.</p></body></html></string>
|
<string><html><head/><body><p>If enabled NPCs apply evasion maneuver to avoid collisions with others.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>NPCs avoid collisions</string>
|
<string>NPCs Avoid Collisions</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -89,7 +89,7 @@
|
|||||||
<string><html><head/><body><p>Make the value of filled soul gems dependent only on soul magnitude.</p></body></html></string>
|
<string><html><head/><body><p>Make the value of filled soul gems dependent only on soul magnitude.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Soulgem values rebalance</string>
|
<string>Soulgem Values Rebalance</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -99,7 +99,7 @@
|
|||||||
<string><html><head/><body><p>If this setting is true, supporting models will make use of day night switch nodes.</p></body></html></string>
|
<string><html><head/><body><p>If this setting is true, supporting models will make use of day night switch nodes.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Day night switch nodes</string>
|
<string>Day Night Switch Nodes</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -109,7 +109,7 @@
|
|||||||
<string><html><head/><body><p>Make player followers and escorters start combat with enemies who have started combat with them or the player. Otherwise they wait for the enemies or the player to do an attack first.</p></body></html></string>
|
<string><html><head/><body><p>Make player followers and escorters start combat with enemies who have started combat with them or the player. Otherwise they wait for the enemies or the player to do an attack first.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Followers defend immediately</string>
|
<string>Followers Defend Immediately</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -119,7 +119,7 @@
|
|||||||
<string><html><head/><body><p><a name="docs-internal-guid-f375b85a-7fff-02ff-a5af-c5cff63923c0"/>When enabled, a navigation mesh is built in the background for world geometry to be used for pathfinding. When disabled only the path grid is used to build paths. Single-core CPU systems may have a big performance impact on existing interior location and moving across the exterior world. May slightly affect performance on multi-core CPU systems. Multi-core CPU systems may have different latency for nav mesh update depending on other settings and system performance. Moving across external world, entering/exiting location produce nav mesh update. NPC and creatures may not be able to find path before nav mesh is built around them. Try to disable this if you want to have old fashioned AI which doesn't know where to go when you stand behind that stone and cast a firebolt.</p></body></html></string>
|
<string><html><head/><body><p><a name="docs-internal-guid-f375b85a-7fff-02ff-a5af-c5cff63923c0"/>When enabled, a navigation mesh is built in the background for world geometry to be used for pathfinding. When disabled only the path grid is used to build paths. Single-core CPU systems may have a big performance impact on existing interior location and moving across the exterior world. May slightly affect performance on multi-core CPU systems. Multi-core CPU systems may have different latency for nav mesh update depending on other settings and system performance. Moving across external world, entering/exiting location produce nav mesh update. NPC and creatures may not be able to find path before nav mesh is built around them. Try to disable this if you want to have old fashioned AI which doesn't know where to go when you stand behind that stone and cast a firebolt.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use navigation mesh for pathfinding</string>
|
<string>Use Navigation Mesh for Pathfinding</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -129,7 +129,7 @@
|
|||||||
<string><html><head/><body><p>If enabled, a magical ammunition is required to bypass normal weapon resistance or weakness. If disabled, a magical ranged weapon or a magical ammunition is required.</p></body></html></string>
|
<string><html><head/><body><p>If enabled, a magical ammunition is required to bypass normal weapon resistance or weakness. If disabled, a magical ranged weapon or a magical ammunition is required.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Only magical ammo bypass resistance</string>
|
<string>Only Magical Ammo Bypass Resistance</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -139,7 +139,7 @@
|
|||||||
<string><html><head/><body><p>If this setting is true, containers supporting graphic herbalism will do so instead of opening the menu.</p></body></html></string>
|
<string><html><head/><body><p>If this setting is true, containers supporting graphic herbalism will do so instead of opening the menu.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Graphic herbalism</string>
|
<string>Graphic Herbalism</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -149,7 +149,7 @@
|
|||||||
<string><html><head/><body><p>Makes player swim a bit upward from the line of sight. Applies only in third person mode. Intended to make simpler swimming without diving.</p></body></html></string>
|
<string><html><head/><body><p>Makes player swim a bit upward from the line of sight. Applies only in third person mode. Intended to make simpler swimming without diving.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Swim upward correction</string>
|
<string>Swim Upward Correction</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -159,7 +159,7 @@
|
|||||||
<string><html><head/><body><p>Make enchanted weapons without Magical flag bypass normal weapons resistance, like in Morrowind.</p></body></html></string>
|
<string><html><head/><body><p>Make enchanted weapons without Magical flag bypass normal weapons resistance, like in Morrowind.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enchanted weapons are magical</string>
|
<string>Enchanted Weapons Are Magical</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -169,7 +169,7 @@
|
|||||||
<string><html><head/><body><p>Prevents merchants from equipping items that are sold to them.</p></body></html></string>
|
<string><html><head/><body><p>Prevents merchants from equipping items that are sold to them.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Merchant equipping fix</string>
|
<string>Merchant Equipping Fix</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -179,7 +179,7 @@
|
|||||||
<string><html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html></string>
|
<string><html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Trainers choose offered skills by base value</string>
|
<string>Trainers Choose Offered Skills by Base Value</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -189,7 +189,7 @@
|
|||||||
<string><html><head/><body><p>If this setting is true, the player is allowed to loot actors (e.g. summoned creatures) during death animation, if they are not in combat. In this case we have to increment death counter and run disposed actor's script instantly.</p><p>If this setting is false, player has to wait until end of death animation in all cases. Makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder. Conflicts with mannequin mods, which use SkipAnim to prevent end of death animation.</p></body></html></string>
|
<string><html><head/><body><p>If this setting is true, the player is allowed to loot actors (e.g. summoned creatures) during death animation, if they are not in combat. In this case we have to increment death counter and run disposed actor's script instantly.</p><p>If this setting is false, player has to wait until end of death animation in all cases. Makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder. Conflicts with mannequin mods, which use SkipAnim to prevent end of death animation.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Can loot during death animation</string>
|
<string>Can Loot During Death Animation</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -199,7 +199,7 @@
|
|||||||
<string><html><head/><body><p>Make stealing items from NPCs that were knocked down possible during combat.</p></body></html></string>
|
<string><html><head/><body><p>Make stealing items from NPCs that were knocked down possible during combat.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Steal from knocked out actors in combat</string>
|
<string>Steal from Knocked out Actors in Combat</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -209,7 +209,7 @@
|
|||||||
<string><html><head/><body><p>Effects of reflected Absorb spells are not mirrored - like in Morrowind.</p></body></html></string>
|
<string><html><head/><body><p>Effects of reflected Absorb spells are not mirrored - like in Morrowind.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Classic reflected Absorb spells behavior</string>
|
<string>Classic Reflected Absorb Spells Behavior</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -219,7 +219,7 @@
|
|||||||
<string><html><head/><body><p>Makes unarmed creature attacks able to reduce armor condition, just as attacks from NPCs and armed creatures.</p></body></html></string>
|
<string><html><head/><body><p>Makes unarmed creature attacks able to reduce armor condition, just as attacks from NPCs and armed creatures.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Unarmed creature attacks damage armor</string>
|
<string>Unarmed Creature Attacks Damage Armor</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -230,7 +230,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="unarmedFactorsStrengthLabel">
|
<widget class="QLabel" name="unarmedFactorsStrengthLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Factor strength into hand-to-hand combat</string>
|
<string>Factor Strength into Hand-to-Hand Combat</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -246,12 +246,12 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Affect werewolves</string>
|
<string>Affect Werewolves</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Do not affect werewolves</string>
|
<string>Do Not Affect Werewolves</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
@ -262,7 +262,7 @@
|
|||||||
<string><html><head/><body><p>How many threads will be spawned to compute physics update in the background. A value of 0 means that the update will be performed in the main thread.</p><p>A value greater than 1 requires the Bullet library be compiled with multithreading support.</p></body></html></string>
|
<string><html><head/><body><p>How many threads will be spawned to compute physics update in the background. A value of 0 means that the update will be performed in the main thread.</p><p>A value greater than 1 requires the Bullet library be compiled with multithreading support.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Background physics threads</string>
|
<string>Background Physics Threads</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -272,7 +272,7 @@
|
|||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="labelActorCollisionShapeType">
|
<widget class="QLabel" name="labelActorCollisionShapeType">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Actor collision shape type</string>
|
<string>Actor Collision Shape Type</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -282,16 +282,16 @@
|
|||||||
<string>Collision is used for both physics simulation and navigation mesh generation for pathfinding. Cylinder gives the best consistency between available navigation paths and ability to move by them. Changing this value affects navigation mesh generation therefore navigation mesh disk cache generated for one value will not be useful with another.</string>
|
<string>Collision is used for both physics simulation and navigation mesh generation for pathfinding. Cylinder gives the best consistency between available navigation paths and ability to move by them. Changing this value affects navigation mesh generation therefore navigation mesh disk cache generated for one value will not be useful with another.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentText">
|
<property name="currentText">
|
||||||
<string>Axis-aligned bounding box</string>
|
<string>Axis-Aligned Bounding Box</string>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Axis-aligned bounding box</string>
|
<string>Axis-Aligned Bounding Box</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Rotating box</string>
|
<string>Rotating Box</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -343,7 +343,7 @@
|
|||||||
<string><html><head/><body><p>Makes NPCs and player movement more smooth. Recommended to use with "turn to movement direction" enabled.</p></body></html></string>
|
<string><html><head/><body><p>Makes NPCs and player movement more smooth. Recommended to use with "turn to movement direction" enabled.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Smooth movement</string>
|
<string>Smooth Movement</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -353,7 +353,7 @@
|
|||||||
<string><html><head/><body><p>Load per-group KF-files and skeleton files from Animations folder</p></body></html></string>
|
<string><html><head/><body><p>Load per-group KF-files and skeleton files from Animations folder</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use additional animation sources</string>
|
<string>Use Additional Animation Sources</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -376,7 +376,7 @@
|
|||||||
<string><html><head/><body><p>Affects side and diagonal movement. Enabling this setting makes movement more realistic.</p><p>If disabled then the whole character's body is pointed to the direction of view. Diagonal movement has no special animation and causes sliding.</p><p>If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it changes straight right and straight left movement as well. Also turns the whole body up or down when swimming according to the movement direction.</p></body></html></string>
|
<string><html><head/><body><p>Affects side and diagonal movement. Enabling this setting makes movement more realistic.</p><p>If disabled then the whole character's body is pointed to the direction of view. Diagonal movement has no special animation and causes sliding.</p><p>If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it changes straight right and straight left movement as well. Also turns the whole body up or down when swimming according to the movement direction.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Turn to movement direction</string>
|
<string>Turn to Movement Direction</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -389,7 +389,7 @@
|
|||||||
<string><html><head/><body><p>Render holstered weapons (with quivers and scabbards), requires modded assets.</p></body></html></string>
|
<string><html><head/><body><p>Render holstered weapons (with quivers and scabbards), requires modded assets.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Weapon sheathing</string>
|
<string>Weapon Sheathing</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -402,7 +402,7 @@
|
|||||||
<string><html><head/><body><p>Render holstered shield, requires modded assets.</p></body></html></string>
|
<string><html><head/><body><p>Render holstered shield, requires modded assets.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Shield sheathing</string>
|
<string>Shield Sheathing</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -412,7 +412,7 @@
|
|||||||
<string><html><head/><body><p>In third person, the camera will sway along with the movement animations of the player. Enabling this option disables this swaying by having the player character move independently of its animation. This was the default behavior of OpenMW 0.48 and earlier.</p></body></html></string>
|
<string><html><head/><body><p>In third person, the camera will sway along with the movement animations of the player. Enabling this option disables this swaying by having the player character move independently of its animation. This was the default behavior of OpenMW 0.48 and earlier.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Player movement ignores animation</string>
|
<string>Player Movement Ignores Animation</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -422,7 +422,7 @@
|
|||||||
<string><html><head/><body><p>Use casting animations for magic items, just as for spells.</p></body></html></string>
|
<string><html><head/><body><p>Use casting animations for magic items, just as for spells.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use magic item animation</string>
|
<string>Use Magic Item Animation</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -447,7 +447,7 @@
|
|||||||
If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file (.nif or .osg file). Affects objects.</p></body></html></string>
|
If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file (.nif or .osg file). Affects objects.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Auto use object normal maps</string>
|
<string>Auto Use Object Normal Maps</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -457,7 +457,7 @@
|
|||||||
<string><html><head/><body><p>Enables soft particles for particle effects. This technique softens the intersection between individual particles and other opaque geometry by blending between them.</p></body></html></string>
|
<string><html><head/><body><p>Enables soft particles for particle effects. This technique softens the intersection between individual particles and other opaque geometry by blending between them.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Soft particles</string>
|
<string>Soft Particles</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -471,7 +471,7 @@
|
|||||||
(.osg file, not supported in .nif files). Affects objects.</p></body></html></string>
|
(.osg file, not supported in .nif files). Affects objects.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Auto use object specular maps</string>
|
<string>Auto Use Object Specular Maps</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -481,7 +481,7 @@
|
|||||||
<string><html><head/><body><p>See 'auto use object normal maps'. Affects terrain.</p></body></html></string>
|
<string><html><head/><body><p>See 'auto use object normal maps'. Affects terrain.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Auto use terrain normal maps</string>
|
<string>Auto Use Terrain Normal Maps</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -504,7 +504,7 @@
|
|||||||
<string><html><head/><body><p>If a file with pattern 'terrain specular map pattern' exists, use that file as a 'diffuse specular' map. The texture must contain the layer colour in the RGB channel (as usual), and a specular multiplier in the alpha channel.</p></body></html></string>
|
<string><html><head/><body><p>If a file with pattern 'terrain specular map pattern' exists, use that file as a 'diffuse specular' map. The texture must contain the layer colour in the RGB channel (as usual), and a specular multiplier in the alpha channel.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Auto use terrain specular maps</string>
|
<string>Auto Use Terrain Specular Maps</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -514,7 +514,7 @@
|
|||||||
<string><html><head/><body><p>Simulate coverage-preserving mipmaps to prevent alpha-tested meshes shrinking as they get further away. Will cause meshes whose textures have coverage-preserving mipmaps to grow, though, so refer to mod installation instructions for how to set this.</p></body></html></string>
|
<string><html><head/><body><p>Simulate coverage-preserving mipmaps to prevent alpha-tested meshes shrinking as they get further away. Will cause meshes whose textures have coverage-preserving mipmaps to grow, though, so refer to mod installation instructions for how to set this.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Adjust coverage for alpha test</string>
|
<string>Adjust Coverage for Alpha Test</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -524,7 +524,7 @@
|
|||||||
<string><html><head/><body><p>Allows MSAA to work with alpha-tested meshes, producing better-looking edges without pixelation. Can negatively impact performance.</p></body></html></string>
|
<string><html><head/><body><p>Allows MSAA to work with alpha-tested meshes, producing better-looking edges without pixelation. Can negatively impact performance.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use anti-alias alpha testing</string>
|
<string>Use Anti-Aliased Alpha Testing</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -537,7 +537,7 @@
|
|||||||
</p></body></html></string>
|
</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bump/reflect map local lighting</string>
|
<string>Bump/Reflect Map Local Lighting</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -547,7 +547,7 @@
|
|||||||
<string><html><head/><body><p>EXPERIMENTAL: Stop rain and snow from falling through overhangs and roofs.</p></body></html></string>
|
<string><html><head/><body><p>EXPERIMENTAL: Stop rain and snow from falling through overhangs and roofs.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Weather particle occlusion</string>
|
<string>Weather Particle Occlusion</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -570,7 +570,7 @@
|
|||||||
<string><html><head/><body><p>Use exponential fog formula. By default, linear fog is used.</p></body></html></string>
|
<string><html><head/><body><p>Use exponential fog formula. By default, linear fog is used.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Exponential fog</string>
|
<string>Exponential Fog</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -613,7 +613,7 @@
|
|||||||
This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV.</p></body></html></string>
|
This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Radial fog</string>
|
<string>Radial Fog</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -626,7 +626,7 @@
|
|||||||
<string><html><head/><body><p>The fraction of the maximum distance at which blending with the sky starts.</p></body></html></string>
|
<string><html><head/><body><p>The fraction of the maximum distance at which blending with the sky starts.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sky blending start</string>
|
<string>Sky Blending Start</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -636,7 +636,7 @@
|
|||||||
<string><html><head/><body><p>Reduce visibility of clipping plane by blending objects with the sky.</p></body></html></string>
|
<string><html><head/><body><p>Reduce visibility of clipping plane by blending objects with the sky.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sky blending</string>
|
<string>Sky Blending</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -652,59 +652,16 @@
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="terrainLayout" columnstretch="0,0">
|
<layout class="QGridLayout" name="terrainLayout" columnstretch="0,0">
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QCheckBox" name="distantLandCheckBox">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Distant land</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="viewingDistanceComboBox">
|
|
||||||
<property name="suffix">
|
|
||||||
<string> cells</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>0.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<spacer name="verticalSpacer_15">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="objectPagingMinSizeLabel">
|
<widget class="QLabel" name="objectPagingMinSizeLabel">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Controls how large an object must be to be visible in the scene. The object’s size is divided by its distance to the camera and the result of the division is compared with this value. The smaller this value is, the more objects you will see in the scene.</p></body></html></string>
|
<string><html><head/><body><p>Controls how large an object must be to be visible in the scene. The object’s size is divided by its distance to the camera and the result of the division is compared with this value. The smaller this value is, the more objects you will see in the scene.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Object paging min size</string>
|
<string>Object Paging Min Size</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="4" column="1">
|
||||||
<widget class="QLabel" name="viewingDistanceLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Viewing distance</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="objectPagingMinSizeComboBox">
|
<widget class="QDoubleSpinBox" name="objectPagingMinSizeComboBox">
|
||||||
<property name="decimals">
|
<property name="decimals">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
@ -720,13 +677,59 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="viewingDistanceLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Viewing Distance</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="viewingDistanceComboBox">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> cells</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.125000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<spacer name="verticalSpacer_15">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="distantLandCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Distant Land</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
<widget class="QCheckBox" name="activeGridObjectPagingCheckBox">
|
<widget class="QCheckBox" name="activeGridObjectPagingCheckBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Use object paging for active cells grid.</p></body></html></string>
|
<string><html><head/><body><p>Use object paging for active cells grid.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Active grid object paging</string>
|
<string>Active Grid Object Paging</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -741,16 +744,22 @@
|
|||||||
<layout class="QHBoxLayout" name="horizontalPostProcessLayout">
|
<layout class="QHBoxLayout" name="horizontalPostProcessLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="postProcessLayout" columnstretch="0,0">
|
<layout class="QGridLayout" name="postProcessLayout" columnstretch="0,0">
|
||||||
<item row="5" column="0">
|
<item row="5" column="1">
|
||||||
<widget class="QLabel" name="postprocessHDRTimeLabel">
|
<widget class="QDoubleSpinBox" name="postprocessHDRTimeComboBox">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="decimals">
|
||||||
<string><html><head/><body><p>Controls how much eye adaptation can change from frame to frame. Smaller values makes for slower transitions.</p></body></html></string>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="minimum">
|
||||||
<string>Auto exposure speed</string>
|
<double>0.010000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>10.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.001000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -776,26 +785,20 @@
|
|||||||
<string><html><head/><body><p>Re-render transparent objects with forced alpha clipping.</p></body></html></string>
|
<string><html><head/><body><p>Re-render transparent objects with forced alpha clipping.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Transparent postpass</string>
|
<string>Transparent Postpass</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="5" column="0">
|
||||||
<widget class="QDoubleSpinBox" name="postprocessHDRTimeComboBox">
|
<widget class="QLabel" name="postprocessHDRTimeLabel">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="decimals">
|
<property name="toolTip">
|
||||||
<number>3</number>
|
<string><html><head/><body><p>Controls how much eye adaptation can change from frame to frame. Smaller values makes for slower transitions.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="text">
|
||||||
<double>0.010000000000000</double>
|
<string>Auto Exposure Speed</string>
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>10.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.001000000000000</double>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -805,7 +808,7 @@
|
|||||||
<string><html><head/><body><p>If this setting is true, post processing will be enabled.</p></body></html></string>
|
<string><html><head/><body><p>If this setting is true, post processing will be enabled.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable post processing</string>
|
<string>Enable Post Processing</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -824,17 +827,17 @@
|
|||||||
<widget class="QComboBox" name="shadowComputeSceneBoundsComboBox">
|
<widget class="QComboBox" name="shadowComputeSceneBoundsComboBox">
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>bounds</string>
|
<string>Bounds</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>primitives</string>
|
<string>Primitives</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>none</string>
|
<string>None</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
@ -845,7 +848,7 @@
|
|||||||
<string><html><head/><body><p>Type of "compute scene bounds" computation method to be used. Bounds (default) for good balance between performance and shadow quality, primitives for better looking shadows or none for no computation.</p></body></html></string>
|
<string><html><head/><body><p>Type of "compute scene bounds" computation method to be used. Bounds (default) for good balance between performance and shadow quality, primitives for better looking shadows or none for no computation.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Shadow planes computation method</string>
|
<string>Shadow Planes Computation Method</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -866,6 +869,9 @@
|
|||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>81920</number>
|
<number>81920</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>128</number>
|
||||||
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<number>8192</number>
|
<number>8192</number>
|
||||||
</property>
|
</property>
|
||||||
@ -877,7 +883,7 @@
|
|||||||
<string><html><head/><body><p>Enable shadows for NPCs and creatures besides the player character. May have a minor performance impact.</p></body></html></string>
|
<string><html><head/><body><p>Enable shadows for NPCs and creatures besides the player character. May have a minor performance impact.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable actor shadows</string>
|
<string>Enable Actor Shadows</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -911,7 +917,7 @@
|
|||||||
<string><html><head/><body><p>The fraction of the limit above at which shadows begin to gradually fade away.</p></body></html></string>
|
<string><html><head/><body><p>The fraction of the limit above at which shadows begin to gradually fade away.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Fade start multiplier</string>
|
<string>Fade Start Multiplier</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -921,7 +927,7 @@
|
|||||||
<string><html><head/><body><p>Enable shadows exclusively for the player character. May have a very minor performance impact.</p></body></html></string>
|
<string><html><head/><body><p>Enable shadows exclusively for the player character. May have a very minor performance impact.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable player shadows</string>
|
<string>Enable Player Shadows</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -931,7 +937,7 @@
|
|||||||
<string><html><head/><body><p>The resolution of each individual shadow map. Increasing it significantly improves shadow quality but may have a minor performance impact.</p></body></html></string>
|
<string><html><head/><body><p>The resolution of each individual shadow map. Increasing it significantly improves shadow quality but may have a minor performance impact.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Shadow map resolution</string>
|
<string>Shadow Map Resolution</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -941,7 +947,7 @@
|
|||||||
<string><html><head/><body><p>The distance from the camera at which shadows completely disappear.</p></body></html></string>
|
<string><html><head/><body><p>The distance from the camera at which shadows completely disappear.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Shadow distance limit:</string>
|
<string>Shadow Distance Limit:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -951,7 +957,7 @@
|
|||||||
<string><html><head/><body><p>Enable shadows for primarily inanimate objects. May have a significant performance impact.</p></body></html></string>
|
<string><html><head/><body><p>Enable shadows for primarily inanimate objects. May have a significant performance impact.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable object shadows</string>
|
<string>Enable Object Shadows</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -969,6 +975,9 @@
|
|||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>1.000000000000000</double>
|
<double>1.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.010000000000000</double>
|
||||||
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<double>0.900000000000000</double>
|
<double>0.900000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
@ -993,7 +1002,7 @@
|
|||||||
<string><html><head/><body><p>Due to limitations with Morrowind's data, only actors can cast shadows indoors, which some might feel is distracting.</p><p>Has no effect if actor/player shadows are not enabled.</p></body></html></string>
|
<string><html><head/><body><p>Due to limitations with Morrowind's data, only actors can cast shadows indoors, which some might feel is distracting.</p><p>Has no effect if actor/player shadows are not enabled.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable indoor shadows</string>
|
<string>Enable Indoor Shadows</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1003,7 +1012,7 @@
|
|||||||
<string><html><head/><body><p>Enable shadows for the terrain including distant terrain. May have a significant performance and shadow quality impact.</p></body></html></string>
|
<string><html><head/><body><p>Enable shadows for the terrain including distant terrain. May have a significant performance and shadow quality impact.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable terrain shadows</string>
|
<string>Enable Terrain Shadows</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1024,7 +1033,7 @@
|
|||||||
<string><html><head/><body><p>Maximum distance at which lights will appear (measured in units).</p><p>Set this to 0 to use an unlimited distance.</p></body></html></string>
|
<string><html><head/><body><p>Maximum distance at which lights will appear (measured in units).</p><p>Set this to 0 to use an unlimited distance.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Lights maximum distance</string>
|
<string>Maximum Light Distance</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1047,7 +1056,7 @@
|
|||||||
<string><html><head/><body><p>Maximum number of lights per object.</p><p>A low number near default will cause light popping similar to what you would see with legacy lighting.</p></body></html></string>
|
<string><html><head/><body><p>Maximum number of lights per object.</p><p>A low number near default will cause light popping similar to what you would see with legacy lighting.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max light sources</string>
|
<string>Max Lights</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1057,7 +1066,7 @@
|
|||||||
<string><html><head/><body><p>Fraction of maximum distance at which lights will start to fade.</p><p>Set this to a low value for slower transitions or a high value for quicker transitions.</p></body></html></string>
|
<string><html><head/><body><p>Fraction of maximum distance at which lights will start to fade.</p><p>Set this to a low value for slower transitions or a high value for quicker transitions.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Lights fade multiplier</string>
|
<string>Fade Start Multiplier</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1070,7 +1079,7 @@
|
|||||||
<p> "Shaders" carries all of the benefits that "Shaders (compatibility)" does, but uses a modern approach that allows for a higher max lights count with little to no performance penalties on modern hardware.</p></body></html></string>
|
<p> "Shaders" carries all of the benefits that "Shaders (compatibility)" does, but uses a modern approach that allows for a higher max lights count with little to no performance penalties on modern hardware.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Lighting method</string>
|
<string>Lighting Method</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1099,7 +1108,7 @@
|
|||||||
<string><html><head/><body><p>Multipler for bounding sphere of lights.</p><p>Higher numbers allows for smooth falloff but require an increase in number of max lights.</p><p>Does not effect the illumination or strength of lights.</p></body></html></string>
|
<string><html><head/><body><p>Multipler for bounding sphere of lights.</p><p>Higher numbers allows for smooth falloff but require an increase in number of max lights.</p><p>Does not effect the illumination or strength of lights.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Lights bounding sphere multiplier</string>
|
<string>Bounding Sphere Multiplier</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1119,7 +1128,7 @@
|
|||||||
<string><html><head/><body><p>Minimum ambient interior brightness.</p><p>Increase this if you feel interiors are too dark.</p></body></html></string>
|
<string><html><head/><body><p>Minimum ambient interior brightness.</p><p>Increase this if you feel interiors are too dark.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Lights minimum interior brightness</string>
|
<string>Minimum Interior Brightness</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1214,7 +1223,7 @@
|
|||||||
<string>Select your preferred audio device.</string>
|
<string>Select your preferred audio device.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Audio device</string>
|
<string>Audio Device</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1300,7 +1309,7 @@
|
|||||||
<string>Select your preferred HRTF profile.</string>
|
<string>Select your preferred HRTF profile.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>HRTF profile</string>
|
<string>HRTF Profile</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1330,6 +1339,16 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cameraListenerCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>In third-person view, use the camera as the sound listener instead of the player character.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Use the Camera as the Sound Listener</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -1374,7 +1393,7 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Tooltip and crosshair</string>
|
<string>Tooltip and Crosshair</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
@ -1420,7 +1439,7 @@
|
|||||||
<string><html><head/><body><p>This setting scales GUI windows. A value of 1.0 results in the normal scale.</p></body></html></string>
|
<string><html><head/><body><p>This setting scales GUI windows. A value of 1.0 results in the normal scale.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>GUI scaling factor</string>
|
<string>GUI Scaling Factor</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1430,7 +1449,7 @@
|
|||||||
<string><html><head/><body><p>Show the remaining duration of magic effects and lights if this setting is true. The remaining duration is displayed in the tooltip by hovering over the magical effect. </p><p>The default value is false.</p></body></html></string>
|
<string><html><head/><body><p>Show the remaining duration of magic effects and lights if this setting is true. The remaining duration is displayed in the tooltip by hovering over the magical effect. </p><p>The default value is false.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show effect duration</string>
|
<string>Show Effect Duration</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1440,7 +1459,7 @@
|
|||||||
<string><html><head/><body><p>If this setting is true, dialogue topics will have a different color if the topic is specific to the NPC you're talking to or the topic was previously seen. Color can be changed in settings.cfg.</p><p>The default value is false.</p></body></html></string>
|
<string><html><head/><body><p>If this setting is true, dialogue topics will have a different color if the topic is specific to the NPC you're talking to or the topic was previously seen. Color can be changed in settings.cfg.</p><p>The default value is false.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Change dialogue topic color</string>
|
<string>Change Dialogue Topic Color</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1450,7 +1469,7 @@
|
|||||||
<string>Size of characters in game texts.</string>
|
<string>Size of characters in game texts.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Font size</string>
|
<string>Font Size</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1460,7 +1479,7 @@
|
|||||||
<string><html><head/><body><p>Enable zooming on local and global maps.</p></body></html></string>
|
<string><html><head/><body><p>Enable zooming on local and global maps.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Can zoom on maps</string>
|
<string>Can Zoom on Maps</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1470,7 +1489,7 @@
|
|||||||
<string><html><head/><body><p>If this setting is true, damage bonus of arrows and bolts will be shown on item tooltip.</p><p>The default value is false.</p></body></html></string>
|
<string><html><head/><body><p>If this setting is true, damage bonus of arrows and bolts will be shown on item tooltip.</p><p>The default value is false.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show projectile damage</string>
|
<string>Show Projectile Damage</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1480,7 +1499,7 @@
|
|||||||
<string><html><head/><body><p>If this setting is true, melee weapons reach and speed will be shown on item tooltip.</p><p>The default value is false.</p></body></html></string>
|
<string><html><head/><body><p>If this setting is true, melee weapons reach and speed will be shown on item tooltip.</p><p>The default value is false.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show melee info</string>
|
<string>Show Melee Info</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1490,14 +1509,14 @@
|
|||||||
<string><html><head/><body><p>Stretch menus, load screens, etc. to the window aspect ratio.</p></body></html></string>
|
<string><html><head/><body><p>Stretch menus, load screens, etc. to the window aspect ratio.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Stretch menu background</string>
|
<string>Stretch Menu Background</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="showOwnedLabel">
|
<widget class="QLabel" name="showOwnedLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show owned objects</string>
|
<string>Show Owned Objects</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1507,7 +1526,7 @@
|
|||||||
<string><html><head/><body><p>Whether or not the chance of success will be displayed in the enchanting menu.</p><p>The default value is false.</p></body></html></string>
|
<string><html><head/><body><p>Whether or not the chance of success will be displayed in the enchanting menu.</p><p>The default value is false.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show enchant chance</string>
|
<string>Show Enchant Chance</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1545,7 +1564,7 @@
|
|||||||
<string><html><head/><body><p>This setting determines whether the amount of the time the player has spent playing will be displayed for each saved game in the Load menu.</p></body></html></string>
|
<string><html><head/><body><p>This setting determines whether the amount of the time the player has spent playing will be displayed for each saved game in the Load menu.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add "Time Played" to saves</string>
|
<string>Add "Time Played" to Saves</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1554,7 +1573,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="maximumQuicksavesLabel">
|
<widget class="QLabel" name="maximumQuicksavesLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Maximum quicksaves</string>
|
<string>Maximum Quicksaves</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1581,7 +1600,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="screenshotFormatLabel">
|
<widget class="QLabel" name="screenshotFormatLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Screenshot format</string>
|
<string>Screenshot Format</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1609,7 +1628,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="notifyOnSavedScreenshotCheckBox">
|
<widget class="QCheckBox" name="notifyOnSavedScreenshotCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Notify on saved screenshot</string>
|
<string>Notify on Saved Screenshot</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1659,14 +1678,14 @@
|
|||||||
<string><html><head/><body><p>OpenMW will capture control of the cursor if this setting is true.</p><p>In “look mode”, OpenMW will center the cursor regardless of the value of this setting (since the cursor/crosshair is always centered in the OpenMW window). However, in GUI mode, this setting determines the behavior when the cursor is moved outside the OpenMW window. If true, the cursor movement stops at the edge of the window preventing access to other applications. If false, the cursor is allowed to move freely on the desktop.</p><p>This setting does not apply to the screen where escape has been pressed, where the cursor is never captured. Regardless of this setting “Alt-Tab” or some other operating system dependent key sequence can be used to allow the operating system to regain control of the mouse cursor. This setting interacts with the minimize on focus loss setting by affecting what counts as a focus loss. Specifically on a two-screen configuration it may be more convenient to access the second screen with setting disabled.</p><p>Note for developers: it’s desirable to have this setting disabled when running the game in a debugger, to prevent the mouse cursor from becoming unusable when the game pauses on a breakpoint.</p></body></html></string>
|
<string><html><head/><body><p>OpenMW will capture control of the cursor if this setting is true.</p><p>In “look mode”, OpenMW will center the cursor regardless of the value of this setting (since the cursor/crosshair is always centered in the OpenMW window). However, in GUI mode, this setting determines the behavior when the cursor is moved outside the OpenMW window. If true, the cursor movement stops at the edge of the window preventing access to other applications. If false, the cursor is allowed to move freely on the desktop.</p><p>This setting does not apply to the screen where escape has been pressed, where the cursor is never captured. Regardless of this setting “Alt-Tab” or some other operating system dependent key sequence can be used to allow the operating system to regain control of the mouse cursor. This setting interacts with the minimize on focus loss setting by affecting what counts as a focus loss. Specifically on a two-screen configuration it may be more convenient to access the second screen with setting disabled.</p><p>Note for developers: it’s desirable to have this setting disabled when running the game in a debugger, to prevent the mouse cursor from becoming unusable when the game pauses on a breakpoint.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Grab cursor</string>
|
<string>Grab Cursor</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="skipMenuCheckBox">
|
<widget class="QCheckBox" name="skipMenuCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Skip menu and generate default character</string>
|
<string>Skip Menu and Generate Default Character</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1691,14 +1710,14 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="startDefaultCharacterAtLabel">
|
<widget class="QLabel" name="startDefaultCharacterAtLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Start default character at</string>
|
<string>Start Default Character at</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="startDefaultCharacterAtField">
|
<widget class="QLineEdit" name="startDefaultCharacterAtField">
|
||||||
<property name="placeholderText">
|
<property name="placeholderText">
|
||||||
<string>default cell</string>
|
<string>Default Cell</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1707,7 +1726,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Run script after startup:</string>
|
<string>Run Script After Startup:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -33,7 +33,7 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||||||
target_link_libraries(openmw-iniimporter gcov)
|
target_link_libraries(openmw-iniimporter gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw-iniimporter PRIVATE
|
target_precompile_headers(openmw-iniimporter PRIVATE
|
||||||
<string>
|
<string>
|
||||||
<vector>
|
<vector>
|
||||||
|
@ -21,7 +21,7 @@ if (WIN32)
|
|||||||
install(TARGETS openmw-navmeshtool RUNTIME DESTINATION ".")
|
install(TARGETS openmw-navmeshtool RUNTIME DESTINATION ".")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw-navmeshtool PRIVATE
|
target_precompile_headers(openmw-navmeshtool PRIVATE
|
||||||
<algorithm>
|
<algorithm>
|
||||||
<memory>
|
<memory>
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <components/files/conversion.hpp>
|
#include <components/files/conversion.hpp>
|
||||||
#include <components/files/multidircollection.hpp>
|
#include <components/files/multidircollection.hpp>
|
||||||
#include <components/platform/platform.hpp>
|
#include <components/platform/platform.hpp>
|
||||||
|
#include <components/resource/bgsmfilemanager.hpp>
|
||||||
#include <components/resource/bulletshapemanager.hpp>
|
#include <components/resource/bulletshapemanager.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/resource/niffilemanager.hpp>
|
#include <components/resource/niffilemanager.hpp>
|
||||||
@ -165,7 +166,9 @@ namespace NavMeshTool
|
|||||||
dataDirs.insert(dataDirs.begin(), resDir / "vfs");
|
dataDirs.insert(dataDirs.begin(), resDir / "vfs");
|
||||||
const Files::Collections fileCollections(dataDirs);
|
const Files::Collections fileCollections(dataDirs);
|
||||||
const auto& archives = variables["fallback-archive"].as<StringsVector>();
|
const auto& archives = variables["fallback-archive"].as<StringsVector>();
|
||||||
const auto& contentFiles = variables["content"].as<StringsVector>();
|
StringsVector contentFiles{ "builtin.omwscripts" };
|
||||||
|
const auto& configContentFiles = variables["content"].as<StringsVector>();
|
||||||
|
contentFiles.insert(contentFiles.end(), configContentFiles.begin(), configContentFiles.end());
|
||||||
const std::size_t threadsNumber = variables["threads"].as<std::size_t>();
|
const std::size_t threadsNumber = variables["threads"].as<std::size_t>();
|
||||||
|
|
||||||
if (threadsNumber < 1)
|
if (threadsNumber < 1)
|
||||||
@ -218,7 +221,8 @@ namespace NavMeshTool
|
|||||||
|
|
||||||
Resource::ImageManager imageManager(&vfs, expiryDelay);
|
Resource::ImageManager imageManager(&vfs, expiryDelay);
|
||||||
Resource::NifFileManager nifFileManager(&vfs, &encoder.getStatelessEncoder());
|
Resource::NifFileManager nifFileManager(&vfs, &encoder.getStatelessEncoder());
|
||||||
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, expiryDelay);
|
Resource::BgsmFileManager bgsmFileManager(&vfs, expiryDelay);
|
||||||
|
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, &bgsmFileManager, expiryDelay);
|
||||||
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager, expiryDelay);
|
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager, expiryDelay);
|
||||||
DetourNavigator::RecastGlobalAllocator::init();
|
DetourNavigator::RecastGlobalAllocator::init();
|
||||||
DetourNavigator::Settings navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();
|
DetourNavigator::Settings navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();
|
||||||
|
@ -17,6 +17,6 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||||||
target_link_libraries(niftest gcov)
|
target_link_libraries(niftest gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(niftest PRIVATE <filesystem>)
|
target_precompile_headers(niftest PRIVATE <filesystem>)
|
||||||
endif()
|
endif()
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <components/bgsm/file.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/files/constrainedfilestream.hpp>
|
#include <components/files/constrainedfilestream.hpp>
|
||||||
#include <components/files/conversion.hpp>
|
#include <components/files/conversion.hpp>
|
||||||
@ -25,7 +26,7 @@
|
|||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
|
|
||||||
/// See if the file has the named extension
|
/// See if the file has the named extension
|
||||||
bool hasExtension(const std::filesystem::path& filename, const std::string& extensionToFind)
|
bool hasExtension(const std::filesystem::path& filename, std::string_view extensionToFind)
|
||||||
{
|
{
|
||||||
const auto extension = Files::pathToUnicodeString(filename.extension());
|
const auto extension = Files::pathToUnicodeString(filename.extension());
|
||||||
return Misc::StringUtils::ciEqual(extension, extensionToFind);
|
return Misc::StringUtils::ciEqual(extension, extensionToFind);
|
||||||
@ -36,63 +37,62 @@ bool isNIF(const std::filesystem::path& filename)
|
|||||||
{
|
{
|
||||||
return hasExtension(filename, ".nif") || hasExtension(filename, ".kf");
|
return hasExtension(filename, ".nif") || hasExtension(filename, ".kf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the file is a material file.
|
||||||
|
bool isMaterial(const std::filesystem::path& filename)
|
||||||
|
{
|
||||||
|
return hasExtension(filename, ".bgem") || hasExtension(filename, ".bgsm");
|
||||||
|
}
|
||||||
|
|
||||||
/// See if the file has the "bsa" extension.
|
/// See if the file has the "bsa" extension.
|
||||||
bool isBSA(const std::filesystem::path& filename)
|
bool isBSA(const std::filesystem::path& filename)
|
||||||
{
|
{
|
||||||
return hasExtension(filename, ".bsa") || hasExtension(filename, ".ba2");
|
return hasExtension(filename, ".bsa") || hasExtension(filename, ".ba2");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<VFS::Archive> makeBsaArchive(const std::filesystem::path& path)
|
|
||||||
{
|
|
||||||
switch (Bsa::BSAFile::detectVersion(path))
|
|
||||||
{
|
|
||||||
case Bsa::BSAVER_COMPRESSED:
|
|
||||||
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_COMPRESSED>::type>(path);
|
|
||||||
case Bsa::BSAVER_BA2_GNRL:
|
|
||||||
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_BA2_GNRL>::type>(path);
|
|
||||||
case Bsa::BSAVER_BA2_DX10:
|
|
||||||
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_BA2_DX10>::type>(path);
|
|
||||||
case Bsa::BSAVER_UNCOMPRESSED:
|
|
||||||
return std::make_unique<VFS::ArchiveSelector<Bsa::BSAVER_UNCOMPRESSED>::type>(path);
|
|
||||||
case Bsa::BSAVER_UNKNOWN:
|
|
||||||
default:
|
|
||||||
std::cerr << "'" << Files::pathToUnicodeString(path) << "' is not a recognized BSA archive" << std::endl;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<VFS::Archive> makeArchive(const std::filesystem::path& path)
|
std::unique_ptr<VFS::Archive> makeArchive(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
if (isBSA(path))
|
if (isBSA(path))
|
||||||
return makeBsaArchive(path);
|
return VFS::makeBsaArchive(path);
|
||||||
if (std::filesystem::is_directory(path))
|
if (std::filesystem::is_directory(path))
|
||||||
return std::make_unique<VFS::FileSystemArchive>(path);
|
return std::make_unique<VFS::FileSystemArchive>(path);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readNIF(
|
void readFile(
|
||||||
const std::filesystem::path& source, const std::filesystem::path& path, const VFS::Manager* vfs, bool quiet)
|
const std::filesystem::path& source, const std::filesystem::path& path, const VFS::Manager* vfs, bool quiet)
|
||||||
{
|
{
|
||||||
const std::string pathStr = Files::pathToUnicodeString(path);
|
const std::string pathStr = Files::pathToUnicodeString(path);
|
||||||
|
const bool isNif = isNIF(path);
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
{
|
{
|
||||||
if (hasExtension(path, ".kf"))
|
if (isNif)
|
||||||
std::cout << "Reading KF file '" << pathStr << "'";
|
std::cout << "Reading " << (hasExtension(path, ".nif") ? "NIF" : "KF") << " file '" << pathStr << "'";
|
||||||
else
|
else
|
||||||
std::cout << "Reading NIF file '" << pathStr << "'";
|
std::cout << "Reading " << (hasExtension(path, ".bgsm") ? "BGSM" : "BGEM") << " file '" << pathStr << "'";
|
||||||
if (!source.empty())
|
if (!source.empty())
|
||||||
std::cout << " from '" << Files::pathToUnicodeString(isBSA(source) ? source.filename() : source) << "'";
|
std::cout << " from '" << Files::pathToUnicodeString(isBSA(source) ? source.filename() : source) << "'";
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
std::filesystem::path fullPath = !source.empty() ? source / path : path;
|
const std::filesystem::path fullPath = !source.empty() ? source / path : path;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Nif::NIFFile file(fullPath);
|
if (isNif)
|
||||||
Nif::Reader reader(file, nullptr);
|
{
|
||||||
if (vfs != nullptr)
|
Nif::NIFFile file(Files::pathToUnicodeString(fullPath));
|
||||||
reader.parse(vfs->get(pathStr));
|
Nif::Reader reader(file, nullptr);
|
||||||
|
if (vfs != nullptr)
|
||||||
|
reader.parse(vfs->get(pathStr));
|
||||||
|
else
|
||||||
|
reader.parse(Files::openConstrainedFileStream(fullPath));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
reader.parse(Files::openConstrainedFileStream(fullPath));
|
{
|
||||||
|
if (vfs != nullptr)
|
||||||
|
Bgsm::parse(vfs->get(pathStr));
|
||||||
|
else
|
||||||
|
Bgsm::parse(Files::openConstrainedFileStream(fullPath));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
@ -114,27 +114,33 @@ void readVFS(std::unique_ptr<VFS::Archive>&& archive, const std::filesystem::pat
|
|||||||
vfs.addArchive(std::move(archive));
|
vfs.addArchive(std::move(archive));
|
||||||
vfs.buildIndex();
|
vfs.buildIndex();
|
||||||
|
|
||||||
for (const auto& name : vfs.getRecursiveDirectoryIterator(""))
|
for (const auto& name : vfs.getRecursiveDirectoryIterator())
|
||||||
{
|
{
|
||||||
if (isNIF(name.value()))
|
if (isNIF(name.value()) || isMaterial(name.value()))
|
||||||
{
|
{
|
||||||
readNIF(archivePath, name.value(), &vfs, quiet);
|
readFile(archivePath, name.value(), &vfs, quiet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!archivePath.empty() && !isBSA(archivePath))
|
if (!archivePath.empty() && !isBSA(archivePath))
|
||||||
{
|
{
|
||||||
Files::PathContainer dataDirs = { archivePath };
|
const Files::Collections fileCollections({ archivePath });
|
||||||
const Files::Collections fileCollections = Files::Collections(dataDirs);
|
|
||||||
const Files::MultiDirCollection& bsaCol = fileCollections.getCollection(".bsa");
|
const Files::MultiDirCollection& bsaCol = fileCollections.getCollection(".bsa");
|
||||||
const Files::MultiDirCollection& ba2Col = fileCollections.getCollection(".ba2");
|
const Files::MultiDirCollection& ba2Col = fileCollections.getCollection(".ba2");
|
||||||
for (auto& file : bsaCol)
|
for (const Files::MultiDirCollection& collection : { bsaCol, ba2Col })
|
||||||
{
|
{
|
||||||
readVFS(makeBsaArchive(file.second), file.second, quiet);
|
for (auto& file : collection)
|
||||||
}
|
{
|
||||||
for (auto& file : ba2Col)
|
try
|
||||||
{
|
{
|
||||||
readVFS(makeBsaArchive(file.second), file.second, quiet);
|
readVFS(VFS::makeBsaArchive(file.second), file.second, quiet);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to read archive file '" << Files::pathToUnicodeString(file.second)
|
||||||
|
<< "': " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,10 +148,10 @@ void readVFS(std::unique_ptr<VFS::Archive>&& archive, const std::filesystem::pat
|
|||||||
bool parseOptions(int argc, char** argv, Files::PathContainer& files, Files::PathContainer& archives,
|
bool parseOptions(int argc, char** argv, Files::PathContainer& files, Files::PathContainer& archives,
|
||||||
bool& writeDebugLog, bool& quiet)
|
bool& writeDebugLog, bool& quiet)
|
||||||
{
|
{
|
||||||
bpo::options_description desc(R"(Ensure that OpenMW can use the provided NIF, KF and BSA/BA2 files
|
bpo::options_description desc(R"(Ensure that OpenMW can use the provided NIF, KF, BGEM/BGSM and BSA/BA2 files
|
||||||
|
|
||||||
Usages:
|
Usages:
|
||||||
niftest <nif files, kf files, BSA/BA2 files, or directories>
|
niftest <nif files, kf files, bgem/bgsm files, BSA/BA2 files, or directories>
|
||||||
Scan the file or directories for NIF errors.
|
Scan the file or directories for NIF errors.
|
||||||
|
|
||||||
Allowed options)");
|
Allowed options)");
|
||||||
@ -234,9 +240,9 @@ int main(int argc, char** argv)
|
|||||||
const std::string pathStr = Files::pathToUnicodeString(path);
|
const std::string pathStr = Files::pathToUnicodeString(path);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (isNIF(path))
|
if (isNIF(path) || isMaterial(path))
|
||||||
{
|
{
|
||||||
readNIF({}, path, vfs.get(), quiet);
|
readFile({}, path, vfs.get(), quiet);
|
||||||
}
|
}
|
||||||
else if (auto archive = makeArchive(path))
|
else if (auto archive = makeArchive(path))
|
||||||
{
|
{
|
||||||
@ -244,7 +250,7 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "Error: '" << pathStr << "' is not a NIF/KF file, BSA/BA2 archive, or directory"
|
std::cerr << "Error: '" << pathStr << "' is not a NIF/KF/BGEM/BGSM file, BSA/BA2 archive, or directory"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ else()
|
|||||||
set (OPENCS_OPENMW_CFG "")
|
set (OPENCS_OPENMW_CFG "")
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
add_library(openmw-cs-lib
|
add_library(openmw-cs-lib STATIC
|
||||||
${OPENCS_SRC}
|
${OPENCS_SRC}
|
||||||
${OPENCS_UI_HDR}
|
${OPENCS_UI_HDR}
|
||||||
${OPENCS_MOC_SRC}
|
${OPENCS_MOC_SRC}
|
||||||
@ -250,13 +250,14 @@ target_link_libraries(openmw-cs-lib
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (QT_VERSION_MAJOR VERSION_EQUAL 6)
|
if (QT_VERSION_MAJOR VERSION_EQUAL 6)
|
||||||
target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL Qt::OpenGLWidgets)
|
target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL Qt::OpenGLWidgets Qt::Svg)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL)
|
target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL Qt::Svg)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(openmw-cs-lib ${Boost_LOCALE_LIBRARY})
|
target_link_libraries(openmw-cs-lib ${Boost_LOCALE_LIBRARY})
|
||||||
|
target_sources(openmw-cs PRIVATE ${CMAKE_SOURCE_DIR}/files/windows/openmw-cs.exe.manifest)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32 AND BUILD_OPENCS)
|
if (WIN32 AND BUILD_OPENCS)
|
||||||
@ -292,7 +293,7 @@ if (BUILD_WITH_CODE_COVERAGE)
|
|||||||
target_link_libraries(openmw-cs-lib gcov)
|
target_link_libraries(openmw-cs-lib gcov)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
|
||||||
target_precompile_headers(openmw-cs-lib PRIVATE
|
target_precompile_headers(openmw-cs-lib PRIVATE
|
||||||
<boost/program_options/options_description.hpp>
|
<boost/program_options/options_description.hpp>
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ int runApplication(int argc, char* argv[])
|
|||||||
|
|
||||||
Application application(argc, argv);
|
Application application(argc, argv);
|
||||||
|
|
||||||
application.setWindowIcon(QIcon(":./openmw-cs.png"));
|
application.setWindowIcon(QIcon(":openmw-cs"));
|
||||||
|
|
||||||
CS::Editor editor(argc, argv);
|
CS::Editor editor(argc, argv);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -93,7 +93,6 @@ void CSMDoc::Runner::start(bool delayed)
|
|||||||
arguments << "--data=\"" + Files::pathToQString(mProjectPath.parent_path()) + "\"";
|
arguments << "--data=\"" + Files::pathToQString(mProjectPath.parent_path()) + "\"";
|
||||||
|
|
||||||
arguments << "--replace=content";
|
arguments << "--replace=content";
|
||||||
arguments << "--content=builtin.omwscripts";
|
|
||||||
|
|
||||||
for (const auto& mContentFile : mContentFiles)
|
for (const auto& mContentFile : mContentFiles)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +135,7 @@ void CSMDoc::WriteDialogueCollectionStage::perform(int stage, Messages& messages
|
|||||||
if (topic.mState == CSMWorld::RecordBase::State_Deleted)
|
if (topic.mState == CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
// if the topic is deleted, we do not need to bother with INFO records.
|
// if the topic is deleted, we do not need to bother with INFO records.
|
||||||
ESM::Dialogue dialogue = topic.get();
|
const ESM::Dialogue& dialogue = topic.get();
|
||||||
writer.startRecord(dialogue.sRecordId);
|
writer.startRecord(dialogue.sRecordId);
|
||||||
dialogue.save(writer, true);
|
dialogue.save(writer, true);
|
||||||
writer.endRecord(dialogue.sRecordId);
|
writer.endRecord(dialogue.sRecordId);
|
||||||
@ -187,6 +187,7 @@ void CSMDoc::WriteDialogueCollectionStage::perform(int stage, Messages& messages
|
|||||||
{
|
{
|
||||||
ESM::DialInfo info = record.get();
|
ESM::DialInfo info = record.get();
|
||||||
info.mId = record.get().mOriginalId;
|
info.mId = record.get().mOriginalId;
|
||||||
|
info.mData.mType = topic.get().mType;
|
||||||
|
|
||||||
if (iter == infos.begin())
|
if (iter == infos.begin())
|
||||||
info.mPrev = ESM::RefId();
|
info.mPrev = ESM::RefId();
|
||||||
|
@ -452,7 +452,10 @@ std::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseText()
|
|||||||
return std::shared_ptr<Node>();
|
return std::shared_ptr<Node>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<TextNode>(columnId, text);
|
auto node = std::make_shared<TextNode>(columnId, text);
|
||||||
|
if (!node->isValid())
|
||||||
|
error();
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseValue()
|
std::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseValue()
|
||||||
|
@ -34,6 +34,8 @@ namespace CSMFilter
|
|||||||
///< Return a string that represents this node.
|
///< Return a string that represents this node.
|
||||||
///
|
///
|
||||||
/// \param numericColumns Use numeric IDs instead of string to represent columns.
|
/// \param numericColumns Use numeric IDs instead of string to represent columns.
|
||||||
|
|
||||||
|
bool isValid() { return mRegExp.isValid(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ void CSMPrefs::State::declare()
|
|||||||
.setTooltip(
|
.setTooltip(
|
||||||
"When editing a record, open the view in a new window,"
|
"When editing a record, open the view in a new window,"
|
||||||
" rather than docked in the main view.");
|
" rather than docked in the main view.");
|
||||||
|
declareInt(mValues->mIdTables.mFilterDelay, "Delay before applying a filter (in miliseconds)");
|
||||||
|
|
||||||
declareCategory("ID Dialogues");
|
declareCategory("ID Dialogues");
|
||||||
declareBool(mValues->mIdDialogues.mToolbar, "Show toolbar");
|
declareBool(mValues->mIdDialogues.mToolbar, "Show toolbar");
|
||||||
|
@ -138,6 +138,7 @@ namespace CSMPrefs
|
|||||||
EnumSettingValue mJumpToAdded{ mIndex, sName, "jump-to-added", sJumpAndSelectValues, 0 };
|
EnumSettingValue mJumpToAdded{ mIndex, sName, "jump-to-added", sJumpAndSelectValues, 0 };
|
||||||
Settings::SettingValue<bool> mExtendedConfig{ mIndex, sName, "extended-config", false };
|
Settings::SettingValue<bool> mExtendedConfig{ mIndex, sName, "extended-config", false };
|
||||||
Settings::SettingValue<bool> mSubviewNewWindow{ mIndex, sName, "subview-new-window", false };
|
Settings::SettingValue<bool> mSubviewNewWindow{ mIndex, sName, "subview-new-window", false };
|
||||||
|
Settings::SettingValue<int> mFilterDelay{ mIndex, sName, "filter-delay", 500 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IdDialoguesCategory : Settings::WithIndex
|
struct IdDialoguesCategory : Settings::WithIndex
|
||||||
|
@ -60,38 +60,38 @@ void CSMTools::EnchantmentCheckStage::perform(int stage, CSMDoc::Messages& messa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<ESM::ENAMstruct>::const_iterator effect = enchantment.mEffects.mList.begin();
|
std::vector<ESM::IndexedENAMstruct>::const_iterator effect = enchantment.mEffects.mList.begin();
|
||||||
|
|
||||||
for (size_t i = 1; i <= enchantment.mEffects.mList.size(); i++)
|
for (size_t i = 1; i <= enchantment.mEffects.mList.size(); i++)
|
||||||
{
|
{
|
||||||
const std::string number = std::to_string(i);
|
const std::string number = std::to_string(i);
|
||||||
// At the time of writing this effects, attributes and skills are hardcoded
|
// At the time of writing this effects, attributes and skills are hardcoded
|
||||||
if (effect->mEffectID < 0 || effect->mEffectID > 142)
|
if (effect->mData.mEffectID < 0 || effect->mData.mEffectID > 142)
|
||||||
{
|
{
|
||||||
messages.add(id, "Effect #" + number + " is invalid", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Effect #" + number + " is invalid", "", CSMDoc::Message::Severity_Error);
|
||||||
++effect;
|
++effect;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effect->mSkill < -1 || effect->mSkill > 26)
|
if (effect->mData.mSkill < -1 || effect->mData.mSkill > 26)
|
||||||
messages.add(
|
messages.add(
|
||||||
id, "Effect #" + number + " affected skill is invalid", "", CSMDoc::Message::Severity_Error);
|
id, "Effect #" + number + " affected skill is invalid", "", CSMDoc::Message::Severity_Error);
|
||||||
if (effect->mAttribute < -1 || effect->mAttribute > 7)
|
if (effect->mData.mAttribute < -1 || effect->mData.mAttribute > 7)
|
||||||
messages.add(
|
messages.add(
|
||||||
id, "Effect #" + number + " affected attribute is invalid", "", CSMDoc::Message::Severity_Error);
|
id, "Effect #" + number + " affected attribute is invalid", "", CSMDoc::Message::Severity_Error);
|
||||||
if (effect->mRange < 0 || effect->mRange > 2)
|
if (effect->mData.mRange < 0 || effect->mData.mRange > 2)
|
||||||
messages.add(id, "Effect #" + number + " range is invalid", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Effect #" + number + " range is invalid", "", CSMDoc::Message::Severity_Error);
|
||||||
if (effect->mArea < 0)
|
if (effect->mData.mArea < 0)
|
||||||
messages.add(id, "Effect #" + number + " area is negative", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Effect #" + number + " area is negative", "", CSMDoc::Message::Severity_Error);
|
||||||
if (effect->mDuration < 0)
|
if (effect->mData.mDuration < 0)
|
||||||
messages.add(id, "Effect #" + number + " duration is negative", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Effect #" + number + " duration is negative", "", CSMDoc::Message::Severity_Error);
|
||||||
if (effect->mMagnMin < 0)
|
if (effect->mData.mMagnMin < 0)
|
||||||
messages.add(
|
messages.add(
|
||||||
id, "Effect #" + number + " minimum magnitude is negative", "", CSMDoc::Message::Severity_Error);
|
id, "Effect #" + number + " minimum magnitude is negative", "", CSMDoc::Message::Severity_Error);
|
||||||
if (effect->mMagnMax < 0)
|
if (effect->mData.mMagnMax < 0)
|
||||||
messages.add(
|
messages.add(
|
||||||
id, "Effect #" + number + " maximum magnitude is negative", "", CSMDoc::Message::Severity_Error);
|
id, "Effect #" + number + " maximum magnitude is negative", "", CSMDoc::Message::Severity_Error);
|
||||||
if (effect->mMagnMin > effect->mMagnMax)
|
if (effect->mData.mMagnMin > effect->mData.mMagnMax)
|
||||||
messages.add(id, "Effect #" + number + " minimum magnitude is higher than maximum magnitude", "",
|
messages.add(id, "Effect #" + number + " minimum magnitude is higher than maximum magnitude", "",
|
||||||
CSMDoc::Message::Severity_Error);
|
CSMDoc::Message::Severity_Error);
|
||||||
++effect;
|
++effect;
|
||||||
|
@ -58,7 +58,12 @@ void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages& messa
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ESM::MagicEffect effect = record.get();
|
ESM::MagicEffect effect = record.get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, CSMWorld::getRecordId(effect));
|
||||||
|
|
||||||
|
if (effect.mData.mSpeed <= 0.0f)
|
||||||
|
{
|
||||||
|
messages.add(id, "Speed is less than or equal to zero", "", CSMDoc::Message::Severity_Error);
|
||||||
|
}
|
||||||
|
|
||||||
if (effect.mDescription.empty())
|
if (effect.mDescription.empty())
|
||||||
{
|
{
|
||||||
|
@ -171,10 +171,9 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
|
|||||||
|
|
||||||
// Check info conditions
|
// Check info conditions
|
||||||
|
|
||||||
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator it = topicInfo.mSelects.begin();
|
for (const auto& select : topicInfo.mSelects)
|
||||||
it != topicInfo.mSelects.end(); ++it)
|
|
||||||
{
|
{
|
||||||
verifySelectStruct((*it), id, messages);
|
verifySelectStruct(select, id, messages);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,49 +307,15 @@ bool CSMTools::TopicInfoCheckStage::verifyItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CSMTools::TopicInfoCheckStage::verifySelectStruct(
|
bool CSMTools::TopicInfoCheckStage::verifySelectStruct(
|
||||||
const ESM::DialInfo::SelectStruct& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
|
const ESM::DialogueCondition& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
CSMWorld::ConstInfoSelectWrapper infoCondition(select);
|
CSMWorld::ConstInfoSelectWrapper infoCondition(select);
|
||||||
|
|
||||||
if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_None)
|
if (select.mFunction == ESM::DialogueCondition::Function_None)
|
||||||
{
|
{
|
||||||
messages.add(id, "Invalid condition '" + infoCondition.toString() + "'", "", CSMDoc::Message::Severity_Error);
|
messages.add(id, "Invalid condition '" + infoCondition.toString() + "'", "", CSMDoc::Message::Severity_Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!infoCondition.variantTypeIsValid())
|
|
||||||
{
|
|
||||||
std::ostringstream stream;
|
|
||||||
stream << "Value of condition '" << infoCondition.toString() << "' has invalid ";
|
|
||||||
|
|
||||||
switch (select.mValue.getType())
|
|
||||||
{
|
|
||||||
case ESM::VT_None:
|
|
||||||
stream << "None";
|
|
||||||
break;
|
|
||||||
case ESM::VT_Short:
|
|
||||||
stream << "Short";
|
|
||||||
break;
|
|
||||||
case ESM::VT_Int:
|
|
||||||
stream << "Int";
|
|
||||||
break;
|
|
||||||
case ESM::VT_Long:
|
|
||||||
stream << "Long";
|
|
||||||
break;
|
|
||||||
case ESM::VT_Float:
|
|
||||||
stream << "Float";
|
|
||||||
break;
|
|
||||||
case ESM::VT_String:
|
|
||||||
stream << "String";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream << "unknown";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stream << " type";
|
|
||||||
|
|
||||||
messages.add(id, stream.str(), "", CSMDoc::Message::Severity_Error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (infoCondition.conditionIsAlwaysTrue())
|
else if (infoCondition.conditionIsAlwaysTrue())
|
||||||
{
|
{
|
||||||
messages.add(
|
messages.add(
|
||||||
@ -365,48 +330,48 @@ bool CSMTools::TopicInfoCheckStage::verifySelectStruct(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Id checks
|
// Id checks
|
||||||
if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Global
|
if (select.mFunction == ESM::DialogueCondition::Function_Global
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mGlobals, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mGlobals, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Journal
|
else if (select.mFunction == ESM::DialogueCondition::Function_Journal
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mJournals, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mJournals, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Item
|
else if (select.mFunction == ESM::DialogueCondition::Function_Item
|
||||||
&& !verifyItem(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
|
&& !verifyItem(ESM::RefId::stringRefId(select.mVariable), id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Dead
|
else if (select.mFunction == ESM::DialogueCondition::Function_Dead
|
||||||
&& !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
|
&& !verifyActor(ESM::RefId::stringRefId(select.mVariable), id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotId
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotId
|
||||||
&& !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
|
&& !verifyActor(ESM::RefId::stringRefId(select.mVariable), id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotFaction
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotFaction
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mFactions, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mFactions, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotClass
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotClass
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mClasses, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mClasses, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotRace
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotRace
|
||||||
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mRaces, id, messages))
|
&& !verifyId(ESM::RefId::stringRefId(select.mVariable), mRaces, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotCell
|
else if (select.mFunction == ESM::DialogueCondition::Function_NotCell
|
||||||
&& !verifyCell(infoCondition.getVariableName(), id, messages))
|
&& !verifyCell(select.mVariable, id, messages))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ namespace CSMTools
|
|||||||
const ESM::RefId& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
const ESM::RefId& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
bool verifyItem(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
bool verifyItem(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
bool verifySelectStruct(
|
bool verifySelectStruct(
|
||||||
const ESM::DialInfo::SelectStruct& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
const ESM::DialogueCondition& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
bool verifySound(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
bool verifySound(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -67,6 +67,11 @@ namespace CSMWorld
|
|||||||
return mMaleParts[ESM::getMeshPart(index)];
|
return mMaleParts[ESM::getMeshPart(index)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const osg::Vec2f& ActorAdapter::RaceData::getGenderWeightHeight(bool isFemale)
|
||||||
|
{
|
||||||
|
return isFemale ? mWeightsHeights.mFemaleWeightHeight : mWeightsHeights.mMaleWeightHeight;
|
||||||
|
}
|
||||||
|
|
||||||
bool ActorAdapter::RaceData::hasDependency(const ESM::RefId& id) const
|
bool ActorAdapter::RaceData::hasDependency(const ESM::RefId& id) const
|
||||||
{
|
{
|
||||||
return mDependencies.find(id) != mDependencies.end();
|
return mDependencies.find(id) != mDependencies.end();
|
||||||
@ -90,10 +95,11 @@ namespace CSMWorld
|
|||||||
mDependencies.emplace(id);
|
mDependencies.emplace(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorAdapter::RaceData::reset_data(const ESM::RefId& id, bool isBeast)
|
void ActorAdapter::RaceData::reset_data(const ESM::RefId& id, const WeightsHeights& raceStats, bool isBeast)
|
||||||
{
|
{
|
||||||
mId = id;
|
mId = id;
|
||||||
mIsBeast = isBeast;
|
mIsBeast = isBeast;
|
||||||
|
mWeightsHeights = raceStats;
|
||||||
for (auto& str : mFemaleParts)
|
for (auto& str : mFemaleParts)
|
||||||
str = ESM::RefId();
|
str = ESM::RefId();
|
||||||
for (auto& str : mMaleParts)
|
for (auto& str : mMaleParts)
|
||||||
@ -163,6 +169,11 @@ namespace CSMWorld
|
|||||||
return it->second.first;
|
return it->second.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const osg::Vec2f& ActorAdapter::ActorData::getRaceWeightHeight() const
|
||||||
|
{
|
||||||
|
return mRaceData->getGenderWeightHeight(isFemale());
|
||||||
|
}
|
||||||
|
|
||||||
bool ActorAdapter::ActorData::hasDependency(const ESM::RefId& id) const
|
bool ActorAdapter::ActorData::hasDependency(const ESM::RefId& id) const
|
||||||
{
|
{
|
||||||
return mDependencies.find(id) != mDependencies.end();
|
return mDependencies.find(id) != mDependencies.end();
|
||||||
@ -504,7 +515,11 @@ namespace CSMWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& race = raceRecord.get();
|
auto& race = raceRecord.get();
|
||||||
data->reset_data(id, race.mData.mFlags & ESM::Race::Beast);
|
|
||||||
|
WeightsHeights scaleStats = { osg::Vec2f(race.mData.mMaleWeight, race.mData.mMaleHeight),
|
||||||
|
osg::Vec2f(race.mData.mFemaleWeight, race.mData.mFemaleHeight) };
|
||||||
|
|
||||||
|
data->reset_data(id, scaleStats, race.mData.mFlags & ESM::Race::Beast);
|
||||||
|
|
||||||
// Setup body parts
|
// Setup body parts
|
||||||
for (int i = 0; i < mBodyParts.getSize(); ++i)
|
for (int i = 0; i < mBodyParts.getSize(); ++i)
|
||||||
|
@ -41,6 +41,12 @@ namespace CSMWorld
|
|||||||
/// Tracks unique strings
|
/// Tracks unique strings
|
||||||
using RefIdSet = std::unordered_set<ESM::RefId>;
|
using RefIdSet = std::unordered_set<ESM::RefId>;
|
||||||
|
|
||||||
|
struct WeightsHeights
|
||||||
|
{
|
||||||
|
osg::Vec2f mMaleWeightHeight;
|
||||||
|
osg::Vec2f mFemaleWeightHeight;
|
||||||
|
};
|
||||||
|
|
||||||
/// Contains base race data shared between actors
|
/// Contains base race data shared between actors
|
||||||
class RaceData
|
class RaceData
|
||||||
{
|
{
|
||||||
@ -57,6 +63,8 @@ namespace CSMWorld
|
|||||||
const ESM::RefId& getFemalePart(ESM::PartReferenceType index) const;
|
const ESM::RefId& getFemalePart(ESM::PartReferenceType index) const;
|
||||||
/// Retrieves the associated body part
|
/// Retrieves the associated body part
|
||||||
const ESM::RefId& getMalePart(ESM::PartReferenceType index) const;
|
const ESM::RefId& getMalePart(ESM::PartReferenceType index) const;
|
||||||
|
|
||||||
|
const osg::Vec2f& getGenderWeightHeight(bool isFemale);
|
||||||
/// Checks if the race has a data dependency
|
/// Checks if the race has a data dependency
|
||||||
bool hasDependency(const ESM::RefId& id) const;
|
bool hasDependency(const ESM::RefId& id) const;
|
||||||
|
|
||||||
@ -67,7 +75,8 @@ namespace CSMWorld
|
|||||||
/// Marks an additional dependency
|
/// Marks an additional dependency
|
||||||
void addOtherDependency(const ESM::RefId& id);
|
void addOtherDependency(const ESM::RefId& id);
|
||||||
/// Clears parts and dependencies
|
/// Clears parts and dependencies
|
||||||
void reset_data(const ESM::RefId& raceId, bool isBeast = false);
|
void reset_data(const ESM::RefId& raceId,
|
||||||
|
const WeightsHeights& raceStats = { osg::Vec2f(1.f, 1.f), osg::Vec2f(1.f, 1.f) }, bool isBeast = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool handles(ESM::PartReferenceType type) const;
|
bool handles(ESM::PartReferenceType type) const;
|
||||||
@ -75,6 +84,7 @@ namespace CSMWorld
|
|||||||
bool mIsBeast;
|
bool mIsBeast;
|
||||||
RacePartList mFemaleParts;
|
RacePartList mFemaleParts;
|
||||||
RacePartList mMaleParts;
|
RacePartList mMaleParts;
|
||||||
|
WeightsHeights mWeightsHeights;
|
||||||
RefIdSet mDependencies;
|
RefIdSet mDependencies;
|
||||||
};
|
};
|
||||||
using RaceDataPtr = std::shared_ptr<RaceData>;
|
using RaceDataPtr = std::shared_ptr<RaceData>;
|
||||||
@ -96,6 +106,8 @@ namespace CSMWorld
|
|||||||
std::string getSkeleton() const;
|
std::string getSkeleton() const;
|
||||||
/// Retrieves the associated actor part
|
/// Retrieves the associated actor part
|
||||||
ESM::RefId getPart(ESM::PartReferenceType index) const;
|
ESM::RefId getPart(ESM::PartReferenceType index) const;
|
||||||
|
|
||||||
|
const osg::Vec2f& getRaceWeightHeight() const;
|
||||||
/// Checks if the actor has a data dependency
|
/// Checks if the actor has a data dependency
|
||||||
bool hasDependency(const ESM::RefId& id) const;
|
bool hasDependency(const ESM::RefId& id) const;
|
||||||
|
|
||||||
|
@ -585,19 +585,22 @@ namespace CSMWorld
|
|||||||
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
||||||
{
|
{
|
||||||
ESXRecordT record2 = record.get();
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
float bodyAttr = std::clamp(data.toFloat(), 0.5f, 2.0f);
|
||||||
|
|
||||||
if (mWeight)
|
if (mWeight)
|
||||||
{
|
{
|
||||||
if (mMale)
|
if (mMale)
|
||||||
record2.mData.mMaleWeight = data.toFloat();
|
record2.mData.mMaleWeight = bodyAttr;
|
||||||
else
|
else
|
||||||
record2.mData.mFemaleWeight = data.toFloat();
|
record2.mData.mFemaleWeight = bodyAttr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mMale)
|
if (mMale)
|
||||||
record2.mData.mMaleHeight = data.toFloat();
|
record2.mData.mMaleHeight = bodyAttr;
|
||||||
else
|
else
|
||||||
record2.mData.mFemaleHeight = data.toFloat();
|
record2.mData.mFemaleHeight = bodyAttr;
|
||||||
}
|
}
|
||||||
record.setModified(record2);
|
record.setModified(record2);
|
||||||
}
|
}
|
||||||
@ -968,7 +971,7 @@ namespace CSMWorld
|
|||||||
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
||||||
{
|
{
|
||||||
ESXRecordT record2 = record.get();
|
ESXRecordT record2 = record.get();
|
||||||
record2.mScale = data.toFloat();
|
record2.mScale = std::clamp(data.toFloat(), 0.5f, 2.0f);
|
||||||
record.setModified(record2);
|
record.setModified(record2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,8 +1136,8 @@ namespace CSMWorld
|
|||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
struct TeleportColumn : public Column<ESXRecordT>
|
struct TeleportColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
TeleportColumn()
|
TeleportColumn(int flags)
|
||||||
: Column<ESXRecordT>(Columns::ColumnId_Teleport, ColumnBase::Display_Boolean)
|
: Column<ESXRecordT>(Columns::ColumnId_Teleport, ColumnBase::Display_Boolean, flags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1162,6 +1165,8 @@ namespace CSMWorld
|
|||||||
|
|
||||||
QVariant get(const Record<ESXRecordT>& record) const override
|
QVariant get(const Record<ESXRecordT>& record) const override
|
||||||
{
|
{
|
||||||
|
if (!record.get().mTeleport)
|
||||||
|
return QVariant();
|
||||||
return QString::fromUtf8(record.get().mDestCell.c_str());
|
return QString::fromUtf8(record.get().mDestCell.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1179,6 +1184,26 @@ namespace CSMWorld
|
|||||||
bool isUserEditable() const override { return true; }
|
bool isUserEditable() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ESXRecordT>
|
||||||
|
struct IsLockedColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
IsLockedColumn(int flags)
|
||||||
|
: Column<ESXRecordT>(Columns::ColumnId_IsLocked, ColumnBase::Display_Boolean, flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant get(const Record<ESXRecordT>& record) const override { return record.get().mIsLocked; }
|
||||||
|
|
||||||
|
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
record2.mIsLocked = data.toBool();
|
||||||
|
record.setModified(record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEditable() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
struct LockLevelColumn : public Column<ESXRecordT>
|
struct LockLevelColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
@ -1187,7 +1212,12 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant get(const Record<ESXRecordT>& record) const override { return record.get().mLockLevel; }
|
QVariant get(const Record<ESXRecordT>& record) const override
|
||||||
|
{
|
||||||
|
if (record.get().mIsLocked)
|
||||||
|
return record.get().mLockLevel;
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
||||||
{
|
{
|
||||||
@ -1209,7 +1239,9 @@ namespace CSMWorld
|
|||||||
|
|
||||||
QVariant get(const Record<ESXRecordT>& record) const override
|
QVariant get(const Record<ESXRecordT>& record) const override
|
||||||
{
|
{
|
||||||
return QString::fromUtf8(record.get().mKey.getRefIdString().c_str());
|
if (record.get().mIsLocked)
|
||||||
|
return QString::fromUtf8(record.get().mKey.getRefIdString().c_str());
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
||||||
@ -1279,17 +1311,21 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
ESM::Position ESXRecordT::*mPosition;
|
ESM::Position ESXRecordT::*mPosition;
|
||||||
int mIndex;
|
int mIndex;
|
||||||
|
bool mIsDoor;
|
||||||
|
|
||||||
PosColumn(ESM::Position ESXRecordT::*position, int index, bool door)
|
PosColumn(ESM::Position ESXRecordT::*position, int index, bool door)
|
||||||
: Column<ESXRecordT>((door ? Columns::ColumnId_DoorPositionXPos : Columns::ColumnId_PositionXPos) + index,
|
: Column<ESXRecordT>((door ? Columns::ColumnId_DoorPositionXPos : Columns::ColumnId_PositionXPos) + index,
|
||||||
ColumnBase::Display_Float)
|
ColumnBase::Display_Float)
|
||||||
, mPosition(position)
|
, mPosition(position)
|
||||||
, mIndex(index)
|
, mIndex(index)
|
||||||
|
, mIsDoor(door)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant get(const Record<ESXRecordT>& record) const override
|
QVariant get(const Record<ESXRecordT>& record) const override
|
||||||
{
|
{
|
||||||
|
if (!record.get().mTeleport && mIsDoor)
|
||||||
|
return QVariant();
|
||||||
const ESM::Position& position = record.get().*mPosition;
|
const ESM::Position& position = record.get().*mPosition;
|
||||||
return position.pos[mIndex];
|
return position.pos[mIndex];
|
||||||
}
|
}
|
||||||
@ -1313,17 +1349,21 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
ESM::Position ESXRecordT::*mPosition;
|
ESM::Position ESXRecordT::*mPosition;
|
||||||
int mIndex;
|
int mIndex;
|
||||||
|
bool mIsDoor;
|
||||||
|
|
||||||
RotColumn(ESM::Position ESXRecordT::*position, int index, bool door)
|
RotColumn(ESM::Position ESXRecordT::*position, int index, bool door)
|
||||||
: Column<ESXRecordT>((door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot) + index,
|
: Column<ESXRecordT>((door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot) + index,
|
||||||
ColumnBase::Display_Double)
|
ColumnBase::Display_Double)
|
||||||
, mPosition(position)
|
, mPosition(position)
|
||||||
, mIndex(index)
|
, mIndex(index)
|
||||||
|
, mIsDoor(door)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant get(const Record<ESXRecordT>& record) const override
|
QVariant get(const Record<ESXRecordT>& record) const override
|
||||||
{
|
{
|
||||||
|
if (!record.get().mTeleport && mIsDoor)
|
||||||
|
return QVariant();
|
||||||
const ESM::Position& position = record.get().*mPosition;
|
const ESM::Position& position = record.get().*mPosition;
|
||||||
return osg::RadiansToDegrees(position.rot[mIndex]);
|
return osg::RadiansToDegrees(position.rot[mIndex]);
|
||||||
}
|
}
|
||||||
@ -2049,6 +2089,26 @@ namespace CSMWorld
|
|||||||
bool isEditable() const override { return true; }
|
bool isEditable() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ESXRecordT>
|
||||||
|
struct ProjectileSpeedColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
ProjectileSpeedColumn()
|
||||||
|
: Column<ESXRecordT>(Columns::ColumnId_ProjectileSpeed, ColumnBase::Display_Float)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant get(const Record<ESXRecordT>& record) const override { return record.get().mData.mSpeed; }
|
||||||
|
|
||||||
|
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
record2.mData.mSpeed = data.toFloat();
|
||||||
|
record.setModified(record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEditable() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
struct SchoolColumn : public Column<ESXRecordT>
|
struct SchoolColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
|
@ -57,8 +57,10 @@ namespace CSMWorld
|
|||||||
{ ColumnId_Charges, "Charges" },
|
{ ColumnId_Charges, "Charges" },
|
||||||
{ ColumnId_Enchantment, "Enchantment" },
|
{ ColumnId_Enchantment, "Enchantment" },
|
||||||
{ ColumnId_StackCount, "Count" },
|
{ ColumnId_StackCount, "Count" },
|
||||||
|
{ ColumnId_GoldValue, "Value" },
|
||||||
{ ColumnId_Teleport, "Teleport" },
|
{ ColumnId_Teleport, "Teleport" },
|
||||||
{ ColumnId_TeleportCell, "Teleport Cell" },
|
{ ColumnId_TeleportCell, "Teleport Cell" },
|
||||||
|
{ ColumnId_IsLocked, "Locked" },
|
||||||
{ ColumnId_LockLevel, "Lock Level" },
|
{ ColumnId_LockLevel, "Lock Level" },
|
||||||
{ ColumnId_Key, "Key" },
|
{ ColumnId_Key, "Key" },
|
||||||
{ ColumnId_Trap, "Trap" },
|
{ ColumnId_Trap, "Trap" },
|
||||||
@ -235,6 +237,7 @@ namespace CSMWorld
|
|||||||
{ ColumnId_RegionSounds, "Sounds" },
|
{ ColumnId_RegionSounds, "Sounds" },
|
||||||
{ ColumnId_SoundName, "Sound Name" },
|
{ ColumnId_SoundName, "Sound Name" },
|
||||||
{ ColumnId_SoundChance, "Chance" },
|
{ ColumnId_SoundChance, "Chance" },
|
||||||
|
{ ColumnId_SoundProbability, "Probability" },
|
||||||
|
|
||||||
{ ColumnId_FactionReactions, "Reactions" },
|
{ ColumnId_FactionReactions, "Reactions" },
|
||||||
{ ColumnId_FactionRanks, "Ranks" },
|
{ ColumnId_FactionRanks, "Ranks" },
|
||||||
@ -321,7 +324,6 @@ namespace CSMWorld
|
|||||||
{ ColumnId_MaxAttack, "Max Attack" },
|
{ ColumnId_MaxAttack, "Max Attack" },
|
||||||
{ ColumnId_CreatureMisc, "Creature Misc" },
|
{ ColumnId_CreatureMisc, "Creature Misc" },
|
||||||
|
|
||||||
{ ColumnId_Idle1, "Idle 1" },
|
|
||||||
{ ColumnId_Idle2, "Idle 2" },
|
{ ColumnId_Idle2, "Idle 2" },
|
||||||
{ ColumnId_Idle3, "Idle 3" },
|
{ ColumnId_Idle3, "Idle 3" },
|
||||||
{ ColumnId_Idle4, "Idle 4" },
|
{ ColumnId_Idle4, "Idle 4" },
|
||||||
@ -329,6 +331,7 @@ namespace CSMWorld
|
|||||||
{ ColumnId_Idle6, "Idle 6" },
|
{ ColumnId_Idle6, "Idle 6" },
|
||||||
{ ColumnId_Idle7, "Idle 7" },
|
{ ColumnId_Idle7, "Idle 7" },
|
||||||
{ ColumnId_Idle8, "Idle 8" },
|
{ ColumnId_Idle8, "Idle 8" },
|
||||||
|
{ ColumnId_Idle9, "Idle 9" },
|
||||||
|
|
||||||
{ ColumnId_RegionWeather, "Weather" },
|
{ ColumnId_RegionWeather, "Weather" },
|
||||||
{ ColumnId_WeatherName, "Type" },
|
{ ColumnId_WeatherName, "Type" },
|
||||||
@ -376,6 +379,7 @@ namespace CSMWorld
|
|||||||
{ ColumnId_Blocked, "Blocked" },
|
{ ColumnId_Blocked, "Blocked" },
|
||||||
|
|
||||||
{ ColumnId_LevelledCreatureId, "Levelled Creature" },
|
{ ColumnId_LevelledCreatureId, "Levelled Creature" },
|
||||||
|
{ ColumnId_ProjectileSpeed, "Projectile Speed" },
|
||||||
|
|
||||||
// end marker
|
// end marker
|
||||||
{ -1, 0 },
|
{ -1, 0 },
|
||||||
|
@ -310,14 +310,14 @@ namespace CSMWorld
|
|||||||
ColumnId_MaxAttack = 284,
|
ColumnId_MaxAttack = 284,
|
||||||
ColumnId_CreatureMisc = 285,
|
ColumnId_CreatureMisc = 285,
|
||||||
|
|
||||||
ColumnId_Idle1 = 286,
|
ColumnId_Idle2 = 286,
|
||||||
ColumnId_Idle2 = 287,
|
ColumnId_Idle3 = 287,
|
||||||
ColumnId_Idle3 = 288,
|
ColumnId_Idle4 = 288,
|
||||||
ColumnId_Idle4 = 289,
|
ColumnId_Idle5 = 289,
|
||||||
ColumnId_Idle5 = 290,
|
ColumnId_Idle6 = 290,
|
||||||
ColumnId_Idle6 = 291,
|
ColumnId_Idle7 = 291,
|
||||||
ColumnId_Idle7 = 292,
|
ColumnId_Idle8 = 292,
|
||||||
ColumnId_Idle8 = 293,
|
ColumnId_Idle9 = 293,
|
||||||
|
|
||||||
ColumnId_RegionWeather = 294,
|
ColumnId_RegionWeather = 294,
|
||||||
ColumnId_WeatherName = 295,
|
ColumnId_WeatherName = 295,
|
||||||
@ -349,6 +349,14 @@ namespace CSMWorld
|
|||||||
|
|
||||||
ColumnId_SelectionGroupObjects = 316,
|
ColumnId_SelectionGroupObjects = 316,
|
||||||
|
|
||||||
|
ColumnId_SoundProbability = 317,
|
||||||
|
|
||||||
|
ColumnId_IsLocked = 318,
|
||||||
|
|
||||||
|
ColumnId_ProjectileSpeed = 319,
|
||||||
|
|
||||||
|
ColumnId_GoldValue = 320,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
ColumnId_UseValue1 = 0x10000,
|
ColumnId_UseValue1 = 0x10000,
|
||||||
|
@ -161,7 +161,7 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
defines["radialFog"] = "0";
|
defines["radialFog"] = "0";
|
||||||
defines["lightingModel"] = "0";
|
defines["lightingModel"] = "0";
|
||||||
defines["reverseZ"] = "0";
|
defines["reverseZ"] = "0";
|
||||||
defines["refraction_enabled"] = "0";
|
defines["waterRefraction"] = "0";
|
||||||
for (const auto& define : shadowDefines)
|
for (const auto& define : shadowDefines)
|
||||||
defines[define.first] = define.second;
|
defines[define.first] = define.second;
|
||||||
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
|
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
|
||||||
@ -301,8 +301,8 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
mRegions.addColumn(new NestedParentColumn<ESM::Region>(Columns::ColumnId_RegionWeather));
|
mRegions.addColumn(new NestedParentColumn<ESM::Region>(Columns::ColumnId_RegionWeather));
|
||||||
index = mRegions.getColumns() - 1;
|
index = mRegions.getColumns() - 1;
|
||||||
mRegions.addAdapter(std::make_pair(&mRegions.getColumn(index), new RegionWeatherAdapter()));
|
mRegions.addAdapter(std::make_pair(&mRegions.getColumn(index), new RegionWeatherAdapter()));
|
||||||
mRegions.getNestableColumn(index)->addColumn(
|
mRegions.getNestableColumn(index)->addColumn(new NestedChildColumn(
|
||||||
new NestedChildColumn(Columns::ColumnId_WeatherName, ColumnBase::Display_String, false));
|
Columns::ColumnId_WeatherName, ColumnBase::Display_String, ColumnBase::Flag_Dialogue, false));
|
||||||
mRegions.getNestableColumn(index)->addColumn(
|
mRegions.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn(Columns::ColumnId_WeatherChance, ColumnBase::Display_UnsignedInteger8));
|
new NestedChildColumn(Columns::ColumnId_WeatherChance, ColumnBase::Display_UnsignedInteger8));
|
||||||
// Region Sounds
|
// Region Sounds
|
||||||
@ -313,6 +313,8 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
new NestedChildColumn(Columns::ColumnId_SoundName, ColumnBase::Display_Sound));
|
new NestedChildColumn(Columns::ColumnId_SoundName, ColumnBase::Display_Sound));
|
||||||
mRegions.getNestableColumn(index)->addColumn(
|
mRegions.getNestableColumn(index)->addColumn(
|
||||||
new NestedChildColumn(Columns::ColumnId_SoundChance, ColumnBase::Display_UnsignedInteger8));
|
new NestedChildColumn(Columns::ColumnId_SoundChance, ColumnBase::Display_UnsignedInteger8));
|
||||||
|
mRegions.getNestableColumn(index)->addColumn(new NestedChildColumn(
|
||||||
|
Columns::ColumnId_SoundProbability, ColumnBase::Display_String, ColumnBase::Flag_Dialogue, false));
|
||||||
|
|
||||||
mBirthsigns.addColumn(new StringIdColumn<ESM::BirthSign>);
|
mBirthsigns.addColumn(new StringIdColumn<ESM::BirthSign>);
|
||||||
mBirthsigns.addColumn(new RecordStateColumn<ESM::BirthSign>);
|
mBirthsigns.addColumn(new RecordStateColumn<ESM::BirthSign>);
|
||||||
@ -500,6 +502,7 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
mMagicEffects.addColumn(new FixedRecordTypeColumn<ESM::MagicEffect>(UniversalId::Type_MagicEffect));
|
mMagicEffects.addColumn(new FixedRecordTypeColumn<ESM::MagicEffect>(UniversalId::Type_MagicEffect));
|
||||||
mMagicEffects.addColumn(new SchoolColumn<ESM::MagicEffect>);
|
mMagicEffects.addColumn(new SchoolColumn<ESM::MagicEffect>);
|
||||||
mMagicEffects.addColumn(new BaseCostColumn<ESM::MagicEffect>);
|
mMagicEffects.addColumn(new BaseCostColumn<ESM::MagicEffect>);
|
||||||
|
mMagicEffects.addColumn(new ProjectileSpeedColumn<ESM::MagicEffect>);
|
||||||
mMagicEffects.addColumn(new EffectTextureColumn<ESM::MagicEffect>(Columns::ColumnId_Icon));
|
mMagicEffects.addColumn(new EffectTextureColumn<ESM::MagicEffect>(Columns::ColumnId_Icon));
|
||||||
mMagicEffects.addColumn(new EffectTextureColumn<ESM::MagicEffect>(Columns::ColumnId_Particle));
|
mMagicEffects.addColumn(new EffectTextureColumn<ESM::MagicEffect>(Columns::ColumnId_Particle));
|
||||||
mMagicEffects.addColumn(new EffectObjectColumn<ESM::MagicEffect>(Columns::ColumnId_CastingObject));
|
mMagicEffects.addColumn(new EffectObjectColumn<ESM::MagicEffect>(Columns::ColumnId_CastingObject));
|
||||||
@ -510,6 +513,7 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_HitSound));
|
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_HitSound));
|
||||||
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_AreaSound));
|
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_AreaSound));
|
||||||
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_BoltSound));
|
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_BoltSound));
|
||||||
|
|
||||||
mMagicEffects.addColumn(
|
mMagicEffects.addColumn(
|
||||||
new FlagColumn<ESM::MagicEffect>(Columns::ColumnId_AllowSpellmaking, ESM::MagicEffect::AllowSpellmaking));
|
new FlagColumn<ESM::MagicEffect>(Columns::ColumnId_AllowSpellmaking, ESM::MagicEffect::AllowSpellmaking));
|
||||||
mMagicEffects.addColumn(
|
mMagicEffects.addColumn(
|
||||||
@ -589,7 +593,8 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
mRefs.addColumn(new ChargesColumn<CellRef>);
|
mRefs.addColumn(new ChargesColumn<CellRef>);
|
||||||
mRefs.addColumn(new EnchantmentChargesColumn<CellRef>);
|
mRefs.addColumn(new EnchantmentChargesColumn<CellRef>);
|
||||||
mRefs.addColumn(new StackSizeColumn<CellRef>);
|
mRefs.addColumn(new StackSizeColumn<CellRef>);
|
||||||
mRefs.addColumn(new TeleportColumn<CellRef>);
|
mRefs.addColumn(new TeleportColumn<CellRef>(
|
||||||
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
|
||||||
mRefs.addColumn(new TeleportCellColumn<CellRef>);
|
mRefs.addColumn(new TeleportCellColumn<CellRef>);
|
||||||
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mDoorDest, 0, true));
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mDoorDest, 0, true));
|
||||||
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mDoorDest, 1, true));
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mDoorDest, 1, true));
|
||||||
@ -597,6 +602,8 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 0, true));
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 0, true));
|
||||||
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 1, true));
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 1, true));
|
||||||
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 2, true));
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 2, true));
|
||||||
|
mRefs.addColumn(new IsLockedColumn<CellRef>(
|
||||||
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
|
||||||
mRefs.addColumn(new LockLevelColumn<CellRef>);
|
mRefs.addColumn(new LockLevelColumn<CellRef>);
|
||||||
mRefs.addColumn(new KeyColumn<CellRef>);
|
mRefs.addColumn(new KeyColumn<CellRef>);
|
||||||
mRefs.addColumn(new TrapColumn<CellRef>);
|
mRefs.addColumn(new TrapColumn<CellRef>);
|
||||||
|
@ -63,9 +63,18 @@ bool CSMWorld::IdTableProxyModel::filterAcceptsRow(int sourceRow, const QModelIn
|
|||||||
|
|
||||||
CSMWorld::IdTableProxyModel::IdTableProxyModel(QObject* parent)
|
CSMWorld::IdTableProxyModel::IdTableProxyModel(QObject* parent)
|
||||||
: QSortFilterProxyModel(parent)
|
: QSortFilterProxyModel(parent)
|
||||||
|
, mFilterTimer{ new QTimer(this) }
|
||||||
, mSourceModel(nullptr)
|
, mSourceModel(nullptr)
|
||||||
{
|
{
|
||||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
|
||||||
|
mFilterTimer->setSingleShot(true);
|
||||||
|
int intervalSetting = CSMPrefs::State::get()["ID Tables"]["filter-delay"].toInt();
|
||||||
|
mFilterTimer->setInterval(intervalSetting);
|
||||||
|
|
||||||
|
connect(&CSMPrefs::State::get(), &CSMPrefs::State::settingChanged, this,
|
||||||
|
[this](const CSMPrefs::Setting* setting) { this->settingChanged(setting); });
|
||||||
|
connect(mFilterTimer.get(), &QTimer::timeout, this, [this]() { this->timerTimeout(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex(const std::string& id, int column) const
|
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex(const std::string& id, int column) const
|
||||||
@ -87,10 +96,8 @@ void CSMWorld::IdTableProxyModel::setSourceModel(QAbstractItemModel* model)
|
|||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::setFilter(const std::shared_ptr<CSMFilter::Node>& filter)
|
void CSMWorld::IdTableProxyModel::setFilter(const std::shared_ptr<CSMFilter::Node>& filter)
|
||||||
{
|
{
|
||||||
beginResetModel();
|
mAwaitingFilter = filter;
|
||||||
mFilter = filter;
|
mFilterTimer->start();
|
||||||
updateColumnMap();
|
|
||||||
endResetModel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
|
bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const
|
||||||
@ -131,6 +138,26 @@ void CSMWorld::IdTableProxyModel::refreshFilter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::IdTableProxyModel::timerTimeout()
|
||||||
|
{
|
||||||
|
if (mAwaitingFilter)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
mFilter = mAwaitingFilter;
|
||||||
|
updateColumnMap();
|
||||||
|
endResetModel();
|
||||||
|
mAwaitingFilter.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::IdTableProxyModel::settingChanged(const CSMPrefs::Setting* setting)
|
||||||
|
{
|
||||||
|
if (*setting == "ID Tables/filter-delay")
|
||||||
|
{
|
||||||
|
mFilterTimer->setInterval(setting->toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::sourceRowsInserted(const QModelIndex& parent, int /*start*/, int end)
|
void CSMWorld::IdTableProxyModel::sourceRowsInserted(const QModelIndex& parent, int /*start*/, int end)
|
||||||
{
|
{
|
||||||
refreshFilter();
|
refreshFilter();
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "../prefs/state.hpp"
|
||||||
|
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
|
|
||||||
@ -29,6 +32,8 @@ namespace CSMWorld
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
std::shared_ptr<CSMFilter::Node> mFilter;
|
std::shared_ptr<CSMFilter::Node> mFilter;
|
||||||
|
std::unique_ptr<QTimer> mFilterTimer;
|
||||||
|
std::shared_ptr<CSMFilter::Node> mAwaitingFilter;
|
||||||
std::map<int, int> mColumnMap; // column ID, column index in this model (or -1)
|
std::map<int, int> mColumnMap; // column ID, column index in this model (or -1)
|
||||||
|
|
||||||
// Cache of enum values for enum columns (e.g. Modified, Record Type).
|
// Cache of enum values for enum columns (e.g. Modified, Record Type).
|
||||||
@ -68,6 +73,10 @@ namespace CSMWorld
|
|||||||
|
|
||||||
virtual void sourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
virtual void sourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
void timerTimeout();
|
||||||
|
|
||||||
|
void settingChanged(const CSMPrefs::Setting* setting);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void rowAdded(const std::string& id);
|
void rowAdded(const std::string& id);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,133 +7,13 @@
|
|||||||
|
|
||||||
#include <components/esm3/loadinfo.hpp>
|
#include <components/esm3/loadinfo.hpp>
|
||||||
|
|
||||||
namespace ESM
|
#include <QVariant>
|
||||||
{
|
|
||||||
class Variant;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
// ESM::DialInfo::SelectStruct.mSelectRule
|
|
||||||
// 012345...
|
|
||||||
// ^^^ ^^
|
|
||||||
// ||| ||
|
|
||||||
// ||| |+------------- condition variable string
|
|
||||||
// ||| +-------------- comparison type, ['0'..'5']; e.g. !=, <, >=, etc
|
|
||||||
// ||+---------------- function index (encoded, where function == '1')
|
|
||||||
// |+----------------- function, ['1'..'C']; e.g. Global, Local, Not ID, etc
|
|
||||||
// +------------------ unknown
|
|
||||||
//
|
|
||||||
|
|
||||||
// Wrapper for DialInfo::SelectStruct
|
|
||||||
class ConstInfoSelectWrapper
|
class ConstInfoSelectWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Order matters
|
|
||||||
enum FunctionName
|
|
||||||
{
|
|
||||||
Function_RankLow = 0,
|
|
||||||
Function_RankHigh,
|
|
||||||
Function_RankRequirement,
|
|
||||||
Function_Reputation,
|
|
||||||
Function_Health_Percent,
|
|
||||||
Function_PcReputation,
|
|
||||||
Function_PcLevel,
|
|
||||||
Function_PcHealthPercent,
|
|
||||||
Function_PcMagicka,
|
|
||||||
Function_PcFatigue,
|
|
||||||
Function_PcStrength,
|
|
||||||
Function_PcBlock,
|
|
||||||
Function_PcArmorer,
|
|
||||||
Function_PcMediumArmor,
|
|
||||||
Function_PcHeavyArmor,
|
|
||||||
Function_PcBluntWeapon,
|
|
||||||
Function_PcLongBlade,
|
|
||||||
Function_PcAxe,
|
|
||||||
Function_PcSpear,
|
|
||||||
Function_PcAthletics,
|
|
||||||
Function_PcEnchant,
|
|
||||||
Function_PcDestruction,
|
|
||||||
Function_PcAlteration,
|
|
||||||
Function_PcIllusion,
|
|
||||||
Function_PcConjuration,
|
|
||||||
Function_PcMysticism,
|
|
||||||
Function_PcRestoration,
|
|
||||||
Function_PcAlchemy,
|
|
||||||
Function_PcUnarmored,
|
|
||||||
Function_PcSecurity,
|
|
||||||
Function_PcSneak,
|
|
||||||
Function_PcAcrobatics,
|
|
||||||
Function_PcLightArmor,
|
|
||||||
Function_PcShortBlade,
|
|
||||||
Function_PcMarksman,
|
|
||||||
Function_PcMerchantile,
|
|
||||||
Function_PcSpeechcraft,
|
|
||||||
Function_PcHandToHand,
|
|
||||||
Function_PcGender,
|
|
||||||
Function_PcExpelled,
|
|
||||||
Function_PcCommonDisease,
|
|
||||||
Function_PcBlightDisease,
|
|
||||||
Function_PcClothingModifier,
|
|
||||||
Function_PcCrimeLevel,
|
|
||||||
Function_SameSex,
|
|
||||||
Function_SameRace,
|
|
||||||
Function_SameFaction,
|
|
||||||
Function_FactionRankDifference,
|
|
||||||
Function_Detected,
|
|
||||||
Function_Alarmed,
|
|
||||||
Function_Choice,
|
|
||||||
Function_PcIntelligence,
|
|
||||||
Function_PcWillpower,
|
|
||||||
Function_PcAgility,
|
|
||||||
Function_PcSpeed,
|
|
||||||
Function_PcEndurance,
|
|
||||||
Function_PcPersonality,
|
|
||||||
Function_PcLuck,
|
|
||||||
Function_PcCorpus,
|
|
||||||
Function_Weather,
|
|
||||||
Function_PcVampire,
|
|
||||||
Function_Level,
|
|
||||||
Function_Attacked,
|
|
||||||
Function_TalkedToPc,
|
|
||||||
Function_PcHealth,
|
|
||||||
Function_CreatureTarget,
|
|
||||||
Function_FriendHit,
|
|
||||||
Function_Fight,
|
|
||||||
Function_Hello,
|
|
||||||
Function_Alarm,
|
|
||||||
Function_Flee,
|
|
||||||
Function_ShouldAttack,
|
|
||||||
Function_Werewolf,
|
|
||||||
Function_PcWerewolfKills = 73,
|
|
||||||
|
|
||||||
Function_Global,
|
|
||||||
Function_Local,
|
|
||||||
Function_Journal,
|
|
||||||
Function_Item,
|
|
||||||
Function_Dead,
|
|
||||||
Function_NotId,
|
|
||||||
Function_NotFaction,
|
|
||||||
Function_NotClass,
|
|
||||||
Function_NotRace,
|
|
||||||
Function_NotCell,
|
|
||||||
Function_NotLocal,
|
|
||||||
|
|
||||||
Function_None
|
|
||||||
};
|
|
||||||
|
|
||||||
enum RelationType
|
|
||||||
{
|
|
||||||
Relation_Equal,
|
|
||||||
Relation_NotEqual,
|
|
||||||
Relation_Greater,
|
|
||||||
Relation_GreaterOrEqual,
|
|
||||||
Relation_Less,
|
|
||||||
Relation_LessOrEqual,
|
|
||||||
|
|
||||||
Relation_None
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ComparisonType
|
enum ComparisonType
|
||||||
{
|
{
|
||||||
Comparison_Boolean,
|
Comparison_Boolean,
|
||||||
@ -143,25 +23,13 @@ namespace CSMWorld
|
|||||||
Comparison_None
|
Comparison_None
|
||||||
};
|
};
|
||||||
|
|
||||||
static const size_t RuleMinSize;
|
|
||||||
|
|
||||||
static const size_t FunctionPrefixOffset;
|
|
||||||
static const size_t FunctionIndexOffset;
|
|
||||||
static const size_t RelationIndexOffset;
|
|
||||||
static const size_t VarNameOffset;
|
|
||||||
|
|
||||||
static const char* FunctionEnumStrings[];
|
static const char* FunctionEnumStrings[];
|
||||||
static const char* RelationEnumStrings[];
|
static const char* RelationEnumStrings[];
|
||||||
static const char* ComparisonEnumStrings[];
|
|
||||||
|
|
||||||
static std::string convertToString(FunctionName name);
|
ConstInfoSelectWrapper(const ESM::DialogueCondition& select);
|
||||||
static std::string convertToString(RelationType type);
|
|
||||||
static std::string convertToString(ComparisonType type);
|
|
||||||
|
|
||||||
ConstInfoSelectWrapper(const ESM::DialInfo::SelectStruct& select);
|
ESM::DialogueCondition::Function getFunctionName() const;
|
||||||
|
ESM::DialogueCondition::Comparison getRelationType() const;
|
||||||
FunctionName getFunctionName() const;
|
|
||||||
RelationType getRelationType() const;
|
|
||||||
ComparisonType getComparisonType() const;
|
ComparisonType getComparisonType() const;
|
||||||
|
|
||||||
bool hasVariable() const;
|
bool hasVariable() const;
|
||||||
@ -169,17 +37,12 @@ namespace CSMWorld
|
|||||||
|
|
||||||
bool conditionIsAlwaysTrue() const;
|
bool conditionIsAlwaysTrue() const;
|
||||||
bool conditionIsNeverTrue() const;
|
bool conditionIsNeverTrue() const;
|
||||||
bool variantTypeIsValid() const;
|
|
||||||
|
|
||||||
const ESM::Variant& getVariant() const;
|
QVariant getValue() const;
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void readRule();
|
|
||||||
void readFunctionName();
|
|
||||||
void readRelationType();
|
|
||||||
void readVariableName();
|
|
||||||
void updateHasVariable();
|
void updateHasVariable();
|
||||||
void updateComparisonType();
|
void updateComparisonType();
|
||||||
|
|
||||||
@ -207,38 +70,29 @@ namespace CSMWorld
|
|||||||
template <typename Type1, typename Type2>
|
template <typename Type1, typename Type2>
|
||||||
bool conditionIsNeverTrue(std::pair<Type1, Type1> conditionRange, std::pair<Type2, Type2> validRange) const;
|
bool conditionIsNeverTrue(std::pair<Type1, Type1> conditionRange, std::pair<Type2, Type2> validRange) const;
|
||||||
|
|
||||||
FunctionName mFunctionName;
|
|
||||||
RelationType mRelationType;
|
|
||||||
ComparisonType mComparisonType;
|
ComparisonType mComparisonType;
|
||||||
|
|
||||||
bool mHasVariable;
|
bool mHasVariable;
|
||||||
std::string mVariableName;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ESM::DialInfo::SelectStruct& mConstSelect;
|
const ESM::DialogueCondition& mConstSelect;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrapper for DialInfo::SelectStruct that can modify the wrapped select struct
|
// Wrapper for DialogueCondition that can modify the wrapped select struct
|
||||||
class InfoSelectWrapper : public ConstInfoSelectWrapper
|
class InfoSelectWrapper : public ConstInfoSelectWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InfoSelectWrapper(ESM::DialInfo::SelectStruct& select);
|
InfoSelectWrapper(ESM::DialogueCondition& select);
|
||||||
|
|
||||||
// Wrapped SelectStruct will not be modified until update() is called
|
// Wrapped SelectStruct will not be modified until update() is called
|
||||||
void setFunctionName(FunctionName name);
|
void setFunctionName(ESM::DialogueCondition::Function name);
|
||||||
void setRelationType(RelationType type);
|
void setRelationType(ESM::DialogueCondition::Comparison type);
|
||||||
void setVariableName(const std::string& name);
|
void setVariableName(const std::string& name);
|
||||||
|
void setValue(int value);
|
||||||
// Modified wrapped SelectStruct
|
void setValue(float value);
|
||||||
void update();
|
|
||||||
|
|
||||||
// This sets properties based on the function name to its defaults and updates the wrapped object
|
|
||||||
void setDefaults();
|
|
||||||
|
|
||||||
ESM::Variant& getVariant();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ESM::DialInfo::SelectStruct& mSelect;
|
ESM::DialogueCondition& mSelect;
|
||||||
|
|
||||||
void writeRule();
|
void writeRule();
|
||||||
};
|
};
|
||||||
|
@ -38,7 +38,6 @@ namespace CSMWorld
|
|||||||
point.mZ = 0;
|
point.mZ = 0;
|
||||||
point.mAutogenerated = 0;
|
point.mAutogenerated = 0;
|
||||||
point.mConnectionNum = 0;
|
point.mConnectionNum = 0;
|
||||||
point.mUnknown = 0;
|
|
||||||
|
|
||||||
points.insert(points.begin() + position, point);
|
points.insert(points.begin() + position, point);
|
||||||
pathgrid.mData.mPoints = pathgrid.mPoints.size();
|
pathgrid.mData.mPoints = pathgrid.mPoints.size();
|
||||||
@ -414,20 +413,32 @@ namespace CSMWorld
|
|||||||
|
|
||||||
QVariant RegionSoundListAdapter::getData(const Record<ESM::Region>& record, int subRowIndex, int subColIndex) const
|
QVariant RegionSoundListAdapter::getData(const Record<ESM::Region>& record, int subRowIndex, int subColIndex) const
|
||||||
{
|
{
|
||||||
ESM::Region region = record.get();
|
const ESM::Region& region = record.get();
|
||||||
|
|
||||||
std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
const std::vector<ESM::Region::SoundRef>& soundList = region.mSoundList;
|
||||||
|
|
||||||
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(soundList.size()))
|
const size_t index = static_cast<size_t>(subRowIndex);
|
||||||
|
if (subRowIndex < 0 || index >= soundList.size())
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
|
|
||||||
ESM::Region::SoundRef soundRef = soundList[subRowIndex];
|
const ESM::Region::SoundRef& soundRef = soundList[subRowIndex];
|
||||||
switch (subColIndex)
|
switch (subColIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return QString(soundRef.mSound.getRefIdString().c_str());
|
return QString(soundRef.mSound.getRefIdString().c_str());
|
||||||
case 1:
|
case 1:
|
||||||
return soundRef.mChance;
|
return soundRef.mChance;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
float probability = 1.f;
|
||||||
|
for (size_t i = 0; i < index; ++i)
|
||||||
|
{
|
||||||
|
const float p = std::min(soundList[i].mChance / 100.f, 1.f);
|
||||||
|
probability *= 1.f - p;
|
||||||
|
}
|
||||||
|
probability *= std::min(soundRef.mChance / 100.f, 1.f) * 100.f;
|
||||||
|
return QString("%1%").arg(probability, 0, 'f', 2);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Region sounds subcolumn index out of range");
|
throw std::runtime_error("Region sounds subcolumn index out of range");
|
||||||
}
|
}
|
||||||
@ -463,7 +474,7 @@ namespace CSMWorld
|
|||||||
|
|
||||||
int RegionSoundListAdapter::getColumnsCount(const Record<ESM::Region>& record) const
|
int RegionSoundListAdapter::getColumnsCount(const Record<ESM::Region>& record) const
|
||||||
{
|
{
|
||||||
return 2;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegionSoundListAdapter::getRowsCount(const Record<ESM::Region>& record) const
|
int RegionSoundListAdapter::getRowsCount(const Record<ESM::Region>& record) const
|
||||||
@ -527,13 +538,11 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
// default row
|
// default row
|
||||||
ESM::DialInfo::SelectStruct condStruct;
|
ESM::DialogueCondition condStruct;
|
||||||
condStruct.mSelectRule = "01000";
|
condStruct.mIndex = conditions.size();
|
||||||
condStruct.mValue = ESM::Variant();
|
|
||||||
condStruct.mValue.setType(ESM::VT_Int);
|
|
||||||
|
|
||||||
conditions.insert(conditions.begin() + position, condStruct);
|
conditions.insert(conditions.begin() + position, condStruct);
|
||||||
|
|
||||||
@ -544,7 +553,7 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(conditions.size()))
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(conditions.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
@ -558,8 +567,8 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
info.mSelects = static_cast<const NestedTableWrapper<std::vector<ESM::DialInfo::SelectStruct>>&>(nestedTable)
|
info.mSelects
|
||||||
.mNestedTable;
|
= static_cast<const NestedTableWrapper<std::vector<ESM::DialogueCondition>>&>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
record.setModified(info);
|
record.setModified(info);
|
||||||
}
|
}
|
||||||
@ -567,14 +576,14 @@ namespace CSMWorld
|
|||||||
NestedTableWrapperBase* InfoConditionAdapter::table(const Record<Info>& record) const
|
NestedTableWrapperBase* InfoConditionAdapter::table(const Record<Info>& record) const
|
||||||
{
|
{
|
||||||
// deleted by dtor of NestedTableStoring
|
// deleted by dtor of NestedTableStoring
|
||||||
return new NestedTableWrapper<std::vector<ESM::DialInfo::SelectStruct>>(record.get().mSelects);
|
return new NestedTableWrapper<std::vector<ESM::DialogueCondition>>(record.get().mSelects);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant InfoConditionAdapter::getData(const Record<Info>& record, int subRowIndex, int subColIndex) const
|
QVariant InfoConditionAdapter::getData(const Record<Info>& record, int subRowIndex, int subColIndex) const
|
||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
@ -596,23 +605,11 @@ namespace CSMWorld
|
|||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
return infoSelectWrapper.getRelationType();
|
return infoSelectWrapper.getRelationType() - ESM::DialogueCondition::Comp_Eq;
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
switch (infoSelectWrapper.getVariant().getType())
|
return infoSelectWrapper.getValue();
|
||||||
{
|
|
||||||
case ESM::VT_Int:
|
|
||||||
{
|
|
||||||
return infoSelectWrapper.getVariant().getInteger();
|
|
||||||
}
|
|
||||||
case ESM::VT_Float:
|
|
||||||
{
|
|
||||||
return infoSelectWrapper.getVariant().getFloat();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Info condition subcolumn index out of range");
|
throw std::runtime_error("Info condition subcolumn index out of range");
|
||||||
@ -624,7 +621,7 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
Info info = record.get();
|
Info info = record.get();
|
||||||
|
|
||||||
std::vector<ESM::DialInfo::SelectStruct>& conditions = info.mSelects;
|
auto& conditions = info.mSelects;
|
||||||
|
|
||||||
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(conditions.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
@ -636,27 +633,18 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
case 0: // Function
|
case 0: // Function
|
||||||
{
|
{
|
||||||
infoSelectWrapper.setFunctionName(static_cast<ConstInfoSelectWrapper::FunctionName>(value.toInt()));
|
infoSelectWrapper.setFunctionName(static_cast<ESM::DialogueCondition::Function>(value.toInt()));
|
||||||
|
|
||||||
if (infoSelectWrapper.getComparisonType() != ConstInfoSelectWrapper::Comparison_Numeric
|
|
||||||
&& infoSelectWrapper.getVariant().getType() != ESM::VT_Int)
|
|
||||||
{
|
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
|
||||||
}
|
|
||||||
|
|
||||||
infoSelectWrapper.update();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: // Variable
|
case 1: // Variable
|
||||||
{
|
{
|
||||||
infoSelectWrapper.setVariableName(value.toString().toUtf8().constData());
|
infoSelectWrapper.setVariableName(value.toString().toUtf8().constData());
|
||||||
infoSelectWrapper.update();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: // Relation
|
case 2: // Relation
|
||||||
{
|
{
|
||||||
infoSelectWrapper.setRelationType(static_cast<ConstInfoSelectWrapper::RelationType>(value.toInt()));
|
infoSelectWrapper.setRelationType(
|
||||||
infoSelectWrapper.update();
|
static_cast<ESM::DialogueCondition::Comparison>(value.toInt() + ESM::DialogueCondition::Comp_Eq));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: // Value
|
case 3: // Value
|
||||||
@ -668,13 +656,11 @@ namespace CSMWorld
|
|||||||
// QVariant seems to have issues converting 0
|
// QVariant seems to have issues converting 0
|
||||||
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
||||||
{
|
{
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
infoSelectWrapper.setValue(value.toInt());
|
||||||
infoSelectWrapper.getVariant().setInteger(value.toInt());
|
|
||||||
}
|
}
|
||||||
else if (value.toFloat(&conversionResult) && conversionResult)
|
else if (value.toFloat(&conversionResult) && conversionResult)
|
||||||
{
|
{
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Float);
|
infoSelectWrapper.setValue(value.toFloat());
|
||||||
infoSelectWrapper.getVariant().setFloat(value.toFloat());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -683,8 +669,7 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
if ((value.toInt(&conversionResult) && conversionResult) || value.toString().compare("0") == 0)
|
||||||
{
|
{
|
||||||
infoSelectWrapper.getVariant().setType(ESM::VT_Int);
|
infoSelectWrapper.setValue(value.toInt());
|
||||||
infoSelectWrapper.getVariant().setInteger(value.toInt());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -996,7 +981,10 @@ namespace CSMWorld
|
|||||||
case 5:
|
case 5:
|
||||||
{
|
{
|
||||||
if (isInterior && interiorWater)
|
if (isInterior && interiorWater)
|
||||||
|
{
|
||||||
cell.mWater = value.toFloat();
|
cell.mWater = value.toFloat();
|
||||||
|
cell.setHasWaterHeightSub(true);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return; // return without saving
|
return; // return without saving
|
||||||
break;
|
break;
|
||||||
|
@ -255,20 +255,22 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
ESXRecordT magic = record.get();
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
std::vector<ESM::IndexedENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
// blank row
|
// blank row
|
||||||
ESM::ENAMstruct effect;
|
ESM::IndexedENAMstruct effect;
|
||||||
effect.mEffectID = 0;
|
effect.mIndex = position;
|
||||||
effect.mSkill = -1;
|
effect.mData.mEffectID = 0;
|
||||||
effect.mAttribute = -1;
|
effect.mData.mSkill = -1;
|
||||||
effect.mRange = 0;
|
effect.mData.mAttribute = -1;
|
||||||
effect.mArea = 0;
|
effect.mData.mRange = 0;
|
||||||
effect.mDuration = 0;
|
effect.mData.mArea = 0;
|
||||||
effect.mMagnMin = 0;
|
effect.mData.mDuration = 0;
|
||||||
effect.mMagnMax = 0;
|
effect.mData.mMagnMin = 0;
|
||||||
|
effect.mData.mMagnMax = 0;
|
||||||
|
|
||||||
effectsList.insert(effectsList.begin() + position, effect);
|
effectsList.insert(effectsList.begin() + position, effect);
|
||||||
|
magic.mEffects.updateIndexes();
|
||||||
|
|
||||||
record.setModified(magic);
|
record.setModified(magic);
|
||||||
}
|
}
|
||||||
@ -277,12 +279,13 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
ESXRecordT magic = record.get();
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
std::vector<ESM::IndexedENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(effectsList.size()))
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(effectsList.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
|
|
||||||
effectsList.erase(effectsList.begin() + rowToRemove);
|
effectsList.erase(effectsList.begin() + rowToRemove);
|
||||||
|
magic.mEffects.updateIndexes();
|
||||||
|
|
||||||
record.setModified(magic);
|
record.setModified(magic);
|
||||||
}
|
}
|
||||||
@ -292,7 +295,7 @@ namespace CSMWorld
|
|||||||
ESXRecordT magic = record.get();
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
magic.mEffects.mList
|
magic.mEffects.mList
|
||||||
= static_cast<const NestedTableWrapper<std::vector<ESM::ENAMstruct>>&>(nestedTable).mNestedTable;
|
= static_cast<const NestedTableWrapper<std::vector<ESM::IndexedENAMstruct>>&>(nestedTable).mNestedTable;
|
||||||
|
|
||||||
record.setModified(magic);
|
record.setModified(magic);
|
||||||
}
|
}
|
||||||
@ -300,19 +303,19 @@ namespace CSMWorld
|
|||||||
NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const override
|
NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const override
|
||||||
{
|
{
|
||||||
// deleted by dtor of NestedTableStoring
|
// deleted by dtor of NestedTableStoring
|
||||||
return new NestedTableWrapper<std::vector<ESM::ENAMstruct>>(record.get().mEffects.mList);
|
return new NestedTableWrapper<std::vector<ESM::IndexedENAMstruct>>(record.get().mEffects.mList);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant getData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const override
|
QVariant getData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const override
|
||||||
{
|
{
|
||||||
ESXRecordT magic = record.get();
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
std::vector<ESM::IndexedENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(effectsList.size()))
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(effectsList.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
|
|
||||||
ESM::ENAMstruct effect = effectsList[subRowIndex];
|
ESM::ENAMstruct effect = effectsList[subRowIndex].mData;
|
||||||
switch (subColIndex)
|
switch (subColIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -374,12 +377,12 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
ESXRecordT magic = record.get();
|
ESXRecordT magic = record.get();
|
||||||
|
|
||||||
std::vector<ESM::ENAMstruct>& effectsList = magic.mEffects.mList;
|
std::vector<ESM::IndexedENAMstruct>& effectsList = magic.mEffects.mList;
|
||||||
|
|
||||||
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(effectsList.size()))
|
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(effectsList.size()))
|
||||||
throw std::runtime_error("index out of range");
|
throw std::runtime_error("index out of range");
|
||||||
|
|
||||||
ESM::ENAMstruct effect = effectsList[subRowIndex];
|
ESM::ENAMstruct effect = effectsList[subRowIndex].mData;
|
||||||
switch (subColIndex)
|
switch (subColIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -438,7 +441,7 @@ namespace CSMWorld
|
|||||||
throw std::runtime_error("Magic Effects subcolumn index out of range");
|
throw std::runtime_error("Magic Effects subcolumn index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
magic.mEffects.mList[subRowIndex] = effect;
|
magic.mEffects.mList[subRowIndex].mData = effect;
|
||||||
|
|
||||||
record.setModified(magic);
|
record.setModified(magic);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,11 @@ namespace CSMWorld
|
|||||||
|
|
||||||
State mState;
|
State mState;
|
||||||
|
|
||||||
|
explicit RecordBase(State state)
|
||||||
|
: mState(state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~RecordBase() = default;
|
virtual ~RecordBase() = default;
|
||||||
|
|
||||||
virtual std::unique_ptr<RecordBase> clone() const = 0;
|
virtual std::unique_ptr<RecordBase> clone() const = 0;
|
||||||
@ -69,21 +74,18 @@ namespace CSMWorld
|
|||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
Record<ESXRecordT>::Record()
|
Record<ESXRecordT>::Record()
|
||||||
: mBase()
|
: RecordBase(State_BaseOnly)
|
||||||
|
, mBase()
|
||||||
, mModified()
|
, mModified()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
Record<ESXRecordT>::Record(State state, const ESXRecordT* base, const ESXRecordT* modified)
|
Record<ESXRecordT>::Record(State state, const ESXRecordT* base, const ESXRecordT* modified)
|
||||||
|
: RecordBase(state)
|
||||||
|
, mBase(base == nullptr ? ESXRecordT{} : *base)
|
||||||
|
, mModified(modified == nullptr ? ESXRecordT{} : *modified)
|
||||||
{
|
{
|
||||||
if (base)
|
|
||||||
mBase = *base;
|
|
||||||
|
|
||||||
if (modified)
|
|
||||||
mModified = *modified;
|
|
||||||
|
|
||||||
this->mState = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
|
@ -33,7 +33,7 @@ QVariant CSMWorld::PotionRefIdAdapter::getData(const RefIdColumn* column, const
|
|||||||
data.getRecord(RefIdData::LocalIndex(index, UniversalId::Type_Potion)));
|
data.getRecord(RefIdData::LocalIndex(index, UniversalId::Type_Potion)));
|
||||||
|
|
||||||
if (column == mAutoCalc)
|
if (column == mAutoCalc)
|
||||||
return record.get().mData.mAutoCalc != 0;
|
return record.get().mData.mFlags & ESM::Potion::Autocalc;
|
||||||
|
|
||||||
// to show nested tables in dialogue subview, see IdTree::hasChildren()
|
// to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||||
if (column == mColumns.mEffects)
|
if (column == mColumns.mEffects)
|
||||||
@ -51,7 +51,7 @@ void CSMWorld::PotionRefIdAdapter::setData(
|
|||||||
ESM::Potion potion = record.get();
|
ESM::Potion potion = record.get();
|
||||||
|
|
||||||
if (column == mAutoCalc)
|
if (column == mAutoCalc)
|
||||||
potion.mData.mAutoCalc = value.toInt();
|
potion.mData.mFlags = value.toBool();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InventoryRefIdAdapter<ESM::Potion>::setData(column, data, index, value);
|
InventoryRefIdAdapter<ESM::Potion>::setData(column, data, index, value);
|
||||||
|
@ -97,7 +97,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
inventoryColumns.mIcon = &mColumns.back();
|
inventoryColumns.mIcon = &mColumns.back();
|
||||||
mColumns.emplace_back(Columns::ColumnId_Weight, ColumnBase::Display_Float);
|
mColumns.emplace_back(Columns::ColumnId_Weight, ColumnBase::Display_Float);
|
||||||
inventoryColumns.mWeight = &mColumns.back();
|
inventoryColumns.mWeight = &mColumns.back();
|
||||||
mColumns.emplace_back(Columns::ColumnId_StackCount, ColumnBase::Display_Integer);
|
mColumns.emplace_back(Columns::ColumnId_GoldValue, ColumnBase::Display_Integer);
|
||||||
inventoryColumns.mValue = &mColumns.back();
|
inventoryColumns.mValue = &mColumns.back();
|
||||||
|
|
||||||
IngredientColumns ingredientColumns(inventoryColumns);
|
IngredientColumns ingredientColumns(inventoryColumns);
|
||||||
@ -210,7 +210,6 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiDuration, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiDuration, CSMWorld::ColumnBase::Display_Integer));
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiWanderToD, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiWanderToD, CSMWorld::ColumnBase::Display_Integer));
|
||||||
|
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle1, CSMWorld::ColumnBase::Display_Integer));
|
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle2, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle2, CSMWorld::ColumnBase::Display_Integer));
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle3, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle3, CSMWorld::ColumnBase::Display_Integer));
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle4, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle4, CSMWorld::ColumnBase::Display_Integer));
|
||||||
@ -218,6 +217,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle6, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle6, CSMWorld::ColumnBase::Display_Integer));
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle7, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle7, CSMWorld::ColumnBase::Display_Integer));
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle8, CSMWorld::ColumnBase::Display_Integer));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle8, CSMWorld::ColumnBase::Display_Integer));
|
||||||
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle9, CSMWorld::ColumnBase::Display_Integer));
|
||||||
|
|
||||||
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_Boolean));
|
mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_Boolean));
|
||||||
mColumns.back().addColumn(
|
mColumns.back().addColumn(
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "regionmap.hpp"
|
#include "regionmap.hpp"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
|
#include <QPalette>
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
@ -21,20 +23,33 @@
|
|||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
|
|
||||||
CSMWorld::RegionMap::CellDescription::CellDescription()
|
namespace CSMWorld
|
||||||
: mDeleted(false)
|
|
||||||
{
|
{
|
||||||
|
float getLandHeight(const CSMWorld::Cell& cell, CSMWorld::Data& data)
|
||||||
|
{
|
||||||
|
const IdCollection<Land>& lands = data.getLand();
|
||||||
|
int landIndex = lands.searchId(cell.mId);
|
||||||
|
if (landIndex == -1)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
// If any part of land is above water, returns > 0 - otherwise returns < 0
|
||||||
|
const Land& land = lands.getRecord(landIndex).get();
|
||||||
|
if (land.getLandData())
|
||||||
|
return land.getLandData()->mMaxHeight - cell.mWater;
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::RegionMap::CellDescription::CellDescription(const Record<Cell>& cell)
|
CSMWorld::RegionMap::CellDescription::CellDescription(const Record<Cell>& cell, float landHeight)
|
||||||
{
|
{
|
||||||
const Cell& cell2 = cell.get();
|
const Cell& cell2 = cell.get();
|
||||||
|
|
||||||
if (!cell2.isExterior())
|
if (!cell2.isExterior())
|
||||||
throw std::logic_error("Interior cell in region map");
|
throw std::logic_error("Interior cell in region map");
|
||||||
|
|
||||||
|
mMaxLandHeight = landHeight;
|
||||||
mDeleted = cell.isDeleted();
|
mDeleted = cell.isDeleted();
|
||||||
|
|
||||||
mRegion = cell2.mRegion;
|
mRegion = cell2.mRegion;
|
||||||
mName = cell2.mName;
|
mName = cell2.mName;
|
||||||
}
|
}
|
||||||
@ -92,7 +107,7 @@ void CSMWorld::RegionMap::buildMap()
|
|||||||
|
|
||||||
if (cell2.isExterior())
|
if (cell2.isExterior())
|
||||||
{
|
{
|
||||||
CellDescription description(cell);
|
CellDescription description(cell, getLandHeight(cell2, mData));
|
||||||
|
|
||||||
CellCoordinates index = getIndex(cell2);
|
CellCoordinates index = getIndex(cell2);
|
||||||
|
|
||||||
@ -140,7 +155,7 @@ void CSMWorld::RegionMap::addCells(int start, int end)
|
|||||||
{
|
{
|
||||||
CellCoordinates index = getIndex(cell2);
|
CellCoordinates index = getIndex(cell2);
|
||||||
|
|
||||||
CellDescription description(cell);
|
CellDescription description(cell, getLandHeight(cell.get(), mData));
|
||||||
|
|
||||||
addCell(index, description);
|
addCell(index, description);
|
||||||
}
|
}
|
||||||
@ -335,10 +350,11 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
|
|||||||
auto iter = mColours.find(cell->second.mRegion);
|
auto iter = mColours.find(cell->second.mRegion);
|
||||||
|
|
||||||
if (iter != mColours.end())
|
if (iter != mColours.end())
|
||||||
return QBrush(QColor(iter->second & 0xff, (iter->second >> 8) & 0xff, (iter->second >> 16) & 0xff));
|
return QBrush(QColor(iter->second & 0xff, (iter->second >> 8) & 0xff, (iter->second >> 16) & 0xff),
|
||||||
|
cell->second.mMaxLandHeight > 0 ? Qt::SolidPattern : Qt::CrossPattern);
|
||||||
|
|
||||||
if (cell->second.mRegion.empty())
|
if (cell->second.mRegion.empty()) // no region
|
||||||
return QBrush(Qt::Dense6Pattern); // no region
|
return QBrush(cell->second.mMaxLandHeight > 0 ? Qt::Dense3Pattern : Qt::Dense6Pattern);
|
||||||
|
|
||||||
return QBrush(Qt::red, Qt::Dense6Pattern); // invalid region
|
return QBrush(Qt::red, Qt::Dense6Pattern); // invalid region
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,12 @@ namespace CSMWorld
|
|||||||
private:
|
private:
|
||||||
struct CellDescription
|
struct CellDescription
|
||||||
{
|
{
|
||||||
|
float mMaxLandHeight;
|
||||||
bool mDeleted;
|
bool mDeleted;
|
||||||
ESM::RefId mRegion;
|
ESM::RefId mRegion;
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
|
||||||
CellDescription();
|
CellDescription(const Record<Cell>& cell, float landHeight);
|
||||||
|
|
||||||
CellDescription(const Record<Cell>& cell);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Data& mData;
|
Data& mData;
|
||||||
|
@ -28,7 +28,7 @@ void CSMWorld::Resources::recreate(const VFS::Manager* vfs, const char* const* e
|
|||||||
|
|
||||||
size_t baseSize = mBaseDirectory.size();
|
size_t baseSize = mBaseDirectory.size();
|
||||||
|
|
||||||
for (const auto& filepath : vfs->getRecursiveDirectoryIterator(""))
|
for (const auto& filepath : vfs->getRecursiveDirectoryIterator())
|
||||||
{
|
{
|
||||||
const std::string_view view = filepath.view();
|
const std::string_view view = filepath.view();
|
||||||
if (view.size() < baseSize + 1 || !view.starts_with(mBaseDirectory) || view[baseSize] != '/')
|
if (view.size() < baseSize + 1 || !view.starts_with(mBaseDirectory) || view[baseSize] != '/')
|
||||||
|
@ -58,7 +58,7 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
|||||||
|
|
||||||
if (tmpIcon != id.getIcon())
|
if (tmpIcon != id.getIcon())
|
||||||
{
|
{
|
||||||
return ":/multitype.png"; // icon stolen from gnome TODO: get new icon
|
return ":multitype";
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpIcon = id.getIcon();
|
tmpIcon = id.getIcon();
|
||||||
|
@ -23,158 +23,137 @@ namespace
|
|||||||
constexpr TypeData sNoArg[] = {
|
constexpr TypeData sNoArg[] = {
|
||||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", ":placeholder" },
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", ":placeholder" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables",
|
||||||
":./global-variable.png" },
|
":global-variable" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":./gmst.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":gmst" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":./skill.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":skill" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":./class.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":class" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":./faction.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":faction" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":./race.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":race" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":./sound.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":sound" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":./script.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":script" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":./region.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":region" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", ":birthsign" },
|
||||||
":./birthsign.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":spell" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":./spell.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", ":dialogue-topics" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics",
|
|
||||||
":./dialogue-topics.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals",
|
||||||
":./journal-topics.png" },
|
":journal-topics" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos",
|
||||||
":./dialogue-topic-infos.png" },
|
":dialogue-info" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos",
|
||||||
":./journal-topic-infos.png" },
|
":journal-topic-infos" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":cell" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments",
|
||||||
":./enchantment.png" },
|
":enchantment" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", ":body-part" },
|
||||||
":./body-part.png" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects", ":object" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances", ":instance" },
|
||||||
":./object.png" },
|
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", ":region-map" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", ":filter" },
|
||||||
":./instance.png" },
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", ":resources-mesh" },
|
||||||
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", ":resources-icon" },
|
||||||
":./region-map.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", ":./filter.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes",
|
|
||||||
":./resources-mesh" },
|
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", ":./resources-icon" },
|
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files",
|
||||||
":./resources-music" },
|
":resources-music" },
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files",
|
||||||
":resources-sound" },
|
":resources-sound" },
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures",
|
||||||
":./resources-texture" },
|
":resources-texture" },
|
||||||
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos",
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", ":resources-video" },
|
||||||
":./resources-video" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles",
|
||||||
":./debug-profile.png" },
|
":debug-profile" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SelectionGroup, "Selection Groups", "" },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SelectionGroup, "Selection Groups", "" },
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":./run-log.png" },
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":run-log" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators",
|
||||||
":./sound-generator.png" },
|
":sound-generator" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects",
|
||||||
":./magic-effect.png" },
|
":magic-effect" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", ":land-heightmap" },
|
||||||
":./land-heightmap.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "Land Textures",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "Land Textures",
|
||||||
":./land-texture.png" },
|
":land-texture" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", ":pathgrid" },
|
||||||
":./pathgrid.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts",
|
||||||
":./start-script.png" },
|
":start-script" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata", ":metadata" },
|
||||||
":./metadata.png" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr TypeData sIdArg[] = {
|
constexpr TypeData sIdArg[] = {
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable",
|
||||||
":./global-variable.png" },
|
":global-variable" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":./gmst.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":gmst" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":./skill.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":skill" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":./class.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":class" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":./faction.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":faction" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":./race.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":race" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":./sound.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":sound" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":./script.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":script" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./region.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":region" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":birthsign" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":spell" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", ":./dialogue-topics.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", ":dialogue-topics" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", ":journal-topics" },
|
||||||
":./journal-topics.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo",
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo",
|
||||||
":./dialogue-topic-infos.png" },
|
":dialogue-info" },
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo",
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo",
|
||||||
":./journal-topic-infos.png" },
|
":journal-topic-infos" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":cell" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":cell" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", ":./object.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", ":object" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":activator" },
|
||||||
":./activator.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":potion" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":apparatus" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":armor" },
|
||||||
":./apparatus.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":book" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":./armor.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":clothing" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":./book.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container", ":container" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":./clothing.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":creature" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":door" },
|
||||||
":./container.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":ingredient" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":./creature.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":./door.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient",
|
|
||||||
":./ingredient.png" },
|
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList,
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList,
|
||||||
"Creature Levelled List", ":./levelled-creature.png" },
|
"Creature Levelled List", ":levelled-creature" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList, "Item Levelled List",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList, "Item Levelled List",
|
||||||
":./levelled-item.png" },
|
":levelled-item" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":light" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":lockpick" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, "Miscellaneous",
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, "Miscellaneous",
|
||||||
":./miscellaneous.png" },
|
":miscellaneous" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":./npc.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":npc" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":./probe.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":probe" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":repair" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":static" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":weapon" },
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance",
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance", ":instance" },
|
||||||
":./instance.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":filter" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
|
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":scene" },
|
||||||
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":./scene.png" },
|
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", ":edit-preview" },
|
||||||
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", ":enchantment" },
|
||||||
":./record-preview.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":body-part" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment",
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", ":resources-mesh" },
|
||||||
":./enchantment.png" },
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", ":resources-icon" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":./body-part.png" },
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", ":resources-music" },
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", ":./resources-mesh" },
|
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", ":./resources-icon" },
|
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", ":./resources-music" },
|
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File",
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File",
|
||||||
":./resources-sound" },
|
":resources-sound" },
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture",
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", ":resources-texture" },
|
||||||
":./resources-texture" },
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":resources-video" },
|
||||||
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":./resources-video" },
|
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile",
|
||||||
":./debug-profile.png" },
|
":debug-profile" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator",
|
||||||
":./sound-generator.png" },
|
":sound-generator" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect",
|
||||||
":./magic-effect.png" },
|
":magic-effect" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":./land-heightmap.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":land-heightmap" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "Land Texture",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "Land Texture",
|
||||||
":./land-texture.png" },
|
":land-texture" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":./pathgrid.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":pathgrid" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script",
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script",
|
||||||
":./start-script.png" },
|
":start-script" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":./metadata.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":metadata" },
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr TypeData sIndexArg[] = {
|
constexpr TypeData sIndexArg[] = {
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults,
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults,
|
||||||
"Verification Results", ":./menu-verify.png" },
|
"Verification Results", ":menu-verify" },
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log",
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log",
|
||||||
":./error-log.png" },
|
":error-log" },
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search",
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", ":menu-search" },
|
||||||
":./menu-search.png" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WriteToStream
|
struct WriteToStream
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
QPushButton* CSVDoc::StartupDialogue::addButton(const QString& label, const QIcon& icon)
|
QPushButton* CSVDoc::StartupDialogue::addButton(const QString& label, const QString& icon)
|
||||||
{
|
{
|
||||||
int column = mColumn--;
|
int column = mColumn--;
|
||||||
|
|
||||||
@ -39,13 +39,13 @@ QWidget* CSVDoc::StartupDialogue::createButtons()
|
|||||||
mLayout = new QGridLayout(widget);
|
mLayout = new QGridLayout(widget);
|
||||||
|
|
||||||
/// \todo add icons
|
/// \todo add icons
|
||||||
QPushButton* loadDocument = addButton("Edit A Content File", QIcon(":startup/edit-content"));
|
QPushButton* loadDocument = addButton("Edit A Content File", ":startup/edit-content");
|
||||||
connect(loadDocument, &QPushButton::clicked, this, &StartupDialogue::loadDocument);
|
connect(loadDocument, &QPushButton::clicked, this, &StartupDialogue::loadDocument);
|
||||||
|
|
||||||
QPushButton* createAddon = addButton("Create A New Addon", QIcon(":startup/create-addon"));
|
QPushButton* createAddon = addButton("Create A New Addon", ":startup/create-addon");
|
||||||
connect(createAddon, &QPushButton::clicked, this, &StartupDialogue::createAddon);
|
connect(createAddon, &QPushButton::clicked, this, &StartupDialogue::createAddon);
|
||||||
|
|
||||||
QPushButton* createGame = addButton("Create A New Game", QIcon(":startup/create-game"));
|
QPushButton* createGame = addButton("Create A New Game", ":startup/create-game");
|
||||||
connect(createGame, &QPushButton::clicked, this, &StartupDialogue::createGame);
|
connect(createGame, &QPushButton::clicked, this, &StartupDialogue::createGame);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
|
@ -20,7 +20,7 @@ namespace CSVDoc
|
|||||||
int mColumn;
|
int mColumn;
|
||||||
QGridLayout* mLayout;
|
QGridLayout* mLayout;
|
||||||
|
|
||||||
QPushButton* addButton(const QString& label, const QIcon& icon);
|
QPushButton* addButton(const QString& label, const QString& icon);
|
||||||
|
|
||||||
QWidget* createButtons();
|
QWidget* createButtons();
|
||||||
|
|
||||||
|
@ -71,30 +71,30 @@ void CSVDoc::View::setupFileMenu()
|
|||||||
{
|
{
|
||||||
QMenu* file = menuBar()->addMenu(tr("File"));
|
QMenu* file = menuBar()->addMenu(tr("File"));
|
||||||
|
|
||||||
QAction* newGame = createMenuEntry("New Game", ":./menu-new-game.png", file, "document-file-newgame");
|
QAction* newGame = createMenuEntry("New Game", ":menu-new-game", file, "document-file-newgame");
|
||||||
connect(newGame, &QAction::triggered, this, &View::newGameRequest);
|
connect(newGame, &QAction::triggered, this, &View::newGameRequest);
|
||||||
|
|
||||||
QAction* newAddon = createMenuEntry("New Addon", ":./menu-new-addon.png", file, "document-file-newaddon");
|
QAction* newAddon = createMenuEntry("New Addon", ":menu-new-addon", file, "document-file-newaddon");
|
||||||
connect(newAddon, &QAction::triggered, this, &View::newAddonRequest);
|
connect(newAddon, &QAction::triggered, this, &View::newAddonRequest);
|
||||||
|
|
||||||
QAction* open = createMenuEntry("Open", ":./menu-open.png", file, "document-file-open");
|
QAction* open = createMenuEntry("Open", ":menu-open", file, "document-file-open");
|
||||||
connect(open, &QAction::triggered, this, &View::loadDocumentRequest);
|
connect(open, &QAction::triggered, this, &View::loadDocumentRequest);
|
||||||
|
|
||||||
QAction* save = createMenuEntry("Save", ":./menu-save.png", file, "document-file-save");
|
QAction* save = createMenuEntry("Save", ":menu-save", file, "document-file-save");
|
||||||
connect(save, &QAction::triggered, this, &View::save);
|
connect(save, &QAction::triggered, this, &View::save);
|
||||||
mSave = save;
|
mSave = save;
|
||||||
|
|
||||||
file->addSeparator();
|
file->addSeparator();
|
||||||
|
|
||||||
QAction* verify = createMenuEntry("Verify", ":./menu-verify.png", file, "document-file-verify");
|
QAction* verify = createMenuEntry("Verify", ":menu-verify", file, "document-file-verify");
|
||||||
connect(verify, &QAction::triggered, this, &View::verify);
|
connect(verify, &QAction::triggered, this, &View::verify);
|
||||||
mVerify = verify;
|
mVerify = verify;
|
||||||
|
|
||||||
QAction* merge = createMenuEntry("Merge", ":./menu-merge.png", file, "document-file-merge");
|
QAction* merge = createMenuEntry("Merge", ":menu-merge", file, "document-file-merge");
|
||||||
connect(merge, &QAction::triggered, this, &View::merge);
|
connect(merge, &QAction::triggered, this, &View::merge);
|
||||||
mMerge = merge;
|
mMerge = merge;
|
||||||
|
|
||||||
QAction* loadErrors = createMenuEntry("Error Log", ":./error-log.png", file, "document-file-errorlog");
|
QAction* loadErrors = createMenuEntry("Error Log", ":error-log", file, "document-file-errorlog");
|
||||||
connect(loadErrors, &QAction::triggered, this, &View::loadErrorLog);
|
connect(loadErrors, &QAction::triggered, this, &View::loadErrorLog);
|
||||||
|
|
||||||
QAction* meta = createMenuEntry(CSMWorld::UniversalId::Type_MetaDatas, file, "document-file-metadata");
|
QAction* meta = createMenuEntry(CSMWorld::UniversalId::Type_MetaDatas, file, "document-file-metadata");
|
||||||
@ -102,10 +102,10 @@ void CSVDoc::View::setupFileMenu()
|
|||||||
|
|
||||||
file->addSeparator();
|
file->addSeparator();
|
||||||
|
|
||||||
QAction* close = createMenuEntry("Close", ":./menu-close.png", file, "document-file-close");
|
QAction* close = createMenuEntry("Close", ":menu-close", file, "document-file-close");
|
||||||
connect(close, &QAction::triggered, this, &View::close);
|
connect(close, &QAction::triggered, this, &View::close);
|
||||||
|
|
||||||
QAction* exit = createMenuEntry("Exit", ":./menu-exit.png", file, "document-file-exit");
|
QAction* exit = createMenuEntry("Exit", ":menu-exit", file, "document-file-exit");
|
||||||
connect(exit, &QAction::triggered, this, &View::exit);
|
connect(exit, &QAction::triggered, this, &View::exit);
|
||||||
|
|
||||||
connect(this, &View::exitApplicationRequest, &mViewManager, &ViewManager::exitApplication);
|
connect(this, &View::exitApplicationRequest, &mViewManager, &ViewManager::exitApplication);
|
||||||
@ -140,17 +140,16 @@ void CSVDoc::View::setupEditMenu()
|
|||||||
mUndo = mDocument->getUndoStack().createUndoAction(this, tr("Undo"));
|
mUndo = mDocument->getUndoStack().createUndoAction(this, tr("Undo"));
|
||||||
setupShortcut("document-edit-undo", mUndo);
|
setupShortcut("document-edit-undo", mUndo);
|
||||||
connect(mUndo, &QAction::changed, this, &View::undoActionChanged);
|
connect(mUndo, &QAction::changed, this, &View::undoActionChanged);
|
||||||
mUndo->setIcon(QIcon(QString::fromStdString(":./menu-undo.png")));
|
mUndo->setIcon(QIcon(QString::fromStdString(":menu-undo")));
|
||||||
edit->addAction(mUndo);
|
edit->addAction(mUndo);
|
||||||
|
|
||||||
mRedo = mDocument->getUndoStack().createRedoAction(this, tr("Redo"));
|
mRedo = mDocument->getUndoStack().createRedoAction(this, tr("Redo"));
|
||||||
connect(mRedo, &QAction::changed, this, &View::redoActionChanged);
|
connect(mRedo, &QAction::changed, this, &View::redoActionChanged);
|
||||||
setupShortcut("document-edit-redo", mRedo);
|
setupShortcut("document-edit-redo", mRedo);
|
||||||
mRedo->setIcon(QIcon(QString::fromStdString(":./menu-redo.png")));
|
mRedo->setIcon(QIcon(QString::fromStdString(":menu-redo")));
|
||||||
edit->addAction(mRedo);
|
edit->addAction(mRedo);
|
||||||
|
|
||||||
QAction* userSettings
|
QAction* userSettings = createMenuEntry("Preferences", ":menu-preferences", edit, "document-edit-preferences");
|
||||||
= createMenuEntry("Preferences", ":./menu-preferences.png", edit, "document-edit-preferences");
|
|
||||||
connect(userSettings, &QAction::triggered, this, &View::editSettingsRequest);
|
connect(userSettings, &QAction::triggered, this, &View::editSettingsRequest);
|
||||||
|
|
||||||
QAction* search = createMenuEntry(CSMWorld::UniversalId::Type_Search, edit, "document-edit-search");
|
QAction* search = createMenuEntry(CSMWorld::UniversalId::Type_Search, edit, "document-edit-search");
|
||||||
@ -161,10 +160,10 @@ void CSVDoc::View::setupViewMenu()
|
|||||||
{
|
{
|
||||||
QMenu* view = menuBar()->addMenu(tr("View"));
|
QMenu* view = menuBar()->addMenu(tr("View"));
|
||||||
|
|
||||||
QAction* newWindow = createMenuEntry("New View", ":./menu-new-window.png", view, "document-view-newview");
|
QAction* newWindow = createMenuEntry("New View", ":menu-new-window", view, "document-view-newview");
|
||||||
connect(newWindow, &QAction::triggered, this, &View::newView);
|
connect(newWindow, &QAction::triggered, this, &View::newView);
|
||||||
|
|
||||||
mShowStatusBar = createMenuEntry("Toggle Status Bar", ":./menu-status-bar.png", view, "document-view-statusbar");
|
mShowStatusBar = createMenuEntry("Toggle Status Bar", ":menu-status-bar", view, "document-view-statusbar");
|
||||||
connect(mShowStatusBar, &QAction::toggled, this, &View::toggleShowStatusBar);
|
connect(mShowStatusBar, &QAction::toggled, this, &View::toggleShowStatusBar);
|
||||||
mShowStatusBar->setCheckable(true);
|
mShowStatusBar->setCheckable(true);
|
||||||
mShowStatusBar->setChecked(CSMPrefs::get()["Windows"]["show-statusbar"].isTrue());
|
mShowStatusBar->setChecked(CSMPrefs::get()["Windows"]["show-statusbar"].isTrue());
|
||||||
@ -289,7 +288,7 @@ void CSVDoc::View::setupAssetsMenu()
|
|||||||
{
|
{
|
||||||
QMenu* assets = menuBar()->addMenu(tr("Assets"));
|
QMenu* assets = menuBar()->addMenu(tr("Assets"));
|
||||||
|
|
||||||
QAction* reload = createMenuEntry("Reload", ":./menu-reload.png", assets, "document-assets-reload");
|
QAction* reload = createMenuEntry("Reload", ":menu-reload", assets, "document-assets-reload");
|
||||||
connect(reload, &QAction::triggered, &mDocument->getData(), &CSMWorld::Data::assetsChanged);
|
connect(reload, &QAction::triggered, &mDocument->getData(), &CSMWorld::Data::assetsChanged);
|
||||||
|
|
||||||
assets->addSeparator();
|
assets->addSeparator();
|
||||||
@ -341,9 +340,9 @@ void CSVDoc::View::setupDebugMenu()
|
|||||||
QAction* runDebug = debug->addMenu(mGlobalDebugProfileMenu);
|
QAction* runDebug = debug->addMenu(mGlobalDebugProfileMenu);
|
||||||
runDebug->setText(tr("Run OpenMW"));
|
runDebug->setText(tr("Run OpenMW"));
|
||||||
setupShortcut("document-debug-run", runDebug);
|
setupShortcut("document-debug-run", runDebug);
|
||||||
runDebug->setIcon(QIcon(QString::fromStdString(":./run-openmw.png")));
|
runDebug->setIcon(QIcon(QString::fromStdString(":run-openmw")));
|
||||||
|
|
||||||
QAction* stopDebug = createMenuEntry("Stop OpenMW", ":./stop-openmw.png", debug, "document-debug-shutdown");
|
QAction* stopDebug = createMenuEntry("Stop OpenMW", ":stop-openmw", debug, "document-debug-shutdown");
|
||||||
connect(stopDebug, &QAction::triggered, this, &View::stop);
|
connect(stopDebug, &QAction::triggered, this, &View::stop);
|
||||||
mStopDebug = stopDebug;
|
mStopDebug = stopDebug;
|
||||||
|
|
||||||
@ -355,16 +354,16 @@ void CSVDoc::View::setupHelpMenu()
|
|||||||
{
|
{
|
||||||
QMenu* help = menuBar()->addMenu(tr("Help"));
|
QMenu* help = menuBar()->addMenu(tr("Help"));
|
||||||
|
|
||||||
QAction* helpInfo = createMenuEntry("Help", ":/info.png", help, "document-help-help");
|
QAction* helpInfo = createMenuEntry("Help", ":info", help, "document-help-help");
|
||||||
connect(helpInfo, &QAction::triggered, this, &View::openHelp);
|
connect(helpInfo, &QAction::triggered, this, &View::openHelp);
|
||||||
|
|
||||||
QAction* tutorial = createMenuEntry("Tutorial", ":/info.png", help, "document-help-tutorial");
|
QAction* tutorial = createMenuEntry("Tutorial", ":info", help, "document-help-tutorial");
|
||||||
connect(tutorial, &QAction::triggered, this, &View::tutorial);
|
connect(tutorial, &QAction::triggered, this, &View::tutorial);
|
||||||
|
|
||||||
QAction* about = createMenuEntry("About OpenMW-CS", ":./info.png", help, "document-help-about");
|
QAction* about = createMenuEntry("About OpenMW-CS", ":info", help, "document-help-about");
|
||||||
connect(about, &QAction::triggered, this, &View::infoAbout);
|
connect(about, &QAction::triggered, this, &View::infoAbout);
|
||||||
|
|
||||||
QAction* aboutQt = createMenuEntry("About Qt", ":./qt.png", help, "document-help-qt");
|
QAction* aboutQt = createMenuEntry("About Qt", ":qt", help, "document-help-qt");
|
||||||
connect(aboutQt, &QAction::triggered, this, &View::infoAboutQt);
|
connect(aboutQt, &QAction::triggered, this, &View::infoAboutQt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1111,7 +1110,16 @@ void CSVDoc::View::updateWidth(bool isGrowLimit, int minSubViewWidth)
|
|||||||
{
|
{
|
||||||
QRect rect;
|
QRect rect;
|
||||||
if (isGrowLimit)
|
if (isGrowLimit)
|
||||||
rect = QApplication::screenAt(pos())->geometry();
|
{
|
||||||
|
// Widget position can be negative, we should clamp it.
|
||||||
|
QPoint position = pos();
|
||||||
|
if (position.x() <= 0)
|
||||||
|
position.setX(0);
|
||||||
|
if (position.y() <= 0)
|
||||||
|
position.setY(0);
|
||||||
|
|
||||||
|
rect = QApplication::screenAt(position)->geometry();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
rect = desktopRect();
|
rect = desktopRect();
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ CSVFilter::EditWidget::EditWidget(CSMWorld::Data& data, QWidget* parent)
|
|||||||
|
|
||||||
mHelpAction = new QAction(tr("Help"), this);
|
mHelpAction = new QAction(tr("Help"), this);
|
||||||
connect(mHelpAction, &QAction::triggered, this, &EditWidget::openHelp);
|
connect(mHelpAction, &QAction::triggered, this, &EditWidget::openHelp);
|
||||||
mHelpAction->setIcon(QIcon(":/info.png"));
|
mHelpAction->setIcon(QIcon(":info"));
|
||||||
addAction(mHelpAction);
|
addAction(mHelpAction);
|
||||||
auto* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
|
auto* openHelpShortcut = new CSMPrefs::Shortcut("help", this);
|
||||||
openHelpShortcut->associateAction(mHelpAction);
|
openHelpShortcut->associateAction(mHelpAction);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
|
#include <osg/Vec3d>
|
||||||
|
|
||||||
#include <apps/opencs/model/world/actoradapter.hpp>
|
#include <apps/opencs/model/world/actoradapter.hpp>
|
||||||
#include <apps/opencs/model/world/idcollection.hpp>
|
#include <apps/opencs/model/world/idcollection.hpp>
|
||||||
@ -29,7 +30,7 @@ namespace CSVRender
|
|||||||
Actor::Actor(const ESM::RefId& id, CSMWorld::Data& data)
|
Actor::Actor(const ESM::RefId& id, CSMWorld::Data& data)
|
||||||
: mId(id)
|
: mId(id)
|
||||||
, mData(data)
|
, mData(data)
|
||||||
, mBaseNode(new osg::Group())
|
, mBaseNode(new osg::PositionAttitudeTransform())
|
||||||
, mSkeleton(nullptr)
|
, mSkeleton(nullptr)
|
||||||
{
|
{
|
||||||
mActorData = mData.getActorAdapter()->getActorData(mId);
|
mActorData = mData.getActorAdapter()->getActorData(mId);
|
||||||
@ -60,6 +61,10 @@ namespace CSVRender
|
|||||||
|
|
||||||
// Attach parts to skeleton
|
// Attach parts to skeleton
|
||||||
loadBodyParts();
|
loadBodyParts();
|
||||||
|
|
||||||
|
const osg::Vec2f& attributes = mActorData->getRaceWeightHeight();
|
||||||
|
|
||||||
|
mBaseNode->setScale(osg::Vec3d(attributes.x(), attributes.x(), attributes.y()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@ -59,9 +60,9 @@ namespace CSVRender
|
|||||||
CSMWorld::Data& mData;
|
CSMWorld::Data& mData;
|
||||||
CSMWorld::ActorAdapter::ActorDataPtr mActorData;
|
CSMWorld::ActorAdapter::ActorDataPtr mActorData;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Group> mBaseNode;
|
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
|
||||||
SceneUtil::Skeleton* mSkeleton;
|
SceneUtil::Skeleton* mSkeleton;
|
||||||
SceneUtil::NodeMapVisitor::NodeMap mNodeMap;
|
SceneUtil::NodeMap mNodeMap;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
class QWidget;
|
class QWidget;
|
||||||
|
|
||||||
CSVRender::InstanceMoveMode::InstanceMoveMode(QWidget* parent)
|
CSVRender::InstanceMoveMode::InstanceMoveMode(QWidget* parent)
|
||||||
: ModeButton(QIcon(QPixmap(":scenetoolbar/transform-move")),
|
: ModeButton(QIcon(":scenetoolbar/transform-move"),
|
||||||
"Move selected instances"
|
"Move selected instances"
|
||||||
"<ul><li>Use {scene-edit-primary} to move instances around freely</li>"
|
"<ul><li>Use {scene-edit-primary} to move instances around freely</li>"
|
||||||
"<li>Use {scene-edit-secondary} to move instances around within the grid</li>"
|
"<li>Use {scene-edit-secondary} to move instances around within the grid</li>"
|
||||||
|
@ -58,7 +58,8 @@ namespace CSVRender
|
|||||||
|
|
||||||
InstanceSelectionMode::~InstanceSelectionMode()
|
InstanceSelectionMode::~InstanceSelectionMode()
|
||||||
{
|
{
|
||||||
mParentNode->removeChild(mBaseNode);
|
if (mBaseNode)
|
||||||
|
mParentNode->removeChild(mBaseNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceSelectionMode::setDragStart(const osg::Vec3d& dragStart)
|
void InstanceSelectionMode::setDragStart(const osg::Vec3d& dragStart)
|
||||||
|
@ -12,11 +12,10 @@ namespace CSVRender
|
|||||||
{
|
{
|
||||||
// elements that are part of the actual scene
|
// elements that are part of the actual scene
|
||||||
Mask_Hidden = 0x0,
|
Mask_Hidden = 0x0,
|
||||||
Mask_Reference = 0x2,
|
Mask_Reference = 0x1,
|
||||||
Mask_Pathgrid = 0x4,
|
Mask_Pathgrid = 0x2,
|
||||||
Mask_Water = 0x8,
|
Mask_Water = 0x4,
|
||||||
Mask_Fog = 0x10,
|
Mask_Terrain = 0x8,
|
||||||
Mask_Terrain = 0x20,
|
|
||||||
|
|
||||||
// used within models
|
// used within models
|
||||||
Mask_ParticleSystem = 0x100,
|
Mask_ParticleSystem = 0x100,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <osg/Vec4f>
|
#include <osg/Vec4f>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
#include <components/esm/defs.hpp>
|
#include <components/esm/position.hpp>
|
||||||
#include <components/esm/refid.hpp>
|
#include <components/esm/refid.hpp>
|
||||||
|
|
||||||
#include "tagbase.hpp"
|
#include "tagbase.hpp"
|
||||||
|
@ -160,7 +160,6 @@ void CSVRender::PagedWorldspaceWidget::addVisibilitySelectorButtons(CSVWidget::S
|
|||||||
{
|
{
|
||||||
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
||||||
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain");
|
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain");
|
||||||
tool->addButton(Button_Fog, Mask_Fog, "Fog", "", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::SceneToolMode* tool)
|
void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::SceneToolMode* tool)
|
||||||
@ -170,9 +169,10 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons(CSVWidget::Sce
|
|||||||
/// \todo replace EditMode with suitable subclasses
|
/// \todo replace EditMode with suitable subclasses
|
||||||
tool->addButton(new TerrainShapeMode(this, mRootNode, tool), "terrain-shape");
|
tool->addButton(new TerrainShapeMode(this, mRootNode, tool), "terrain-shape");
|
||||||
tool->addButton(new TerrainTextureMode(this, mRootNode, tool), "terrain-texture");
|
tool->addButton(new TerrainTextureMode(this, mRootNode, tool), "terrain-texture");
|
||||||
tool->addButton(
|
const QIcon vertexIcon = QIcon(":scenetoolbar/editing-terrain-vertex-paint");
|
||||||
new EditMode(this, QIcon(":placeholder"), Mask_Reference, "Terrain vertex paint editing"), "terrain-vertex");
|
const QIcon movementIcon = QIcon(":scenetoolbar/editing-terrain-movement");
|
||||||
tool->addButton(new EditMode(this, QIcon(":placeholder"), Mask_Reference, "Terrain movement"), "terrain-move");
|
tool->addButton(new EditMode(this, vertexIcon, Mask_Reference, "Terrain vertex paint editing"), "terrain-vertex");
|
||||||
|
tool->addButton(new EditMode(this, movementIcon, Mask_Reference, "Terrain movement"), "terrain-move");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::handleInteractionPress(const WorldspaceHitResult& hit, InteractionType type)
|
void CSVRender::PagedWorldspaceWidget::handleInteractionPress(const WorldspaceHitResult& hit, InteractionType type)
|
||||||
|
@ -36,8 +36,8 @@ class QWidget;
|
|||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent)
|
PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent)
|
||||||
: EditMode(worldspaceWidget, QIcon(":placeholder"), Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(),
|
: EditMode(worldspaceWidget, QIcon(":scenetoolbar/editing-pathgrid"),
|
||||||
parent)
|
Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(), parent)
|
||||||
, mDragMode(DragMode_None)
|
, mDragMode(DragMode_None)
|
||||||
, mFromNode(0)
|
, mFromNode(0)
|
||||||
, mSelectionMode(nullptr)
|
, mSelectionMode(nullptr)
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
#include <components/sceneutil/glextensions.hpp>
|
||||||
#include <components/sceneutil/lightmanager.hpp>
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
|
||||||
#include "../widget/scenetoolmode.hpp"
|
#include "../widget/scenetoolmode.hpp"
|
||||||
@ -76,6 +77,8 @@ namespace CSVRender
|
|||||||
= new osgViewer::GraphicsWindowEmbedded(0, 0, width(), height());
|
= new osgViewer::GraphicsWindowEmbedded(0, 0, width(), height());
|
||||||
mWidget->setGraphicsWindowEmbedded(window);
|
mWidget->setGraphicsWindowEmbedded(window);
|
||||||
|
|
||||||
|
mRenderer->setRealizeOperation(new SceneUtil::GetGLExtensionsOperation());
|
||||||
|
|
||||||
int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
|
int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
|
||||||
mRenderer->setRunMaxFrameRate(frameRateLimit);
|
mRenderer->setRunMaxFrameRate(frameRateLimit);
|
||||||
mRenderer->setUseConfigureAffinity(false);
|
mRenderer->setUseConfigureAffinity(false);
|
||||||
|
@ -347,7 +347,6 @@ void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons(CSVWidget:
|
|||||||
{
|
{
|
||||||
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
WorldspaceWidget::addVisibilitySelectorButtons(tool);
|
||||||
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain", "", true);
|
tool->addButton(Button_Terrain, Mask_Terrain, "Terrain", "", true);
|
||||||
tool->addButton(Button_Fog, Mask_Fog, "Fog");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
|
std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
|
||||||
|
@ -222,8 +222,7 @@ namespace CSVRender
|
|||||||
Button_Reference = 0x1,
|
Button_Reference = 0x1,
|
||||||
Button_Pathgrid = 0x2,
|
Button_Pathgrid = 0x2,
|
||||||
Button_Water = 0x4,
|
Button_Water = 0x4,
|
||||||
Button_Fog = 0x8,
|
Button_Terrain = 0x8
|
||||||
Button_Terrain = 0x10
|
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void addVisibilitySelectorButtons(CSVWidget::SceneToolToggle2* tool);
|
virtual void addVisibilitySelectorButtons(CSVWidget::SceneToolToggle2* tool);
|
||||||
|
@ -94,7 +94,7 @@ void CSVWidget::SceneToolMode::showPanel(const QPoint& position)
|
|||||||
|
|
||||||
void CSVWidget::SceneToolMode::addButton(const std::string& icon, const std::string& id, const QString& tooltip)
|
void CSVWidget::SceneToolMode::addButton(const std::string& icon, const std::string& id, const QString& tooltip)
|
||||||
{
|
{
|
||||||
ModeButton* button = new ModeButton(QIcon(QPixmap(icon.c_str())), tooltip, mPanel);
|
ModeButton* button = new ModeButton(QIcon(icon.c_str()), tooltip, mPanel);
|
||||||
addButton(button, id);
|
addButton(button, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,10 +60,10 @@ CSVWidget::ShapeBrushWindow::ShapeBrushWindow(CSMDoc::Document& document, QWidge
|
|||||||
: QFrame(parent, Qt::Popup)
|
: QFrame(parent, Qt::Popup)
|
||||||
, mDocument(document)
|
, mDocument(document)
|
||||||
{
|
{
|
||||||
mButtonPoint = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-point")), "", this);
|
mButtonPoint = new QPushButton(QIcon(":scenetoolbar/brush-point"), "", this);
|
||||||
mButtonSquare = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-square")), "", this);
|
mButtonSquare = new QPushButton(QIcon(":scenetoolbar/brush-square"), "", this);
|
||||||
mButtonCircle = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-circle")), "", this);
|
mButtonCircle = new QPushButton(QIcon(":scenetoolbar/brush-circle"), "", this);
|
||||||
mButtonCustom = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-custom")), "", this);
|
mButtonCustom = new QPushButton(QIcon(":scenetoolbar/brush-custom"), "", this);
|
||||||
|
|
||||||
mSizeSliders = new ShapeBrushSizeControls("Brush size", this);
|
mSizeSliders = new ShapeBrushSizeControls("Brush size", this);
|
||||||
|
|
||||||
@ -201,25 +201,25 @@ void CSVWidget::SceneToolShapeBrush::setButtonIcon(CSVWidget::BrushShape brushSh
|
|||||||
{
|
{
|
||||||
case BrushShape_Point:
|
case BrushShape_Point:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-point")));
|
setIcon(QIcon(":scenetoolbar/brush-point"));
|
||||||
tooltip += mShapeBrushWindow->toolTipPoint;
|
tooltip += mShapeBrushWindow->toolTipPoint;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BrushShape_Square:
|
case BrushShape_Square:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-square")));
|
setIcon(QIcon(":scenetoolbar/brush-square"));
|
||||||
tooltip += mShapeBrushWindow->toolTipSquare;
|
tooltip += mShapeBrushWindow->toolTipSquare;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BrushShape_Circle:
|
case BrushShape_Circle:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-circle")));
|
setIcon(QIcon(":scenetoolbar/brush-circle"));
|
||||||
tooltip += mShapeBrushWindow->toolTipCircle;
|
tooltip += mShapeBrushWindow->toolTipCircle;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BrushShape_Custom:
|
case BrushShape_Custom:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-custom")));
|
setIcon(QIcon(":scenetoolbar/brush-custom"));
|
||||||
tooltip += mShapeBrushWindow->toolTipCustom;
|
tooltip += mShapeBrushWindow->toolTipCustom;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -90,10 +90,10 @@ CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QW
|
|||||||
mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel));
|
mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel));
|
||||||
}
|
}
|
||||||
|
|
||||||
mButtonPoint = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-point")), "", this);
|
mButtonPoint = new QPushButton(QIcon(":scenetoolbar/brush-point"), "", this);
|
||||||
mButtonSquare = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-square")), "", this);
|
mButtonSquare = new QPushButton(QIcon(":scenetoolbar/brush-square"), "", this);
|
||||||
mButtonCircle = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-circle")), "", this);
|
mButtonCircle = new QPushButton(QIcon(":scenetoolbar/brush-circle"), "", this);
|
||||||
mButtonCustom = new QPushButton(QIcon(QPixmap(":scenetoolbar/brush-custom")), "", this);
|
mButtonCustom = new QPushButton(QIcon(":scenetoolbar/brush-custom"), "", this);
|
||||||
|
|
||||||
mSizeSliders = new BrushSizeControls("Brush size", this);
|
mSizeSliders = new BrushSizeControls("Brush size", this);
|
||||||
|
|
||||||
@ -282,25 +282,25 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon(CSVWidget::BrushShape brush
|
|||||||
{
|
{
|
||||||
case BrushShape_Point:
|
case BrushShape_Point:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-point")));
|
setIcon(QIcon(":scenetoolbar/brush-point"));
|
||||||
tooltip += mTextureBrushWindow->toolTipPoint;
|
tooltip += mTextureBrushWindow->toolTipPoint;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BrushShape_Square:
|
case BrushShape_Square:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-square")));
|
setIcon(QIcon(":scenetoolbar/brush-square"));
|
||||||
tooltip += mTextureBrushWindow->toolTipSquare;
|
tooltip += mTextureBrushWindow->toolTipSquare;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BrushShape_Circle:
|
case BrushShape_Circle:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-circle")));
|
setIcon(QIcon(":scenetoolbar/brush-circle"));
|
||||||
tooltip += mTextureBrushWindow->toolTipCircle;
|
tooltip += mTextureBrushWindow->toolTipCircle;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BrushShape_Custom:
|
case BrushShape_Custom:
|
||||||
|
|
||||||
setIcon(QIcon(QPixmap(":scenetoolbar/brush-custom")));
|
setIcon(QIcon(":scenetoolbar/brush-custom"));
|
||||||
tooltip += mTextureBrushWindow->toolTipCustom;
|
tooltip += mTextureBrushWindow->toolTipCustom;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ void CSVWidget::SceneToolToggle2::addButton(
|
|||||||
stream << mSingleIcon << id;
|
stream << mSingleIcon << id;
|
||||||
|
|
||||||
PushButton* button = new PushButton(
|
PushButton* button = new PushButton(
|
||||||
QIcon(QPixmap(stream.str().c_str())), PushButton::Type_Toggle, tooltip.isEmpty() ? name : tooltip, mPanel);
|
QIcon(stream.str().c_str()), PushButton::Type_Toggle, tooltip.isEmpty() ? name : tooltip, mPanel);
|
||||||
|
|
||||||
button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||||
button->setIconSize(QSize(mIconSize, mIconSize));
|
button->setIconSize(QSize(mIconSize, mIconSize));
|
||||||
|
@ -29,7 +29,7 @@ void CSVWorld::DragRecordTable::startDragFromTable(const CSVWorld::DragRecordTab
|
|||||||
mime->setIndexAtDragStart(index);
|
mime->setIndexAtDragStart(index);
|
||||||
QDrag* drag = new QDrag(this);
|
QDrag* drag = new QDrag(this);
|
||||||
drag->setMimeData(mime);
|
drag->setMimeData(mime);
|
||||||
drag->setPixmap(QString::fromUtf8(mime->getIcon().c_str()));
|
drag->setPixmap(QIcon(mime->getIcon().c_str()).pixmap(QSize(16, 16)));
|
||||||
drag->exec(Qt::CopyAction);
|
drag->exec(Qt::CopyAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,41 +46,41 @@ QWidget* CSVWorld::IdCompletionDelegate::createEditor(QWidget* parent, const QSt
|
|||||||
|
|
||||||
switch (conditionFunction)
|
switch (conditionFunction)
|
||||||
{
|
{
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Global:
|
case ESM::DialogueCondition::Function_Global:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_GlobalVariable);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_GlobalVariable);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Journal:
|
case ESM::DialogueCondition::Function_Journal:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Journal);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Journal);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Item:
|
case ESM::DialogueCondition::Function_Item:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Dead:
|
case ESM::DialogueCondition::Function_Dead:
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotId:
|
case ESM::DialogueCondition::Function_NotId:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Referenceable);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotFaction:
|
case ESM::DialogueCondition::Function_NotFaction:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Faction);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Faction);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotClass:
|
case ESM::DialogueCondition::Function_NotClass:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Class);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Class);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotRace:
|
case ESM::DialogueCondition::Function_NotRace:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Race);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Race);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotCell:
|
case ESM::DialogueCondition::Function_NotCell:
|
||||||
{
|
{
|
||||||
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Cell);
|
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_Cell);
|
||||||
}
|
}
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_Local:
|
case ESM::DialogueCondition::Function_Local:
|
||||||
case CSMWorld::ConstInfoSelectWrapper::Function_NotLocal:
|
case ESM::DialogueCondition::Function_NotLocal:
|
||||||
{
|
{
|
||||||
return new CSVWidget::DropLineEdit(display, parent);
|
return new CSVWidget::DropLineEdit(display, parent);
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,6 @@
|
|||||||
|
|
||||||
#include <components/misc/strings/lower.hpp>
|
#include <components/misc/strings/lower.hpp>
|
||||||
|
|
||||||
bool CSVWorld::IdValidator::isValid(const QChar& c, bool first) const
|
|
||||||
{
|
|
||||||
if (c.isLetter() || c == '_')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!first && (c.isDigit() || c.isSpace()))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSVWorld::IdValidator::IdValidator(bool relaxed, QObject* parent)
|
CSVWorld::IdValidator::IdValidator(bool relaxed, QObject* parent)
|
||||||
: QValidator(parent)
|
: QValidator(parent)
|
||||||
, mRelaxed(relaxed)
|
, mRelaxed(relaxed)
|
||||||
@ -92,7 +81,7 @@ QValidator::State CSVWorld::IdValidator::validate(QString& input, int& pos) cons
|
|||||||
{
|
{
|
||||||
prevScope = false;
|
prevScope = false;
|
||||||
|
|
||||||
if (!isValid(*iter, first))
|
if (!iter->isPrint())
|
||||||
return QValidator::Invalid;
|
return QValidator::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,6 @@ namespace CSVWorld
|
|||||||
std::string mNamespace;
|
std::string mNamespace;
|
||||||
mutable std::string mError;
|
mutable std::string mError;
|
||||||
|
|
||||||
private:
|
|
||||||
bool isValid(const QChar& c, bool first) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IdValidator(bool relaxed = false, QObject* parent = nullptr);
|
IdValidator(bool relaxed = false, QObject* parent = nullptr);
|
||||||
///< \param relaxed Relaxed rules for IDs that also functino as user visible text
|
///< \param relaxed Relaxed rules for IDs that also functino as user visible text
|
||||||
|
@ -92,7 +92,7 @@ CSVWorld::RecordButtonBar::RecordButtonBar(const CSMWorld::UniversalId& id, CSMW
|
|||||||
if (mTable.getFeatures() & CSMWorld::IdTable::Feature_View)
|
if (mTable.getFeatures() & CSMWorld::IdTable::Feature_View)
|
||||||
{
|
{
|
||||||
QToolButton* viewButton = new QToolButton(this);
|
QToolButton* viewButton = new QToolButton(this);
|
||||||
viewButton->setIcon(QIcon(":/cell.png"));
|
viewButton->setIcon(QIcon(":cell"));
|
||||||
viewButton->setToolTip("Open a scene view of the cell this record is located in");
|
viewButton->setToolTip("Open a scene view of the cell this record is located in");
|
||||||
buttonsLayout->addWidget(viewButton);
|
buttonsLayout->addWidget(viewButton);
|
||||||
connect(viewButton, &QToolButton::clicked, this, &RecordButtonBar::viewRecord);
|
connect(viewButton, &QToolButton::clicked, this, &RecordButtonBar::viewRecord);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user