From edd6df1857ab373bd0d369efa9edf6252ca5c7ee Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 02:05:17 +0100 Subject: [PATCH 01/61] Try enabling Windows Shared Runners again. Hopefully this will work now https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/merge_requests/99 is merged. --- .gitlab-ci.yml | 94 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1f8bc6417..c1d6b5753 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -41,26 +41,98 @@ MacOS: paths: - build/OpenMW-*.dmg -Windows: +Windows_Ninja_RelWithDebInfo: tags: - windows + before_script: + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install ninja -y + - choco install python -y + - refreshenv + stage: build + allow_failure: true + script: + - $time = (Get-Date -Format "HH:mm:ss") + - $config = "RelWithDebInfo" + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N + - cd MSVC2019_64_Ninja + - .\ActivateMSVC.ps1 + - cmake --build . --config $config + - cd $config + - | + if (Get-ChildItem -Recurse *.pdb) { + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item + } + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' + cache: + paths: + - deps + - MSVC2019_64_Ninja/deps + artifacts: + when: always + paths: + - "*.zip" - "*.log" + - MSVC2019_64_Ninja/* + - MSVC2019_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 + - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log + + +Windows_MSBuild_RelWithDebInfo: + tags: + - windows + before_script: + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install python -y + - refreshenv stage: build allow_failure: true script: - - Set-Variable -Name "time" -Value (date -Format "%H:%m") + - $time = (Get-Date -Format "HH:mm:ss") + - $config = "RelWithDebInfo" - echo ${time} - echo "started by ${GITLAB_USER_NAME}" -# TODO: to anyone wanting to do further work here, we need to figure out how to get the below working -# TODO: on gitlab's new shared windows runners. They currently don't have bash or anything else installed -# TODO: it is currently just a bare windows 10 with powershell. -# - env # turn on for debugging -# - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V -# - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" -# - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% -# - 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\ + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V + - cd MSVC2019_64 + - .\ActivateMSVC.ps1 + - cmake --build . --config $config + - cd $config + - | + if (Get-ChildItem -Recurse *.pdb) { + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item + } + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' cache: paths: - deps + - MSVC2019_64/deps artifacts: + when: always paths: - - "*.zip" + - "*.zip" - "*.log" + - MSVC2019_64/* + - MSVC2019_64/*.log + - MSVC2019_64/*/*.log + - MSVC2019_64/*/*/*.log + - MSVC2019_64/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*/*.log \ No newline at end of file From 82882beee68ef4098b94e684e2a510891d474733 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 02:08:25 +0100 Subject: [PATCH 02/61] Fix missing line breaks --- .gitlab-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c1d6b5753..086107db2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -78,7 +78,8 @@ Windows_Ninja_RelWithDebInfo: artifacts: when: always paths: - - "*.zip" - "*.log" + - "*.zip" + - "*.log" - MSVC2019_64_Ninja/* - MSVC2019_64_Ninja/*.log - MSVC2019_64_Ninja/*/*.log @@ -126,7 +127,8 @@ Windows_MSBuild_RelWithDebInfo: artifacts: when: always paths: - - "*.zip" - "*.log" + - "*.zip" + - "*.log" - MSVC2019_64/* - MSVC2019_64/*.log - MSVC2019_64/*/*.log From decf59d20e3f277ac0fbd558abf9005c52ac7196 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 02:30:51 +0100 Subject: [PATCH 03/61] Don't try and activate MSVC when using MSBuild --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 086107db2..ac84ed953 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -111,7 +111,6 @@ Windows_MSBuild_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - .\ActivateMSVC.ps1 - cmake --build . --config $config - cd $config - | From c7cf163667510f1d9d0ee4decf6f549b9d304b86 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:23:12 +0100 Subject: [PATCH 04/61] Don't keep whole build directory. --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ac84ed953..774a163fb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -80,7 +80,6 @@ Windows_Ninja_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64_Ninja/* - MSVC2019_64_Ninja/*.log - MSVC2019_64_Ninja/*/*.log - MSVC2019_64_Ninja/*/*/*.log @@ -128,7 +127,6 @@ Windows_MSBuild_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64/* - MSVC2019_64/*.log - MSVC2019_64/*/*.log - MSVC2019_64/*/*/*.log From d6ab2f965955eb88f988b3d3b301664c979b8c84 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:23:59 +0100 Subject: [PATCH 05/61] Disallow failure --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 774a163fb..61e389f19 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,7 +54,6 @@ Windows_Ninja_RelWithDebInfo: - choco install python -y - refreshenv stage: build - allow_failure: true script: - $time = (Get-Date -Format "HH:mm:ss") - $config = "RelWithDebInfo" @@ -102,7 +101,6 @@ Windows_MSBuild_RelWithDebInfo: - choco install python -y - refreshenv stage: build - allow_failure: true script: - $time = (Get-Date -Format "HH:mm:ss") - $config = "RelWithDebInfo" From 53be725df264dea2d44bae6f3c80d17e865abe4c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:26:42 +0100 Subject: [PATCH 06/61] Make build succeed so cache is kept --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 61e389f19..d252236ac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -60,6 +60,7 @@ Windows_Ninja_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N + - exit 0 - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - cmake --build . --config $config @@ -107,6 +108,7 @@ Windows_MSBuild_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V + - exit 0 - cd MSVC2019_64 - cmake --build . --config $config - cd $config From bf69f90f8001e0951332d3390b8e71f2fdc5584f Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:28:42 +0100 Subject: [PATCH 07/61] Revert "Make build succeed so cache is kept" This reverts commit 53be725df264dea2d44bae6f3c80d17e865abe4c. It was only needed for CI reasons. --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d252236ac..61e389f19 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -60,7 +60,6 @@ Windows_Ninja_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - - exit 0 - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - cmake --build . --config $config @@ -108,7 +107,6 @@ Windows_MSBuild_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - - exit 0 - cd MSVC2019_64 - cmake --build . --config $config - cd $config From 0d7b9c51fd9403b2c76f88b5879920d7dd0be7bc Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 28 Jun 2020 03:51:41 +0100 Subject: [PATCH 08/61] Log misparsed stuff as it caused an unexpected CI failure --- CI/activate_msvc.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CI/activate_msvc.sh b/CI/activate_msvc.sh index 0764cd02f..1641f6b3e 100644 --- a/CI/activate_msvc.sh +++ b/CI/activate_msvc.sh @@ -39,6 +39,10 @@ originalIFS="$IFS" IFS=$'\n\r' for pair in $(cmd //c "set"); do IFS='=' read -r -a separatedPair <<< "${pair}" + if [ ${#separatedPair[@]} -ne 2 ]; then + echo "Parsed '$pair' as ${#separatedPair[@]} parts, expected 2." + continue + fi originalCmdEnv["${separatedPair[0]}"]="${separatedPair[1]}" done @@ -49,6 +53,10 @@ declare -A cmdEnvChanges for pair in $cmdEnv; do if [ -n "$pair" ]; then IFS='=' read -r -a separatedPair <<< "${pair}" + if [ ${#separatedPair[@]} -ne 2 ]; then + echo "Parsed '$pair' as ${#separatedPair[@]} parts, expected 2." + continue + fi key="${separatedPair[0]}" value="${separatedPair[1]}" if ! [ ${originalCmdEnv[$key]+_} ] || [ "${originalCmdEnv[$key]}" != "$value" ]; then From 1bb54a28bc5903b27bd8bd8f368d10482b7181ee Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 03:23:15 +0100 Subject: [PATCH 09/61] Build fewer targets Most importantly, skip the CS. This should bring the build time under an hour. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d77db4059..0f62bfa37 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,7 +67,7 @@ Windows_Ninja_RelWithDebInfo: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config + - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -113,7 +113,7 @@ Windows_MSBuild_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config + - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From c29a1c256751650acc17c8f2018d03b4e40de953 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 03:52:54 +0100 Subject: [PATCH 10/61] ninja: error: unknown target 'openwm', did you mean 'openmw'? --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0f62bfa37..fda13c4be 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,7 +67,7 @@ Windows_Ninja_RelWithDebInfo: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -113,7 +113,7 @@ Windows_MSBuild_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From db8f0ad6fd05c3842a9a0c0b498420ac597302c2 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 11 Jul 2020 17:24:20 +0400 Subject: [PATCH 11/61] Do not use outdated references when moving objects to new cells (bug #5387) --- CHANGELOG.md | 1 + apps/openmw/mwbase/windowmanager.hpp | 2 ++ apps/openmw/mwgui/console.cpp | 6 ++++++ apps/openmw/mwgui/console.hpp | 2 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 5 +++++ apps/openmw/mwgui/windowmanagerimp.hpp | 2 ++ apps/openmw/mwscript/transformationextensions.cpp | 6 ++++-- apps/openmw/mwworld/worldimp.cpp | 2 ++ 8 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7be9cc2c7..991744bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Bug #5369: Spawnpoint in the Grazelands doesn't produce oversized creatures Bug #5370: Opening an unlocked but trapped door uses the key Bug #5384: openmw-cs: deleting an instance requires reload of scene window to show in editor + Bug #5387: Move/MoveWorld don't update the object's cell properly Bug #5397: NPC greeting does not reset if you leave + reenter area Bug #5400: Editor: Verifier checks race of non-skin bodyparts Bug #5403: Enchantment effect doesn't show on an enemy during death animation diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index f35df7881..1d59015d3 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -237,6 +237,8 @@ namespace MWBase virtual void update (float duration) = 0; + virtual void updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) = 0; + /** * Fetches a GMST string from the store, if there is no setting with the given * ID or it is not a string the default string is returned. diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index df4bdec5b..120573d59 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -472,6 +472,12 @@ namespace MWGui setCoord(10,10, width-10, height/2); } + void Console::updateSelectedObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) + { + if (mPtr == currentPtr) + mPtr = newPtr; + } + void Console::setSelectedObject(const MWWorld::Ptr& object) { if (!object.isEmpty()) diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 883bc8967..e431d18d1 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -58,6 +58,8 @@ namespace MWGui void executeFile (const std::string& path); + void updateSelectedObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr); + void clear(); virtual void resetReference (); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 02b42c9cd..840f0f9cf 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -574,6 +574,11 @@ namespace MWGui } } + void WindowManager::updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) + { + mConsole->updateSelectedObjectPtr(currentPtr, newPtr); + } + void WindowManager::updateVisible() { bool loading = (getMode() == GM_Loading || getMode() == GM_LoadingWallpaper); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index a8cb0b10a..67a16f516 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -242,6 +242,8 @@ namespace MWGui virtual void unsetSelectedSpell(); virtual void unsetSelectedWeapon(); + virtual void updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr); + virtual void showCrosshair(bool show); virtual bool getSubtitlesEnabled(); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 791d054f3..7bb9093c1 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -725,7 +725,8 @@ namespace MWScript // We should move actors, standing on moving object, too. // This approach can be used to create elevators. moveStandingActors(ptr, diff); - MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x(), worldPos.y(), worldPos.z()); + dynamic_cast(runtime.getContext()).updatePtr(ptr, + MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x(), worldPos.y(), worldPos.z())); } }; @@ -761,7 +762,8 @@ namespace MWScript // We should move actors, standing on moving object, too. // This approach can be used to create elevators. moveStandingActors(ptr, diff); - MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+diff.x(), objPos[1]+diff.y(), objPos[2]+diff.z()); + dynamic_cast(runtime.getContext()).updatePtr(ptr, + MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+diff.x(), objPos[1]+diff.y(), objPos[2]+diff.z())); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index fd934b8a8..1efb03b32 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1201,6 +1201,8 @@ namespace MWWorld } } } + + MWBase::Environment::get().getWindowManager()->updateConsoleObjectPtr(ptr, newPtr); } if (haveToMove && newPtr.getRefData().getBaseNode()) { From a9e6bf11c2df6c0380286b98b0283b11152ff4a1 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 16:36:21 +0100 Subject: [PATCH 12/61] Configurations (via inheritance) --- .gitlab-ci.yml | 51 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fda13c4be..638e89317 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,7 @@ MacOS: paths: - build/OpenMW-*.dmg -Windows_Ninja_RelWithDebInfo: +.Windows_Ninja_Base: tags: - windows before_script: @@ -61,7 +61,6 @@ Windows_Ninja_RelWithDebInfo: stage: build script: - $time = (Get-Date -Format "HH:mm:ss") - - $config = "RelWithDebInfo" - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N @@ -71,10 +70,10 @@ Windows_Ninja_RelWithDebInfo: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' cache: paths: - deps @@ -93,8 +92,25 @@ Windows_Ninja_RelWithDebInfo: - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log +Windows_Ninja_Release: + extends: + - .Windows_Ninja_Base + variables: + - config: "Release" -Windows_MSBuild_RelWithDebInfo: +Windows_Ninja_Debug: + extends: + - .Windows_Ninja_Base + variables: + - config: "Debug" + +Windows_Ninja_RelWithDebInfo: + extends: + - .Windows_Ninja_Base + variables: + - config: "RelWithDebInfo" + +.Windows_MSBuild_Base: tags: - windows before_script: @@ -108,7 +124,6 @@ Windows_MSBuild_RelWithDebInfo: stage: build script: - $time = (Get-Date -Format "HH:mm:ss") - - $config = "RelWithDebInfo" - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V @@ -117,10 +132,10 @@ Windows_MSBuild_RelWithDebInfo: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' cache: paths: - deps @@ -137,4 +152,22 @@ Windows_MSBuild_RelWithDebInfo: - MSVC2019_64/*/*/*/*/*.log - MSVC2019_64/*/*/*/*/*/*.log - MSVC2019_64/*/*/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*/*/*.log \ No newline at end of file + - MSVC2019_64/*/*/*/*/*/*/*/*.log + +Windows_MSBuild_Release: + extends: + - .Windows_MSBuild_Base + variables: + - config: "Release" + +Windows_MSBuild_Debug: + extends: + - .Windows_MSBuild_Base + variables: + - config: "Debug" + +Windows_MSBuild_RelWithDebInfo: + extends: + - .Windows_MSBuild_Base + variables: + - config: "RelWithDebInfo" \ No newline at end of file From 3862f0d10a09b3035656327b162981e119c40456 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 16:42:15 +0100 Subject: [PATCH 13/61] Migrate variable names Some of the built-ins were deprecated/removed --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 638e89317..56b893338 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -70,10 +70,10 @@ MacOS: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: paths: - deps @@ -132,10 +132,10 @@ Windows_Ninja_RelWithDebInfo: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: paths: - deps From 81aed34588a464f0763823be2ac3d17911394896 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 16:54:13 +0100 Subject: [PATCH 14/61] variables should be a hash of key value pairs --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 56b893338..e49690153 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -96,19 +96,19 @@ Windows_Ninja_Release: extends: - .Windows_Ninja_Base variables: - - config: "Release" + config: "Release" Windows_Ninja_Debug: extends: - .Windows_Ninja_Base variables: - - config: "Debug" + config: "Debug" Windows_Ninja_RelWithDebInfo: extends: - .Windows_Ninja_Base variables: - - config: "RelWithDebInfo" + config: "RelWithDebInfo" .Windows_MSBuild_Base: tags: @@ -158,16 +158,16 @@ Windows_MSBuild_Release: extends: - .Windows_MSBuild_Base variables: - - config: "Release" + config: "Release" Windows_MSBuild_Debug: extends: - .Windows_MSBuild_Base variables: - - config: "Debug" + config: "Debug" Windows_MSBuild_RelWithDebInfo: extends: - .Windows_MSBuild_Base variables: - - config: "RelWithDebInfo" \ No newline at end of file + config: "RelWithDebInfo" \ No newline at end of file From 58e3900ea0edc9e09ad9d561a9d02e7ade4c3b1e Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 8 Jul 2020 14:12:55 +0400 Subject: [PATCH 15/61] Avoid redundant call --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index fd934b8a8..0ab15dfc4 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1907,7 +1907,7 @@ namespace MWWorld std::string enchantId = selectedEnchantItem.getClass().getEnchantment(selectedEnchantItem); if (!enchantId.empty()) { - const ESM::Enchantment* ench = mStore.get().search(selectedEnchantItem.getClass().getEnchantment(selectedEnchantItem)); + const ESM::Enchantment* ench = mStore.get().search(enchantId); if (ench) preloadEffects(&ench->mEffects); } From bdf215d1a9b6c966621028a575afd3f3996455d9 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 11 Jul 2020 18:32:33 +0200 Subject: [PATCH 16/61] Add bug #4764 to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7be9cc2c7..c2869408e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Bug #3714: Savegame fails to load due to conflict between SpellState and MagicEffects Bug #4021: Attributes and skills are not stored as floats Bug #4623: Corprus implementation is incorrect + Bug #4764: Data race in osg ParticleSystem Bug #4774: Guards are ignorant of an invisible player that tries to attack them Bug #5108: Savegame bloating due to inefficient fog textures format Bug #5165: Active spells should use real time intead of timestamps From db0ad8421f57d2ac0993d96b7e35bcdb3d6aadf0 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 11 Jul 2020 16:16:44 +0200 Subject: [PATCH 17/61] Report OSG rendering stats --- apps/openmw/engine.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ec12d6a1f..7cbc1c99f 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -908,7 +908,14 @@ void OMW::Engine::go() if (stats) { const auto frameNumber = mViewer->getFrameStamp()->getFrameNumber(); - mViewer->getViewerStats()->report(stats, frameNumber); + if (frameNumber >= 2) + { + mViewer->getViewerStats()->report(stats, frameNumber - 2); + osgViewer::Viewer::Cameras cameras; + mViewer->getCameras(cameras); + for (auto camera : cameras) + camera->getStats()->report(stats, frameNumber - 2); + } } mEnvironment.limitFrameRate(frameTimer.time_s()); From da791590ac05010ba768480754b97b47cb939a5e Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 11 Jul 2020 20:40:00 +0400 Subject: [PATCH 18/61] Update HUD icons during mechanics update again to avoid crashes --- apps/openmw/mwgui/statswatcher.cpp | 21 --------------- .../mwmechanics/mechanicsmanagerimp.cpp | 26 ++++++++++++++++++- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwgui/statswatcher.cpp b/apps/openmw/mwgui/statswatcher.cpp index 7baec2f2c..ccb77de8f 100644 --- a/apps/openmw/mwgui/statswatcher.cpp +++ b/apps/openmw/mwgui/statswatcher.cpp @@ -136,27 +136,6 @@ namespace MWGui } mWatchedStatsEmpty = false; - - // Update the equipped weapon icon - MWWorld::InventoryStore& inv = mWatched.getClass().getInventoryStore(mWatched); - MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if (weapon == inv.end()) - winMgr->unsetSelectedWeapon(); - else - winMgr->setSelectedWeapon(*weapon); - - // Update the selected spell icon - MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); - if (enchantItem != inv.end()) - winMgr->setSelectedEnchantItem(*enchantItem); - else - { - const std::string& spell = winMgr->getSelectedSpell(); - if (!spell.empty()) - winMgr->setSelectedSpell(spell, int(MWMechanics::getSpellSuccessChance(spell, mWatched))); - else - winMgr->unsetSelectedSpell(); - } } void StatsWatcher::addListener(StatsListener* listener) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index fcae60c58..fd8902b37 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -302,13 +302,37 @@ namespace MWMechanics void MechanicsManager::update(float duration, bool paused) { + // Note: we should do it here since game mechanics and world updates use these values + MWWorld::Ptr ptr = getPlayer(); + MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); + + // Update the equipped weapon icon + MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr); + MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weapon == inv.end()) + winMgr->unsetSelectedWeapon(); + else + winMgr->setSelectedWeapon(*weapon); + + // Update the selected spell icon + MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); + if (enchantItem != inv.end()) + winMgr->setSelectedEnchantItem(*enchantItem); + else + { + const std::string& spell = winMgr->getSelectedSpell(); + if (!spell.empty()) + winMgr->setSelectedSpell(spell, int(MWMechanics::getSpellSuccessChance(spell, ptr))); + else + winMgr->unsetSelectedSpell(); + } + if (mUpdatePlayer) { mUpdatePlayer = false; // HACK? The player has been changed, so a new Animation object may // have been made for them. Make sure they're properly updated. - MWWorld::Ptr ptr = getPlayer(); mActors.removeActor(ptr); mActors.addActor(ptr, true); } From 699ec9e06e8926ad9a6115dbb6f1ead6507096c3 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 17:52:42 +0100 Subject: [PATCH 19/61] separate caches for MSBuild and Ninja --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e49690153..258963a2f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,6 +75,7 @@ MacOS: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: + key: ninja paths: - deps - MSVC2019_64_Ninja/deps @@ -137,6 +138,7 @@ Windows_Ninja_RelWithDebInfo: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: + key: msbuild paths: - deps - MSVC2019_64/deps From 24129e8a54029dc92cbc5c94bdbb7f7397e62ae4 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 20:40:36 +0100 Subject: [PATCH 20/61] Runner now supports sensible globbing patterns --- .gitlab-ci.yml | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 258963a2f..e332c6a94 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -84,14 +84,7 @@ MacOS: paths: - "*.zip" - "*.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 - - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log - - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/**.log Windows_Ninja_Release: extends: @@ -147,14 +140,7 @@ Windows_Ninja_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64/*.log - - MSVC2019_64/*/*.log - - MSVC2019_64/*/*/*.log - - MSVC2019_64/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*/*/*.log + - MSVC2019_64/**.log Windows_MSBuild_Release: extends: From 094f0d1772d86795dd07a8f8fddaf5dfb7977f7c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 22:46:12 +0100 Subject: [PATCH 21/61] Maybe this will make globbing work --- .gitlab-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e332c6a94..4e2bb3451 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -84,7 +84,8 @@ MacOS: paths: - "*.zip" - "*.log" - - MSVC2019_64_Ninja/**.log + - MSVC2019_64_Ninja/*.log + - MSVC2019_64_Ninja/**/*.log Windows_Ninja_Release: extends: @@ -140,7 +141,8 @@ Windows_Ninja_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64/**.log + - MSVC2019_64/*.log + - MSVC2019_64/**/*.log Windows_MSBuild_Release: extends: From ef451fa26680a0536b053de73f0e27fe6c23d667 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 03:17:46 +0100 Subject: [PATCH 22/61] Revert "Runner now supports sensible globbing patterns" & "Maybe this will make globbing work" Runner *actually* only supports sensible globbing patterns for cache, not artifacts. This reverts commits 24129e8a54029dc92cbc5c94bdbb7f7397e62ae4 and 094f0d1772d86795dd07a8f8fddaf5dfb7977f7c. --- .gitlab-ci.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4e2bb3451..258963a2f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -85,7 +85,13 @@ MacOS: - "*.zip" - "*.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 + - MSVC2019_64_Ninja/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log Windows_Ninja_Release: extends: @@ -142,7 +148,13 @@ Windows_Ninja_RelWithDebInfo: - "*.zip" - "*.log" - MSVC2019_64/*.log - - MSVC2019_64/**/*.log + - MSVC2019_64/*/*.log + - MSVC2019_64/*/*/*.log + - MSVC2019_64/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*/*.log Windows_MSBuild_Release: extends: From 22c5c7a96e7f158c0d9feb45bd671f5bdc1ffe05 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 03:18:56 +0100 Subject: [PATCH 23/61] Build the CS again. Maybe this will work now the cache isn't trash --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 258963a2f..f88029ce7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -129,7 +129,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From 271f7040a653cf48275b872d71e062d0947938e0 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 12 Jul 2020 13:25:40 +0200 Subject: [PATCH 24/61] Fix a regression caused by #2648 (fixes #5513) --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1fbe8f7fd..209ab538e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1185,7 +1185,6 @@ namespace MWWorld mRendering->updatePtr(ptr, newPtr); MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr); mPhysics->updatePtr(ptr, newPtr); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().updatePtrs(ptr, newPtr); MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager(); mechMgr->updateCell(ptr, newPtr); @@ -1203,6 +1202,7 @@ namespace MWWorld } MWBase::Environment::get().getWindowManager()->updateConsoleObjectPtr(ptr, newPtr); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().updatePtrs(ptr, newPtr); } if (haveToMove && newPtr.getRefData().getBaseNode()) { From 20859bbc50341745b3be00ef8995d1f9d698bd8b Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 13:55:45 +0100 Subject: [PATCH 25/61] Revert "Build the CS again." There wasn't enough time. This reverts commit 22c5c7a96e7f158c0d9feb45bd671f5bdc1ffe05. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f88029ce7..258963a2f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -129,7 +129,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From 6f3e87ce696a904b1e3b40a0ec0042030ec597af Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 13:58:12 +0100 Subject: [PATCH 26/61] Cache less stuff to avoid duplicate entries. This might make everything faster if we're network-bound. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 258963a2f..2d34e6fd3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -78,7 +78,7 @@ MacOS: key: ninja paths: - deps - - MSVC2019_64_Ninja/deps + - MSVC2019_64_Ninja/deps/Qt artifacts: when: always paths: @@ -141,7 +141,7 @@ Windows_Ninja_RelWithDebInfo: key: msbuild paths: - deps - - MSVC2019_64/deps + - MSVC2019_64/deps/Qt artifacts: when: always paths: From 5934a9d145babfa36c7703c3fe4a0923543753c3 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 15:08:47 +0100 Subject: [PATCH 27/61] Actualy build the reduced cache. It looks like cache is only invalidated if new files are added, not old ones removed. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2d34e6fd3..2bdfa990e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,7 +75,7 @@ MacOS: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: - key: ninja + key: ninja-v2 paths: - deps - MSVC2019_64_Ninja/deps/Qt @@ -138,7 +138,7 @@ Windows_Ninja_RelWithDebInfo: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: - key: msbuild + key: msbuild-v2 paths: - deps - MSVC2019_64/deps/Qt From 65ac0c86b8a3fdb77d9347597ae3cc441b8190d5 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 12 Jul 2020 19:05:47 +0300 Subject: [PATCH 28/61] Fix search filter unicode character case sensitivity --- apps/openmw/mwgui/sortfilteritemmodel.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/sortfilteritemmodel.cpp b/apps/openmw/mwgui/sortfilteritemmodel.cpp index 615e2dfc9..f18cac681 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.cpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.cpp @@ -69,8 +69,8 @@ namespace return compareType(leftName, rightName); // compare items by name - leftName = Misc::StringUtils::lowerCase(left.mBase.getClass().getName(left.mBase)); - rightName = Misc::StringUtils::lowerCase(right.mBase.getClass().getName(right.mBase)); + leftName = Misc::StringUtils::lowerCaseUtf8(left.mBase.getClass().getName(left.mBase)); + rightName = Misc::StringUtils::lowerCaseUtf8(right.mBase.getClass().getName(right.mBase)); result = leftName.compare(rightName); if (result != 0) @@ -213,7 +213,7 @@ namespace MWGui if (!mNameFilter.empty()) { - const auto itemName = Misc::StringUtils::lowerCase(base.getClass().getName(base)); + const auto itemName = Misc::StringUtils::lowerCaseUtf8(base.getClass().getName(base)); return itemName.find(mNameFilter) != std::string::npos; } @@ -226,7 +226,7 @@ namespace MWGui for (const auto& effect : effects) { - const auto ciEffect = Misc::StringUtils::lowerCase(effect); + const auto ciEffect = Misc::StringUtils::lowerCaseUtf8(effect); if (ciEffect.find(mEffectFilter) != std::string::npos) return true; @@ -285,7 +285,7 @@ namespace MWGui return false; } - std::string compare = Misc::StringUtils::lowerCase(item.mBase.getClass().getName(item.mBase)); + std::string compare = Misc::StringUtils::lowerCaseUtf8(item.mBase.getClass().getName(item.mBase)); if(compare.find(mNameFilter) == std::string::npos) return false; @@ -318,12 +318,12 @@ namespace MWGui void SortFilterItemModel::setNameFilter (const std::string& filter) { - mNameFilter = Misc::StringUtils::lowerCase(filter); + mNameFilter = Misc::StringUtils::lowerCaseUtf8(filter); } void SortFilterItemModel::setEffectFilter (const std::string& filter) { - mEffectFilter = Misc::StringUtils::lowerCase(filter); + mEffectFilter = Misc::StringUtils::lowerCaseUtf8(filter); } void SortFilterItemModel::update() From 5675d6ce81116261df3d320a163ba8d9500e41f2 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Fri, 19 Jun 2020 22:03:11 +0200 Subject: [PATCH 29/61] Generalize calculation of focal point offset for 3rd person camera. When player swim, the view slowly switches from "over shoulder" to "above head". New functions to switch shoulder. --- apps/openmw/mwrender/camera.cpp | 95 +++++++++++++++++++++++++-------- apps/openmw/mwrender/camera.hpp | 17 ++++-- 2 files changed, 86 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 09ad40428..e0f031b8c 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -7,6 +7,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" #include "../mwworld/class.hpp" #include "../mwworld/ptr.hpp" @@ -64,7 +65,10 @@ namespace MWRender mCameraDistance(0.f), mThirdPersonMode(ThirdPersonViewMode::Standard), mOverShoulderOffset(osg::Vec2f(30.0f, -10.0f)), - mSmoothTransitionToCombatMode(0.f) + mDefaultShoulderIsRight(true), + mThirdPersionOffsetType(ThirdPersonOffsetType::RightShoulder), + mFocalPointCurrentOffset(osg::Vec2d()), + mFocalPointTransitionSpeed(1.f) { mVanity.enabled = false; mVanity.allowed = true; @@ -121,12 +125,9 @@ namespace MWRender osg::Vec3d offset(0, 0, 10.f); if (mThirdPersonMode == ThirdPersonViewMode::OverShoulder && !mPreviewMode && !mVanity.enabled) { - float horizontalOffset = mOverShoulderOffset.x() * (1.f - mSmoothTransitionToCombatMode); - float verticalOffset = mSmoothTransitionToCombatMode * 15.f + (1.f - mSmoothTransitionToCombatMode) * mOverShoulderOffset.y(); - - offset.x() += horizontalOffset * cos(getYaw()); - offset.y() += horizontalOffset * sin(getYaw()); - offset.z() += verticalOffset; + offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw()); + offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw()); + offset.z() += mFocalPointCurrentOffset.y(); } return offset; } @@ -214,28 +215,78 @@ namespace MWRender rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true); } - updateSmoothTransitionToCombatMode(duration); + updateFocalPointOffset(duration); } void Camera::setOverShoulderOffset(float horizontal, float vertical) { - mOverShoulderOffset = osg::Vec2f(horizontal, vertical); + mOverShoulderOffset = osg::Vec2f(std::abs(horizontal), vertical); + mDefaultShoulderIsRight = horizontal >= 0; } - void Camera::updateSmoothTransitionToCombatMode(float duration) + void Camera::switchToLeftShoulder() { - bool combatMode = true; - if (mTrackingPtr.getClass().isActor()) - combatMode = mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing; - float speed = ((combatMode ? 1.f : 0.f) - mSmoothTransitionToCombatMode) * 5; - if (speed != 0) - speed += speed > 0 ? 1 : -1; - - mSmoothTransitionToCombatMode += speed * duration; - if (mSmoothTransitionToCombatMode > 1) - mSmoothTransitionToCombatMode = 1; - if (mSmoothTransitionToCombatMode < 0) - mSmoothTransitionToCombatMode = 0; + if (mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) + mThirdPersionOffsetType = ThirdPersonOffsetType::LeftShoulder; + } + + void Camera::switchToRightShoulder() + { + if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder) + mThirdPersionOffsetType = ThirdPersonOffsetType::RightShoulder; + } + + void Camera::switchToDefaultShoulder() + { + if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder || mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) + mThirdPersionOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; + } + + void Camera::updateFocalPointOffset(float duration) + { + if (mThirdPersonMode == ThirdPersonViewMode::Standard) + return; // In Standard mode there is no focal point offset. + + ThirdPersonOffsetType newOffsetType = mThirdPersionOffsetType; + if (mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing) + newOffsetType = ThirdPersonOffsetType::Combat; + else if (MWBase::Environment::get().getWorld()->isSwimming(mTrackingPtr)) + newOffsetType = ThirdPersonOffsetType::Swimming; + else if (mThirdPersionOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Swimming) + newOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; + if (newOffsetType != mThirdPersionOffsetType) + { + if (newOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Combat) + mFocalPointTransitionSpeed = 5; + else + mFocalPointTransitionSpeed = 1; + mThirdPersionOffsetType = newOffsetType; + } + + osg::Vec2d focalPointTargetOffset; + switch (mThirdPersionOffsetType) + { + case ThirdPersonOffsetType::RightShoulder: + focalPointTargetOffset = mOverShoulderOffset; + break; + case ThirdPersonOffsetType::LeftShoulder: + focalPointTargetOffset = mOverShoulderOffset + focalPointTargetOffset.x() *= -1; + break; + case ThirdPersonOffsetType::Combat: + case ThirdPersonOffsetType::Swimming: + default: + focalPointTargetOffset = osg::Vec2d(0, 15); + } + + osg::Vec2d delta = focalPointTargetOffset - mFocalPointCurrentOffset; + if (delta.length2() > 0) + { + float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed; + mFocalPointCurrentOffset += delta * std::min(coef, 1.0f); + } + else + mFocalPointTransitionSpeed = 1.f; } void Camera::toggleViewMode(bool force) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 6398f4825..1e1d12f10 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -27,6 +27,8 @@ namespace MWRender enum class ThirdPersonViewMode {Standard, OverShoulder}; private: + enum class ThirdPersonOffsetType { RightShoulder, LeftShoulder, Combat, Swimming }; + struct CamData { float pitch, yaw, offset; }; @@ -60,12 +62,15 @@ namespace MWRender ThirdPersonViewMode mThirdPersonMode; osg::Vec2f mOverShoulderOffset; + bool mDefaultShoulderIsRight; osg::Vec3d mFocalPointAdjustment; - // Makes sense only if mThirdPersonMode is OverShoulder. Can be in range [0, 1]. - // Used for smooth transition from non-combat camera position (0) to combat camera position (1). - float mSmoothTransitionToCombatMode; - void updateSmoothTransitionToCombatMode(float duration); + // Makes sense only if mThirdPersonMode is OverShoulder. + ThirdPersonOffsetType mThirdPersionOffsetType; + osg::Vec2d mFocalPointCurrentOffset; + float mFocalPointTransitionSpeed; + + void updateFocalPointOffset(float duration); float getCameraDistanceCorrection() const; osg::ref_ptr mUpdateCallback; @@ -79,6 +84,10 @@ namespace MWRender void setThirdPersonViewMode(ThirdPersonViewMode mode) { mThirdPersonMode = mode; } void setOverShoulderOffset(float horizontal, float vertical); + void switchToLeftShoulder(); + void switchToRightShoulder(); + void switchToDefaultShoulder(); + /// Update the view matrix of \a cam void updateCamera(osg::Camera* cam); From ef03f2c033ebd8a6c2de41d7ed692b0715050123 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 20 Jun 2020 00:46:26 +0200 Subject: [PATCH 30/61] Auto switch shoulder --- apps/openmw/mwrender/camera.cpp | 2 +- apps/openmw/mwrender/camera.hpp | 3 +- apps/openmw/mwworld/worldimp.cpp | 35 +++++++++++++++++-- .../reference/modding/settings/camera.rst | 12 +++++++ files/settings-default.cfg | 3 ++ 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index e0f031b8c..3da94f97d 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -270,7 +270,7 @@ namespace MWRender focalPointTargetOffset = mOverShoulderOffset; break; case ThirdPersonOffsetType::LeftShoulder: - focalPointTargetOffset = mOverShoulderOffset + focalPointTargetOffset = mOverShoulderOffset; focalPointTargetOffset.x() *= -1; break; case ThirdPersonOffsetType::Combat: diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 1e1d12f10..b3e7e1f67 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -82,8 +82,9 @@ namespace MWRender MWWorld::Ptr getTrackingPtr() const; void setThirdPersonViewMode(ThirdPersonViewMode mode) { mThirdPersonMode = mode; } - void setOverShoulderOffset(float horizontal, float vertical); + ThirdPersonViewMode getThirdPersonViewMode() const { return mThirdPersonMode; } + void setOverShoulderOffset(float horizontal, float vertical); void switchToLeftShoulder(); void switchToRightShoulder(); void switchToDefaultShoulder(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 209ab538e..80a9a01ae 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1869,13 +1869,44 @@ namespace MWWorld float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f; float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f); - // Adjust focal point. osg::Vec3d focal = camera->getFocalPoint(); osg::Vec3d focalOffset = camera->getFocalPointOffset(); + osg::Vec3d playerPos = focal - focalOffset; + + static const bool autoSwitchShoulder = Settings::Manager::getBool("auto switch shoulder", "Camera"); + if (camera->getThirdPersonViewMode() == MWRender::Camera::ThirdPersonViewMode::OverShoulder + && autoSwitchShoulder && !camera->isVanityOrPreviewModeEnabled()) + { + const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit + const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance + auto orient = osg::Quat(camera->getYaw(), osg::Vec3d(0,0,1)); + int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door | MWPhysics::CollisionType_HeightMap; + MWPhysics::PhysicsSystem::RayResult rayRight = mPhysics->castRay( + playerPos + orient * osg::Vec3d(28, 0, 0), + playerPos + orient * osg::Vec3d(limitToSwitchBack, limitToSwitchBack, 0), + {}, {}, mask); + MWPhysics::PhysicsSystem::RayResult rayLeft = mPhysics->castRay( + playerPos + orient * osg::Vec3d(-28, 0, 0), + playerPos + orient * osg::Vec3d(-limitToSwitchBack, limitToSwitchBack, 0), + {}, {}, mask); + MWPhysics::PhysicsSystem::RayResult rayForward = mPhysics->castRay( + playerPos, playerPos + orient * osg::Vec3d(0, limitToSwitchBack, 0), + {}, {}, mask); + bool rightTooClose = rayRight.mHit && (rayRight.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; + bool leftTooClose = rayLeft.mHit && (rayLeft.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; + if (!rayRight.mHit && leftTooClose) + camera->switchToRightShoulder(); + else if (!rayLeft.mHit && rightTooClose) + camera->switchToLeftShoulder(); + else if (!rayRight.mHit && !rayLeft.mHit && !rayForward.mHit) + camera->switchToDefaultShoulder(); + } + + // Adjust focal point. float offsetLen = focalOffset.length(); if (offsetLen > 0) { - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit); + MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(playerPos, focal, focalObstacleLimit); if (result.mHit) { double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen; diff --git a/docs/source/reference/modding/settings/camera.rst b/docs/source/reference/modding/settings/camera.rst index 20349e97f..21fec8fd6 100644 --- a/docs/source/reference/modding/settings/camera.rst +++ b/docs/source/reference/modding/settings/camera.rst @@ -150,3 +150,15 @@ Recommened values: 30 -10 for the right shoulder, -30 -10 for the left shoulder. This setting can only be configured by editing the settings configuration file. +auto switch shoulder +-------------------- + +:Type: boolean +:Range: True/False +:Default: True + +This setting makes difference only in third person mode if 'view over shoulder' is enabled. +When player is close to an obstacle, automatically switches camera to the shoulder that is farther away from the obstacle. + +This setting can only be configured by editing the settings configuration file. + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 1e62ff5bf..b960946d8 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -42,6 +42,9 @@ view over shoulder = false # Makes sense only if 'view over shoulder' is true. First number is horizontal offset (negative value means offset to the left), second number is vertical offset. view over shoulder offset = 30 -10 +# Switch shoulder automatically when player is close to an obstacle. +auto switch shoulder = true + [Cells] # Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled. From 5bdf61a886d6da3913593ffe607d51c50e9783fb Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Mon, 22 Jun 2020 19:26:37 +0200 Subject: [PATCH 31/61] Slightly pulls camera away when the character moves --- apps/openmw/mwrender/camera.cpp | 19 +++++++++++++++++-- apps/openmw/mwrender/camera.hpp | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 3da94f97d..e856b8ab3 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -68,7 +68,8 @@ namespace MWRender mDefaultShoulderIsRight(true), mThirdPersionOffsetType(ThirdPersonOffsetType::RightShoulder), mFocalPointCurrentOffset(osg::Vec2d()), - mFocalPointTransitionSpeed(1.f) + mFocalPointTransitionSpeed(1.f), + mSmoothedSpeed(0.f) { mVanity.enabled = false; mVanity.allowed = true; @@ -216,6 +217,10 @@ namespace MWRender } updateFocalPointOffset(duration); + + float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); + float maxDelta = 300.f * duration; + mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } void Camera::setOverShoulderOffset(float horizontal, float vertical) @@ -482,7 +487,17 @@ namespace MWRender float Camera::getCameraDistanceCorrection() const { - return mThirdPersonMode != ThirdPersonViewMode::Standard ? std::max(-getPitch(), 0.f) * 50.f : 0; + if (mThirdPersonMode == ThirdPersonViewMode::Standard) + return 0; + else + { + float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; + + float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; + float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + + return pitchCorrection + speedCorrection; + } } void Camera::setCameraDistance() diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index b3e7e1f67..eb7462945 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -70,6 +70,8 @@ namespace MWRender osg::Vec2d mFocalPointCurrentOffset; float mFocalPointTransitionSpeed; + float mSmoothedSpeed; + void updateFocalPointOffset(float duration); float getCameraDistanceCorrection() const; From 51173ebcf5c7f9dfce9f57ceea6cfb30bf9ea6c9 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 11 Jul 2020 14:21:18 +0200 Subject: [PATCH 32/61] Refactoring. Move all code related to 'view over shoulder' to a separate file. --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwrender/camera.cpp | 89 +++----------------- apps/openmw/mwrender/camera.hpp | 25 ++---- apps/openmw/mwrender/renderingmanager.cpp | 19 ++--- apps/openmw/mwrender/renderingmanager.hpp | 2 + apps/openmw/mwrender/viewovershoulder.cpp | 99 +++++++++++++++++++++++ apps/openmw/mwrender/viewovershoulder.hpp | 30 +++++++ apps/openmw/mwworld/worldimp.cpp | 35 +------- 8 files changed, 159 insertions(+), 142 deletions(-) create mode 100644 apps/openmw/mwrender/viewovershoulder.cpp create mode 100644 apps/openmw/mwrender/viewovershoulder.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index fddfa276f..01d270f82 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -20,7 +20,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender actors objects renderingmanager animation rotatecontroller sky npcanimation vismask creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation - bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation + bulletdebugdraw globalmap characterpreview camera viewovershoulder localmap water terrainstorage ripplesimulation renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging ) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index e856b8ab3..3b3f1aec9 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -7,7 +7,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwbase/world.hpp" #include "../mwworld/class.hpp" #include "../mwworld/ptr.hpp" @@ -63,13 +62,12 @@ namespace MWRender mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), mCameraDistance(0.f), - mThirdPersonMode(ThirdPersonViewMode::Standard), - mOverShoulderOffset(osg::Vec2f(30.0f, -10.0f)), - mDefaultShoulderIsRight(true), - mThirdPersionOffsetType(ThirdPersonOffsetType::RightShoulder), mFocalPointCurrentOffset(osg::Vec2d()), + mFocalPointTargetOffset(osg::Vec2d()), mFocalPointTransitionSpeed(1.f), - mSmoothedSpeed(0.f) + mSmoothedSpeed(0.f), + mDynamicCameraDistanceEnabled(false), + mShowCrosshairInThirdPersonMode(false) { mVanity.enabled = false; mVanity.allowed = true; @@ -124,7 +122,7 @@ namespace MWRender osg::Vec3d Camera::getFocalPointOffset() const { osg::Vec3d offset(0, 0, 10.f); - if (mThirdPersonMode == ThirdPersonViewMode::OverShoulder && !mPreviewMode && !mVanity.enabled) + if (!mPreviewMode && !mVanity.enabled) { offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw()); offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw()); @@ -209,7 +207,7 @@ namespace MWRender // only show the crosshair in game mode MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager(); wm->showCrosshair(!wm->isGuiMode() && !mVanity.enabled && !mPreviewMode - && (mFirstPersonView || mThirdPersonMode != ThirdPersonViewMode::Standard)); + && (mFirstPersonView || mShowCrosshairInThirdPersonMode)); if(mVanity.enabled) { @@ -223,68 +221,9 @@ namespace MWRender mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } - void Camera::setOverShoulderOffset(float horizontal, float vertical) - { - mOverShoulderOffset = osg::Vec2f(std::abs(horizontal), vertical); - mDefaultShoulderIsRight = horizontal >= 0; - } - - void Camera::switchToLeftShoulder() - { - if (mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) - mThirdPersionOffsetType = ThirdPersonOffsetType::LeftShoulder; - } - - void Camera::switchToRightShoulder() - { - if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder) - mThirdPersionOffsetType = ThirdPersonOffsetType::RightShoulder; - } - - void Camera::switchToDefaultShoulder() - { - if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder || mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) - mThirdPersionOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; - } - void Camera::updateFocalPointOffset(float duration) { - if (mThirdPersonMode == ThirdPersonViewMode::Standard) - return; // In Standard mode there is no focal point offset. - - ThirdPersonOffsetType newOffsetType = mThirdPersionOffsetType; - if (mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing) - newOffsetType = ThirdPersonOffsetType::Combat; - else if (MWBase::Environment::get().getWorld()->isSwimming(mTrackingPtr)) - newOffsetType = ThirdPersonOffsetType::Swimming; - else if (mThirdPersionOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Swimming) - newOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; - if (newOffsetType != mThirdPersionOffsetType) - { - if (newOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Combat) - mFocalPointTransitionSpeed = 5; - else - mFocalPointTransitionSpeed = 1; - mThirdPersionOffsetType = newOffsetType; - } - - osg::Vec2d focalPointTargetOffset; - switch (mThirdPersionOffsetType) - { - case ThirdPersonOffsetType::RightShoulder: - focalPointTargetOffset = mOverShoulderOffset; - break; - case ThirdPersonOffsetType::LeftShoulder: - focalPointTargetOffset = mOverShoulderOffset; - focalPointTargetOffset.x() *= -1; - break; - case ThirdPersonOffsetType::Combat: - case ThirdPersonOffsetType::Swimming: - default: - focalPointTargetOffset = osg::Vec2d(0, 15); - } - - osg::Vec2d delta = focalPointTargetOffset - mFocalPointCurrentOffset; + osg::Vec2d delta = mFocalPointTargetOffset - mFocalPointCurrentOffset; if (delta.length2() > 0) { float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed; @@ -487,17 +426,15 @@ namespace MWRender float Camera::getCameraDistanceCorrection() const { - if (mThirdPersonMode == ThirdPersonViewMode::Standard) + if (!mDynamicCameraDistanceEnabled) return 0; - else - { - float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; - float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; - float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; - return pitchCorrection + speedCorrection; - } + float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; + float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + + return pitchCorrection + speedCorrection; } void Camera::setCameraDistance() diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index eb7462945..5f3c5d6e4 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -23,12 +23,7 @@ namespace MWRender /// \brief Camera control class Camera { - public: - enum class ThirdPersonViewMode {Standard, OverShoulder}; - private: - enum class ThirdPersonOffsetType { RightShoulder, LeftShoulder, Combat, Swimming }; - struct CamData { float pitch, yaw, offset; }; @@ -60,17 +55,14 @@ namespace MWRender float mCameraDistance; - ThirdPersonViewMode mThirdPersonMode; - osg::Vec2f mOverShoulderOffset; - bool mDefaultShoulderIsRight; osg::Vec3d mFocalPointAdjustment; - - // Makes sense only if mThirdPersonMode is OverShoulder. - ThirdPersonOffsetType mThirdPersionOffsetType; osg::Vec2d mFocalPointCurrentOffset; + osg::Vec2d mFocalPointTargetOffset; float mFocalPointTransitionSpeed; float mSmoothedSpeed; + bool mDynamicCameraDistanceEnabled; + bool mShowCrosshairInThirdPersonMode; void updateFocalPointOffset(float duration); float getCameraDistanceCorrection() const; @@ -83,13 +75,10 @@ namespace MWRender MWWorld::Ptr getTrackingPtr() const; - void setThirdPersonViewMode(ThirdPersonViewMode mode) { mThirdPersonMode = mode; } - ThirdPersonViewMode getThirdPersonViewMode() const { return mThirdPersonMode; } - - void setOverShoulderOffset(float horizontal, float vertical); - void switchToLeftShoulder(); - void switchToRightShoulder(); - void switchToDefaultShoulder(); + void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeed = v; } + void setFocalPointTargetOffset(osg::Vec2d v) { mFocalPointTargetOffset = v; } + void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } + void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } /// Update the view matrix of \a cam void updateCamera(osg::Camera* cam); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c7dd5ca63..d91da5a08 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -65,6 +65,7 @@ #include "vismask.hpp" #include "pathgrid.hpp" #include "camera.hpp" +#include "viewovershoulder.hpp" #include "water.hpp" #include "terrainstorage.hpp" #include "util.hpp" @@ -306,6 +307,8 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath)); mCamera.reset(new Camera(mViewer->getCamera())); + if (Settings::Manager::getBool("view over shoulder", "Camera")) + mViewOverShoulderController.reset(new ViewOverShoulderController(mCamera.get())); mViewer->setLightingMode(osgViewer::View::NO_LIGHT); @@ -366,7 +369,6 @@ namespace MWRender float firstPersonFov = Settings::Manager::getFloat("first person field of view", "Camera"); mFirstPersonFieldOfView = std::min(std::max(1.f, firstPersonFov), 179.f); mStateUpdater->setFogEnd(mViewDistance); - updateThirdPersonViewMode(); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance)); @@ -382,19 +384,6 @@ namespace MWRender mWorkQueue = nullptr; } - void RenderingManager::updateThirdPersonViewMode() - { - if (Settings::Manager::getBool("view over shoulder", "Camera")) - mCamera->setThirdPersonViewMode(Camera::ThirdPersonViewMode::OverShoulder); - else - mCamera->setThirdPersonViewMode(Camera::ThirdPersonViewMode::Standard); - - std::stringstream offset(Settings::Manager::getString("view over shoulder offset", "Camera")); - float horizontal = 30.f, vertical = -10.f; - offset >> horizontal >> vertical; - mCamera->setOverShoulderOffset(horizontal, vertical); - } - osgUtil::IncrementalCompileOperation* RenderingManager::getIncrementalCompileOperation() { return mViewer->getIncrementalCompileOperation(); @@ -630,6 +619,8 @@ namespace MWRender updateNavMesh(); updateRecastMesh(); + if (mViewOverShoulderController) + mViewOverShoulderController->update(); mCamera->update(dt, paused); osg::Vec3d focal, cameraPos; diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 6700f5ce6..d6a0f89c3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -79,6 +79,7 @@ namespace MWRender class NpcAnimation; class Pathgrid; class Camera; + class ViewOverShoulderController; class Water; class TerrainStorage; class LandManager; @@ -294,6 +295,7 @@ namespace MWRender osg::ref_ptr mPlayerAnimation; osg::ref_ptr mPlayerNode; std::unique_ptr mCamera; + std::unique_ptr mViewOverShoulderController; osg::Vec3f mCurrentCameraPos; osg::ref_ptr mStateUpdater; diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp new file mode 100644 index 000000000..f908b1430 --- /dev/null +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -0,0 +1,99 @@ +#include "viewovershoulder.hpp" + +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/refdata.hpp" + +#include "../mwmechanics/drawstate.hpp" + +namespace MWRender +{ + + ViewOverShoulderController::ViewOverShoulderController(Camera* camera) : + mCamera(camera), mMode(Mode::RightShoulder), + mAutoSwitchShoulder(Settings::Manager::getBool("auto switch shoulder", "Camera")), + mOverShoulderHorizontalOffset(30.f), mOverShoulderVerticalOffset(-10.f) + { + std::stringstream offset(Settings::Manager::getString("view over shoulder offset", "Camera")); + offset >> mOverShoulderHorizontalOffset >> mOverShoulderVerticalOffset; + mDefaultShoulderIsRight = mOverShoulderHorizontalOffset >= 0; + mOverShoulderHorizontalOffset = std::abs(mOverShoulderHorizontalOffset); + + mCamera->enableDynamicCameraDistance(true); + mCamera->enableCrosshairInThirdPersonMode(true); + } + + void ViewOverShoulderController::update() + { + if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson()) + return; + + Mode newMode = mMode; + auto ptr = mCamera->getTrackingPtr(); + if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing) + newMode = Mode::Combat; + else if (MWBase::Environment::get().getWorld()->isSwimming(ptr)) + newMode = Mode::Swimming; + else if (mMode == Mode::Combat || mMode == Mode::Swimming) + newMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; + if (newMode != mMode) + { + if (newMode == Mode::Combat || mMode == Mode::Combat) + mCamera->setFocalPointTransitionSpeed(5.f); + else + mCamera->setFocalPointTransitionSpeed(1.f); + mMode = newMode; + } + + if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder)) + trySwitchShoulder(); + + osg::Vec2d focalPointTargetOffset; + switch (mMode) + { + case Mode::RightShoulder: + mCamera->setFocalPointTargetOffset({mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset}); + break; + case Mode::LeftShoulder: + mCamera->setFocalPointTargetOffset({-mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset}); + break; + case Mode::Combat: + case Mode::Swimming: + default: + mCamera->setFocalPointTargetOffset({0, 15}); + } + } + + void ViewOverShoulderController::trySwitchShoulder() + { + const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit + const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance + + auto orient = osg::Quat(mCamera->getYaw(), osg::Vec3d(0,0,1)); + osg::Vec3d playerPos = mCamera->getFocalPoint() - mCamera->getFocalPointOffset(); + + MWBase::World* world = MWBase::Environment::get().getWorld(); + osg::Vec3d sideOffset = orient * osg::Vec3d(world->getHalfExtents(mCamera->getTrackingPtr()).x() - 1, 0, 0); + float rayRight = world->getDistToNearestRayHit( + playerPos + sideOffset, orient * osg::Vec3d(1, 1, 0), limitToSwitchBack + 1); + float rayLeft = world->getDistToNearestRayHit( + playerPos - sideOffset, orient * osg::Vec3d(-1, 1, 0), limitToSwitchBack + 1); + float rayForward = world->getDistToNearestRayHit( + playerPos, orient * osg::Vec3d(0, 1, 0), limitToSwitchBack + 1); + + if (rayLeft < limitToSwitch && rayRight > limitToSwitchBack) + mMode = Mode::RightShoulder; + else if (rayRight < limitToSwitch && rayLeft > limitToSwitchBack) + mMode = Mode::LeftShoulder; + else if (rayLeft > limitToSwitchBack && rayRight > limitToSwitchBack && rayForward > limitToSwitchBack) + mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; + } + +} \ No newline at end of file diff --git a/apps/openmw/mwrender/viewovershoulder.hpp b/apps/openmw/mwrender/viewovershoulder.hpp new file mode 100644 index 000000000..80ac30865 --- /dev/null +++ b/apps/openmw/mwrender/viewovershoulder.hpp @@ -0,0 +1,30 @@ +#ifndef VIEWOVERSHOULDER_H +#define VIEWOVERSHOULDER_H + +#include "camera.hpp" + +namespace MWRender +{ + + class ViewOverShoulderController + { + public: + ViewOverShoulderController(Camera* camera); + + void update(); + + private: + void trySwitchShoulder(); + enum class Mode { RightShoulder, LeftShoulder, Combat, Swimming }; + + Camera* mCamera; + Mode mMode; + bool mAutoSwitchShoulder; + float mOverShoulderHorizontalOffset; + float mOverShoulderVerticalOffset; + bool mDefaultShoulderIsRight; + }; + +} + +#endif // VIEWOVERSHOULDER_H diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 80a9a01ae..209ab538e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1869,44 +1869,13 @@ namespace MWWorld float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f; float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f); + // Adjust focal point. osg::Vec3d focal = camera->getFocalPoint(); osg::Vec3d focalOffset = camera->getFocalPointOffset(); - osg::Vec3d playerPos = focal - focalOffset; - - static const bool autoSwitchShoulder = Settings::Manager::getBool("auto switch shoulder", "Camera"); - if (camera->getThirdPersonViewMode() == MWRender::Camera::ThirdPersonViewMode::OverShoulder - && autoSwitchShoulder && !camera->isVanityOrPreviewModeEnabled()) - { - const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit - const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance - auto orient = osg::Quat(camera->getYaw(), osg::Vec3d(0,0,1)); - int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door | MWPhysics::CollisionType_HeightMap; - MWPhysics::PhysicsSystem::RayResult rayRight = mPhysics->castRay( - playerPos + orient * osg::Vec3d(28, 0, 0), - playerPos + orient * osg::Vec3d(limitToSwitchBack, limitToSwitchBack, 0), - {}, {}, mask); - MWPhysics::PhysicsSystem::RayResult rayLeft = mPhysics->castRay( - playerPos + orient * osg::Vec3d(-28, 0, 0), - playerPos + orient * osg::Vec3d(-limitToSwitchBack, limitToSwitchBack, 0), - {}, {}, mask); - MWPhysics::PhysicsSystem::RayResult rayForward = mPhysics->castRay( - playerPos, playerPos + orient * osg::Vec3d(0, limitToSwitchBack, 0), - {}, {}, mask); - bool rightTooClose = rayRight.mHit && (rayRight.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; - bool leftTooClose = rayLeft.mHit && (rayLeft.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; - if (!rayRight.mHit && leftTooClose) - camera->switchToRightShoulder(); - else if (!rayLeft.mHit && rightTooClose) - camera->switchToLeftShoulder(); - else if (!rayRight.mHit && !rayLeft.mHit && !rayForward.mHit) - camera->switchToDefaultShoulder(); - } - - // Adjust focal point. float offsetLen = focalOffset.length(); if (offsetLen > 0) { - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(playerPos, focal, focalObstacleLimit); + MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit); if (result.mHit) { double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen; From 173c1fdabb507f0dd204a0219b06d96af33a47fe Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 12 Jul 2020 01:55:20 +0200 Subject: [PATCH 33/61] Make transition in 'auto switch shoulder' smoother. --- apps/openmw/mwrender/camera.cpp | 35 +++++++++++++++++++++-- apps/openmw/mwrender/camera.hpp | 12 ++++++-- apps/openmw/mwrender/viewovershoulder.cpp | 27 ++++++++--------- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 3b3f1aec9..1e6ea2843 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -64,7 +64,8 @@ namespace MWRender mCameraDistance(0.f), mFocalPointCurrentOffset(osg::Vec2d()), mFocalPointTargetOffset(osg::Vec2d()), - mFocalPointTransitionSpeed(1.f), + mFocalPointTransitionSpeedCoef(1.f), + mPreviousTransitionInfluence(0.f), mSmoothedSpeed(0.f), mDynamicCameraDistanceEnabled(false), mShowCrosshairInThirdPersonMode(false) @@ -221,16 +222,44 @@ namespace MWRender mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } + void Camera::setFocalPointTargetOffset(osg::Vec2d v) + { + mFocalPointTargetOffset = v; + mPreviousTransitionSpeed = mFocalPointTransitionSpeed; + mPreviousTransitionInfluence = 1.0f; + } + void Camera::updateFocalPointOffset(float duration) { + if (duration <= 0) + return; + + osg::Vec2d oldOffset = mFocalPointCurrentOffset; + + if (mPreviousTransitionInfluence > 0) + { + mFocalPointCurrentOffset -= mPreviousExtraOffset; + mPreviousExtraOffset = mPreviousExtraOffset / mPreviousTransitionInfluence + mPreviousTransitionSpeed * duration; + mPreviousTransitionInfluence = + std::max(0.f, mPreviousTransitionInfluence - duration * mFocalPointTransitionSpeedCoef); + mPreviousExtraOffset *= mPreviousTransitionInfluence; + mFocalPointCurrentOffset += mPreviousExtraOffset; + } + osg::Vec2d delta = mFocalPointTargetOffset - mFocalPointCurrentOffset; if (delta.length2() > 0) { - float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed; + float coef = duration * (1.0 + 5.0 / delta.length()) * + mFocalPointTransitionSpeedCoef * (1.0f - mPreviousTransitionInfluence); mFocalPointCurrentOffset += delta * std::min(coef, 1.0f); } else - mFocalPointTransitionSpeed = 1.f; + { + mPreviousExtraOffset = osg::Vec2d(); + mPreviousTransitionInfluence = 0.f; + } + + mFocalPointTransitionSpeed = (mFocalPointCurrentOffset - oldOffset) / duration; } void Camera::toggleViewMode(bool force) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 5f3c5d6e4..bd70d6d9a 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -58,7 +58,13 @@ namespace MWRender osg::Vec3d mFocalPointAdjustment; osg::Vec2d mFocalPointCurrentOffset; osg::Vec2d mFocalPointTargetOffset; - float mFocalPointTransitionSpeed; + float mFocalPointTransitionSpeedCoef; + + // This fields are used to make focal point transition smooth if previous transition was not finished. + float mPreviousTransitionInfluence; + osg::Vec2d mFocalPointTransitionSpeed; + osg::Vec2d mPreviousTransitionSpeed; + osg::Vec2d mPreviousExtraOffset; float mSmoothedSpeed; bool mDynamicCameraDistanceEnabled; @@ -75,8 +81,8 @@ namespace MWRender MWWorld::Ptr getTrackingPtr() const; - void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeed = v; } - void setFocalPointTargetOffset(osg::Vec2d v) { mFocalPointTargetOffset = v; } + void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; } + void setFocalPointTargetOffset(osg::Vec2d v); void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp index f908b1430..5d7ec7117 100644 --- a/apps/openmw/mwrender/viewovershoulder.cpp +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -28,6 +28,7 @@ namespace MWRender mCamera->enableDynamicCameraDistance(true); mCamera->enableCrosshairInThirdPersonMode(true); + mCamera->setFocalPointTargetOffset({mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset}); } void ViewOverShoulderController::update() @@ -35,27 +36,23 @@ namespace MWRender if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson()) return; - Mode newMode = mMode; + Mode oldMode = mMode; auto ptr = mCamera->getTrackingPtr(); if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing) - newMode = Mode::Combat; + mMode = Mode::Combat; else if (MWBase::Environment::get().getWorld()->isSwimming(ptr)) - newMode = Mode::Swimming; - else if (mMode == Mode::Combat || mMode == Mode::Swimming) - newMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; - if (newMode != mMode) - { - if (newMode == Mode::Combat || mMode == Mode::Combat) - mCamera->setFocalPointTransitionSpeed(5.f); - else - mCamera->setFocalPointTransitionSpeed(1.f); - mMode = newMode; - } - + mMode = Mode::Swimming; + else if (oldMode == Mode::Combat || oldMode == Mode::Swimming) + mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder)) trySwitchShoulder(); + if (oldMode == mMode) return; + + if (oldMode == Mode::Combat || mMode == Mode::Combat) + mCamera->setFocalPointTransitionSpeed(5.f); + else + mCamera->setFocalPointTransitionSpeed(1.f); - osg::Vec2d focalPointTargetOffset; switch (mMode) { case Mode::RightShoulder: From 383fa3d3ab040e41880bc55d6ac74be82f4d4be0 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 12 Jul 2020 21:03:18 +0200 Subject: [PATCH 34/61] Make 'zoom out when move' configurable. --- apps/openmw/mwrender/camera.cpp | 3 ++- apps/openmw/mwrender/camera.hpp | 1 + docs/source/reference/modding/settings/camera.rst | 12 ++++++++++++ files/settings-default.cfg | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 1e6ea2843..7531e712b 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -67,6 +67,7 @@ namespace MWRender mFocalPointTransitionSpeedCoef(1.f), mPreviousTransitionInfluence(0.f), mSmoothedSpeed(0.f), + mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")), mDynamicCameraDistanceEnabled(false), mShowCrosshairInThirdPersonMode(false) { @@ -461,7 +462,7 @@ namespace MWRender float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; - float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * mZoomOutWhenMoveCoef; return pitchCorrection + speedCorrection; } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index bd70d6d9a..59fa53047 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -67,6 +67,7 @@ namespace MWRender osg::Vec2d mPreviousExtraOffset; float mSmoothedSpeed; + float mZoomOutWhenMoveCoef; bool mDynamicCameraDistanceEnabled; bool mShowCrosshairInThirdPersonMode; diff --git a/docs/source/reference/modding/settings/camera.rst b/docs/source/reference/modding/settings/camera.rst index 21fec8fd6..be636cef4 100644 --- a/docs/source/reference/modding/settings/camera.rst +++ b/docs/source/reference/modding/settings/camera.rst @@ -162,3 +162,15 @@ When player is close to an obstacle, automatically switches camera to the should This setting can only be configured by editing the settings configuration file. +zoom out when move coef +----------------------- + +:Type: floating point +:Range: Any +:Default: 20 + +This setting makes difference only in third person mode if 'view over shoulder' is enabled. +Slightly pulls camera away (or closer in case of negative value) when the character moves. To disable set it to zero. + +This setting can only be configured by editing the settings configuration file. + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index b960946d8..35be128a8 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -45,6 +45,9 @@ view over shoulder offset = 30 -10 # Switch shoulder automatically when player is close to an obstacle. auto switch shoulder = true +# Slightly pulls camera away when the character moves. Works only in 'view over shoulder' mode. Set to 0 to disable. +zoom out when move coef = 20 + [Cells] # Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled. From 7676a36b32bf86c79672878f7f4e696ce69283bc Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 22:38:48 +0100 Subject: [PATCH 35/61] Time a build with the reduced cache --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2bdfa990e..313f21d4f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -172,4 +172,4 @@ Windows_MSBuild_RelWithDebInfo: extends: - .Windows_MSBuild_Base variables: - config: "RelWithDebInfo" \ No newline at end of file + config: "RelWithDebInfo" From 0d1fb31358b02b76835d4df70965bd4c4fd73ca2 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 22:39:24 +0100 Subject: [PATCH 36/61] Revert "Revert "Build the CS again."" Maybe the reduced cache makes it fit. This reverts commit 20859bbc50341745b3be00ef8995d1f9d698bd8b. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 313f21d4f..cfb304af7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -129,7 +129,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From c132646b974de5641b7c3da2343fa5e44ddd8f91 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 01:44:08 +0100 Subject: [PATCH 37/61] Time commands --- .gitlab-ci.yml | 80 +++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cfb304af7..3ae240162 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,30 +50,34 @@ MacOS: tags: - windows before_script: - - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" - - choco install git --force --params "/GitAndUnixToolsOnPath" -y - - choco install 7zip -y - - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y - - choco install vswhere -y - - choco install ninja -y - - choco install python -y - - refreshenv + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } + - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } + - Measure-Command -Expression { choco install 7zip -y | Out-Default } + - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } + - Measure-Command -Expression { choco install vswhere -y | Out-Default } + - Measure-Command -Expression { choco install ninja -y | Out-Default } + - Measure-Command -Expression { choco install python -y | Out-Default } + - Measure-Command -Expression { refreshenv | Out-Default } + - Get-Date -Format "HH:mm:ss" stage: build script: - - $time = (Get-Date -Format "HH:mm:ss") - - echo ${time} - - echo "started by ${GITLAB_USER_NAME}" - - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - - cd MSVC2019_64_Ninja - - .\ActivateMSVC.ps1 - - cmake --build . --config $config - - cd $config + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } + - Measure-Command -Expression { echo ${time} | Out-Default } + - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } + - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N | Out-Default } + - Measure-Command -Expression { cd MSVC2019_64_Ninja | Out-Default } + - Measure-Command -Expression { .\ActivateMSVC.ps1 | Out-Default } + - Measure-Command -Expression { cmake --build . --config $config | Out-Default } + - Measure-Command -Expression { cd $config | Out-Default } - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' - Get-ChildItem -Recurse *.pdb | Remove-Item + Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } + Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' + - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } + - Get-Date -Format "HH:mm:ss" cache: key: ninja-v2 paths: @@ -115,28 +119,32 @@ Windows_Ninja_RelWithDebInfo: tags: - windows before_script: - - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" - - choco install git --force --params "/GitAndUnixToolsOnPath" -y - - choco install 7zip -y - - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y - - choco install vswhere -y - - choco install python -y - - refreshenv + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } + - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } + - Measure-Command -Expression { choco install 7zip -y | Out-Default } + - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } + - Measure-Command -Expression { choco install vswhere -y | Out-Default } + - Measure-Command -Expression { choco install python -y | Out-Default } + - Measure-Command -Expression { refreshenv | Out-Default } + - Get-Date -Format "HH:mm:ss" stage: build script: - - $time = (Get-Date -Format "HH:mm:ss") - - echo ${time} - - echo "started by ${GITLAB_USER_NAME}" - - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - - cd MSVC2019_64 - - cmake --build . --config $config - - cd $config + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } + - Measure-Command -Expression { echo ${time} | Out-Default } + - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } + - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V | Out-Default } + - Measure-Command -Expression { cd MSVC2019_64 | Out-Default } + - Measure-Command -Expression { cmake --build . --config $config | Out-Default } + - Measure-Command -Expression { cd $config | Out-Default } - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' - Get-ChildItem -Recurse *.pdb | Remove-Item + Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } + Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' + - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } + - Get-Date -Format "HH:mm:ss" cache: key: msbuild-v2 paths: From 6a8e736bd247b2667d5d9f0abaf0e008e81fab60 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 16:53:23 +0100 Subject: [PATCH 38/61] Revert "Time commands" This reverts commit c132646b974de5641b7c3da2343fa5e44ddd8f91. --- .gitlab-ci.yml | 80 +++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3ae240162..cfb304af7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,34 +50,30 @@ MacOS: tags: - windows before_script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } - - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } - - Measure-Command -Expression { choco install 7zip -y | Out-Default } - - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } - - Measure-Command -Expression { choco install vswhere -y | Out-Default } - - Measure-Command -Expression { choco install ninja -y | Out-Default } - - Measure-Command -Expression { choco install python -y | Out-Default } - - Measure-Command -Expression { refreshenv | Out-Default } - - Get-Date -Format "HH:mm:ss" + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install ninja -y + - choco install python -y + - refreshenv stage: build script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } - - Measure-Command -Expression { echo ${time} | Out-Default } - - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } - - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N | Out-Default } - - Measure-Command -Expression { cd MSVC2019_64_Ninja | Out-Default } - - Measure-Command -Expression { .\ActivateMSVC.ps1 | Out-Default } - - Measure-Command -Expression { cmake --build . --config $config | Out-Default } - - Measure-Command -Expression { cd $config | Out-Default } + - $time = (Get-Date -Format "HH:mm:ss") + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N + - cd MSVC2019_64_Ninja + - .\ActivateMSVC.ps1 + - cmake --build . --config $config + - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } - Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item } - - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } - - Get-Date -Format "HH:mm:ss" + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: key: ninja-v2 paths: @@ -119,32 +115,28 @@ Windows_Ninja_RelWithDebInfo: tags: - windows before_script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } - - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } - - Measure-Command -Expression { choco install 7zip -y | Out-Default } - - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } - - Measure-Command -Expression { choco install vswhere -y | Out-Default } - - Measure-Command -Expression { choco install python -y | Out-Default } - - Measure-Command -Expression { refreshenv | Out-Default } - - Get-Date -Format "HH:mm:ss" + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install python -y + - refreshenv stage: build script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } - - Measure-Command -Expression { echo ${time} | Out-Default } - - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } - - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V | Out-Default } - - Measure-Command -Expression { cd MSVC2019_64 | Out-Default } - - Measure-Command -Expression { cmake --build . --config $config | Out-Default } - - Measure-Command -Expression { cd $config | Out-Default } + - $time = (Get-Date -Format "HH:mm:ss") + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V + - cd MSVC2019_64 + - cmake --build . --config $config + - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } - Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item } - - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } - - Get-Date -Format "HH:mm:ss" + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: key: msbuild-v2 paths: From 5549ddab97f8d9b5cf0581219497deb92ccf6fd9 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 17:08:46 +0100 Subject: [PATCH 39/61] Split CS into separate jobs so build time is less tight. Now we have twelve Windows jobs. Yay! --- .gitlab-ci.yml | 70 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cfb304af7..9d0645eda 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,6 +46,12 @@ MacOS: paths: - build/OpenMW-*.dmg +variables: &engine-targets + targets: openmw openmw-essimporter openmw-iniimporter openmw-launcher openmw-wizard + +variables: &cs-targets + targets: openmw-cs bsatool esmtool niftest + .Windows_Ninja_Base: tags: - windows @@ -66,7 +72,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config + - cmake --build . --config $config --target $targets - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -93,22 +99,46 @@ MacOS: - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log -Windows_Ninja_Release: +Windows_Ninja_Engine_Release: + extends: + - .Windows_Ninja_Base + variables: + <<: *engine-targets + config: "Release" + +Windows_Ninja_Engine_Debug: + extends: + - .Windows_Ninja_Base + variables: + <<: *engine-targets + config: "Debug" + +Windows_Ninja_Engine_RelWithDebInfo: + extends: + - .Windows_Ninja_Base + variables: + <<: *engine-targets + config: "RelWithDebInfo" + +Windows_Ninja_CS_Release: extends: - .Windows_Ninja_Base variables: + <<: *cs-targets config: "Release" -Windows_Ninja_Debug: +Windows_Ninja_CS_Debug: extends: - .Windows_Ninja_Base variables: + <<: *cs-targets config: "Debug" -Windows_Ninja_RelWithDebInfo: +Windows_Ninja_CS_RelWithDebInfo: extends: - .Windows_Ninja_Base variables: + <<: *cs-targets config: "RelWithDebInfo" .Windows_MSBuild_Base: @@ -129,7 +159,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config + - cmake --build . --config $config --target $targets - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -156,20 +186,44 @@ Windows_Ninja_RelWithDebInfo: - MSVC2019_64/*/*/*/*/*/*/*.log - MSVC2019_64/*/*/*/*/*/*/*/*.log -Windows_MSBuild_Release: +Windows_MSBuild_Engine_Release: + extends: + - .Windows_MSBuild_Base + variables: + <<: *engine-targets + config: "Release" + +Windows_MSBuild_Engine_Debug: + extends: + - .Windows_MSBuild_Base + variables: + <<: *engine-targets + config: "Debug" + +Windows_MSBuild_Engine_RelWithDebInfo: + extends: + - .Windows_MSBuild_Base + variables: + <<: *engine-targets + config: "RelWithDebInfo" + +Windows_MSBuild_CS_Release: extends: - .Windows_MSBuild_Base variables: + <<: *cs-targets config: "Release" -Windows_MSBuild_Debug: +Windows_MSBuild_CS_Debug: extends: - .Windows_MSBuild_Base variables: + <<: *cs-targets config: "Debug" -Windows_MSBuild_RelWithDebInfo: +Windows_MSBuild_CS_RelWithDebInfo: extends: - .Windows_MSBuild_Base variables: + <<: *cs-targets config: "RelWithDebInfo" From a43766bbc82f9e672939d3bea517a38fedbe53b9 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 18:02:05 +0100 Subject: [PATCH 40/61] Try removing bashism reliance --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d0645eda..e70892f18 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: openmw openmw-essimporter openmw-iniimporter openmw-launcher openmw-wizard + targets: "openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard" variables: &cs-targets - targets: openmw-cs bsatool esmtool niftest + targets: "openmw-cs", "bsatool", "esmtool", "niftest" .Windows_Ninja_Base: tags: From a03fd0330299abd29fe924ff52cca4eeb9a56732 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 18:04:25 +0100 Subject: [PATCH 41/61] YAML wants lots of quotes --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e70892f18..90f1c5135 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: "openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard" + targets: '"openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard"' variables: &cs-targets - targets: "openmw-cs", "bsatool", "esmtool", "niftest" + targets: '"openmw-cs", "bsatool", "esmtool", "niftest"' .Windows_Ninja_Base: tags: From 1720e2e1fda17f7a2aa989d935b9970c65cfd661 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 18:47:42 +0100 Subject: [PATCH 42/61] CI kick --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 90f1c5135..1afb7b2ad 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -226,4 +226,4 @@ Windows_MSBuild_CS_RelWithDebInfo: - .Windows_MSBuild_Base variables: <<: *cs-targets - config: "RelWithDebInfo" + config: "RelWithDebInfo" \ No newline at end of file From b7c1c52439021970713276637eda4254c356a853 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 13 Jul 2020 20:04:23 +0200 Subject: [PATCH 43/61] Adjust actor rotation when flee by axis x Otherwise Cliff Racers can go underwater. --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aicombat.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ed287ee..d9c1c5065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Bug #5499: Faction advance is available when requirements not met Bug #5502: Dead zone for analogue stick movement is too small Bug #5507: Sound volume is not clamped on ingame settings update + Bug #5531: Actors flee using current rotation by axis x Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging Feature #5297: Add a search function to the "Datafiles" tab of the OpenMW launcher diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index a77539a1f..1ae27a9cb 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -344,6 +344,7 @@ namespace MWMechanics { storage.mFleeBlindRunTimer += duration; + storage.mMovement.mRotation[0] = -actor.getRefData().getPosition().rot[0]; storage.mMovement.mRotation[2] = osg::PI + getZAngleToDir(target.getRefData().getPosition().asVec3()-actor.getRefData().getPosition().asVec3()); storage.mMovement.mPosition[1] = 1; updateActorsMovement(actor, duration, storage); From 000b52fc05623e1993fb73036be340cc32eece67 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 22:03:48 +0100 Subject: [PATCH 44/61] Swap quotes around --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1afb7b2ad..01947e374 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: '"openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard"' + targets: "'openmw', 'openmw-essimporter', 'openmw-iniimporter', 'openmw-launcher', 'openmw-wizard'" variables: &cs-targets - targets: '"openmw-cs", "bsatool", "esmtool", "niftest"' + targets: "'openmw-cs', 'bsatool', 'esmtool', 'niftest'" .Windows_Ninja_Base: tags: From cd4ab320d8b8b4cf3391d1b11becfec7e2231ba7 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 22:34:58 +0100 Subject: [PATCH 45/61] Don't bother trying to set a PowerShell array from YAML Just set a string and split it in the script. --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 01947e374..e16aefcc1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: "'openmw', 'openmw-essimporter', 'openmw-iniimporter', 'openmw-launcher', 'openmw-wizard'" + targets: "openmw,openmw-essimporter,openmw-iniimporter,openmw-launcher,openmw-wizard" variables: &cs-targets - targets: "'openmw-cs', 'bsatool', 'esmtool', 'niftest'" + targets: "openmw-cs,bsatool,esmtool,niftest" .Windows_Ninja_Base: tags: @@ -72,7 +72,7 @@ variables: &cs-targets - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target $targets + - cmake --build . --config $config --target ($targets.Split(',')) - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -159,7 +159,7 @@ Windows_Ninja_CS_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target $targets + - cmake --build . --config $config --target ($targets.Split(',')) - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From b05d071e69c5c94ccfb9adb8e1c2c859627b91df Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 14 Jul 2020 10:53:01 +0400 Subject: [PATCH 46/61] Resume failed scripts execution after game reload (feature #5524) --- CHANGELOG.md | 1 + apps/openmw/mwbase/scriptmanager.hpp | 2 ++ apps/openmw/mwscript/scriptmanagerimp.cpp | 24 ++++++++++++++++------- apps/openmw/mwscript/scriptmanagerimp.hpp | 17 +++++++++++++++- apps/openmw/mwstate/statemanagerimp.cpp | 2 +- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ed287ee..e6ec9cf57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Feature #5445: Handle NiLines Feature #5457: Realistic diagonal movement Feature #5486: Fixes trainers to choose their training skills based on their base skill points + Feature #5524: Resume failed script execution after reload Task #5480: Drop Qt4 support 0.46.0 diff --git a/apps/openmw/mwbase/scriptmanager.hpp b/apps/openmw/mwbase/scriptmanager.hpp index da3454d34..ac8333ed1 100644 --- a/apps/openmw/mwbase/scriptmanager.hpp +++ b/apps/openmw/mwbase/scriptmanager.hpp @@ -35,6 +35,8 @@ namespace MWBase virtual ~ScriptManager() {} + virtual void clear() = 0; + virtual bool run (const std::string& name, Interpreter::Context& interpreterContext) = 0; ///< Run the script with the given name (compile first, if not compiled yet) diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index b69eb7f60..0077b7cd0 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -79,8 +79,8 @@ namespace MWScript if (Success) { std::vector code; - mParser.getCode (code); - mScripts.insert (std::make_pair (name, std::make_pair (code, mParser.getLocals()))); + mParser.getCode(code); + mScripts.emplace(name, CompiledScript(code, mParser.getLocals())); return true; } @@ -100,7 +100,7 @@ namespace MWScript { // failed -> ignore script from now on. std::vector empty; - mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); + mScripts.emplace(name, CompiledScript(empty, Compiler::Locals())); return false; } @@ -109,7 +109,7 @@ namespace MWScript } // execute script - if (!iter->second.first.empty()) + if (!iter->second.mByteCode.empty() && iter->second.mActive) try { if (!mOpcodesInstalled) @@ -118,7 +118,7 @@ namespace MWScript mOpcodesInstalled = true; } - mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext); + mInterpreter.run (&iter->second.mByteCode[0], iter->second.mByteCode.size(), interpreterContext); return true; } catch (const MissingImplicitRefError& e) @@ -129,11 +129,21 @@ namespace MWScript { Log(Debug::Error) << "Execution of script " << name << " failed: " << e.what(); - iter->second.first.clear(); // don't execute again. + iter->second.mActive = false; // don't execute again. } return false; } + void ScriptManager::clear() + { + for (auto& script : mScripts) + { + script.second.mActive = true; + } + + mGlobalScripts.clear(); + } + std::pair ScriptManager::compileAll() { int count = 0; @@ -163,7 +173,7 @@ namespace MWScript ScriptCollection::iterator iter = mScripts.find (name2); if (iter!=mScripts.end()) - return iter->second.second; + return iter->second.mLocals; } { diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 27567a191..50cc7afa8 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -41,7 +41,20 @@ namespace MWScript Interpreter::Interpreter mInterpreter; bool mOpcodesInstalled; - typedef std::pair, Compiler::Locals> CompiledScript; + struct CompiledScript + { + std::vector mByteCode; + Compiler::Locals mLocals; + bool mActive; + + CompiledScript(const std::vector& code, const Compiler::Locals& locals) + { + mByteCode = code; + mLocals = locals; + mActive = true; + } + }; + typedef std::map ScriptCollection; ScriptCollection mScripts; @@ -55,6 +68,8 @@ namespace MWScript Compiler::Context& compilerContext, int warningsMode, const std::vector& scriptBlacklist); + virtual void clear(); + virtual bool run (const std::string& name, Interpreter::Context& interpreterContext); ///< Run the script with the given name (compile first, if not compiled yet) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 9974b8f16..d59704bf1 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -47,7 +47,7 @@ void MWState::StateManager::cleanup (bool force) MWBase::Environment::get().getSoundManager()->clear(); MWBase::Environment::get().getDialogueManager()->clear(); MWBase::Environment::get().getJournal()->clear(); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().clear(); + MWBase::Environment::get().getScriptManager()->clear(); MWBase::Environment::get().getWorld()->clear(); MWBase::Environment::get().getWindowManager()->clear(); MWBase::Environment::get().getInputManager()->clear(); From a83b32074f825e1c194f457ba1db1c9c0bf5cf23 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 14 Jul 2020 22:22:52 +0200 Subject: [PATCH 47/61] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5262fe462..c98dfbe3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Feature #5457: Realistic diagonal movement Feature #5486: Fixes trainers to choose their training skills based on their base skill points Feature #5524: Resume failed script execution after reload + Feature #5525: Search fields tweaks (utf-8) Task #5480: Drop Qt4 support 0.46.0 From 9240833bda3375e57781c015bdb95d83a133038e Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 12 Jul 2020 15:25:14 +0200 Subject: [PATCH 48/61] Init sound by a single object --- apps/openmw/mwsound/sound.hpp | 90 ++++++++++--------------- apps/openmw/mwsound/soundmanagerimp.cpp | 77 +++++++++++++++++---- 2 files changed, 100 insertions(+), 67 deletions(-) diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 7324b6747..9d264e1b6 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -11,85 +11,65 @@ namespace MWSound inline int operator&(int a, PlayMode b) { return a & static_cast(b); } inline int operator&(PlayMode a, PlayMode b) { return static_cast(a) & static_cast(b); } + struct SoundParams + { + osg::Vec3f mPos; + float mVolume = 1; + float mBaseVolume = 1; + float mPitch = 1; + float mMinDistance = 1; + float mMaxDistance = 1000; + int mFlags = 0; + float mFadeOutTime = 0; + }; + class SoundBase { SoundBase& operator=(const SoundBase&) = delete; SoundBase(const SoundBase&) = delete; SoundBase(SoundBase&&) = delete; - osg::Vec3f mPos; - float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */ - float mBaseVolume; - float mPitch; - float mMinDistance; - float mMaxDistance; - int mFlags; - - float mFadeOutTime; + SoundParams mParams; protected: - Sound_Instance mHandle; + Sound_Instance mHandle = nullptr; friend class OpenAL_Output; public: - void setPosition(const osg::Vec3f &pos) { mPos = pos; } - void setVolume(float volume) { mVolume = volume; } - void setBaseVolume(float volume) { mBaseVolume = volume; } - void setFadeout(float duration) { mFadeOutTime = duration; } + void setPosition(const osg::Vec3f &pos) { mParams.mPos = pos; } + void setVolume(float volume) { mParams.mVolume = volume; } + void setBaseVolume(float volume) { mParams.mBaseVolume = volume; } + void setFadeout(float duration) { mParams.mFadeOutTime = duration; } void updateFade(float duration) { - if(mFadeOutTime > 0.0f) + if (mParams.mFadeOutTime > 0.0f) { - float soundDuration = std::min(duration, mFadeOutTime); - mVolume *= (mFadeOutTime-soundDuration) / mFadeOutTime; - mFadeOutTime -= soundDuration; + float soundDuration = std::min(duration, mParams.mFadeOutTime); + mParams.mVolume *= (mParams.mFadeOutTime - soundDuration) / mParams.mFadeOutTime; + mParams.mFadeOutTime -= soundDuration; } } - const osg::Vec3f &getPosition() const { return mPos; } - float getRealVolume() const { return mVolume * mBaseVolume; } - float getPitch() const { return mPitch; } - float getMinDistance() const { return mMinDistance; } - float getMaxDistance() const { return mMaxDistance; } + const osg::Vec3f &getPosition() const { return mParams.mPos; } + float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume; } + float getPitch() const { return mParams.mPitch; } + float getMinDistance() const { return mParams.mMinDistance; } + float getMaxDistance() const { return mParams.mMaxDistance; } MWSound::Type getPlayType() const - { return static_cast(mFlags&MWSound::Type::Mask); } - bool getUseEnv() const { return !(mFlags&MWSound::PlayMode::NoEnv); } - bool getIsLooping() const { return mFlags&MWSound::PlayMode::Loop; } - bool getDistanceCull() const { return mFlags&MWSound::PlayMode::RemoveAtDistance; } - bool getIs3D() const { return mFlags&Play_3D; } - - void init(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - { - mPos = pos; - mVolume = vol; - mBaseVolume = basevol; - mPitch = pitch; - mMinDistance = mindist; - mMaxDistance = maxdist; - mFlags = flags; - mFadeOutTime = 0.0f; - mHandle = nullptr; - } + { return static_cast(mParams.mFlags & MWSound::Type::Mask); } + bool getUseEnv() const { return !(mParams.mFlags & MWSound::PlayMode::NoEnv); } + bool getIsLooping() const { return mParams.mFlags & MWSound::PlayMode::Loop; } + bool getDistanceCull() const { return mParams.mFlags & MWSound::PlayMode::RemoveAtDistance; } + bool getIs3D() const { return mParams.mFlags & Play_3D; } - void init(float vol, float basevol, float pitch, int flags) + void init(const SoundParams& params) { - mPos = osg::Vec3f(0.0f, 0.0f, 0.0f); - mVolume = vol; - mBaseVolume = basevol; - mPitch = pitch; - mMinDistance = 1.0f; - mMaxDistance = 1000.0f; - mFlags = flags; - mFadeOutTime = 0.0f; + mParams = params; mHandle = nullptr; } - SoundBase() - : mPos(0.0f, 0.0f, 0.0f), mVolume(1.0f), mBaseVolume(1.0f), mPitch(1.0f) - , mMinDistance(1.0f), mMaxDistance(1000.0f), mFlags(0), mFadeOutTime(0.0f) - , mHandle(nullptr) - { } + SoundBase() = default; }; class Sound : public SoundBase { diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index a4241fef2..17aa184a7 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -290,13 +290,25 @@ namespace MWSound StreamPtr sound = getStreamRef(); if(playlocal) { - sound->init(1.0f, basevol, 1.0f, PlayMode::NoEnv|Type::Voice|Play_2D); + sound->init([&] { + SoundParams params; + params.mBaseVolume = basevol; + params.mFlags = PlayMode::NoEnv | Type::Voice | Play_2D; + return params; + } ()); played = mOutput->streamSound(decoder, sound.get(), true); } else { - sound->init(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, - PlayMode::Normal|Type::Voice|Play_3D); + sound->init([&] { + SoundParams params; + params.mPos = pos; + params.mBaseVolume = basevol; + params.mMinDistance = minDistance; + params.mMaxDistance = maxDistance; + params.mFlags = PlayMode::Normal | Type::Voice | Play_3D; + return params; + } ()); played = mOutput->streamSound3D(decoder, sound.get(), true); } if(!played) @@ -332,8 +344,12 @@ namespace MWSound decoder->open(filename); mMusic = getStreamRef(); - mMusic->init(1.0f, volumeFromType(Type::Music), 1.0f, - PlayMode::NoEnv|Type::Music|Play_2D); + mMusic->init([&] { + SoundParams params; + params.mBaseVolume = volumeFromType(Type::Music); + params.mFlags = PlayMode::NoEnv | Type::Music | Play_2D; + return params; + } ()); mOutput->streamSound(decoder, mMusic.get()); } @@ -561,7 +577,12 @@ namespace MWSound return nullptr; StreamPtr track = getStreamRef(); - track->init(1.0f, volumeFromType(type), 1.0f, PlayMode::NoEnv|type|Play_2D); + track->init([&] { + SoundParams params; + params.mBaseVolume = volumeFromType(type); + params.mFlags = PlayMode::NoEnv | type | Play_2D; + return params; + } ()); if(!mOutput->streamSound(decoder, track.get())) return nullptr; @@ -598,7 +619,14 @@ namespace MWSound stopSound(sfx, MWWorld::ConstPtr()); SoundPtr sound = getSoundRef(); - sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); + sound->init([&] { + SoundParams params; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mFlags = mode | type | Play_2D; + return params; + } ()); if(!mOutput->playSound(sound.get(), sfx->mHandle, offset)) return nullptr; @@ -635,13 +663,29 @@ namespace MWSound SoundPtr sound = getSoundRef(); if(!(mode&PlayMode::NoPlayerLocal) && ptr == MWMechanics::getPlayer()) { - sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); + sound->init([&] { + SoundParams params; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mFlags = mode | type | Play_2D; + return params; + } ()); played = mOutput->playSound(sound.get(), sfx->mHandle, offset); } else { - sound->init(objpos, volume * sfx->mVolume, volumeFromType(type), pitch, - sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); + sound->init([&] { + SoundParams params; + params.mPos = objpos; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mMinDistance = sfx->mMinDist; + params.mMaxDistance = sfx->mMaxDist; + params.mFlags = mode | type | Play_3D; + return params; + } ()); played = mOutput->playSound3D(sound.get(), sfx->mHandle, offset); } if(!played) @@ -670,8 +714,17 @@ namespace MWSound if(!sfx) return nullptr; SoundPtr sound = getSoundRef(); - sound->init(initialPos, volume * sfx->mVolume, volumeFromType(type), pitch, - sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); + sound->init([&] { + SoundParams params; + params.mPos = initialPos; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mMinDistance = sfx->mMinDist; + params.mMaxDistance = sfx->mMaxDist; + params.mFlags = mode | type | Play_3D; + return params; + } ()); if(!mOutput->playSound3D(sound.get(), sfx->mHandle, offset)) return nullptr; From 68148f5ec70f50b392524a3eccb85776fc360746 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Thu, 16 Jul 2020 22:21:50 +0200 Subject: [PATCH 49/61] 1. Skip smooth camera transition after changing cell; 2. Fix 'zoom out when move' for extremely high speed; --- apps/openmw/mwrender/camera.cpp | 10 ++++++++++ apps/openmw/mwrender/camera.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 2 ++ 3 files changed, 14 insertions(+) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 7531e712b..9e03ff908 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -65,6 +65,7 @@ namespace MWRender mFocalPointCurrentOffset(osg::Vec2d()), mFocalPointTargetOffset(osg::Vec2d()), mFocalPointTransitionSpeedCoef(1.f), + mSkipFocalPointTransition(true), mPreviousTransitionInfluence(0.f), mSmoothedSpeed(0.f), mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")), @@ -219,6 +220,7 @@ namespace MWRender updateFocalPointOffset(duration); float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); + speed /= (1.f + speed / 500.f); float maxDelta = 300.f * duration; mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } @@ -235,6 +237,14 @@ namespace MWRender if (duration <= 0) return; + if (mSkipFocalPointTransition) + { + mSkipFocalPointTransition = false; + mPreviousExtraOffset = osg::Vec2d(); + mPreviousTransitionInfluence = 0.f; + mFocalPointCurrentOffset = mFocalPointTargetOffset; + } + osg::Vec2d oldOffset = mFocalPointCurrentOffset; if (mPreviousTransitionInfluence > 0) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 59fa53047..7fa92b3f9 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -59,6 +59,7 @@ namespace MWRender osg::Vec2d mFocalPointCurrentOffset; osg::Vec2d mFocalPointTargetOffset; float mFocalPointTransitionSpeedCoef; + bool mSkipFocalPointTransition; // This fields are used to make focal point transition smooth if previous transition was not finished. float mPreviousTransitionInfluence; @@ -84,6 +85,7 @@ namespace MWRender void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; } void setFocalPointTargetOffset(osg::Vec2d v); + void skipFocalPointTransition() { mSkipFocalPointTransition = true; } void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 209ab538e..6e459d5e2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -945,6 +945,7 @@ namespace MWWorld removeContainerScripts(getPlayerPtr()); mWorldScene->changeToInteriorCell(cellName, position, adjustPlayerPos, changeEvent); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); + mRendering->getCamera()->skipFocalPointTransition(); } void World::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) @@ -960,6 +961,7 @@ namespace MWWorld removeContainerScripts(getPlayerPtr()); mWorldScene->changeToExteriorCell(position, adjustPlayerPos, changeEvent); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); + mRendering->getCamera()->skipFocalPointTransition(); } void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) From 8ac143c9831af86fe16b523f731858bbbecf25b3 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Thu, 16 Jul 2020 23:32:59 +0200 Subject: [PATCH 50/61] Camera can pull out after clearing obstruction instead of instant snapback. --- apps/openmw/mwrender/camera.cpp | 7 +++++++ apps/openmw/mwrender/camera.hpp | 1 + 2 files changed, 8 insertions(+) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 7531e712b..d074471ad 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -62,6 +62,7 @@ namespace MWRender mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), mCameraDistance(0.f), + mMaxNextCameraDistance(800.f), mFocalPointCurrentOffset(osg::Vec2d()), mFocalPointTargetOffset(osg::Vec2d()), mFocalPointTransitionSpeedCoef(1.f), @@ -221,6 +222,8 @@ namespace MWRender float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); float maxDelta = 300.f * duration; mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); + + mMaxNextCameraDistance = mCameraDistance + duration * (100.f + mBaseCameraDistance); } void Camera::setFocalPointTargetOffset(osg::Vec2d v) @@ -472,7 +475,11 @@ namespace MWRender if (mVanity.enabled || mPreviewMode) mCameraDistance = mPreviewCam.offset; else if (!mFirstPersonView) + { mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection(); + if (mDynamicCameraDistanceEnabled) + mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance); + } mFocalPointAdjustment = osg::Vec3d(); } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 59fa53047..041df7afe 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -54,6 +54,7 @@ namespace MWRender bool mViewModeToggleQueued; float mCameraDistance; + float mMaxNextCameraDistance; osg::Vec3d mFocalPointAdjustment; osg::Vec2d mFocalPointCurrentOffset; From 4d206d2c678a56c98ebfdd812a1216681fe3714a Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 27 Jun 2020 00:58:33 +0200 Subject: [PATCH 51/61] Improved preview mode --- apps/openmw/mwbase/world.hpp | 2 + apps/openmw/mwinput/actionmanager.cpp | 24 ++++++--- apps/openmw/mwinput/inputmanagerimp.cpp | 3 ++ apps/openmw/mwinput/mousemanager.cpp | 7 ++- apps/openmw/mwinput/sensormanager.cpp | 5 +- apps/openmw/mwrender/camera.cpp | 66 ++++++++++++----------- apps/openmw/mwrender/camera.hpp | 5 ++ apps/openmw/mwrender/renderingmanager.cpp | 55 ++++++++++++++++++- apps/openmw/mwrender/renderingmanager.hpp | 8 +++ apps/openmw/mwrender/viewovershoulder.cpp | 13 +++-- apps/openmw/mwworld/worldimp.cpp | 10 ++++ apps/openmw/mwworld/worldimp.hpp | 3 ++ files/settings-default.cfg | 4 ++ 13 files changed, 157 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 627e2f2b7..17e233053 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -422,6 +422,8 @@ namespace MWBase virtual void changeVanityModeScale(float factor) = 0; virtual bool vanityRotateCamera(float * rot) = 0; virtual void setCameraDistance(float dist, bool adjust = false, bool override = true)=0; + virtual void applyDeferredPreviewRotationToPlayer(float dt) = 0; + virtual void disableDeferredPreviewRotation() = 0; virtual void setupPlayer() = 0; virtual void renderPlayer() = 0; diff --git a/apps/openmw/mwinput/actionmanager.cpp b/apps/openmw/mwinput/actionmanager.cpp index f2af3089d..bbfad1fdd 100644 --- a/apps/openmw/mwinput/actionmanager.cpp +++ b/apps/openmw/mwinput/actionmanager.cpp @@ -110,23 +110,31 @@ namespace MWInput if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch")) { + static const bool separatePreviewCamera = Settings::Manager::getBool("separate preview camera", "Camera"); if (mBindingsManager->actionIsActive(A_TogglePOV)) { - if (mPreviewPOVDelay <= 0.5 && - (mPreviewPOVDelay += dt) > 0.5) + if (separatePreviewCamera) { - mPreviewPOVDelay = 1.f; - MWBase::Environment::get().getWorld()->togglePreviewMode(true); + if (mPreviewPOVDelay <= 0.5 && (mPreviewPOVDelay += dt) > 0.5) + { + mPreviewPOVDelay = 1.f; + MWBase::Environment::get().getWorld()->togglePreviewMode(true); + } + } + else + { + if (mPreviewPOVDelay == 0) + MWBase::Environment::get().getWorld()->togglePreviewMode(true); + mPreviewPOVDelay += dt; } } else { //disable preview mode - MWBase::Environment::get().getWorld()->togglePreviewMode(false); - if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.5) - { + if (mPreviewPOVDelay > 0 || separatePreviewCamera) + MWBase::Environment::get().getWorld()->togglePreviewMode(false); + if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= (separatePreviewCamera ? 0.5 : 0.25)) MWBase::Environment::get().getWorld()->togglePOV(); - } mPreviewPOVDelay = 0.f; } } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 79541fbe4..690183c57 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -9,6 +9,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" #include "../mwworld/esmstore.hpp" @@ -101,6 +102,8 @@ namespace MWInput mMouseManager->update(dt); mSensorManager->update(dt); mActionManager->update(dt, controllerMove); + + MWBase::Environment::get().getWorld()->applyDeferredPreviewRotationToPlayer(dt); } void InputManager::setDragDrop(bool dragDrop) diff --git a/apps/openmw/mwinput/mousemanager.cpp b/apps/openmw/mwinput/mousemanager.cpp index 3fef62345..5a0446093 100644 --- a/apps/openmw/mwinput/mousemanager.cpp +++ b/apps/openmw/mwinput/mousemanager.cpp @@ -108,6 +108,8 @@ namespace MWInput player.yaw(x); player.pitch(y); } + else if (!input->getControlSwitch("playerlooking")) + MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation(); if (arg.zrel && input->getControlSwitch("playerviewswitch") && input->getControlSwitch("playercontrols")) //Check to make sure you are allowed to zoomout and there is a change { @@ -212,12 +214,15 @@ namespace MWInput rot[2] = xAxis * dt * 1000.0f * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f; // Only actually turn player when we're not in vanity mode - if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols")) + bool controls = MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"); + if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && controls) { MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); player.yaw(rot[2]); player.pitch(rot[0]); } + else if (!controls) + MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation(); MWBase::Environment::get().getInputManager()->resetIdleTime(); } diff --git a/apps/openmw/mwinput/sensormanager.cpp b/apps/openmw/mwinput/sensormanager.cpp index f3c2c2305..5a3d8847b 100644 --- a/apps/openmw/mwinput/sensormanager.cpp +++ b/apps/openmw/mwinput/sensormanager.cpp @@ -254,12 +254,15 @@ namespace MWInput rot[2] = mGyroXSpeed * dt * mGyroHSensitivity * 4 * (mInvertX ? -1 : 1); // Only actually turn player when we're not in vanity mode - if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking")) + bool playerLooking = MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking"); + if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && playerLooking) { MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); player.yaw(rot[2]); player.pitch(rot[0]); } + else if (!playerLooking) + MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation(); MWBase::Environment::get().getInputManager()->resetIdleTime(); } diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 7c43a522c..787e016ef 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -58,6 +58,7 @@ namespace MWRender mIsNearest(false), mHeight(124.f), mBaseCameraDistance(Settings::Manager::getFloat("third person camera distance", "Camera")), + mUseSeparatePreviewCam(Settings::Manager::getBool("separate preview camera", "Camera")), mVanityToggleQueued(false), mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), @@ -126,7 +127,7 @@ namespace MWRender osg::Vec3d Camera::getFocalPointOffset() const { osg::Vec3d offset(0, 0, 10.f); - if (!mPreviewMode && !mVanity.enabled) + if (!mUseSeparatePreviewCam || (!mPreviewMode && !mVanity.enabled)) { offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw()); offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw()); @@ -322,17 +323,19 @@ namespace MWRender processViewChange(); - float offset = mPreviewCam.offset; - - if (mVanity.enabled) { - setPitch(osg::DegreesToRadians(-30.f)); - mMainCam.offset = mCameraDistance; - } else { - offset = mMainCam.offset; + if (mUseSeparatePreviewCam) + { + float offset = mPreviewCam.offset; + if (mVanity.enabled) + { + setPitch(osg::DegreesToRadians(-30.f)); + mMainCam.offset = mCameraDistance; + } + else + offset = mMainCam.offset; + mCameraDistance = offset; } - mCameraDistance = offset; - return true; } @@ -347,16 +350,18 @@ namespace MWRender mPreviewMode = enable; processViewChange(); - float offset = mCameraDistance; - if (mPreviewMode) { - mMainCam.offset = offset; - offset = mPreviewCam.offset; - } else { - mPreviewCam.offset = offset; - offset = mMainCam.offset; + if (mUseSeparatePreviewCam) + { + float offset = mCameraDistance; + if (mPreviewMode) { + mMainCam.offset = offset; + offset = mPreviewCam.offset; + } else { + mPreviewCam.offset = offset; + offset = mMainCam.offset; + } + mCameraDistance = offset; } - - mCameraDistance = offset; } void Camera::setSneakOffset(float offset) @@ -366,7 +371,7 @@ namespace MWRender float Camera::getYaw() const { - if(mVanity.enabled || mPreviewMode) + if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) return mPreviewCam.yaw; return mMainCam.yaw; } @@ -378,18 +383,16 @@ namespace MWRender } else if (angle < -osg::PI) { angle += osg::PI*2; } - if (mVanity.enabled || mPreviewMode) { + if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) mPreviewCam.yaw = angle; - } else { + else mMainCam.yaw = angle; - } } float Camera::getPitch() const { - if (mVanity.enabled || mPreviewMode) { + if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) return mPreviewCam.pitch; - } return mMainCam.pitch; } @@ -397,7 +400,7 @@ namespace MWRender { const float epsilon = 0.000001f; float limit = osg::PI_2 - epsilon; - if(mPreviewMode) + if(mUseSeparatePreviewCam && mPreviewMode) limit /= 2; if(angle > limit) @@ -405,11 +408,10 @@ namespace MWRender else if(angle < -limit) angle = -limit; - if (mVanity.enabled || mPreviewMode) { + if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) mPreviewCam.pitch = angle; - } else { + else mMainCam.pitch = angle; - } } float Camera::getCameraDistance() const @@ -428,7 +430,7 @@ namespace MWRender if (adjust) { - if (mVanity.enabled || mPreviewMode) + if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) dist += mCameraDistance; else dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance); @@ -443,7 +445,7 @@ namespace MWRender mIsNearest = true; } - if (mVanity.enabled || mPreviewMode) + if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) mPreviewCam.offset = dist; else if (!mFirstPersonView) { @@ -482,7 +484,7 @@ namespace MWRender void Camera::setCameraDistance() { - if (mVanity.enabled || mPreviewMode) + if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) mCameraDistance = mPreviewCam.offset; else if (!mFirstPersonView) { diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index d1acb814c..fb83cf4d3 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -48,6 +48,7 @@ namespace MWRender float mHeight, mBaseCameraDistance; CamData mMainCam, mPreviewCam; + bool mUseSeparatePreviewCam; bool mVanityToggleQueued; bool mVanityToggleQueuedValue; @@ -115,6 +116,9 @@ namespace MWRender bool toggleVanityMode(bool enable); void allowVanityMode(bool allow); + void useSeparatePreviewCamera(bool v) { mUseSeparatePreviewCam = v; } + bool isUsingSeparatePreviewCamera() const { return mUseSeparatePreviewCam; } + /// @note this may be ignored if an important animation is currently playing void togglePreviewMode(bool enable); @@ -152,6 +156,7 @@ namespace MWRender void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const; bool isVanityOrPreviewModeEnabled() const; + bool isVanityModeEnabled() const { return mVanity.enabled; } bool isNearest() const; }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index d91da5a08..46b573b2e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -58,6 +58,7 @@ #include "../mwgui/loadingscreen.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwmechanics/movement.hpp" #include "sky.hpp" #include "effectmanager.hpp" @@ -203,6 +204,8 @@ namespace MWRender , mNightEyeFactor(0.f) , mFieldOfViewOverridden(false) , mFieldOfViewOverride(0.f) + , mDeferredRotation(osg::Vec3f()) + , mDeferredRotationDisabled(false) { resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem); resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); @@ -653,7 +656,8 @@ namespace MWRender if(ptr == mCamera->getTrackingPtr() && !mCamera->isVanityOrPreviewModeEnabled()) { - mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0], -ptr.getRefData().getPosition().rot[2], false); + mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0] - mDeferredRotation.x(), + -ptr.getRefData().getPosition().rot[2] - mDeferredRotation.z(), false); } ptr.getRefData().getBaseNode()->setAttitude(rot); @@ -1324,6 +1328,50 @@ namespace MWRender return true; } + void RenderingManager::applyDeferredPreviewRotationToPlayer(float dt) + { + MWWorld::Ptr ptr = mCamera->getTrackingPtr(); + if (mCamera->isVanityOrPreviewModeEnabled() || ptr.isEmpty()) + return; + + osg::Vec3f rot = mDeferredRotation; + float delta = rot.normalize(); + delta = std::min(delta, (delta + 1.f) * 3 * dt); + rot *= delta; + mDeferredRotation -= rot; + + auto& movement = ptr.getClass().getMovementSettings(ptr); + movement.mRotation[0] += rot.x(); + movement.mRotation[1] += rot.y(); + movement.mRotation[2] += rot.z(); + } + + void RenderingManager::calculateDeferredRotation() + { + MWWorld::Ptr ptr = mCamera->getTrackingPtr(); + if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isUsingSeparatePreviewCamera() || ptr.isEmpty()) + return; + if (mCamera->isFirstPerson() || mDeferredRotationDisabled) + { + mDeferredRotationDisabled = false; + mDeferredRotation = osg::Vec3f(); + mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0], + -ptr.getRefData().getPosition().rot[2], false); + return; + } + + mDeferredRotation.x() = -ptr.getRefData().getPosition().rot[0] - mCamera->getPitch(); + mDeferredRotation.z() = -ptr.getRefData().getPosition().rot[2] - mCamera->getYaw(); + if (mDeferredRotation.x() > osg::PI) + mDeferredRotation.x() -= 2 * osg::PI; + if (mDeferredRotation.x() < -osg::PI) + mDeferredRotation.x() += 2 * osg::PI; + if (mDeferredRotation.z() > osg::PI) + mDeferredRotation.z() -= 2 * osg::PI; + if (mDeferredRotation.z() < -osg::PI) + mDeferredRotation.z() += 2 * osg::PI; + } + void RenderingManager::setCameraDistance(float dist, bool adjust, bool override) { if(!mCamera->isVanityOrPreviewModeEnabled() && !mCamera->isFirstPerson()) @@ -1373,11 +1421,14 @@ namespace MWRender void RenderingManager::togglePreviewMode(bool enable) { mCamera->togglePreviewMode(enable); + calculateDeferredRotation(); } bool RenderingManager::toggleVanityMode(bool enable) { - return mCamera->toggleVanityMode(enable); + bool res = mCamera->toggleVanityMode(enable); + calculateDeferredRotation(); + return res; } void RenderingManager::allowVanityMode(bool allow) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index d6a0f89c3..000826caa 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -221,6 +221,9 @@ namespace MWRender void allowVanityMode(bool allow); void changeVanityModeScale(float factor); + void applyDeferredPreviewRotationToPlayer(float dt); + void disableDeferredPreviewRotation() { mDeferredRotationDisabled = true; } + /// temporarily override the field of view with given value. void overrideFieldOfView(float val); /// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file. @@ -310,6 +313,11 @@ namespace MWRender float mFieldOfView; float mFirstPersonFieldOfView; + // Used to rotate player to the direction of view after exiting preview or vanity mode. + osg::Vec3f mDeferredRotation; + bool mDeferredRotationDisabled; + void calculateDeferredRotation(); + void operator = (const RenderingManager&); RenderingManager(const RenderingManager&); }; diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp index 5d7ec7117..12f47b5f7 100644 --- a/apps/openmw/mwrender/viewovershoulder.cpp +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -33,12 +33,13 @@ namespace MWRender void ViewOverShoulderController::update() { - if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson()) + if (mCamera->isFirstPerson()) return; Mode oldMode = mMode; auto ptr = mCamera->getTrackingPtr(); - if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing) + bool combat = ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing; + if (combat && !mCamera->isVanityOrPreviewModeEnabled()) mMode = Mode::Combat; else if (MWBase::Environment::get().getWorld()->isSwimming(ptr)) mMode = Mode::Swimming; @@ -46,9 +47,13 @@ namespace MWRender mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder)) trySwitchShoulder(); - if (oldMode == mMode) return; - if (oldMode == Mode::Combat || mMode == Mode::Combat) + if (oldMode == mMode) + return; + + if (mCamera->isVanityOrPreviewModeEnabled()) + mCamera->setFocalPointTransitionSpeed(mCamera->isVanityModeEnabled() ? 0.2 : 1); + else if (oldMode == Mode::Combat || mMode == Mode::Combat) mCamera->setFocalPointTransitionSpeed(5.f); else mCamera->setFocalPointTransitionSpeed(1.f); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6e459d5e2..423c55732 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2405,6 +2405,16 @@ namespace MWWorld return mRendering->toggleVanityMode(enable); } + void World::disableDeferredPreviewRotation() + { + mRendering->disableDeferredPreviewRotation(); + } + + void World::applyDeferredPreviewRotationToPlayer(float dt) + { + mRendering->applyDeferredPreviewRotationToPlayer(dt); + } + void World::allowVanityMode(bool allow) { mRendering->allowVanityMode(allow); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index aeb6bbae4..c08206600 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -536,6 +536,9 @@ namespace MWWorld bool vanityRotateCamera(float * rot) override; void setCameraDistance(float dist, bool adjust = false, bool override = true) override; + void applyDeferredPreviewRotationToPlayer(float dt) override; + void disableDeferredPreviewRotation() override; + void setupPlayer() override; void renderPlayer() override; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 35be128a8..e4ef28f02 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -33,6 +33,10 @@ field of view = 60.0 # Best to leave this at the default since vanilla assets are not complete enough to adapt to high FoV's. Too low FoV would clip the hands off screen. first person field of view = 60.0 +# true - standard bahaviour of preview and vanity camera +# false - smooth preview mode +separate preview camera = true + # Distance from the camera to the character in third person mode. third person camera distance = 192 From 8ac7ffc32bef80cfa424f3d4f94f480ef647ee1a Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Fri, 17 Jul 2020 01:11:09 +0200 Subject: [PATCH 52/61] Remove 'separate preview camera' and make the new behavior the default one. Also minor refactoring in camera.cpp --- apps/openmw/mwinput/actionmanager.cpp | 22 +--- apps/openmw/mwrender/camera.cpp | 146 +++------------------- apps/openmw/mwrender/camera.hpp | 20 +-- apps/openmw/mwrender/renderingmanager.cpp | 2 +- files/settings-default.cfg | 4 - 5 files changed, 32 insertions(+), 162 deletions(-) diff --git a/apps/openmw/mwinput/actionmanager.cpp b/apps/openmw/mwinput/actionmanager.cpp index bbfad1fdd..ddde7a11e 100644 --- a/apps/openmw/mwinput/actionmanager.cpp +++ b/apps/openmw/mwinput/actionmanager.cpp @@ -110,30 +110,18 @@ namespace MWInput if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch")) { - static const bool separatePreviewCamera = Settings::Manager::getBool("separate preview camera", "Camera"); if (mBindingsManager->actionIsActive(A_TogglePOV)) { - if (separatePreviewCamera) - { - if (mPreviewPOVDelay <= 0.5 && (mPreviewPOVDelay += dt) > 0.5) - { - mPreviewPOVDelay = 1.f; - MWBase::Environment::get().getWorld()->togglePreviewMode(true); - } - } - else - { - if (mPreviewPOVDelay == 0) - MWBase::Environment::get().getWorld()->togglePreviewMode(true); - mPreviewPOVDelay += dt; - } + if (mPreviewPOVDelay == 0) + MWBase::Environment::get().getWorld()->togglePreviewMode(true); + mPreviewPOVDelay += dt; } else { //disable preview mode - if (mPreviewPOVDelay > 0 || separatePreviewCamera) + if (mPreviewPOVDelay > 0) MWBase::Environment::get().getWorld()->togglePreviewMode(false); - if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= (separatePreviewCamera ? 0.5 : 0.25)) + if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.25) MWBase::Environment::get().getWorld()->togglePOV(); mPreviewPOVDelay = 0.f; } diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 787e016ef..a674643d8 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -58,7 +58,6 @@ namespace MWRender mIsNearest(false), mHeight(124.f), mBaseCameraDistance(Settings::Manager::getFloat("third person camera distance", "Camera")), - mUseSeparatePreviewCam(Settings::Manager::getBool("separate preview camera", "Camera")), mVanityToggleQueued(false), mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), @@ -77,13 +76,6 @@ namespace MWRender mVanity.enabled = false; mVanity.allowed = true; - mPreviewCam.pitch = 0.f; - mPreviewCam.yaw = 0.f; - mPreviewCam.offset = 400.f; - mMainCam.pitch = 0.f; - mMainCam.yaw = 0.f; - mMainCam.offset = 400.f; - mCameraDistance = mBaseCameraDistance; mUpdateCallback = new UpdateRenderCameraCallback(this); @@ -95,17 +87,11 @@ namespace MWRender mCamera->removeUpdateCallback(mUpdateCallback); } - MWWorld::Ptr Camera::getTrackingPtr() const - { - return mTrackingPtr; - } - osg::Vec3d Camera::getFocalPoint() const { - const osg::Node* trackNode = mTrackingNode; - if (!trackNode) + if (!mTrackingNode) return osg::Vec3d(); - osg::NodePathList nodepaths = trackNode->getParentalNodePaths(); + osg::NodePathList nodepaths = mTrackingNode->getParentalNodePaths(); if (nodepaths.empty()) return osg::Vec3d(); osg::Matrix worldMat = osg::computeLocalToWorld(nodepaths[0]); @@ -127,12 +113,9 @@ namespace MWRender osg::Vec3d Camera::getFocalPointOffset() const { osg::Vec3d offset(0, 0, 10.f); - if (!mUseSeparatePreviewCam || (!mPreviewMode && !mVanity.enabled)) - { - offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw()); - offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw()); - offset.z() += mFocalPointCurrentOffset.y(); - } + offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw()); + offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw()); + offset.z() += mFocalPointCurrentOffset.y(); return offset; } @@ -199,7 +182,6 @@ namespace MWRender } if (mViewModeToggleQueued) { - togglePreviewMode(false); toggleViewMode(); mViewModeToggleQueued = false; @@ -295,7 +277,7 @@ namespace MWRender mFirstPersonView = !mFirstPersonView; processViewChange(); } - + void Camera::allowVanityMode(bool allow) { if (!allow && mVanity.enabled) @@ -322,20 +304,6 @@ namespace MWRender mVanity.enabled = enable; processViewChange(); - - if (mUseSeparatePreviewCam) - { - float offset = mPreviewCam.offset; - if (mVanity.enabled) - { - setPitch(osg::DegreesToRadians(-30.f)); - mMainCam.offset = mCameraDistance; - } - else - offset = mMainCam.offset; - mCameraDistance = offset; - } - return true; } @@ -349,19 +317,6 @@ namespace MWRender mPreviewMode = enable; processViewChange(); - - if (mUseSeparatePreviewCam) - { - float offset = mCameraDistance; - if (mPreviewMode) { - mMainCam.offset = offset; - offset = mPreviewCam.offset; - } else { - mPreviewCam.offset = offset; - offset = mMainCam.offset; - } - mCameraDistance = offset; - } } void Camera::setSneakOffset(float offset) @@ -369,13 +324,6 @@ namespace MWRender mAnimation->setFirstPersonOffset(osg::Vec3f(0,0,-offset)); } - float Camera::getYaw() const - { - if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) - return mPreviewCam.yaw; - return mMainCam.yaw; - } - void Camera::setYaw(float angle) { if (angle > osg::PI) { @@ -383,35 +331,14 @@ namespace MWRender } else if (angle < -osg::PI) { angle += osg::PI*2; } - if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) - mPreviewCam.yaw = angle; - else - mMainCam.yaw = angle; - } - - float Camera::getPitch() const - { - if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) - return mPreviewCam.pitch; - return mMainCam.pitch; + mYaw = angle; } void Camera::setPitch(float angle) { const float epsilon = 0.000001f; float limit = osg::PI_2 - epsilon; - if(mUseSeparatePreviewCam && mPreviewMode) - limit /= 2; - - if(angle > limit) - angle = limit; - else if(angle < -limit) - angle = -limit; - - if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) - mPreviewCam.pitch = angle; - else - mMainCam.pitch = angle; + mPitch = osg::clampBetween(angle, -limit, limit); } float Camera::getCameraDistance() const @@ -426,28 +353,13 @@ namespace MWRender if(mFirstPersonView && !mPreviewMode && !mVanity.enabled) return; - mIsNearest = false; - if (adjust) - { - if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) - dist += mCameraDistance; - else - dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance); - } - + dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance); - if (dist >= mFurthest) - dist = mFurthest; - else if (dist <= mNearest) - { - dist = mNearest; - mIsNearest = true; - } + mIsNearest = dist <= mNearest; + dist = osg::clampBetween(dist, mNearest, mFurthest); - if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) - mPreviewCam.offset = dist; - else if (!mFirstPersonView) + if (!mFirstPersonView) { mBaseCameraDistance = dist; Settings::Manager::setFloat("third person camera distance", "Camera", dist); @@ -459,14 +371,9 @@ namespace MWRender { if(mFirstPersonView && !mPreviewMode && !mVanity.enabled) return; - - if (adjust) dist += mCameraDistance; - - if (dist >= mFurthest) - dist = mFurthest; - else if (dist < 10.f) - dist = 10.f; - mCameraDistance = dist; + if (adjust) + dist += mCameraDistance; + mCameraDistance = osg::clampBetween(dist, 10.f, mFurthest); } float Camera::getCameraDistanceCorrection() const @@ -484,21 +391,17 @@ namespace MWRender void Camera::setCameraDistance() { - if (mUseSeparatePreviewCam && (mVanity.enabled || mPreviewMode)) - mCameraDistance = mPreviewCam.offset; - else if (!mFirstPersonView) - { - mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection(); - if (mDynamicCameraDistanceEnabled) - mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance); - } mFocalPointAdjustment = osg::Vec3d(); + if (mFirstPersonView) + return; + mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection(); + if (mDynamicCameraDistanceEnabled) + mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance); } void Camera::setAnimation(NpcAnimation *anim) { mAnimation = anim; - processViewChange(); } @@ -525,13 +428,4 @@ namespace MWRender rotateCamera(getPitch(), getYaw(), false); } - bool Camera::isVanityOrPreviewModeEnabled() const - { - return mPreviewMode || mVanity.enabled; - } - - bool Camera::isNearest() const - { - return mIsNearest; - } } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index fb83cf4d3..1701be375 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -24,10 +24,6 @@ namespace MWRender class Camera { private: - struct CamData { - float pitch, yaw, offset; - }; - MWWorld::Ptr mTrackingPtr; osg::ref_ptr mTrackingNode; float mHeightScale; @@ -47,8 +43,7 @@ namespace MWRender } mVanity; float mHeight, mBaseCameraDistance; - CamData mMainCam, mPreviewCam; - bool mUseSeparatePreviewCam; + float mPitch, mYaw; bool mVanityToggleQueued; bool mVanityToggleQueuedValue; @@ -83,7 +78,7 @@ namespace MWRender Camera(osg::Camera* camera); ~Camera(); - MWWorld::Ptr getTrackingPtr() const; + MWWorld::Ptr getTrackingPtr() const { return mTrackingPtr; } void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; } void setFocalPointTargetOffset(osg::Vec2d v); @@ -101,10 +96,10 @@ namespace MWRender /// \param rot Rotation angles in radians void rotateCamera(float pitch, float yaw, bool adjust); - float getYaw() const; + float getYaw() const { return mYaw; } void setYaw(float angle); - float getPitch() const; + float getPitch() const { return mPitch; } void setPitch(float angle); /// Attach camera to object @@ -116,9 +111,6 @@ namespace MWRender bool toggleVanityMode(bool enable); void allowVanityMode(bool allow); - void useSeparatePreviewCamera(bool v) { mUseSeparatePreviewCam = v; } - bool isUsingSeparatePreviewCamera() const { return mUseSeparatePreviewCam; } - /// @note this may be ignored if an important animation is currently playing void togglePreviewMode(bool enable); @@ -155,10 +147,10 @@ namespace MWRender /// Stores focal and camera world positions in passed arguments void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const; - bool isVanityOrPreviewModeEnabled() const; + bool isVanityOrPreviewModeEnabled() const { return mPreviewMode || mVanity.enabled; } bool isVanityModeEnabled() const { return mVanity.enabled; } - bool isNearest() const; + bool isNearest() const { return mIsNearest; } }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 46b573b2e..e4150eebc 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1349,7 +1349,7 @@ namespace MWRender void RenderingManager::calculateDeferredRotation() { MWWorld::Ptr ptr = mCamera->getTrackingPtr(); - if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isUsingSeparatePreviewCamera() || ptr.isEmpty()) + if (mCamera->isVanityOrPreviewModeEnabled() || ptr.isEmpty()) return; if (mCamera->isFirstPerson() || mDeferredRotationDisabled) { diff --git a/files/settings-default.cfg b/files/settings-default.cfg index e4ef28f02..35be128a8 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -33,10 +33,6 @@ field of view = 60.0 # Best to leave this at the default since vanilla assets are not complete enough to adapt to high FoV's. Too low FoV would clip the hands off screen. first person field of view = 60.0 -# true - standard bahaviour of preview and vanity camera -# false - smooth preview mode -separate preview camera = true - # Distance from the camera to the character in third person mode. third person camera distance = 192 From 63cab4052d370bf099d43494fc3136f6b2b5c9ab Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 18 Jul 2020 10:27:13 +0200 Subject: [PATCH 53/61] Refactoring in mwrender::Camera. enum for normal/preview/vanity mode. --- apps/openmw/mwrender/camera.cpp | 49 ++++++++--------------- apps/openmw/mwrender/camera.hpp | 23 +++++------ apps/openmw/mwrender/viewovershoulder.cpp | 12 +++--- 3 files changed, 34 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index a674643d8..16deed878 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -52,7 +52,8 @@ namespace MWRender mCamera(camera), mAnimation(nullptr), mFirstPersonView(true), - mPreviewMode(false), + mMode(Mode::Normal), + mVanityAllowed(true), mNearest(30.f), mFurthest(800.f), mIsNearest(false), @@ -73,9 +74,6 @@ namespace MWRender mDynamicCameraDistanceEnabled(false), mShowCrosshairInThirdPersonMode(false) { - mVanity.enabled = false; - mVanity.allowed = true; - mCameraDistance = mBaseCameraDistance; mUpdateCallback = new UpdateRenderCameraCallback(this); @@ -133,9 +131,6 @@ namespace MWRender void Camera::updateCamera(osg::Camera *cam) { - if (mTrackingPtr.isEmpty()) - return; - osg::Vec3d focal, position; getPosition(focal, position); @@ -165,11 +160,6 @@ namespace MWRender setPitch(pitch); } - void Camera::attachTo(const MWWorld::Ptr &ptr) - { - mTrackingPtr = ptr; - } - void Camera::update(float duration, bool paused) { if (mAnimation->upperBodyReady()) @@ -193,13 +183,11 @@ namespace MWRender // only show the crosshair in game mode MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager(); - wm->showCrosshair(!wm->isGuiMode() && !mVanity.enabled && !mPreviewMode + wm->showCrosshair(!wm->isGuiMode() && mMode != Mode::Preview && mMode != Mode::Vanity && (mFirstPersonView || mShowCrosshairInThirdPersonMode)); - if(mVanity.enabled) - { + if(mMode == Mode::Vanity) rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true); - } updateFocalPointOffset(duration); @@ -280,9 +268,9 @@ namespace MWRender void Camera::allowVanityMode(bool allow) { - if (!allow && mVanity.enabled) + if (!allow && mMode == Mode::Vanity) toggleVanityMode(false); - mVanity.allowed = allow; + mVanityAllowed = allow; } bool Camera::toggleVanityMode(bool enable) @@ -296,12 +284,12 @@ namespace MWRender return false; } - if(!mVanity.allowed && enable) + if (!mVanityAllowed && enable) return false; - if(mVanity.enabled == enable) + if ((mMode == Mode::Vanity) == enable) return true; - mVanity.enabled = enable; + mMode = enable ? Mode::Vanity : Mode::Normal; processViewChange(); return true; @@ -312,10 +300,10 @@ namespace MWRender if (mFirstPersonView && !mAnimation->upperBodyReady()) return; - if(mPreviewMode == enable) + if((mMode == Mode::Preview) == enable) return; - mPreviewMode = enable; + mMode = enable ? Mode::Preview : Mode::Normal; processViewChange(); } @@ -350,26 +338,21 @@ namespace MWRender void Camera::updateBaseCameraDistance(float dist, bool adjust) { - if(mFirstPersonView && !mPreviewMode && !mVanity.enabled) + if (isFirstPerson()) return; if (adjust) dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance); mIsNearest = dist <= mNearest; - dist = osg::clampBetween(dist, mNearest, mFurthest); - - if (!mFirstPersonView) - { - mBaseCameraDistance = dist; - Settings::Manager::setFloat("third person camera distance", "Camera", dist); - } + mBaseCameraDistance = osg::clampBetween(dist, mNearest, mFurthest); + Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance); setCameraDistance(); } void Camera::setCameraDistance(float dist, bool adjust) { - if(mFirstPersonView && !mPreviewMode && !mVanity.enabled) + if (isFirstPerson()) return; if (adjust) dist += mCameraDistance; @@ -392,7 +375,7 @@ namespace MWRender void Camera::setCameraDistance() { mFocalPointAdjustment = osg::Vec3d(); - if (mFirstPersonView) + if (isFirstPerson()) return; mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection(); if (mDynamicCameraDistanceEnabled) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 1701be375..4c5523974 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -23,6 +23,9 @@ namespace MWRender /// \brief Camera control class Camera { + public: + enum class Mode { Normal, Vanity, Preview }; + private: MWWorld::Ptr mTrackingPtr; osg::ref_ptr mTrackingNode; @@ -33,15 +36,13 @@ namespace MWRender NpcAnimation *mAnimation; bool mFirstPersonView; - bool mPreviewMode; + Mode mMode; + bool mVanityAllowed; + float mNearest; float mFurthest; bool mIsNearest; - struct { - bool enabled, allowed; - } mVanity; - float mHeight, mBaseCameraDistance; float mPitch, mYaw; @@ -78,6 +79,8 @@ namespace MWRender Camera(osg::Camera* camera); ~Camera(); + /// Attach camera to object + void attachTo(const MWWorld::Ptr &ptr) { mTrackingPtr = ptr; } MWWorld::Ptr getTrackingPtr() const { return mTrackingPtr; } void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; } @@ -102,9 +105,6 @@ namespace MWRender float getPitch() const { return mPitch; } void setPitch(float angle); - /// Attach camera to object - void attachTo(const MWWorld::Ptr &); - /// @param Force view mode switch, even if currently not allowed by the animation. void toggleViewMode(bool force=false); @@ -117,8 +117,7 @@ namespace MWRender /// \brief Lowers the camera for sneak. void setSneakOffset(float offset); - bool isFirstPerson() const - { return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); } + bool isFirstPerson() const { return mFirstPersonView && mMode == Mode::Normal; } void processViewChange(); @@ -147,8 +146,8 @@ namespace MWRender /// Stores focal and camera world positions in passed arguments void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const; - bool isVanityOrPreviewModeEnabled() const { return mPreviewMode || mVanity.enabled; } - bool isVanityModeEnabled() const { return mVanity.enabled; } + bool isVanityOrPreviewModeEnabled() const { return mMode != Mode::Normal; } + Mode getMode() const { return mMode; } bool isNearest() const { return mIsNearest; } }; diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp index 12f47b5f7..ceb9407a1 100644 --- a/apps/openmw/mwrender/viewovershoulder.cpp +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -51,12 +51,14 @@ namespace MWRender if (oldMode == mMode) return; - if (mCamera->isVanityOrPreviewModeEnabled()) - mCamera->setFocalPointTransitionSpeed(mCamera->isVanityModeEnabled() ? 0.2 : 1); - else if (oldMode == Mode::Combat || mMode == Mode::Combat) + if (mCamera->getMode() == Camera::Mode::Vanity) + // Player doesn't touch controls for a long time. Transition should be very slow. + mCamera->setFocalPointTransitionSpeed(0.2f); + else if ((oldMode == Mode::Combat || mMode == Mode::Combat) && mCamera->getMode() == Camera::Mode::Normal) + // Transition to/from combat mode and we are not it preview mode. Should be fast. mCamera->setFocalPointTransitionSpeed(5.f); else - mCamera->setFocalPointTransitionSpeed(1.f); + mCamera->setFocalPointTransitionSpeed(1.f); // Default transition speed. switch (mMode) { @@ -98,4 +100,4 @@ namespace MWRender mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; } -} \ No newline at end of file +} From 9f850b6ffcedaa946251a5551cca16992e7731f3 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 18 Jul 2020 11:48:46 +0200 Subject: [PATCH 54/61] Move deferred rotation logic from renderingmanager.cpp to camera.cpp --- apps/openmw/mwrender/camera.cpp | 69 ++++++++++++++++++++++- apps/openmw/mwrender/camera.hpp | 9 +++ apps/openmw/mwrender/renderingmanager.cpp | 55 +----------------- apps/openmw/mwrender/renderingmanager.hpp | 8 --- apps/openmw/mwworld/worldimp.cpp | 4 +- 5 files changed, 81 insertions(+), 64 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 16deed878..877cb7570 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -13,6 +13,7 @@ #include "../mwworld/refdata.hpp" #include "../mwmechanics/drawstate.hpp" +#include "../mwmechanics/movement.hpp" #include "../mwmechanics/npcstats.hpp" #include "npcanimation.hpp" @@ -72,7 +73,9 @@ namespace MWRender mSmoothedSpeed(0.f), mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")), mDynamicCameraDistanceEnabled(false), - mShowCrosshairInThirdPersonMode(false) + mShowCrosshairInThirdPersonMode(false), + mDeferredRotation(osg::Vec3f()), + mDeferredRotationDisabled(false) { mCameraDistance = mBaseCameraDistance; @@ -269,7 +272,10 @@ namespace MWRender void Camera::allowVanityMode(bool allow) { if (!allow && mMode == Mode::Vanity) + { + disableDeferredPreviewRotation(); toggleVanityMode(false); + } mVanityAllowed = allow; } @@ -290,6 +296,8 @@ namespace MWRender if ((mMode == Mode::Vanity) == enable) return true; mMode = enable ? Mode::Vanity : Mode::Normal; + if (!enable) + calculateDeferredRotation(); processViewChange(); return true; @@ -304,6 +312,8 @@ namespace MWRender return; mMode = enable ? Mode::Preview : Mode::Normal; + if (!enable) + calculateDeferredRotation(); processViewChange(); } @@ -411,4 +421,61 @@ namespace MWRender rotateCamera(getPitch(), getYaw(), false); } + void Camera::applyDeferredPreviewRotationToPlayer(float dt) + { + if (isVanityOrPreviewModeEnabled() || mTrackingPtr.isEmpty()) + return; + + osg::Vec3f rot = mDeferredRotation; + float delta = rot.normalize(); + delta = std::min(delta, (delta + 1.f) * 3 * dt); + rot *= delta; + mDeferredRotation -= rot; + + auto& movement = mTrackingPtr.getClass().getMovementSettings(mTrackingPtr); + movement.mRotation[0] += rot.x(); + movement.mRotation[1] += rot.y(); + movement.mRotation[2] += rot.z(); + if (std::abs(mDeferredRotation.z()) > 0.0001) + { + float s = std::sin(mDeferredRotation.z()); + float c = std::cos(mDeferredRotation.z()); + float x = movement.mPosition[0]; + float y = movement.mPosition[1]; + movement.mPosition[0] = x * c + y * s; + movement.mPosition[1] = x * -s + y * c; + } + } + + void Camera::rotateCameraToTrackingPtr() + { + setPitch(-mTrackingPtr.getRefData().getPosition().rot[0] - mDeferredRotation.x()); + setYaw(-mTrackingPtr.getRefData().getPosition().rot[2] - mDeferredRotation.z()); + } + + void Camera::calculateDeferredRotation() + { + MWWorld::Ptr ptr = mTrackingPtr; + if (isVanityOrPreviewModeEnabled() || ptr.isEmpty()) + return; + if (isFirstPerson() || mDeferredRotationDisabled) + { + mDeferredRotationDisabled = false; + mDeferredRotation = osg::Vec3f(); + rotateCameraToTrackingPtr(); + return; + } + + mDeferredRotation.x() = -ptr.getRefData().getPosition().rot[0] - mPitch; + mDeferredRotation.z() = -ptr.getRefData().getPosition().rot[2] - mYaw; + if (mDeferredRotation.x() > osg::PI) + mDeferredRotation.x() -= 2 * osg::PI; + if (mDeferredRotation.x() < -osg::PI) + mDeferredRotation.x() += 2 * osg::PI; + if (mDeferredRotation.z() > osg::PI) + mDeferredRotation.z() -= 2 * osg::PI; + if (mDeferredRotation.z() < -osg::PI) + mDeferredRotation.z() += 2 * osg::PI; + } + } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 4c5523974..c5f7ec2b2 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -75,6 +75,11 @@ namespace MWRender osg::ref_ptr mUpdateCallback; + // Used to rotate player to the direction of view after exiting preview or vanity mode. + osg::Vec3f mDeferredRotation; + bool mDeferredRotationDisabled; + void calculateDeferredRotation(); + public: Camera(osg::Camera* camera); ~Camera(); @@ -98,6 +103,7 @@ namespace MWRender /// Set where the camera is looking at. Uses Morrowind (euler) angles /// \param rot Rotation angles in radians void rotateCamera(float pitch, float yaw, bool adjust); + void rotateCameraToTrackingPtr(); float getYaw() const { return mYaw; } void setYaw(float angle); @@ -114,6 +120,9 @@ namespace MWRender /// @note this may be ignored if an important animation is currently playing void togglePreviewMode(bool enable); + void applyDeferredPreviewRotationToPlayer(float dt); + void disableDeferredPreviewRotation() { mDeferredRotationDisabled = true; } + /// \brief Lowers the camera for sneak. void setSneakOffset(float offset); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e4150eebc..d9739e844 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -58,7 +58,6 @@ #include "../mwgui/loadingscreen.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwmechanics/movement.hpp" #include "sky.hpp" #include "effectmanager.hpp" @@ -204,8 +203,6 @@ namespace MWRender , mNightEyeFactor(0.f) , mFieldOfViewOverridden(false) , mFieldOfViewOverride(0.f) - , mDeferredRotation(osg::Vec3f()) - , mDeferredRotationDisabled(false) { resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem); resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); @@ -656,8 +653,7 @@ namespace MWRender if(ptr == mCamera->getTrackingPtr() && !mCamera->isVanityOrPreviewModeEnabled()) { - mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0] - mDeferredRotation.x(), - -ptr.getRefData().getPosition().rot[2] - mDeferredRotation.z(), false); + mCamera->rotateCameraToTrackingPtr(); } ptr.getRefData().getBaseNode()->setAttitude(rot); @@ -1328,50 +1324,6 @@ namespace MWRender return true; } - void RenderingManager::applyDeferredPreviewRotationToPlayer(float dt) - { - MWWorld::Ptr ptr = mCamera->getTrackingPtr(); - if (mCamera->isVanityOrPreviewModeEnabled() || ptr.isEmpty()) - return; - - osg::Vec3f rot = mDeferredRotation; - float delta = rot.normalize(); - delta = std::min(delta, (delta + 1.f) * 3 * dt); - rot *= delta; - mDeferredRotation -= rot; - - auto& movement = ptr.getClass().getMovementSettings(ptr); - movement.mRotation[0] += rot.x(); - movement.mRotation[1] += rot.y(); - movement.mRotation[2] += rot.z(); - } - - void RenderingManager::calculateDeferredRotation() - { - MWWorld::Ptr ptr = mCamera->getTrackingPtr(); - if (mCamera->isVanityOrPreviewModeEnabled() || ptr.isEmpty()) - return; - if (mCamera->isFirstPerson() || mDeferredRotationDisabled) - { - mDeferredRotationDisabled = false; - mDeferredRotation = osg::Vec3f(); - mCamera->rotateCamera(-ptr.getRefData().getPosition().rot[0], - -ptr.getRefData().getPosition().rot[2], false); - return; - } - - mDeferredRotation.x() = -ptr.getRefData().getPosition().rot[0] - mCamera->getPitch(); - mDeferredRotation.z() = -ptr.getRefData().getPosition().rot[2] - mCamera->getYaw(); - if (mDeferredRotation.x() > osg::PI) - mDeferredRotation.x() -= 2 * osg::PI; - if (mDeferredRotation.x() < -osg::PI) - mDeferredRotation.x() += 2 * osg::PI; - if (mDeferredRotation.z() > osg::PI) - mDeferredRotation.z() -= 2 * osg::PI; - if (mDeferredRotation.z() < -osg::PI) - mDeferredRotation.z() += 2 * osg::PI; - } - void RenderingManager::setCameraDistance(float dist, bool adjust, bool override) { if(!mCamera->isVanityOrPreviewModeEnabled() && !mCamera->isFirstPerson()) @@ -1421,14 +1373,11 @@ namespace MWRender void RenderingManager::togglePreviewMode(bool enable) { mCamera->togglePreviewMode(enable); - calculateDeferredRotation(); } bool RenderingManager::toggleVanityMode(bool enable) { - bool res = mCamera->toggleVanityMode(enable); - calculateDeferredRotation(); - return res; + return mCamera->toggleVanityMode(enable); } void RenderingManager::allowVanityMode(bool allow) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 000826caa..d6a0f89c3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -221,9 +221,6 @@ namespace MWRender void allowVanityMode(bool allow); void changeVanityModeScale(float factor); - void applyDeferredPreviewRotationToPlayer(float dt); - void disableDeferredPreviewRotation() { mDeferredRotationDisabled = true; } - /// temporarily override the field of view with given value. void overrideFieldOfView(float val); /// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file. @@ -313,11 +310,6 @@ namespace MWRender float mFieldOfView; float mFirstPersonFieldOfView; - // Used to rotate player to the direction of view after exiting preview or vanity mode. - osg::Vec3f mDeferredRotation; - bool mDeferredRotationDisabled; - void calculateDeferredRotation(); - void operator = (const RenderingManager&); RenderingManager(const RenderingManager&); }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 423c55732..ca451601b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2407,12 +2407,12 @@ namespace MWWorld void World::disableDeferredPreviewRotation() { - mRendering->disableDeferredPreviewRotation(); + mRendering->getCamera()->disableDeferredPreviewRotation(); } void World::applyDeferredPreviewRotationToPlayer(float dt) { - mRendering->applyDeferredPreviewRotationToPlayer(dt); + mRendering->getCamera()->applyDeferredPreviewRotationToPlayer(dt); } void World::allowVanityMode(bool allow) From 2e6aa155a35a8c271b8935f4b95fe65d69afad2d Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 18 Jul 2020 13:27:53 +0200 Subject: [PATCH 55/61] New settings 'preview if stand still' and 'deferred preview rotation'. --- apps/openmw/mwrender/camera.cpp | 52 +++++++++++++++++-- apps/openmw/mwrender/camera.hpp | 7 ++- apps/openmw/mwrender/viewovershoulder.cpp | 3 ++ apps/openmw/mwworld/worldimp.cpp | 4 +- .../reference/modding/settings/camera.rst | 24 +++++++++ files/settings-default.cfg | 6 +++ 6 files changed, 87 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 877cb7570..54bc581ef 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -55,6 +55,8 @@ namespace MWRender mFirstPersonView(true), mMode(Mode::Normal), mVanityAllowed(true), + mStandingPreviewAllowed(Settings::Manager::getBool("preview if stand still", "Camera")), + mDeferredRotationAllowed(Settings::Manager::getBool("deferred preview rotation", "Camera")), mNearest(30.f), mFurthest(800.f), mIsNearest(false), @@ -200,6 +202,24 @@ namespace MWRender mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); mMaxNextCameraDistance = mCameraDistance + duration * (100.f + mBaseCameraDistance); + updateStandingPreviewMode(); + } + + void Camera::updateStandingPreviewMode() + { + if (!mStandingPreviewAllowed) + return; + float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); + bool combat = mTrackingPtr.getClass().isActor() && + mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing; + bool standingStill = speed == 0 && !combat && !mFirstPersonView; + if (!standingStill && mMode == Mode::StandingPreview) + { + mMode = Mode::Normal; + calculateDeferredRotation(); + } + else if (standingStill && mMode == Mode::Normal) + mMode = Mode::StandingPreview; } void Camera::setFocalPointTargetOffset(osg::Vec2d v) @@ -266,6 +286,7 @@ namespace MWRender mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).setSideMovementAngle(0); mFirstPersonView = !mFirstPersonView; + updateStandingPreviewMode(); processViewChange(); } @@ -296,6 +317,8 @@ namespace MWRender if ((mMode == Mode::Vanity) == enable) return true; mMode = enable ? Mode::Vanity : Mode::Normal; + if (!mDeferredRotationAllowed) + disableDeferredPreviewRotation(); if (!enable) calculateDeferredRotation(); @@ -312,8 +335,14 @@ namespace MWRender return; mMode = enable ? Mode::Preview : Mode::Normal; - if (!enable) + if (mMode == Mode::Normal) + updateStandingPreviewMode(); + if (mMode == Mode::Normal) + { + if (!mDeferredRotationAllowed) + disableDeferredPreviewRotation(); calculateDeferredRotation(); + } processViewChange(); } @@ -432,6 +461,13 @@ namespace MWRender rot *= delta; mDeferredRotation -= rot; + if (mDeferredRotationDisabled) + { + mDeferredRotationDisabled = delta > 0.0001; + rotateCameraToTrackingPtr(); + return; + } + auto& movement = mTrackingPtr.getClass().getMovementSettings(mTrackingPtr); movement.mRotation[0] += rot.x(); movement.mRotation[1] += rot.y(); @@ -453,16 +489,22 @@ namespace MWRender setYaw(-mTrackingPtr.getRefData().getPosition().rot[2] - mDeferredRotation.z()); } + void Camera::instantTransition() + { + mSkipFocalPointTransition = true; + mDeferredRotationDisabled = false; + mDeferredRotation = osg::Vec3f(); + rotateCameraToTrackingPtr(); + } + void Camera::calculateDeferredRotation() { MWWorld::Ptr ptr = mTrackingPtr; if (isVanityOrPreviewModeEnabled() || ptr.isEmpty()) return; - if (isFirstPerson() || mDeferredRotationDisabled) + if (mFirstPersonView) { - mDeferredRotationDisabled = false; - mDeferredRotation = osg::Vec3f(); - rotateCameraToTrackingPtr(); + instantTransition(); return; } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index c5f7ec2b2..f2e5c390d 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -24,7 +24,7 @@ namespace MWRender class Camera { public: - enum class Mode { Normal, Vanity, Preview }; + enum class Mode { Normal, Vanity, Preview, StandingPreview }; private: MWWorld::Ptr mTrackingPtr; @@ -38,6 +38,8 @@ namespace MWRender bool mFirstPersonView; Mode mMode; bool mVanityAllowed; + bool mStandingPreviewAllowed; + bool mDeferredRotationAllowed; float mNearest; float mFurthest; @@ -79,6 +81,7 @@ namespace MWRender osg::Vec3f mDeferredRotation; bool mDeferredRotationDisabled; void calculateDeferredRotation(); + void updateStandingPreviewMode(); public: Camera(osg::Camera* camera); @@ -90,7 +93,7 @@ namespace MWRender void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; } void setFocalPointTargetOffset(osg::Vec2d v); - void skipFocalPointTransition() { mSkipFocalPointTransition = true; } + void instantTransition(); void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp index ceb9407a1..4d708afe0 100644 --- a/apps/openmw/mwrender/viewovershoulder.cpp +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -77,6 +77,9 @@ namespace MWRender void ViewOverShoulderController::trySwitchShoulder() { + if (mCamera->getMode() != Camera::Mode::Normal) + return; + const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ca451601b..84f50cdef 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -945,7 +945,7 @@ namespace MWWorld removeContainerScripts(getPlayerPtr()); mWorldScene->changeToInteriorCell(cellName, position, adjustPlayerPos, changeEvent); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); - mRendering->getCamera()->skipFocalPointTransition(); + mRendering->getCamera()->instantTransition(); } void World::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) @@ -961,7 +961,7 @@ namespace MWWorld removeContainerScripts(getPlayerPtr()); mWorldScene->changeToExteriorCell(position, adjustPlayerPos, changeEvent); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); - mRendering->getCamera()->skipFocalPointTransition(); + mRendering->getCamera()->instantTransition(); } void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) diff --git a/docs/source/reference/modding/settings/camera.rst b/docs/source/reference/modding/settings/camera.rst index be636cef4..18b6754a7 100644 --- a/docs/source/reference/modding/settings/camera.rst +++ b/docs/source/reference/modding/settings/camera.rst @@ -174,3 +174,27 @@ Slightly pulls camera away (or closer in case of negative value) when the charac This setting can only be configured by editing the settings configuration file. +preview if stand still +---------------------- + +:Type: boolean +:Range: True/False +:Default: False + +If enabled then the character rotation is not synchonized with the camera rotation while the character doesn't move and not in combat mode. + +This setting can only be configured by editing the settings configuration file. + +deferred preview rotation +------------------------- + +:Type: boolean +:Range: True/False +:Default: True + +Makes difference only in third person mode. +If enabled then the character smoothly rotates to the view direction after exiting preview or vanity mode. +If disabled then the camera rotates rather than the character. + +This setting can only be configured by editing the settings configuration file. + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 35be128a8..a9777fc42 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -48,6 +48,12 @@ auto switch shoulder = true # Slightly pulls camera away when the character moves. Works only in 'view over shoulder' mode. Set to 0 to disable. zoom out when move coef = 20 +# Automatically enable preview mode when player doesn't move. +preview if stand still = false + +# Rotate the character to the view direction after exiting preview mode. +deferred preview rotation = true + [Cells] # Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled. From d78b22767053073d71bda9e6c229c8c8cf050dde Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 19 Jul 2020 11:53:39 +0200 Subject: [PATCH 56/61] Fix inverted preview rotation when using controller --- apps/openmw/mwinput/mousemanager.cpp | 8 ++++---- apps/openmw/mwinput/sensormanager.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwinput/mousemanager.cpp b/apps/openmw/mwinput/mousemanager.cpp index 5a0446093..84ab091c5 100644 --- a/apps/openmw/mwinput/mousemanager.cpp +++ b/apps/openmw/mwinput/mousemanager.cpp @@ -209,17 +209,17 @@ namespace MWInput return; float rot[3]; - rot[0] = yAxis * dt * 1000.0f * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f; + rot[0] = -yAxis * dt * 1000.0f * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f; rot[1] = 0.0f; - rot[2] = xAxis * dt * 1000.0f * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f; + rot[2] = -xAxis * dt * 1000.0f * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f; // Only actually turn player when we're not in vanity mode bool controls = MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"); if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && controls) { MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); - player.yaw(rot[2]); - player.pitch(rot[0]); + player.yaw(-rot[2]); + player.pitch(-rot[0]); } else if (!controls) MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation(); diff --git a/apps/openmw/mwinput/sensormanager.cpp b/apps/openmw/mwinput/sensormanager.cpp index 5a3d8847b..3e8e70aef 100644 --- a/apps/openmw/mwinput/sensormanager.cpp +++ b/apps/openmw/mwinput/sensormanager.cpp @@ -249,17 +249,17 @@ namespace MWInput if (!mGuiCursorEnabled) { float rot[3]; - rot[0] = mGyroYSpeed * dt * mGyroVSensitivity * 4 * (mInvertY ? -1 : 1); + rot[0] = -mGyroYSpeed * dt * mGyroVSensitivity * 4 * (mInvertY ? -1 : 1); rot[1] = 0.0f; - rot[2] = mGyroXSpeed * dt * mGyroHSensitivity * 4 * (mInvertX ? -1 : 1); + rot[2] = -mGyroXSpeed * dt * mGyroHSensitivity * 4 * (mInvertX ? -1 : 1); // Only actually turn player when we're not in vanity mode bool playerLooking = MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking"); if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && playerLooking) { MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); - player.yaw(rot[2]); - player.pitch(rot[0]); + player.yaw(-rot[2]); + player.pitch(-rot[0]); } else if (!playerLooking) MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation(); From 62c8ea373bc55503f996c735ce8796dd0e0f7c75 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 19 Jul 2020 22:12:17 +0200 Subject: [PATCH 57/61] Fix not completely correct camera transition when switching from 1st person to 3rd person if armed. --- apps/openmw/mwinput/actionmanager.cpp | 12 +++++++----- apps/openmw/mwrender/camera.cpp | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwinput/actionmanager.cpp b/apps/openmw/mwinput/actionmanager.cpp index ddde7a11e..ec6c5cf7f 100644 --- a/apps/openmw/mwinput/actionmanager.cpp +++ b/apps/openmw/mwinput/actionmanager.cpp @@ -110,19 +110,21 @@ namespace MWInput if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch")) { + const float switchLimit = 0.25; + MWBase::World* world = MWBase::Environment::get().getWorld(); if (mBindingsManager->actionIsActive(A_TogglePOV)) { - if (mPreviewPOVDelay == 0) - MWBase::Environment::get().getWorld()->togglePreviewMode(true); + if (world->isFirstPerson() ? mPreviewPOVDelay > switchLimit : mPreviewPOVDelay == 0) + world->togglePreviewMode(true); mPreviewPOVDelay += dt; } else { //disable preview mode if (mPreviewPOVDelay > 0) - MWBase::Environment::get().getWorld()->togglePreviewMode(false); - if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= 0.25) - MWBase::Environment::get().getWorld()->togglePOV(); + world->togglePreviewMode(false); + if (mPreviewPOVDelay > 0.f && mPreviewPOVDelay <= switchLimit) + world->togglePOV(); mPreviewPOVDelay = 0.f; } } diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 54bc581ef..328e53a79 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -287,6 +287,7 @@ namespace MWRender mFirstPersonView = !mFirstPersonView; updateStandingPreviewMode(); + instantTransition(); processViewChange(); } @@ -337,6 +338,8 @@ namespace MWRender mMode = enable ? Mode::Preview : Mode::Normal; if (mMode == Mode::Normal) updateStandingPreviewMode(); + else if (mFirstPersonView) + instantTransition(); if (mMode == Mode::Normal) { if (!mDeferredRotationAllowed) From 3be1cdef33cde567939bf02262e386e62fb5ed25 Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Wed, 22 Jul 2020 21:54:18 +0200 Subject: [PATCH 58/61] [macOS, CI] Use Xcode 11.6 (#2970) * [macOS, CI] Use Xcode 11.6 * [macOS, CI] Enable OpenCs build and see how it goes * [macOS, CI] Re-enable package build and check --- .travis.yml | 8 ++++---- CI/before_script.osx.sh | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd0e6e713..36b15d794 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,9 +37,9 @@ addons: build_command: "make VERBOSE=1 -j3" matrix: include: - - name: OpenMW (all) on MacOS 10.15 with Xcode 12 + - name: OpenMW (all) on MacOS 10.15 with Xcode 11.6 os: osx - osx_image: xcode12 + osx_image: xcode11.6 if: branch != coverity_scan - name: OpenMW (all) on Ubuntu Focal with GCC os: linux @@ -71,8 +71,8 @@ before_script: script: - cd ./build - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ${ANALYZE} make -j3; fi -# - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi -# - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi + - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi + - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi - cd "${TRAVIS_BUILD_DIR}" diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 15d6862db..993de79fe 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -20,7 +20,7 @@ cmake \ -D CMAKE_BUILD_TYPE=RELEASE \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ -D BUILD_OPENMW=TRUE \ --D BUILD_OPENCS=FALSE \ +-D BUILD_OPENCS=TRUE \ -D BUILD_ESMTOOL=TRUE \ -D BUILD_BSATOOL=TRUE \ -D BUILD_ESSIMPORTER=TRUE \ From 8cdc7031f54f9ab92a0bb7cb8736cd3d3751f9fa Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Fri, 24 Jul 2020 21:47:49 +0200 Subject: [PATCH 59/61] Support vectors in settings.cfg --- apps/openmw/mwrender/viewovershoulder.cpp | 10 +++---- components/settings/settings.cpp | 36 +++++++++++++++++++++++ components/settings/settings.hpp | 6 ++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp index 4d708afe0..39599bfea 100644 --- a/apps/openmw/mwrender/viewovershoulder.cpp +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -21,14 +21,14 @@ namespace MWRender mAutoSwitchShoulder(Settings::Manager::getBool("auto switch shoulder", "Camera")), mOverShoulderHorizontalOffset(30.f), mOverShoulderVerticalOffset(-10.f) { - std::stringstream offset(Settings::Manager::getString("view over shoulder offset", "Camera")); - offset >> mOverShoulderHorizontalOffset >> mOverShoulderVerticalOffset; - mDefaultShoulderIsRight = mOverShoulderHorizontalOffset >= 0; - mOverShoulderHorizontalOffset = std::abs(mOverShoulderHorizontalOffset); + osg::Vec2f offset = Settings::Manager::getVector2("view over shoulder offset", "Camera"); + mOverShoulderHorizontalOffset = std::abs(offset.x()); + mOverShoulderVerticalOffset = offset.y(); + mDefaultShoulderIsRight = offset.x() >= 0; mCamera->enableDynamicCameraDistance(true); mCamera->enableCrosshairInThirdPersonMode(true); - mCamera->setFocalPointTargetOffset({mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset}); + mCamera->setFocalPointTargetOffset(offset); } void ViewOverShoulderController::update() diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 540af4d19..b29dadcdc 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -76,6 +76,28 @@ bool Manager::getBool (const std::string& setting, const std::string& category) return Misc::StringUtils::ciEqual(string, "true"); } +osg::Vec2f Manager::getVector2 (const std::string& setting, const std::string& category) +{ + const std::string& value = getString(setting, category); + std::stringstream stream(value); + float x, y; + stream >> x >> y; + if (stream.fail()) + throw std::runtime_error(std::string("Can't parse 2d vector: " + value)); + return osg::Vec2f(x, y); +} + +osg::Vec3f Manager::getVector3 (const std::string& setting, const std::string& category) +{ + const std::string& value = getString(setting, category); + std::stringstream stream(value); + float x, y, z; + stream >> x >> y >> z; + if (stream.fail()) + throw std::runtime_error(std::string("Can't parse 3d vector: " + value)); + return osg::Vec3f(x, y, z); +} + void Manager::setString(const std::string &setting, const std::string &category, const std::string &value) { CategorySettingValueMap::key_type key = std::make_pair(category, setting); @@ -111,6 +133,20 @@ void Manager::setBool(const std::string &setting, const std::string &category, c setString(setting, category, value ? "true" : "false"); } +void Manager::setVector2 (const std::string &setting, const std::string &category, const osg::Vec2f value) +{ + std::ostringstream stream; + stream << value.x() << " " << value.y(); + setString(setting, category, stream.str()); +} + +void Manager::setVector3 (const std::string &setting, const std::string &category, const osg::Vec3f value) +{ + std::ostringstream stream; + stream << value.x() << ' ' << value.y() << ' ' << value.z(); + setString(setting, category, stream.str()); +} + void Manager::resetPendingChange(const std::string &setting, const std::string &category) { CategorySettingValueMap::key_type key = std::make_pair(category, setting); diff --git a/components/settings/settings.hpp b/components/settings/settings.hpp index 17d237fc3..ecc5aa5fd 100644 --- a/components/settings/settings.hpp +++ b/components/settings/settings.hpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include namespace Settings { @@ -44,11 +46,15 @@ namespace Settings static float getFloat (const std::string& setting, const std::string& category); static std::string getString (const std::string& setting, const std::string& category); static bool getBool (const std::string& setting, const std::string& category); + static osg::Vec2f getVector2 (const std::string& setting, const std::string& category); + static osg::Vec3f getVector3 (const std::string& setting, const std::string& category); static void setInt (const std::string& setting, const std::string& category, const int value); static void setFloat (const std::string& setting, const std::string& category, const float value); static void setString (const std::string& setting, const std::string& category, const std::string& value); static void setBool (const std::string& setting, const std::string& category, const bool value); + static void setVector2 (const std::string& setting, const std::string& category, const osg::Vec2f value); + static void setVector3 (const std::string& setting, const std::string& category, const osg::Vec3f value); }; } From e6036e13b92a46310cc9a387f73422dfb88f541d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 25 Jul 2020 15:54:49 +0400 Subject: [PATCH 60/61] Use more C++11 loops in game mechanics code --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 15 +++-- apps/openmw/mwmechanics/aifollow.cpp | 4 +- apps/openmw/mwmechanics/aisequence.cpp | 46 ++++++------- apps/openmw/mwmechanics/aiwander.cpp | 6 +- apps/openmw/mwmechanics/autocalcspell.cpp | 82 ++++++++++------------- apps/openmw/mwmechanics/character.cpp | 6 +- apps/openmw/mwmechanics/levelledlist.hpp | 18 ++--- apps/openmw/mwmechanics/objects.cpp | 21 +++--- apps/openmw/mwmechanics/obstacle.cpp | 6 +- 9 files changed, 94 insertions(+), 110 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 47f72efce..ce2553756 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -60,13 +60,14 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont // Make all nearby actors also avoid the door std::vector actors; MWBase::Environment::get().getMechanicsManager()->getActorsInRange(pos.asVec3(),100,actors); - for(std::vector::iterator it = actors.begin(); it != actors.end(); ++it) { - if(*it != getPlayer()) { //Not the player - MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence(); - if(seq.getTypeId() != MWMechanics::AiPackageTypeId::AvoidDoor) { //Only add it once - seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr),*it); - } - } + for(auto& actor : actors) + { + if (actor == getPlayer()) + continue; + + MWMechanics::AiSequence& seq = actor.getClass().getCreatureStats(actor).getAiSequence(); + if (seq.getTypeId() != MWMechanics::AiPackageTypeId::AvoidDoor) + seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr), actor); } return false; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index a9e43b3c3..b3c308d75 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -124,9 +124,9 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte followDistance = 313; short i = 0; followers.sort(); - for (std::list::iterator it = followers.begin(); it != followers.end(); ++it) + for (int followIndex : followers) { - if (*it == mFollowIndex) + if (followIndex == mFollowIndex) followDistance += 130 * i; ++i; } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index f747b16f2..57d32898c 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -406,36 +406,36 @@ void AiSequence::fill(const ESM::AIPackageList &list) if (!list.mList.empty() && list.mList.begin() != (list.mList.end()-1)) mRepeat = true; - for (std::vector::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) + for (const auto& esmPackage : list.mList) { std::unique_ptr package; - if (it->mType == ESM::AI_Wander) + if (esmPackage.mType == ESM::AI_Wander) { - ESM::AIWander data = it->mWander; + ESM::AIWander data = esmPackage.mWander; std::vector idles; idles.reserve(8); for (int i=0; i<8; ++i) idles.push_back(data.mIdle[i]); package = std::make_unique(data.mDistance, data.mDuration, data.mTimeOfDay, idles, data.mShouldRepeat != 0); } - else if (it->mType == ESM::AI_Escort) + else if (esmPackage.mType == ESM::AI_Escort) { - ESM::AITarget data = it->mTarget; + ESM::AITarget data = esmPackage.mTarget; package = std::make_unique(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); } - else if (it->mType == ESM::AI_Travel) + else if (esmPackage.mType == ESM::AI_Travel) { - ESM::AITravel data = it->mTravel; + ESM::AITravel data = esmPackage.mTravel; package = std::make_unique(data.mX, data.mY, data.mZ); } - else if (it->mType == ESM::AI_Activate) + else if (esmPackage.mType == ESM::AI_Activate) { - ESM::AIActivate data = it->mActivate; + ESM::AIActivate data = esmPackage.mActivate; package = std::make_unique(data.mName.toString()); } - else //if (it->mType == ESM::AI_Follow) + else //if (esmPackage.mType == ESM::AI_Follow) { - ESM::AITarget data = it->mTarget; + ESM::AITarget data = esmPackage.mTarget; package = std::make_unique(data.mId.toString(), data.mDuration, data.mX, data.mY, data.mZ); } mPackages.push_back(std::move(package)); @@ -457,10 +457,9 @@ void AiSequence::readState(const ESM::AiSequence::AiSequence &sequence) // If there is more than one non-combat, non-pursue package in the list, enable repeating. int count = 0; - for (std::vector::const_iterator it = sequence.mPackages.begin(); - it != sequence.mPackages.end(); ++it) + for (auto& container : sequence.mPackages) { - if (isActualAiPackage(static_cast(it->mType))) + if (isActualAiPackage(static_cast(container.mType))) count++; } @@ -468,20 +467,19 @@ void AiSequence::readState(const ESM::AiSequence::AiSequence &sequence) mRepeat = true; // Load packages - for (std::vector::const_iterator it = sequence.mPackages.begin(); - it != sequence.mPackages.end(); ++it) + for (auto& container : sequence.mPackages) { std::unique_ptr package; - switch (it->mType) + switch (container.mType) { case ESM::AiSequence::Ai_Wander: { - package.reset(new AiWander(static_cast(it->mPackage))); + package.reset(new AiWander(static_cast(container.mPackage))); break; } case ESM::AiSequence::Ai_Travel: { - const auto source = static_cast(it->mPackage); + const auto source = static_cast(container.mPackage); if (source->mHidden) package.reset(new AiInternalTravel(source)); else @@ -490,27 +488,27 @@ void AiSequence::readState(const ESM::AiSequence::AiSequence &sequence) } case ESM::AiSequence::Ai_Escort: { - package.reset(new AiEscort(static_cast(it->mPackage))); + package.reset(new AiEscort(static_cast(container.mPackage))); break; } case ESM::AiSequence::Ai_Follow: { - package.reset(new AiFollow(static_cast(it->mPackage))); + package.reset(new AiFollow(static_cast(container.mPackage))); break; } case ESM::AiSequence::Ai_Activate: { - package.reset(new AiActivate(static_cast(it->mPackage))); + package.reset(new AiActivate(static_cast(container.mPackage))); break; } case ESM::AiSequence::Ai_Combat: { - package.reset(new AiCombat(static_cast(it->mPackage))); + package.reset(new AiCombat(static_cast(container.mPackage))); break; } case ESM::AiSequence::Ai_Pursue: { - package.reset(new AiPursue(static_cast(it->mPackage))); + package.reset(new AiPursue(static_cast(container.mPackage))); break; } default: diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 11c50dc09..9e179edeb 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -809,11 +809,11 @@ namespace MWMechanics void AiWander::AddNonPathGridAllowedPoints(osg::Vec3f npcPos, const ESM::Pathgrid * pathGrid, int pointIndex, AiWanderStorage& storage) { storage.mAllowedNodes.push_back(PathFinder::makePathgridPoint(npcPos)); - for (std::vector::const_iterator it = pathGrid->mEdges.begin(); it != pathGrid->mEdges.end(); ++it) + for (auto& edge : pathGrid->mEdges) { - if (it->mV0 == pointIndex) + if (edge.mV0 == pointIndex) { - AddPointBetweenPathGridPoints(pathGrid->mPoints[it->mV0], pathGrid->mPoints[it->mV1], storage); + AddPointBetweenPathGridPoints(pathGrid->mPoints[edge.mV0], pathGrid->mPoints[edge.mV1], storage); } } } diff --git a/apps/openmw/mwmechanics/autocalcspell.cpp b/apps/openmw/mwmechanics/autocalcspell.cpp index 9cee1aa31..662cfe473 100644 --- a/apps/openmw/mwmechanics/autocalcspell.cpp +++ b/apps/openmw/mwmechanics/autocalcspell.cpp @@ -61,38 +61,36 @@ namespace MWMechanics // Note: the algorithm heavily depends on the traversal order of the spells. For vanilla-compatible results the // Store must preserve the record ordering as it was in the content files. - for (MWWorld::Store::iterator iter = spells.begin(); iter != spells.end(); ++iter) + for (const ESM::Spell& spell : spells) { - const ESM::Spell* spell = &*iter; - - if (spell->mData.mType != ESM::Spell::ST_Spell) + if (spell.mData.mType != ESM::Spell::ST_Spell) continue; - if (!(spell->mData.mFlags & ESM::Spell::F_Autocalc)) + if (!(spell.mData.mFlags & ESM::Spell::F_Autocalc)) continue; static const int iAutoSpellTimesCanCast = gmst.find("iAutoSpellTimesCanCast")->mValue.getInteger(); - if (baseMagicka < iAutoSpellTimesCanCast * spell->mData.mCost) + if (baseMagicka < iAutoSpellTimesCanCast * spell.mData.mCost) continue; - if (race && race->mPowers.exists(spell->mId)) + if (race && race->mPowers.exists(spell.mId)) continue; - if (!attrSkillCheck(spell, actorSkills, actorAttributes)) + if (!attrSkillCheck(&spell, actorSkills, actorAttributes)) continue; int school; float skillTerm; - calcWeakestSchool(spell, actorSkills, school, skillTerm); + calcWeakestSchool(&spell, actorSkills, school, skillTerm); assert(school >= 0 && school < 6); SchoolCaps& cap = schoolCaps[school]; - if (cap.mReachedLimit && spell->mData.mCost <= cap.mMinCost) + if (cap.mReachedLimit && spell.mData.mCost <= cap.mMinCost) continue; static const float fAutoSpellChance = gmst.find("fAutoSpellChance")->mValue.getFloat(); - if (calcAutoCastChance(spell, actorSkills, actorAttributes, school) < fAutoSpellChance) + if (calcAutoCastChance(&spell, actorSkills, actorAttributes, school) < fAutoSpellChance) continue; - selectedSpells.push_back(spell->mId); + selectedSpells.push_back(spell.mId); if (cap.mReachedLimit) { @@ -101,9 +99,9 @@ namespace MWMechanics selectedSpells.erase(found); cap.mMinCost = std::numeric_limits::max(); - for (std::vector::iterator weakIt = selectedSpells.begin(); weakIt != selectedSpells.end(); ++weakIt) + for (const std::string& testSpellName : selectedSpells) { - const ESM::Spell* testSpell = spells.find(*weakIt); + const ESM::Spell* testSpell = spells.find(testSpellName); //int testSchool; //float dummySkillTerm; @@ -130,10 +128,10 @@ namespace MWMechanics if (cap.mCount == cap.mLimit) cap.mReachedLimit = true; - if (spell->mData.mCost < cap.mMinCost) + if (spell.mData.mCost < cap.mMinCost) { - cap.mWeakestSpell = spell->mId; - cap.mMinCost = spell->mData.mCost; + cap.mWeakestSpell = spell.mId; + cap.mMinCost = spell.mData.mCost; } } } @@ -154,32 +152,28 @@ namespace MWMechanics std::vector selectedSpells; - - const MWWorld::Store &spells = - esmStore.get(); - for (MWWorld::Store::iterator iter = spells.begin(); iter != spells.end(); ++iter) + const MWWorld::Store &spells = esmStore.get(); + for (const ESM::Spell& spell : spells) { - const ESM::Spell* spell = &*iter; - - if (spell->mData.mType != ESM::Spell::ST_Spell) + if (spell.mData.mType != ESM::Spell::ST_Spell) continue; - if (!(spell->mData.mFlags & ESM::Spell::F_PCStart)) + if (!(spell.mData.mFlags & ESM::Spell::F_PCStart)) continue; - if (reachedLimit && spell->mData.mCost <= minCost) + if (reachedLimit && spell.mData.mCost <= minCost) continue; - if (race && std::find(race->mPowers.mList.begin(), race->mPowers.mList.end(), spell->mId) != race->mPowers.mList.end()) + if (race && std::find(race->mPowers.mList.begin(), race->mPowers.mList.end(), spell.mId) != race->mPowers.mList.end()) continue; - if (baseMagicka < spell->mData.mCost) + if (baseMagicka < spell.mData.mCost) continue; static const float fAutoPCSpellChance = esmStore.get().find("fAutoPCSpellChance")->mValue.getFloat(); - if (calcAutoCastChance(spell, actorSkills, actorAttributes, -1) < fAutoPCSpellChance) + if (calcAutoCastChance(&spell, actorSkills, actorAttributes, -1) < fAutoPCSpellChance) continue; - if (!attrSkillCheck(spell, actorSkills, actorAttributes)) + if (!attrSkillCheck(&spell, actorSkills, actorAttributes)) continue; - selectedSpells.push_back(spell->mId); + selectedSpells.push_back(spell.mId); if (reachedLimit) { @@ -188,9 +182,9 @@ namespace MWMechanics selectedSpells.erase(it); minCost = std::numeric_limits::max(); - for (std::vector::iterator weakIt = selectedSpells.begin(); weakIt != selectedSpells.end(); ++weakIt) + for (const std::string& testSpellName : selectedSpells) { - const ESM::Spell* testSpell = esmStore.get().find(*weakIt); + const ESM::Spell* testSpell = esmStore.get().find(testSpellName); if (testSpell->mData.mCost < minCost) { minCost = testSpell->mData.mCost; @@ -200,9 +194,9 @@ namespace MWMechanics } else { - if (spell->mData.mCost < minCost) + if (spell.mData.mCost < minCost) { - weakestSpell = spell; + weakestSpell = &spell; minCost = weakestSpell->mData.mCost; } static const unsigned int iAutoPCSpellMax = esmStore.get().find("iAutoPCSpellMax")->mValue.getInteger(); @@ -216,23 +210,22 @@ namespace MWMechanics bool attrSkillCheck (const ESM::Spell* spell, const int* actorSkills, const int* actorAttributes) { - const std::vector& effects = spell->mEffects.mList; - for (std::vector::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) + for (const auto& spellEffect : spell->mEffects.mList) { - const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mEffectID); + const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(spellEffect.mEffectID); static const int iAutoSpellAttSkillMin = MWBase::Environment::get().getWorld()->getStore().get().find("iAutoSpellAttSkillMin")->mValue.getInteger(); if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill)) { - assert (effectIt->mSkill >= 0 && effectIt->mSkill < ESM::Skill::Length); - if (actorSkills[effectIt->mSkill] < iAutoSpellAttSkillMin) + assert (spellEffect.mSkill >= 0 && spellEffect.mSkill < ESM::Skill::Length); + if (actorSkills[spellEffect.mSkill] < iAutoSpellAttSkillMin) return false; } if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute)) { - assert (effectIt->mAttribute >= 0 && effectIt->mAttribute < ESM::Attribute::Length); - if (actorAttributes[effectIt->mAttribute] < iAutoSpellAttSkillMin) + assert (spellEffect.mAttribute >= 0 && spellEffect.mAttribute < ESM::Attribute::Length); + if (actorAttributes[spellEffect.mAttribute] < iAutoSpellAttSkillMin) return false; } } @@ -244,11 +237,8 @@ namespace MWMechanics { // Morrowind for some reason uses a formula slightly different from magicka cost calculation float minChance = std::numeric_limits::max(); - - const ESM::EffectList& effects = spell->mEffects; - for (std::vector::const_iterator it = effects.mList.begin(); it != effects.mList.end(); ++it) + for (const ESM::ENAMstruct& effect : spell->mEffects.mList) { - const ESM::ENAMstruct& effect = *it; const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effect.mEffectID); int minMagn = 1; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index aed638895..c8e81aa49 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2653,11 +2653,11 @@ void CharacterController::updateContinuousVfx() std::vector effects; mAnimation->getLoopingEffects(effects); - for (std::vector::iterator it = effects.begin(); it != effects.end(); ++it) + for (int effectId : effects) { if (mPtr.getClass().getCreatureStats(mPtr).isDeathAnimationFinished() - || mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(MWMechanics::EffectKey(*it)).getMagnitude() <= 0) - mAnimation->removeEffect(*it); + || mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(MWMechanics::EffectKey(effectId)).getMagnitude() <= 0) + mAnimation->removeEffect(effectId); } } diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 697e2eda8..f716f068d 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -31,10 +31,10 @@ namespace MWMechanics std::vector candidates; int highestLevel = 0; - for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + for (const auto& levelledItem : items) { - if (it->mLevel > highestLevel && it->mLevel <= playerLevel) - highestLevel = it->mLevel; + if (levelledItem.mLevel > highestLevel && levelledItem.mLevel <= playerLevel) + highestLevel = levelledItem.mLevel; } // For levelled creatures, the flags are swapped. This file format just makes so much sense. @@ -43,14 +43,14 @@ namespace MWMechanics allLevels = levItem->mFlags & ESM::CreatureLevList::AllLevels; std::pair highest = std::make_pair(-1, ""); - for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + for (const auto& levelledItem : items) { - if (playerLevel >= it->mLevel - && (allLevels || it->mLevel == highestLevel)) + if (playerLevel >= levelledItem.mLevel + && (allLevels || levelledItem.mLevel == highestLevel)) { - candidates.push_back(it->mId); - if (it->mLevel >= highest.first) - highest = std::make_pair(it->mLevel, it->mId); + candidates.push_back(levelledItem.mId); + if (levelledItem.mLevel >= highest.first) + highest = std::make_pair(levelledItem.mLevel, levelledItem.mId); } } if (candidates.empty()) diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp index 9e05509f1..5b18fc2c3 100644 --- a/apps/openmw/mwmechanics/objects.cpp +++ b/apps/openmw/mwmechanics/objects.cpp @@ -19,11 +19,10 @@ Objects::Objects() Objects::~Objects() { - PtrControllerMap::iterator it(mObjects.begin()); - for (; it != mObjects.end();++it) + for(auto& object : mObjects) { - delete it->second; - it->second = nullptr; + delete object.second; + object.second = nullptr; } } @@ -77,8 +76,8 @@ void Objects::update(float duration, bool paused) { if(!paused) { - for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter) - iter->second->update(duration); + for(auto& object : mObjects) + object.second->update(duration); } else { @@ -87,15 +86,15 @@ void Objects::update(float duration, bool paused) if(mode != MWGui::GM_Container) return; - for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter) + for(auto& object : mObjects) { - if (iter->first.getTypeName() != typeid(ESM::Container).name()) + if (object.first.getTypeName() != typeid(ESM::Container).name()) continue; - if (iter->second->isAnimPlaying("containeropen")) + if (object.second->isAnimPlaying("containeropen")) { - iter->second->update(duration); - MWBase::Environment::get().getWorld()->updateAnimatedCollisionShape(iter->first); + object.second->update(duration); + MWBase::Environment::get().getWorld()->updateAnimatedCollisionShape(object.first); } } } diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index e30a2947f..715dfecd2 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -36,17 +36,13 @@ namespace MWMechanics // Check all the doors in this cell const MWWorld::CellRefList& doors = cell->getReadOnlyDoors(); - const MWWorld::CellRefList::List& refList = doors.mList; - MWWorld::CellRefList::List::const_iterator it = refList.begin(); osg::Vec3f pos(actor.getRefData().getPosition().asVec3()); pos.z() = 0; osg::Vec3f actorDir = (actor.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0)); - for (; it != refList.end(); ++it) + for (const auto& ref : doors.mList) { - const MWWorld::LiveCellRef& ref = *it; - osg::Vec3f doorPos(ref.mData.getPosition().asVec3()); // FIXME: cast From 2e27de027e642c7db06724fd54f2f7f6578e8092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Sat, 25 Jul 2020 13:58:42 +0000 Subject: [PATCH 61/61] Add members in AdvancedPage class to avoid memory leak when the list of cells names is updated as we recreated a completer at each notification event --- CHANGELOG.md | 1 + apps/launcher/advancedpage.cpp | 12 ++++++------ apps/launcher/advancedpage.hpp | 4 ++++ components/contentselector/view/combobox.cpp | 1 + 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c98dfbe3d..e75b20dad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ Feature #5524: Resume failed script execution after reload Feature #5525: Search fields tweaks (utf-8) Task #5480: Drop Qt4 support + Task #5520: Improve cell name autocompleter implementation 0.46.0 ------ diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index e9db74cae..00d0df048 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -19,15 +19,15 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, setupUi(this); loadSettings(); + mCellNameCompleter.setModel(&mCellNameCompleterModel); + startDefaultCharacterAtField->setCompleter(&mCellNameCompleter); } void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList cellNames) { - // Set up an auto-completer for the "Start default character at" field - auto *completer = new QCompleter(cellNames); - completer->setCompletionMode(QCompleter::PopupCompletion); - completer->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); - startDefaultCharacterAtField->setCompleter(completer); - + // Update the list of suggestions for the "Start default character at" field + mCellNameCompleterModel.setStringList(cellNames); + mCellNameCompleter.setCompletionMode(QCompleter::PopupCompletion); + mCellNameCompleter.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); } void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state) { diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index 3f5e5bfa7..25cb66d9d 100644 --- a/apps/launcher/advancedpage.hpp +++ b/apps/launcher/advancedpage.hpp @@ -2,6 +2,8 @@ #define ADVANCEDPAGE_H #include +#include +#include #include "ui_advancedpage.h" @@ -35,6 +37,8 @@ namespace Launcher Files::ConfigurationManager &mCfgMgr; Config::GameSettings &mGameSettings; Settings::Manager &mEngineSettings; + QCompleter mCellNameCompleter; + QStringListModel mCellNameCompleterModel; /** * Load the cells associated with the given content files for use in autocomplete diff --git a/components/contentselector/view/combobox.cpp b/components/contentselector/view/combobox.cpp index 959eca289..1ef9f9bd7 100644 --- a/components/contentselector/view/combobox.cpp +++ b/components/contentselector/view/combobox.cpp @@ -8,6 +8,7 @@ ContentSelectorView::ComboBox::ComboBox(QWidget *parent) : { mValidator = new QRegExpValidator(QRegExp("^[a-zA-Z0-9_]*$"), this); // Alpha-numeric + underscore setValidator(mValidator); + setEditable(true); setCompleter(0); setEnabled (true);