diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 955a3facc..426d944ef 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,50 +1,89 @@ stages: - build - -Debian: + +.Debian: tags: - docker - linux image: debian:bullseye cache: - key: cache.002 paths: - apt-cache/ - ccache/ before_script: - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR - apt-get update -yq - - apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake build-essential libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-iostreams-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt5opengl5-dev libopenal-dev libopenscenegraph-dev libunshield-dev libtinyxml-dev libmygui-dev libbullet-dev ccache + - apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake build-essential libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-iostreams-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt5opengl5-dev libopenal-dev libopenscenegraph-dev libunshield-dev libtinyxml-dev libmygui-dev libbullet-dev liblz4-dev ccache git clang stage: build script: - export CCACHE_BASEDIR="`pwd`" - export CCACHE_DIR="`pwd`/ccache" && mkdir -pv "$CCACHE_DIR" - - ccache -z -M 250M - - cores_to_use=$((`nproc`-2)); if (( $cores_to_use < 1 )); then cores_to_use=1; fi - - mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - - make -j$cores_to_use - - DESTDIR=artifacts make install + - ccache -z -M "${CCACHE_SIZE}" + - CI/before_script.linux.sh + - cd build + - cmake --build . -- -j $(nproc) + - cmake --install . + - if [[ "${BUILD_TESTS_ONLY}" ]]; then ./openmw_test_suite; fi - ccache -s artifacts: paths: - - build/artifacts/ + - build/install/ + +Debian_GCC: + extends: .Debian + cache: + key: Debian_GCC.v2 + variables: + CC: gcc + CXX: g++ + CCACHE_SIZE: 3G + +Debian_GCC_tests: + extends: .Debian + cache: + key: Debian_GCC_tests.v2 + variables: + CC: gcc + CXX: g++ + CCACHE_SIZE: 1G + BUILD_TESTS_ONLY: 1 + +Debian_Clang: + extends: .Debian + cache: + key: Debian_Clang.v2 + variables: + CC: clang + CXX: clang++ + CCACHE_SIZE: 2G + +Debian_Clang_tests: + extends: .Debian + cache: + key: Debian_Clang_tests.v2 + variables: + CC: clang + CXX: clang++ + CCACHE_SIZE: 1G + BUILD_TESTS_ONLY: 1 MacOS: tags: - macos - - xcode - except: - - branches # because our CI VMs are not public, MRs can't use them and timeout stage: build - allow_failure: true + only: + variables: + - $CI_PROJECT_ID == "7107382" script: - - rm -fr build/* # remove anything in the build directory + - rm -fr build/* # remove anything in the build directory - CI/before_install.osx.sh - CI/before_script.osx.sh - cd build; make -j2 package + - for dmg in *.dmg; do mv "$dmg" "${dmg%.dmg}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.dmg"; done artifacts: paths: - build/OpenMW-*.dmg + - "build/**/*.log" variables: &engine-targets targets: "openmw_vr,openmw-essimporter,openmw-iniimporter,openmw-launcher,openmw-wizard" @@ -57,6 +96,7 @@ variables: &cs-targets - windows before_script: - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolately/" --priority=1 - choco install git --force --params "/GitAndUnixToolsOnPath" -y - choco install 7zip -y - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y @@ -146,6 +186,7 @@ Windows_Ninja_CS_RelWithDebInfo: - windows before_script: - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolately/" --priority=1 - choco install git --force --params "/GitAndUnixToolsOnPath" -y - choco install 7zip -y - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y @@ -226,4 +267,36 @@ Windows_MSBuild_CS_RelWithDebInfo: - .Windows_MSBuild_Base variables: <<: *cs-targets - config: "RelWithDebInfo" \ No newline at end of file + config: "RelWithDebInfo" + +Debian_AndroidNDK_arm64-v8a: + tags: + - linux + image: debian:bullseye + variables: + CCACHE_SIZE: 3G + cache: + key: Debian_AndroidNDK_arm64-v8a.v2 + paths: + - apt-cache/ + - ccache/ + before_script: + - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR + - echo "deb http://deb.debian.org/debian unstable main contrib" > /etc/apt/sources.list + - echo "google-android-ndk-installer google-android-installers/mirror select https://dl.google.com" | debconf-set-selections + - apt-get update -yq + - apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake ccache curl unzip git build-essential google-android-ndk-installer + stage: build + script: + - export CCACHE_BASEDIR="`pwd`" + - export CCACHE_DIR="`pwd`/ccache" && mkdir -pv "$CCACHE_DIR" + - ccache -z -M "${CCACHE_SIZE}" + - CI/before_install.android.sh + - CI/before_script.android.sh + - cd build + - cmake --build . -- -j $(nproc) + - cmake --install . + - ccache -s + artifacts: + paths: + - build/install/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index cd0e6e713..2f457798a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ addons: # FFmpeg libavcodec-dev, libavformat-dev, libavutil-dev, libswresample-dev, libswscale-dev, # Audio, Video and Misc. deps - libsdl2-dev, libqt5opengl5-dev, libopenal-dev, libunshield-dev, libtinyxml-dev, + libsdl2-dev, libqt5opengl5-dev, libopenal-dev, libunshield-dev, libtinyxml-dev, liblz4-dev # The other ones from OpenMW ppa libbullet-dev, libopenscenegraph-dev, libmygui-dev ] @@ -37,14 +37,20 @@ 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 dist: focal if: branch != coverity_scan + - name: OpenMW (tests only) on Ubuntu Focal with GCC + os: linux + dist: focal + if: branch != coverity_scan + env: + - BUILD_TESTS_ONLY: 1 - name: OpenMW (openmw) on Ubuntu Focal with Clang's Static Analysis os: linux dist: focal @@ -71,9 +77,9 @@ 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}" = "linux" ]; then ./openmw_test_suite; 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" ] && [ "${BUILD_TESTS_ONLY}" ]; 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}" - ccache -s diff --git a/AUTHORS.md b/AUTHORS.md index 0f0522c44..25004078e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -10,7 +10,10 @@ If you feel your name is missing from this list, please notify a developer. Programmers ----------- - Marc Zinnschlag (Zini) - Lead Programmer/Project Manager + Bret Curtis (psi29a) - Project leader 2019-present + Marc Zinnschlag (Zini) - Project leader 2010-2018 + Nicolay Korslund - Project leader 2008-2010 + scrawl - Top contributor Adam Hogan (aurix) Aesylwinn @@ -39,7 +42,6 @@ Programmers Austin Salgat (Salgat) Ben Shealy (bentsherman) Berulacks - Bret Curtis (psi29a) Britt Mathis (galdor557) Capostrophic Carl Maxwell @@ -146,7 +148,6 @@ Programmers Nathan Jeffords (blunted2night) NeveHanter Nialsy - Nicolay Korslund Nikolay Kasyanov (corristo) nobrakal Nolan Poe (nopoe) @@ -175,7 +176,6 @@ Programmers Roman Siromakha (elsid) Sandy Carter (bwrsandman) Scott Howard (maqifrnswa) - scrawl Sebastian Wick (swick) Sergey Fukanchik Sergey Shambir (sergey-shambir) @@ -302,4 +302,4 @@ Thanks to Kevin Ryan, for creating the icon used for the Data Files tab of the OpenMW Launcher. Thanks to DejaVu team, -for their DejaVuLGCSansMono fontface, see DejaVu Font License.txt for their license terms. +for their DejaVuLGCSansMono fontface, see DejaVuFontLicense.txt for their license terms. diff --git a/CHANGELOG.md b/CHANGELOG.md index c98dfbe3d..32862b20b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,21 @@ Bug #1662: Qt4 and Windows binaries crash if there's a non-ASCII character in a file path/config path Bug #1952: Incorrect particle lighting + Bug #2069: Fireflies in Fireflies invade Morrowind look wrong Bug #2311: Targeted scripts are not properly supported on non-unique RefIDs + Bug #2473: Unable to overstock merchants + Bug #2798: Mutable ESM records Bug #3676: NiParticleColorModifier isn't applied properly Bug #3714: Savegame fails to load due to conflict between SpellState and MagicEffects + Bug #3862: Random container contents behave differently than vanilla + Bug #3929: Leveled list merchant containers respawn on barter Bug #4021: Attributes and skills are not stored as floats + Bug #4055: Local scripts don't inherit variables from their base record Bug #4623: Corprus implementation is incorrect + Bug #4631: Setting MSAA level too high doesn't fall back to highest supported level Bug #4764: Data race in osg ParticleSystem Bug #4774: Guards are ignorant of an invisible player that tries to attack them + Bug #5101: Hostile followers travel with the player Bug #5108: Savegame bloating due to inefficient fog textures format Bug #5165: Active spells should use real time intead of timestamps Bug #5358: ForceGreeting always resets the dialogue window completely @@ -41,16 +49,37 @@ 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 + Bug #5539: Window resize breaks when going from a lower resolution to full screen resolution + Bug #5548: Certain exhausted topics can be highlighted again even though there's no new dialogue + Bug #5557: Diagonal movement is noticeably slower with analogue stick + Bug #5588: Randomly clicking on the journal's right-side page when it's empty shows random topics + Bug #5603: Setting constant effect cast style doesn't correct effects view + Bug #5611: Usable items with "0 Uses" should be used only once + Bug #5622: Can't properly interact with the console when in pause menu + Bug #5639: Tooltips cover Messageboxes + Bug #5644: Summon effects running on the player during game initialization cause crashes Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging + Feature #2404: Levelled List can not be placed into a container + Feature #4894: Consider actors as obstacles for pathfinding + Feature #5043: Head Bobbing Feature #5297: Add a search function to the "Datafiles" tab of the OpenMW launcher Feature #5362: Show the soul gems' trapped soul in count dialog 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 #5519: Code Patch tab in launcher Feature #5524: Resume failed script execution after reload Feature #5525: Search fields tweaks (utf-8) + Feature #5545: Option to allow stealing from an unconscious NPC during combat + Feature #5563: Run physics update in background thread + Feature #5579: MCP SetAngle enhancement + Feature #5580: Service refusal filtering + Feature #5610: Actors movement should be smoother + Feature #5642: Ability to attach arrows to actor skeleton instead of bow mesh + Feature #5649: Skyrim SE compressed BSA format support Task #5480: Drop Qt4 support + Task #5520: Improve cell name autocompleter implementation 0.46.0 ------ diff --git a/CI/activate_msvc.sh b/CI/activate_msvc.sh index 1641f6b3e..47f2c246f 100644 --- a/CI/activate_msvc.sh +++ b/CI/activate_msvc.sh @@ -1,6 +1,16 @@ #!/bin/bash -set -euo pipefail +oldSettings=$- +set -eu + +function restoreOldSettings { + if [[ $oldSettings != *e* ]]; then + set +e + fi + if [[ $oldSettings != *u* ]]; then + set +u + fi +} if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then echo "Error: Script not sourced." @@ -8,6 +18,7 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then echo "source ./activate_msvc.sh" echo "or" echo ". ./activate_msvc.sh" + restoreOldSettings exit 1 fi @@ -78,7 +89,10 @@ command -v mt >/dev/null 2>&1 || { echo "Error: mt (MS Windows Manifest Tool) mi if [ $MISSINGTOOLS -ne 0 ]; then echo "Some build tools were unavailable after activating MSVC in the shell. It's likely that your Visual Studio $MSVC_DISPLAY_YEAR installation needs repairing." + restoreOldSettings return 1 fi -IFS="$originalIFS" \ No newline at end of file +IFS="$originalIFS" + +restoreOldSettings \ No newline at end of file diff --git a/CI/before_install.android.sh b/CI/before_install.android.sh new file mode 100755 index 000000000..791377dd9 --- /dev/null +++ b/CI/before_install.android.sh @@ -0,0 +1,4 @@ +#!/bin/sh -ex + +curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/android/openmw-android-deps-20201018.zip -o ~/openmw-android-deps.zip +unzip -o ~/openmw-android-deps -d /usr/lib/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr > /dev/null diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh index 5dae1f102..fd77e0693 100755 --- a/CI/before_install.osx.sh +++ b/CI/before_install.osx.sh @@ -1,6 +1,12 @@ #!/bin/sh -e -brew install ccache +# Some of these tools can come from places other than brew, so check before installing +command -v ccache >/dev/null 2>&1 || brew install ccache +command -v cmake >/dev/null 2>&1 || brew install cmake +command -v qmake >/dev/null 2>&1 || brew install qt + +brew link --overwrite lz4 # overwrite system lz4; use brew +brew reinstall lz4 curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-ef2462c.zip -o ~/openmw-deps.zip unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null diff --git a/CI/before_script.android.sh b/CI/before_script.android.sh new file mode 100755 index 000000000..8f0ec77da --- /dev/null +++ b/CI/before_script.android.sh @@ -0,0 +1,25 @@ +#!/bin/sh -ex + +# hack to work around: FFmpeg version is too old, 3.2 is required +sed -i s/"NOT FFVER_OK"/"FALSE"/ CMakeLists.txt + +mkdir build +cd build + +cmake \ +-DCMAKE_TOOLCHAIN_FILE=/usr/lib/android-sdk/ndk-bundle/build/cmake/android.toolchain.cmake \ +-DANDROID_ABI=arm64-v8a \ +-DANDROID_PLATFORM=android-21 \ +-DCMAKE_C_COMPILER_LAUNCHER=ccache \ +-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ +-DCMAKE_INSTALL_PREFIX=install \ +-DBUILD_BSATOOL=0 \ +-DBUILD_NIFTEST=0 \ +-DBUILD_ESMTOOL=0 \ +-DBUILD_LAUNCHER=0 \ +-DBUILD_MWINIIMPORTER=0 \ +-DBUILD_ESSIMPORTER=0 \ +-DBUILD_OPENCS=0 \ +-DBUILD_WIZARD=0 \ +-DMyGUI_LIBRARY="/usr/lib/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/libMyGUIEngineStatic.a" \ +.. diff --git a/CI/before_script.linux.sh b/CI/before_script.linux.sh index f4aaeecc9..6df3dc32e 100755 --- a/CI/before_script.linux.sh +++ b/CI/before_script.linux.sh @@ -2,22 +2,43 @@ free -m -env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_googletest.sh -GOOGLETEST_DIR="$(pwd)/googletest/build" +if [[ "${BUILD_TESTS_ONLY}" ]]; then + export GOOGLETEST_DIR="$(pwd)/googletest/build/install" + env GENERATOR='Unix Makefiles' CONFIGURATION=Release CI/build_googletest.sh +fi mkdir build cd build -${ANALYZE} cmake \ - -DCMAKE_C_COMPILER="${CC}" \ - -DCMAKE_CXX_COMPILER="${CXX}" \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ - -DBUILD_UNITTESTS=TRUE \ - -DUSE_SYSTEM_TINYXML=TRUE \ - -DCMAKE_INSTALL_PREFIX="/usr" \ - -DBINDIR="/usr/games" \ - -DCMAKE_BUILD_TYPE="DEBUG" \ - -DGTEST_ROOT="${GOOGLETEST_DIR}" \ - -DGMOCK_ROOT="${GOOGLETEST_DIR}" \ - .. +if [[ "${BUILD_TESTS_ONLY}" ]]; then + ${ANALYZE} cmake \ + -D CMAKE_C_COMPILER="${CC}" \ + -D CMAKE_CXX_COMPILER="${CXX}" \ + -D CMAKE_C_COMPILER_LAUNCHER=ccache \ + -D CMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -D CMAKE_INSTALL_PREFIX=install \ + -D CMAKE_BUILD_TYPE=RelWithDebInfo \ + -D USE_SYSTEM_TINYXML=TRUE \ + -D BUILD_OPENMW=OFF \ + -D BUILD_BSATOOL=OFF \ + -D BUILD_ESMTOOL=OFF \ + -D BUILD_LAUNCHER=OFF \ + -D BUILD_MWINIIMPORTER=OFF \ + -D BUILD_ESSIMPORTER=OFF \ + -D BUILD_OPENCS=OFF \ + -D BUILD_WIZARD=OFF \ + -D BUILD_UNITTESTS=ON \ + -D GTEST_ROOT="${GOOGLETEST_DIR}" \ + -D GMOCK_ROOT="${GOOGLETEST_DIR}" \ + .. +else + ${ANALYZE} cmake \ + -D CMAKE_C_COMPILER="${CC}" \ + -D CMAKE_CXX_COMPILER="${CXX}" \ + -D CMAKE_C_COMPILER_LAUNCHER=ccache \ + -D CMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -D USE_SYSTEM_TINYXML=TRUE \ + -D CMAKE_INSTALL_PREFIX=install \ + -D CMAKE_BUILD_TYPE=Debug \ + .. +fi diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index d7f0f01fb..da4ec984b 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -69,7 +69,7 @@ NMAKE="" NINJA="" PDBS="" PLATFORM="" -CONFIGURATION="" +CONFIGURATIONS=() TEST_FRAMEWORK="" GOOGLE_INSTALL_ROOT="" INSTALL_PREFIX="." @@ -133,7 +133,7 @@ while [ $# -gt 0 ]; do PDBS=true ;; c ) - CONFIGURATION=$1 + CONFIGURATIONS+=( $1 ) shift ;; t ) @@ -147,8 +147,10 @@ while [ $# -gt 0 ]; do cat < + -c Set the configuration, can also be set with environment variable CONFIGURATION. + For mutli-config generators, this is ignored, and all configurations are set up. + For single-config generators, several configurations can be set up at once by specifying -c multiple times. -d Skip checking the downloads. -D @@ -168,7 +170,7 @@ Options: -v <2017/2019> Choose the Visual Studio version to use. -n - Produce NMake makefiles instead of a Visual Studio solution. Cannout be used with -N. + Produce NMake makefiles instead of a Visual Studio solution. Cannot be used with -N. -N Produce Ninja (multi-config if CMake is new enough to support it) files instead of a Visual Studio solution. Cannot be used with -n.. -P @@ -191,7 +193,7 @@ done if [ -n "$NMAKE" ] || [ -n "$NINJA" ]; then if [ -n "$NMAKE" ] && [ -n "$NINJA" ]; then - echo "Cannout run in NMake and Ninja mode at the same time." + echo "Cannot run in NMake and Ninja mode at the same time." wrappedExit 1 fi ACTIVATE_MSVC=true @@ -262,10 +264,10 @@ download() { if [ -z $VERBOSE ]; then RET=0 - curl --silent --retry 10 -kLy 5 -o $FILE $URL || RET=$? + curl --silent --retry 10 -Ly 5 -o $FILE $URL || RET=$? else RET=0 - curl --retry 10 -kLy 5 -o $FILE $URL || RET=$? + curl --retry 10 -Ly 5 -o $FILE $URL || RET=$? fi if [ $RET -ne 0 ]; then @@ -297,29 +299,40 @@ add_cmake_opts() { CMAKE_OPTS="$CMAKE_OPTS $@" } -RUNTIME_DLLS="" +declare -A RUNTIME_DLLS +RUNTIME_DLLS["Release"]="" +RUNTIME_DLLS["Debug"]="" +RUNTIME_DLLS["RelWithDebInfo"]="" add_runtime_dlls() { - RUNTIME_DLLS="$RUNTIME_DLLS $@" + local CONFIG=$1 + shift + RUNTIME_DLLS[$CONFIG]="${RUNTIME_DLLS[$CONFIG]} $@" } -OSG_PLUGINS="" +declare -A OSG_PLUGINS +OSG_PLUGINS["Release"]="" +OSG_PLUGINS["Debug"]="" +OSG_PLUGINS["RelWithDebInfo"]="" add_osg_dlls() { - OSG_PLUGINS="$OSG_PLUGINS $@" + local CONFIG=$1 + shift + OSG_PLUGINS[$CONFIG]="${OSG_PLUGINS[$CONFIG]} $@" } -QT_PLATFORMS="" +declare -A QT_PLATFORMS +QT_PLATFORMS["Release"]="" +QT_PLATFORMS["Debug"]="" +QT_PLATFORMS["RelWithDebInfo"]="" add_qt_platform_dlls() { - QT_PLATFORMS="$QT_PLATFORMS $@" + local CONFIG=$1 + shift + QT_PLATFORMS[$CONFIG]="${QT_PLATFORMS[$CONFIG]} $@" } if [ -z $PLATFORM ]; then PLATFORM="$(uname -m)" fi -if [ -z $CONFIGURATION ]; then - CONFIGURATION="Debug" -fi - if [ -z $VS_VERSION ]; then VS_VERSION="2017" fi @@ -381,23 +394,6 @@ case $PLATFORM in ;; esac -case $CONFIGURATION in - debug|Debug|DEBUG ) - CONFIGURATION=Debug - BUILD_CONFIG=Debug - ;; - - release|Release|RELEASE ) - CONFIGURATION=Release - BUILD_CONFIG=Release - ;; - - relwithdebinfo|RelWithDebInfo|RELWITHDEBINFO ) - CONFIGURATION=Release - BUILD_CONFIG=RelWithDebInfo - ;; -esac - if [ $BITS -eq 64 ] && [ $MSVC_REAL_VER -lt 16 ]; then GENERATOR="${GENERATOR} Win64" fi @@ -415,6 +411,79 @@ if [ -n "$NINJA" ]; then fi fi +if [ -n "$SINGLE_CONFIG" ]; then + if [ ${#CONFIGURATIONS[@]} -eq 0 ]; then + if [ -n "${CONFIGURATION:-}" ]; then + CONFIGURATIONS=("$CONFIGURATION") + else + CONFIGURATIONS=("Debug") + fi + elif [ ${#CONFIGURATIONS[@]} -ne 1 ]; then + # It's simplest just to recursively call the script a few times. + RECURSIVE_OPTIONS=() + if [ -n "$VERBOSE" ]; then + RECURSIVE_OPTIONS+=("-V") + fi + if [ -n "$SKIP_DOWNLOAD" ]; then + RECURSIVE_OPTIONS+=("-d") + fi + if [ -n "$BULLET_DOUBLE" ]; then + RECURSIVE_OPTIONS+=("-D") + fi + if [ -n "$SKIP_EXTRACT" ]; then + RECURSIVE_OPTIONS+=("-e") + fi + if [ -n "$KEEP" ]; then + RECURSIVE_OPTIONS+=("-k") + fi + if [ -n "$UNITY_BUILD" ]; then + RECURSIVE_OPTIONS+=("-u") + fi + if [ -n "$NMAKE" ]; then + RECURSIVE_OPTIONS+=("-n") + fi + if [ -n "$NINJA" ]; then + RECURSIVE_OPTIONS+=("-N") + fi + if [ -n "$PDBS" ]; then + RECURSIVE_OPTIONS+=("-P") + fi + if [ -n "$TEST_FRAMEWORK" ]; then + RECURSIVE_OPTIONS+=("-t") + fi + RECURSIVE_OPTIONS+=("-v $VS_VERSION") + RECURSIVE_OPTIONS+=("-p $PLATFORM") + RECURSIVE_OPTIONS+=("-i '$INSTALL_PREFIX'") + + for config in ${CONFIGURATIONS[@]}; do + $0 ${RECURSIVE_OPTIONS[@]} -c $config + done + + wrappedExit 1 + fi +else + if [ ${#CONFIGURATIONS[@]} -ne 0 ]; then + echo "Ignoring configurations argument - generator is multi-config" + fi + CONFIGURATIONS=("Release" "Debug" "RelWithDebInfo") +fi + +for i in ${!CONFIGURATIONS[@]}; do + case ${CONFIGURATIONS[$i]} in + debug|Debug|DEBUG ) + CONFIGURATIONS[$i]=Debug + ;; + + release|Release|RELEASE ) + CONFIGURATIONS[$i]=Release + ;; + + relwithdebinfo|RelWithDebInfo|RELWITHDEBINFO ) + CONFIGURATIONS[$i]=RelWithDebInfo + ;; + esac +done + if [ $MSVC_REAL_VER -ge 16 ] && [ -z "$NMAKE" ] && [ -z "$NINJA" ]; then if [ $BITS -eq 64 ]; then add_cmake_opts "-G\"$GENERATOR\" -A x64" @@ -426,7 +495,7 @@ else fi if [ -n "$SINGLE_CONFIG" ]; then - add_cmake_opts "-DCMAKE_BUILD_TYPE=${BUILD_CONFIG}" + add_cmake_opts "-DCMAKE_BUILD_TYPE=${CONFIGURATIONS[0]}" fi if ! [ -z $UNITY_BUILD ]; then @@ -458,54 +527,59 @@ if [ -z $SKIP_DOWNLOAD ]; then # Boost if [ -z $APPVEYOR ]; then download "Boost ${BOOST_VER}" \ - "https://sourceforge.net/projects/boost/files/boost-binaries/${BOOST_VER}/boost_${BOOST_VER_URL}-msvc-${MSVC_VER}-${BITS}.exe" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/boost_${BOOST_VER_URL}-msvc-${MSVC_VER}-${BITS}.exe" \ "boost-${BOOST_VER}-msvc${MSVC_VER}-win${BITS}.exe" fi # Bullet download "Bullet 2.89 (${BULLET_DBL_DISPLAY})" \ - "https://rgw.ctrl-c.liu.se/openmw/Deps/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" \ "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" # FFmpeg download "FFmpeg 4.2.2" \ - "https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-4.2.2-win${BITS}-shared.zip" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/ffmpeg-4.2.2-win${BITS}.zip" \ "ffmpeg-4.2.2-win${BITS}.zip" \ - "https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-4.2.2-win${BITS}-dev.zip" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/ffmpeg-4.2.2-dev-win${BITS}.zip" \ "ffmpeg-4.2.2-dev-win${BITS}.zip" # MyGUI download "MyGUI 3.4.0" \ - "https://rgw.ctrl-c.liu.se/openmw/Deps/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \ "MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" if [ -n "$PDBS" ]; then download "MyGUI symbols" \ - "https://rgw.ctrl-c.liu.se/openmw/Deps/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \ "MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" fi # OpenAL download "OpenAL-Soft 1.20.1" \ - "http://openal-soft.org/openal-binaries/openal-soft-1.20.1-bin.zip" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/OpenAL-Soft-1.20.1.zip" \ "OpenAL-Soft-1.20.1.zip" # OSG download "OpenSceneGraph 3.6.5" \ - "https://rgw.ctrl-c.liu.se/openmw/Deps/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" \ "OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}.7z" if [ -n "$PDBS" ]; then download "OpenSceneGraph symbols" \ - "https://rgw.ctrl-c.liu.se/openmw/Deps/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" \ "OSG-3.6.5-msvc${MSVC_REAL_YEAR}-win${BITS}-sym.7z" fi # SDL2 download "SDL 2.0.12" \ - "https://www.libsdl.org/release/SDL2-devel-2.0.12-VC.zip" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/SDL2-2.0.12.zip" \ "SDL2-2.0.12.zip" + # LZ4 + download "LZ4 1.9.2" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/lz4_win${BITS}_v1_9_2.7z" \ + "lz4_win${BITS}_v1_9_2.7z" + # Google test and mock if [ ! -z $TEST_FRAMEWORK ]; then echo "Google test 1.10.0..." @@ -529,7 +603,7 @@ elif [ -n "$NINJA" ]; then fi if [ -n "$SINGLE_CONFIG" ]; then - BUILD_DIR="${BUILD_DIR}_${BUILD_CONFIG}" + BUILD_DIR="${BUILD_DIR}_${CONFIGURATIONS[0]}" fi if [ -z $KEEP ]; then @@ -630,7 +704,9 @@ printf "FFmpeg 4.2.2... " rm -rf "ffmpeg-4.2.2-win${BITS}-dev" fi export FFMPEG_HOME="$(real_pwd)/FFmpeg" - add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-58,avformat-58,avutil-56,swresample-3,swscale-5}.dll + for config in ${CONFIGURATIONS[@]}; do + add_runtime_dlls $config "$(pwd)/FFmpeg/bin/"{avcodec-58,avformat-58,avutil-56,swresample-3,swscale-5}.dll + done if [ $BITS -eq 32 ]; then add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\"" fi @@ -655,14 +731,16 @@ printf "MyGUI 3.4.0... " mv "MyGUI-3.4.0-msvc${MSVC_REAL_YEAR}-win${BITS}" MyGUI fi export MYGUI_HOME="$(real_pwd)/MyGUI" - if [ $CONFIGURATION == "Debug" ]; then - SUFFIX="_d" - MYGUI_CONFIGURATION="Debug" - else - SUFFIX="" - MYGUI_CONFIGURATION="RelWithDebInfo" - fi - add_runtime_dlls "$(pwd)/MyGUI/bin/${MYGUI_CONFIGURATION}/MyGUIEngine${SUFFIX}.dll" + for CONFIGURATION in ${CONFIGURATIONS[@]}; do + if [ $CONFIGURATION == "Debug" ]; then + SUFFIX="_d" + MYGUI_CONFIGURATION="Debug" + else + SUFFIX="" + MYGUI_CONFIGURATION="RelWithDebInfo" + fi + add_runtime_dlls $CONFIGURATION "$(pwd)/MyGUI/bin/${MYGUI_CONFIGURATION}/MyGUIEngine${SUFFIX}.dll" + done echo Done. } cd $DEPS @@ -679,7 +757,9 @@ printf "OpenAL-Soft 1.20.1... " OPENAL_SDK="$(real_pwd)/openal-soft-1.20.1-bin" add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \ -DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib" - add_runtime_dlls "$(pwd)/openal-soft-1.20.1-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll" + for config in ${CONFIGURATIONS[@]}; do + add_runtime_dlls $config "$(pwd)/openal-soft-1.20.1-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll" + done echo Done. } cd $DEPS @@ -702,15 +782,17 @@ printf "OSG 3.6.5... " fi OSG_SDK="$(real_pwd)/OSG" add_cmake_opts -DOSG_DIR="$OSG_SDK" - if [ $CONFIGURATION == "Debug" ]; then - SUFFIX="d" - else - SUFFIX="" - fi - add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng}${SUFFIX}.dll \ - "$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow}${SUFFIX}.dll - add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_"{bmp,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll - add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer,shadow}${SUFFIX}.dll + for CONFIGURATION in ${CONFIGURATIONS[@]}; do + if [ $CONFIGURATION == "Debug" ]; then + SUFFIX="d" + else + SUFFIX="" + fi + add_runtime_dlls $CONFIGURATION "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng}${SUFFIX}.dll \ + "$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer,Shadow}${SUFFIX}.dll + add_osg_dlls $CONFIGURATION "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_"{bmp,dds,freetype,jpeg,osg,png,tga}${SUFFIX}.dll + add_osg_dlls $CONFIGURATION "$(pwd)/OSG/bin/osgPlugins-3.6.5/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer,shadow}${SUFFIX}.dll + done echo Done. } cd $DEPS @@ -782,26 +864,30 @@ fi cd $QT_SDK add_cmake_opts -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \ -DCMAKE_PREFIX_PATH="$QT_SDK" - if [ $CONFIGURATION == "Debug" ]; then - SUFFIX="d" - else - SUFFIX="" - fi - add_runtime_dlls "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll - add_qt_platform_dlls "$(pwd)/plugins/platforms/qwindows${SUFFIX}.dll" + for CONFIGURATION in ${CONFIGURATIONS[@]}; do + if [ $CONFIGURATION == "Debug" ]; then + DLLSUFFIX="d" + else + DLLSUFFIX="" + fi + add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll + add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll" + done echo Done. else QT_SDK="C:/Qt/5.13/msvc2017${SUFFIX}" add_cmake_opts -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \ -DCMAKE_PREFIX_PATH="$QT_SDK" - if [ $CONFIGURATION == "Debug" ]; then - SUFFIX="d" - else - SUFFIX="" - fi - DIR=$(windowsPathAsUnix "${QT_SDK}") - add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll - add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll" + for CONFIGURATION in ${CONFIGURATIONS[@]}; do + if [ $CONFIGURATION == "Debug" ]; then + DLLSUFFIX="d" + else + DLLSUFFIX="" + fi + DIR=$(windowsPathAsUnix "${QT_SDK}") + add_runtime_dlls $CONFIGURATION "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll + add_qt_platform_dlls $CONFIGURATION "${DIR}/plugins/platforms/qwindows${DLLSUFFIX}.dll" + done echo Done. fi } @@ -817,7 +903,34 @@ printf "SDL 2.0.12... " eval 7z x -y SDL2-2.0.12.zip $STRIP fi export SDL2DIR="$(real_pwd)/SDL2-2.0.12" - add_runtime_dlls "$(pwd)/SDL2-2.0.12/lib/x${ARCHSUFFIX}/SDL2.dll" + for config in ${CONFIGURATIONS[@]}; do + add_runtime_dlls $config "$(pwd)/SDL2-2.0.12/lib/x${ARCHSUFFIX}/SDL2.dll" + done + echo Done. +} +cd $DEPS +echo +# LZ4 +printf "LZ4 1.9.2... " +{ + if [ -d LZ4_1.9.2 ]; then + printf "Exists. " + elif [ -z $SKIP_EXTRACT ]; then + rm -rf LZ4_1.9.2 + eval 7z x -y lz4_win${BITS}_v1_9_2.7z -o./LZ4_1.9.2 $STRIP + fi + export LZ4DIR="$(real_pwd)/LZ4_1.9.2" + add_cmake_opts -DLZ4_INCLUDE_DIR="${LZ4DIR}/include" \ + -DLZ4_LIBRARY="${LZ4DIR}/lib/liblz4.lib" + for CONFIGURATION in ${CONFIGURATIONS[@]}; do + if [ $CONFIGURATION == "Debug" ]; then + LZ4_CONFIGURATION="Debug" + else + SUFFIX="" + LZ4_CONFIGURATION="Release" + fi + add_runtime_dlls $CONFIGURATION "$(pwd)/LZ4_1.9.2/bin/${LZ4_CONFIGURATION}/liblz4.dll" + done echo Done. } cd $DEPS @@ -828,41 +941,51 @@ if [ ! -z $TEST_FRAMEWORK ]; then printf "Google test 1.10.0 ..." cd googletest - if [ ! -d build ]; then - mkdir build - fi + mkdir -p build${MSVC_REAL_YEAR} - cd build + cd build${MSVC_REAL_YEAR} GOOGLE_INSTALL_ROOT="${DEPS_INSTALL}/GoogleTest" - if [ $CONFIGURATION == "Debug" ]; then + + for CONFIGURATION in ${CONFIGURATIONS[@]}; do + # FindGMock.cmake mentions Release explicitly, but not RelWithDebInfo. Only one optimised library config can be used, so go for the safer one. + GTEST_CONFIG=$([ $CONFIGURATION == "RelWithDebInfo" ] && echo "Release" || echo "$CONFIGURATION" ) + if [ $GTEST_CONFIG == "Debug" ]; then DEBUG_SUFFIX="d" else DEBUG_SUFFIX="" - fi + fi - if [ ! -d $GOOGLE_INSTALL_ROOT ]; then + if [ ! -f "$GOOGLE_INSTALL_ROOT/lib/gtest${DEBUG_SUFFIX}.lib" ]; then + # Always use MSBuild solution files as they don't need the environment activating + cmake .. -DCMAKE_USE_WIN32_THREADS_INIT=1 -G "Visual Studio $MSVC_REAL_VER $MSVC_REAL_YEAR$([ $BITS -eq 64 ] && [ $MSVC_REAL_VER -lt 16 ] && echo " Win64")" $([ $MSVC_REAL_VER -ge 16 ] && echo "-A $([ $BITS -eq 64 ] && echo "x64" || echo "Win32")") -DBUILD_SHARED_LIBS=1 + cmake --build . --config "${GTEST_CONFIG}" + cmake --install . --config "${GTEST_CONFIG}" --prefix "${GOOGLE_INSTALL_ROOT}" + fi - cmake .. -DCMAKE_BUILD_TYPE="${CONFIGURATION}" -DCMAKE_INSTALL_PREFIX="${GOOGLE_INSTALL_ROOT}" -DCMAKE_USE_WIN32_THREADS_INIT=1 -G "${GENERATOR}" -DBUILD_SHARED_LIBS=1 - cmake --build . --config "${CONFIGURATION}" - cmake --build . --target install --config "${CONFIGURATION}" - - add_runtime_dlls "${GOOGLE_INSTALL_ROOT}\bin\gtest_main${DEBUG_SUFFIX}.dll" - add_runtime_dlls "${GOOGLE_INSTALL_ROOT}\bin\gtest${DEBUG_SUFFIX}.dll" - add_runtime_dlls "${GOOGLE_INSTALL_ROOT}\bin\gmock_main${DEBUG_SUFFIX}.dll" - add_runtime_dlls "${GOOGLE_INSTALL_ROOT}\bin\gmock${DEBUG_SUFFIX}.dll" - fi + add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gtest_main${DEBUG_SUFFIX}.dll" + add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gtest${DEBUG_SUFFIX}.dll" + add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gmock_main${DEBUG_SUFFIX}.dll" + add_runtime_dlls $CONFIGURATION "${GOOGLE_INSTALL_ROOT}\bin\gmock${DEBUG_SUFFIX}.dll" + done add_cmake_opts -DBUILD_UNITTESTS=yes # FindGTest and FindGMock do not work perfectly on Windows # but we can help them by telling them everything we know about installation add_cmake_opts -DGMOCK_ROOT="$GOOGLE_INSTALL_ROOT" add_cmake_opts -DGTEST_ROOT="$GOOGLE_INSTALL_ROOT" - add_cmake_opts -DGTEST_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gtest${DEBUG_SUFFIX}.lib" - add_cmake_opts -DGTEST_MAIN_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gtest_main${DEBUG_SUFFIX}.lib" - add_cmake_opts -DGMOCK_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gmock${DEBUG_SUFFIX}.lib" - add_cmake_opts -DGMOCK_MAIN_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gmock_main${DEBUG_SUFFIX}.lib" + add_cmake_opts -DGTEST_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gtest.lib" + add_cmake_opts -DGTEST_MAIN_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gtest_main.lib" + add_cmake_opts -DGMOCK_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gmock.lib" + add_cmake_opts -DGMOCK_MAIN_LIBRARY="$GOOGLE_INSTALL_ROOT/lib/gmock_main.lib" + add_cmake_opts -DGTEST_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gtestd.lib" + add_cmake_opts -DGTEST_MAIN_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gtest_maind.lib" + add_cmake_opts -DGMOCK_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gmockd.lib" + add_cmake_opts -DGMOCK_MAIN_LIBRARY_DEBUG="$GOOGLE_INSTALL_ROOT/lib/gmock_maind.lib" add_cmake_opts -DGTEST_LINKED_AS_SHARED_LIBRARY=True + add_cmake_opts -DGTEST_LIBRARY_TYPE=SHARED + add_cmake_opts -DGTEST_MAIN_LIBRARY_TYPE=SHARED + echo Done. fi @@ -926,45 +1049,47 @@ if [ ! -z $CI ]; then fi # NOTE: Disable this when/if we want to run test cases #if [ -z $CI ]; then - echo "- Copying Runtime DLLs..." - DLL_PREFIX="" - if [ -z $SINGLE_CONFIG ]; then - mkdir -p $BUILD_CONFIG - DLL_PREFIX="$BUILD_CONFIG/" - fi - for DLL in $RUNTIME_DLLS; do - TARGET="$(basename "$DLL")" - if [[ "$DLL" == *":"* ]]; then - originalIFS="$IFS" - IFS=':'; SPLIT=( ${DLL} ); IFS=$originalIFS - DLL=${SPLIT[0]} - TARGET=${SPLIT[1]} + for CONFIGURATION in ${CONFIGURATIONS[@]}; do + echo "- Copying Runtime DLLs for $CONFIGURATION..." + DLL_PREFIX="" + if [ -z $SINGLE_CONFIG ]; then + mkdir -p $CONFIGURATION + DLL_PREFIX="$CONFIGURATION/" fi - echo " ${TARGET}." - cp "$DLL" "${DLL_PREFIX}$TARGET" + for DLL in ${RUNTIME_DLLS[$CONFIGURATION]}; do + TARGET="$(basename "$DLL")" + if [[ "$DLL" == *":"* ]]; then + originalIFS="$IFS" + IFS=':'; SPLIT=( ${DLL} ); IFS=$originalIFS + DLL=${SPLIT[0]} + TARGET=${SPLIT[1]} + fi + echo " ${TARGET}." + cp "$DLL" "${DLL_PREFIX}$TARGET" + done + echo + echo "- OSG Plugin DLLs..." + mkdir -p ${DLL_PREFIX}osgPlugins-3.6.5 + for DLL in ${OSG_PLUGINS[$CONFIGURATION]}; do + echo " $(basename $DLL)." + cp "$DLL" ${DLL_PREFIX}osgPlugins-3.6.5 + done + echo + echo "- Qt Platform DLLs..." + mkdir -p ${DLL_PREFIX}platforms + for DLL in ${QT_PLATFORMS[$CONFIGURATION]}; do + echo " $(basename $DLL)" + cp "$DLL" "${DLL_PREFIX}platforms" + done + echo done - echo - echo "- OSG Plugin DLLs..." - mkdir -p ${DLL_PREFIX}osgPlugins-3.6.5 - for DLL in $OSG_PLUGINS; do - echo " $(basename $DLL)." - cp "$DLL" ${DLL_PREFIX}osgPlugins-3.6.5 - done - echo - echo "- Qt Platform DLLs..." - mkdir -p ${DLL_PREFIX}platforms - for DLL in $QT_PLATFORMS; do - echo " $(basename $DLL)" - cp "$DLL" "${DLL_PREFIX}platforms" - done - echo #fi if [ -n "$ACTIVATE_MSVC" ]; then echo -n "- Activating MSVC in the current shell... " command -v vswhere >/dev/null 2>&1 || { echo "Error: vswhere is not on the path."; wrappedExit 1; } - MSVC_INSTALLATION_PATH=$(vswhere -legacy -products '*' -version "[$MSVC_VER,$(awk "BEGIN { print $MSVC_REAL_VER + 1; exit }"))" -property installationPath) + MSVC_INSTALLATION_PATH=$(vswhere -products '*' -version "[$MSVC_REAL_VER,$(awk "BEGIN { print $MSVC_REAL_VER + 1; exit }"))" -property installationPath) if [ -z "$MSVC_INSTALLATION_PATH" ]; then echo "vswhere was unable to find MSVC $MSVC_DISPLAY_YEAR" wrappedExit 1 diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 15d6862db..e11ef1b58 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -13,14 +13,14 @@ cmake \ -D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \ -D CMAKE_C_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ -D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ --D CMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" \ +-D CMAKE_CXX_FLAGS="-stdlib=libc++" \ -D CMAKE_C_FLAGS_RELEASE="-g -O0" \ -D CMAKE_CXX_FLAGS_RELEASE="-g -O0" \ --D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \ +-D CMAKE_OSX_DEPLOYMENT_TARGET="10.12" \ -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 \ diff --git a/CI/build_googletest.sh b/CI/build_googletest.sh index 0ffda7f9b..a9a50fee7 100755 --- a/CI/build_googletest.sh +++ b/CI/build_googletest.sh @@ -1,13 +1,17 @@ -#!/bin/sh -e +#!/bin/sh -ex git clone -b release-1.10.0 https://github.com/google/googletest.git cd googletest mkdir build cd build cmake \ + -D CMAKE_C_COMPILER="${CC}" \ + -D CMAKE_CXX_COMPILER="${CXX}" \ + -D CMAKE_C_COMPILER_LAUNCHER=ccache \ + -D CMAKE_CXX_COMPILER_LAUNCHER=ccache \ -D CMAKE_BUILD_TYPE="${CONFIGURATION}" \ - -D CMAKE_INSTALL_PREFIX=. \ + -D CMAKE_INSTALL_PREFIX="${GOOGLETEST_DIR}" \ -G "${GENERATOR}" \ .. -cmake --build . --config "${CONFIGURATION}" -cmake --build . --target install --config "${CONFIGURATION}" +cmake --build . --config "${CONFIGURATION}" -- -j $(nproc) +cmake --install . --config "${CONFIGURATION}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 82ca38782..7ae9c21e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,11 @@ +project(OpenMW) +cmake_minimum_required(VERSION 3.1.0) + +# for link time optimization, remove if cmake version is >= 3.9 +if(POLICY CMP0069) + cmake_policy(SET CMP0069 NEW) +endif() + # Apps and tools option(BUILD_OPENMW "Build OpenMW" ON) option(BUILD_LAUNCHER "Build Launcher" ON) @@ -14,17 +22,14 @@ option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF) option(BULLET_USE_DOUBLES "Use double precision for Bullet" OFF) +set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 and up. + if (NOT BUILD_LAUNCHER AND NOT BUILD_OPENCS AND NOT BUILD_WIZARD) set(USE_QT FALSE) else() set(USE_QT TRUE) endif() -# set the minimum required version across the board -cmake_minimum_required(VERSION 3.1.0) - -project(OpenMW) - # If the user doesn't supply a CMAKE_BUILD_TYPE via command line, choose one for them. IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING @@ -59,7 +64,7 @@ set(OPENMW_VERSION_COMMITDATE "") set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") -set(OPENMW_DOC_BASEURL "https://openmw.readthedocs.io/en/master/") +set(OPENMW_DOC_BASEURL "https://openmw.readthedocs.io/en/stable/") set(GIT_CHECKOUT FALSE) if(EXISTS ${PROJECT_SOURCE_DIR}/.git) @@ -98,6 +103,7 @@ option(OSG_STATIC "Link static build of OpenSceneGraph into the binaries" FALSE) option(QT_STATIC "Link static build of QT into the binaries" FALSE) option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE) +option(OPENMW_LTO_BUILD "Build OpenMW with Link-Time Optimization (Needs ~2GB of RAM)" OFF) # what is necessary to build documentation IF( BUILD_DOCS ) @@ -111,7 +117,6 @@ option(OPENMW_OSX_DEPLOYMENT OFF) if (MSVC) option(OPENMW_MP_BUILD "Build OpenMW with /MP flag" OFF) - option(OPENMW_LTO_BUILD "Build OpenMW with Link-Time Optimization (Needs ~2GB of RAM)" OFF) endif() # Set up common paths @@ -148,6 +153,8 @@ endif() # Dependencies find_package(OpenGL REQUIRED) +find_package(LZ4 REQUIRED) + if (USE_QT) find_package(Qt5Core 5.12 REQUIRED) find_package(Qt5Widgets REQUIRED) @@ -388,9 +395,29 @@ if (NOT WIN32 AND NOT APPLE) endif() # CXX Compiler settings -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) + +if(OPENMW_LTO_BUILD) + if(NOT CMAKE_VERSION VERSION_LESS 3.9) + include(CheckIPOSupported) + check_ipo_supported(RESULT HAVE_IPO OUTPUT HAVE_IPO_OUTPUT) + if(HAVE_IPO) + message(STATUS "LTO enabled for Release configuration.") + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) + else() + message(WARNING "Requested option OPENMW_LTO_BUILD not supported by this compiler: ${HAVE_IPO_OUTPUT}") + if(MSVC) + message(STATUS "Note: Flags used to be set manually for this setting with MSVC. We now rely on CMake for this. Upgrade CMake to at least 3.13 to re-enable this setting.") + endif() + endif() + else() + message(WARNING "Requested option OPENMW_LTO_BUILD not supported by this cmake version: ${CMAKE_VERSION}. Upgrade CMake to at least 3.9 to enable support for certain compilers. Newer CMake versions support more compilers.") + endif() +endif() + + if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -std=c++14 -pedantic -Wno-long-long") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -pedantic -Wno-long-long") add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS=ON ) if (APPLE) @@ -407,166 +434,14 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.6) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter") endif() -elseif (MSVC) - # Enable link-time code generation globally for all linking - if (OPENMW_LTO_BUILD) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") - set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG") - endif() + if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 5.0) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override") + endif() +elseif (MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE") endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) -IF(NOT WIN32 AND NOT APPLE) - # Linux installation - - # Install binaries - IF(BUILD_OPENMW) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_OPENMW) - IF(BUILD_LAUNCHER) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-launcher" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_LAUNCHER) - IF(BUILD_BSATOOL) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_BSATOOL) - IF(BUILD_ESMTOOL) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_ESMTOOL) - IF(BUILD_NIFTEST) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/niftest" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_NIFTEST) - IF(BUILD_MWINIIMPORTER) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-iniimporter" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_MWINIIMPORTER) - IF(BUILD_ESSIMPORTER) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-essimporter" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_ESSIMPORTER) - IF(BUILD_OPENCS) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-cs" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_OPENCS) - IF(BUILD_WIZARD) - INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-wizard" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_WIZARD) - - # Install licenses - INSTALL(FILES "files/mygui/DejaVu Font License.txt" DESTINATION "${LICDIR}" ) - - # Install icon and desktop file - INSTALL(FILES "${OpenMW_BINARY_DIR}/org.openmw.launcher.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw") - INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/metainfo" COMPONENT "openmw") - IF(BUILD_OPENCS) - INSTALL(FILES "${OpenMW_BINARY_DIR}/org.openmw.cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs") - ENDIF(BUILD_OPENCS) - - # Install global configuration files - INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") - INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw") - INSTALL(FILES "${OpenMW_BINARY_DIR}/resources/version" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") - INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") - - IF(BUILD_OPENCS) - INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") - ENDIF(BUILD_OPENCS) - - # Install resources - INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" COMPONENT "Resources") - INSTALL(DIRECTORY DESTINATION "${DATADIR}/data" COMPONENT "Resources") -ENDIF(NOT WIN32 AND NOT APPLE) - -if(WIN32) - FILE(GLOB dll_files_debug "${OpenMW_BINARY_DIR}/Debug/*.dll") - FILE(GLOB dll_files_release "${OpenMW_BINARY_DIR}/Release/*.dll") - INSTALL(FILES ${dll_files_debug} DESTINATION "." CONFIGURATIONS Debug) - INSTALL(FILES ${dll_files_release} DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) - INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg" CONFIGURATIONS Debug) - INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg" CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) - INSTALL(FILES "${OpenMW_SOURCE_DIR}/CHANGELOG.md" DESTINATION "." RENAME "CHANGELOG.txt") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/README.md" DESTINATION "." RENAME "README.txt") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/LICENSE" DESTINATION "." RENAME "LICENSE.txt") - INSTALL(FILES - "${OpenMW_SOURCE_DIR}/files/mygui/DejaVu Font License.txt" - DESTINATION ".") - INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/settings-default.cfg" DESTINATION "." CONFIGURATIONS Debug) - INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/settings-default.cfg" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) - INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Debug) - INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) - - INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Debug/platforms" DESTINATION "." CONFIGURATIONS Debug) - INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Release/platforms" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) - - INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Debug/resources" DESTINATION "." CONFIGURATIONS Debug) - INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/Release/resources" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) - - FILE(GLOB plugin_dir_debug "${OpenMW_BINARY_DIR}/Debug/osgPlugins-*") - FILE(GLOB plugin_dir_release "${OpenMW_BINARY_DIR}/Release/osgPlugins-*") - INSTALL(DIRECTORY ${plugin_dir_debug} DESTINATION "." CONFIGURATIONS Debug) - INSTALL(DIRECTORY ${plugin_dir_release} DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) - - SET(CPACK_GENERATOR "NSIS") - SET(CPACK_PACKAGE_NAME "OpenMW") - SET(CPACK_PACKAGE_VENDOR "OpenMW.org") - SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) - SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) - SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR}) - SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) - SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW") - IF(BUILD_LAUNCHER) - SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-launcher;OpenMW Launcher") - ENDIF(BUILD_LAUNCHER) - IF(BUILD_OPENCS) - SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-cs;OpenMW Construction Set") - ENDIF(BUILD_OPENCS) - IF(BUILD_WIZARD) - SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-wizard;OpenMW Wizard") - ENDIF(BUILD_WIZARD) - SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\README.txt'") - SET(CPACK_NSIS_DELETE_ICONS_EXTRA " - !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP - Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Readme.lnk\\\" - ") - SET(CPACK_RESOURCE_FILE_README "${OpenMW_SOURCE_DIR}/README.md") - SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/README.md") - SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") - SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}") - SET(CPACK_NSIS_HELP_LINK "https:\\\\\\\\www.openmw.org") - SET(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\www.openmw.org") - SET(CPACK_NSIS_INSTALLED_ICON_NAME "openmw-launcher.exe") - SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "openmw-launcher.exe") - SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico") - SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico") - SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp") - - SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe") - if(EXISTS ${VCREDIST32}) - INSTALL(FILES ${VCREDIST32} DESTINATION "redist") - SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" ) - endif(EXISTS ${VCREDIST32}) - - SET(VCREDIST64 "${OpenMW_BINARY_DIR}/vcredist_x64.exe") - if(EXISTS ${VCREDIST64}) - INSTALL(FILES ${VCREDIST64} DESTINATION "redist") - SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x64.exe\\\" /q'" ) - endif(EXISTS ${VCREDIST64}) - - SET(OALREDIST "${OpenMW_BINARY_DIR}/oalinst.exe") - if(EXISTS ${OALREDIST}) - INSTALL(FILES ${OALREDIST} DESTINATION "redist") - SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS} - ExecWait '\\\"$INSTDIR\\\\redist\\\\oalinst.exe\\\" /s'" ) - endif(EXISTS ${OALREDIST}) - - if(CMAKE_CL_64) - SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") - endif() - - include(CPack) -endif(WIN32) - # Extern set(RECASTNAVIGATION_STATIC ON CACHE BOOL "Build recastnavigation static libraries") @@ -735,6 +610,10 @@ if (WIN32) set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") set_target_properties(osg-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") + + if (MSVC_VERSION GREATER_EQUAL 1915 AND MSVC_VERSION LESS 1920) + target_compile_definitions(components INTERFACE _ENABLE_EXTENDED_ALIGNED_STORAGE) + endif() if (BUILD_BSATOOL) set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") @@ -886,7 +765,164 @@ if (OPENMW_OSX_DEPLOYMENT AND APPLE) fixup_bundle(\"${INSTALLED_OPENCS_APP}\" \"${OPENCS_PLUGINS}\" \"\") " COMPONENT Runtime) include(CPack) -endif () +elseif(NOT APPLE) + get_generator_is_multi_config(multi_config) + if (multi_config) + SET(INSTALL_SOURCE "${OpenMW_BINARY_DIR}/$") + else () + SET(INSTALL_SOURCE "${OpenMW_BINARY_DIR}") + endif () + + if(WIN32) + INSTALL(DIRECTORY "${INSTALL_SOURCE}/" DESTINATION "." FILES_MATCHING PATTERN "*.dll" + PATTERN "deps" EXCLUDE + PATTERN "apps" EXCLUDE + PATTERN "CMakeFiles" EXCLUDE + PATTERN "components" EXCLUDE + PATTERN "docs" EXCLUDE + PATTERN "extern" EXCLUDE + PATTERN "files" EXCLUDE + PATTERN "Testing" EXCLUDE) + INSTALL(DIRECTORY "${INSTALL_SOURCE}/" DESTINATION "." CONFIGURATIONS Debug;RelWithDebInfo FILES_MATCHING PATTERN "*.pdb" + PATTERN "deps" EXCLUDE + PATTERN "apps" EXCLUDE + PATTERN "CMakeFiles" EXCLUDE + PATTERN "components" EXCLUDE + PATTERN "docs" EXCLUDE + PATTERN "extern" EXCLUDE + PATTERN "files" EXCLUDE + PATTERN "Testing" EXCLUDE) + INSTALL(FILES "${INSTALL_SOURCE}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/CHANGELOG.md" DESTINATION "." RENAME "CHANGELOG.txt") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/README.md" DESTINATION "." RENAME "README.txt") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/LICENSE" DESTINATION "." RENAME "LICENSE.txt") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/mygui/DejaVuFontLicense.txt" DESTINATION ".") + INSTALL(FILES "${INSTALL_SOURCE}/settings-default.cfg" DESTINATION ".") + INSTALL(FILES "${INSTALL_SOURCE}/gamecontrollerdb.txt" DESTINATION ".") + + INSTALL(DIRECTORY "${INSTALL_SOURCE}/resources" DESTINATION ".") + + SET(CPACK_GENERATOR "NSIS") + SET(CPACK_PACKAGE_NAME "OpenMW") + SET(CPACK_PACKAGE_VENDOR "OpenMW.org") + SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) + SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) + SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR}) + SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) + SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW") + IF(BUILD_LAUNCHER) + SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-launcher;OpenMW Launcher") + ENDIF(BUILD_LAUNCHER) + IF(BUILD_OPENCS) + SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-cs;OpenMW Construction Set") + ENDIF(BUILD_OPENCS) + IF(BUILD_WIZARD) + SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-wizard;OpenMW Wizard") + ENDIF(BUILD_WIZARD) + SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\README.txt'") + SET(CPACK_NSIS_DELETE_ICONS_EXTRA " + !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP + Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Readme.lnk\\\" + ") + SET(CPACK_RESOURCE_FILE_README "${OpenMW_SOURCE_DIR}/README.md") + SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/README.md") + SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") + SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}") + SET(CPACK_NSIS_HELP_LINK "https:\\\\\\\\www.openmw.org") + SET(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\www.openmw.org") + SET(CPACK_NSIS_INSTALLED_ICON_NAME "openmw-launcher.exe") + SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "openmw-launcher.exe") + SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico") + SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico") + SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp") + + SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe") + if(EXISTS ${VCREDIST32}) + INSTALL(FILES ${VCREDIST32} DESTINATION "redist") + SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" ) + endif(EXISTS ${VCREDIST32}) + + SET(VCREDIST64 "${OpenMW_BINARY_DIR}/vcredist_x64.exe") + if(EXISTS ${VCREDIST64}) + INSTALL(FILES ${VCREDIST64} DESTINATION "redist") + SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x64.exe\\\" /q'" ) + endif(EXISTS ${VCREDIST64}) + + SET(OALREDIST "${OpenMW_BINARY_DIR}/oalinst.exe") + if(EXISTS ${OALREDIST}) + INSTALL(FILES ${OALREDIST} DESTINATION "redist") + SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS} + ExecWait '\\\"$INSTDIR\\\\redist\\\\oalinst.exe\\\" /s'" ) + endif(EXISTS ${OALREDIST}) + + if(CMAKE_CL_64) + SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") + endif() + + include(CPack) + else(WIN32) + # Linux installation + + # Install binaries + IF(BUILD_OPENMW) + IF(ANDROID) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/libopenmw.so" DESTINATION "${BINDIR}" ) + ELSE(ANDROID) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw" DESTINATION "${BINDIR}" ) + ENDIF(ANDROID) + ENDIF(BUILD_OPENMW) + IF(BUILD_LAUNCHER) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw-launcher" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_LAUNCHER) + IF(BUILD_BSATOOL) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/bsatool" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_BSATOOL) + IF(BUILD_ESMTOOL) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/esmtool" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_ESMTOOL) + IF(BUILD_NIFTEST) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/niftest" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_NIFTEST) + IF(BUILD_MWINIIMPORTER) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw-iniimporter" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_MWINIIMPORTER) + IF(BUILD_ESSIMPORTER) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw-essimporter" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_ESSIMPORTER) + IF(BUILD_OPENCS) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw-cs" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_OPENCS) + IF(BUILD_WIZARD) + INSTALL(PROGRAMS "${INSTALL_SOURCE}/openmw-wizard" DESTINATION "${BINDIR}" ) + ENDIF(BUILD_WIZARD) + + # Install licenses + INSTALL(FILES "files/mygui/DejaVuFontLicense.txt" DESTINATION "${LICDIR}" ) + + # Install icon and desktop file + INSTALL(FILES "${OpenMW_BINARY_DIR}/org.openmw.launcher.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw") + INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/metainfo" COMPONENT "openmw") + IF(BUILD_OPENCS) + INSTALL(FILES "${OpenMW_BINARY_DIR}/org.openmw.cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs") + ENDIF(BUILD_OPENCS) + + # Install global configuration files + INSTALL(FILES "${INSTALL_SOURCE}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") + INSTALL(FILES "${INSTALL_SOURCE}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw") + INSTALL(FILES "${INSTALL_SOURCE}/resources/version" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") + INSTALL(FILES "${INSTALL_SOURCE}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") + + IF(BUILD_OPENCS) + INSTALL(FILES "${INSTALL_SOURCE}/openmw-cs.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") + ENDIF(BUILD_OPENCS) + + # Install resources + INSTALL(DIRECTORY "${INSTALL_SOURCE}/resources" DESTINATION "${DATADIR}" COMPONENT "Resources") + INSTALL(DIRECTORY DESTINATION "${DATADIR}/data" COMPONENT "Resources") + endif(WIN32) +endif(OPENMW_OSX_DEPLOYMENT AND APPLE) # Doxygen Target -- simply run 'make doc' or 'make doc_pages' # output directory for 'make doc' is "${OpenMW_BINARY_DIR}/docs/Doxygen" diff --git a/README.md b/README.md index 4cd5a434e..746ee1482 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ OpenMW also comes with OpenMW-CS, a replacement for Bethesda's Construction Set. * IRC: #openmw on irc.freenode.net Font Licenses: -* DejaVuLGCSansMono.ttf: custom (see [files/mygui/DejaVu Font License.txt](https://github.com/OpenMW/openmw/blob/master/files/mygui/DejaVu%20Font%20License.txt) for more information) +* DejaVuLGCSansMono.ttf: custom (see [files/mygui/DejaVuFontLicense.txt](https://github.com/OpenMW/openmw/blob/master/files/mygui/DejaVuFontLicense.txt) for more information) Current Status -------------- diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index e9db74cae..050ab8d21 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -4,9 +4,12 @@ #include #include #include +#include #include #include +#include + Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings, Settings::Manager &engineSettings, QWidget *parent) @@ -19,15 +22,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) { @@ -55,142 +58,276 @@ void Launcher::AdvancedPage::on_runScriptAfterStartupBrowseButton_clicked() runScriptAfterStartupField->setText(path); } +namespace +{ + constexpr double CellSizeInUnits = 8192; + + double convertToCells(double unitRadius) + { + return std::round((unitRadius / 0.93 + 1024) / CellSizeInUnits); + } + + double convertToUnits(double CellGridRadius) + { + return (CellSizeInUnits * CellGridRadius - 1024) * 0.93; + } +} + bool Launcher::AdvancedPage::loadSettings() { - // Testing - bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1; - if (skipMenu) { - skipMenuCheckBox->setCheckState(Qt::Checked); - } - startDefaultCharacterAtLabel->setEnabled(skipMenu); - startDefaultCharacterAtField->setEnabled(skipMenu); - - startDefaultCharacterAtField->setText(mGameSettings.value("start")); - runScriptAfterStartupField->setText(mGameSettings.value("script-run")); - - // Game Settings - loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); - loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); - loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); - loadSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game"); - loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); - loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game"); - loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game"); - int unarmedFactorsStrengthIndex = mEngineSettings.getInt("strength influences hand to hand", "Game"); - if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2) - unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex); - loadSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game"); - loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game"); - loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game"); - connect(animSourcesCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotAnimSourcesToggled(bool))); - loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game"); - if (animSourcesCheckBox->checkState()) + // Game mechanics { - loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game"); - loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game"); + loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); + loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); + loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); + loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); + loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game"); + loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game"); + loadSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game"); + loadSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game"); + loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game"); + loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game"); + loadSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game"); + loadSettingBool(avoidCollisionsCheckBox, "NPCs avoid collisions", "Game"); + int unarmedFactorsStrengthIndex = mEngineSettings.getInt("strength influences hand to hand", "Game"); + if (unarmedFactorsStrengthIndex >= 0 && unarmedFactorsStrengthIndex <= 2) + unarmedFactorsStrengthComboBox->setCurrentIndex(unarmedFactorsStrengthIndex); + loadSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game"); + loadSettingBool(enableNavigatorCheckBox, "enable", "Navigator"); + int numPhysicsThreads = mEngineSettings.getInt("async num threads", "Physics"); + if (numPhysicsThreads >= 0) + physicsThreadsSpinBox->setValue(numPhysicsThreads); } - loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game"); - loadSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game"); - // Input Settings - loadSettingBool(grabCursorCheckBox, "grab cursor", "Input"); - loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); + // Visuals + { + loadSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders"); + loadSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders"); + loadSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders"); + loadSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders"); + loadSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders"); + loadSettingBool(radialFogCheckBox, "radial fog", "Shaders"); + loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game"); + connect(animSourcesCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotAnimSourcesToggled(bool))); + loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game"); + if (animSourcesCheckBox->checkState()) + { + loadSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game"); + loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game"); + } + loadSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game"); + loadSettingBool(smoothMovementCheckBox, "smooth movement", "Game"); - // Saves Settings - loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); - maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves")); + const bool distantTerrain = mEngineSettings.getBool("distant terrain", "Terrain"); + const bool objectPaging = mEngineSettings.getBool("object paging", "Terrain"); + if (distantTerrain && objectPaging) { + distantLandCheckBox->setCheckState(Qt::Checked); + } - // User Interface Settings - loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); - loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game"); - loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); - loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); - loadSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI"); - int showOwnedIndex = mEngineSettings.getInt("show owned", "Game"); - // Match the index with the option (only 0, 1, 2, or 3 are valid). Will default to 0 if invalid. - if (showOwnedIndex >= 0 && showOwnedIndex <= 3) - showOwnedComboBox->setCurrentIndex(showOwnedIndex); + loadSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain"); + viewingDistanceComboBox->setValue(convertToCells(mEngineSettings.getInt("viewing distance", "Camera"))); + } - // Other Settings - QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); - if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) - screenshotFormatComboBox->addItem(screenshotFormatString); - screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString)); + // Camera + { + loadSettingBool(viewOverShoulderCheckBox, "view over shoulder", "Camera"); + connect(viewOverShoulderCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotViewOverShoulderToggled(bool))); + viewOverShoulderVerticalLayout->setEnabled(viewOverShoulderCheckBox->checkState()); + loadSettingBool(autoSwitchShoulderCheckBox, "auto switch shoulder", "Camera"); + loadSettingBool(previewIfStandStillCheckBox, "preview if stand still", "Camera"); + loadSettingBool(deferredPreviewRotationCheckBox, "deferred preview rotation", "Camera"); + loadSettingBool(headBobbingCheckBox, "head bobbing", "Camera"); + defaultShoulderComboBox->setCurrentIndex( + mEngineSettings.getVector2("view over shoulder offset", "Camera").x() >= 0 ? 0 : 1); + } + // Interface Changes + { + loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); + loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game"); + loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); + loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); + loadSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI"); + int showOwnedIndex = mEngineSettings.getInt("show owned", "Game"); + // Match the index with the option (only 0, 1, 2, or 3 are valid). Will default to 0 if invalid. + if (showOwnedIndex >= 0 && showOwnedIndex <= 3) + showOwnedComboBox->setCurrentIndex(showOwnedIndex); + } + + // Bug fixes + { + loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); + loadSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game"); + } + + // Miscellaneous + { + // Saves + loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); + maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves")); + + // Other Settings + QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); + if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) + screenshotFormatComboBox->addItem(screenshotFormatString); + screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString)); + } + + // Testing + { + loadSettingBool(grabCursorCheckBox, "grab cursor", "Input"); + + bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1; + if (skipMenu) + { + skipMenuCheckBox->setCheckState(Qt::Checked); + } + startDefaultCharacterAtLabel->setEnabled(skipMenu); + startDefaultCharacterAtField->setEnabled(skipMenu); + + startDefaultCharacterAtField->setText(mGameSettings.value("start")); + runScriptAfterStartupField->setText(mGameSettings.value("script-run")); + } return true; } void Launcher::AdvancedPage::saveSettings() { - // Ensure we only set the new settings if they changed. This is to avoid cluttering the - // user settings file (which by definition should only contain settings the user has touched) + // Game mechanics + { + saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); + saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); + saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); + saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); + saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game"); + saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game"); + saveSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game"); + saveSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game"); + saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game"); + saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game"); + saveSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game"); + saveSettingBool(avoidCollisionsCheckBox, "NPCs avoid collisions", "Game"); + int unarmedFactorsStrengthIndex = unarmedFactorsStrengthComboBox->currentIndex(); + if (unarmedFactorsStrengthIndex != mEngineSettings.getInt("strength influences hand to hand", "Game")) + mEngineSettings.setInt("strength influences hand to hand", "Game", unarmedFactorsStrengthIndex); + saveSettingBool(stealingFromKnockedOutCheckBox, "always allow stealing from knocked out actors", "Game"); + saveSettingBool(enableNavigatorCheckBox, "enable", "Navigator"); + int numPhysicsThreads = physicsThreadsSpinBox->value(); + if (numPhysicsThreads != mEngineSettings.getInt("async num threads", "Physics")) + mEngineSettings.setInt("async num threads", "Physics", numPhysicsThreads); + } + + // Visuals + { + saveSettingBool(autoUseObjectNormalMapsCheckBox, "auto use object normal maps", "Shaders"); + saveSettingBool(autoUseObjectSpecularMapsCheckBox, "auto use object specular maps", "Shaders"); + saveSettingBool(autoUseTerrainNormalMapsCheckBox, "auto use terrain normal maps", "Shaders"); + saveSettingBool(autoUseTerrainSpecularMapsCheckBox, "auto use terrain specular maps", "Shaders"); + saveSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders"); + saveSettingBool(radialFogCheckBox, "radial fog", "Shaders"); + saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game"); + saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game"); + saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game"); + saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game"); + saveSettingBool(turnToMovementDirectionCheckBox, "turn to movement direction", "Game"); + saveSettingBool(smoothMovementCheckBox, "smooth movement", "Game"); + + const bool distantTerrain = mEngineSettings.getBool("distant terrain", "Terrain"); + const bool objectPaging = mEngineSettings.getBool("object paging", "Terrain"); + const bool wantDistantLand = distantLandCheckBox->checkState(); + if (wantDistantLand != (distantTerrain && objectPaging)) { + mEngineSettings.setBool("distant terrain", "Terrain", wantDistantLand); + mEngineSettings.setBool("object paging", "Terrain", wantDistantLand); + } + + saveSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain"); + double viewingDistance = viewingDistanceComboBox->value(); + if (viewingDistance != convertToCells(mEngineSettings.getInt("viewing distance", "Camera"))) + { + mEngineSettings.setInt("viewing distance", "Camera", convertToUnits(viewingDistance)); + } + } + + // Camera + { + saveSettingBool(viewOverShoulderCheckBox, "view over shoulder", "Camera"); + saveSettingBool(autoSwitchShoulderCheckBox, "auto switch shoulder", "Camera"); + saveSettingBool(previewIfStandStillCheckBox, "preview if stand still", "Camera"); + saveSettingBool(deferredPreviewRotationCheckBox, "deferred preview rotation", "Camera"); + saveSettingBool(headBobbingCheckBox, "head bobbing", "Camera"); + + osg::Vec2f shoulderOffset = mEngineSettings.getVector2("view over shoulder offset", "Camera"); + if (defaultShoulderComboBox->currentIndex() != (shoulderOffset.x() >= 0 ? 0 : 1)) + { + if (defaultShoulderComboBox->currentIndex() == 0) + shoulderOffset.x() = std::abs(shoulderOffset.x()); + else + shoulderOffset.x() = -std::abs(shoulderOffset.x()); + mEngineSettings.setVector2("view over shoulder offset", "Camera", shoulderOffset); + } + } + + // Interface Changes + { + saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); + saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game"); + saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); + saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); + saveSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI"); + int showOwnedCurrentIndex = showOwnedComboBox->currentIndex(); + if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game")) + mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex); + } + + // Bug fixes + { + saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); + saveSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game"); + } + + // Miscellaneous + { + // Saves Settings + saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); + int maximumQuicksaves = maximumQuicksavesComboBox->value(); + if (maximumQuicksaves != mEngineSettings.getInt("max quicksaves", "Saves")) + { + mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves); + } + + // Other Settings + std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString(); + if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General")) + mEngineSettings.setString("screenshot format", "General", screenshotFormatString); + } // Testing - int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked; - if (skipMenu != mGameSettings.value("skip-menu").toInt()) - mGameSettings.setValue("skip-menu", QString::number(skipMenu)); + { + saveSettingBool(grabCursorCheckBox, "grab cursor", "Input"); - QString startCell = startDefaultCharacterAtField->text(); - if (startCell != mGameSettings.value("start")) { - mGameSettings.setValue("start", startCell); + int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked; + if (skipMenu != mGameSettings.value("skip-menu").toInt()) + mGameSettings.setValue("skip-menu", QString::number(skipMenu)); + + QString startCell = startDefaultCharacterAtField->text(); + if (startCell != mGameSettings.value("start")) + { + mGameSettings.setValue("start", startCell); + } + QString scriptRun = runScriptAfterStartupField->text(); + if (scriptRun != mGameSettings.value("script-run")) + mGameSettings.setValue("script-run", scriptRun); } - QString scriptRun = runScriptAfterStartupField->text(); - if (scriptRun != mGameSettings.value("script-run")) - mGameSettings.setValue("script-run", scriptRun); - - // Game Settings - saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); - saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); - saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); - saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); - saveSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game"); - saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game"); - saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game"); - int unarmedFactorsStrengthIndex = unarmedFactorsStrengthComboBox->currentIndex(); - if (unarmedFactorsStrengthIndex != mEngineSettings.getInt("strength influences hand to hand", "Game")) - mEngineSettings.setInt("strength influences hand to hand", "Game", unarmedFactorsStrengthIndex); - saveSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game"); - saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game"); - saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game"); - saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game"); - saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game"); - saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game"); - saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game"); - saveSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game"); - - // Input Settings - saveSettingBool(grabCursorCheckBox, "grab cursor", "Input"); - saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input"); - - // Saves Settings - saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); - int maximumQuicksaves = maximumQuicksavesComboBox->value(); - if (maximumQuicksaves != mEngineSettings.getInt("max quicksaves", "Saves")) { - mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves); - } - - // User Interface Settings - saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game"); - saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game"); - saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game"); - saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game"); - saveSettingBool(changeDialogTopicsCheckBox, "color topic enable", "GUI"); - int showOwnedCurrentIndex = showOwnedComboBox->currentIndex(); - if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game")) - mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex); - - // Other Settings - std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString(); - if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General")) - mEngineSettings.setString("screenshot format", "General", screenshotFormatString); } -void Launcher::AdvancedPage::loadSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) { +void Launcher::AdvancedPage::loadSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) +{ if (mEngineSettings.getBool(setting, group)) checkbox->setCheckState(Qt::Checked); } -void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) { +void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) +{ bool cValue = checkbox->checkState(); if (cValue != mEngineSettings.getBool(setting, group)) mEngineSettings.setBool(setting, group, cValue); @@ -211,3 +348,8 @@ void Launcher::AdvancedPage::slotAnimSourcesToggled(bool checked) shieldSheathingCheckBox->setCheckState(Qt::Unchecked); } } + +void Launcher::AdvancedPage::slotViewOverShoulderToggled(bool checked) +{ + viewOverShoulderVerticalLayout->setEnabled(viewOverShoulderCheckBox->checkState()); +} diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index 3f5e5bfa7..bdf5af0c8 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" @@ -30,11 +32,14 @@ namespace Launcher void on_skipMenuCheckBox_stateChanged(int state); void on_runScriptAfterStartupBrowseButton_clicked(); void slotAnimSourcesToggled(bool checked); + void slotViewOverShoulderToggled(bool checked); private: 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/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 45c093bee..d7e7eabc5 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -13,12 +13,13 @@ #include +#include + #include -#include QString getAspect(int x, int y) { - int gcd = Misc::gcd (x, y); + int gcd = std::gcd (x, y); int xaspect = x / gcd; int yaspect = y / gcd; // special case: 8 : 5 is usually referred to as 16:10 @@ -65,16 +66,19 @@ bool Launcher::GraphicsPage::setupSDL() msgBox.setWindowTitle(tr("Error receiving number of screens")); msgBox.setIcon(QMessageBox::Critical); msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(tr("
SDL_GetNumDisplayModes failed:

") + QString::fromUtf8(SDL_GetError()) + "
"); + msgBox.setText(tr("
SDL_GetNumVideoDisplays failed:

") + QString::fromUtf8(SDL_GetError()) + "
"); msgBox.exec(); return false; } screenComboBox->clear(); + mResolutionsPerScreen.clear(); for (int i = 0; i < displays; i++) { + mResolutionsPerScreen.append(getAvailableResolutions(i)); screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1)); } + screenChanged(0); // Disconnect from SDL processes quitSDL(); @@ -331,7 +335,7 @@ void Launcher::GraphicsPage::screenChanged(int screen) { if (screen >= 0) { resolutionComboBox->clear(); - resolutionComboBox->addItems(getAvailableResolutions(screen)); + resolutionComboBox->addItems(mResolutionsPerScreen[screen]); } } diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 4ce5b584f..3b03a72bd 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -38,6 +38,8 @@ namespace Launcher Files::ConfigurationManager &mCfgMgr; Settings::Manager &mEngineSettings; + QVector mResolutionsPerScreen; + static QStringList getAvailableResolutions(int screen); static QRect getMaximumResolution(); diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index d87a43100..214d31dd4 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -84,7 +84,7 @@ namespace Launcher inline bool startProgram(const QString &name, bool detached = false) { return startProgram(name, QStringList(), detached); } bool startProgram(const QString &name, const QStringList &arguments, bool detached = false); - void closeEvent(QCloseEvent *event); + void closeEvent(QCloseEvent *event) override; PlayPage *mPlayPage; GraphicsPage *mGraphicsPage; diff --git a/apps/launcher/utils/lineedit.hpp b/apps/launcher/utils/lineedit.hpp index 2dd7da32b..50da73045 100644 --- a/apps/launcher/utils/lineedit.hpp +++ b/apps/launcher/utils/lineedit.hpp @@ -27,7 +27,7 @@ public: LineEdit(QWidget *parent = 0); protected: - void resizeEvent(QResizeEvent *); + void resizeEvent(QResizeEvent *) override; private slots: void updateClearButton(const QString &text); diff --git a/apps/launcher/utils/textinputdialog.hpp b/apps/launcher/utils/textinputdialog.hpp index 9eb9c717d..a9353956a 100644 --- a/apps/launcher/utils/textinputdialog.hpp +++ b/apps/launcher/utils/textinputdialog.hpp @@ -21,7 +21,7 @@ namespace Launcher inline LineEdit *lineEdit() { return mLineEdit; } void setOkButtonEnabled(bool enabled); - int exec(); + int exec() override; private: diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index dc9b98596..b20920904 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -233,8 +233,15 @@ target_link_libraries(openmw-cs Qt5::Widgets Qt5::Core Qt5::Network Qt5::OpenGL) if (WIN32) target_link_libraries(openmw-cs ${Boost_LOCALE_LIBRARY}) INSTALL(TARGETS openmw-cs RUNTIME DESTINATION ".") - INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/openmw-cs.cfg" DESTINATION "." CONFIGURATIONS Debug) - INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/openmw-cs.cfg" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel) + + get_generator_is_multi_config(multi_config) + if (multi_config) + SET(INSTALL_SOURCE "${OpenMW_BINARY_DIR}/$") + else () + SET(INSTALL_SOURCE "${OpenMW_BINARY_DIR}") + endif () + + INSTALL(FILES "${INSTALL_SOURCE}/openmw-cs.cfg" DESTINATION ".") endif() if (MSVC) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index 0473291ce..d1d4944cf 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -22,7 +22,7 @@ class Application : public QApplication { private: - bool notify (QObject *receiver, QEvent *event) + bool notify (QObject *receiver, QEvent *event) override { try { diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index 64afd0dd8..d3a0cc9b3 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -37,10 +37,10 @@ namespace CSMDoc OpenSaveStage (Document& document, SavingState& state, bool projectFile); ///< \param projectFile Saving the project file instead of the content file. - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -55,10 +55,10 @@ namespace CSMDoc WriteHeaderStage (Document& document, SavingState& state, bool simple); ///< \param simple Simplified header (used for project files). - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -75,10 +75,10 @@ namespace CSMDoc WriteCollectionStage (const CollectionT& collection, SavingState& state, CSMWorld::Scope scope = CSMWorld::Scope_Content); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -125,10 +125,10 @@ namespace CSMDoc WriteDialogueCollectionStage (Document& document, SavingState& state, bool journal); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -142,10 +142,10 @@ namespace CSMDoc WriteRefIdCollectionStage (Document& document, SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -159,10 +159,10 @@ namespace CSMDoc CollectionReferencesStage (Document& document, SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -175,10 +175,10 @@ namespace CSMDoc WriteCellCollectionStage (Document& document, SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -192,10 +192,10 @@ namespace CSMDoc WritePathgridCollectionStage (Document& document, SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -209,10 +209,10 @@ namespace CSMDoc WriteLandCollectionStage (Document& document, SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -226,10 +226,10 @@ namespace CSMDoc WriteLandTextureCollectionStage (Document& document, SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -241,10 +241,10 @@ namespace CSMDoc CloseSaveStage (SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -257,10 +257,10 @@ namespace CSMDoc FinalSavingStage (Document& document, SavingState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, Messages& messages); + void perform (int stage, Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; } diff --git a/apps/opencs/model/filter/andnode.hpp b/apps/opencs/model/filter/andnode.hpp index 56d1d7948..ab2c3ea99 100644 --- a/apps/opencs/model/filter/andnode.hpp +++ b/apps/opencs/model/filter/andnode.hpp @@ -11,8 +11,8 @@ namespace CSMFilter AndNode (const std::vector >& nodes); - virtual bool test (const CSMWorld::IdTableBase& table, int row, - const std::map& columns) const; + bool test (const CSMWorld::IdTableBase& table, int row, + const std::map& columns) const override; ///< \return Can the specified table row pass through to filter? /// \param columns column ID to column index mapping }; diff --git a/apps/opencs/model/filter/booleannode.hpp b/apps/opencs/model/filter/booleannode.hpp index 32206b575..bed6cbeb0 100644 --- a/apps/opencs/model/filter/booleannode.hpp +++ b/apps/opencs/model/filter/booleannode.hpp @@ -13,12 +13,12 @@ namespace CSMFilter BooleanNode (bool true_); - virtual bool test (const CSMWorld::IdTableBase& table, int row, - const std::map& columns) const; + bool test (const CSMWorld::IdTableBase& table, int row, + const std::map& columns) const override; ///< \return Can the specified table row pass through to filter? /// \param columns column ID to column index mapping - virtual std::string toString (bool numericColumns) const; + std::string toString (bool numericColumns) const override; ///< Return a string that represents this node. /// /// \param numericColumns Use numeric IDs instead of string to represent columns. diff --git a/apps/opencs/model/filter/leafnode.hpp b/apps/opencs/model/filter/leafnode.hpp index 2f3d91070..d27bdcfe8 100644 --- a/apps/opencs/model/filter/leafnode.hpp +++ b/apps/opencs/model/filter/leafnode.hpp @@ -11,7 +11,7 @@ namespace CSMFilter { public: - virtual std::vector getReferencedColumns() const; + std::vector getReferencedColumns() const override; ///< Return a list of the IDs of the columns referenced by this node. The column mapping /// passed into test as columns must contain all columns listed here. }; diff --git a/apps/opencs/model/filter/narynode.hpp b/apps/opencs/model/filter/narynode.hpp index 1cd93e62e..231e38e13 100644 --- a/apps/opencs/model/filter/narynode.hpp +++ b/apps/opencs/model/filter/narynode.hpp @@ -21,11 +21,11 @@ namespace CSMFilter const Node& operator[] (int index) const; - virtual std::vector getReferencedColumns() const; + std::vector getReferencedColumns() const override; ///< Return a list of the IDs of the columns referenced by this node. The column mapping /// passed into test as columns must contain all columns listed here. - virtual std::string toString (bool numericColumns) const; + std::string toString (bool numericColumns) const override; ///< Return a string that represents this node. /// /// \param numericColumns Use numeric IDs instead of string to represent columns. diff --git a/apps/opencs/model/filter/notnode.hpp b/apps/opencs/model/filter/notnode.hpp index e3c57cede..5b15163d9 100644 --- a/apps/opencs/model/filter/notnode.hpp +++ b/apps/opencs/model/filter/notnode.hpp @@ -11,8 +11,8 @@ namespace CSMFilter NotNode (std::shared_ptr child); - virtual bool test (const CSMWorld::IdTableBase& table, int row, - const std::map& columns) const; + bool test (const CSMWorld::IdTableBase& table, int row, + const std::map& columns) const override; ///< \return Can the specified table row pass through to filter? /// \param columns column ID to column index mapping }; diff --git a/apps/opencs/model/filter/ornode.hpp b/apps/opencs/model/filter/ornode.hpp index b89da4e75..61115b3d9 100644 --- a/apps/opencs/model/filter/ornode.hpp +++ b/apps/opencs/model/filter/ornode.hpp @@ -11,8 +11,8 @@ namespace CSMFilter OrNode (const std::vector >& nodes); - virtual bool test (const CSMWorld::IdTableBase& table, int row, - const std::map& columns) const; + bool test (const CSMWorld::IdTableBase& table, int row, + const std::map& columns) const override; ///< \return Can the specified table row pass through to filter? /// \param columns column ID to column index mapping }; diff --git a/apps/opencs/model/filter/textnode.hpp b/apps/opencs/model/filter/textnode.hpp index 60ead85de..0e7a0e4f5 100644 --- a/apps/opencs/model/filter/textnode.hpp +++ b/apps/opencs/model/filter/textnode.hpp @@ -14,16 +14,16 @@ namespace CSMFilter TextNode (int columnId, const std::string& text); - virtual bool test (const CSMWorld::IdTableBase& table, int row, - const std::map& columns) const; + bool test (const CSMWorld::IdTableBase& table, int row, + const std::map& columns) const override; ///< \return Can the specified table row pass through to filter? /// \param columns column ID to column index mapping - virtual std::vector getReferencedColumns() const; + std::vector getReferencedColumns() const override; ///< Return a list of the IDs of the columns referenced by this node. The column mapping /// passed into test as columns must contain all columns listed here. - virtual std::string toString (bool numericColumns) const; + std::string toString (bool numericColumns) const override; ///< Return a string that represents this node. /// /// \param numericColumns Use numeric IDs instead of string to represent columns. diff --git a/apps/opencs/model/filter/unarynode.hpp b/apps/opencs/model/filter/unarynode.hpp index cbee4e0ba..39326d167 100644 --- a/apps/opencs/model/filter/unarynode.hpp +++ b/apps/opencs/model/filter/unarynode.hpp @@ -18,11 +18,11 @@ namespace CSMFilter Node& getChild(); - virtual std::vector getReferencedColumns() const; + std::vector getReferencedColumns() const override; ///< Return a list of the IDs of the columns referenced by this node. The column mapping /// passed into test as columns must contain all columns listed here. - virtual std::string toString (bool numericColumns) const; + std::string toString (bool numericColumns) const override; ///< Return a string that represents this node. /// /// \param numericColumns Use numeric IDs instead of string to represent columns. diff --git a/apps/opencs/model/filter/valuenode.hpp b/apps/opencs/model/filter/valuenode.hpp index 5b7ffec4e..339e4948a 100644 --- a/apps/opencs/model/filter/valuenode.hpp +++ b/apps/opencs/model/filter/valuenode.hpp @@ -27,16 +27,16 @@ namespace CSMFilter ValueNode (int columnId, Type lowerType, Type upperType, double lower, double upper); - virtual bool test (const CSMWorld::IdTableBase& table, int row, - const std::map& columns) const; + bool test (const CSMWorld::IdTableBase& table, int row, + const std::map& columns) const override; ///< \return Can the specified table row pass through to filter? /// \param columns column ID to column index mapping - virtual std::vector getReferencedColumns() const; + std::vector getReferencedColumns() const override; ///< Return a list of the IDs of the columns referenced by this node. The column mapping /// passed into test as columns must contain all columns listed here. - virtual std::string toString (bool numericColumns) const; + std::string toString (bool numericColumns) const override; ///< Return a string that represents this node. /// /// \param numericColumns Use numeric IDs instead of string to represent columns. diff --git a/apps/opencs/model/prefs/boolsetting.hpp b/apps/opencs/model/prefs/boolsetting.hpp index 37c018d14..941cb5037 100644 --- a/apps/opencs/model/prefs/boolsetting.hpp +++ b/apps/opencs/model/prefs/boolsetting.hpp @@ -23,9 +23,9 @@ namespace CSMPrefs BoolSetting& setTooltip (const std::string& tooltip); /// Return label, input widget. - virtual std::pair makeWidgets (QWidget *parent); + std::pair makeWidgets (QWidget *parent) override; - virtual void updateWidget(); + void updateWidget() override; private slots: diff --git a/apps/opencs/model/prefs/coloursetting.hpp b/apps/opencs/model/prefs/coloursetting.hpp index e892b21d6..4a814c0e2 100644 --- a/apps/opencs/model/prefs/coloursetting.hpp +++ b/apps/opencs/model/prefs/coloursetting.hpp @@ -29,9 +29,9 @@ namespace CSMPrefs ColourSetting& setTooltip (const std::string& tooltip); /// Return label, input widget. - virtual std::pair makeWidgets (QWidget *parent); + std::pair makeWidgets (QWidget *parent) override; - virtual void updateWidget(); + void updateWidget() override; private slots: diff --git a/apps/opencs/model/prefs/doublesetting.hpp b/apps/opencs/model/prefs/doublesetting.hpp index 4d297409b..47886e446 100644 --- a/apps/opencs/model/prefs/doublesetting.hpp +++ b/apps/opencs/model/prefs/doublesetting.hpp @@ -36,9 +36,9 @@ namespace CSMPrefs DoubleSetting& setTooltip (const std::string& tooltip); /// Return label, input widget. - virtual std::pair makeWidgets (QWidget *parent); + std::pair makeWidgets (QWidget *parent) override; - virtual void updateWidget(); + void updateWidget() override; private slots: diff --git a/apps/opencs/model/prefs/enumsetting.hpp b/apps/opencs/model/prefs/enumsetting.hpp index b01635cdf..235f6adc3 100644 --- a/apps/opencs/model/prefs/enumsetting.hpp +++ b/apps/opencs/model/prefs/enumsetting.hpp @@ -54,9 +54,9 @@ namespace CSMPrefs EnumSetting& addValue (const std::string& value, const std::string& tooltip); /// Return label, input widget. - virtual std::pair makeWidgets (QWidget *parent); + std::pair makeWidgets (QWidget *parent) override; - virtual void updateWidget(); + void updateWidget() override; private slots: diff --git a/apps/opencs/model/prefs/intsetting.hpp b/apps/opencs/model/prefs/intsetting.hpp index ee0989d83..f18213b77 100644 --- a/apps/opencs/model/prefs/intsetting.hpp +++ b/apps/opencs/model/prefs/intsetting.hpp @@ -32,9 +32,9 @@ namespace CSMPrefs IntSetting& setTooltip (const std::string& tooltip); /// Return label, input widget. - virtual std::pair makeWidgets (QWidget *parent); + std::pair makeWidgets (QWidget *parent) override; - virtual void updateWidget(); + void updateWidget() override; private slots: diff --git a/apps/opencs/model/prefs/modifiersetting.hpp b/apps/opencs/model/prefs/modifiersetting.hpp index 2c6a45b5a..977badb8d 100644 --- a/apps/opencs/model/prefs/modifiersetting.hpp +++ b/apps/opencs/model/prefs/modifiersetting.hpp @@ -19,13 +19,13 @@ namespace CSMPrefs ModifierSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key, const std::string& label); - virtual std::pair makeWidgets(QWidget* parent); + std::pair makeWidgets(QWidget* parent) override; - virtual void updateWidget(); + void updateWidget() override; protected: - bool eventFilter(QObject* target, QEvent* event); + bool eventFilter(QObject* target, QEvent* event) override; private: diff --git a/apps/opencs/model/prefs/shortcuteventhandler.hpp b/apps/opencs/model/prefs/shortcuteventhandler.hpp index 6a7ba2522..700b977fd 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.hpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.hpp @@ -27,7 +27,7 @@ namespace CSMPrefs protected: - bool eventFilter(QObject* watched, QEvent* event); + bool eventFilter(QObject* watched, QEvent* event) override; private: diff --git a/apps/opencs/model/prefs/shortcutsetting.hpp b/apps/opencs/model/prefs/shortcutsetting.hpp index c388305a6..a0c588b42 100644 --- a/apps/opencs/model/prefs/shortcutsetting.hpp +++ b/apps/opencs/model/prefs/shortcutsetting.hpp @@ -19,13 +19,13 @@ namespace CSMPrefs ShortcutSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key, const std::string& label); - virtual std::pair makeWidgets(QWidget* parent); + std::pair makeWidgets(QWidget* parent) override; - virtual void updateWidget(); + void updateWidget() override; protected: - bool eventFilter(QObject* target, QEvent* event); + bool eventFilter(QObject* target, QEvent* event) override; private: diff --git a/apps/opencs/model/tools/birthsigncheck.hpp b/apps/opencs/model/tools/birthsigncheck.hpp index 9001c524c..498894f88 100644 --- a/apps/opencs/model/tools/birthsigncheck.hpp +++ b/apps/opencs/model/tools/birthsigncheck.hpp @@ -22,10 +22,10 @@ namespace CSMTools BirthsignCheckStage (const CSMWorld::IdCollection &birthsigns, const CSMWorld::Resources &textures); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/bodypartcheck.hpp b/apps/opencs/model/tools/bodypartcheck.hpp index 5c8ae2929..2c379bd07 100644 --- a/apps/opencs/model/tools/bodypartcheck.hpp +++ b/apps/opencs/model/tools/bodypartcheck.hpp @@ -25,10 +25,10 @@ namespace CSMTools const CSMWorld::Resources &meshes, const CSMWorld::IdCollection &races ); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform( int stage, CSMDoc::Messages &messages ); + void perform(int stage, CSMDoc::Messages &messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/classcheck.hpp b/apps/opencs/model/tools/classcheck.hpp index ba0a07047..a78c2eb97 100644 --- a/apps/opencs/model/tools/classcheck.hpp +++ b/apps/opencs/model/tools/classcheck.hpp @@ -19,10 +19,10 @@ namespace CSMTools ClassCheckStage (const CSMWorld::IdCollection& classes); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/enchantmentcheck.hpp b/apps/opencs/model/tools/enchantmentcheck.hpp index 3bd85326f..e9c8b9eec 100644 --- a/apps/opencs/model/tools/enchantmentcheck.hpp +++ b/apps/opencs/model/tools/enchantmentcheck.hpp @@ -19,10 +19,10 @@ namespace CSMTools EnchantmentCheckStage (const CSMWorld::IdCollection& enchantments); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; diff --git a/apps/opencs/model/tools/factioncheck.hpp b/apps/opencs/model/tools/factioncheck.hpp index b26d19717..d281c1b41 100644 --- a/apps/opencs/model/tools/factioncheck.hpp +++ b/apps/opencs/model/tools/factioncheck.hpp @@ -19,10 +19,10 @@ namespace CSMTools FactionCheckStage (const CSMWorld::IdCollection& factions); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/gmstcheck.hpp b/apps/opencs/model/tools/gmstcheck.hpp index 27bd61317..2c12a8607 100644 --- a/apps/opencs/model/tools/gmstcheck.hpp +++ b/apps/opencs/model/tools/gmstcheck.hpp @@ -16,10 +16,10 @@ namespace CSMTools GmstCheckStage(const CSMWorld::IdCollection& gameSettings); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform(int stage, CSMDoc::Messages& messages); + void perform(int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages private: diff --git a/apps/opencs/model/tools/journalcheck.hpp b/apps/opencs/model/tools/journalcheck.hpp index 661edcaef..b63127b52 100644 --- a/apps/opencs/model/tools/journalcheck.hpp +++ b/apps/opencs/model/tools/journalcheck.hpp @@ -18,10 +18,10 @@ namespace CSMTools JournalCheckStage(const CSMWorld::IdCollection& journals, const CSMWorld::InfoCollection& journalInfos); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform(int stage, CSMDoc::Messages& messages); + void perform(int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages private: diff --git a/apps/opencs/model/tools/magiceffectcheck.hpp b/apps/opencs/model/tools/magiceffectcheck.hpp index a52723b0f..4b2c24cc7 100644 --- a/apps/opencs/model/tools/magiceffectcheck.hpp +++ b/apps/opencs/model/tools/magiceffectcheck.hpp @@ -32,9 +32,9 @@ namespace CSMTools const CSMWorld::Resources &icons, const CSMWorld::Resources &textures); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages &messages); + void perform (int stage, CSMDoc::Messages &messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/mandatoryid.hpp b/apps/opencs/model/tools/mandatoryid.hpp index 86015c982..9d069a2da 100644 --- a/apps/opencs/model/tools/mandatoryid.hpp +++ b/apps/opencs/model/tools/mandatoryid.hpp @@ -27,10 +27,10 @@ namespace CSMTools MandatoryIdStage (const CSMWorld::CollectionBase& idCollection, const CSMWorld::UniversalId& collectionId, const std::vector& ids); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/mergeoperation.hpp b/apps/opencs/model/tools/mergeoperation.hpp index 733fc8eba..427967190 100644 --- a/apps/opencs/model/tools/mergeoperation.hpp +++ b/apps/opencs/model/tools/mergeoperation.hpp @@ -31,7 +31,7 @@ namespace CSMTools protected slots: - virtual void operationDone(); + void operationDone() override; signals: diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 4b41c5a04..bcb3fe2ad 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -22,10 +22,10 @@ namespace CSMTools StartMergeStage (MergeState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -38,10 +38,10 @@ namespace CSMTools FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -55,10 +55,10 @@ namespace CSMTools MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)()); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -93,10 +93,10 @@ namespace CSMTools MergeRefIdsStage (MergeState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -109,10 +109,10 @@ namespace CSMTools MergeReferencesStage (MergeState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -125,10 +125,10 @@ namespace CSMTools PopulateLandTexturesMergeStage (MergeState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -140,10 +140,10 @@ namespace CSMTools MergeLandStage (MergeState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -157,10 +157,10 @@ namespace CSMTools FixLandsAndLandTexturesMergeStage (MergeState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; @@ -174,10 +174,10 @@ namespace CSMTools CleanupLandTexturesMergeStage (MergeState& state); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/pathgridcheck.hpp b/apps/opencs/model/tools/pathgridcheck.hpp index 3e2fdd0ab..212637fd4 100644 --- a/apps/opencs/model/tools/pathgridcheck.hpp +++ b/apps/opencs/model/tools/pathgridcheck.hpp @@ -32,9 +32,9 @@ namespace CSMTools PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids); - virtual int setup(); + int setup() override; - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; }; } diff --git a/apps/opencs/model/tools/racecheck.hpp b/apps/opencs/model/tools/racecheck.hpp index 55c283611..7c70f13b0 100644 --- a/apps/opencs/model/tools/racecheck.hpp +++ b/apps/opencs/model/tools/racecheck.hpp @@ -24,10 +24,10 @@ namespace CSMTools RaceCheckStage (const CSMWorld::IdCollection& races); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/referenceablecheck.hpp b/apps/opencs/model/tools/referenceablecheck.hpp index e55e5fad9..83c8f1232 100644 --- a/apps/opencs/model/tools/referenceablecheck.hpp +++ b/apps/opencs/model/tools/referenceablecheck.hpp @@ -22,8 +22,8 @@ namespace CSMTools const CSMWorld::Resources& icons, const CSMWorld::IdCollection& bodyparts); - virtual void perform(int stage, CSMDoc::Messages& messages); - virtual int setup(); + void perform(int stage, CSMDoc::Messages& messages) override; + int setup() override; private: //CONCRETE CHECKS diff --git a/apps/opencs/model/tools/referencecheck.hpp b/apps/opencs/model/tools/referencecheck.hpp index 7373903e6..2da139869 100644 --- a/apps/opencs/model/tools/referencecheck.hpp +++ b/apps/opencs/model/tools/referencecheck.hpp @@ -14,8 +14,8 @@ namespace CSMTools const CSMWorld::IdCollection& cells, const CSMWorld::IdCollection& factions); - virtual void perform(int stage, CSMDoc::Messages& messages); - virtual int setup(); + void perform(int stage, CSMDoc::Messages& messages) override; + int setup() override; private: const CSMWorld::RefCollection& mReferences; diff --git a/apps/opencs/model/tools/regioncheck.hpp b/apps/opencs/model/tools/regioncheck.hpp index 4c12727f0..e7ddb0bca 100644 --- a/apps/opencs/model/tools/regioncheck.hpp +++ b/apps/opencs/model/tools/regioncheck.hpp @@ -19,10 +19,10 @@ namespace CSMTools RegionCheckStage (const CSMWorld::IdCollection& regions); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 61b4e6307..809dfcc3e 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -33,15 +33,15 @@ namespace CSMTools ReportModel (bool fieldColumn = false, bool severityColumn = true); - virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; + int rowCount (const QModelIndex & parent = QModelIndex()) const override; - virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; + int columnCount (const QModelIndex & parent = QModelIndex()) const override; - virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override; - virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()) override; void add (const CSMDoc::Message& message); diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 8f4ac9763..d975e02da 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -36,20 +36,20 @@ namespace CSMTools CSMDoc::Message::Severity getSeverity (Type type); - virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); + void report (const std::string& message, const Compiler::TokenLoc& loc, Type type) override; ///< Report error to the user. - virtual void report (const std::string& message, Type type); + void report (const std::string& message, Type type) override; ///< Report a file related error public: ScriptCheckStage (const CSMDoc::Document& document); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/searchstage.hpp b/apps/opencs/model/tools/searchstage.hpp index 073487c0d..86abf31a3 100644 --- a/apps/opencs/model/tools/searchstage.hpp +++ b/apps/opencs/model/tools/searchstage.hpp @@ -24,10 +24,10 @@ namespace CSMTools SearchStage (const CSMWorld::IdTableBase *model); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages. void setOperation (const SearchOperation *operation); diff --git a/apps/opencs/model/tools/skillcheck.hpp b/apps/opencs/model/tools/skillcheck.hpp index edd6b79a0..b1af887f6 100644 --- a/apps/opencs/model/tools/skillcheck.hpp +++ b/apps/opencs/model/tools/skillcheck.hpp @@ -19,10 +19,10 @@ namespace CSMTools SkillCheckStage (const CSMWorld::IdCollection& skills); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/soundcheck.hpp b/apps/opencs/model/tools/soundcheck.hpp index fc5925717..80eb9e7f2 100644 --- a/apps/opencs/model/tools/soundcheck.hpp +++ b/apps/opencs/model/tools/soundcheck.hpp @@ -22,10 +22,10 @@ namespace CSMTools SoundCheckStage (const CSMWorld::IdCollection& sounds, const CSMWorld::Resources &soundfiles); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/soundgencheck.hpp b/apps/opencs/model/tools/soundgencheck.hpp index 3c2a7f071..306d35ded 100644 --- a/apps/opencs/model/tools/soundgencheck.hpp +++ b/apps/opencs/model/tools/soundgencheck.hpp @@ -20,10 +20,10 @@ namespace CSMTools const CSMWorld::IdCollection &sounds, const CSMWorld::RefIdCollection &objects); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform(int stage, CSMDoc::Messages &messages); + void perform(int stage, CSMDoc::Messages &messages) override; ///< Messages resulting from this stage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/spellcheck.hpp b/apps/opencs/model/tools/spellcheck.hpp index 03513adc3..bfc962810 100644 --- a/apps/opencs/model/tools/spellcheck.hpp +++ b/apps/opencs/model/tools/spellcheck.hpp @@ -19,10 +19,10 @@ namespace CSMTools SpellCheckStage (const CSMWorld::IdCollection& spells); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform (int stage, CSMDoc::Messages& messages); + void perform (int stage, CSMDoc::Messages& messages) override; ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/startscriptcheck.hpp b/apps/opencs/model/tools/startscriptcheck.hpp index a7d70ee5a..a45d3c943 100644 --- a/apps/opencs/model/tools/startscriptcheck.hpp +++ b/apps/opencs/model/tools/startscriptcheck.hpp @@ -21,8 +21,8 @@ namespace CSMTools StartScriptCheckStage (const CSMWorld::IdCollection& startScripts, const CSMWorld::IdCollection& scripts); - virtual void perform(int stage, CSMDoc::Messages& messages); - virtual int setup(); + void perform(int stage, CSMDoc::Messages& messages) override; + int setup() override; }; } diff --git a/apps/opencs/model/tools/topicinfocheck.hpp b/apps/opencs/model/tools/topicinfocheck.hpp index 9575181b0..b9dbdc153 100644 --- a/apps/opencs/model/tools/topicinfocheck.hpp +++ b/apps/opencs/model/tools/topicinfocheck.hpp @@ -40,10 +40,10 @@ namespace CSMTools const CSMWorld::RefIdData& referencables, const CSMWorld::Resources& soundFiles); - virtual int setup(); + int setup() override; ///< \return number of steps - virtual void perform(int step, CSMDoc::Messages& messages); + void perform(int step, CSMDoc::Messages& messages) override; ///< Messages resulting from this stage will be appended to \a messages private: diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index 3d6802b86..451ef9d0e 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -120,19 +120,19 @@ namespace CSMWorld void add (const ESXRecordT& record); ///< Add a new record (modified) - virtual int getSize() const; + int getSize() const override; - virtual std::string getId (int index) const; + std::string getId (int index) const override; - virtual int getIndex (const std::string& id) const; + int getIndex (const std::string& id) const override; - virtual int getColumns() const; + int getColumns() const override; - virtual QVariant getData (int index, int column) const; + QVariant getData (int index, int column) const override; - virtual void setData (int index, int column, const QVariant& data); + void setData (int index, int column, const QVariant& data) override; - virtual const ColumnBase& getColumn (int column) const; + const ColumnBase& getColumn (int column) const override; virtual void merge(); ///< Merge modified into base. @@ -140,43 +140,43 @@ namespace CSMWorld virtual void purge(); ///< Remove records that are flagged as erased. - virtual void removeRows (int index, int count) ; + void removeRows (int index, int count) override; - virtual void appendBlankRecord (const std::string& id, - UniversalId::Type type = UniversalId::Type_None); + void appendBlankRecord (const std::string& id, + UniversalId::Type type = UniversalId::Type_None) override; ///< \param type Will be ignored, unless the collection supports multiple record types - virtual void cloneRecord(const std::string& origin, + void cloneRecord(const std::string& origin, const std::string& destination, - const UniversalId::Type type); + const UniversalId::Type type) override; - virtual bool touchRecord(const std::string& id); + bool touchRecord(const std::string& id) override; ///< Change the state of a record from base to modified, if it is not already. /// \return True if the record was changed. - virtual int searchId (const std::string& id) const; + int searchId (const std::string& id) const override; ////< Search record with \a id. /// \return index of record (if found) or -1 (not found) - virtual void replace (int index, const RecordBase& record); + void replace (int index, const RecordBase& record) override; ///< If the record type does not match, an exception is thrown. /// /// \attention \a record must not change the ID. - virtual void appendRecord (const RecordBase& record, - UniversalId::Type type = UniversalId::Type_None); + void appendRecord (const RecordBase& record, + UniversalId::Type type = UniversalId::Type_None) override; ///< If the record type does not match, an exception is thrown. ///< \param type Will be ignored, unless the collection supports multiple record types - virtual const Record& getRecord (const std::string& id) const; + const Record& getRecord (const std::string& id) const override; - virtual const Record& getRecord (int index) const; + const Record& getRecord (int index) const override; - virtual int getAppendIndex (const std::string& id, - UniversalId::Type type = UniversalId::Type_None) const; + int getAppendIndex (const std::string& id, + UniversalId::Type type = UniversalId::Type_None) const override; ///< \param type Will be ignored, unless the collection supports multiple record types - virtual std::vector getIds (bool listDeleted = true) const; + std::vector getIds (bool listDeleted = true) const override; ///< Return a sorted collection of all IDs /// /// \param listDeleted include deleted record in the list @@ -190,7 +190,7 @@ namespace CSMWorld /// If the index is invalid either generally (by being out of range) or for the particular /// record, an exception is thrown. - virtual bool reorderRows (int baseIndex, const std::vector& newOrder); + bool reorderRows (int baseIndex, const std::vector& newOrder) override; ///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices /// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex). /// diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index d4f78854d..6dc58bd63 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -211,13 +211,13 @@ namespace CSMWorld : Column (id, ColumnBase::Display_NestedHeader, flags), mFixedRows(fixedRows) {} - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { // There is nothing to do here. // This prevents exceptions from parent's implementation } - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { // by default editable; also see IdTree::hasChildren() if (mFixedRows) @@ -226,7 +226,7 @@ namespace CSMWorld return QVariant::fromValue(ColumnBase::TableEdit_Full); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -240,7 +240,7 @@ namespace CSMWorld NestedChildColumn (int id, Display display, int flags = ColumnBase::Flag_Dialogue, bool isEditable = true); - virtual bool isEditable() const; + bool isEditable() const override; private: bool mIsEditable; diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index ccc18263b..c69ca1d84 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -28,19 +28,19 @@ namespace CSMWorld { FloatValueColumn() : Column (Columns::ColumnId_Value, ColumnBase::Display_Float) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mValue.getFloat(); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mValue.setFloat (data.toFloat()); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -54,12 +54,12 @@ namespace CSMWorld hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mId.c_str()); } - virtual bool isEditable() const + bool isEditable() const override { return false; } @@ -86,7 +86,7 @@ namespace CSMWorld : Column (Columns::ColumnId_Modification, ColumnBase::Display_RecordState) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { if (record.mState==Record::State_Erased) return static_cast (Record::State_Deleted); @@ -94,17 +94,17 @@ namespace CSMWorld return static_cast (record.mState); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { record.mState = static_cast (data.toInt()); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return false; } @@ -120,12 +120,12 @@ namespace CSMWorld mType (type) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return mType; } - virtual bool isEditable() const + bool isEditable() const override { return false; } @@ -139,19 +139,19 @@ namespace CSMWorld : Column (Columns::ColumnId_ValueType, display, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mValue.getType()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mValue.setType (static_cast (data.toInt())); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -163,7 +163,7 @@ namespace CSMWorld { VarValueColumn() : Column (Columns::ColumnId_Value, ColumnBase::Display_Var, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { switch (record.get().mValue.getType()) { @@ -185,7 +185,7 @@ namespace CSMWorld } } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -214,7 +214,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -227,12 +227,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Description, ColumnBase::Display_LongString) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mDescription.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -241,7 +241,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -254,12 +254,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Specialisation, ColumnBase::Display_Specialisation) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mSpecialization; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -268,7 +268,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -284,12 +284,12 @@ namespace CSMWorld mIndex (index) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mUseValue[mIndex]; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -298,7 +298,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -311,12 +311,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mAttribute; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -325,7 +325,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -336,12 +336,12 @@ namespace CSMWorld { NameColumn() : Column (Columns::ColumnId_Name, ColumnBase::Display_String) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mName.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -350,7 +350,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -366,12 +366,12 @@ namespace CSMWorld mIndex (index) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mAttribute[mIndex]; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -380,7 +380,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -399,14 +399,14 @@ namespace CSMWorld mIndex (index), mMajor (major) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { int skill = record.get().mData.getSkill (mIndex, mMajor); return QString::fromUtf8 (ESM::Skill::indexToId (skill).c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { std::istringstream stream (data.toString().toUtf8().constData()); @@ -425,7 +425,7 @@ namespace CSMWorld } } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -437,12 +437,12 @@ namespace CSMWorld PlayableColumn() : Column (Columns::ColumnId_Playable, ColumnBase::Display_Boolean) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mIsPlayable!=0; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -451,7 +451,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -462,12 +462,12 @@ namespace CSMWorld { HiddenColumn() : Column (Columns::ColumnId_Hidden, ColumnBase::Display_Boolean) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mIsHidden!=0; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -476,7 +476,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -494,7 +494,7 @@ namespace CSMWorld mInverted (inverted) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { bool flag = (record.get().mData.mFlags & mMask)!=0; @@ -504,7 +504,7 @@ namespace CSMWorld return flag; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -518,7 +518,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -535,7 +535,7 @@ namespace CSMWorld mInverted (inverted) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { bool flag = (record.get().mFlags & mMask)!=0; @@ -545,7 +545,7 @@ namespace CSMWorld return flag; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -559,7 +559,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -579,7 +579,7 @@ namespace CSMWorld mMale (male), mWeight (weight) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { const ESM::Race::MaleFemaleF& value = mWeight ? record.get().mData.mWeight : record.get().mData.mHeight; @@ -587,7 +587,7 @@ namespace CSMWorld return mMale ? value.mMale : value.mFemale; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -599,7 +599,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -624,7 +624,7 @@ namespace CSMWorld mType (type) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { int value = 0; @@ -638,7 +638,7 @@ namespace CSMWorld return value; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { int value = data.toInt(); @@ -659,7 +659,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -672,12 +672,12 @@ namespace CSMWorld : Column (Columns::ColumnId_SoundFile, ColumnBase::Display_SoundRes) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mSound.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -686,7 +686,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -699,19 +699,19 @@ namespace CSMWorld : Column (Columns::ColumnId_MapColour, ColumnBase::Display_Colour) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mMapColor; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT copy = record.get(); copy.mMapColor = data.toInt(); record.setModified (copy); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -724,12 +724,12 @@ namespace CSMWorld : Column (Columns::ColumnId_SleepEncounter, ColumnBase::Display_CreatureLevelledList) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mSleepList.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -738,7 +738,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -749,12 +749,12 @@ namespace CSMWorld { TextureColumn() : Column (Columns::ColumnId_Texture, ColumnBase::Display_Texture) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mTexture.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -763,7 +763,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -776,12 +776,12 @@ namespace CSMWorld : Column (Columns::ColumnId_SpellType, ColumnBase::Display_SpellType) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mType; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -790,7 +790,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -801,19 +801,19 @@ namespace CSMWorld { CostColumn() : Column (Columns::ColumnId_Cost, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mCost; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mData.mCost = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -835,12 +835,12 @@ namespace CSMWorld type==Type_File ? 0 : ColumnBase::Flag_Dialogue) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mScriptText.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -849,7 +849,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -860,12 +860,12 @@ namespace CSMWorld { RegionColumn() : Column (Columns::ColumnId_Region, ColumnBase::Display_Region) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mRegion.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -874,7 +874,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -891,12 +891,12 @@ namespace CSMWorld mBlocked (blocked) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mCell.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -905,12 +905,12 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return !mBlocked; } @@ -923,12 +923,12 @@ namespace CSMWorld : Column (Columns::ColumnId_OriginalCell, ColumnBase::Display_Cell) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mOriginalCell.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -937,12 +937,12 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return false; } @@ -954,12 +954,12 @@ namespace CSMWorld IdColumn() : Column (Columns::ColumnId_ReferenceableId, ColumnBase::Display_Referenceable) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mRefID.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -968,7 +968,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -979,19 +979,19 @@ namespace CSMWorld { ScaleColumn() : Column (Columns::ColumnId_Scale, ColumnBase::Display_Float) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mScale; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mScale = data.toFloat(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1002,12 +1002,12 @@ namespace CSMWorld { OwnerColumn() : Column (Columns::ColumnId_Owner, ColumnBase::Display_Npc) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mOwner.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1016,7 +1016,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1027,12 +1027,12 @@ namespace CSMWorld { SoulColumn() : Column (Columns::ColumnId_Soul, ColumnBase::Display_Creature) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mSoul.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1041,7 +1041,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1052,12 +1052,12 @@ namespace CSMWorld { FactionColumn() : Column (Columns::ColumnId_Faction, ColumnBase::Display_Faction) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mFaction.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1066,7 +1066,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1079,19 +1079,19 @@ namespace CSMWorld : Column (Columns::ColumnId_FactionIndex, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mFactionRank; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mFactionRank = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1102,19 +1102,19 @@ namespace CSMWorld { ChargesColumn() : Column (Columns::ColumnId_Charges, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mChargeInt; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mChargeInt = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1127,19 +1127,19 @@ namespace CSMWorld : Column (Columns::ColumnId_Enchantment, ColumnBase::Display_Float) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mEnchantmentCharge; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mEnchantmentCharge = data.toFloat(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1151,19 +1151,19 @@ namespace CSMWorld GoldValueColumn() : Column (Columns::ColumnId_CoinValue, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mGoldValue; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mGoldValue = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1176,12 +1176,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Teleport, ColumnBase::Display_Boolean) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mTeleport; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1190,7 +1190,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1203,12 +1203,12 @@ namespace CSMWorld : Column (Columns::ColumnId_TeleportCell, ColumnBase::Display_Cell) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mDestCell.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1217,12 +1217,12 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return true; } @@ -1235,19 +1235,19 @@ namespace CSMWorld : Column (Columns::ColumnId_LockLevel, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mLockLevel; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mLockLevel = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1258,12 +1258,12 @@ namespace CSMWorld { KeyColumn() : Column (Columns::ColumnId_Key, ColumnBase::Display_Miscellaneous) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mKey.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1272,7 +1272,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1283,12 +1283,12 @@ namespace CSMWorld { TrapColumn() : Column (Columns::ColumnId_Trap, ColumnBase::Display_Spell) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mTrap.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1297,7 +1297,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1308,12 +1308,12 @@ namespace CSMWorld { FilterColumn() : Column (Columns::ColumnId_Filter, ColumnBase::Display_Filter) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mFilter.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1322,7 +1322,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1339,13 +1339,13 @@ namespace CSMWorld (door ? Columns::ColumnId_DoorPositionXPos : Columns::ColumnId_PositionXPos)+index, ColumnBase::Display_Float), mPosition (position), mIndex (index) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { const ESM::Position& position = record.get().*mPosition; return position.pos[mIndex]; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1356,7 +1356,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1373,13 +1373,13 @@ namespace CSMWorld (door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index, ColumnBase::Display_Double), mPosition (position), mIndex (index) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { const ESM::Position& position = record.get().*mPosition; return osg::RadiansToDegrees(position.rot[mIndex]); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1390,7 +1390,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1404,12 +1404,12 @@ namespace CSMWorld hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mType); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1418,12 +1418,12 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return false; } @@ -1436,12 +1436,12 @@ namespace CSMWorld : Column (Columns::ColumnId_QuestStatusType, ColumnBase::Display_QuestStatusType) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mQuestStatus); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1450,7 +1450,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1461,12 +1461,12 @@ namespace CSMWorld { QuestDescriptionColumn() : Column (Columns::ColumnId_QuestDescription, ColumnBase::Display_LongString) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mResponse.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1475,7 +1475,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1488,19 +1488,19 @@ namespace CSMWorld : Column (Columns::ColumnId_QuestIndex, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mDisposition; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mData.mDisposition = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1514,12 +1514,12 @@ namespace CSMWorld journal ? ColumnBase::Display_Journal : ColumnBase::Display_Topic) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mTopicId.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1528,12 +1528,12 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return false; } @@ -1544,12 +1544,12 @@ namespace CSMWorld { ActorColumn() : Column (Columns::ColumnId_Actor, ColumnBase::Display_Npc) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mActor.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1558,7 +1558,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1569,12 +1569,12 @@ namespace CSMWorld { RaceColumn() : Column (Columns::ColumnId_Race, ColumnBase::Display_Race) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mRace.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1583,7 +1583,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1594,12 +1594,12 @@ namespace CSMWorld { ClassColumn() : Column (Columns::ColumnId_Class, ColumnBase::Display_Class) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mClass.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1608,7 +1608,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1619,12 +1619,12 @@ namespace CSMWorld { PcFactionColumn() : Column (Columns::ColumnId_PcFaction, ColumnBase::Display_Faction) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mPcFaction.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1633,7 +1633,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1644,12 +1644,12 @@ namespace CSMWorld { ResponseColumn() : Column (Columns::ColumnId_Response, ColumnBase::Display_LongString) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mResponse.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1658,7 +1658,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1671,19 +1671,19 @@ namespace CSMWorld : Column (Columns::ColumnId_Disposition, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mDisposition; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mData.mDisposition = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1696,19 +1696,19 @@ namespace CSMWorld : Column (Columns::ColumnId_Rank, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mData.mRank); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mData.mRank = static_cast (data.toInt()); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1721,19 +1721,19 @@ namespace CSMWorld : Column (Columns::ColumnId_PcRank, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mData.mPCrank); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mData.mPCrank = static_cast (data.toInt()); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1746,12 +1746,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Gender, ColumnBase::Display_Gender) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mData.mGender); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1760,7 +1760,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1773,7 +1773,7 @@ namespace CSMWorld : Column(Columns::ColumnId_Gender, ColumnBase::Display_GenderNpc) {} - virtual QVariant get(const Record& record) const + QVariant get(const Record& record) const override { // Implemented this way to allow additional gender types in the future. if ((record.get().mData.mFlags & ESM::BodyPart::BPF_Female) == ESM::BodyPart::BPF_Female) @@ -1782,7 +1782,7 @@ namespace CSMWorld return 0; } - virtual void set(Record& record, const QVariant& data) + void set(Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1795,7 +1795,7 @@ namespace CSMWorld record.setModified(record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1808,12 +1808,12 @@ namespace CSMWorld : Column (Columns::ColumnId_EnchantmentType, ColumnBase::Display_EnchantmentType) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mData.mType); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1822,7 +1822,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1833,19 +1833,19 @@ namespace CSMWorld { ChargesColumn2() : Column (Columns::ColumnId_Charges, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mCharge; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mData.mCharge = data.toInt(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1857,12 +1857,12 @@ namespace CSMWorld AutoCalcColumn() : Column (Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mAutocalc!=0; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1871,7 +1871,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1882,12 +1882,12 @@ namespace CSMWorld { ModelColumn() : Column (Columns::ColumnId_Model, ColumnBase::Display_Mesh) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mModel.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1896,7 +1896,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1908,12 +1908,12 @@ namespace CSMWorld VampireColumn() : Column (Columns::ColumnId_Vampire, ColumnBase::Display_Boolean) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mVampire!=0; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1922,7 +1922,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1935,12 +1935,12 @@ namespace CSMWorld : Column (Columns::ColumnId_BodyPartType, ColumnBase::Display_BodyPartType) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mData.mPart); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1949,7 +1949,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1962,12 +1962,12 @@ namespace CSMWorld : Column (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType, flags) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mData.mType); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -1976,7 +1976,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -1989,12 +1989,12 @@ namespace CSMWorld : Column (Columns::ColumnId_OwnerGlobal, ColumnBase::Display_GlobalVariable) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mGlobalVariable.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2003,7 +2003,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2016,12 +2016,12 @@ namespace CSMWorld : Column (Columns::ColumnId_RefNumCounter, ColumnBase::Display_Integer, 0) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mRefNumCounter); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2030,12 +2030,12 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return false; } @@ -2048,12 +2048,12 @@ namespace CSMWorld : Column (Columns::ColumnId_RefNum, ColumnBase::Display_Integer, 0) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mRefNum.mIndex); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2062,12 +2062,12 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } - virtual bool isUserEditable() const + bool isUserEditable() const override { return false; } @@ -2080,12 +2080,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Sound, ColumnBase::Display_Sound) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mSound.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2094,7 +2094,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2107,12 +2107,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Creature, ColumnBase::Display_Creature) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mCreature.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2121,7 +2121,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2134,12 +2134,12 @@ namespace CSMWorld : Column (Columns::ColumnId_SoundGeneratorType, ColumnBase::Display_SoundGeneratorType) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return static_cast (record.get().mType); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2148,7 +2148,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2159,19 +2159,19 @@ namespace CSMWorld { BaseCostColumn() : Column (Columns::ColumnId_BaseCost, ColumnBase::Display_Float) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mBaseCost; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); record2.mData.mBaseCost = data.toFloat(); record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2184,12 +2184,12 @@ namespace CSMWorld : Column (Columns::ColumnId_School, ColumnBase::Display_School) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mData.mSchool; } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2198,7 +2198,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2216,14 +2216,14 @@ namespace CSMWorld this->mColumnId==Columns::ColumnId_Particle); } - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 ( (this->mColumnId==Columns::ColumnId_Icon ? record.get().mIcon : record.get().mParticle).c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2234,7 +2234,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2252,7 +2252,7 @@ namespace CSMWorld this->mColumnId==Columns::ColumnId_BoltObject); } - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { const std::string *string = 0; @@ -2270,7 +2270,7 @@ namespace CSMWorld return QString::fromUtf8 (string->c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { std::string *string = 0; @@ -2292,7 +2292,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2310,7 +2310,7 @@ namespace CSMWorld this->mColumnId==Columns::ColumnId_BoltSound); } - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { const std::string *string = 0; @@ -2328,7 +2328,7 @@ namespace CSMWorld return QString::fromUtf8 (string->c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { std::string *string = 0; @@ -2350,7 +2350,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2363,12 +2363,12 @@ namespace CSMWorld : Column (Columns::ColumnId_FileFormat, ColumnBase::Display_Integer) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return record.get().mFormat; } - virtual bool isEditable() const + bool isEditable() const override { return false; } @@ -2381,12 +2381,12 @@ namespace CSMWorld : Column (Columns::ColumnId_Author, ColumnBase::Display_String32) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mAuthor.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2395,7 +2395,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2408,12 +2408,12 @@ namespace CSMWorld : Column (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString256) {} - virtual QVariant get (const Record& record) const + QVariant get (const Record& record) const override { return QString::fromUtf8 (record.get().mDescription.c_str()); } - virtual void set (Record& record, const QVariant& data) + void set (Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); @@ -2422,7 +2422,7 @@ namespace CSMWorld record.setModified (record2); } - virtual bool isEditable() const + bool isEditable() const override { return true; } @@ -2511,9 +2511,9 @@ namespace CSMWorld BodyPartRaceColumn(const MeshTypeColumn *meshType); - virtual QVariant get(const Record &record) const; - virtual void set(Record &record, const QVariant &data); - virtual bool isEditable() const; + QVariant get(const Record &record) const override; + void set(Record &record, const QVariant &data) override; + bool isEditable() const override; }; } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 58a1b1d1c..88af32636 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -142,9 +142,9 @@ namespace CSMWorld ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand *parent = 0); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; class CreateCommand : public QUndoCommand @@ -175,9 +175,9 @@ namespace CSMWorld void addNestedValue(int parentColumn, int nestedColumn, const QVariant &value); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; class CloneCommand : public CreateCommand @@ -191,9 +191,9 @@ namespace CSMWorld const UniversalId::Type type, QUndoCommand* parent = 0); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; class RevertCommand : public QUndoCommand @@ -212,9 +212,9 @@ namespace CSMWorld virtual ~RevertCommand(); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; class DeleteCommand : public QUndoCommand @@ -235,9 +235,9 @@ namespace CSMWorld virtual ~DeleteCommand(); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; class ReorderRowsCommand : public QUndoCommand @@ -250,9 +250,9 @@ namespace CSMWorld ReorderRowsCommand (IdTable& model, int baseIndex, const std::vector& newOrder); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; class CreatePathgridCommand : public CreateCommand @@ -261,7 +261,7 @@ namespace CSMWorld CreatePathgridCommand(IdTable& model, const std::string& id, QUndoCommand *parent = 0); - virtual void redo(); + void redo() override; }; /// \brief Update cell ID according to x/y-coordinates @@ -281,9 +281,9 @@ namespace CSMWorld UpdateCellCommand (IdTable& model, int row, QUndoCommand *parent = 0); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; @@ -318,9 +318,9 @@ namespace CSMWorld DeleteNestedCommand (IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; class AddNestedCommand : public QUndoCommand, private NestedTableStoring @@ -340,9 +340,9 @@ namespace CSMWorld AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0); - virtual void redo(); + void redo() override; - virtual void undo(); + void undo() override; }; } diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 4136061e4..6b7b8d318 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -31,24 +31,23 @@ namespace CSMWorld virtual ~IdTable(); - virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; + int rowCount (const QModelIndex & parent = QModelIndex()) const override; - virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; + int columnCount (const QModelIndex & parent = QModelIndex()) const override; - virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override; - virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - virtual Qt::ItemFlags flags (const QModelIndex & index) const; + Qt::ItemFlags flags (const QModelIndex & index) const override; - virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()) override; - virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) - const; + QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex parent (const QModelIndex& index) const; + QModelIndex parent (const QModelIndex& index) const override; void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None); ///< \param type Will be ignored, unless the collection supports multiple record types @@ -66,7 +65,7 @@ namespace CSMWorld std::string getId(int row) const; - virtual QModelIndex getModelIndex (const std::string& id, int column) const; + QModelIndex getModelIndex (const std::string& id, int column) const override; void setRecord (const std::string& id, const RecordBase& record, UniversalId::Type type = UniversalId::Type_None); @@ -74,10 +73,10 @@ namespace CSMWorld const RecordBase& getRecord (const std::string& id) const; - virtual int searchColumnIndex (Columns::ColumnId id) const; + int searchColumnIndex (Columns::ColumnId id) const override; ///< Return index of column with the given \a id. If no such column exists, -1 is returned. - virtual int findColumnIndex (Columns::ColumnId id) const; + int findColumnIndex (Columns::ColumnId id) const override; ///< Return index of column with the given \a id. If no such column exists, an exception is /// thrown. @@ -85,14 +84,14 @@ namespace CSMWorld ///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices /// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex). - virtual std::pair view (int row) const; + std::pair view (int row) const override; ///< Return the UniversalId and the hint for viewing \a row. If viewing is not /// supported by this table, return (UniversalId::Type_None, ""). /// Is \a id flagged as deleted? - virtual bool isDeleted (const std::string& id) const; + bool isDeleted (const std::string& id) const override; - virtual int getColumnId(int column) const; + int getColumnId(int column) const override; protected: diff --git a/apps/opencs/model/world/idtableproxymodel.hpp b/apps/opencs/model/world/idtableproxymodel.hpp index ad5f267db..14d705792 100644 --- a/apps/opencs/model/world/idtableproxymodel.hpp +++ b/apps/opencs/model/world/idtableproxymodel.hpp @@ -39,7 +39,7 @@ namespace CSMWorld virtual QModelIndex getModelIndex (const std::string& id, int column) const; - virtual void setSourceModel(QAbstractItemModel *model); + void setSourceModel(QAbstractItemModel *model) override; void setFilter (const std::shared_ptr& filter); @@ -47,9 +47,9 @@ namespace CSMWorld protected: - virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; - virtual bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const; + bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const override; QString getRecordId(int sourceRow) const; diff --git a/apps/opencs/model/world/idtree.hpp b/apps/opencs/model/world/idtree.hpp index 1539bd4a2..c525a60b8 100644 --- a/apps/opencs/model/world/idtree.hpp +++ b/apps/opencs/model/world/idtree.hpp @@ -44,22 +44,21 @@ namespace CSMWorld virtual ~IdTree(); - virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; + int rowCount (const QModelIndex & parent = QModelIndex()) const override; - virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; + int columnCount (const QModelIndex & parent = QModelIndex()) const override; - virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override; - virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - virtual Qt::ItemFlags flags (const QModelIndex & index) const; + Qt::ItemFlags flags (const QModelIndex & index) const override; - virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()) override; - virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) - const; + QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex parent (const QModelIndex& index) const; + QModelIndex parent (const QModelIndex& index) const override; QModelIndex getNestedModelIndex (const std::string& id, int column) const; @@ -71,7 +70,7 @@ namespace CSMWorld void addNestedRow (const QModelIndex& parent, int position); - virtual bool hasChildren (const QModelIndex& index) const; + bool hasChildren (const QModelIndex& index) const override; virtual int searchNestedColumnIndex(int parentColumn, Columns::ColumnId id); ///< \return the column index or -1 if the requested column wasn't found. diff --git a/apps/opencs/model/world/infocollection.hpp b/apps/opencs/model/world/infocollection.hpp index e5a5575c7..8f5aea601 100644 --- a/apps/opencs/model/world/infocollection.hpp +++ b/apps/opencs/model/world/infocollection.hpp @@ -29,11 +29,11 @@ namespace CSMWorld public: - virtual int getAppendIndex (const std::string& id, - UniversalId::Type type = UniversalId::Type_None) const; + int getAppendIndex (const std::string& id, + UniversalId::Type type = UniversalId::Type_None) const override; ///< \param type Will be ignored, unless the collection supports multiple record types - virtual bool reorderRows (int baseIndex, const std::vector& newOrder); + bool reorderRows (int baseIndex, const std::vector& newOrder) override; ///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices /// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex). /// diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp index 51d93f9a1..6a8e66b4f 100644 --- a/apps/opencs/model/world/infotableproxymodel.hpp +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -30,15 +30,15 @@ namespace CSMWorld public: InfoTableProxyModel(UniversalId::Type type, QObject *parent = 0); - virtual void setSourceModel(QAbstractItemModel *sourceModel); + void setSourceModel(QAbstractItemModel *sourceModel) override; protected: - virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; protected slots: - virtual void sourceRowsInserted(const QModelIndex &parent, int start, int end); - virtual void sourceRowsRemoved(const QModelIndex &parent, int start, int end); - virtual void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void sourceRowsInserted(const QModelIndex &parent, int start, int end) override; + void sourceRowsRemoved(const QModelIndex &parent, int start, int end) override; + void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) override; }; } diff --git a/apps/opencs/model/world/nestedcoladapterimp.hpp b/apps/opencs/model/world/nestedcoladapterimp.hpp index 60d983098..54780d290 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.hpp +++ b/apps/opencs/model/world/nestedcoladapterimp.hpp @@ -30,24 +30,24 @@ namespace CSMWorld public: PathgridPointListAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class PathgridEdgeListAdapter : public NestedColumnAdapter @@ -55,24 +55,24 @@ namespace CSMWorld public: PathgridEdgeListAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class FactionReactionsAdapter : public NestedColumnAdapter @@ -80,24 +80,24 @@ namespace CSMWorld public: FactionReactionsAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class FactionRanksAdapter : public NestedColumnAdapter @@ -105,24 +105,24 @@ namespace CSMWorld public: FactionRanksAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class RegionSoundListAdapter : public NestedColumnAdapter @@ -130,24 +130,24 @@ namespace CSMWorld public: RegionSoundListAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; template @@ -156,7 +156,7 @@ namespace CSMWorld public: SpellListAdapter () {} - virtual void addRow(Record& record, int position) const + void addRow(Record& record, int position) const override { ESXRecordT raceOrBthSgn = record.get(); @@ -170,7 +170,7 @@ namespace CSMWorld record.setModified (raceOrBthSgn); } - virtual void removeRow(Record& record, int rowToRemove) const + void removeRow(Record& record, int rowToRemove) const override { ESXRecordT raceOrBthSgn = record.get(); @@ -184,7 +184,7 @@ namespace CSMWorld record.setModified (raceOrBthSgn); } - virtual void setTable(Record& record, const NestedTableWrapperBase& nestedTable) const + void setTable(Record& record, const NestedTableWrapperBase& nestedTable) const override { ESXRecordT raceOrBthSgn = record.get(); @@ -194,13 +194,13 @@ namespace CSMWorld record.setModified (raceOrBthSgn); } - virtual NestedTableWrapperBase* table(const Record& record) const + NestedTableWrapperBase* table(const Record& record) const override { // deleted by dtor of NestedTableStoring return new NestedTableWrapper >(record.get().mPowers.mList); } - virtual QVariant getData(const Record& record, int subRowIndex, int subColIndex) const + QVariant getData(const Record& record, int subRowIndex, int subColIndex) const override { ESXRecordT raceOrBthSgn = record.get(); @@ -217,8 +217,8 @@ namespace CSMWorld } } - virtual void setData(Record& record, const QVariant& value, - int subRowIndex, int subColIndex) const + void setData(Record& record, const QVariant& value, + int subRowIndex, int subColIndex) const override { ESXRecordT raceOrBthSgn = record.get(); @@ -239,12 +239,12 @@ namespace CSMWorld record.setModified (raceOrBthSgn); } - virtual int getColumnsCount(const Record& record) const + int getColumnsCount(const Record& record) const override { return 1; } - virtual int getRowsCount(const Record& record) const + int getRowsCount(const Record& record) const override { return static_cast(record.get().mPowers.mList.size()); } @@ -256,7 +256,7 @@ namespace CSMWorld public: EffectsListAdapter () {} - virtual void addRow(Record& record, int position) const + void addRow(Record& record, int position) const override { ESXRecordT magic = record.get(); @@ -278,7 +278,7 @@ namespace CSMWorld record.setModified (magic); } - virtual void removeRow(Record& record, int rowToRemove) const + void removeRow(Record& record, int rowToRemove) const override { ESXRecordT magic = record.get(); @@ -292,7 +292,7 @@ namespace CSMWorld record.setModified (magic); } - virtual void setTable(Record& record, const NestedTableWrapperBase& nestedTable) const + void setTable(Record& record, const NestedTableWrapperBase& nestedTable) const override { ESXRecordT magic = record.get(); @@ -302,13 +302,13 @@ namespace CSMWorld record.setModified (magic); } - virtual NestedTableWrapperBase* table(const Record& record) const + NestedTableWrapperBase* table(const Record& record) const override { // deleted by dtor of NestedTableStoring return new NestedTableWrapper >(record.get().mEffects.mList); } - virtual QVariant getData(const Record& record, int subRowIndex, int subColIndex) const + QVariant getData(const Record& record, int subRowIndex, int subColIndex) const override { ESXRecordT magic = record.get(); @@ -370,8 +370,8 @@ namespace CSMWorld } } - virtual void setData(Record& record, const QVariant& value, - int subRowIndex, int subColIndex) const + void setData(Record& record, const QVariant& value, + int subRowIndex, int subColIndex) const override { ESXRecordT magic = record.get(); @@ -415,12 +415,12 @@ namespace CSMWorld record.setModified (magic); } - virtual int getColumnsCount(const Record& record) const + int getColumnsCount(const Record& record) const override { return 8; } - virtual int getRowsCount(const Record& record) const + int getRowsCount(const Record& record) const override { return static_cast(record.get().mEffects.mList.size()); } @@ -431,24 +431,24 @@ namespace CSMWorld public: InfoListAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class InfoConditionAdapter : public NestedColumnAdapter @@ -456,24 +456,24 @@ namespace CSMWorld public: InfoConditionAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class RaceAttributeAdapter : public NestedColumnAdapter @@ -481,24 +481,24 @@ namespace CSMWorld public: RaceAttributeAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class RaceSkillsBonusAdapter : public NestedColumnAdapter @@ -506,24 +506,24 @@ namespace CSMWorld public: RaceSkillsBonusAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class CellListAdapter : public NestedColumnAdapter @@ -531,24 +531,24 @@ namespace CSMWorld public: CellListAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; class RegionWeatherAdapter : public NestedColumnAdapter @@ -556,24 +556,24 @@ namespace CSMWorld public: RegionWeatherAdapter (); - virtual void addRow(Record& record, int position) const; + void addRow(Record& record, int position) const override; - virtual void removeRow(Record& record, int rowToRemove) const; + void removeRow(Record& record, int rowToRemove) const override; - virtual void setTable(Record& record, - const NestedTableWrapperBase& nestedTable) const; + void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* table(const Record& record) const; + NestedTableWrapperBase* table(const Record& record) const override; - virtual QVariant getData(const Record& record, - int subRowIndex, int subColIndex) const; + QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const override; - virtual void setData(Record& record, - const QVariant& value, int subRowIndex, int subColIndex) const; + void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getColumnsCount(const Record& record) const; + int getColumnsCount(const Record& record) const override; - virtual int getRowsCount(const Record& record) const; + int getRowsCount(const Record& record) const override; }; } diff --git a/apps/opencs/model/world/nestedidcollection.hpp b/apps/opencs/model/world/nestedidcollection.hpp index 56b112365..a699d4bd6 100644 --- a/apps/opencs/model/world/nestedidcollection.hpp +++ b/apps/opencs/model/world/nestedidcollection.hpp @@ -32,24 +32,24 @@ namespace CSMWorld NestedIdCollection (); ~NestedIdCollection(); - virtual void addNestedRow(int row, int column, int position); + void addNestedRow(int row, int column, int position) override; - virtual void removeNestedRows(int row, int column, int subRow); + void removeNestedRows(int row, int column, int subRow) override; - virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const; + QVariant getNestedData(int row, int column, int subRow, int subColumn) const override; - virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn); + void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn) override; - virtual NestedTableWrapperBase* nestedTable(int row, int column) const; + NestedTableWrapperBase* nestedTable(int row, int column) const override; - virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable); + void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable) override; - virtual int getNestedRowsCount(int row, int column) const; + int getNestedRowsCount(int row, int column) const override; - virtual int getNestedColumnsCount(int row, int column) const; + int getNestedColumnsCount(int row, int column) const override; // this method is inherited from NestedCollection, not from Collection - virtual NestableColumn *getNestableColumn(int column); + NestableColumn *getNestableColumn(int column) override; void addAdapter(std::pair* > adapter); }; diff --git a/apps/opencs/model/world/nestedinfocollection.hpp b/apps/opencs/model/world/nestedinfocollection.hpp index 03c0c2349..fe2cd43fa 100644 --- a/apps/opencs/model/world/nestedinfocollection.hpp +++ b/apps/opencs/model/world/nestedinfocollection.hpp @@ -24,24 +24,24 @@ namespace CSMWorld NestedInfoCollection (); ~NestedInfoCollection(); - virtual void addNestedRow(int row, int column, int position); + void addNestedRow(int row, int column, int position) override; - virtual void removeNestedRows(int row, int column, int subRow); + void removeNestedRows(int row, int column, int subRow) override; - virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const; + QVariant getNestedData(int row, int column, int subRow, int subColumn) const override; - virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn); + void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn) override; - virtual NestedTableWrapperBase* nestedTable(int row, int column) const; + NestedTableWrapperBase* nestedTable(int row, int column) const override; - virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable); + void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable) override; - virtual int getNestedRowsCount(int row, int column) const; + int getNestedRowsCount(int row, int column) const override; - virtual int getNestedColumnsCount(int row, int column) const; + int getNestedColumnsCount(int row, int column) const override; // this method is inherited from NestedCollection, not from Collection > - virtual NestableColumn *getNestableColumn(int column); + NestableColumn *getNestableColumn(int column) override; void addAdapter(std::pair* > adapter); }; diff --git a/apps/opencs/model/world/nestedtableproxymodel.hpp b/apps/opencs/model/world/nestedtableproxymodel.hpp index 2d5a46c48..b10f8a3a3 100644 --- a/apps/opencs/model/world/nestedtableproxymodel.hpp +++ b/apps/opencs/model/world/nestedtableproxymodel.hpp @@ -39,25 +39,25 @@ namespace CSMWorld CSMWorld::IdTree* model() const; - virtual QModelIndex mapFromSource(const QModelIndex& sourceIndex) const; + QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; - virtual QModelIndex mapToSource(const QModelIndex& proxyIndex) const; + QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; - virtual int rowCount(const QModelIndex& parent) const; + int rowCount(const QModelIndex& parent) const override; - virtual int columnCount(const QModelIndex& parent) const; + int columnCount(const QModelIndex& parent) const override; - virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex parent(const QModelIndex& index) const; + QModelIndex parent(const QModelIndex& index) const override; - virtual QVariant headerData (int section, Qt::Orientation orientation, int role) const; + QVariant headerData (int section, Qt::Orientation orientation, int role) const override; - virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; - virtual bool setData (const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); + bool setData (const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override; - virtual Qt::ItemFlags flags(const QModelIndex& index) const; + Qt::ItemFlags flags(const QModelIndex& index) const override; private: void setupHeaderVectors(ColumnBase::Display columnId); diff --git a/apps/opencs/model/world/nestedtablewrapper.hpp b/apps/opencs/model/world/nestedtablewrapper.hpp index f0ca00dbe..7d46dff8b 100644 --- a/apps/opencs/model/world/nestedtablewrapper.hpp +++ b/apps/opencs/model/world/nestedtablewrapper.hpp @@ -22,7 +22,7 @@ namespace CSMWorld virtual ~NestedTableWrapper() {} - virtual int size() const + int size() const override { return mNestedTable.size(); //i hope that this will be enough } diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 3362f9f96..82f2abe77 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -45,11 +45,11 @@ namespace CSMWorld Record(State state, const ESXRecordT *base = 0, const ESXRecordT *modified = 0); - virtual RecordBase *clone() const; + RecordBase *clone() const override; - virtual RecordBase *modifiedCopy() const; + RecordBase *modifiedCopy() const override; - virtual void assign (const RecordBase& record); + void assign (const RecordBase& record) override; const ESXRecordT& get() const; ///< Throws an exception, if the record is deleted. diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 6cb6fcd9c..7695e9ace 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -39,15 +39,14 @@ namespace CSMWorld BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base); - virtual std::string getId (const RecordBase& record) const; + std::string getId (const RecordBase& record) const override; - virtual void setId (RecordBase& record, const std::string& id); + void setId (RecordBase& record, const std::string& id) override; - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. UniversalId::Type getType() const; @@ -129,11 +128,11 @@ namespace CSMWorld ModelRefIdAdapter (UniversalId::Type type, const ModelColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -192,11 +191,11 @@ namespace CSMWorld NameRefIdAdapter (UniversalId::Type type, const NameColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -261,11 +260,11 @@ namespace CSMWorld InventoryRefIdAdapter (UniversalId::Type type, const InventoryColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -333,11 +332,11 @@ namespace CSMWorld PotionRefIdAdapter (const PotionColumns& columns, const RefIdColumn *autoCalc); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -356,11 +355,11 @@ namespace CSMWorld IngredientRefIdAdapter (const IngredientColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -378,27 +377,27 @@ namespace CSMWorld virtual ~IngredEffectRefIdAdapter(); - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const; + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override; - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const; + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override; - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const; + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override; - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override; - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override; - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override; }; struct EnchantableColumns : public InventoryColumns @@ -419,11 +418,11 @@ namespace CSMWorld EnchantableRefIdAdapter (UniversalId::Type type, const EnchantableColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -488,11 +487,11 @@ namespace CSMWorld ToolRefIdAdapter (UniversalId::Type type, const ToolColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -563,11 +562,11 @@ namespace CSMWorld ActorRefIdAdapter (UniversalId::Type type, const ActorColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -664,11 +663,11 @@ namespace CSMWorld ApparatusRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *type, const RefIdColumn *quality); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -684,11 +683,11 @@ namespace CSMWorld ArmorRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type, const RefIdColumn *health, const RefIdColumn *armor, const RefIdColumn *partRef); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -703,11 +702,11 @@ namespace CSMWorld BookRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *bookType, const RefIdColumn *skill, const RefIdColumn *text); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -721,11 +720,11 @@ namespace CSMWorld ClothingRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type, const RefIdColumn *partRef); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -741,10 +740,10 @@ namespace CSMWorld ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -770,11 +769,11 @@ namespace CSMWorld CreatureRefIdAdapter (const CreatureColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -788,11 +787,11 @@ namespace CSMWorld DoorRefIdAdapter (const NameColumns& columns, const RefIdColumn *openSound, const RefIdColumn *closeSound); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -816,11 +815,11 @@ namespace CSMWorld LightRefIdAdapter (const LightColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -832,11 +831,11 @@ namespace CSMWorld MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -865,11 +864,11 @@ namespace CSMWorld NpcRefIdAdapter (const NpcColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -895,11 +894,11 @@ namespace CSMWorld WeaponRefIdAdapter (const WeaponColumns& columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -912,27 +911,27 @@ namespace CSMWorld NpcAttributesRefIdAdapter (); - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const; + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override; - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const; + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override; - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const; + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override; - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override; - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override; - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override; }; class NpcSkillsRefIdAdapter : public NestedRefIdAdapterBase @@ -941,27 +940,27 @@ namespace CSMWorld NpcSkillsRefIdAdapter (); - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const; + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override; - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const; + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override; - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const; + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override; - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override; - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override; - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override; }; class NpcMiscRefIdAdapter : public NestedRefIdAdapterBase @@ -974,27 +973,27 @@ namespace CSMWorld NpcMiscRefIdAdapter (); virtual ~NpcMiscRefIdAdapter(); - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const; + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override; - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const; + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override; - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const; + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override; - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override; - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override; - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override; }; class CreatureAttributesRefIdAdapter : public NestedRefIdAdapterBase @@ -1003,27 +1002,27 @@ namespace CSMWorld CreatureAttributesRefIdAdapter (); - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const; + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override; - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const; + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override; - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const; + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override; - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override; - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override; - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override; }; class CreatureAttackRefIdAdapter : public NestedRefIdAdapterBase @@ -1032,27 +1031,27 @@ namespace CSMWorld CreatureAttackRefIdAdapter (); - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const; + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override; - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const; + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override; - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const; + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override; - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override; - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override; - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override; }; class CreatureMiscRefIdAdapter : public NestedRefIdAdapterBase @@ -1065,27 +1064,27 @@ namespace CSMWorld CreatureMiscRefIdAdapter (); virtual ~CreatureMiscRefIdAdapter(); - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const; + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override; - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const; + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override; - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override; - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const; + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override; - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override; - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override; - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override; - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override; }; template @@ -1106,61 +1105,61 @@ namespace CSMWorld virtual ~EffectsRefIdAdapter() {} - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); EffectsListAdapter::addRow(record, position); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); EffectsListAdapter::removeRow(record, rowToRemove); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); EffectsListAdapter::setTable(record, nestedTable); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); return EffectsListAdapter::table(record); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); return EffectsListAdapter::getData(record, subRowIndex, subColIndex); } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); EffectsListAdapter::setData(record, value, subRowIndex, subColIndex); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { const Record record; // not used, just a dummy return EffectsListAdapter::getColumnsCount(record); } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1183,8 +1182,8 @@ namespace CSMWorld virtual ~NestedInventoryRefIdAdapter() {} - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1202,8 +1201,8 @@ namespace CSMWorld record.setModified (container); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1219,8 +1218,8 @@ namespace CSMWorld record.setModified (container); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1232,8 +1231,8 @@ namespace CSMWorld record.setModified (container); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1242,8 +1241,8 @@ namespace CSMWorld return new NestedTableWrapper >(record.get().mInventory.mList); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1264,8 +1263,8 @@ namespace CSMWorld } } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); @@ -1292,12 +1291,12 @@ namespace CSMWorld record.setModified (container); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { return 2; } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1321,8 +1320,8 @@ namespace CSMWorld virtual ~NestedSpellRefIdAdapter() {} - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1340,8 +1339,8 @@ namespace CSMWorld record.setModified (caster); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1357,8 +1356,8 @@ namespace CSMWorld record.setModified (caster); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1370,8 +1369,8 @@ namespace CSMWorld record.setModified (caster); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1380,8 +1379,8 @@ namespace CSMWorld return new NestedTableWrapper >(record.get().mSpells.mList); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1399,8 +1398,8 @@ namespace CSMWorld throw std::runtime_error("Trying to access non-existing column in the nested table!"); } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); @@ -1418,12 +1417,12 @@ namespace CSMWorld record.setModified (caster); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { return 1; } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1447,8 +1446,8 @@ namespace CSMWorld virtual ~NestedTravelRefIdAdapter() {} - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1475,8 +1474,8 @@ namespace CSMWorld record.setModified (traveller); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1492,8 +1491,8 @@ namespace CSMWorld record.setModified (traveller); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1505,8 +1504,8 @@ namespace CSMWorld record.setModified (traveller); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1515,8 +1514,8 @@ namespace CSMWorld return new NestedTableWrapper >(record.get().mTransport.mList); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1542,8 +1541,8 @@ namespace CSMWorld } } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); @@ -1569,12 +1568,12 @@ namespace CSMWorld record.setModified (traveller); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { return 7; } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1600,8 +1599,8 @@ namespace CSMWorld // FIXME: should check if the AI package type is already in the list and use a default // that wasn't used already (in extreme case do not add anything at all? - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1627,8 +1626,8 @@ namespace CSMWorld record.setModified (actor); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1644,8 +1643,8 @@ namespace CSMWorld record.setModified (actor); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1657,8 +1656,8 @@ namespace CSMWorld record.setModified (actor); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1667,8 +1666,8 @@ namespace CSMWorld return new NestedTableWrapper >(record.get().mAiPackage.mList); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1768,8 +1767,8 @@ namespace CSMWorld } } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); @@ -1891,12 +1890,12 @@ namespace CSMWorld record.setModified (actor); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { return 19; } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1921,8 +1920,8 @@ namespace CSMWorld virtual ~BodyPartRefIdAdapter() {} - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1943,8 +1942,8 @@ namespace CSMWorld record.setModified (apparel); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1960,8 +1959,8 @@ namespace CSMWorld record.setModified (apparel); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1973,8 +1972,8 @@ namespace CSMWorld record.setModified (apparel); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -1983,8 +1982,8 @@ namespace CSMWorld return new NestedTableWrapper >(record.get().mParts.mParts); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2012,8 +2011,8 @@ namespace CSMWorld } } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); @@ -2035,12 +2034,12 @@ namespace CSMWorld record.setModified (apparel); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { return 3; } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2067,11 +2066,11 @@ namespace CSMWorld LevelledListRefIdAdapter (UniversalId::Type type, const LevListColumns &columns); - virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) - const; + QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const override; - virtual void setData (const RefIdColumn *column, RefIdData& data, int index, - const QVariant& value) const; + void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const override; ///< If the data type does not match an exception is thrown. }; @@ -2117,32 +2116,32 @@ namespace CSMWorld virtual ~NestedListLevListRefIdAdapter() {} - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { throw std::logic_error ("cannot add a row to a fixed table"); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { throw std::logic_error ("cannot remove a row to a fixed table"); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { throw std::logic_error ("table operation not supported"); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { throw std::logic_error ("table operation not supported"); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2171,8 +2170,8 @@ namespace CSMWorld } } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); @@ -2240,12 +2239,12 @@ namespace CSMWorld record.setModified (leveled); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { return 3; } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { return 1; // fixed at size 1 } @@ -2267,8 +2266,8 @@ namespace CSMWorld virtual ~NestedLevListRefIdAdapter() {} - virtual void addNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int position) const + void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2288,8 +2287,8 @@ namespace CSMWorld record.setModified (leveled); } - virtual void removeNestedRow (const RefIdColumn *column, - RefIdData& data, int index, int rowToRemove) const + void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2305,8 +2304,8 @@ namespace CSMWorld record.setModified (leveled); } - virtual void setNestedTable (const RefIdColumn* column, - RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const + void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2318,8 +2317,8 @@ namespace CSMWorld record.setModified (leveled); } - virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, - const RefIdData& data, int index) const + NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2328,8 +2327,8 @@ namespace CSMWorld return new NestedTableWrapper >(record.get().mList); } - virtual QVariant getNestedData (const RefIdColumn *column, - const RefIdData& data, int index, int subRowIndex, int subColIndex) const + QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); @@ -2350,8 +2349,8 @@ namespace CSMWorld } } - virtual void setNestedData (const RefIdColumn *column, - RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const + void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const override { Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); @@ -2372,12 +2371,12 @@ namespace CSMWorld record.setModified (leveled); } - virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const + int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const override { return 2; } - virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const + int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const override { const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index 48558d1c2..e85263ac1 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -32,9 +32,9 @@ namespace CSMWorld int flag = Flag_Table | Flag_Dialogue, bool editable = true, bool userEditable = true); - virtual bool isEditable() const; + bool isEditable() const override; - virtual bool isUserEditable() const; + bool isUserEditable() const override; }; class RefIdCollection : public CollectionBase, public NestedCollection @@ -60,82 +60,82 @@ namespace CSMWorld virtual ~RefIdCollection(); - virtual int getSize() const; + int getSize() const override; - virtual std::string getId (int index) const; + std::string getId (int index) const override; - virtual int getIndex (const std::string& id) const; + int getIndex (const std::string& id) const override; - virtual int getColumns() const; + int getColumns() const override; - virtual const ColumnBase& getColumn (int column) const; + const ColumnBase& getColumn (int column) const override; - virtual QVariant getData (int index, int column) const; + QVariant getData (int index, int column) const override; - virtual void setData (int index, int column, const QVariant& data); + void setData (int index, int column, const QVariant& data) override; - virtual void removeRows (int index, int count); + void removeRows (int index, int count) override; - virtual void cloneRecord(const std::string& origin, + void cloneRecord(const std::string& origin, const std::string& destination, - const UniversalId::Type type); + const UniversalId::Type type) override; - virtual bool touchRecord(const std::string& id); + bool touchRecord(const std::string& id) override; - virtual void appendBlankRecord (const std::string& id, UniversalId::Type type); + void appendBlankRecord (const std::string& id, UniversalId::Type type) override; ///< \param type Will be ignored, unless the collection supports multiple record types - virtual int searchId (const std::string& id) const; + int searchId (const std::string& id) const override; ////< Search record with \a id. /// \return index of record (if found) or -1 (not found) - virtual void replace (int index, const RecordBase& record); + void replace (int index, const RecordBase& record) override; ///< If the record type does not match, an exception is thrown. /// /// \attention \a record must not change the ID. - virtual void appendRecord (const RecordBase& record, UniversalId::Type type); + void appendRecord (const RecordBase& record, UniversalId::Type type) override; ///< If the record type does not match, an exception is thrown. /// ///< \param type Will be ignored, unless the collection supports multiple record types - virtual const RecordBase& getRecord (const std::string& id) const; + const RecordBase& getRecord (const std::string& id) const override; - virtual const RecordBase& getRecord (int index) const; + const RecordBase& getRecord (int index) const override; void load (ESM::ESMReader& reader, bool base, UniversalId::Type type); - virtual int getAppendIndex (const std::string& id, UniversalId::Type type) const; + int getAppendIndex (const std::string& id, UniversalId::Type type) const override; ///< \param type Will be ignored, unless the collection supports multiple record types - virtual std::vector getIds (bool listDeleted) const; + std::vector getIds (bool listDeleted) const override; ///< Return a sorted collection of all IDs /// /// \param listDeleted include deleted record in the list - virtual bool reorderRows (int baseIndex, const std::vector& newOrder); + bool reorderRows (int baseIndex, const std::vector& newOrder) override; ///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices /// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex). /// /// \return Success? - virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const; + QVariant getNestedData(int row, int column, int subRow, int subColumn) const override; - virtual NestedTableWrapperBase* nestedTable(int row, int column) const; + NestedTableWrapperBase* nestedTable(int row, int column) const override; - virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable); + void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable) override; - virtual int getNestedRowsCount(int row, int column) const; + int getNestedRowsCount(int row, int column) const override; - virtual int getNestedColumnsCount(int row, int column) const; + int getNestedColumnsCount(int row, int column) const override; - NestableColumn *getNestableColumn(int column); + NestableColumn *getNestableColumn(int column) override; - virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn); + void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn) override; - virtual void removeNestedRows(int row, int column, int subRow); + void removeNestedRows(int row, int column, int subRow) override; - virtual void addNestedRow(int row, int col, int position); + void addNestedRow(int row, int col, int position) override; void save (int index, ESM::ESMWriter& writer) const; diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index 94f641edc..1480bb71d 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -66,24 +66,24 @@ namespace CSMWorld { std::vector > mContainer; - virtual int getSize() const; + int getSize() const override; - virtual const RecordBase& getRecord (int index) const; + const RecordBase& getRecord (int index) const override; - virtual RecordBase& getRecord (int index); + RecordBase& getRecord (int index) override; - virtual void appendRecord (const std::string& id, bool base); + void appendRecord (const std::string& id, bool base) override; - virtual void insertRecord (RecordBase& record); + void insertRecord (RecordBase& record) override; - virtual int load (ESM::ESMReader& reader, bool base); + int load (ESM::ESMReader& reader, bool base) override; ///< \return index of a loaded record or -1 if no record was loaded - virtual void erase (int index, int count); + void erase (int index, int count) override; - virtual std::string getId (int index) const; + std::string getId (int index) const override; - virtual void save (int index, ESM::ESMWriter& writer) const; + void save (int index, ESM::ESMWriter& writer) const override; }; template diff --git a/apps/opencs/model/world/regionmap.hpp b/apps/opencs/model/world/regionmap.hpp index 7d7685e89..1de7f1cdb 100644 --- a/apps/opencs/model/world/regionmap.hpp +++ b/apps/opencs/model/world/regionmap.hpp @@ -91,15 +91,15 @@ namespace CSMWorld RegionMap (Data& data); - virtual int rowCount (const QModelIndex& parent = QModelIndex()) const; + int rowCount (const QModelIndex& parent = QModelIndex()) const override; - virtual int columnCount (const QModelIndex& parent = QModelIndex()) const; + int columnCount (const QModelIndex& parent = QModelIndex()) const override; - virtual QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const; + QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const override; ///< \note Calling this function with role==Role_CellId may return the ID of a cell /// that does not exist. - virtual Qt::ItemFlags flags (const QModelIndex& index) const; + Qt::ItemFlags flags (const QModelIndex& index) const override; private slots: diff --git a/apps/opencs/model/world/resourcetable.hpp b/apps/opencs/model/world/resourcetable.hpp index 7d538df53..8a3fab8a2 100644 --- a/apps/opencs/model/world/resourcetable.hpp +++ b/apps/opencs/model/world/resourcetable.hpp @@ -18,41 +18,40 @@ namespace CSMWorld virtual ~ResourceTable(); - virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; + int rowCount (const QModelIndex & parent = QModelIndex()) const override; - virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; + int columnCount (const QModelIndex & parent = QModelIndex()) const override; - virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override; - virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - virtual Qt::ItemFlags flags (const QModelIndex & index) const; + Qt::ItemFlags flags (const QModelIndex & index) const override; - virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) - const; + QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex parent (const QModelIndex& index) const; + QModelIndex parent (const QModelIndex& index) const override; - virtual QModelIndex getModelIndex (const std::string& id, int column) const; + QModelIndex getModelIndex (const std::string& id, int column) const override; /// Return index of column with the given \a id. If no such column exists, -1 is /// returned. - virtual int searchColumnIndex (Columns::ColumnId id) const; + int searchColumnIndex (Columns::ColumnId id) const override; /// Return index of column with the given \a id. If no such column exists, an /// exception is thrown. - virtual int findColumnIndex (Columns::ColumnId id) const; + int findColumnIndex (Columns::ColumnId id) const override; /// Return the UniversalId and the hint for viewing \a row. If viewing is not /// supported by this table, return (UniversalId::Type_None, ""). - virtual std::pair view (int row) const; + std::pair view (int row) const override; /// Is \a id flagged as deleted? - virtual bool isDeleted (const std::string& id) const; + bool isDeleted (const std::string& id) const override; - virtual int getColumnId (int column) const; + int getColumnId (int column) const override; /// Signal Qt that the data is about to change. void beginReset(); diff --git a/apps/opencs/model/world/scriptcontext.hpp b/apps/opencs/model/world/scriptcontext.hpp index 2cd59f070..8e1a5e57b 100644 --- a/apps/opencs/model/world/scriptcontext.hpp +++ b/apps/opencs/model/world/scriptcontext.hpp @@ -23,23 +23,23 @@ namespace CSMWorld ScriptContext (const Data& data); - virtual bool canDeclareLocals() const; + bool canDeclareLocals() const override; ///< Is the compiler allowed to declare local variables? - virtual char getGlobalType (const std::string& name) const; + char getGlobalType (const std::string& name) const override; ///< 'l: long, 's': short, 'f': float, ' ': does not exist. - virtual std::pair getMemberType (const std::string& name, - const std::string& id) const; + std::pair getMemberType (const std::string& name, + const std::string& id) const override; ///< Return type of member variable \a name in script \a id or in script of reference of /// \a id /// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist. /// second: true: script of reference - virtual bool isId (const std::string& name) const; + bool isId (const std::string& name) const override; ///< Does \a name match an ID, that can be referenced? - virtual bool isJournalId (const std::string& name) const; + bool isJournalId (const std::string& name) const override; ///< Does \a name match a journal ID? void invalidateIds(); diff --git a/apps/opencs/model/world/subcellcollection.hpp b/apps/opencs/model/world/subcellcollection.hpp index 496cb0643..a60929680 100644 --- a/apps/opencs/model/world/subcellcollection.hpp +++ b/apps/opencs/model/world/subcellcollection.hpp @@ -20,7 +20,7 @@ namespace CSMWorld { const IdCollection& mCells; - virtual void loadRecord (ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted); + void loadRecord (ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted) override; public: diff --git a/apps/opencs/model/world/tablemimedata.hpp b/apps/opencs/model/world/tablemimedata.hpp index 3be8054bd..234524912 100644 --- a/apps/opencs/model/world/tablemimedata.hpp +++ b/apps/opencs/model/world/tablemimedata.hpp @@ -36,7 +36,7 @@ namespace CSMWorld ~TableMimeData(); - virtual QStringList formats() const; + QStringList formats() const override; std::string getIcon() const; diff --git a/apps/opencs/view/doc/loader.hpp b/apps/opencs/view/doc/loader.hpp index e004007c9..24cbee788 100644 --- a/apps/opencs/view/doc/loader.hpp +++ b/apps/opencs/view/doc/loader.hpp @@ -38,7 +38,7 @@ namespace CSVDoc private: - void closeEvent (QCloseEvent *event); + void closeEvent (QCloseEvent *event) override; public: diff --git a/apps/opencs/view/doc/newgame.hpp b/apps/opencs/view/doc/newgame.hpp index 70e9d684b..e3c6f53ca 100644 --- a/apps/opencs/view/doc/newgame.hpp +++ b/apps/opencs/view/doc/newgame.hpp @@ -44,7 +44,7 @@ namespace CSVDoc void create(); - void reject(); + void reject() override; }; } diff --git a/apps/opencs/view/doc/runlogsubview.hpp b/apps/opencs/view/doc/runlogsubview.hpp index cfb676a37..e7b490fff 100644 --- a/apps/opencs/view/doc/runlogsubview.hpp +++ b/apps/opencs/view/doc/runlogsubview.hpp @@ -13,7 +13,7 @@ namespace CSVDoc RunLogSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; }; } diff --git a/apps/opencs/view/doc/sizehint.hpp b/apps/opencs/view/doc/sizehint.hpp index cf5a02580..1b3c52eb8 100644 --- a/apps/opencs/view/doc/sizehint.hpp +++ b/apps/opencs/view/doc/sizehint.hpp @@ -14,7 +14,7 @@ namespace CSVDoc SizeHintWidget(QWidget *parent = 0); ~SizeHintWidget(); - virtual QSize sizeHint() const; + QSize sizeHint() const override; void setSizeHint(const QSize &size); }; } diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 44b81743f..ca9ca8225 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -34,7 +34,7 @@ namespace CSVDoc void setUniversalId(const CSMWorld::UniversalId& id); - bool event (QEvent *event); + bool event (QEvent *event) override; public: @@ -54,7 +54,7 @@ namespace CSVDoc private: - void closeEvent (QCloseEvent *event); + void closeEvent (QCloseEvent *event) override; signals: diff --git a/apps/opencs/view/doc/subviewfactoryimp.hpp b/apps/opencs/view/doc/subviewfactoryimp.hpp index 670137985..152b443a3 100644 --- a/apps/opencs/view/doc/subviewfactoryimp.hpp +++ b/apps/opencs/view/doc/subviewfactoryimp.hpp @@ -12,7 +12,7 @@ namespace CSVDoc { public: - virtual CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) override; }; template @@ -32,7 +32,7 @@ namespace CSVDoc SubViewFactoryWithCreator (bool sorting = true); - virtual CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) override; }; template diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 87c312412..322bcdfb7 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -64,7 +64,7 @@ namespace CSVDoc private: - void closeEvent (QCloseEvent *event); + void closeEvent (QCloseEvent *event) override; QAction* createMenuEntry(CSMWorld::UniversalId::Type type, QMenu* menu, const char* shortcutName); QAction* createMenuEntry(const std::string& title, const std::string& iconName, QMenu* menu, const char* shortcutName); diff --git a/apps/opencs/view/filter/filterbox.hpp b/apps/opencs/view/filter/filterbox.hpp index e794a9880..94aa80b84 100644 --- a/apps/opencs/view/filter/filterbox.hpp +++ b/apps/opencs/view/filter/filterbox.hpp @@ -34,11 +34,11 @@ namespace CSVFilter private: - void dragEnterEvent (QDragEnterEvent* event); + void dragEnterEvent (QDragEnterEvent* event) override; - void dropEvent (QDropEvent* event); + void dropEvent (QDropEvent* event) override; - void dragMoveEvent(QDragMoveEvent *event); + void dragMoveEvent(QDragMoveEvent *event) override; signals: void recordFilterChanged (std::shared_ptr filter); diff --git a/apps/opencs/view/prefs/contextmenulist.hpp b/apps/opencs/view/prefs/contextmenulist.hpp index a3b6c9735..f527057d2 100644 --- a/apps/opencs/view/prefs/contextmenulist.hpp +++ b/apps/opencs/view/prefs/contextmenulist.hpp @@ -18,9 +18,9 @@ namespace CSVPrefs protected: - void contextMenuEvent(QContextMenuEvent* e); + void contextMenuEvent(QContextMenuEvent* e) override; - void mousePressEvent(QMouseEvent* e); + void mousePressEvent(QMouseEvent* e) override; private slots: diff --git a/apps/opencs/view/prefs/dialogue.hpp b/apps/opencs/view/prefs/dialogue.hpp index ce017209a..2e0975649 100644 --- a/apps/opencs/view/prefs/dialogue.hpp +++ b/apps/opencs/view/prefs/dialogue.hpp @@ -34,7 +34,7 @@ namespace CSVPrefs protected: - void closeEvent (QCloseEvent *event); + void closeEvent (QCloseEvent *event) override; public slots: diff --git a/apps/opencs/view/prefs/pagebase.hpp b/apps/opencs/view/prefs/pagebase.hpp index 91a4dee5b..ce5b378b3 100644 --- a/apps/opencs/view/prefs/pagebase.hpp +++ b/apps/opencs/view/prefs/pagebase.hpp @@ -26,7 +26,7 @@ namespace CSVPrefs protected: - void contextMenuEvent(QContextMenuEvent*); + void contextMenuEvent(QContextMenuEvent*) override; private slots: diff --git a/apps/opencs/view/render/cameracontroller.hpp b/apps/opencs/view/render/cameracontroller.hpp index 658e572c5..dff0f212e 100644 --- a/apps/opencs/view/render/cameracontroller.hpp +++ b/apps/opencs/view/render/cameracontroller.hpp @@ -96,10 +96,10 @@ namespace CSVRender void fixUpAxis(const osg::Vec3d& up); void unfixUpAxis(); - void handleMouseMoveEvent(int x, int y); - void handleMouseScrollEvent(int x); + void handleMouseMoveEvent(int x, int y) override; + void handleMouseScrollEvent(int x) override; - void update(double dt); + void update(double dt) override; private: @@ -152,10 +152,10 @@ namespace CSVRender void setOrbitSpeedMultiplier(double value); void setPickingMask(unsigned int value); - void handleMouseMoveEvent(int x, int y); - void handleMouseScrollEvent(int x); + void handleMouseMoveEvent(int x, int y) override; + void handleMouseScrollEvent(int x) override; - void update(double dt); + void update(double dt) override; /// \brief Flag controller to be re-initialized. void reset(); diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 056c50e45..c18c29efe 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -45,7 +45,7 @@ namespace CSVRender { public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { traverse(node, nv); CellNodeContainer* container = static_cast(node->getUserData()); diff --git a/apps/opencs/view/render/cellarrow.hpp b/apps/opencs/view/render/cellarrow.hpp index 452356194..9a49b80db 100644 --- a/apps/opencs/view/render/cellarrow.hpp +++ b/apps/opencs/view/render/cellarrow.hpp @@ -27,7 +27,7 @@ namespace CSVRender CellArrow *getCellArrow() const; - virtual QString getToolTip (bool hideBasics) const; + QString getToolTip (bool hideBasics) const override; }; diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index 911594327..c0482c81a 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -34,7 +34,7 @@ namespace CSVRender unsigned int getInteractionMask() const; - virtual void activate (CSVWidget::SceneToolbar *toolbar); + void activate (CSVWidget::SceneToolbar *toolbar) override; /// Default-implementation: Ignored. virtual void setEditLock (bool locked); @@ -90,15 +90,15 @@ namespace CSVRender virtual void dragWheel (int diff, double speedFactor); /// Default-implementation: ignored - virtual void dragEnterEvent (QDragEnterEvent *event); + void dragEnterEvent (QDragEnterEvent *event) override; /// Default-implementation: ignored - virtual void dropEvent (QDropEvent *event); + void dropEvent (QDropEvent *event) override; /// Default-implementation: ignored - virtual void dragMoveEvent (QDragMoveEvent *event); + void dragMoveEvent (QDragMoveEvent *event) override; - virtual void mouseMoveEvent (QMouseEvent *event); + void mouseMoveEvent (QMouseEvent *event) override; /// Default: return -1 virtual int getSubMode() const; diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index beb60aff3..29955feef 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -64,41 +64,41 @@ namespace CSVRender InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr parentNode, QWidget *parent = 0); - virtual void activate (CSVWidget::SceneToolbar *toolbar); + void activate (CSVWidget::SceneToolbar *toolbar) override; - virtual void deactivate (CSVWidget::SceneToolbar *toolbar); + void deactivate (CSVWidget::SceneToolbar *toolbar) override; - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; - virtual void primaryOpenPressed (const WorldspaceHitResult& hit); + void primaryOpenPressed (const WorldspaceHitResult& hit) override; - virtual void primaryEditPressed (const WorldspaceHitResult& hit); + void primaryEditPressed (const WorldspaceHitResult& hit) override; - virtual void secondaryEditPressed (const WorldspaceHitResult& hit); + void secondaryEditPressed (const WorldspaceHitResult& hit) override; - virtual void primarySelectPressed (const WorldspaceHitResult& hit); + void primarySelectPressed (const WorldspaceHitResult& hit) override; - virtual void secondarySelectPressed (const WorldspaceHitResult& hit); + void secondarySelectPressed (const WorldspaceHitResult& hit) override; - virtual bool primaryEditStartDrag (const QPoint& pos); + bool primaryEditStartDrag (const QPoint& pos) override; - virtual bool secondaryEditStartDrag (const QPoint& pos); + bool secondaryEditStartDrag (const QPoint& pos) override; - virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); + void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) override; - virtual void dragCompleted(const QPoint& pos); + void dragCompleted(const QPoint& pos) override; /// \note dragAborted will not be called, if the drag is aborted via changing /// editing mode - virtual void dragAborted(); + void dragAborted() override; - virtual void dragWheel (int diff, double speedFactor); + void dragWheel (int diff, double speedFactor) override; - virtual void dragEnterEvent (QDragEnterEvent *event); + void dragEnterEvent (QDragEnterEvent *event) override; - virtual void dropEvent (QDropEvent *event); + void dropEvent (QDropEvent *event) override; - virtual int getSubMode() const; + int getSubMode() const override; signals: diff --git a/apps/opencs/view/render/instanceselectionmode.hpp b/apps/opencs/view/render/instanceselectionmode.hpp index a590240d9..a23811671 100644 --- a/apps/opencs/view/render/instanceselectionmode.hpp +++ b/apps/opencs/view/render/instanceselectionmode.hpp @@ -21,7 +21,7 @@ namespace CSVRender /// /// \return Have there been any menu items to be added (if menu is 0 and there /// items to be added, the function must return true anyway. - bool createContextMenu(QMenu* menu); + bool createContextMenu(QMenu* menu) override; private: diff --git a/apps/opencs/view/render/lighting.cpp b/apps/opencs/view/render/lighting.cpp index f62e86148..82ad43e6a 100644 --- a/apps/opencs/view/render/lighting.cpp +++ b/apps/opencs/view/render/lighting.cpp @@ -14,7 +14,7 @@ public: , mIndex(index) { } - virtual void apply(osg::Switch &switchNode) + void apply(osg::Switch &switchNode) override { if (switchNode.getName() == Constants::NightDayLabel) switchNode.setSingleChildOn(mIndex); diff --git a/apps/opencs/view/render/lightingbright.hpp b/apps/opencs/view/render/lightingbright.hpp index 7bdebfd3d..aa1492752 100644 --- a/apps/opencs/view/render/lightingbright.hpp +++ b/apps/opencs/view/render/lightingbright.hpp @@ -17,11 +17,11 @@ namespace CSVRender LightingBright(); - virtual void activate (osg::Group* rootNode, bool /*isExterior*/); + void activate (osg::Group* rootNode, bool /*isExterior*/) override; - virtual void deactivate(); + void deactivate() override; - virtual osg::Vec4f getAmbientColour(osg::Vec4f* defaultAmbient); + osg::Vec4f getAmbientColour(osg::Vec4f* defaultAmbient) override; }; } diff --git a/apps/opencs/view/render/lightingday.hpp b/apps/opencs/view/render/lightingday.hpp index 516dd2bbf..eafc6b8e8 100644 --- a/apps/opencs/view/render/lightingday.hpp +++ b/apps/opencs/view/render/lightingday.hpp @@ -11,11 +11,11 @@ namespace CSVRender LightingDay(); - virtual void activate (osg::Group* rootNode, bool /*isExterior*/); + void activate (osg::Group* rootNode, bool /*isExterior*/) override; - virtual void deactivate(); + void deactivate() override; - virtual osg::Vec4f getAmbientColour(osg::Vec4f *defaultAmbient); + osg::Vec4f getAmbientColour(osg::Vec4f *defaultAmbient) override; }; } diff --git a/apps/opencs/view/render/lightingnight.hpp b/apps/opencs/view/render/lightingnight.hpp index 3f03150cd..bfa94ce97 100644 --- a/apps/opencs/view/render/lightingnight.hpp +++ b/apps/opencs/view/render/lightingnight.hpp @@ -11,10 +11,10 @@ namespace CSVRender LightingNight(); - virtual void activate (osg::Group* rootNode, bool isExterior); - virtual void deactivate(); + void activate (osg::Group* rootNode, bool isExterior) override; + void deactivate() override; - virtual osg::Vec4f getAmbientColour(osg::Vec4f *defaultAmbient); + osg::Vec4f getAmbientColour(osg::Vec4f *defaultAmbient) override; }; } diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index 4d1763f80..a19d64223 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -54,7 +54,7 @@ namespace CSVRender Object* mObject; - virtual QString getToolTip (bool hideBasics) const; + QString getToolTip (bool hideBasics) const override; }; class ObjectMarkerTag : public ObjectTag diff --git a/apps/opencs/view/render/orbitcameramode.hpp b/apps/opencs/view/render/orbitcameramode.hpp index 90c9e97f4..10bc97b0f 100644 --- a/apps/opencs/view/render/orbitcameramode.hpp +++ b/apps/opencs/view/render/orbitcameramode.hpp @@ -24,9 +24,9 @@ namespace CSVRender QWidget* parent = nullptr); ~OrbitCameraMode(); - virtual void activate(CSVWidget::SceneToolbar* toolbar); - virtual void deactivate(CSVWidget::SceneToolbar* toolbar); - virtual bool createContextMenu(QMenu* menu); + void activate(CSVWidget::SceneToolbar* toolbar) override; + void deactivate(CSVWidget::SceneToolbar* toolbar) override; + bool createContextMenu(QMenu* menu) override; private: diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index fcc55fe7d..d17670cfa 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -39,26 +39,26 @@ namespace CSVRender /// \return Any cells added or removed? bool adjustCells(); - virtual void referenceableDataChanged (const QModelIndex& topLeft, - const QModelIndex& bottomRight); + void referenceableDataChanged (const QModelIndex& topLeft, + const QModelIndex& bottomRight) override; - virtual void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end); + void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end) override; - virtual void referenceableAdded (const QModelIndex& index, int start, int end); + void referenceableAdded (const QModelIndex& index, int start, int end) override; - virtual void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); + void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) override; - virtual void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end); + void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end) override; - virtual void referenceAdded (const QModelIndex& index, int start, int end); + void referenceAdded (const QModelIndex& index, int start, int end) override; - virtual void pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); + void pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) override; - virtual void pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end); + void pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end) override; - virtual void pathgridAdded (const QModelIndex& parent, int start, int end); + void pathgridAdded (const QModelIndex& parent, int start, int end) override; - virtual std::string getStartupInstruction(); + std::string getStartupInstruction() override; /// \note Does not update the view or any cell marker void addCellToScene (const CSMWorld::CellCoordinates& coordinates); @@ -86,45 +86,45 @@ namespace CSVRender virtual ~PagedWorldspaceWidget(); /// Decodes the the hint string to set of cell that are rendered. - void useViewHint (const std::string& hint); + void useViewHint (const std::string& hint) override; void setCellSelection(const CSMWorld::CellSelection& selection); const CSMWorld::CellSelection& getCellSelection() const; /// \return Drop handled? - virtual bool handleDrop (const std::vector& data, - DropType type); + bool handleDrop (const std::vector& data, + DropType type) override; - virtual dropRequirments getDropRequirements(DropType type) const; + dropRequirments getDropRequirements(DropType type) const override; /// \attention The created tool is not added to the toolbar (via addTool). Doing /// that is the responsibility of the calling function. virtual CSVWidget::SceneToolToggle2 *makeControlVisibilitySelector ( CSVWidget::SceneToolbar *parent); - virtual unsigned int getVisibilityMask() const; + unsigned int getVisibilityMask() const override; /// \param elementMask Elements to be affected by the clear operation - virtual void clearSelection (int elementMask); + void clearSelection (int elementMask) override; /// \param elementMask Elements to be affected by the select operation - virtual void invertSelection (int elementMask); + void invertSelection (int elementMask) override; /// \param elementMask Elements to be affected by the select operation - virtual void selectAll (int elementMask); + void selectAll (int elementMask) override; // Select everything that references the same ID as at least one of the elements // already selected // /// \param elementMask Elements to be affected by the select operation - virtual void selectAllWithSameParentId (int elementMask); + void selectAllWithSameParentId (int elementMask) override; - virtual std::string getCellId (const osg::Vec3f& point) const; + std::string getCellId (const osg::Vec3f& point) const override; - virtual Cell* getCell(const osg::Vec3d& point) const; + Cell* getCell(const osg::Vec3d& point) const override; - virtual Cell* getCell(const CSMWorld::CellCoordinates& coords) const; + Cell* getCell(const CSMWorld::CellCoordinates& coords) const override; void setCellAlteredHeight(const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float height); @@ -132,24 +132,24 @@ namespace CSVRender void resetAllAlteredHeights(); - virtual std::vector > getSelection (unsigned int elementMask) - const; + std::vector > getSelection (unsigned int elementMask) + const override; - virtual std::vector > getEdited (unsigned int elementMask) - const; + std::vector > getEdited (unsigned int elementMask) + const override; - virtual void setSubMode (int subMode, unsigned int elementMask); + void setSubMode (int subMode, unsigned int elementMask) override; /// Erase all overrides and restore the visual representation to its true state. - virtual void reset (unsigned int elementMask); + void reset (unsigned int elementMask) override; protected: - virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool); + void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool) override; - virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); + void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool) override; - virtual void handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type); + void handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type) override; signals: diff --git a/apps/opencs/view/render/pathgrid.cpp b/apps/opencs/view/render/pathgrid.cpp index d8acfe2e1..7f0454d8f 100644 --- a/apps/opencs/view/render/pathgrid.cpp +++ b/apps/opencs/view/render/pathgrid.cpp @@ -23,7 +23,7 @@ namespace CSVRender { public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { PathgridTag* tag = static_cast(node->getUserData()); tag->getPathgrid()->update(); diff --git a/apps/opencs/view/render/pathgrid.hpp b/apps/opencs/view/render/pathgrid.hpp index 181a62b44..8f5d45a48 100644 --- a/apps/opencs/view/render/pathgrid.hpp +++ b/apps/opencs/view/render/pathgrid.hpp @@ -40,7 +40,7 @@ namespace CSVRender Pathgrid* getPathgrid () const; - virtual QString getToolTip (bool hideBasics) const; + QString getToolTip (bool hideBasics) const override; private: diff --git a/apps/opencs/view/render/pathgridmode.hpp b/apps/opencs/view/render/pathgridmode.hpp index a012a67e4..6d8f96e8c 100644 --- a/apps/opencs/view/render/pathgridmode.hpp +++ b/apps/opencs/view/render/pathgridmode.hpp @@ -17,31 +17,31 @@ namespace CSVRender PathgridMode(WorldspaceWidget* worldspace, QWidget* parent=0); - virtual void activate(CSVWidget::SceneToolbar* toolbar); + void activate(CSVWidget::SceneToolbar* toolbar) override; - virtual void deactivate(CSVWidget::SceneToolbar* toolbar); + void deactivate(CSVWidget::SceneToolbar* toolbar) override; - virtual void primaryOpenPressed(const WorldspaceHitResult& hit); + void primaryOpenPressed(const WorldspaceHitResult& hit) override; - virtual void primaryEditPressed(const WorldspaceHitResult& hit); + void primaryEditPressed(const WorldspaceHitResult& hit) override; - virtual void secondaryEditPressed(const WorldspaceHitResult& hit); + void secondaryEditPressed(const WorldspaceHitResult& hit) override; - virtual void primarySelectPressed(const WorldspaceHitResult& hit); + void primarySelectPressed(const WorldspaceHitResult& hit) override; - virtual void secondarySelectPressed(const WorldspaceHitResult& hit); + void secondarySelectPressed(const WorldspaceHitResult& hit) override; - virtual bool primaryEditStartDrag (const QPoint& pos); + bool primaryEditStartDrag (const QPoint& pos) override; - virtual bool secondaryEditStartDrag (const QPoint& pos); + bool secondaryEditStartDrag (const QPoint& pos) override; - virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor); + void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) override; - virtual void dragCompleted(const QPoint& pos); + void dragCompleted(const QPoint& pos) override; /// \note dragAborted will not be called, if the drag is aborted via changing /// editing mode - virtual void dragAborted(); + void dragAborted() override; private: diff --git a/apps/opencs/view/render/pathgridselectionmode.hpp b/apps/opencs/view/render/pathgridselectionmode.hpp index e4cb1e044..19bfca803 100644 --- a/apps/opencs/view/render/pathgridselectionmode.hpp +++ b/apps/opencs/view/render/pathgridselectionmode.hpp @@ -21,7 +21,7 @@ namespace CSVRender /// /// \return Have there been any menu items to be added (if menu is 0 and there /// items to be added, the function must return true anyway. - bool createContextMenu(QMenu* menu); + bool createContextMenu(QMenu* menu) override; private: diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 85b898d04..6a94254b9 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -97,8 +97,8 @@ namespace CSVRender void setAmbient(const osg::Vec4f& ambient); - virtual void mouseMoveEvent (QMouseEvent *event); - virtual void wheelEvent (QWheelEvent *event); + void mouseMoveEvent (QMouseEvent *event) override; + void wheelEvent (QWheelEvent *event) override; std::shared_ptr mResourceSystem; diff --git a/apps/opencs/view/render/selectionmode.hpp b/apps/opencs/view/render/selectionmode.hpp index f28888bfd..95f6de41b 100644 --- a/apps/opencs/view/render/selectionmode.hpp +++ b/apps/opencs/view/render/selectionmode.hpp @@ -30,7 +30,7 @@ namespace CSVRender /// /// \return Have there been any menu items to be added (if menu is 0 and there /// items to be added, the function must return true anyway. - virtual bool createContextMenu (QMenu* menu); + bool createContextMenu (QMenu* menu) override; private: diff --git a/apps/opencs/view/render/terrainstorage.hpp b/apps/opencs/view/render/terrainstorage.hpp index 74c30ce5c..21faf9b64 100644 --- a/apps/opencs/view/render/terrainstorage.hpp +++ b/apps/opencs/view/render/terrainstorage.hpp @@ -19,7 +19,7 @@ namespace CSVRender void setAlteredHeight(int inCellX, int inCellY, float heightMap); void resetHeights(); - virtual bool useAlteration() const { return true; } + bool useAlteration() const override { return true; } float getSumOfAlteredAndTrueHeight(int cellX, int cellY, int inCellX, int inCellY); float* getAlteredHeight(int inCellX, int inCellY); diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index d169220f9..eec1b01f3 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.hpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.hpp @@ -39,71 +39,70 @@ namespace CSVRender UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget *parent); - virtual dropRequirments getDropRequirements(DropType type) const; + dropRequirments getDropRequirements(DropType type) const override; /// \return Drop handled? - virtual bool handleDrop (const std::vector& data, - DropType type); + bool handleDrop (const std::vector& data, + DropType type) override; /// \param elementMask Elements to be affected by the clear operation - virtual void clearSelection (int elementMask); + void clearSelection (int elementMask) override; /// \param elementMask Elements to be affected by the select operation - virtual void invertSelection (int elementMask); + void invertSelection (int elementMask) override; /// \param elementMask Elements to be affected by the select operation - virtual void selectAll (int elementMask); + void selectAll (int elementMask) override; // Select everything that references the same ID as at least one of the elements // already selected // /// \param elementMask Elements to be affected by the select operation - virtual void selectAllWithSameParentId (int elementMask); + void selectAllWithSameParentId (int elementMask) override; - virtual std::string getCellId (const osg::Vec3f& point) const; + std::string getCellId (const osg::Vec3f& point) const override; - virtual Cell* getCell(const osg::Vec3d& point) const; + Cell* getCell(const osg::Vec3d& point) const override; - virtual Cell* getCell(const CSMWorld::CellCoordinates& coords) const; + Cell* getCell(const CSMWorld::CellCoordinates& coords) const override; - virtual std::vector > getSelection (unsigned int elementMask) - const; + std::vector > getSelection (unsigned int elementMask) + const override; - virtual std::vector > getEdited (unsigned int elementMask) - const; + std::vector > getEdited (unsigned int elementMask) + const override; - virtual void setSubMode (int subMode, unsigned int elementMask); + void setSubMode (int subMode, unsigned int elementMask) override; /// Erase all overrides and restore the visual representation to its true state. - virtual void reset (unsigned int elementMask); + void reset (unsigned int elementMask) override; private: - virtual void referenceableDataChanged (const QModelIndex& topLeft, - const QModelIndex& bottomRight); + void referenceableDataChanged (const QModelIndex& topLeft, + const QModelIndex& bottomRight) override; - virtual void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end); + void referenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end) override; - virtual void referenceableAdded (const QModelIndex& index, int start, int end); + void referenceableAdded (const QModelIndex& index, int start, int end) override; - virtual void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); + void referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) override; - virtual void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end); + void referenceAboutToBeRemoved (const QModelIndex& parent, int start, int end) override; - virtual void referenceAdded (const QModelIndex& index, int start, int end); + void referenceAdded (const QModelIndex& index, int start, int end) override; - virtual void pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); + void pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) override; - virtual void pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end); + void pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end) override; - virtual void pathgridAdded (const QModelIndex& parent, int start, int end); + void pathgridAdded (const QModelIndex& parent, int start, int end) override; - - virtual std::string getStartupInstruction(); + std::string getStartupInstruction() override; protected: - virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool); + void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool) override; private slots: diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index a80032b82..5ed3d01b3 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -203,12 +203,12 @@ namespace CSVRender virtual void updateOverlay(); - virtual void mouseMoveEvent (QMouseEvent *event); - virtual void wheelEvent (QWheelEvent *event); + void mouseMoveEvent (QMouseEvent *event) override; + void wheelEvent (QWheelEvent *event) override; virtual void handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type); - virtual void settingChanged (const CSMPrefs::Setting *setting); + void settingChanged (const CSMPrefs::Setting *setting) override; EditMode *getEditMode(); @@ -216,11 +216,11 @@ namespace CSVRender private: - void dragEnterEvent(QDragEnterEvent *event); + void dragEnterEvent(QDragEnterEvent *event) override; - void dropEvent(QDropEvent* event); + void dropEvent(QDropEvent* event) override; - void dragMoveEvent(QDragMoveEvent *event); + void dragMoveEvent(QDragMoveEvent *event) override; virtual std::string getStartupInstruction() = 0; diff --git a/apps/opencs/view/tools/merge.hpp b/apps/opencs/view/tools/merge.hpp index e332b799f..c82feba14 100644 --- a/apps/opencs/view/tools/merge.hpp +++ b/apps/opencs/view/tools/merge.hpp @@ -35,7 +35,7 @@ namespace CSVTools CSVDoc::AdjusterWidget *mAdjuster; CSMDoc::DocumentManager& mDocumentManager; - void keyPressEvent (QKeyEvent *event); + void keyPressEvent (QKeyEvent *event) override; public: diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp index 9f43efdac..6d48690b4 100644 --- a/apps/opencs/view/tools/reportsubview.hpp +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -27,7 +27,7 @@ namespace CSVTools ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; private slots: diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index 426c12f68..7b28f2b0f 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -27,8 +27,8 @@ namespace CSVTools RichTextDelegate (QObject *parent = 0); - virtual void paint(QPainter *painter, const QStyleOptionViewItem& option, - const QModelIndex& index) const; + void paint(QPainter *painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const override; }; } diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index 88936d3c3..4c169a986 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -49,11 +49,11 @@ namespace CSVTools private: - void contextMenuEvent (QContextMenuEvent *event); + void contextMenuEvent (QContextMenuEvent *event) override; - void mouseMoveEvent (QMouseEvent *event); + void mouseMoveEvent (QMouseEvent *event) override; - virtual void mouseDoubleClickEvent (QMouseEvent *event); + void mouseDoubleClickEvent (QMouseEvent *event) override; public: @@ -64,7 +64,7 @@ namespace CSVTools ReportTable (CSMDoc::Document& document, const CSMWorld::UniversalId& id, bool richTextDescription, int refreshState = 0, QWidget *parent = 0); - virtual std::vector getDraggedRecords() const; + std::vector getDraggedRecords() const override; void clear(); diff --git a/apps/opencs/view/tools/searchsubview.hpp b/apps/opencs/view/tools/searchsubview.hpp index c0f3eac84..cbcb01577 100644 --- a/apps/opencs/view/tools/searchsubview.hpp +++ b/apps/opencs/view/tools/searchsubview.hpp @@ -41,15 +41,15 @@ namespace CSVTools protected: - void showEvent (QShowEvent *event); + void showEvent (QShowEvent *event) override; public: SearchSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; - virtual void setStatusBar (bool show); + void setStatusBar (bool show) override; private slots: diff --git a/apps/opencs/view/widget/coloreditor.hpp b/apps/opencs/view/widget/coloreditor.hpp index 368896e42..d4a802ca2 100644 --- a/apps/opencs/view/widget/coloreditor.hpp +++ b/apps/opencs/view/widget/coloreditor.hpp @@ -37,8 +37,8 @@ namespace CSVWidget void setColor(const int colorInt); protected: - virtual void paintEvent(QPaintEvent *event); - virtual void showEvent(QShowEvent *event); + void paintEvent(QPaintEvent *event) override; + void showEvent(QShowEvent *event) override; private: ColorEditor(QWidget *parent = 0, const bool popupOnStart = false); diff --git a/apps/opencs/view/widget/colorpickerpopup.hpp b/apps/opencs/view/widget/colorpickerpopup.hpp index eb5653f46..d653d68fb 100644 --- a/apps/opencs/view/widget/colorpickerpopup.hpp +++ b/apps/opencs/view/widget/colorpickerpopup.hpp @@ -19,8 +19,8 @@ namespace CSVWidget void showPicker(const QPoint &position, const QColor &initialColor); protected: - virtual void mousePressEvent(QMouseEvent *event); - virtual bool eventFilter(QObject *object, QEvent *event); + void mousePressEvent(QMouseEvent *event) override; + bool eventFilter(QObject *object, QEvent *event) override; signals: void colorChanged(const QColor &color); diff --git a/apps/opencs/view/widget/completerpopup.hpp b/apps/opencs/view/widget/completerpopup.hpp index 6857064b8..62fdf5388 100644 --- a/apps/opencs/view/widget/completerpopup.hpp +++ b/apps/opencs/view/widget/completerpopup.hpp @@ -10,7 +10,7 @@ namespace CSVWidget public: CompleterPopup(QWidget *parent = 0); - virtual int sizeHintForRow(int row) const; + int sizeHintForRow(int row) const override; }; } diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp index 60832e71b..ed991af0d 100644 --- a/apps/opencs/view/widget/droplineedit.hpp +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -29,9 +29,9 @@ namespace CSVWidget DropLineEdit(CSMWorld::ColumnBase::Display type, QWidget *parent = 0); protected: - void dragEnterEvent(QDragEnterEvent *event); - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void dropEvent(QDropEvent *event) override; signals: void tableMimeDataDropped(const CSMWorld::UniversalId &id, const CSMDoc::Document *document); diff --git a/apps/opencs/view/widget/pushbutton.hpp b/apps/opencs/view/widget/pushbutton.hpp index bdbdc9c4d..5522cd74f 100644 --- a/apps/opencs/view/widget/pushbutton.hpp +++ b/apps/opencs/view/widget/pushbutton.hpp @@ -38,11 +38,11 @@ namespace CSVWidget protected: - virtual void keyPressEvent (QKeyEvent *event); + void keyPressEvent (QKeyEvent *event) override; - virtual void keyReleaseEvent (QKeyEvent *event); + void keyReleaseEvent (QKeyEvent *event) override; - virtual void mouseReleaseEvent (QMouseEvent *event); + void mouseReleaseEvent (QMouseEvent *event) override; public: diff --git a/apps/opencs/view/widget/scenetool.hpp b/apps/opencs/view/widget/scenetool.hpp index cdea88096..295375f26 100644 --- a/apps/opencs/view/widget/scenetool.hpp +++ b/apps/opencs/view/widget/scenetool.hpp @@ -24,7 +24,7 @@ namespace CSVWidget protected: - void mouseReleaseEvent (QMouseEvent *event); + void mouseReleaseEvent (QMouseEvent *event) override; private slots: diff --git a/apps/opencs/view/widget/scenetoolbar.hpp b/apps/opencs/view/widget/scenetoolbar.hpp index 8e2c8ab00..d9998eefc 100644 --- a/apps/opencs/view/widget/scenetoolbar.hpp +++ b/apps/opencs/view/widget/scenetoolbar.hpp @@ -19,7 +19,7 @@ namespace CSVWidget protected: - virtual void focusInEvent (QFocusEvent *event); + void focusInEvent (QFocusEvent *event) override; public: diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 90f1dc419..896a6d9c6 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -31,7 +31,7 @@ namespace CSVWidget void adjustToolTip (const ModeButton *activeMode); - virtual void contextMenuEvent (QContextMenuEvent *event); + void contextMenuEvent (QContextMenuEvent *event) override; /// Add context menu items to \a menu. Default-implementation: Pass on request to /// current mode button or return false, if there is no current mode button. @@ -46,13 +46,13 @@ namespace CSVWidget protected: - bool event(QEvent* event); + bool event(QEvent* event) override; public: SceneToolMode (SceneToolbar *parent, const QString& toolTip); - virtual void showPanel (const QPoint& position); + void showPanel (const QPoint& position) override; void addButton (const std::string& icon, const std::string& id, const QString& tooltip = ""); diff --git a/apps/opencs/view/widget/scenetoolrun.hpp b/apps/opencs/view/widget/scenetoolrun.hpp index dd035462f..4a90aa7c0 100644 --- a/apps/opencs/view/widget/scenetoolrun.hpp +++ b/apps/opencs/view/widget/scenetoolrun.hpp @@ -35,9 +35,9 @@ namespace CSVWidget SceneToolRun (SceneToolbar *parent, const QString& toolTip, const QString& icon, const std::vector& profiles); - virtual void showPanel (const QPoint& position); + void showPanel (const QPoint& position) override; - virtual void activate(); + void activate() override; /// \attention This function does not remove the profile from the profile selection /// panel. diff --git a/apps/opencs/view/widget/scenetoolshapebrush.hpp b/apps/opencs/view/widget/scenetoolshapebrush.hpp index 2c027baf0..76c0dfa04 100644 --- a/apps/opencs/view/widget/scenetoolshapebrush.hpp +++ b/apps/opencs/view/widget/scenetoolshapebrush.hpp @@ -105,18 +105,18 @@ namespace CSVWidget SceneToolShapeBrush (SceneToolbar *parent, const QString& toolTip, CSMDoc::Document& document); - virtual void showPanel (const QPoint& position); + void showPanel (const QPoint& position) override; void updatePanel (); - void dropEvent (QDropEvent *event); - void dragEnterEvent (QDragEnterEvent *event); + void dropEvent (QDropEvent *event) override; + void dragEnterEvent (QDragEnterEvent *event) override; friend class CSVRender::TerrainShapeMode; public slots: void setButtonIcon(CSVWidget::BrushShape brushShape); void clicked (const QModelIndex& index); - virtual void activate(); + void activate() override; signals: void passEvent(QDropEvent *event); diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index 5f5ccc6b1..c6f0b5e52 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -112,11 +112,11 @@ namespace CSVWidget SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip, CSMDoc::Document& document); - virtual void showPanel (const QPoint& position); + void showPanel (const QPoint& position) override; void updatePanel (); - void dropEvent (QDropEvent *event); - void dragEnterEvent (QDragEnterEvent *event); + void dropEvent (QDropEvent *event) override; + void dragEnterEvent (QDragEnterEvent *event) override; friend class CSVRender::TerrainTextureMode; @@ -124,7 +124,7 @@ namespace CSVWidget void setButtonIcon(CSVWidget::BrushShape brushShape); void updateBrushHistory (const std::string& mBrushTexture); void clicked (const QModelIndex& index); - virtual void activate(); + void activate() override; signals: void passEvent(QDropEvent *event); diff --git a/apps/opencs/view/widget/scenetooltoggle.hpp b/apps/opencs/view/widget/scenetooltoggle.hpp index 68cd2362e..f08d117fb 100644 --- a/apps/opencs/view/widget/scenetooltoggle.hpp +++ b/apps/opencs/view/widget/scenetooltoggle.hpp @@ -46,7 +46,7 @@ namespace CSVWidget SceneToolToggle (SceneToolbar *parent, const QString& toolTip, const std::string& emptyIcon); - virtual void showPanel (const QPoint& position); + void showPanel (const QPoint& position) override; /// \attention After the last button has been added, setSelection must be called at /// least once to finalise the layout. diff --git a/apps/opencs/view/widget/scenetooltoggle2.hpp b/apps/opencs/view/widget/scenetooltoggle2.hpp index 50337ac11..e25019298 100644 --- a/apps/opencs/view/widget/scenetooltoggle2.hpp +++ b/apps/opencs/view/widget/scenetooltoggle2.hpp @@ -52,7 +52,7 @@ namespace CSVWidget SceneToolToggle2 (SceneToolbar *parent, const QString& toolTip, const std::string& compositeIcon, const std::string& singleIcon); - virtual void showPanel (const QPoint& position); + void showPanel (const QPoint& position) override; /// \param buttonId used to compose the icon filename /// \param mask used for the reported getSelectionMask() / setSelectionMask() diff --git a/apps/opencs/view/world/bodypartcreator.hpp b/apps/opencs/view/world/bodypartcreator.hpp index 3c27136dd..f526b7fae 100644 --- a/apps/opencs/view/world/bodypartcreator.hpp +++ b/apps/opencs/view/world/bodypartcreator.hpp @@ -23,7 +23,7 @@ namespace CSVWorld private: /// \return ID entered by user. - virtual std::string getId() const; + std::string getId() const override; public: @@ -33,10 +33,10 @@ namespace CSVWorld const CSMWorld::UniversalId& id); /// \return Error description for current user input. - virtual std::string getErrors() const; + std::string getErrors() const override; /// \brief Clear ID and checkbox input widgets. - virtual void reset(); + void reset() override; private slots: diff --git a/apps/opencs/view/world/cellcreator.hpp b/apps/opencs/view/world/cellcreator.hpp index 6c682c6cd..032096aa2 100644 --- a/apps/opencs/view/world/cellcreator.hpp +++ b/apps/opencs/view/world/cellcreator.hpp @@ -21,21 +21,21 @@ namespace CSVWorld protected: - virtual std::string getId() const; + std::string getId() const override; /// Allow subclasses to add additional data to \a command. - virtual void configureCreateCommand(CSMWorld::CreateCommand& command) const; + void configureCreateCommand(CSMWorld::CreateCommand& command) const override; public: CellCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); - virtual void reset(); + void reset() override; - virtual void cloneMode(const std::string& originId, - const CSMWorld::UniversalId::Type type); + void cloneMode(const std::string& originId, + const CSMWorld::UniversalId::Type type) override; - virtual std::string getErrors() const; + std::string getErrors() const override; ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. diff --git a/apps/opencs/view/world/colordelegate.hpp b/apps/opencs/view/world/colordelegate.hpp index 87051e86d..041051d13 100644 --- a/apps/opencs/view/world/colordelegate.hpp +++ b/apps/opencs/view/world/colordelegate.hpp @@ -19,17 +19,17 @@ namespace CSVWorld CSMDoc::Document& document, QObject *parent); - virtual void paint(QPainter *painter, + void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const; + const QModelIndex &index) const override; }; class ColorDelegateFactory : public CommandDelegateFactory { public: - virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher, + CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document &document, - QObject *parent) const; + QObject *parent) const override; ///< The ownership of the returned CommandDelegate is transferred to the caller. }; } diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index f50333e4e..516f71f15 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -74,7 +74,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const override; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function always returns 0. @@ -85,7 +85,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const override; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index f8e775369..df06359a0 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -53,9 +53,9 @@ namespace CSVWorld ~DataDisplayDelegate(); - virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; /// pass a QSize defining height / width of icon. Default is QSize (16,16). void setIconSize (const QSize& icon); @@ -74,7 +74,7 @@ namespace CSVWorld /// rebuild the list of pixmaps from the provided icons (called when icon size is changed) void buildPixmaps(); - virtual void settingChanged (const CSMPrefs::Setting *setting); + void settingChanged (const CSMPrefs::Setting *setting) override; }; class DataDisplayDelegateFactory : public EnumDelegateFactory @@ -85,7 +85,7 @@ namespace CSVWorld public: - virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; + CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const override; ///< The ownership of the returned CommandDelegate is transferred to the caller. protected: diff --git a/apps/opencs/view/world/dialoguecreator.hpp b/apps/opencs/view/world/dialoguecreator.hpp index 20430fdb6..0aef2f84d 100644 --- a/apps/opencs/view/world/dialoguecreator.hpp +++ b/apps/opencs/view/world/dialoguecreator.hpp @@ -11,7 +11,7 @@ namespace CSVWorld protected: - virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + void configureCreateCommand (CSMWorld::CreateCommand& command) const override; public: @@ -23,7 +23,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const override; ///< The ownership of the returned Creator is transferred to the caller. }; @@ -31,7 +31,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const override; ///< The ownership of the returned Creator is transferred to the caller. }; } diff --git a/apps/opencs/view/world/dialoguespinbox.hpp b/apps/opencs/view/world/dialoguespinbox.hpp index a68e0c314..b7c4889a5 100644 --- a/apps/opencs/view/world/dialoguespinbox.hpp +++ b/apps/opencs/view/world/dialoguespinbox.hpp @@ -16,9 +16,9 @@ namespace CSVWorld protected: - virtual void focusInEvent(QFocusEvent *event); - virtual void focusOutEvent(QFocusEvent *event); - virtual void wheelEvent(QWheelEvent *event); + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + void wheelEvent(QWheelEvent *event) override; }; class DialogueDoubleSpinBox : public QDoubleSpinBox @@ -31,9 +31,9 @@ namespace CSVWorld protected: - virtual void focusInEvent(QFocusEvent *event); - virtual void focusOutEvent(QFocusEvent *event); - virtual void wheelEvent(QWheelEvent *event); + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + void wheelEvent(QWheelEvent *event) override; }; } diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 52d3d8da5..eb14efa8e 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -52,22 +52,22 @@ namespace CSVWorld NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent = 0); - virtual void setEditorData (QWidget* editor, const QModelIndex& index) const; + void setEditorData (QWidget* editor, const QModelIndex& index) const override; - virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; - virtual void paint (QPainter* painter, + void paint (QPainter* painter, const QStyleOptionViewItem& option, - const QModelIndex& index) const; + const QModelIndex& index) const override; ///< does nothing - virtual QSize sizeHint (const QStyleOptionViewItem& option, - const QModelIndex& index) const; + QSize sizeHint (const QStyleOptionViewItem& option, + const QModelIndex& index) const override; ///< does nothing - virtual QWidget *createEditor (QWidget *parent, + QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option, - const QModelIndex& index) const; + const QModelIndex& index) const override; }; //this can't be nested into the DialogueDelegateDispatcher, because it needs to emit signals @@ -136,22 +136,22 @@ namespace CSVWorld ///< will return null if delegate is not present, parent of the widget is //same as for dispatcher itself - virtual void setEditorData (QWidget* editor, const QModelIndex& index) const; + void setEditorData (QWidget* editor, const QModelIndex& index) const override; - virtual void setModelData (QWidget* editor, QAbstractItemModel* model, - const QModelIndex& index) const; + void setModelData (QWidget* editor, QAbstractItemModel* model, + const QModelIndex& index) const override; virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const; - virtual void paint (QPainter* painter, + void paint (QPainter* painter, const QStyleOptionViewItem& option, - const QModelIndex& index) const; + const QModelIndex& index) const override; ///< does nothing - virtual QSize sizeHint (const QStyleOptionViewItem& option, - const QModelIndex& index) const; + QSize sizeHint (const QStyleOptionViewItem& option, + const QModelIndex& index) const override; ///< does nothing private slots: @@ -248,7 +248,7 @@ namespace CSVWorld SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; private slots: @@ -276,7 +276,7 @@ namespace CSVWorld DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting = false); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; private slots: diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 9e29b6145..a6b6756aa 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -37,11 +37,11 @@ namespace CSVWorld protected: void startDragFromTable(const DragRecordTable& table); - void dragEnterEvent(QDragEnterEvent *event); + void dragEnterEvent(QDragEnterEvent *event) override; - void dragMoveEvent(QDragMoveEvent *event); + void dragMoveEvent(QDragMoveEvent *event) override; - void dropEvent(QDropEvent *event); + void dropEvent(QDropEvent *event) override; private: CSMWorld::ColumnBase::Display getIndexDisplayType(const QModelIndex &index) const; diff --git a/apps/opencs/view/world/enumdelegate.hpp b/apps/opencs/view/world/enumdelegate.hpp index bd20943d9..91326e2c0 100644 --- a/apps/opencs/view/world/enumdelegate.hpp +++ b/apps/opencs/view/world/enumdelegate.hpp @@ -23,8 +23,8 @@ namespace CSVWorld private: - virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, - const QModelIndex& index) const; + void setModelDataImp (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const override; virtual void addCommands (QAbstractItemModel *model, const QModelIndex& index, int type) const; @@ -34,21 +34,21 @@ namespace CSVWorld EnumDelegate (const std::vector >& values, CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent); - virtual QWidget *createEditor(QWidget *parent, + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option, - const QModelIndex& index) const; + const QModelIndex& index) const override; - virtual QWidget *createEditor(QWidget *parent, + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index, - CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const; + CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const override; - virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const; + void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const override; - virtual void paint (QPainter *painter, const QStyleOptionViewItem& option, - const QModelIndex& index) const; + void paint (QPainter *painter, const QStyleOptionViewItem& option, + const QModelIndex& index) const override; - virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; @@ -68,7 +68,7 @@ namespace CSVWorld EnumDelegateFactory (const std::vector>& names, bool allowNone = false); /// \param allowNone Use value of -1 for "none selected" (empty string) - virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; + CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const override; ///< The ownership of the returned CommandDelegate is transferred to the caller. void add (int value, const QString& name); diff --git a/apps/opencs/view/world/extendedcommandconfigurator.hpp b/apps/opencs/view/world/extendedcommandconfigurator.hpp index 641b4a524..42573924a 100644 --- a/apps/opencs/view/world/extendedcommandconfigurator.hpp +++ b/apps/opencs/view/world/extendedcommandconfigurator.hpp @@ -63,7 +63,7 @@ namespace CSVWorld void setEditLock(bool locked); protected: - virtual void resizeEvent(QResizeEvent *event); + void resizeEvent(QResizeEvent *event) override; private slots: void performExtendedCommand(); diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 3baacfc06..3e2a43c91 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -96,25 +96,25 @@ namespace CSVWorld GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, bool relaxedIdRules = false); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; - virtual void reset(); + void reset() override; - virtual void toggleWidgets (bool active = true); + void toggleWidgets (bool active = true) override; - virtual void cloneMode(const std::string& originId, - const CSMWorld::UniversalId::Type type); + void cloneMode(const std::string& originId, + const CSMWorld::UniversalId::Type type) override; - virtual void touch(const std::vector& ids); + void touch(const std::vector& ids) override; virtual std::string getErrors() const; ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. - virtual void setScope (unsigned int scope); + void setScope (unsigned int scope) override; /// Focus main input widget - virtual void focus(); + void focus() override; private slots: diff --git a/apps/opencs/view/world/globalcreator.hpp b/apps/opencs/view/world/globalcreator.hpp index 8c6cc628c..057798a4c 100644 --- a/apps/opencs/view/world/globalcreator.hpp +++ b/apps/opencs/view/world/globalcreator.hpp @@ -15,7 +15,7 @@ namespace CSVWorld protected: - virtual void configureCreateCommand(CSMWorld::CreateCommand& command) const; + void configureCreateCommand(CSMWorld::CreateCommand& command) const override; }; } diff --git a/apps/opencs/view/world/idcompletiondelegate.hpp b/apps/opencs/view/world/idcompletiondelegate.hpp index d2ac6874f..57c2c11c4 100644 --- a/apps/opencs/view/world/idcompletiondelegate.hpp +++ b/apps/opencs/view/world/idcompletiondelegate.hpp @@ -13,22 +13,22 @@ namespace CSVWorld CSMDoc::Document& document, QObject *parent); - virtual QWidget *createEditor (QWidget *parent, + QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const; + const QModelIndex &index) const override; - virtual QWidget *createEditor (QWidget *parent, + QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index, - CSMWorld::ColumnBase::Display display) const; + CSMWorld::ColumnBase::Display display) const override; }; class IdCompletionDelegateFactory : public CommandDelegateFactory { public: - virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher, + CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, - QObject *parent) const; + QObject *parent) const override; ///< The ownership of the returned CommandDelegate is transferred to the caller. }; } diff --git a/apps/opencs/view/world/idtypedelegate.hpp b/apps/opencs/view/world/idtypedelegate.hpp index d0ed6997b..f1c3b539c 100755 --- a/apps/opencs/view/world/idtypedelegate.hpp +++ b/apps/opencs/view/world/idtypedelegate.hpp @@ -20,7 +20,7 @@ namespace CSVWorld IdTypeDelegateFactory(); - virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; + CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const override; ///< The ownership of the returned CommandDelegate is transferred to the caller. }; } diff --git a/apps/opencs/view/world/idvalidator.hpp b/apps/opencs/view/world/idvalidator.hpp index a9df9580a..17624a243 100644 --- a/apps/opencs/view/world/idvalidator.hpp +++ b/apps/opencs/view/world/idvalidator.hpp @@ -22,7 +22,7 @@ namespace CSVWorld IdValidator (bool relaxed = false, QObject *parent = 0); ///< \param relaxed Relaxed rules for IDs that also functino as user visible text - virtual State validate (QString& input, int& pos) const; + State validate (QString& input, int& pos) const override; void setNamespace (const std::string& namespace_); diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index d131e3fac..404dcf372 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -22,26 +22,26 @@ namespace CSVWorld CSVWidget::DropLineEdit *mTopic; - virtual std::string getId() const; + std::string getId() const override; - virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + void configureCreateCommand (CSMWorld::CreateCommand& command) const override; public: InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager); - virtual void cloneMode (const std::string& originId, - const CSMWorld::UniversalId::Type type); + void cloneMode (const std::string& originId, + const CSMWorld::UniversalId::Type type) override; - virtual void reset(); + void reset() override; - virtual std::string getErrors() const; + std::string getErrors() const override; ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. /// Focus main input widget - virtual void focus(); + void focus() override; private slots: @@ -52,7 +52,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const override; ///< The ownership of the returned Creator is transferred to the caller. }; } diff --git a/apps/opencs/view/world/nestedtable.hpp b/apps/opencs/view/world/nestedtable.hpp index b39c7e560..f864f5d80 100644 --- a/apps/opencs/view/world/nestedtable.hpp +++ b/apps/opencs/view/world/nestedtable.hpp @@ -42,10 +42,10 @@ namespace CSVWorld bool editable = true, bool fixedRows = false); - virtual std::vector getDraggedRecords() const; + std::vector getDraggedRecords() const override; private: - void contextMenuEvent (QContextMenuEvent *event); + void contextMenuEvent (QContextMenuEvent *event) override; private slots: void removeRowActionTriggered(); diff --git a/apps/opencs/view/world/pathgridcreator.hpp b/apps/opencs/view/world/pathgridcreator.hpp index 7e82155f6..773735e25 100644 --- a/apps/opencs/view/world/pathgridcreator.hpp +++ b/apps/opencs/view/world/pathgridcreator.hpp @@ -33,7 +33,7 @@ namespace CSVWorld private: /// \return Cell ID entered by user. - virtual std::string getId() const; + std::string getId() const override; /// \return reference to table containing pathgrids. CSMWorld::IdTable& getPathgridsTable() const; @@ -49,18 +49,18 @@ namespace CSVWorld /// \brief Set cell ID input widget to ID of record to be cloned. /// \param originId Cell ID to be cloned. /// \param type Type of record to be cloned. - virtual void cloneMode( + void cloneMode( const std::string& originId, - const CSMWorld::UniversalId::Type type); + const CSMWorld::UniversalId::Type type) override; /// \return Error description for current user input. - virtual std::string getErrors() const; + std::string getErrors() const override; /// \brief Set focus to cell ID input widget. - virtual void focus(); + void focus() override; /// \brief Clear cell ID input widget. - virtual void reset(); + void reset() override; private slots: @@ -73,9 +73,9 @@ namespace CSVWorld { public: - virtual Creator *makeCreator( + Creator *makeCreator( CSMDoc::Document& document, - const CSMWorld::UniversalId& id) const; + const CSMWorld::UniversalId& id) const override; }; } diff --git a/apps/opencs/view/world/previewsubview.hpp b/apps/opencs/view/world/previewsubview.hpp index a28be5c36..ed88d0488 100644 --- a/apps/opencs/view/world/previewsubview.hpp +++ b/apps/opencs/view/world/previewsubview.hpp @@ -26,9 +26,9 @@ namespace CSVWorld PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; - virtual std::string getTitle() const; + std::string getTitle() const override; private slots: diff --git a/apps/opencs/view/world/recordstatusdelegate.hpp b/apps/opencs/view/world/recordstatusdelegate.hpp index acaf872a6..6ec8c37bd 100644 --- a/apps/opencs/view/world/recordstatusdelegate.hpp +++ b/apps/opencs/view/world/recordstatusdelegate.hpp @@ -28,7 +28,7 @@ namespace CSVWorld RecordStatusDelegateFactory(); - virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; + CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const override; ///< The ownership of the returned CommandDelegate is transferred to the caller. }; diff --git a/apps/opencs/view/world/referenceablecreator.hpp b/apps/opencs/view/world/referenceablecreator.hpp index 14ad24b29..d4657bcf7 100644 --- a/apps/opencs/view/world/referenceablecreator.hpp +++ b/apps/opencs/view/world/referenceablecreator.hpp @@ -15,19 +15,19 @@ namespace CSVWorld private: - virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + void configureCreateCommand (CSMWorld::CreateCommand& command) const override; public: ReferenceableCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); - virtual void reset(); + void reset() override; - virtual void cloneMode (const std::string& originId, - const CSMWorld::UniversalId::Type type); + void cloneMode (const std::string& originId, + const CSMWorld::UniversalId::Type type) override; - virtual void toggleWidgets(bool active = true); + void toggleWidgets(bool active = true) override; }; } diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 31010fa24..3903900ad 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -25,26 +25,26 @@ namespace CSVWorld private: - virtual std::string getId() const; + std::string getId() const override; - virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + void configureCreateCommand (CSMWorld::CreateCommand& command) const override; public: ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager &completionManager); - virtual void cloneMode(const std::string& originId, - const CSMWorld::UniversalId::Type type); + void cloneMode(const std::string& originId, + const CSMWorld::UniversalId::Type type) override; - virtual void reset(); + void reset() override; - virtual std::string getErrors() const; + std::string getErrors() const override; ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. /// Focus main input widget - virtual void focus(); + void focus() override; private slots: @@ -55,7 +55,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const override; ///< The ownership of the returned Creator is transferred to the caller. }; } diff --git a/apps/opencs/view/world/regionmap.hpp b/apps/opencs/view/world/regionmap.hpp index ba773224f..b1f7cdc67 100644 --- a/apps/opencs/view/world/regionmap.hpp +++ b/apps/opencs/view/world/regionmap.hpp @@ -39,7 +39,7 @@ namespace CSVWorld private: - void contextMenuEvent (QContextMenuEvent *event); + void contextMenuEvent (QContextMenuEvent *event) override; QModelIndexList getUnselectedCells() const; ///< \note Non-existent cells are not listed. @@ -54,16 +54,16 @@ namespace CSVWorld void setRegion (const std::string& regionId); ///< Set region Id of selected cells. - void mouseMoveEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event) override; - void dropEvent(QDropEvent* event); + void dropEvent(QDropEvent* event) override; public: RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, QWidget *parent = 0); - virtual std::vector getDraggedRecords() const; + std::vector getDraggedRecords() const override; signals: @@ -71,7 +71,7 @@ namespace CSVWorld private slots: - void selectAll(); + void selectAll() override; void clearSelection(); diff --git a/apps/opencs/view/world/regionmapsubview.hpp b/apps/opencs/view/world/regionmapsubview.hpp index 524727901..232d88fc6 100644 --- a/apps/opencs/view/world/regionmapsubview.hpp +++ b/apps/opencs/view/world/regionmapsubview.hpp @@ -24,7 +24,7 @@ namespace CSVWorld RegionMapSubView (CSMWorld::UniversalId universalId, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; private slots: diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 85f7d0925..aabb7ca2a 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -51,13 +51,13 @@ namespace CSVWorld SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; - virtual void setStatusBar (bool show); + void setStatusBar (bool show) override; - virtual void useHint (const std::string& hint); + void useHint (const std::string& hint) override; - virtual std::string getTitle() const; + std::string getTitle() const override; private: diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index b0a4b0577..21fabee58 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -61,7 +61,7 @@ namespace CSVWorld protected: - bool event (QEvent *event); + bool event (QEvent *event) override; public: @@ -79,9 +79,9 @@ namespace CSVWorld protected: - virtual void resizeEvent(QResizeEvent *e); + void resizeEvent(QResizeEvent *e) override; - virtual void contextMenuEvent(QContextMenuEvent *event); + void contextMenuEvent(QContextMenuEvent *event) override; private: @@ -89,11 +89,11 @@ namespace CSVWorld const CSMDoc::Document& mDocument; const QRegExp mWhiteListQoutes; - void dragEnterEvent (QDragEnterEvent* event); + void dragEnterEvent (QDragEnterEvent* event) override; - void dropEvent (QDropEvent* event); + void dropEvent (QDropEvent* event) override; - void dragMoveEvent (QDragMoveEvent* event); + void dragMoveEvent (QDragMoveEvent* event) override; bool stringNeedsQuote(const std::string& id) const; @@ -133,11 +133,11 @@ namespace CSVWorld public: LineNumberArea(ScriptEdit *editor); - QSize sizeHint() const; + QSize sizeHint() const override; protected: - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; }; } #endif // SCRIPTEDIT_H diff --git a/apps/opencs/view/world/scripterrortable.hpp b/apps/opencs/view/world/scripterrortable.hpp index 4841aac5b..ad287707d 100644 --- a/apps/opencs/view/world/scripterrortable.hpp +++ b/apps/opencs/view/world/scripterrortable.hpp @@ -28,10 +28,10 @@ namespace CSVWorld Compiler::Extensions mExtensions; CSMWorld::ScriptContext mContext; - virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); + void report (const std::string& message, const Compiler::TokenLoc& loc, Type type) override; ///< Report error to the user. - virtual void report (const std::string& message, Type type); + void report (const std::string& message, Type type) override; ///< Report a file related error void addMessage (const std::string& message, CSMDoc::Message::Severity severity, diff --git a/apps/opencs/view/world/scripthighlighter.hpp b/apps/opencs/view/world/scripthighlighter.hpp index a7d0fc2a1..9b4a5b7be 100644 --- a/apps/opencs/view/world/scripthighlighter.hpp +++ b/apps/opencs/view/world/scripthighlighter.hpp @@ -54,37 +54,37 @@ namespace CSVWorld private: - virtual bool parseInt (int value, const Compiler::TokenLoc& loc, - Compiler::Scanner& scanner); + bool parseInt (int value, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) override; ///< Handle an int token. /// \return fetch another token? - virtual bool parseFloat (float value, const Compiler::TokenLoc& loc, - Compiler::Scanner& scanner); + bool parseFloat (float value, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) override; ///< Handle a float token. /// \return fetch another token? - virtual bool parseName (const std::string& name, - const Compiler::TokenLoc& loc, Compiler::Scanner& scanner); + bool parseName (const std::string& name, + const Compiler::TokenLoc& loc, Compiler::Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const Compiler::TokenLoc& loc, - Compiler::Scanner& scanner); + bool parseKeyword (int keyword, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const Compiler::TokenLoc& loc, - Compiler::Scanner& scanner); + bool parseSpecial (int code, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - virtual bool parseComment (const std::string& comment, const Compiler::TokenLoc& loc, - Compiler::Scanner& scanner); + bool parseComment (const std::string& comment, const Compiler::TokenLoc& loc, + Compiler::Scanner& scanner) override; ///< Handle comment token. /// \return fetch another token? - virtual void parseEOF (Compiler::Scanner& scanner); + void parseEOF (Compiler::Scanner& scanner) override; ///< Handle EOF token. void highlight (const Compiler::TokenLoc& loc, Type type); @@ -93,7 +93,7 @@ namespace CSVWorld ScriptHighlighter (const CSMWorld::Data& data, Mode mode, QTextDocument *parent); - virtual void highlightBlock (const QString& text); + void highlightBlock (const QString& text) override; void setMarkOccurrences(bool); diff --git a/apps/opencs/view/world/scriptsubview.hpp b/apps/opencs/view/world/scriptsubview.hpp index c1016babf..dc352cc5b 100644 --- a/apps/opencs/view/world/scriptsubview.hpp +++ b/apps/opencs/view/world/scriptsubview.hpp @@ -70,11 +70,11 @@ namespace CSVWorld ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; - virtual void useHint (const std::string& hint); + void useHint (const std::string& hint) override; - virtual void setStatusBar (bool show); + void setStatusBar (bool show) override; public slots: diff --git a/apps/opencs/view/world/startscriptcreator.hpp b/apps/opencs/view/world/startscriptcreator.hpp index 72eb67bcc..cb7f3f619 100644 --- a/apps/opencs/view/world/startscriptcreator.hpp +++ b/apps/opencs/view/world/startscriptcreator.hpp @@ -26,7 +26,7 @@ namespace CSVWorld private: /// \return script ID entered by user. - virtual std::string getId() const; + std::string getId() const override; /// \return reference to table containing start scripts. CSMWorld::IdTable& getStartScriptsTable() const; @@ -42,18 +42,18 @@ namespace CSVWorld /// \brief Set script ID input widget to ID of record to be cloned. /// \param originId Script ID to be cloned. /// \param type Type of record to be cloned. - virtual void cloneMode( + void cloneMode( const std::string& originId, - const CSMWorld::UniversalId::Type type); + const CSMWorld::UniversalId::Type type) override; /// \return Error description for current user input. - virtual std::string getErrors() const; + std::string getErrors() const override; /// \brief Set focus to script ID input widget. - virtual void focus(); + void focus() override; /// \brief Clear script ID input widget. - virtual void reset(); + void reset() override; private slots: @@ -66,9 +66,9 @@ namespace CSVWorld { public: - virtual Creator *makeCreator( + Creator *makeCreator( CSMDoc::Document& document, - const CSMWorld::UniversalId& id) const; + const CSMWorld::UniversalId& id) const override; }; } diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 36c423b33..61dd57c06 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -77,13 +77,13 @@ namespace CSVWorld private: - void contextMenuEvent (QContextMenuEvent *event); + void contextMenuEvent (QContextMenuEvent *event) override; - void mouseMoveEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event) override; protected: - virtual void mouseDoubleClickEvent (QMouseEvent *event); + void mouseDoubleClickEvent (QMouseEvent *event) override; public: @@ -100,7 +100,7 @@ namespace CSVWorld std::vector getSelectedIds() const; - virtual std::vector getDraggedRecords() const; + std::vector getDraggedRecords() const override; signals: diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index baa68087b..50d61150f 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -63,7 +63,7 @@ namespace CSVWorld virtual ~TableBottomBox(); - virtual bool eventFilter(QObject *object, QEvent *event); + bool eventFilter(QObject *object, QEvent *event) override; void setEditLock (bool locked); diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 1adf862d5..337d2c762 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -41,14 +41,14 @@ namespace CSVWorld TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting); - virtual void setEditLock (bool locked); + void setEditLock (bool locked) override; - virtual void setStatusBar (bool show); + void setStatusBar (bool show) override; - virtual void useHint (const std::string& hint); + void useHint (const std::string& hint) override; protected: - bool eventFilter(QObject* object, QEvent *event); + bool eventFilter(QObject* object, QEvent *event) override; signals: void cloneRequest(const std::string&, diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index ebd5c0ad7..2c4537dac 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -40,13 +40,13 @@ namespace CSVWorld NastyTableModelHack (QAbstractItemModel& model); - int rowCount (const QModelIndex & parent = QModelIndex()) const; + int rowCount (const QModelIndex & parent = QModelIndex()) const override; - int columnCount (const QModelIndex & parent = QModelIndex()) const; + int columnCount (const QModelIndex & parent = QModelIndex()) const override; - QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override; - bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QVariant getData() const; }; @@ -124,12 +124,12 @@ namespace CSVWorld /// cells, a 0-pointer can be passed here. CommandDelegate (CSMWorld::CommandDispatcher *commandDispatcher, CSMDoc::Document& document, QObject *parent); - virtual void setModelData (QWidget *editor, QAbstractItemModel *model, - const QModelIndex& index) const; + void setModelData (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const override; - virtual QWidget *createEditor (QWidget *parent, + QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option, - const QModelIndex& index) const; + const QModelIndex& index) const override; virtual QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option, @@ -142,7 +142,7 @@ namespace CSVWorld ///< \return Does column require update? - virtual void setEditorData (QWidget *editor, const QModelIndex& index) const; + void setEditorData (QWidget *editor, const QModelIndex& index) const override; virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const; diff --git a/apps/opencs/view/world/vartypedelegate.hpp b/apps/opencs/view/world/vartypedelegate.hpp index a8f39c318..44705e80e 100644 --- a/apps/opencs/view/world/vartypedelegate.hpp +++ b/apps/opencs/view/world/vartypedelegate.hpp @@ -11,8 +11,8 @@ namespace CSVWorld { private: - virtual void addCommands (QAbstractItemModel *model, - const QModelIndex& index, int type) const; + void addCommands (QAbstractItemModel *model, + const QModelIndex& index, int type) const override; public: @@ -30,8 +30,8 @@ namespace CSVWorld ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown, ESM::VarType type3 = ESM::VT_Unknown); - virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document& document, QObject *parent) const; + CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, QObject *parent) const override; ///< The ownership of the returned CommandDelegate is transferred to the caller. void add (ESM::VarType type); diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 70fa00a2e..efceb940a 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -73,7 +73,7 @@ add_openmw_dir (mwworld add_openmw_dir (mwphysics physicssystem trace collisiontype actor convert object heightfield closestnotmerayresultcallback contacttestresultcallback deepestnotmecontacttestresultcallback stepper movementsolver - closestnotmeconvexresultcallback + closestnotmeconvexresultcallback raycasting mtphysics ) add_openmw_dir (mwclass @@ -82,7 +82,7 @@ add_openmw_dir (mwclass ) add_openmw_dir (mwmechanics - mechanicsmanagerimp stat creaturestats magiceffects movement actorutil + mechanicsmanagerimp stat creaturestats magiceffects movement actorutil spelllist drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 8c9d7f348..ea29fff53 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -14,6 +14,7 @@ #include #include +#include #include @@ -495,7 +496,7 @@ void OMW::Engine::createWindow(Settings::Manager& settings) bool fullscreen = settings.getBool("fullscreen", "Video"); bool windowBorder = settings.getBool("window border", "Video"); bool vsync = settings.getBool("vsync", "Video"); - int antialiasing = settings.getInt("antialiasing", "Video"); + unsigned int antialiasing = std::max(0, settings.getInt("antialiasing", "Video")); int pos_x = SDL_WINDOWPOS_CENTERED_DISPLAY(screen), pos_y = SDL_WINDOWPOS_CENTERED_DISPLAY(screen); @@ -521,6 +522,8 @@ void OMW::Engine::createWindow(Settings::Manager& settings) checkSDLError(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8)); checkSDLError(SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0)); checkSDLError(SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24)); + if (Debug::shouldDebugOpenGL()) + checkSDLError(SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG)); if (antialiasing > 0) { @@ -528,58 +531,76 @@ void OMW::Engine::createWindow(Settings::Manager& settings) checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); } - while (!mWindow) + osg::ref_ptr graphicsWindow; + while (!graphicsWindow || !graphicsWindow->valid()) { - mWindow = SDL_CreateWindow("OpenMW", pos_x, pos_y, width, height, flags); - if (!mWindow) + while (!mWindow) { - // Try with a lower AA - if (antialiasing > 0) + mWindow = SDL_CreateWindow("OpenMW", pos_x, pos_y, width, height, flags); + if (!mWindow) { - Log(Debug::Warning) << "Warning: " << antialiasing << "x antialiasing not supported, trying " << antialiasing/2; - antialiasing /= 2; - Settings::Manager::setInt("antialiasing", "Video", antialiasing); - checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); - continue; - } - else - { - std::stringstream error; - error << "Failed to create SDL window: " << SDL_GetError(); - throw std::runtime_error(error.str()); + // Try with a lower AA + if (antialiasing > 0) + { + Log(Debug::Warning) << "Warning: " << antialiasing << "x antialiasing not supported, trying " << antialiasing/2; + antialiasing /= 2; + Settings::Manager::setInt("antialiasing", "Video", antialiasing); + checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); + continue; + } + else + { + std::stringstream error; + error << "Failed to create SDL window: " << SDL_GetError(); + throw std::runtime_error(error.str()); + } } } + + setWindowIcon(); + + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + SDL_GetWindowPosition(mWindow, &traits->x, &traits->y); + SDL_GetWindowSize(mWindow, &traits->width, &traits->height); + traits->windowName = SDL_GetWindowTitle(mWindow); + traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS); + traits->screenNum = SDL_GetWindowDisplayIndex(mWindow); + traits->vsync = vsync; + traits->inheritedWindowData = new SDLUtil::GraphicsWindowSDL2::WindowData(mWindow); + + graphicsWindow = new SDLUtil::GraphicsWindowSDL2(traits); + if (!graphicsWindow->valid()) throw std::runtime_error("Failed to create GraphicsContext"); + + if (traits->samples < antialiasing) + { + Log(Debug::Warning) << "Warning: Framebuffer MSAA level is only " << traits->samples << "x instead of " << antialiasing << "x. Trying " << antialiasing / 2 << "x instead."; + graphicsWindow->closeImplementation(); + SDL_DestroyWindow(mWindow); + mWindow = nullptr; + antialiasing /= 2; + Settings::Manager::setInt("antialiasing", "Video", antialiasing); + checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); + continue; + } + + if (traits->red < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has a " << traits->red << " bit red channel."; + if (traits->green < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has a " << traits->green << " bit green channel."; + if (traits->blue < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has a " << traits->blue << " bit blue channel."; + if (traits->depth < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has " << traits->red << " bits of depth precision."; + + traits->alpha = 0; // set to 0 to stop ScreenCaptureHandler reading the alpha channel } - setWindowIcon(); - - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - SDL_GetWindowPosition(mWindow, &traits->x, &traits->y); - SDL_GetWindowSize(mWindow, &traits->width, &traits->height); - traits->windowName = SDL_GetWindowTitle(mWindow); - traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS); - traits->screenNum = SDL_GetWindowDisplayIndex(mWindow); - // We tried to get rid of the hardcoding but failed: https://github.com/OpenMW/openmw/pull/1771 - // Here goes kcat's quote: - // It's ultimately a chicken and egg problem, and the reason why the code is like it was in the first place. - // It needs a context to get the current attributes, but it needs the attributes to set up the context. - // So it just specifies the same values that were given to SDL in the hopes that it's good enough to what the window eventually gets. - traits->red = 8; - traits->green = 8; - traits->blue = 8; - traits->alpha = 0; // set to 0 to stop ScreenCaptureHandler reading the alpha channel - traits->depth = 24; - traits->stencil = 8; - traits->vsync = vsync; - traits->doubleBuffer = true; - traits->inheritedWindowData = new SDLUtil::GraphicsWindowSDL2::WindowData(mWindow); - - osg::ref_ptr graphicsWindow = new SDLUtil::GraphicsWindowSDL2(traits); - if(!graphicsWindow->valid()) throw std::runtime_error("Failed to create GraphicsContext"); - osg::ref_ptr camera = mViewer->getCamera(); camera->setGraphicsContext(graphicsWindow); - camera->setViewport(0, 0, traits->width, traits->height); + camera->setViewport(0, 0, graphicsWindow->getTraits()->width, graphicsWindow->getTraits()->height); + + if (Debug::shouldDebugOpenGL()) + mViewer->setRealizeOperation(new Debug::EnableGLDebugOperation()); #ifdef USE_OPENXR initVr(); @@ -587,7 +608,7 @@ void OMW::Engine::createWindow(Settings::Manager& settings) mViewer->realize(); - mViewer->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, traits->width, traits->height); + mViewer->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, graphicsWindow->getTraits()->width, graphicsWindow->getTraits()->height); } void OMW::Engine::setWindowIcon() @@ -774,7 +795,7 @@ public: { } - virtual void operator()(const osg::Image& image, const unsigned int context_id) + void operator()(const osg::Image& image, const unsigned int context_id) override { // Count screenshots. int shotCount = 0; diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index e25762f32..6103921e0 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -76,10 +76,22 @@ namespace MWBase Exhausted = 2 }; + enum ServiceType + { + Any = -1, + Barter = 1, + Repair = 2, + Spells = 3, + Training = 4, + Travel = 5, + Spellmaking = 6, + Enchanting = 7 + }; + virtual std::list getAvailableTopics() = 0; virtual int getTopicFlag(const std::string&) = 0; - virtual bool checkServiceRefused (ResponseCallback* callback) = 0; + virtual bool checkServiceRefused (ResponseCallback* callback, ServiceType service = ServiceType::Any) = 0; virtual void persuade (int type, ResponseCallback* callback) = 0; virtual int getTemporaryDispositionChange () const = 0; diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index f54149ce5..849403421 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -342,9 +342,9 @@ namespace MWBase virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat) = 0; virtual bool injectKeyRelease(MyGUI::KeyCode key) = 0; - virtual void windowVisibilityChange(bool visible) = 0; - virtual void windowResized(int x, int y) = 0; - virtual void windowClosed() = 0; + void windowVisibilityChange(bool visible) override = 0; + void windowResized(int x, int y) override = 0; + void windowClosed() override = 0; virtual bool isWindowVisible() = 0; virtual void watchActor(const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index fe58fbfb6..778dab85f 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -39,6 +39,7 @@ namespace ESM struct Position; struct Cell; struct Class; + struct Container; struct Creature; struct Potion; struct Spell; @@ -54,6 +55,11 @@ namespace ESM struct TimeStamp; } +namespace MWPhysics +{ + class RayCastingInterface; +} + namespace MWRender { class Animation; @@ -310,6 +316,8 @@ namespace MWBase virtual void updateAnimatedCollisionShape(const MWWorld::Ptr &ptr) = 0; + virtual const MWPhysics::RayCastingInterface* getRayCasting() const = 0; + virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) = 0; ///< cast a Ray and return true if there is an object in the ray path. @@ -385,6 +393,10 @@ namespace MWBase ///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID. /// \return pointer to created record + virtual const ESM::Container *createOverrideRecord (const ESM::Container& record) = 0; + ///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID. + /// \return pointer to created record + virtual void update (float duration, bool paused) = 0; virtual void updatePhysics (float duration, bool paused) = 0; @@ -429,12 +441,12 @@ namespace MWBase virtual void togglePOV(bool force = false) = 0; virtual bool isFirstPerson() const = 0; + virtual bool isPreviewModeEnabled() const = 0; virtual void togglePreviewMode(bool enable) = 0; virtual bool toggleVanityMode(bool enable) = 0; virtual void allowVanityMode(bool allow) = 0; - 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 adjustCameraDistance(float dist) = 0; virtual void applyDeferredPreviewRotationToPlayer(float dt) = 0; virtual void disableDeferredPreviewRotation() = 0; @@ -655,6 +667,8 @@ namespace MWBase virtual bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const = 0; virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0; + + virtual std::vector getAll(const std::string& id) = 0; }; } diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index d5175b739..10ace6f74 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -8,45 +8,45 @@ namespace MWClass class Activator : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; static int getSndGenTypeFromName(const std::string &name); public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + bool hasToolTip (const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) - virtual bool allowTelekinesis(const MWWorld::ConstPtr& ptr) const; + bool allowTelekinesis(const MWWorld::ConstPtr& ptr) const override; ///< Return whether this class of object can be activated with telekinesis - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const override; ///< Generate action for activation static void registerSelf(); - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual bool useAnim() const; + bool useAnim() const override; ///< Whether or not to use animated variant of model (default false) - virtual bool isActivator() const; + bool isActivator() const override; - virtual std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const; + std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const override; }; } diff --git a/apps/openmw/mwclass/actor.cpp b/apps/openmw/mwclass/actor.cpp index 4eb9728a1..33aeb26bb 100644 --- a/apps/openmw/mwclass/actor.cpp +++ b/apps/openmw/mwclass/actor.cpp @@ -6,6 +6,7 @@ #include "../mwbase/world.hpp" #include "../mwbase/soundmanager.hpp" +#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/movement.hpp" #include "../mwmechanics/magiceffects.hpp" @@ -79,7 +80,8 @@ namespace MWClass float weight = getContainerStore(ptr).getWeight(); const MWMechanics::MagicEffects& effects = getCreatureStats(ptr).getMagicEffects(); weight -= effects.get(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).getMagnitude(); - weight += effects.get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).getMagnitude(); + if (ptr != MWMechanics::getPlayer() || !MWBase::Environment::get().getWorld()->getGodModeState()) + weight += effects.get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).getMagnitude(); return (weight < 0) ? 0.0f : weight; } @@ -91,4 +93,13 @@ namespace MWClass { return true; } + + float Actor::getCurrentSpeed(const MWWorld::Ptr& ptr) const + { + const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr); + float moveSpeed = this->getMaxSpeed(ptr) * movementSettings.mSpeedFactor; + if (movementSettings.mIsStrafing) + moveSpeed *= 0.75f; + return moveSpeed; + } } diff --git a/apps/openmw/mwclass/actor.hpp b/apps/openmw/mwclass/actor.hpp index 7cdee8061..3d509b276 100644 --- a/apps/openmw/mwclass/actor.hpp +++ b/apps/openmw/mwclass/actor.hpp @@ -20,28 +20,31 @@ namespace MWClass public: virtual ~Actor(); - virtual void adjustPosition(const MWWorld::Ptr& ptr, bool force) const; + void adjustPosition(const MWWorld::Ptr& ptr, bool force) const override; ///< Adjust position to stand on ground. Must be called post model load /// @param force do this even if the ptr is flying - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual bool useAnim() const; + bool useAnim() const override; - virtual void block(const MWWorld::Ptr &ptr) const; + void block(const MWWorld::Ptr &ptr) const override; - virtual osg::Vec3f getRotationVector(const MWWorld::Ptr& ptr) const; - ///< Return desired rotations, as euler angles. + osg::Vec3f getRotationVector(const MWWorld::Ptr& ptr) const override; + ///< Return desired rotations, as euler angles. Sets getMovementSettings(ptr).mRotation to zero. - virtual float getEncumbrance(const MWWorld::Ptr& ptr) const; + float getEncumbrance(const MWWorld::Ptr& ptr) const override; ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. - virtual bool allowTelekinesis(const MWWorld::ConstPtr& ptr) const; + bool allowTelekinesis(const MWWorld::ConstPtr& ptr) const override; ///< Return whether this class of object can be activated with telekinesis - virtual bool isActor() const; + bool isActor() const override; + /// Return current movement speed. + float getCurrentSpeed(const MWWorld::Ptr& ptr) const override; + // not implemented Actor(const Actor&); Actor& operator= (const Actor&); diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index ea06f74bd..8087c57ba 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -8,50 +8,50 @@ namespace MWClass class Apparatus : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; }; } diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index e25a4ae8a..4f04e0824 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -7,79 +7,79 @@ namespace MWClass { class Armor : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual bool hasItemHealth (const MWWorld::ConstPtr& ptr) const; + bool hasItemHealth (const MWWorld::ConstPtr& ptr) const override; ///< \return Item health data available? - virtual int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const; + int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const override; ///< Return item max health or throw an exception, if class does not have item health - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const; + std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const override; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEquipmentSkill (const MWWorld::ConstPtr& ptr) const; + int getEquipmentSkill (const MWWorld::ConstPtr& ptr) const override; /// Return the index of the skill this item corresponds to when equipped or -1, if there is /// no such skill. - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getEnchantment (const MWWorld::ConstPtr& ptr) const; + std::string getEnchantment (const MWWorld::ConstPtr& ptr) const override; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const override; ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. - virtual std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; + std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const override; ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. \n /// Second item in the pair specifies the error message - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const; + int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; /// Get the effective armor rating, factoring in the actor's skills, for the given armor. - virtual float getEffectiveArmorRating(const MWWorld::ConstPtr& armor, const MWWorld::Ptr& actor) const; + float getEffectiveArmorRating(const MWWorld::ConstPtr& armor, const MWWorld::Ptr& actor) const override; }; } diff --git a/apps/openmw/mwclass/bodypart.hpp b/apps/openmw/mwclass/bodypart.hpp index b75dee754..13d914138 100644 --- a/apps/openmw/mwclass/bodypart.hpp +++ b/apps/openmw/mwclass/bodypart.hpp @@ -8,24 +8,24 @@ namespace MWClass class BodyPart : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + bool hasToolTip (const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) static void registerSelf(); - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; }; } diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 6bdb4e79b..c58e68ad8 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -7,58 +7,58 @@ namespace MWClass { class Book : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getEnchantment (const MWWorld::ConstPtr& ptr) const; + std::string getEnchantment (const MWWorld::ConstPtr& ptr) const override; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const override; ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const; + int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; }; } diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index e71e9b307..a87e0cbe0 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -7,70 +7,70 @@ namespace MWClass { class Clothing : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const; + std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const override; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEquipmentSkill (const MWWorld::ConstPtr& ptr) const; + int getEquipmentSkill (const MWWorld::ConstPtr& ptr) const override; /// Return the index of the skill this item corresponds to when equipped or -1, if there is /// no such skill. - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getEnchantment (const MWWorld::ConstPtr& ptr) const; + std::string getEnchantment (const MWWorld::ConstPtr& ptr) const override; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const override; ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. - virtual std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; + std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const override; ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. /// Second item in the pair specifies the error message - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const; + int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; }; } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index b4b068c91..a27e3debd 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -27,48 +27,46 @@ #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" +#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/npcstats.hpp" namespace MWClass { - class ContainerCustomData : public MWWorld::CustomData + ContainerCustomData::ContainerCustomData(const ESM::Container& container, MWWorld::CellStore* cell) { - public: - MWWorld::ContainerStore mContainerStore; + unsigned int seed = Misc::Rng::rollDice(std::numeric_limits::max()); + // setting ownership not needed, since taking items from a container inherits the + // container's owner automatically + mStore.fillNonRandom(container.mInventory, "", seed); + } - virtual MWWorld::CustomData *clone() const; - - virtual ContainerCustomData& asContainerCustomData() - { - return *this; - } - virtual const ContainerCustomData& asContainerCustomData() const - { - return *this; - } - }; + ContainerCustomData::ContainerCustomData(const ESM::InventoryState& inventory) + { + mStore.readState(inventory); + } MWWorld::CustomData *ContainerCustomData::clone() const { return new ContainerCustomData (*this); } + ContainerCustomData& ContainerCustomData::asContainerCustomData() + { + return *this; + } + const ContainerCustomData& ContainerCustomData::asContainerCustomData() const + { + return *this; + } + void Container::ensureCustomData (const MWWorld::Ptr& ptr) const { if (!ptr.getRefData().getCustomData()) { - std::unique_ptr data (new ContainerCustomData); - - MWWorld::LiveCellRef *ref = - ptr.get(); - - // setting ownership not needed, since taking items from a container inherits the - // container's owner automatically - data->mContainerStore.fill( - ref->mBase->mInventory, ""); + MWWorld::LiveCellRef *ref = ptr.get(); // store - ptr.getRefData().setCustomData (data.release()); + ptr.getRefData().setCustomData (std::make_unique(*ref->mBase, ptr.getCell()).release()); MWBase::Environment::get().getWorld()->addContainerScripts(ptr, ptr.getCell()); } @@ -98,17 +96,6 @@ namespace MWClass } } - void Container::restock(const MWWorld::Ptr& ptr) const - { - MWWorld::LiveCellRef *ref = ptr.get(); - const ESM::InventoryList& list = ref->mBase->mInventory; - MWWorld::ContainerStore& store = getContainerStore(ptr); - - // setting ownership not needed, since taking items from a container inherits the - // container's owner automatically - store.restock(list, ptr, ""); - } - void Container::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const { if (!model.empty()) { @@ -228,12 +215,12 @@ namespace MWClass return !name.empty() ? name : ref->mBase->mId; } - MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr) - const + MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr) const { ensureCustomData (ptr); - - return ptr.getRefData().getCustomData()->asContainerCustomData().mContainerStore; + auto& data = ptr.getRefData().getCustomData()->asContainerCustomData(); + data.mStore.mPtr = ptr; + return data.mStore; } std::string Container::getScript (const MWWorld::ConstPtr& ptr) const @@ -253,8 +240,7 @@ namespace MWClass bool Container::hasToolTip (const MWWorld::ConstPtr& ptr) const { if (const MWWorld::CustomData* data = ptr.getRefData().getCustomData()) - return !canBeHarvested(ptr) || data->asContainerCustomData().mContainerStore.hasVisibleItems(); - + return !canBeHarvested(ptr) || data->asContainerCustomData().mStore.hasVisibleItems(); return true; } @@ -305,6 +291,11 @@ namespace MWClass return !(ref->mBase->mFlags & ESM::Container::Organic); } + void Container::modifyBaseInventory(const std::string& containerId, const std::string& itemId, int amount) const + { + MWMechanics::modifyBaseInventory(containerId, itemId, amount); + } + MWWorld::Ptr Container::copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const { const MWWorld::LiveCellRef *ref = ptr.get(); @@ -317,16 +308,8 @@ namespace MWClass if (!state.mHasCustomState) return; - if (!ptr.getRefData().getCustomData()) - { - // Create a CustomData, but don't fill it from ESM records (not needed) - std::unique_ptr data (new ContainerCustomData); - ptr.getRefData().setCustomData (data.release()); - } - - ContainerCustomData& customData = ptr.getRefData().getCustomData()->asContainerCustomData(); const ESM::ContainerState& containerState = state.asContainerState(); - customData.mContainerStore.readState (containerState.mInventory); + ptr.getRefData().setCustomData(std::make_unique(containerState.mInventory).release()); } void Container::writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const @@ -338,7 +321,13 @@ namespace MWClass } const ContainerCustomData& customData = ptr.getRefData().getCustomData()->asContainerCustomData(); + if (!customData.mStore.isResolved()) + { + state.mHasCustomState = false; + return; + } + ESM::ContainerState& containerState = state.asContainerState(); - customData.mContainerStore.writeState (containerState.mInventory); + customData.mStore.writeState (containerState.mInventory); } } diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index b84c5787b..57dbf0c76 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -2,69 +2,90 @@ #define GAME_MWCLASS_CONTAINER_H #include "../mwworld/class.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/customdata.hpp" + +namespace ESM +{ + struct Container; + struct InventoryState; +} namespace MWClass { + class ContainerCustomData : public MWWorld::CustomData + { + MWWorld::ContainerStore mStore; + public: + ContainerCustomData(const ESM::Container& container, MWWorld::CellStore* cell); + ContainerCustomData(const ESM::InventoryState& inventory); + + MWWorld::CustomData *clone() const override; + + ContainerCustomData& asContainerCustomData() override; + const ContainerCustomData& asContainerCustomData() const override; + + friend class Container; + }; + class Container : public MWWorld::Class { void ensureCustomData (const MWWorld::Ptr& ptr) const; - - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + bool hasToolTip (const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const; + MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const override; ///< Return container store - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual float getCapacity (const MWWorld::Ptr& ptr) const; + float getCapacity (const MWWorld::Ptr& ptr) const override; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. - virtual float getEncumbrance (const MWWorld::Ptr& ptr) const; + float getEncumbrance (const MWWorld::Ptr& ptr) const override; ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. - virtual bool canLock(const MWWorld::ConstPtr &ptr) const; + bool canLock(const MWWorld::ConstPtr &ptr) const override; - virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) - const; + void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) + const override; ///< Read additional state from \a state into \a ptr. - virtual void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) - const; + void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const override; ///< Write additional state from \a ptr into \a state. static void registerSelf(); - virtual void respawn (const MWWorld::Ptr& ptr) const; + void respawn (const MWWorld::Ptr& ptr) const override; - virtual void restock (const MWWorld::Ptr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + bool useAnim() const override; - virtual bool useAnim() const; + void modifyBaseInventory(const std::string& containerId, const std::string& itemId, int amount) const override; }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 5d39c4747..c4edf66e7 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -59,13 +59,13 @@ namespace MWClass MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures MWMechanics::Movement mMovement; - virtual MWWorld::CustomData *clone() const; + MWWorld::CustomData *clone() const override; - virtual CreatureCustomData& asCreatureCustomData() + CreatureCustomData& asCreatureCustomData() override { return *this; } - virtual const CreatureCustomData& asCreatureCustomData() const + const CreatureCustomData& asCreatureCustomData() const override { return *this; } @@ -142,14 +142,9 @@ namespace MWClass data->mCreatureStats.setDeathAnimationFinished(isPersistent(ptr)); // spells - for (std::vector::const_iterator iter (ref->mBase->mSpells.mList.begin()); - iter!=ref->mBase->mSpells.mList.end(); ++iter) - { - if (const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(*iter)) - data->mCreatureStats.getSpells().add (spell); - else /// \todo add option to make this a fatal error message pop-up, but default to warning for vanilla compatibility - Log(Debug::Warning) << "Warning: ignoring nonexistent spell '" << *iter << "' on creature '" << ref->mBase->mId << "'"; - } + bool spellsInitialised = data->mCreatureStats.getSpells().setSpells(ref->mBase->mId); + if (!spellsInitialised) + data->mCreatureStats.getSpells().addAllToInstance(ref->mBase->mSpells.mList); // inventory bool hasInventory = hasInventoryStore(ptr); @@ -519,7 +514,7 @@ namespace MWClass registerClass (typeid (ESM::Creature).name(), instance); } - float Creature::getSpeed(const MWWorld::Ptr &ptr) const + float Creature::getMaxSpeed(const MWWorld::Ptr &ptr) const { const MWMechanics::CreatureStats& stats = getCreatureStats(ptr); @@ -551,11 +546,6 @@ namespace MWClass else moveSpeed = getWalkSpeed(ptr); - const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr); - if (movementSettings.mIsStrafing) - moveSpeed *= 0.75f; - moveSpeed *= movementSettings.mSpeedFactor; - return moveSpeed; } @@ -795,6 +785,9 @@ namespace MWClass CreatureCustomData& customData = ptr.getRefData().getCustomData()->asCreatureCustomData(); const ESM::CreatureState& creatureState = state.asCreatureState(); customData.mContainerStore->readState (creatureState.mInventory); + bool spellsInitialised = customData.mCreatureStats.getSpells().setSpells(ptr.get()->mBase->mId); + if(spellsInitialised) + customData.mCreatureStats.getSpells().clear(); customData.mCreatureStats.readState (creatureState.mCreatureStats); } @@ -863,14 +856,6 @@ namespace MWClass } } - void Creature::restock(const MWWorld::Ptr& ptr) const - { - MWWorld::LiveCellRef *ref = ptr.get(); - const ESM::InventoryList& list = ref->mBase->mInventory; - MWWorld::ContainerStore& store = getContainerStore(ptr); - store.restock(list, ptr, ptr.getCellRef().getRefId()); - } - int Creature::getBaseFightRating(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); @@ -888,6 +873,11 @@ namespace MWClass MWMechanics::setBaseAISetting(id, setting, value); } + void Creature::modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const + { + MWMechanics::modifyBaseInventory(actorId, itemId, amount); + } + float Creature::getWalkSpeed(const MWWorld::Ptr& ptr) const { const MWMechanics::CreatureStats& stats = getCreatureStats(ptr); diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 7c5e5fc9b..5ebb2e81e 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -14,7 +14,7 @@ namespace MWClass { void ensureCustomData (const MWWorld::Ptr& ptr) const; - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; static int getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name); @@ -40,97 +40,97 @@ namespace MWClass public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual bool hasToolTip(const MWWorld::ConstPtr& ptr) const; + bool hasToolTip(const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; + MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const override; ///< Return creature stats - virtual bool hit(const MWWorld::Ptr& ptr, float attackStrength, int type, bool simulated) const; + bool hit(const MWWorld::Ptr& ptr, float attackStrength, int type, bool simulated) const override; - virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful, float hitStrength) const; + void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful, float hitStrength) const override; - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWWorld::ContainerStore& getContainerStore ( - const MWWorld::Ptr& ptr) const; + MWWorld::ContainerStore& getContainerStore ( + const MWWorld::Ptr& ptr) const override; ///< Return container store - virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const; + MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const override; ///< Return inventory store - virtual bool hasInventoryStore (const MWWorld::Ptr &ptr) const; + bool hasInventoryStore (const MWWorld::Ptr &ptr) const override; - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual float getCapacity (const MWWorld::Ptr& ptr) const; + float getCapacity (const MWWorld::Ptr& ptr) const override; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. - virtual float getArmorRating (const MWWorld::Ptr& ptr) const; + float getArmorRating (const MWWorld::Ptr& ptr) const override; ///< @return combined armor rating of this actor - virtual bool isEssential (const MWWorld::ConstPtr& ptr) const; + bool isEssential (const MWWorld::ConstPtr& ptr) const override; ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable) - virtual int getServices (const MWWorld::ConstPtr& actor) const; + int getServices (const MWWorld::ConstPtr& actor) const override; - virtual bool isPersistent (const MWWorld::ConstPtr& ptr) const; + bool isPersistent (const MWWorld::ConstPtr& ptr) const override; - virtual std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const; + std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const override; - virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const; + MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const override; ///< Return desired movement. - float getSpeed (const MWWorld::Ptr& ptr) const; + float getMaxSpeed (const MWWorld::Ptr& ptr) const override; static void registerSelf(); - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const; + void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const override; ///< Get a list of models to preload that this object may use (directly or indirectly). default implementation: list getModel(). - virtual bool isBipedal (const MWWorld::ConstPtr &ptr) const; - virtual bool canFly (const MWWorld::ConstPtr &ptr) const; - virtual bool canSwim (const MWWorld::ConstPtr &ptr) const; - virtual bool canWalk (const MWWorld::ConstPtr &ptr) const; + bool isBipedal (const MWWorld::ConstPtr &ptr) const override; + bool canFly (const MWWorld::ConstPtr &ptr) const override; + bool canSwim (const MWWorld::ConstPtr &ptr) const override; + bool canWalk (const MWWorld::ConstPtr &ptr) const override; - virtual float getSkill(const MWWorld::Ptr &ptr, int skill) const; + float getSkill(const MWWorld::Ptr &ptr, int skill) const override; /// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini) - virtual int getBloodTexture (const MWWorld::ConstPtr& ptr) const; + int getBloodTexture (const MWWorld::ConstPtr& ptr) const override; - virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const; + void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const override; ///< Read additional state from \a state into \a ptr. - virtual void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const; + void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const override; ///< Write additional state from \a ptr into \a state. - virtual int getBaseGold(const MWWorld::ConstPtr& ptr) const; + int getBaseGold(const MWWorld::ConstPtr& ptr) const override; - virtual void respawn (const MWWorld::Ptr& ptr) const; + void respawn (const MWWorld::Ptr& ptr) const override; - virtual void restock (const MWWorld::Ptr &ptr) const; + int getBaseFightRating(const MWWorld::ConstPtr &ptr) const override; - virtual int getBaseFightRating(const MWWorld::ConstPtr &ptr) const; - - virtual void adjustScale(const MWWorld::ConstPtr& ptr, osg::Vec3f& scale, bool rendering) const; + void adjustScale(const MWWorld::ConstPtr& ptr, osg::Vec3f& scale, bool rendering) const override; /// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh - virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const; + void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const override; + + void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const override; float getWalkSpeed(const MWWorld::Ptr& ptr) const final; diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index 2f3ac0d1e..e3e52901e 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -17,13 +17,13 @@ namespace MWClass int mSpawnActorId; bool mSpawn; // Should a new creature be spawned? - virtual MWWorld::CustomData *clone() const; + MWWorld::CustomData *clone() const override; - virtual CreatureLevListCustomData& asCreatureLevListCustomData() + CreatureLevListCustomData& asCreatureLevListCustomData() override { return *this; } - virtual const CreatureLevListCustomData& asCreatureLevListCustomData() const + const CreatureLevListCustomData& asCreatureLevListCustomData() const override { return *this; } diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index 3a05f5272..35152a942 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -11,27 +11,27 @@ namespace MWClass public: - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + bool hasToolTip (const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) static void registerSelf(); - virtual void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const; + void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const override; ///< Get a list of models to preload that this object may use (directly or indirectly). default implementation: list getModel(). - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const; + void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const override; ///< Read additional state from \a state into \a ptr. - virtual void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const; + void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const override; ///< Write additional state from \a ptr into \a state. - virtual void respawn (const MWWorld::Ptr& ptr) const; + void respawn (const MWWorld::Ptr& ptr) const override; }; } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 4f82aa977..ba51d9c2b 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -36,13 +36,13 @@ namespace MWClass public: MWWorld::DoorState mDoorState = MWWorld::DoorState::Idle; - virtual MWWorld::CustomData *clone() const; + MWWorld::CustomData *clone() const override; - virtual DoorCustomData& asDoorCustomData() + DoorCustomData& asDoorCustomData() override { return *this; } - virtual const DoorCustomData& asDoorCustomData() const + const DoorCustomData& asDoorCustomData() const override { return *this; } diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index 84761900c..6c2fa26b8 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -11,55 +11,53 @@ namespace MWClass { void ensureCustomData (const MWWorld::Ptr& ptr) const; - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual bool isDoor() const; + bool isDoor() const override; - virtual bool useAnim() const; + bool useAnim() const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. static std::string getDestination (const MWWorld::LiveCellRef& door); ///< @return destination cell name or token - virtual bool canLock(const MWWorld::ConstPtr &ptr) const; + bool canLock(const MWWorld::ConstPtr &ptr) const override; - virtual bool allowTelekinesis(const MWWorld::ConstPtr &ptr) const; + bool allowTelekinesis(const MWWorld::ConstPtr &ptr) const override; ///< Return whether this class of object can be activated with telekinesis - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr static void registerSelf(); - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual MWWorld::DoorState getDoorState (const MWWorld::ConstPtr &ptr) const; + MWWorld::DoorState getDoorState (const MWWorld::ConstPtr &ptr) const override; /// This does not actually cause the door to move. Use World::activateDoor instead. - virtual void setDoorState (const MWWorld::Ptr &ptr, MWWorld::DoorState state) const; + void setDoorState (const MWWorld::Ptr &ptr, MWWorld::DoorState state) const override; - virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) - const; + void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const override; ///< Read additional state from \a state into \a ptr. - virtual void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) - const; + void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const override; ///< Write additional state from \a ptr into \a state. }; } diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 8b2ea4f86..5219cf39c 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -7,50 +7,50 @@ namespace MWClass { class Ingredient : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; }; } diff --git a/apps/openmw/mwclass/itemlevlist.hpp b/apps/openmw/mwclass/itemlevlist.hpp index 36019f491..771f8b7a7 100644 --- a/apps/openmw/mwclass/itemlevlist.hpp +++ b/apps/openmw/mwclass/itemlevlist.hpp @@ -9,10 +9,10 @@ namespace MWClass { public: - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + bool hasToolTip (const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) static void registerSelf(); diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index ba3179971..e37dddc25 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -7,71 +7,71 @@ namespace MWClass { class Light : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual bool useAnim() const; + bool useAnim() const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + bool hasToolTip (const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual bool showsInInventory (const MWWorld::ConstPtr& ptr) const; + bool showsInInventory (const MWWorld::ConstPtr& ptr) const override; - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const; + std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const override; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual void setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const; + void setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const override; ///< Sets the remaining duration of the object. - virtual float getRemainingUsageTime (const MWWorld::ConstPtr& ptr) const; + float getRemainingUsageTime (const MWWorld::ConstPtr& ptr) const override; ///< Returns the remaining duration of the object. - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; - std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; + std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const override; - virtual std::string getSound(const MWWorld::ConstPtr& ptr) const; + std::string getSound(const MWWorld::ConstPtr& ptr) const override; }; } diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 20ca2d166..fabae3343 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -7,61 +7,61 @@ namespace MWClass { class Lockpick : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const; + std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const override; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; + std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const override; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const; + int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const override; ///< Return item max health or throw an exception, if class does not have item health - virtual bool hasItemHealth (const MWWorld::ConstPtr& ptr) const { return true; } + bool hasItemHealth (const MWWorld::ConstPtr& ptr) const override { return true; } ///< \return Item health data available? (default implementation: false) }; } diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 4812deb5f..9bff85ca5 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -9,52 +9,52 @@ namespace MWClass { public: - virtual MWWorld::Ptr copyToCell(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell, int count) const; + MWWorld::Ptr copyToCell(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell, int count) const override; - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; - virtual bool isKey (const MWWorld::ConstPtr &ptr) const; + bool isKey (const MWWorld::ConstPtr &ptr) const override; - virtual bool isGold (const MWWorld::ConstPtr& ptr) const; + bool isGold (const MWWorld::ConstPtr& ptr) const override; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index f442f2138..1368570b7 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -159,7 +159,7 @@ namespace * * and by adding class, race, specialization bonus. */ - void autoCalculateSkills(const ESM::NPC* npc, MWMechanics::NpcStats& npcStats, const MWWorld::Ptr& ptr) + void autoCalculateSkills(const ESM::NPC* npc, MWMechanics::NpcStats& npcStats, const MWWorld::Ptr& ptr, bool spellsInitialised) { const ESM::Class *class_ = MWBase::Environment::get().getWorld()->getStore().get().find(npc->mClass); @@ -236,9 +236,11 @@ namespace for (int i=0; i spells = MWMechanics::autoCalcNpcSpells(skills, attributes, race); - for (std::vector::iterator it = spells.begin(); it != spells.end(); ++it) - npcStats.getSpells().add(*it); + if (!spellsInitialised) + { + std::vector spells = MWMechanics::autoCalcNpcSpells(skills, attributes, race); + npcStats.getSpells().addAllToInstance(spells); + } } } @@ -252,13 +254,13 @@ namespace MWClass MWMechanics::Movement mMovement; MWWorld::InventoryStore mInventoryStore; - virtual MWWorld::CustomData *clone() const; + MWWorld::CustomData *clone() const override; - virtual NpcCustomData& asNpcCustomData() + NpcCustomData& asNpcCustomData() override { return *this; } - virtual const NpcCustomData& asNpcCustomData() const + const NpcCustomData& asNpcCustomData() const override { return *this; } @@ -312,6 +314,8 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); + bool spellsInitialised = data->mNpcStats.getSpells().setSpells(ref->mBase->mId); + // creature stats int gold=0; if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) @@ -352,7 +356,7 @@ namespace MWClass data->mNpcStats.setReputation(ref->mBase->mNpdt.mReputation); autoCalculateAttributes(ref->mBase, data->mNpcStats); - autoCalculateSkills(ref->mBase, data->mNpcStats, ptr); + autoCalculateSkills(ref->mBase, data->mNpcStats, ptr, spellsInitialised); data->mNpcStats.setNeedRecalcDynamicStats(true); } @@ -363,14 +367,7 @@ namespace MWClass // race powers const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().get().find(ref->mBase->mRace); - for (std::vector::const_iterator iter (race->mPowers.mList.begin()); - iter!=race->mPowers.mList.end(); ++iter) - { - if (const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(*iter)) - data->mNpcStats.getSpells().add (spell); - else - Log(Debug::Warning) << "Warning: ignoring nonexistent race power '" << *iter << "' on NPC '" << ref->mBase->mId << "'"; - } + data->mNpcStats.getSpells().addAllToInstance(race->mPowers.mList); if (!ref->mBase->mFaction.empty()) { @@ -391,17 +388,8 @@ namespace MWClass data->mNpcStats.setAiSetting (MWMechanics::CreatureStats::AI_Alarm, ref->mBase->mAiData.mAlarm); // spells - for (std::vector::const_iterator iter (ref->mBase->mSpells.mList.begin()); - iter!=ref->mBase->mSpells.mList.end(); ++iter) - { - if (const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(*iter)) - data->mNpcStats.getSpells().add (spell); - else - { - /// \todo add option to make this a fatal error message pop-up, but default to warning for vanilla compatibility - Log(Debug::Warning) << "Warning: ignoring nonexistent spell '" << *iter << "' on NPC '" << ref->mBase->mId << "'"; - } - } + if (!spellsInitialised) + data->mNpcStats.getSpells().addAllToInstance(ref->mBase->mSpells.mList); // inventory // setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items @@ -933,13 +921,19 @@ namespace MWClass } else if (!stats.getAiSequence().isInCombat()) { - if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak) || stats.getKnockedDown()) + if (stats.getKnockedDown() || MWBase::Environment::get().getMechanicsManager()->isSneaking(actor)) return std::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing // Can't talk to werewolves if (!getNpcStats(ptr).isWerewolf()) return std::shared_ptr(new MWWorld::ActionTalk(ptr)); } + else // In combat + { + const bool stealingInCombat = Settings::Manager::getBool ("always allow stealing from knocked out actors", "Game"); + if (stealingInCombat && stats.getKnockedDown()) + return std::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing + } // Tribunal and some mod companions oddly enough must use open action as fallback if (!getScript(ptr).empty() && ptr.getRefData().getLocals().getIntVar(getScript(ptr), "companion")) @@ -971,10 +965,13 @@ namespace MWClass return ref->mBase->mScript; } - float Npc::getSpeed(const MWWorld::Ptr& ptr) const + float Npc::getMaxSpeed(const MWWorld::Ptr& ptr) const { + // TODO: This function is called several times per frame for each NPC. + // It would be better to calculate it only once per frame for each NPC and save the result in CreatureStats. const MWMechanics::CreatureStats& stats = getCreatureStats(ptr); - if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead()) + bool godmode = ptr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); + if ((!godmode && stats.isParalyzed()) || stats.getKnockedDown() || stats.isDead()) return 0.f; const MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1014,11 +1011,6 @@ namespace MWClass if(npcdata->mNpcStats.isWerewolf() && running && npcdata->mNpcStats.getDrawState() == MWMechanics::DrawState_Nothing) moveSpeed *= gmst.fWereWolfRunMult->mValue.getFloat(); - const MWMechanics::Movement& movementSettings = ptr.getClass().getMovementSettings(ptr); - if (movementSettings.mIsStrafing) - moveSpeed *= 0.75f; - moveSpeed *= movementSettings.mSpeedFactor; - return moveSpeed; } @@ -1028,7 +1020,8 @@ namespace MWClass return 0.f; const MWMechanics::CreatureStats& stats = getCreatureStats(ptr); - if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead()) + bool godmode = ptr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); + if ((!godmode && stats.isParalyzed()) || stats.getKnockedDown() || stats.isDead()) return 0.f; const NpcCustomData *npcdata = static_cast(ptr.getRefData().getCustomData()); @@ -1091,7 +1084,14 @@ namespace MWClass if (customData.mNpcStats.isDead() && customData.mNpcStats.isDeathAnimationFinished()) return true; - return !customData.mNpcStats.getAiSequence().isInCombat(); + if (!customData.mNpcStats.getAiSequence().isInCombat()) + return true; + + const bool stealingInCombat = Settings::Manager::getBool ("always allow stealing from knocked out actors", "Game"); + if (stealingInCombat && customData.mNpcStats.getKnockedDown()) + return true; + + return false; } MWGui::ToolTipInfo Npc::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const @@ -1342,6 +1342,9 @@ namespace MWClass const ESM::NpcState& npcState = state.asNpcState(); customData.mInventoryStore.readState (npcState.mInventory); customData.mNpcStats.readState (npcState.mNpcStats); + bool spellsInitialised = customData.mNpcStats.getSpells().setSpells(ptr.get()->mBase->mId); + if(spellsInitialised) + customData.mNpcStats.getSpells().clear(); customData.mNpcStats.readState (npcState.mCreatureStats); } @@ -1427,14 +1430,6 @@ namespace MWClass } } - void Npc::restock(const MWWorld::Ptr& ptr) const - { - MWWorld::LiveCellRef *ref = ptr.get(); - const ESM::InventoryList& list = ref->mBase->mInventory; - MWWorld::ContainerStore& store = getContainerStore(ptr); - store.restock(list, ptr, ptr.getCellRef().getRefId()); - } - int Npc::getBaseFightRating (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); @@ -1476,6 +1471,11 @@ namespace MWClass MWMechanics::setBaseAISetting(id, setting, value); } + void Npc::modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const + { + MWMechanics::modifyBaseInventory(actorId, itemId, amount); + } + float Npc::getWalkSpeed(const MWWorld::Ptr& ptr) const { const GMST& gmst = getGmst(); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index b1c91420d..4ee1b1ebb 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -14,7 +14,7 @@ namespace MWClass { void ensureCustomData (const MWWorld::Ptr& ptr) const; - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; struct GMST { @@ -44,128 +44,127 @@ namespace MWClass public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; + MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const override; ///< Return creature stats - virtual MWMechanics::NpcStats& getNpcStats (const MWWorld::Ptr& ptr) const; + MWMechanics::NpcStats& getNpcStats (const MWWorld::Ptr& ptr) const override; ///< Return NPC stats - virtual MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const; + MWWorld::ContainerStore& getContainerStore (const MWWorld::Ptr& ptr) const override; ///< Return container store - virtual bool hasToolTip(const MWWorld::ConstPtr& ptr) const; + bool hasToolTip(const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const; + MWWorld::InventoryStore& getInventoryStore (const MWWorld::Ptr& ptr) const override; ///< Return inventory store - virtual bool hasInventoryStore(const MWWorld::Ptr &ptr) const { return true; } + bool hasInventoryStore(const MWWorld::Ptr &ptr) const override { return true; } - virtual bool hit(const MWWorld::Ptr& ptr, float attackStrength, int type, bool simulated) const; + bool hit(const MWWorld::Ptr& ptr, float attackStrength, int type, bool simulated) const override; - virtual void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful, float hitStrength) const; + void onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful, float hitStrength) const override; - virtual void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const; + void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const override; ///< Get a list of models to preload that this object may use (directly or indirectly). default implementation: list getModel(). - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual float getSpeed (const MWWorld::Ptr& ptr) const; - ///< Return movement speed. + float getMaxSpeed (const MWWorld::Ptr& ptr) const override; + ///< Return maximal movement speed. - virtual float getJump(const MWWorld::Ptr &ptr) const; + float getJump(const MWWorld::Ptr &ptr) const override; ///< Return jump velocity (not accounting for movement) - virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const; + MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const override; ///< Return desired movement. - virtual float getCapacity (const MWWorld::Ptr& ptr) const; + float getCapacity (const MWWorld::Ptr& ptr) const override; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. - virtual float getEncumbrance (const MWWorld::Ptr& ptr) const; + float getEncumbrance (const MWWorld::Ptr& ptr) const override; ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. - virtual float getArmorRating (const MWWorld::Ptr& ptr) const; + float getArmorRating (const MWWorld::Ptr& ptr) const override; ///< @return combined armor rating of this actor - virtual bool apply (const MWWorld::Ptr& ptr, const std::string& id, - const MWWorld::Ptr& actor) const; + bool apply (const MWWorld::Ptr& ptr, const std::string& id, + const MWWorld::Ptr& actor) const override; ///< Apply \a id on \a ptr. /// \param actor Actor that is resposible for the ID being applied to \a ptr. /// \return Any effect? - virtual void adjustScale (const MWWorld::ConstPtr &ptr, osg::Vec3f &scale, bool rendering) const; + void adjustScale (const MWWorld::ConstPtr &ptr, osg::Vec3f &scale, bool rendering) const override; /// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh - virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor=1.f) const; + void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor=1.f) const override; ///< Inform actor \a ptr that a skill use has succeeded. - virtual bool isEssential (const MWWorld::ConstPtr& ptr) const; + bool isEssential (const MWWorld::ConstPtr& ptr) const override; ///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable) - virtual int getServices (const MWWorld::ConstPtr& actor) const; + int getServices (const MWWorld::ConstPtr& actor) const override; - virtual bool isPersistent (const MWWorld::ConstPtr& ptr) const; + bool isPersistent (const MWWorld::ConstPtr& ptr) const override; - virtual std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const; + std::string getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const override; static void registerSelf(); - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual float getSkill(const MWWorld::Ptr& ptr, int skill) const; + float getSkill(const MWWorld::Ptr& ptr, int skill) const override; /// Get a blood texture suitable for \a ptr (see Blood Texture 0-2 in Morrowind.ini) - virtual int getBloodTexture (const MWWorld::ConstPtr& ptr) const; + int getBloodTexture (const MWWorld::ConstPtr& ptr) const override; - virtual bool isNpc() const { + bool isNpc() const override + { return true; } - virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) - const; + void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const override; ///< Read additional state from \a state into \a ptr. - virtual void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) - const; + void writeAdditionalState (const MWWorld::ConstPtr& ptr, ESM::ObjectState& state) const override; ///< Write additional state from \a ptr into \a state. - virtual int getBaseGold(const MWWorld::ConstPtr& ptr) const; + int getBaseGold(const MWWorld::ConstPtr& ptr) const override; - virtual bool isClass(const MWWorld::ConstPtr& ptr, const std::string &className) const; + bool isClass(const MWWorld::ConstPtr& ptr, const std::string &className) const override; - virtual bool canSwim (const MWWorld::ConstPtr &ptr) const; + bool canSwim (const MWWorld::ConstPtr &ptr) const override; - virtual bool canWalk (const MWWorld::ConstPtr &ptr) const; + bool canWalk (const MWWorld::ConstPtr &ptr) const override; - virtual bool isBipedal (const MWWorld::ConstPtr &ptr) const; + bool isBipedal (const MWWorld::ConstPtr &ptr) const override; - virtual void respawn (const MWWorld::Ptr& ptr) const; + void respawn (const MWWorld::Ptr& ptr) const override; - virtual void restock (const MWWorld::Ptr& ptr) const; + int getBaseFightRating (const MWWorld::ConstPtr& ptr) const override; - virtual int getBaseFightRating (const MWWorld::ConstPtr& ptr) const; + std::string getPrimaryFaction(const MWWorld::ConstPtr &ptr) const override; + int getPrimaryFactionRank(const MWWorld::ConstPtr &ptr) const override; - virtual std::string getPrimaryFaction(const MWWorld::ConstPtr &ptr) const; - virtual int getPrimaryFactionRank(const MWWorld::ConstPtr &ptr) const; + void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const override; - virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const; + void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const override; float getWalkSpeed(const MWWorld::Ptr& ptr) const final; diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 8ec4aef44..75d923f0b 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -7,50 +7,50 @@ namespace MWClass { class Potion : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; }; } diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 51a5f8231..a0a41dcfb 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -7,61 +7,61 @@ namespace MWClass { class Probe : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const; + std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const override; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; + std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const override; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const; + int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const override; ///< Return item max health or throw an exception, if class does not have item health - virtual bool hasItemHealth (const MWWorld::ConstPtr& ptr) const { return true; } + bool hasItemHealth (const MWWorld::ConstPtr& ptr) const override { return true; } ///< \return Item health data available? (default implementation: false) }; } diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 5d2cfb682..b9791e9cf 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -7,59 +7,58 @@ namespace MWClass { class Repair : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) - const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu (default implementation: return a /// null action). - virtual bool hasItemHealth (const MWWorld::ConstPtr& ptr) const; + bool hasItemHealth (const MWWorld::ConstPtr& ptr) const override; ///< \return Item health data available? (default implementation: false) - virtual int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const; + int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const override; ///< Return item max health or throw an exception, if class does not have item health /// (default implementation: throw an exception) - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; }; } diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index 6b3b8088c..6bc783dad 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -7,24 +7,24 @@ namespace MWClass { class Static : public MWWorld::Class { - virtual MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + bool hasToolTip (const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) static void registerSelf(); - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; }; } diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 2c1197b69..f1824b7d1 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -7,77 +7,77 @@ namespace MWClass { class Weapon : public MWWorld::Class { - virtual MWWorld::Ptr - copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const; + MWWorld::Ptr + copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const override; public: - virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const; + void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - virtual std::string getName (const MWWorld::ConstPtr& ptr) const; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. - virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, - const MWWorld::Ptr& actor) const; + std::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor) const override; ///< Generate action for activation - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; + MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const override; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. - virtual bool hasItemHealth (const MWWorld::ConstPtr& ptr) const; + bool hasItemHealth (const MWWorld::ConstPtr& ptr) const override; ///< \return Item health data available? - virtual int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const; + int getItemMaxHealth (const MWWorld::ConstPtr& ptr) const override; ///< Return item max health or throw an exception, if class does not have item health - virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; + std::string getScript (const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr - virtual std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const; + std::pair, bool> getEquipmentSlots (const MWWorld::ConstPtr& ptr) const override; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? - virtual int getEquipmentSkill (const MWWorld::ConstPtr& ptr) const; + int getEquipmentSkill (const MWWorld::ConstPtr& ptr) const override; /// Return the index of the skill this item corresponds to when equipped or -1, if there is /// no such skill. - virtual int getValue (const MWWorld::ConstPtr& ptr) const; + int getValue (const MWWorld::ConstPtr& ptr) const override; ///< Return trade value of the object. Throws an exception, if the object can't be traded. static void registerSelf(); - virtual std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getUpSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the pick up sound Id - virtual std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const; + std::string getDownSoundId (const MWWorld::ConstPtr& ptr) const override; ///< Return the put down sound Id - virtual std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const; + std::string getInventoryIcon (const MWWorld::ConstPtr& ptr) const override; ///< Return name of inventory icon. - virtual std::string getEnchantment (const MWWorld::ConstPtr& ptr) const; + std::string getEnchantment (const MWWorld::ConstPtr& ptr) const override; ///< @return the enchantment ID if the object is enchanted, otherwise an empty string - virtual std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; + std::string applyEnchantment(const MWWorld::ConstPtr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const override; ///< Creates a new record using \a ptr as template, with the given name and the given enchantment applied to it. - virtual std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const; + std::pair canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const override; ///< Return 0 if player cannot equip item. 1 if can equip. 2 if it's twohanded weapon. 3 if twohanded weapon conflicts with that. /// Second item in the pair specifies the error message - virtual std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const; + std::shared_ptr use (const MWWorld::Ptr& ptr, bool force=false) const override; ///< Generate action for using via inventory menu - virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; + std::string getModel(const MWWorld::ConstPtr &ptr) const override; - virtual bool canSell (const MWWorld::ConstPtr& item, int npcServices) const; + bool canSell (const MWWorld::ConstPtr& item, int npcServices) const override; - virtual float getWeight (const MWWorld::ConstPtr& ptr) const; + float getWeight (const MWWorld::ConstPtr& ptr) const override; - virtual int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const; + int getEnchantmentPoints (const MWWorld::ConstPtr& ptr) const override; }; } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 3e0cbbad2..047a910b6 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -121,6 +121,7 @@ namespace MWDialogue mTalkedTo = creatureStats.hasTalkedToPlayer(); mActorKnownTopics.clear(); + mActorKnownTopicsFlag.clear(); //greeting const MWWorld::Store &dialogs = @@ -300,11 +301,11 @@ namespace MWDialogue } } + mLastTopic = topic; + executeScript (info->mResultScript, mActor); parseText (info->mResponse); - - mLastTopic = topic; } } @@ -323,6 +324,7 @@ namespace MWDialogue updateGlobals(); mActorKnownTopics.clear(); + mActorKnownTopicsFlag.clear(); const auto& dialogs = MWBase::Environment::get().getWorld()->getStore().get(); @@ -549,9 +551,9 @@ namespace MWDialogue mPermanentDispositionChange += delta; } - bool DialogueManager::checkServiceRefused(ResponseCallback* callback) + bool DialogueManager::checkServiceRefused(ResponseCallback* callback, ServiceType service) { - Filter filter (mActor, mChoice, mTalkedTo); + Filter filter (mActor, service, mTalkedTo); const MWWorld::Store &dialogues = MWBase::Environment::get().getWorld()->getStore().get(); diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 23dd68e91..6c6eb9a9d 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -66,57 +66,57 @@ namespace MWDialogue DialogueManager (const Compiler::Extensions& extensions, Translation::Storage& translationDataStorage); - virtual void clear(); + void clear() override; - virtual bool isInChoice() const; + bool isInChoice() const override; - virtual bool startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback); + bool startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback) override; - std::list getAvailableTopics(); + std::list getAvailableTopics() override; int getTopicFlag(const std::string& topicId) final; bool inJournal (const std::string& topicId, const std::string& infoId) final; - virtual void addTopic (const std::string& topic); + void addTopic (const std::string& topic) override; - virtual void addChoice (const std::string& text,int choice); - const std::vector >& getChoices(); + void addChoice (const std::string& text,int choice) override; + const std::vector >& getChoices() override; - virtual bool isGoodbye(); + bool isGoodbye() override; - virtual void goodbye(); + void goodbye() override; - virtual bool checkServiceRefused (ResponseCallback* callback); + bool checkServiceRefused (ResponseCallback* callback, ServiceType service = ServiceType::Any) override; - virtual void say(const MWWorld::Ptr &actor, const std::string &topic); + void say(const MWWorld::Ptr &actor, const std::string &topic) override; //calbacks for the GUI - virtual void keywordSelected (const std::string& keyword, ResponseCallback* callback); - virtual void goodbyeSelected(); - virtual void questionAnswered (int answer, ResponseCallback* callback); + void keywordSelected (const std::string& keyword, ResponseCallback* callback) override; + void goodbyeSelected() override; + void questionAnswered (int answer, ResponseCallback* callback) override; - virtual void persuade (int type, ResponseCallback* callback); - virtual int getTemporaryDispositionChange () const; + void persuade (int type, ResponseCallback* callback) override; + int getTemporaryDispositionChange () const override; /// @note Controlled by an option, gets discarded when dialogue ends by default - virtual void applyBarterDispositionChange (int delta); + void applyBarterDispositionChange (int delta) override; - virtual int countSavedGameRecords() const; + int countSavedGameRecords() const override; - virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const override; - virtual void readRecord (ESM::ESMReader& reader, uint32_t type); + void readRecord (ESM::ESMReader& reader, uint32_t type) override; /// Changes faction1's opinion of faction2 by \a diff. - virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff); + void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff) override; - virtual void setFactionReaction (const std::string& faction1, const std::string& faction2, int absolute); + void setFactionReaction (const std::string& faction1, const std::string& faction2, int absolute) override; /// @return faction1's opinion of faction2 - virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const; + int getFactionReaction (const std::string& faction1, const std::string& faction2) const override; /// Removes the last added topic response for the given actor from the journal - virtual void clearInfoActor (const MWWorld::Ptr& actor) const; + void clearInfoActor (const MWWorld::Ptr& actor) const override; }; } diff --git a/apps/openmw/mwdialogue/journalimp.hpp b/apps/openmw/mwdialogue/journalimp.hpp index c3e940629..a6501e54e 100644 --- a/apps/openmw/mwdialogue/journalimp.hpp +++ b/apps/openmw/mwdialogue/journalimp.hpp @@ -27,52 +27,52 @@ namespace MWDialogue Journal(); - virtual void clear(); + void clear() override; - virtual void addEntry (const std::string& id, int index, const MWWorld::Ptr& actor); + void addEntry (const std::string& id, int index, const MWWorld::Ptr& actor) override; ///< Add a journal entry. /// @param actor Used as context for replacing of escape sequences (%name, etc). - virtual void setJournalIndex (const std::string& id, int index); + void setJournalIndex (const std::string& id, int index) override; ///< Set the journal index without adding an entry. - virtual int getJournalIndex (const std::string& id) const; + int getJournalIndex (const std::string& id) const override; ///< Get the journal index. - virtual void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor); + void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor) override; /// \note topicId must be lowercase - virtual void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName); + void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName) override; ///< Removes the last topic response added for the given topicId and actor name. /// \note topicId must be lowercase - virtual TEntryIter begin() const; + TEntryIter begin() const override; ///< Iterator pointing to the begin of the main journal. /// /// \note Iterators to main journal entries will never become invalid. - virtual TEntryIter end() const; + TEntryIter end() const override; ///< Iterator pointing past the end of the main journal. - virtual TQuestIter questBegin() const; + TQuestIter questBegin() const override; ///< Iterator pointing to the first quest (sorted by topic ID) - virtual TQuestIter questEnd() const; + TQuestIter questEnd() const override; ///< Iterator pointing past the last quest. - virtual TTopicIter topicBegin() const; + TTopicIter topicBegin() const override; ///< Iterator pointing to the first topic (sorted by topic ID) /// /// \note The topic ID is identical with the user-visible topic string. - virtual TTopicIter topicEnd() const; + TTopicIter topicEnd() const override; ///< Iterator pointing past the last topic. - virtual int countSavedGameRecords() const; + int countSavedGameRecords() const override; - virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) const override; - virtual void readRecord (ESM::ESMReader& reader, uint32_t type); + void readRecord (ESM::ESMReader& reader, uint32_t type) override; }; } diff --git a/apps/openmw/mwdialogue/quest.hpp b/apps/openmw/mwdialogue/quest.hpp index 40824f398..712f94fae 100644 --- a/apps/openmw/mwdialogue/quest.hpp +++ b/apps/openmw/mwdialogue/quest.hpp @@ -24,7 +24,7 @@ namespace MWDialogue Quest (const ESM::QuestState& state); - virtual std::string getName() const; + std::string getName() const override; ///< May be an empty string int getIndex() const; @@ -34,7 +34,7 @@ namespace MWDialogue bool isFinished() const; - virtual void addEntry (const JournalEntry& entry); + void addEntry (const JournalEntry& entry) override; ///< Add entry and adjust index accordingly. /// /// \note Redundant entries are ignored, but the index is still adjusted. diff --git a/apps/openmw/mwgui/alchemywindow.hpp b/apps/openmw/mwgui/alchemywindow.hpp index 82dd0a243..33bd1f974 100644 --- a/apps/openmw/mwgui/alchemywindow.hpp +++ b/apps/openmw/mwgui/alchemywindow.hpp @@ -29,9 +29,9 @@ namespace MWGui public: AlchemyWindow(); - virtual void onOpen(); + void onOpen() override; - void onResChange(int, int) { center(); } + void onResChange(int, int) override { center(); } private: diff --git a/apps/openmw/mwgui/birth.hpp b/apps/openmw/mwgui/birth.hpp index 86af14286..9f9d4332f 100644 --- a/apps/openmw/mwgui/birth.hpp +++ b/apps/openmw/mwgui/birth.hpp @@ -20,9 +20,9 @@ namespace MWGui void setBirthId(const std::string &raceId); void setNextButtonShow(bool shown); - virtual void onOpen(); + void onOpen() override; - bool exit() { return false; } + bool exit() override { return false; } // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 5724defcd..a346526eb 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -115,9 +115,9 @@ struct TypesetBookImpl : TypesetBook return Range (i->data(), i->data() + i->size()); } - size_t pageCount () const { return mPages.size (); } + size_t pageCount () const override { return mPages.size (); } - std::pair getSize () const + std::pair getSize () const override { return std::make_pair (mRect.width (), mRect.height ()); } @@ -261,7 +261,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter { } - Style * createStyle (const std::string& fontName, const Colour& fontColour, bool useBookFont) + Style * createStyle (const std::string& fontName, const Colour& fontColour, bool useBookFont) override { std::string fullFontName; if (fontName.empty()) @@ -291,7 +291,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter } Style* createHotStyle (Style* baseStyle, const Colour& normalColour, const Colour& hoverColour, - const Colour& activeColour, InteractiveId id, bool unique) + const Colour& activeColour, InteractiveId id, bool unique) override { StyleImpl* BaseStyle = static_cast (baseStyle); @@ -311,14 +311,14 @@ struct TypesetBookImpl::Typesetter : BookTypesetter return &style; } - void write (Style * style, Utf8Span text) + void write (Style * style, Utf8Span text) override { Range range = mBook->addContent (text); writeImpl (static_cast (style), range.first, range.second); } - intptr_t addContent (Utf8Span text, bool select) + intptr_t addContent (Utf8Span text, bool select) override { add_partial_text(); @@ -330,14 +330,14 @@ struct TypesetBookImpl::Typesetter : BookTypesetter return reinterpret_cast (&(*i)); } - void selectContent (intptr_t contentHandle) + void selectContent (intptr_t contentHandle) override { add_partial_text(); mCurrentContent = reinterpret_cast (contentHandle); } - void write (Style * style, size_t begin, size_t end) + void write (Style * style, size_t begin, size_t end) override { assert (mCurrentContent != nullptr); assert (end <= mCurrentContent->size ()); @@ -349,7 +349,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter writeImpl (static_cast (style), begin_, end_); } - void lineBreak (float margin) + void lineBreak (float margin) override { assert (margin == 0); //TODO: figure out proper behavior here... @@ -359,7 +359,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter mLine = nullptr; } - void sectionBreak (int margin) + void sectionBreak (int margin) override { add_partial_text(); @@ -374,7 +374,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter } } - void setSectionAlignment (Alignment sectionAlignment) + void setSectionAlignment (Alignment sectionAlignment) override { add_partial_text(); @@ -383,7 +383,7 @@ struct TypesetBookImpl::Typesetter : BookTypesetter mCurrentAlignment = sectionAlignment; } - TypesetBook::Ptr complete () + TypesetBook::Ptr complete () override { int curPageStart = 0; int curPageStop = 0; @@ -869,12 +869,12 @@ protected: } } - void doRender() { mDisplay->doRender (*this); } + void doRender() override { mDisplay->doRender (*this); } // this isn't really a sub-widget, its just a "drawitem" which // should have its own interface - void createDrawItem(MyGUI::ITexture* _texture, MyGUI::ILayerNode* _node) {} - void destroyDrawItem() {}; + void createDrawItem(MyGUI::ITexture* _texture, MyGUI::ILayerNode* _node) override {} + void destroyDrawItem() override {} }; void resetPage() @@ -941,6 +941,9 @@ public: if (!mBook) return; + if (mPage >= mBook->mPages.size()) + return; + dirtyFocusItem (); mFocusItem = 0; @@ -952,6 +955,9 @@ public: if (!mBook) return; + if (mPage >= mBook->mPages.size()) + return; + left -= mCroppedParent->getAbsoluteLeft (); top -= mCroppedParent->getAbsoluteTop (); @@ -988,6 +994,9 @@ public: if (!mBook) return; + if (mPage >= mBook->mPages.size()) + return; + // work around inconsistency in MyGUI where the mouse press coordinates aren't // transformed by the current Layer (even though mouse *move* events are). MyGUI::IntPoint pos (left, top); @@ -1013,6 +1022,9 @@ public: if (!mBook) return; + if (mPage >= mBook->mPages.size()) + return; + // work around inconsistency in MyGUI where the mouse release coordinates aren't // transformed by the current Layer (even though mouse *move* events are). MyGUI::IntPoint pos (left, top); diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index b0dfe09ce..116437f22 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -14,10 +14,10 @@ namespace MWGui public: BookWindow(); - void setPtr(const MWWorld::Ptr& book); + void setPtr(const MWWorld::Ptr& book) override; void setInventoryAllowed(bool allowed); - void onResChange(int, int) { center(); } + void onResChange(int, int) override { center(); } protected: void onNextPageButtonClicked (MyGUI::Widget* sender); diff --git a/apps/openmw/mwgui/class.hpp b/apps/openmw/mwgui/class.hpp index 3a2573fd4..bb34a0553 100644 --- a/apps/openmw/mwgui/class.hpp +++ b/apps/openmw/mwgui/class.hpp @@ -21,9 +21,9 @@ namespace MWGui std::string getText() const; void setButtons(ButtonList &buttons); - virtual void onOpen(); + void onOpen() override; - bool exit() { return false; } + bool exit() override { return false; } // Events typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Int; @@ -69,7 +69,7 @@ namespace MWGui std::string getClassId() const; void setClassId(const std::string &classId); - bool exit() { return false; } + bool exit() override { return false; } // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; @@ -104,9 +104,9 @@ namespace MWGui void setClassId(const std::string &classId); void setNextButtonShow(bool shown); - virtual void onOpen(); + void onOpen() override; - bool exit() { return false; } + bool exit() override { return false; } // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; @@ -148,7 +148,7 @@ namespace MWGui SelectSpecializationDialog(); ~SelectSpecializationDialog(); - virtual bool exit(); + bool exit() override; ESM::Class::Specialization getSpecializationId() const { return mSpecializationId; } @@ -181,7 +181,7 @@ namespace MWGui SelectAttributeDialog(); ~SelectAttributeDialog(); - virtual bool exit(); + bool exit() override; ESM::Attribute::AttributeID getAttributeId() const { return mAttributeId; } @@ -212,7 +212,7 @@ namespace MWGui SelectSkillDialog(); ~SelectSkillDialog(); - virtual bool exit(); + bool exit() override; ESM::Skill::SkillEnum getSkillId() const { return mSkillId; } @@ -268,7 +268,7 @@ namespace MWGui CreateClassDialog(); virtual ~CreateClassDialog(); - bool exit() { return false; } + bool exit() override { return false; } std::string getName() const; std::string getDescription() const; diff --git a/apps/openmw/mwgui/companionitemmodel.hpp b/apps/openmw/mwgui/companionitemmodel.hpp index b30a98142..1872dd156 100644 --- a/apps/openmw/mwgui/companionitemmodel.hpp +++ b/apps/openmw/mwgui/companionitemmodel.hpp @@ -13,8 +13,8 @@ namespace MWGui public: CompanionItemModel (const MWWorld::Ptr& actor); - virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true); - virtual void removeItem (const ItemStack& item, size_t count); + MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true) override; + void removeItem (const ItemStack& item, size_t count) override; bool hasProfit(const MWWorld::Ptr& actor); }; diff --git a/apps/openmw/mwgui/companionwindow.hpp b/apps/openmw/mwgui/companionwindow.hpp index 442ce57da..7a7c92e3d 100644 --- a/apps/openmw/mwgui/companionwindow.hpp +++ b/apps/openmw/mwgui/companionwindow.hpp @@ -22,13 +22,13 @@ namespace MWGui public: CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager); - virtual bool exit(); + bool exit() override; - virtual void resetReference(); + void resetReference() override; - void setPtr(const MWWorld::Ptr& npc); - void onFrame (float dt); - void clear() { resetReference(); } + void setPtr(const MWWorld::Ptr& npc) override; + void onFrame (float dt) override; + void clear() override { resetReference(); } private: ItemView* mItemView; @@ -55,7 +55,7 @@ namespace MWGui void onCloseButtonClicked(MyGUI::Widget* _sender); - virtual void onReferenceUnavailable(); + void onReferenceUnavailable() override; }; } diff --git a/apps/openmw/mwgui/confirmationdialog.hpp b/apps/openmw/mwgui/confirmationdialog.hpp index ab52549ec..2acefd54c 100644 --- a/apps/openmw/mwgui/confirmationdialog.hpp +++ b/apps/openmw/mwgui/confirmationdialog.hpp @@ -10,7 +10,7 @@ namespace MWGui public: ConfirmationDialog(); void askForConfirmation(const std::string& message); - virtual bool exit(); + bool exit() override; typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 120573d59..e56cd170c 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -30,7 +30,7 @@ namespace MWGui ConsoleInterpreterContext (Console& console, MWWorld::Ptr reference); - virtual void report (const std::string& message); + void report (const std::string& message) override; }; ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console, diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index e431d18d1..52aa42f2a 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -39,9 +39,9 @@ namespace MWGui Console(int w, int h, bool consoleOnlyScripts); - virtual void onOpen(); + void onOpen() override; - void onResChange(int width, int height); + void onResChange(int width, int height) override; // Print a message to the console, in specified color. void print(const std::string &msg, const std::string& color = "#FFFFFF"); @@ -60,13 +60,13 @@ namespace MWGui void updateSelectedObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr); - void clear(); + void clear() override; - virtual void resetReference (); + void resetReference () override; protected: - virtual void onReferenceUnavailable(); + void onReferenceUnavailable() override; private: @@ -86,10 +86,10 @@ namespace MWGui bool compile (const std::string& cmd, Compiler::Output& output); /// Report error to the user. - virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); + void report (const std::string& message, const Compiler::TokenLoc& loc, Type type) override; /// Report a file related error - virtual void report (const std::string& message, Type type); + void report (const std::string& message, Type type) override; /// Write all valid identifiers and keywords into mNames and sort them. /// \note If mNames is not empty, this function is a no-op. diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 3f21f7eb4..a73813901 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -172,6 +172,7 @@ namespace MWGui if (!mPtr.isEmpty()) MWBase::Environment::get().getMechanicsManager()->onClose(mPtr); + resetReference(); } void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) @@ -233,36 +234,38 @@ namespace MWGui { MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); + // Copy mPtr because onTakeAllButtonClicked closes the window which resets the reference + MWWorld::Ptr ptr = mPtr; onTakeAllButtonClicked(mTakeButton); - if (mPtr.getClass().isPersistent(mPtr)) + if (ptr.getClass().isPersistent(ptr)) MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}"); else { - MWMechanics::CreatureStats& creatureStats = mPtr.getClass().getCreatureStats(mPtr); + MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr); // If we dispose corpse before end of death animation, we should update death counter counter manually. // Also we should run actor's script - it may react on actor's death. if (creatureStats.isDead() && !creatureStats.isDeathAnimationFinished()) { creatureStats.setDeathAnimationFinished(true); - MWBase::Environment::get().getMechanicsManager()->notifyDied(mPtr); + MWBase::Environment::get().getMechanicsManager()->notifyDied(ptr); - const std::string script = mPtr.getClass().getScript(mPtr); + const std::string script = ptr.getClass().getScript(ptr); if (!script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled()) { - MWScript::InterpreterContext interpreterContext (&mPtr.getRefData().getLocals(), mPtr); + MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); MWBase::Environment::get().getScriptManager()->run (script, interpreterContext); } // Clean up summoned creatures as well - std::map& creatureMap = creatureStats.getSummonedCreatureMap(); + std::map& creatureMap = creatureStats.getSummonedCreatureMap(); for (const auto& creature : creatureMap) - MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mPtr, creature.second); + MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(ptr, creature.second); creatureMap.clear(); } - MWBase::Environment::get().getWorld()->deleteObject(mPtr); + MWBase::Environment::get().getWorld()->deleteObject(ptr); } mPtr = MWWorld::Ptr(); diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index cf02d165d..feda123fb 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -33,13 +33,13 @@ namespace MWGui public: ContainerWindow(DragAndDrop* dragAndDrop); - void setPtr(const MWWorld::Ptr& container); - virtual void onClose(); - void clear() { resetReference(); } + void setPtr(const MWWorld::Ptr& container) override; + void onClose() override; + void clear() override { resetReference(); } - void onFrame(float dt) { checkReferenceAvailable(); } + void onFrame(float dt) override { checkReferenceAvailable(); } - virtual void resetReference(); + void resetReference() override; private: DragAndDrop* mDragAndDrop; @@ -64,7 +64,7 @@ namespace MWGui /// @return is taking the item allowed? bool onTakeItem(const ItemStack& item, int count); - virtual void onReferenceUnavailable(); + void onReferenceUnavailable() override; }; } #endif // CONTAINER_H diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index 0cfa6ebf5..31439f349 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -39,22 +39,29 @@ namespace namespace MWGui { - ContainerItemModel::ContainerItemModel(const std::vector& itemSources, const std::vector& worldItems) - : mItemSources(itemSources) - , mWorldItems(worldItems) + : mWorldItems(worldItems) + , mTrading(true) { - assert (!mItemSources.empty()); + assert (!itemSources.empty()); + // Tie resolution lifetimes to the ItemModel + mItemSources.reserve(itemSources.size()); + for(const MWWorld::Ptr& source : itemSources) + { + MWWorld::ContainerStore& store = source.getClass().getContainerStore(source); + mItemSources.push_back(std::make_pair(source, store.resolveTemporarily())); + } } -ContainerItemModel::ContainerItemModel (const MWWorld::Ptr& source) +ContainerItemModel::ContainerItemModel (const MWWorld::Ptr& source) : mTrading(false) { - mItemSources.push_back(source); + MWWorld::ContainerStore& store = source.getClass().getContainerStore(source); + mItemSources.push_back(std::make_pair(source, store.resolveTemporarily())); } bool ContainerItemModel::allowedToUseItems() const { - if (mItemSources.size() == 0) + if (mItemSources.empty()) return true; MWWorld::Ptr ptr = MWMechanics::getPlayer(); @@ -62,7 +69,7 @@ bool ContainerItemModel::allowedToUseItems() const // Check if the player is allowed to use items from opened container MWBase::MechanicsManager* mm = MWBase::Environment::get().getMechanicsManager(); - return mm->isAllowedToUse(ptr, mItemSources[0], victim); + return mm->isAllowedToUse(ptr, mItemSources[0].first, victim); } ItemStack ContainerItemModel::getItem (ModelIndex index) @@ -93,25 +100,31 @@ ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item) MWWorld::Ptr ContainerItemModel::copyItem (const ItemStack& item, size_t count, bool allowAutoEquip) { - const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1]; - if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source)) + auto& source = mItemSources[0]; + MWWorld::ContainerStore& store = source.first.getClass().getContainerStore(source.first); + if (item.mBase.getContainerStore() == &store) throw std::runtime_error("Item to copy needs to be from a different container!"); - return *source.getClass().getContainerStore(source).add(item.mBase, count, source, allowAutoEquip); + return *store.add(item.mBase, count, source.first, allowAutoEquip); } void ContainerItemModel::removeItem (const ItemStack& item, size_t count) { int toRemove = count; - for (MWWorld::Ptr& source : mItemSources) + for (auto& source : mItemSources) { - MWWorld::ContainerStore& store = source.getClass().getContainerStore(source); + MWWorld::ContainerStore& store = source.first.getClass().getContainerStore(source.first); for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { if (stacks(*it, item.mBase)) { - toRemove -= store.remove(*it, toRemove, source); + int quantity = it->mRef->mData.getCount(false); + // If this is a restocking quantity, just don't remove it + if(quantity < 0 && mTrading) + toRemove += quantity; + else + toRemove -= store.remove(*it, toRemove, source.first); if (toRemove <= 0) return; } @@ -138,9 +151,9 @@ void ContainerItemModel::removeItem (const ItemStack& item, size_t count) void ContainerItemModel::update() { mItems.clear(); - for (MWWorld::Ptr& source : mItemSources) + for (auto& source : mItemSources) { - MWWorld::ContainerStore& store = source.getClass().getContainerStore(source); + MWWorld::ContainerStore& store = source.first.getClass().getContainerStore(source.first); for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { @@ -194,7 +207,7 @@ bool ContainerItemModel::onDropItem(const MWWorld::Ptr &item, int count) if (mItemSources.empty()) return false; - MWWorld::Ptr target = mItemSources[0]; + MWWorld::Ptr target = mItemSources[0].first; if (target.getTypeName() != typeid(ESM::Container).name()) return true; @@ -224,7 +237,7 @@ bool ContainerItemModel::onTakeItem(const MWWorld::Ptr &item, int count) if (mItemSources.empty()) return false; - MWWorld::Ptr target = mItemSources[0]; + MWWorld::Ptr target = mItemSources[0].first; // Looting a dead corpse is considered OK if (target.getClass().isActor() && target.getClass().getCreatureStats(target).isDead()) diff --git a/apps/openmw/mwgui/containeritemmodel.hpp b/apps/openmw/mwgui/containeritemmodel.hpp index 806cc0a73..c54f11314 100644 --- a/apps/openmw/mwgui/containeritemmodel.hpp +++ b/apps/openmw/mwgui/containeritemmodel.hpp @@ -1,8 +1,13 @@ #ifndef MWGUI_CONTAINER_ITEM_MODEL_H #define MWGUI_CONTAINER_ITEM_MODEL_H +#include +#include + #include "itemmodel.hpp" +#include "../mwworld/containerstore.hpp" + namespace MWGui { @@ -17,24 +22,24 @@ namespace MWGui ContainerItemModel (const MWWorld::Ptr& source); - virtual bool allowedToUseItems() const; + bool allowedToUseItems() const override; - virtual bool onDropItem(const MWWorld::Ptr &item, int count); - virtual bool onTakeItem(const MWWorld::Ptr &item, int count); + bool onDropItem(const MWWorld::Ptr &item, int count) override; + bool onTakeItem(const MWWorld::Ptr &item, int count) override; - virtual ItemStack getItem (ModelIndex index); - virtual ModelIndex getIndex (ItemStack item); - virtual size_t getItemCount(); + ItemStack getItem (ModelIndex index) override; + ModelIndex getIndex (ItemStack item) override; + size_t getItemCount() override; - virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true); - virtual void removeItem (const ItemStack& item, size_t count); + MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true) override; + void removeItem (const ItemStack& item, size_t count) override; - virtual void update(); + void update() override; private: - std::vector mItemSources; + std::vector> mItemSources; std::vector mWorldItems; - + const bool mTrading; std::vector mItems; }; diff --git a/apps/openmw/mwgui/debugwindow.hpp b/apps/openmw/mwgui/debugwindow.hpp index af5b914ea..33647c078 100644 --- a/apps/openmw/mwgui/debugwindow.hpp +++ b/apps/openmw/mwgui/debugwindow.hpp @@ -11,7 +11,7 @@ namespace MWGui public: DebugWindow(); - void onFrame(float dt); + void onFrame(float dt) override; private: MyGUI::TabControl* mTabControl; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 6f3fb9e91..cc1314b0e 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -41,7 +41,7 @@ namespace MWGui } - void addResponse(const std::string& title, const std::string& text) + void addResponse(const std::string& title, const std::string& text) override { mWindow->addResponse(title, text, mNeedMargin); } @@ -366,7 +366,9 @@ namespace MWGui void DialogueWindow::onSelectListItem(const std::string& topic, int id) { - if (mGoodbye || MWBase::Environment::get().getDialogueManager()->isInChoice()) + MWBase::DialogueManager* dialogueManager = MWBase::Environment::get().getDialogueManager(); + + if (mGoodbye || dialogueManager->isInChoice()) return; const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -393,21 +395,21 @@ namespace MWGui mPersuasionDialog.setVisible(true); else if (topic == sCompanionShare) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr); - else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(mCallback.get())) + else if (!dialogueManager->checkServiceRefused(mCallback.get())) { - if (topic == sBarter) + if (topic == sBarter && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Barter)) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr); - else if (topic == sSpells) + else if (topic == sSpells && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Spells)) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying, mPtr); - else if (topic == sTravel) + else if (topic == sTravel && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Travel)) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel, mPtr); - else if (topic == sSpellMakingMenuTitle) + else if (topic == sSpellMakingMenuTitle && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Spellmaking)) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation, mPtr); - else if (topic == sEnchanting) + else if (topic == sEnchanting && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Enchanting)) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting, mPtr); - else if (topic == sServiceTrainingTitle) + else if (topic == sServiceTrainingTitle && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Training)) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training, mPtr); - else if (topic == sRepair) + else if (topic == sRepair && !dialogueManager->checkServiceRefused(mCallback.get(), MWBase::DialogueManager::Repair)) MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr); } else @@ -682,7 +684,6 @@ namespace MWGui { mHistoryContents.push_back(new Response(text, title, needMargin)); updateHistory(); - updateTopics(); } void DialogueWindow::addMessageBox(const std::string& text) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index d9c26ef20..ed4c39afe 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -29,9 +29,9 @@ namespace MWGui public: PersuasionDialog(ResponseCallback* callback); - virtual void onOpen(); + void onOpen() override; - virtual MyGUI::Widget* getDefaultKeyFocus(); + MyGUI::Widget* getDefaultKeyFocus() override; private: std::unique_ptr mCallback; @@ -62,7 +62,7 @@ namespace MWGui EventHandle_TopicId eventTopicActivated; Topic(const std::string& id) : mTopicId(id) {} std::string mTopicId; - virtual void activated (); + void activated () override; }; struct Choice : Link @@ -71,14 +71,14 @@ namespace MWGui EventHandle_ChoiceId eventChoiceActivated; Choice(int id) : mChoiceId(id) {} int mChoiceId; - virtual void activated (); + void activated () override; }; struct Goodbye : Link { typedef MyGUI::delegates::CMultiDelegate0 Event_Activated; Event_Activated eventActivated; - virtual void activated (); + void activated () override; }; typedef MWDialogue::KeywordSearch KeywordSearchT; @@ -93,7 +93,7 @@ namespace MWGui struct Response : DialogueText { Response(const std::string& text, const std::string& title = "", bool needMargin = true); - virtual void write (BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, std::map& topicLinks) const; + void write (BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, std::map& topicLinks) const override; void addTopicLink (BookTypesetter::Ptr typesetter, intptr_t topicId, size_t begin, size_t end) const; std::string mTitle; bool mNeedMargin; @@ -102,7 +102,7 @@ namespace MWGui struct Message : DialogueText { Message(const std::string& text); - virtual void write (BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, std::map& topicLinks) const; + void write (BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, std::map& topicLinks) const override; }; class DialogueWindow: public WindowBase, public ReferenceInterface @@ -113,14 +113,14 @@ namespace MWGui void onTradeComplete(); - virtual bool exit(); + bool exit() override; // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; void notifyLinkClicked (TypesetBook::InteractiveId link); - void setPtr(const MWWorld::Ptr& actor); + void setPtr(const MWWorld::Ptr& actor) override; void setKeywords(std::list keyWord); @@ -128,12 +128,12 @@ namespace MWGui void addMessageBox(const std::string& text); - void onFrame(float dt); - void clear() { resetReference(); } + void onFrame(float dt) override; + void clear() override { resetReference(); } void updateTopics(); - void onClose(); + void onClose() override; protected: void updateTopicsPane(); @@ -152,7 +152,7 @@ namespace MWGui void updateHistory(bool scrollbar=false); - virtual void onReferenceUnavailable(); + void onReferenceUnavailable() override; private: void updateDisposition(); diff --git a/apps/openmw/mwgui/enchantingdialog.hpp b/apps/openmw/mwgui/enchantingdialog.hpp index 4906de919..3989ae076 100644 --- a/apps/openmw/mwgui/enchantingdialog.hpp +++ b/apps/openmw/mwgui/enchantingdialog.hpp @@ -19,23 +19,23 @@ namespace MWGui EnchantingDialog(); virtual ~EnchantingDialog(); - virtual void onOpen(); + void onOpen() override; - void onFrame(float dt) { checkReferenceAvailable(); } - void clear() { resetReference(); } + void onFrame(float dt) override { checkReferenceAvailable(); } + void clear() override { resetReference(); } void setSoulGem (const MWWorld::Ptr& gem); void setItem (const MWWorld::Ptr& item); /// Actor Ptr: buy enchantment from this actor /// Soulgem Ptr: player self-enchant - void setPtr(const MWWorld::Ptr& ptr); + void setPtr(const MWWorld::Ptr& ptr) override; - virtual void resetReference(); + void resetReference() override; protected: - virtual void onReferenceUnavailable(); - virtual void notifyEffectsChanged (); + void onReferenceUnavailable() override; + void notifyEffectsChanged() override; void onCancelButtonClicked(MyGUI::Widget* sender); void onSelectItem (MyGUI::Widget* sender); diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index b16a4e57d..d56351414 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -149,8 +149,8 @@ namespace MWGui public: TextElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle, const TextStyle & textStyle, const std::string & text); - virtual int getHeight(); - virtual int pageSplit(); + int getHeight() override; + int pageSplit() override; private: int currentFontHeight() const; TextStyle mTextStyle; @@ -162,8 +162,8 @@ namespace MWGui public: ImageElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle, const std::string & src, int width, int height); - virtual int getHeight(); - virtual int pageSplit(); + int getHeight() override; + int pageSplit() override; private: int mImageHeight; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 420210028..4d2326daa 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -37,8 +37,8 @@ namespace MWGui { public: WorldItemModel(float left, float top) : mLeft(left), mTop(top) {} - virtual ~WorldItemModel() {} - virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool /*allowAutoEquip*/) + virtual ~WorldItemModel() override {} + MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool /*allowAutoEquip*/) override { MWBase::World* world = MWBase::Environment::get().getWorld(); @@ -52,11 +52,11 @@ namespace MWGui return dropped; } - virtual void removeItem (const ItemStack& item, size_t count) { throw std::runtime_error("removeItem not implemented"); } - virtual ModelIndex getIndex (ItemStack item) { throw std::runtime_error("getIndex not implemented"); } - virtual void update() {} - virtual size_t getItemCount() { return 0; } - virtual ItemStack getItem (ModelIndex index) { throw std::runtime_error("getItem not implemented"); } + void removeItem (const ItemStack& item, size_t count) override { throw std::runtime_error("removeItem not implemented"); } + ModelIndex getIndex (ItemStack item) override { throw std::runtime_error("getIndex not implemented"); } + void update() override {} + size_t getItemCount() override { return 0; } + ItemStack getItem (ModelIndex index) override { throw std::runtime_error("getItem not implemented"); } private: // Where to drop the item diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 195c60049..0761897ec 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -114,8 +114,8 @@ namespace MWGui void onMapClicked(MyGUI::Widget* _sender); // LocalMapBase - virtual void customMarkerCreated(MyGUI::Widget* marker) override; - virtual void doorMarkerCreated(MyGUI::Widget* marker) override; + void customMarkerCreated(MyGUI::Widget* marker) override; + void doorMarkerCreated(MyGUI::Widget* marker) override; void updateEnemyHealthBar(); diff --git a/apps/openmw/mwgui/inventoryitemmodel.hpp b/apps/openmw/mwgui/inventoryitemmodel.hpp index d1fb88b6e..30d17f3e6 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.hpp +++ b/apps/openmw/mwgui/inventoryitemmodel.hpp @@ -11,19 +11,19 @@ namespace MWGui public: InventoryItemModel (const MWWorld::Ptr& actor); - virtual ItemStack getItem (ModelIndex index); - virtual ModelIndex getIndex (ItemStack item); - virtual size_t getItemCount(); + ItemStack getItem (ModelIndex index) override; + ModelIndex getIndex (ItemStack item) override; + size_t getItemCount() override; - virtual bool onTakeItem(const MWWorld::Ptr &item, int count); + bool onTakeItem(const MWWorld::Ptr &item, int count) override; - virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true); - virtual void removeItem (const ItemStack& item, size_t count); + MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true) override; + void removeItem (const ItemStack& item, size_t count) override; /// Move items from this model to \a otherModel. - virtual MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel); + MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel) override; - virtual void update(); + void update() override; protected: MWWorld::Ptr mActor; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 0da9fd535..9854e5446 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -782,7 +782,8 @@ namespace MWGui return; const MWMechanics::CreatureStats &stats = player.getClass().getCreatureStats(player); - if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery()) + bool godmode = MWBase::Environment::get().getWorld()->getGodModeState(); + if ((!godmode && stats.isParalyzed()) || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery()) return; ItemModel::ModelIndex selected = -1; diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index b776a60a1..bd986744f 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -35,12 +35,12 @@ namespace MWGui public: InventoryWindow(DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem); - virtual void onOpen(); + void onOpen() override; /// start trading, disables item drag&drop void setTrading(bool trading); - void onFrame(float dt); + void onFrame(float dt) override; void pickUpObject (MWWorld::Ptr object); @@ -56,7 +56,7 @@ namespace MWGui void updatePlayer(); - void clear(); + void clear() override; void useItem(const MWWorld::Ptr& ptr, bool force=false); @@ -66,7 +66,7 @@ namespace MWGui void cycle(bool next); protected: - virtual void onTitleDoubleClicked(); + void onTitleDoubleClicked() override; private: DragAndDrop* mDragAndDrop; @@ -123,7 +123,7 @@ namespace MWGui void onFilterChanged(MyGUI::Widget* _sender); void onNameFilterChanged(MyGUI::EditBox* _sender); void onAvatarClicked(MyGUI::Widget* _sender); - void onPinToggled(); + void onPinToggled() override; void updateEncumbranceBar(); void notifyContentChanged(); diff --git a/apps/openmw/mwgui/itemmodel.hpp b/apps/openmw/mwgui/itemmodel.hpp index 4d923bae3..e120dde0f 100644 --- a/apps/openmw/mwgui/itemmodel.hpp +++ b/apps/openmw/mwgui/itemmodel.hpp @@ -88,15 +88,15 @@ namespace MWGui ProxyItemModel(); virtual ~ProxyItemModel(); - bool allowedToUseItems() const; + bool allowedToUseItems() const override; - virtual void onClose(); - virtual bool onDropItem(const MWWorld::Ptr &item, int count); - virtual bool onTakeItem(const MWWorld::Ptr &item, int count); + void onClose() override; + bool onDropItem(const MWWorld::Ptr &item, int count) override; + bool onTakeItem(const MWWorld::Ptr &item, int count) override; - virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true); - virtual void removeItem (const ItemStack& item, size_t count); - virtual ModelIndex getIndex (ItemStack item); + MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool allowAutoEquip = true) override; + void removeItem (const ItemStack& item, size_t count) override; + ModelIndex getIndex (ItemStack item) override; /// @note Takes ownership of the passed pointer. void setSourceModel(ItemModel* sourceModel); diff --git a/apps/openmw/mwgui/itemselection.hpp b/apps/openmw/mwgui/itemselection.hpp index 07b6452a5..6132bac7a 100644 --- a/apps/openmw/mwgui/itemselection.hpp +++ b/apps/openmw/mwgui/itemselection.hpp @@ -21,7 +21,7 @@ namespace MWGui public: ItemSelectionDialog(const std::string& label); - virtual bool exit(); + bool exit() override; typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Item; diff --git a/apps/openmw/mwgui/jailscreen.hpp b/apps/openmw/mwgui/jailscreen.hpp index 36d19b5a9..871a861d7 100644 --- a/apps/openmw/mwgui/jailscreen.hpp +++ b/apps/openmw/mwgui/jailscreen.hpp @@ -12,9 +12,9 @@ namespace MWGui JailScreen(); void goToJail(int days); - void onFrame(float dt); + void onFrame(float dt) override; - bool exit() { return false; } + bool exit() override { return false; } private: int mDays; diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 3621656bc..426c3b437 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -46,11 +46,11 @@ struct JournalViewModelImpl : JournalViewModel return Utf8Span (point, point + str.size ()); } - void load () + void load () override { } - void unload () + void unload () override { mKeywordSearch.clear (); mKeywordSearchLoaded = false; @@ -69,7 +69,7 @@ struct JournalViewModelImpl : JournalViewModel } } - bool isEmpty () const + bool isEmpty () const override { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); @@ -141,14 +141,14 @@ struct JournalViewModelImpl : JournalViewModel } } - Utf8Span body () const + Utf8Span body () const override { ensureLoaded (); return toUtf8Span (utf8text); } - void visitSpans (std::function < void (TopicId, size_t, size_t)> visitor) const + void visitSpans (std::function < void (TopicId, size_t, size_t)> visitor) const override { ensureLoaded (); mModel->ensureKeyWordSearchLoaded (); @@ -192,7 +192,7 @@ struct JournalViewModelImpl : JournalViewModel }; - void visitQuestNames (bool active_only, std::function visitor) const + void visitQuestNames (bool active_only, std::function visitor) const override { MWBase::Journal * journal = MWBase::Environment::get ().getJournal (); @@ -242,12 +242,12 @@ struct JournalViewModelImpl : JournalViewModel BaseEntry (model, itr) {} - std::string getText () const + std::string getText () const override { return itr->getText(); } - Utf8Span timestamp () const + Utf8Span timestamp () const override { if (timestamp_buffer.empty ()) { @@ -267,7 +267,7 @@ struct JournalViewModelImpl : JournalViewModel } }; - void visitJournalEntries (const std::string& questName, std::function visitor) const + void visitJournalEntries (const std::string& questName, std::function visitor) const override { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); @@ -300,13 +300,13 @@ struct JournalViewModelImpl : JournalViewModel } } - void visitTopicName (TopicId topicId, std::function visitor) const + void visitTopicName (TopicId topicId, std::function visitor) const override { MWDialogue::Topic const & topic = * reinterpret_cast (topicId); visitor (toUtf8Span (topic.getName())); } - void visitTopicNamesStartingWith (Utf8Stream::UnicodeChar character, std::function < void (const std::string&) > visitor) const + void visitTopicNamesStartingWith (Utf8Stream::UnicodeChar character, std::function < void (const std::string&) > visitor) const override { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); @@ -330,19 +330,19 @@ struct JournalViewModelImpl : JournalViewModel BaseEntry (model, itr), mTopic (topic) {} - std::string getText () const + std::string getText () const override { return itr->getText(); } - Utf8Span source () const + Utf8Span source () const override { return toUtf8Span (itr->mActorName); } }; - void visitTopicEntries (TopicId topicId, std::function visitor) const + void visitTopicEntries (TopicId topicId, std::function visitor) const override { typedef MWDialogue::Topic::TEntryIter iterator_t; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 43e7edf1e..1474becf0 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -226,7 +226,7 @@ namespace mTopicsMode = false; } - void onOpen() + void onOpen() override { if (!MWBase::Environment::get().getWindowManager ()->getJournalAllowed ()) { @@ -257,7 +257,7 @@ namespace MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(getWidget(CloseBTN)); } - void onClose() + void onClose() override { mModel->unload (); @@ -270,7 +270,7 @@ namespace mTopicIndexBook.reset (); } - void setVisible (bool newValue) + void setVisible (bool newValue) override { WindowBase::setVisible (newValue); } diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 8cc0a5ef3..c18e6e4c0 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -21,10 +21,10 @@ namespace MWGui static JournalWindow * create (std::shared_ptr Model, bool questList, ToUTF8::FromType encoding); /// destroy this instance of the JournalWindow implementation - virtual ~JournalWindow () {}; + virtual ~JournalWindow () {} /// show/hide the journal window - virtual void setVisible (bool newValue) = 0; + void setVisible (bool newValue) override = 0; }; } diff --git a/apps/openmw/mwgui/keyboardnavigation.hpp b/apps/openmw/mwgui/keyboardnavigation.hpp index 2a094a2df..d5159c24a 100644 --- a/apps/openmw/mwgui/keyboardnavigation.hpp +++ b/apps/openmw/mwgui/keyboardnavigation.hpp @@ -19,7 +19,7 @@ namespace MWGui void saveFocus(int mode); void restoreFocus(int mode); - void _unlinkWidget(MyGUI::Widget* widget); + void _unlinkWidget(MyGUI::Widget* widget) override; void onFrame(); diff --git a/apps/openmw/mwgui/levelupdialog.hpp b/apps/openmw/mwgui/levelupdialog.hpp index 36810665e..6c9182609 100644 --- a/apps/openmw/mwgui/levelupdialog.hpp +++ b/apps/openmw/mwgui/levelupdialog.hpp @@ -11,7 +11,7 @@ namespace MWGui public: LevelupDialog(); - virtual void onOpen(); + void onOpen() override; private: MyGUI::Button* mOkButton; diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 521b88f29..cd0384bb0 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -141,7 +141,7 @@ namespace MWGui { } - virtual void operator () (osg::RenderInfo& renderInfo) const + void operator () (osg::RenderInfo& renderInfo) const override { if (!oneshot) return; @@ -159,7 +159,7 @@ namespace MWGui class DontComputeBoundCallback : public osg::Node::ComputeBoundingSphereCallback { public: - virtual osg::BoundingSphere computeBound(const osg::Node&) const { return osg::BoundingSphere(); } + osg::BoundingSphere computeBound(const osg::Node&) const override { return osg::BoundingSphere(); } }; void LoadingScreen::loadingOn(bool visible) diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index b3e2534ce..2577827aa 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -36,14 +36,14 @@ namespace MWGui virtual ~LoadingScreen(); /// Overridden from Loading::Listener, see the Loading::Listener documentation for usage details - virtual void setLabel (const std::string& label, bool important, bool center); - virtual void loadingOn(bool visible=true); - virtual void loadingOff(); - virtual void setProgressRange (size_t range); - virtual void setProgress (size_t value); - virtual void increaseProgress (size_t increase=1); + void setLabel (const std::string& label, bool important, bool center) override; + void loadingOn(bool visible=true) override; + void loadingOff() override; + void setProgressRange (size_t range) override; + void setProgress (size_t value) override; + void increaseProgress (size_t increase=1) override; - virtual void setVisible(bool visible); + void setVisible(bool visible) override; double getTargetFrameRate() const; diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index 82553d22e..560eb93dc 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -32,13 +32,13 @@ namespace MWGui MainMenu(int w, int h, const VFS::Manager* vfs, const std::string& versionDescription); ~MainMenu(); - void onResChange(int w, int h); + void onResChange(int w, int h) override; - virtual void setVisible (bool visible); + void setVisible (bool visible) override; - void onFrame(float dt); + void onFrame(float dt) override; - bool exit(); + bool exit() override; private: const VFS::Manager* mVFS; diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 7b86f7617..7e8092f28 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -179,7 +179,7 @@ namespace MWGui public: EditNoteDialog(); - virtual void onOpen(); + void onOpen() override; void showDeleteButton(bool show); bool getDeleteButtonShown(); @@ -210,8 +210,8 @@ namespace MWGui void setCellName(const std::string& cellName); - virtual void setAlpha(float alpha); - void setVisible(bool visible); + void setAlpha(float alpha) override; + void setVisible(bool visible) override; void renderGlobalMap(); @@ -227,14 +227,14 @@ namespace MWGui void ensureGlobalMapLoaded(); - virtual void onOpen(); + void onOpen() override; - void onFrame(float dt); + void onFrame(float dt) override; - virtual void updateCustomMarkers(); + void updateCustomMarkers() override; /// Clear all savegame-specific data - void clear(); + void clear() override; void write (ESM::ESMWriter& writer, Loading::Listener& progress); void readRecord (ESM::ESMReader& reader, uint32_t type); @@ -280,13 +280,13 @@ namespace MWGui EditNoteDialog mEditNoteDialog; ESM::CustomMarker mEditingMarker; - virtual void onPinToggled(); - virtual void onTitleDoubleClicked(); + void onPinToggled() override; + void onTitleDoubleClicked() override; - virtual void doorMarkerCreated(MyGUI::Widget* marker); - virtual void customMarkerCreated(MyGUI::Widget *marker); + void doorMarkerCreated(MyGUI::Widget* marker) override; + void customMarkerCreated(MyGUI::Widget *marker) override; - virtual void notifyPlayerUpdate(); + void notifyPlayerUpdate() override; }; } diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 282c0e4ea..e737cb2b2 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -63,6 +63,7 @@ void MerchantRepair::setPtr(const MWWorld::Ptr &actor) int x = static_cast((maxDurability - durability) / r); x = static_cast(fRepairMult * x); + x = std::max(1, x); int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true); diff --git a/apps/openmw/mwgui/merchantrepair.hpp b/apps/openmw/mwgui/merchantrepair.hpp index 26887ae2c..f5276d7f6 100644 --- a/apps/openmw/mwgui/merchantrepair.hpp +++ b/apps/openmw/mwgui/merchantrepair.hpp @@ -12,9 +12,9 @@ class MerchantRepair : public WindowBase public: MerchantRepair(); - virtual void onOpen(); + void onOpen() override; - void setPtr(const MWWorld::Ptr& actor); + void setPtr(const MWWorld::Ptr& actor) override; private: MyGUI::ScrollView* mList; diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index a6f2e3f00..28993d537 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -84,7 +84,7 @@ namespace MWGui MyGUI::Widget* getDefaultKeyFocus() override; - virtual bool exit() override { return false; } + bool exit() override { return false; } bool mMarkedToDelete; diff --git a/apps/openmw/mwgui/pickpocketitemmodel.hpp b/apps/openmw/mwgui/pickpocketitemmodel.hpp index 83caf2ffd..e28af73d7 100644 --- a/apps/openmw/mwgui/pickpocketitemmodel.hpp +++ b/apps/openmw/mwgui/pickpocketitemmodel.hpp @@ -12,14 +12,14 @@ namespace MWGui public: PickpocketItemModel (const MWWorld::Ptr& thief, ItemModel* sourceModel, bool hideItems=true); - virtual bool allowedToUseItems() const; - virtual ItemStack getItem (ModelIndex index); - virtual size_t getItemCount(); - virtual void update(); - virtual void removeItem (const ItemStack& item, size_t count); - virtual void onClose(); - virtual bool onDropItem(const MWWorld::Ptr &item, int count); - virtual bool onTakeItem(const MWWorld::Ptr &item, int count); + bool allowedToUseItems() const override; + ItemStack getItem (ModelIndex index) override; + size_t getItemCount() override; + void update() override; + void removeItem (const ItemStack& item, size_t count) override; + void onClose() override; + bool onDropItem(const MWWorld::Ptr &item, int count) override; + bool onTakeItem(const MWWorld::Ptr &item, int count) override; protected: MWWorld::Ptr mActor; diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index 8449e6a5b..214e52942 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -340,7 +340,8 @@ namespace MWGui || playerStats.getKnockedDown() || playerStats.getHitRecovery(); - bool isReturnNeeded = playerStats.isParalyzed() || playerStats.isDead(); + bool godmode = MWBase::Environment::get().getWorld()->getGodModeState(); + bool isReturnNeeded = (!godmode && playerStats.isParalyzed()) || playerStats.isDead(); if (isReturnNeeded && key->type != Type_Item) { diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 431e847cb..d0e950979 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -22,7 +22,7 @@ namespace MWGui QuickKeysMenu(); ~QuickKeysMenu(); - void onResChange(int, int) { center(); } + void onResChange(int, int) override { center(); } void onItemButtonClicked(MyGUI::Widget* sender); void onMagicButtonClicked(MyGUI::Widget* sender); @@ -34,7 +34,7 @@ namespace MWGui void onAssignMagicItem (MWWorld::Ptr item); void onAssignMagic (const std::string& spellId); void onAssignMagicCancel (); - void onOpen(); + void onOpen() override; void activateQuickKey(int index); void updateActivatedQuickKey(); @@ -51,7 +51,7 @@ namespace MWGui void write (ESM::ESMWriter& writer); void readRecord (ESM::ESMReader& reader, uint32_t type); - void clear(); + void clear() override; private: @@ -102,8 +102,8 @@ namespace MWGui public: MagicSelectionDialog(QuickKeysMenu* parent); - virtual void onOpen(); - virtual bool exit(); + void onOpen() override; + bool exit() override; private: MyGUI::Button* mCancelButton; diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index 0fa4fdec5..0299c2a1a 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -53,10 +53,10 @@ namespace MWGui void setGender(Gender gender) { mGenderIndex = gender == GM_Male ? 0 : 1; } void setNextButtonShow(bool shown); - virtual void onOpen(); - virtual void onClose(); + void onOpen() override; + void onClose() override; - bool exit() { return false; } + bool exit() override { return false; } // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/recharge.hpp b/apps/openmw/mwgui/recharge.hpp index f4602ce30..3d469bac5 100644 --- a/apps/openmw/mwgui/recharge.hpp +++ b/apps/openmw/mwgui/recharge.hpp @@ -22,9 +22,9 @@ class Recharge : public WindowBase public: Recharge(); - virtual void onOpen(); + void onOpen() override; - void setPtr (const MWWorld::Ptr& gem); + void setPtr (const MWWorld::Ptr& gem) override; protected: ItemChargeView* mBox; diff --git a/apps/openmw/mwgui/repair.hpp b/apps/openmw/mwgui/repair.hpp index f31625095..594ad2823 100644 --- a/apps/openmw/mwgui/repair.hpp +++ b/apps/openmw/mwgui/repair.hpp @@ -19,9 +19,9 @@ class Repair : public WindowBase public: Repair(); - virtual void onOpen(); + void onOpen() override; - void setPtr (const MWWorld::Ptr& item); + void setPtr (const MWWorld::Ptr& item) override; protected: ItemChargeView* mRepairBox; diff --git a/apps/openmw/mwgui/review.hpp b/apps/openmw/mwgui/review.hpp index f46ad280d..bd17c7afb 100644 --- a/apps/openmw/mwgui/review.hpp +++ b/apps/openmw/mwgui/review.hpp @@ -31,7 +31,7 @@ namespace MWGui ReviewDialog(); - bool exit() { return false; } + bool exit() override { return false; } void setPlayerName(const std::string &name); void setRace(const std::string &raceId); @@ -47,9 +47,9 @@ namespace MWGui void configureSkills(const SkillList& major, const SkillList& minor); void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value); - virtual void onOpen(); + void onOpen() override; - void onFrame(float duration); + void onFrame(float duration) override; // Events typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; diff --git a/apps/openmw/mwgui/savegamedialog.hpp b/apps/openmw/mwgui/savegamedialog.hpp index e2c41af70..c22d86fd1 100644 --- a/apps/openmw/mwgui/savegamedialog.hpp +++ b/apps/openmw/mwgui/savegamedialog.hpp @@ -19,8 +19,8 @@ namespace MWGui public: SaveGameDialog(); - virtual void onOpen(); - virtual void onClose(); + void onOpen() override; + void onClose() override; void setLoadOrSave(bool load); diff --git a/apps/openmw/mwgui/screenfader.hpp b/apps/openmw/mwgui/screenfader.hpp index aa17ed4e8..8eb8a6859 100644 --- a/apps/openmw/mwgui/screenfader.hpp +++ b/apps/openmw/mwgui/screenfader.hpp @@ -45,7 +45,7 @@ namespace MWGui void fadeOut(const float time, float delay=0); void fadeTo(const int percent, const float time, float delay=0); - void clear(); + void clear() override; void setFactor (float factor); void setRepeat(bool repeat); diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index 7f2a7a281..8a1e323ab 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -17,10 +17,10 @@ namespace MWGui public: ScrollWindow (); - void setPtr (const MWWorld::Ptr& scroll); + void setPtr (const MWWorld::Ptr& scroll) override; void setInventoryAllowed(bool allowed); - void onResChange(int, int) { center(); } + void onResChange(int, int) override { center(); } protected: void onCloseButtonClicked (MyGUI::Widget* _sender); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index aec3396a1..c5fa17ca4 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -10,10 +10,10 @@ #include #include +#include #include #include -#include #include #include #include @@ -60,7 +60,7 @@ namespace std::string getAspect (int x, int y) { - int gcd = Misc::gcd (x, y); + int gcd = std::gcd (x, y); int xaspect = x / gcd; int yaspect = y / gcd; // special case: 8 : 5 is usually referred to as 16:10 diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 37d671a5a..6f25dd114 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -15,11 +15,11 @@ namespace MWGui public: SettingsWindow(); - virtual void onOpen(); + void onOpen() override; void updateControlsBox(); - void onResChange(int, int) { center(); } + void onResChange(int, int) override { center(); } protected: MyGUI::TabControl* mSettingsTab; diff --git a/apps/openmw/mwgui/sortfilteritemmodel.hpp b/apps/openmw/mwgui/sortfilteritemmodel.hpp index 3e616875e..fa70a0edd 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.hpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.hpp @@ -11,13 +11,13 @@ namespace MWGui public: SortFilterItemModel (ItemModel* sourceModel); - virtual void update(); + void update() override; bool filterAccepts (const ItemStack& item); - bool allowedToUseItems() const; - virtual ItemStack getItem (ModelIndex index); - virtual size_t getItemCount(); + bool allowedToUseItems() const override; + ItemStack getItem (ModelIndex index) override; + size_t getItemCount() override; /// Dragged items are not displayed. void addDragItem (const MWWorld::Ptr& dragItem, size_t count); @@ -31,9 +31,9 @@ namespace MWGui /// Use ItemStack::Type for sorting? void setSortByType(bool sort) { mSortByType = sort; } - void onClose(); - bool onDropItem(const MWWorld::Ptr &item, int count); - bool onTakeItem(const MWWorld::Ptr &item, int count); + void onClose() override; + bool onDropItem(const MWWorld::Ptr &item, int count) override; + bool onTakeItem(const MWWorld::Ptr &item, int count) override; static const int Category_Weapon = (1<<1); static const int Category_Apparel = (1<<2); diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index eea98a768..eb51f560b 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -42,7 +42,7 @@ namespace MWGui const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - int price = static_cast(spell.mData.mCost*store.get().find("fSpellValueMult")->mValue.getFloat()); + int price = std::max(1, static_cast(spell.mData.mCost*store.get().find("fSpellValueMult")->mValue.getFloat())); price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true); MWWorld::Ptr player = MWMechanics::getPlayer(); diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index c68ec2483..622548c95 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -27,13 +27,13 @@ namespace MWGui public: SpellBuyingWindow(); - void setPtr(const MWWorld::Ptr& actor); + void setPtr(const MWWorld::Ptr& actor) override; void setPtr(const MWWorld::Ptr& actor, int startOffset); - void onFrame(float dt) { checkReferenceAvailable(); } - void clear() { resetReference(); } + void onFrame(float dt) override { checkReferenceAvailable(); } + void clear() override { resetReference(); } - void onResChange(int, int) { center(); } + void onResChange(int, int) override { center(); } protected: MyGUI::Button* mCancelButton; @@ -52,7 +52,7 @@ namespace MWGui void updateLabels(); - virtual void onReferenceUnavailable(); + void onReferenceUnavailable() override; bool playerHasSpell (const std::string& id); diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index a567d114b..1f086507f 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -475,7 +475,8 @@ namespace MWGui float fSpellMakingValueMult = store.get().find("fSpellMakingValueMult")->mValue.getFloat(); - int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, static_cast(y * fSpellMakingValueMult),true); + int price = std::max(1, static_cast(y * fSpellMakingValueMult)); + price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true); mPriceLabel->setCaption(MyGUI::utility::toString(int(price))); @@ -738,5 +739,24 @@ namespace MWGui { mAddEffectDialog.setConstantEffect(constant); mConstantEffect = constant; + + if (!constant) + return; + + for (auto it = mEffects.begin(); it != mEffects.end();) + { + if (it->mRange != ESM::RT_Self) + { + auto& store = MWBase::Environment::get().getWorld()->getStore(); + auto magicEffect = store.get().find(it->mEffectID); + if ((magicEffect->mData.mFlags & ESM::MagicEffect::CastSelf) == 0) + { + it = mEffects.erase(it); + continue; + } + it->mRange = ESM::RT_Self; + } + ++it; + } } } diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index ec90fa3ce..73352ac23 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -23,8 +23,8 @@ namespace MWGui public: EditEffectDialog(); - virtual void onOpen(); - virtual bool exit(); + void onOpen() override; + bool exit() override; void setConstantEffect(bool constant); @@ -150,21 +150,21 @@ namespace MWGui public: SpellCreationDialog(); - virtual void onOpen(); - void clear() { resetReference(); } + void onOpen() override; + void clear() override { resetReference(); } - void onFrame(float dt) { checkReferenceAvailable(); } + void onFrame(float dt) override { checkReferenceAvailable(); } - void setPtr(const MWWorld::Ptr& actor); + void setPtr(const MWWorld::Ptr& actor) override; protected: - virtual void onReferenceUnavailable (); + void onReferenceUnavailable() override; void onCancelButtonClicked (MyGUI::Widget* sender); void onBuyButtonClicked (MyGUI::Widget* sender); void onAccept(MyGUI::EditBox* sender); - virtual void notifyEffectsChanged (); + void notifyEffectsChanged() override; MyGUI::EditBox* mNameEdit; MyGUI::TextBox* mMagickaCost; diff --git a/apps/openmw/mwgui/spellicons.cpp b/apps/openmw/mwgui/spellicons.cpp index 7750244ca..f5235c8a4 100644 --- a/apps/openmw/mwgui/spellicons.cpp +++ b/apps/openmw/mwgui/spellicons.cpp @@ -25,8 +25,8 @@ namespace MWGui { - void EffectSourceVisitor::visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + void EffectSourceVisitor::visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime, float totalTime) { MagicEffectInfo newEffectSource; diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 26761f2fc..b6aa49e69 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -46,9 +46,9 @@ namespace MWGui virtual ~EffectSourceVisitor() {} - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, - float magnitude, float remainingTime = -1, float totalTime = -1); + void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, + float magnitude, float remainingTime = -1, float totalTime = -1) override; }; class SpellIcons diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index b006b5a66..dcd94b768 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -245,8 +245,9 @@ namespace MWGui if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(player)) return; + bool godmode = MWBase::Environment::get().getWorld()->getGodModeState(); const MWMechanics::CreatureStats &stats = player.getClass().getCreatureStats(player); - if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery()) + if ((!godmode && stats.isParalyzed()) || stats.getKnockedDown() || stats.isDead() || stats.getHitRecovery()) return; mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), "")); diff --git a/apps/openmw/mwgui/spellwindow.hpp b/apps/openmw/mwgui/spellwindow.hpp index 01a9c7392..cf5e88f8e 100644 --- a/apps/openmw/mwgui/spellwindow.hpp +++ b/apps/openmw/mwgui/spellwindow.hpp @@ -19,7 +19,7 @@ namespace MWGui void updateSpells(); - void onFrame(float dt); + void onFrame(float dt) override; /// Cycle to next/previous spell void cycle(bool next); @@ -37,9 +37,9 @@ namespace MWGui void onDeleteSpellAccept(); void askDeleteSpell(const std::string& spellId); - virtual void onPinToggled(); - virtual void onTitleDoubleClicked(); - virtual void onOpen(); + void onPinToggled() override; + void onTitleDoubleClicked() override; + void onOpen() override; SpellView* mSpellView; SpellIcons* mSpellIcons; diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index 5e4404971..7098a2c2b 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -35,7 +35,7 @@ namespace MWGui void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; } void updateSkillArea(); - virtual void onOpen() override { onWindowResize(mMainWidget->castType()); } + void onOpen() override { onWindowResize(mMainWidget->castType()); } private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); @@ -70,8 +70,8 @@ namespace MWGui const int mMinFullWidth; protected: - virtual void onPinToggled() override; - virtual void onTitleDoubleClicked() override; + void onPinToggled() override; + void onTitleDoubleClicked() override; }; } #endif diff --git a/apps/openmw/mwgui/textinput.hpp b/apps/openmw/mwgui/textinput.hpp index 56c6632e1..84d9d032d 100644 --- a/apps/openmw/mwgui/textinput.hpp +++ b/apps/openmw/mwgui/textinput.hpp @@ -20,9 +20,9 @@ namespace MWGui void setNextButtonShow(bool shown); void setTextLabel(const std::string &label); - virtual void onOpen(); + void onOpen() override; - bool exit() { return false; } + bool exit() override { return false; } /** Event : Dialog finished, OK button clicked.\n signature : void method()\n diff --git a/apps/openmw/mwgui/tradeitemmodel.cpp b/apps/openmw/mwgui/tradeitemmodel.cpp index b1bab32dc..f5144ba81 100644 --- a/apps/openmw/mwgui/tradeitemmodel.cpp +++ b/apps/openmw/mwgui/tradeitemmodel.cpp @@ -119,7 +119,7 @@ namespace MWGui mBorrowedToUs.clear(); } - std::vector TradeItemModel::getItemsBorrowedToUs() + const std::vector TradeItemModel::getItemsBorrowedToUs() const { return mBorrowedToUs; } diff --git a/apps/openmw/mwgui/tradeitemmodel.hpp b/apps/openmw/mwgui/tradeitemmodel.hpp index cdb949c49..53b616aed 100644 --- a/apps/openmw/mwgui/tradeitemmodel.hpp +++ b/apps/openmw/mwgui/tradeitemmodel.hpp @@ -15,12 +15,12 @@ namespace MWGui public: TradeItemModel (ItemModel* sourceModel, const MWWorld::Ptr& merchant); - bool allowedToUseItems() const; + bool allowedToUseItems() const override; - virtual ItemStack getItem (ModelIndex index); - virtual size_t getItemCount(); + ItemStack getItem (ModelIndex index) override; + size_t getItemCount() override; - virtual void update(); + void update() override; void borrowItemFromUs (ModelIndex itemIndex, size_t count); @@ -40,7 +40,7 @@ namespace MWGui /// and removing weight for items we've lent to someone else. void adjustEncumbrance (float& encumbrance); - std::vector getItemsBorrowedToUs(); + const std::vector getItemsBorrowedToUs() const; private: void borrowImpl(const ItemStack& item, std::vector& out); diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 3944b757b..f585d9019 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -103,20 +103,6 @@ namespace MWGui setCoord(400, 0, 400, 300); } - void TradeWindow::restock() - { - // Restock items on the actor inventory - mPtr.getClass().restock(mPtr); - - // Also restock any containers owned by this merchant, which are also available to buy in the trade window - std::vector itemSources; - MWBase::Environment::get().getWorld()->getContainersOwnedBy(mPtr, itemSources); - for (MWWorld::Ptr& source : itemSources) - { - source.getClass().restock(source); - } - } - void TradeWindow::setPtr(const MWWorld::Ptr& actor) { mPtr = actor; @@ -125,10 +111,10 @@ namespace MWGui mCurrentMerchantOffer = 0; std::vector itemSources; + // Important: actor goes first, so purchased items come out of the actor's pocket first + itemSources.push_back(actor); MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources); - // Important: actor goes last, so that items purchased by the merchant go into his inventory - itemSources.push_back(actor); std::vector worldItems; MWBase::Environment::get().getWorld()->getItemsOwnedBy(actor, worldItems); @@ -285,8 +271,8 @@ namespace MWGui MWBase::Environment::get().getWorld()->getStore().get(); // were there any items traded at all? - std::vector playerBought = playerItemModel->getItemsBorrowedToUs(); - std::vector merchantBought = mTradeModel->getItemsBorrowedToUs(); + const std::vector& playerBought = playerItemModel->getItemsBorrowedToUs(); + const std::vector& merchantBought = mTradeModel->getItemsBorrowedToUs(); if (playerBought.empty() && merchantBought.empty()) { // user notification @@ -317,7 +303,7 @@ namespace MWGui } // check if the player is attempting to sell back an item stolen from this actor - for (ItemStack& itemStack : merchantBought) + for (const ItemStack& itemStack : merchantBought) { if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(itemStack.mBase.getCellRef().getRefId(), mPtr)) { @@ -367,8 +353,6 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->playSound("Item Gold Up"); MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter); - - restock(); } void TradeWindow::onAccept(MyGUI::EditBox *sender) @@ -482,7 +466,7 @@ namespace MWGui // connected to buying and selling the same item. // This value has been determined by researching the limitations of the vanilla formula // and may not be sufficient if getBarterOffer behavior has been changed. - std::vector playerBorrowed = playerTradeModel->getItemsBorrowedToUs(); + const std::vector& playerBorrowed = playerTradeModel->getItemsBorrowedToUs(); for (const ItemStack& itemStack : playerBorrowed) { const int basePrice = getEffectiveValue(itemStack.mBase, itemStack.mCount); @@ -491,7 +475,7 @@ namespace MWGui merchantOffer -= std::max(cap, buyingPrice); } - std::vector merchantBorrowed = mTradeModel->getItemsBorrowedToUs(); + const std::vector& merchantBorrowed = mTradeModel->getItemsBorrowedToUs(); for (const ItemStack& itemStack : merchantBorrowed) { const int basePrice = getEffectiveValue(itemStack.mBase, itemStack.mCount); @@ -536,4 +520,9 @@ namespace MWGui mTradeModel = nullptr; mSortModel = nullptr; } + + void TradeWindow::onClose() + { + resetReference(); + } } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 0730df04f..f82d7b0f7 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -27,19 +27,20 @@ namespace MWGui public: TradeWindow(); - void setPtr(const MWWorld::Ptr& actor); + void setPtr(const MWWorld::Ptr& actor) override; - void onFrame(float dt); - void clear() { resetReference(); } + void onClose() override; + void onFrame(float dt) override; + void clear() override { resetReference(); } void borrowItem (int index, size_t count); void returnItem (int index, size_t count); int getMerchantServices(); - virtual bool exit(); + bool exit() override; - virtual void resetReference(); + void resetReference() override; typedef MyGUI::delegates::CMultiDelegate0 EventHandle_TradeDone; EventHandle_TradeDone eventTradeDone; @@ -108,11 +109,9 @@ namespace MWGui void updateLabels(); - virtual void onReferenceUnavailable(); + void onReferenceUnavailable() override; int getMerchantGold(); - - void restock(); }; } diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index d0176ece4..da3c7d186 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -99,8 +99,9 @@ namespace MWGui for (int i=0; i<3; ++i) { - int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer - (mPtr,pcStats.getSkill (skills[i].first).getBase() * gmst.find("iTrainingMod")->mValue.getInteger(),true); + int price = static_cast(pcStats.getSkill (skills[i].first).getBase() * gmst.find("iTrainingMod")->mValue.getInteger()); + price = std::max(1, price); + price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true); MyGUI::Button* button = mTrainingOptions->createWidget(price <= playerGold ? "SandTextButton" : "SandTextButtonDisabled", // can't use setEnabled since that removes tooltip MyGUI::IntCoord(5, 5+i*18, mTrainingOptions->getWidth()-10, 18), MyGUI::Align::Default); diff --git a/apps/openmw/mwgui/trainingwindow.hpp b/apps/openmw/mwgui/trainingwindow.hpp index 955615516..57fdd323a 100644 --- a/apps/openmw/mwgui/trainingwindow.hpp +++ b/apps/openmw/mwgui/trainingwindow.hpp @@ -19,20 +19,20 @@ namespace MWGui public: TrainingWindow(); - virtual void onOpen(); + void onOpen() override; - bool exit(); + bool exit() override; - void setPtr(const MWWorld::Ptr& actor); + void setPtr(const MWWorld::Ptr& actor) override; - void onFrame(float dt); + void onFrame(float dt) override; WindowBase* getProgressBar() { return &mProgressBar; } - void clear() { resetReference(); } + void clear() override { resetReference(); } protected: - virtual void onReferenceUnavailable (); + void onReferenceUnavailable() override; void onCancelButtonClicked (MyGUI::Widget* sender); void onTrainingSelected(MyGUI::Widget* sender); diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index 81cd76089..ed7a74b95 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -62,14 +62,19 @@ namespace MWGui { ESM::Position PlayerPos = player.getRefData().getPosition(); float d = sqrt(pow(pos.pos[0] - PlayerPos.pos[0], 2) + pow(pos.pos[1] - PlayerPos.pos[1], 2) + pow(pos.pos[2] - PlayerPos.pos[2], 2)); - price = static_cast(d / gmst.find("fTravelMult")->mValue.getFloat()); + float fTravelMult = gmst.find("fTravelMult")->mValue.getFloat(); + if (fTravelMult != 0) + price = static_cast(d / fTravelMult); + else + price = static_cast(d); } + price = std::max(1, price); price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true); // Add price for the travelling followers std::set followers; - MWWorld::ActionTeleport::getFollowersToTeleport(player, followers); + MWWorld::ActionTeleport::getFollowers(player, followers); // Apply followers cost, unlike vanilla the first follower doesn't travel for free price *= 1 + static_cast(followers.size()); diff --git a/apps/openmw/mwgui/travelwindow.hpp b/apps/openmw/mwgui/travelwindow.hpp index dcf0b7727..962d17161 100644 --- a/apps/openmw/mwgui/travelwindow.hpp +++ b/apps/openmw/mwgui/travelwindow.hpp @@ -24,7 +24,7 @@ namespace MWGui public: TravelWindow(); - void setPtr (const MWWorld::Ptr& actor); + void setPtr (const MWWorld::Ptr& actor) override; protected: MyGUI::Button* mCancelButton; @@ -43,7 +43,7 @@ namespace MWGui void updateLabels(); - virtual void onReferenceUnavailable(); + void onReferenceUnavailable() override; }; } diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp index 2aecb002f..bf84e7e81 100644 --- a/apps/openmw/mwgui/waitdialog.hpp +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -13,7 +13,7 @@ namespace MWGui public: WaitDialogProgressBar(); - virtual void onOpen(); + void onOpen() override; void setProgress(int cur, int total); @@ -27,15 +27,15 @@ namespace MWGui public: WaitDialog(); - void setPtr(const MWWorld::Ptr &ptr); + void setPtr(const MWWorld::Ptr &ptr) override; - virtual void onOpen(); + void onOpen() override; - virtual bool exit(); + bool exit() override; - virtual void clear(); + void clear() override; - void onFrame(float dt); + void onFrame(float dt) override; bool getSleeping() { return mTimeAdvancer.isRunning() && mSleeping; } void wakeUp(); diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp index 4bad3172b..11225fbfb 100644 --- a/apps/openmw/mwgui/windowbase.hpp +++ b/apps/openmw/mwgui/windowbase.hpp @@ -41,7 +41,7 @@ namespace MWGui /// Gracefully exits the window virtual bool exit() {return true;} /// Sets the visibility of the window - virtual void setVisible(bool visible); + void setVisible(bool visible) override; /// Returns the visibility state of the window bool isVisible(); @@ -70,9 +70,9 @@ namespace MWGui { public: WindowModal(const std::string& parLayout); - virtual void onOpen() override; - virtual void onClose() override; - virtual bool exit() override {return true;} + void onOpen() override; + void onClose() override; + bool exit() override {return true;} }; /// A window that cannot be the target of a drag&drop action. diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 3954e911b..270956b3c 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -141,138 +141,136 @@ namespace MWGui void setStore (const MWWorld::ESMStore& store); void initUI(); - virtual void loadUserFonts(); + void loadUserFonts() override; - virtual Loading::Listener* getLoadingScreen(); + Loading::Listener* getLoadingScreen() override; /// @note This method will block until the video finishes playing /// (and will continually update the window while doing so) - virtual void playVideo(const std::string& name, bool allowSkipping); + void playVideo(const std::string& name, bool allowSkipping) override; /// Warning: do not use MyGUI::InputManager::setKeyFocusWidget directly. Instead use this. - virtual void setKeyFocusWidget (MyGUI::Widget* widget); + void setKeyFocusWidget (MyGUI::Widget* widget) override; - virtual void setNewGame(bool newgame); + void setNewGame(bool newgame) override; - virtual void pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg); - virtual void pushGuiMode (GuiMode mode); - virtual void popGuiMode(bool noSound=false); - virtual void removeGuiMode(GuiMode mode, bool noSound=false); ///< can be anywhere in the stack + void pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg) override; + void pushGuiMode (GuiMode mode) override; + void popGuiMode(bool noSound=false) override; + void removeGuiMode(GuiMode mode, bool noSound=false) override; ///< can be anywhere in the stack - virtual void goToJail(int days); + void goToJail(int days) override; - virtual GuiMode getMode() const; - virtual bool containsMode(GuiMode mode) const; + GuiMode getMode() const override; + bool containsMode(GuiMode mode) const override; - virtual bool isGuiMode() const; + bool isGuiMode() const override; - virtual bool isConsoleMode() const; + bool isConsoleMode() const override; - virtual void toggleVisible(GuiWindow wnd); - - virtual DragAndDrop& getDragAndDrop(void) override; - - virtual void forceHide(MWGui::GuiWindow wnd); - virtual void unsetForceHide(MWGui::GuiWindow wnd); + void toggleVisible(GuiWindow wnd) override; + void forceHide(MWGui::GuiWindow wnd) override; + void unsetForceHide(MWGui::GuiWindow wnd) override; + DragAndDrop& getDragAndDrop(void) override; /// Disallow all inventory mode windows - virtual void disallowAll(); + void disallowAll() override; /// Allow one or more windows - virtual void allow(GuiWindow wnd); + void allow(GuiWindow wnd) override; - virtual bool isAllowed(GuiWindow wnd) const; + bool isAllowed(GuiWindow wnd) const override; /// \todo investigate, if we really need to expose every single lousy UI element to the outside world - virtual MWGui::InventoryWindow* getInventoryWindow(); - virtual MWGui::CountDialog* getCountDialog(); - virtual MWGui::ConfirmationDialog* getConfirmationDialog(); - virtual MWGui::TradeWindow* getTradeWindow(); + MWGui::InventoryWindow* getInventoryWindow() override; + MWGui::CountDialog* getCountDialog() override; + MWGui::ConfirmationDialog* getConfirmationDialog() override; + MWGui::TradeWindow* getTradeWindow() override; /// Make the player use an item, while updating GUI state accordingly - virtual void useItem(const MWWorld::Ptr& item, bool bypassBeastRestrictions=false); + void useItem(const MWWorld::Ptr& item, bool bypassBeastRestrictions=false) override; - virtual void updateSpellWindow(); + void updateSpellWindow() override; - virtual void setConsoleSelectedObject(const MWWorld::Ptr& object); + void setConsoleSelectedObject(const MWWorld::Ptr& object) override; /// Set time left for the player to start drowning (update the drowning bar) /// @param time time left to start drowning /// @param maxTime how long we can be underwater (in total) until drowning starts - virtual void setDrowningTimeLeft (float time, float maxTime); + void setDrowningTimeLeft (float time, float maxTime) override; - virtual void changeCell(const MWWorld::CellStore* cell); ///< change the active cell + void changeCell(const MWWorld::CellStore* cell) override; ///< change the active cell - virtual void setFocusObject(const MWWorld::Ptr& focus); - virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); + void setFocusObject(const MWWorld::Ptr& focus) override; + void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) override; - virtual void getMousePosition(int &x, int &y); - virtual void getMousePosition(float &x, float &y); - virtual void setDragDrop(bool dragDrop); - virtual bool getWorldMouseOver(); + void getMousePosition(int &x, int &y) override; + void getMousePosition(float &x, float &y) override; + void setDragDrop(bool dragDrop) override; + bool getWorldMouseOver() override; - virtual bool toggleFogOfWar(); - virtual bool toggleFullHelp(); ///< show extra info in item tooltips (owner, script) - virtual bool getFullHelp() const; + bool toggleFogOfWar() override; + bool toggleFullHelp() override; ///< show extra info in item tooltips (owner, script) + bool getFullHelp() const override; - virtual void setActiveMap(int x, int y, bool interior); + void setActiveMap(int x, int y, bool interior) override; ///< set the indices of the map texture that should be used /// sets the visibility of the drowning bar - virtual void setDrowningBarVisibility(bool visible); + void setDrowningBarVisibility(bool visible) override; // sets the visibility of the hud health/magicka/stamina bars - virtual void setHMSVisibility(bool visible); + void setHMSVisibility(bool visible) override; // sets the visibility of the hud minimap - virtual void setMinimapVisibility(bool visible); - virtual void setWeaponVisibility(bool visible); - virtual void setSpellVisibility(bool visible); - virtual void setSneakVisibility(bool visible); + void setMinimapVisibility(bool visible) override; + void setWeaponVisibility(bool visible) override; + void setSpellVisibility(bool visible) override; + void setSneakVisibility(bool visible) override; /// activate selected quick key - virtual void activateQuickKey (int index); + void activateQuickKey (int index) override; /// update activated quick key state (if action executing was delayed for some reason) - virtual void updateActivatedQuickKey (); + void updateActivatedQuickKey () override; - virtual std::string getSelectedSpell() { return mSelectedSpell; } - virtual void setSelectedSpell(const std::string& spellId, int successChancePercent); - virtual void setSelectedEnchantItem(const MWWorld::Ptr& item); - virtual const MWWorld::Ptr& getSelectedEnchantItem() const; - virtual void setSelectedWeapon(const MWWorld::Ptr& item); - virtual const MWWorld::Ptr& getSelectedWeapon() const; - virtual int getFontHeight() const; - virtual void unsetSelectedSpell(); - virtual void unsetSelectedWeapon(); + std::string getSelectedSpell() override { return mSelectedSpell; } + void setSelectedSpell(const std::string& spellId, int successChancePercent) override; + void setSelectedEnchantItem(const MWWorld::Ptr& item) override; + const MWWorld::Ptr& getSelectedEnchantItem() const override; + void setSelectedWeapon(const MWWorld::Ptr& item) override; + const MWWorld::Ptr& getSelectedWeapon() const override; + int getFontHeight() const override; + void unsetSelectedSpell() override; + void unsetSelectedWeapon() override; - virtual void updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr); + void updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) override; - virtual void showCrosshair(bool show); - virtual bool getSubtitlesEnabled(); + void showCrosshair(bool show) override; + bool getSubtitlesEnabled() override; /// Turn visibility of HUD on or off - virtual bool toggleHud(); + bool toggleHud() override; - virtual void disallowMouse(); - virtual void allowMouse(); - virtual void notifyInputActionBound(); + void disallowMouse() override; + void allowMouse() override; + void notifyInputActionBound() override; - virtual void addVisitedLocation(const std::string& name, int x, int y); + void addVisitedLocation(const std::string& name, int x, int y) override; ///Hides dialog and schedules dialog to be deleted. - virtual void removeDialog(Layout* dialog); + void removeDialog(Layout* dialog) override; ///Gracefully attempts to exit the topmost GUI mode - virtual void exitCurrentGuiMode(); + void exitCurrentGuiMode() override; - virtual void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible); - virtual void staticMessageBox(const std::string& message); - virtual void removeStaticMessageBox(); - virtual void interactiveMessageBox (const std::string& message, - const std::vector& buttons = std::vector(), bool block=false); + void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) override; + void staticMessageBox(const std::string& message) override; + void removeStaticMessageBox() override; + void interactiveMessageBox (const std::string& message, + const std::vector& buttons = std::vector(), bool block=false) override; - virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) + int readPressedButton () override; ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) - virtual void update (float duration); + void update (float duration) override; /** * Fetches a GMST string from the store, if there is no setting with the given @@ -281,108 +279,108 @@ namespace MWGui * @param id Identifier for the GMST setting, e.g. "aName" * @param default Default value if the GMST setting cannot be used. */ - virtual std::string getGameSettingString(const std::string &id, const std::string &default_); + std::string getGameSettingString(const std::string &id, const std::string &default_) override; - virtual void processChangedSettings(const Settings::CategorySettingVector& changed); + void processChangedSettings(const Settings::CategorySettingVector& changed) override; - virtual void windowVisibilityChange(bool visible); - virtual void windowResized(int x, int y); - virtual void windowClosed(); - virtual bool isWindowVisible(); + void windowVisibilityChange(bool visible) override; + void windowResized(int x, int y) override; + void windowClosed() override; + bool isWindowVisible() override; - virtual void watchActor(const MWWorld::Ptr& ptr); - virtual MWWorld::Ptr getWatchedActor() const; + void watchActor(const MWWorld::Ptr& ptr) override; + MWWorld::Ptr getWatchedActor() const override; - virtual void executeInConsole (const std::string& path); + void executeInConsole (const std::string& path) override; - virtual void enableRest() { mRestAllowed = true; } - virtual bool getRestEnabled(); + void enableRest() override { mRestAllowed = true; } + bool getRestEnabled() override; - virtual bool getJournalAllowed() { return (mAllowed & GW_Magic) != 0; } + bool getJournalAllowed() override { return (mAllowed & GW_Magic) != 0; } - virtual bool getPlayerSleeping(); - virtual void wakeUpPlayer(); + bool getPlayerSleeping() override; + void wakeUpPlayer() override; - virtual void updatePlayer(); + void updatePlayer() override; - virtual void showSoulgemDialog (MWWorld::Ptr item); + void showSoulgemDialog (MWWorld::Ptr item) override; - virtual void changePointer (const std::string& name); + void changePointer (const std::string& name) override; - virtual void setEnemy (const MWWorld::Ptr& enemy); + void setEnemy (const MWWorld::Ptr& enemy) override; - virtual int getMessagesCount() const; + int getMessagesCount() const override; - virtual const Translation::Storage& getTranslationDataStorage() const; + const Translation::Storage& getTranslationDataStorage() const override; void onSoulgemDialogButtonPressed (int button); - virtual bool getCursorVisible(); + bool getCursorVisible() override; /// Call when mouse cursor or buttons are used. - virtual void setCursorActive(bool active); + void setCursorActive(bool active) override; /// Clear all savegame-specific data - virtual void clear(); + void clear() override; - virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress); - virtual void readRecord (ESM::ESMReader& reader, uint32_t type); - virtual int countSavedGameRecords() const; + void write (ESM::ESMWriter& writer, Loading::Listener& progress) override; + void readRecord (ESM::ESMReader& reader, uint32_t type) override; + int countSavedGameRecords() const override; /// Does the current stack of GUI-windows permit saving? - virtual bool isSavingAllowed() const; + bool isSavingAllowed() const override; /// Send exit command to active Modal window **/ - virtual void exitCurrentModal(); + void exitCurrentModal() override; /// Sets the current Modal /** Used to send exit command to active Modal when Esc is pressed **/ - virtual void addCurrentModal(WindowModal* input); + void addCurrentModal(WindowModal* input) override; /// Removes the top Modal /** Used when one Modal adds another Modal \param input Pointer to the current modal, to ensure proper modal is removed **/ - virtual void removeCurrentModal(WindowModal* input); + void removeCurrentModal(WindowModal* input) override; - virtual void pinWindow (MWGui::GuiWindow window); - virtual void toggleMaximized(Layout *layout); + void pinWindow (MWGui::GuiWindow window) override; + void toggleMaximized(Layout *layout) override; /// Fade the screen in, over \a time seconds - virtual void fadeScreenIn(const float time, bool clearQueue, float delay); + void fadeScreenIn(const float time, bool clearQueue, float delay) override; /// Fade the screen out to black, over \a time seconds - virtual void fadeScreenOut(const float time, bool clearQueue, float delay); + void fadeScreenOut(const float time, bool clearQueue, float delay) override; /// Fade the screen to a specified percentage of black, over \a time seconds - virtual void fadeScreenTo(const int percent, const float time, bool clearQueue, float delay); + void fadeScreenTo(const int percent, const float time, bool clearQueue, float delay) override; /// Darken the screen to a specified percentage - virtual void setBlindness(const int percent); + void setBlindness(const int percent) override; - virtual void activateHitOverlay(bool interrupt); - virtual void setWerewolfOverlay(bool set); + void activateHitOverlay(bool interrupt) override; + void setWerewolfOverlay(bool set) override; - virtual void toggleConsole(); - virtual void toggleDebugWindow(); + void toggleConsole() override; + void toggleDebugWindow() override; /// Cycle to next or previous spell - virtual void cycleSpell(bool next); + void cycleSpell(bool next) override; /// Cycle to next or previous weapon - virtual void cycleWeapon(bool next); + void cycleWeapon(bool next) override; - virtual void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f); + void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f) override; // In WindowManager for now since there isn't a VFS singleton - virtual std::string correctIconPath(const std::string& path); - virtual std::string correctBookartPath(const std::string& path, int width, int height, bool* exists = nullptr); - virtual std::string correctTexturePath(const std::string& path); - virtual bool textureExists(const std::string& path); + std::string correctIconPath(const std::string& path) override; + std::string correctBookartPath(const std::string& path, int width, int height, bool* exists = nullptr) override; + std::string correctTexturePath(const std::string& path) override; + bool textureExists(const std::string& path) override; - void addCell(MWWorld::CellStore* cell); - void removeCell(MWWorld::CellStore* cell); - void writeFog(MWWorld::CellStore* cell); + void addCell(MWWorld::CellStore* cell) override; + void removeCell(MWWorld::CellStore* cell) override; + void writeFog(MWWorld::CellStore* cell) override; - virtual const MWGui::TextColours& getTextColours(); + const MWGui::TextColours& getTextColours() override; - virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat=false); - virtual bool injectKeyRelease(MyGUI::KeyCode key); + bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat=false) override; + bool injectKeyRelease(MyGUI::KeyCode key) override; private: unsigned int mOldUpdateMask; unsigned int mOldCullMask; @@ -462,7 +460,7 @@ namespace MWGui int mPlayerBounty; - void setCursorVisible(bool visible); + void setCursorVisible(bool visible) override; MyGUI::Gui *mGui; // Gui diff --git a/apps/openmw/mwinput/actionmanager.cpp b/apps/openmw/mwinput/actionmanager.cpp index ec6c5cf7f..b29aa58a2 100644 --- a/apps/openmw/mwinput/actionmanager.cpp +++ b/apps/openmw/mwinput/actionmanager.cpp @@ -26,7 +26,7 @@ namespace MWInput { - const float ZOOM_SCALE = 120.f; /// Used for scrolling camera in and out + const float ZOOM_SCALE = 10.f; /// Used for scrolling camera in and out ActionManager::ActionManager(BindingsManager* bindingsManager, osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation, @@ -141,7 +141,7 @@ namespace MWInput float xAxis = mBindingsManager->getActionValue(A_MoveLeftRight); float yAxis = mBindingsManager->getActionValue(A_MoveForwardBackward); - bool isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25; + bool isRunning = osg::Vec2f(xAxis * 2 - 1, yAxis * 2 - 1).length2() > 0.25f; if ((mAlwaysRunActive && alwaysRunAllowed) || isRunning) player.setRunState(!mBindingsManager->actionIsActive(A_Run)); else @@ -167,6 +167,11 @@ namespace MWInput mAttemptJump = false; } + + bool ActionManager::isPreviewModeEnabled() + { + return MWBase::Environment::get().getWorld()->isPreviewModeEnabled(); + } void ActionManager::resetIdleTime() { @@ -190,6 +195,8 @@ namespace MWInput void ActionManager::executeAction(int action) { + auto* inputManager = MWBase::Environment::get().getInputManager(); + auto* windowManager = MWBase::Environment::get().getWindowManager(); // trigger action activated switch (action) { @@ -206,7 +213,7 @@ namespace MWInput toggleConsole (); break; case A_Activate: - MWBase::Environment::get().getInputManager()->resetIdleTime(); + inputManager->resetIdleTime(); activate(); break; case A_MoveLeft: @@ -267,18 +274,18 @@ namespace MWInput showQuickKeysMenu(); break; case A_ToggleHUD: - MWBase::Environment::get().getWindowManager()->toggleHud(); + windowManager->toggleHud(); break; case A_ToggleDebug: - MWBase::Environment::get().getWindowManager()->toggleDebugWindow(); + windowManager->toggleDebugWindow(); break; case A_ZoomIn: - if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch") && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols") && !MWBase::Environment::get().getWindowManager()->isGuiMode()) - MWBase::Environment::get().getWorld()->setCameraDistance(ZOOM_SCALE, true, true); + if (inputManager->getControlSwitch("playerviewswitch") && inputManager->getControlSwitch("playercontrols") && !windowManager->isGuiMode()) + MWBase::Environment::get().getWorld()->adjustCameraDistance(-ZOOM_SCALE); break; case A_ZoomOut: - if (MWBase::Environment::get().getInputManager()->getControlSwitch("playerviewswitch") && MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols") && !MWBase::Environment::get().getWindowManager()->isGuiMode()) - MWBase::Environment::get().getWorld()->setCameraDistance(-ZOOM_SCALE, true, true); + if (inputManager->getControlSwitch("playerviewswitch") && inputManager->getControlSwitch("playercontrols") && !windowManager->isGuiMode()) + MWBase::Environment::get().getWorld()->adjustCameraDistance(ZOOM_SCALE); break; case A_QuickSave: quickSave(); @@ -287,19 +294,19 @@ namespace MWInput quickLoad(); break; case A_CycleSpellLeft: - if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic)) + if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Magic)) MWBase::Environment::get().getWindowManager()->cycleSpell(false); break; case A_CycleSpellRight: - if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic)) + if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Magic)) MWBase::Environment::get().getWindowManager()->cycleSpell(true); break; case A_CycleWeaponLeft: - if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Inventory)) MWBase::Environment::get().getWindowManager()->cycleWeapon(false); break; case A_CycleWeaponRight: - if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) + if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Inventory)) MWBase::Environment::get().getWindowManager()->cycleWeapon(true); break; case A_Sneak: diff --git a/apps/openmw/mwinput/actionmanager.hpp b/apps/openmw/mwinput/actionmanager.hpp index 7aa73f520..eceac2e94 100644 --- a/apps/openmw/mwinput/actionmanager.hpp +++ b/apps/openmw/mwinput/actionmanager.hpp @@ -54,7 +54,7 @@ namespace MWInput void setAttemptJump(bool enabled) { mAttemptJump = enabled; } - float getPreviewDelay() const { return mPreviewPOVDelay; }; + bool isPreviewModeEnabled(); private: void handleGuiArrowKey(int action); diff --git a/apps/openmw/mwinput/bindingsmanager.cpp b/apps/openmw/mwinput/bindingsmanager.cpp index e0142d420..13a7f8b8b 100644 --- a/apps/openmw/mwinput/bindingsmanager.cpp +++ b/apps/openmw/mwinput/bindingsmanager.cpp @@ -70,14 +70,14 @@ namespace MWInput virtual ~BindingsListener() = default; - virtual void channelChanged(ICS::Channel* channel, float currentValue, float previousValue) + void channelChanged(ICS::Channel* channel, float currentValue, float previousValue) override { int action = channel->getNumber(); mBindingsManager->actionValueChanged(action, currentValue, previousValue); } - virtual void keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , SDL_Scancode key, ICS::Control::ControlChangingDirection direction) + void keyBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , SDL_Scancode key, ICS::Control::ControlChangingDirection direction) override { //Disallow binding escape key if (key==SDL_SCANCODE_ESCAPE) @@ -107,15 +107,15 @@ namespace MWInput MWBase::Environment::get().getWindowManager()->notifyInputActionBound(); } - virtual void mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction) + void mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::NamedAxis axis, ICS::Control::ControlChangingDirection direction) override { // we don't want mouse movement bindings return; } - virtual void mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , unsigned int button, ICS::Control::ControlChangingDirection direction) + void mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , unsigned int button, ICS::Control::ControlChangingDirection direction) override { if (!mDetectingKeyboard) return; @@ -125,8 +125,8 @@ namespace MWInput MWBase::Environment::get().getWindowManager()->notifyInputActionBound(); } - virtual void mouseWheelBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control - , ICS::InputControlSystem::MouseWheelClick click, ICS::Control::ControlChangingDirection direction) + void mouseWheelBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control + , ICS::InputControlSystem::MouseWheelClick click, ICS::Control::ControlChangingDirection direction) override { if (!mDetectingKeyboard) return; @@ -136,8 +136,8 @@ namespace MWInput MWBase::Environment::get().getWindowManager()->notifyInputActionBound(); } - virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control - , int axis, ICS::Control::ControlChangingDirection direction) + void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control + , int axis, ICS::Control::ControlChangingDirection direction) override { //only allow binding to the trigers if (axis != SDL_CONTROLLER_AXIS_TRIGGERLEFT && axis != SDL_CONTROLLER_AXIS_TRIGGERRIGHT) @@ -152,8 +152,8 @@ namespace MWInput MWBase::Environment::get().getWindowManager()->notifyInputActionBound(); } - virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control - , unsigned int button, ICS::Control::ControlChangingDirection direction) + void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, int deviceID, ICS::Control* control + , unsigned int button, ICS::Control::ControlChangingDirection direction) override { if (mDetectingKeyboard) return; diff --git a/apps/openmw/mwinput/controllermanager.cpp b/apps/openmw/mwinput/controllermanager.cpp index b0e769cc6..48091541c 100644 --- a/apps/openmw/mwinput/controllermanager.cpp +++ b/apps/openmw/mwinput/controllermanager.cpp @@ -89,7 +89,7 @@ namespace MWInput bool ControllerManager::update(float dt) { - mGamepadPreviewMode = mActionManager->getPreviewDelay() == 1.f; + mGamepadPreviewMode = mActionManager->isPreviewModeEnabled(); if (mGuiCursorEnabled && !(mJoystickLastUsed && !mGamepadGuiCursorEnabled)) { @@ -190,10 +190,7 @@ namespace MWInput mGamepadZoom = 0; if (mGamepadZoom) - { - MWBase::Environment::get().getWorld()->changeVanityModeScale(mGamepadZoom); - MWBase::Environment::get().getWorld()->setCameraDistance(mGamepadZoom, true, true); - } + MWBase::Environment::get().getWorld()->adjustCameraDistance(-mGamepadZoom); } return triedToMove; @@ -287,16 +284,16 @@ namespace MWInput } else { - if (mGamepadPreviewMode && arg.value) // Preview Mode Gamepad Zooming + if (mGamepadPreviewMode) // Preview Mode Gamepad Zooming { if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) { - mGamepadZoom = arg.value * 0.85f / 1000.f; + mGamepadZoom = arg.value * 0.85f / 1000.f / 12.f; return; // Do not propagate event. } else if (arg.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) { - mGamepadZoom = -arg.value * 0.85f / 1000.f; + mGamepadZoom = -arg.value * 0.85f / 1000.f / 12.f; return; // Do not propagate event. } } diff --git a/apps/openmw/mwinput/controllermanager.hpp b/apps/openmw/mwinput/controllermanager.hpp index 3c1a2ee6e..871f11102 100644 --- a/apps/openmw/mwinput/controllermanager.hpp +++ b/apps/openmw/mwinput/controllermanager.hpp @@ -25,11 +25,11 @@ namespace MWInput bool update(float dt); - virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg); - virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg); - virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg); - virtual void controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg); - virtual void controllerRemoved(const SDL_ControllerDeviceEvent &arg); + void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg) override; + void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg) override; + void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg) override; + void controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg) override; + void controllerRemoved(const SDL_ControllerDeviceEvent &arg) override; void processChangedSettings(const Settings::CategorySettingVector& changed); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 086b0eb73..5ad392bab 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -58,46 +58,45 @@ namespace MWInput virtual ~InputManager(); /// Clear all savegame-specific data - virtual void clear(); + void clear() override; - virtual void update(float dt, bool disableControls=false, bool disableEvents=false); + void update(float dt, bool disableControls=false, bool disableEvents=false) override; - virtual void changeInputMode(bool guiMode); + void changeInputMode(bool guiMode) override; - virtual void processChangedSettings(const Settings::CategorySettingVector& changed); + void processChangedSettings(const Settings::CategorySettingVector& changed) override; - virtual void setDragDrop(bool dragDrop); - virtual void setGamepadGuiCursorEnabled(bool enabled); - virtual void setAttemptJump(bool jumping); + void setDragDrop(bool dragDrop) override; + void setGamepadGuiCursorEnabled(bool enabled) override; + void setAttemptJump(bool jumping) override; - virtual void toggleControlSwitch (const std::string& sw, bool value); - virtual bool getControlSwitch (const std::string& sw); + void toggleControlSwitch (const std::string& sw, bool value) override; + bool getControlSwitch (const std::string& sw) override; - virtual std::string getActionDescription (int action); - virtual std::string getActionKeyBindingName (int action); - virtual std::string getActionControllerBindingName (int action); - virtual int getNumActions() { return A_Last; } - virtual std::vector getActionKeySorting(); - virtual std::vector getActionControllerSorting(); - virtual void enableDetectingBindingMode (int action, bool keyboard); - virtual void resetToDefaultKeyBindings(); - virtual void resetToDefaultControllerBindings(); + std::string getActionDescription (int action) override; + std::string getActionKeyBindingName (int action) override; + std::string getActionControllerBindingName (int action) override; + int getNumActions() override { return A_Last; } + std::vector getActionKeySorting() override; + std::vector getActionControllerSorting() override; + void enableDetectingBindingMode (int action, bool keyboard) override; + void resetToDefaultKeyBindings() override; + void resetToDefaultControllerBindings() override; - virtual void setJoystickLastUsed(bool enabled); - virtual bool joystickLastUsed(); + void setJoystickLastUsed(bool enabled) override; + bool joystickLastUsed() override; - virtual int countSavedGameRecords() const; - virtual void write(ESM::ESMWriter& writer, Loading::Listener& progress); - virtual void readRecord(ESM::ESMReader& reader, uint32_t type); + int countSavedGameRecords() const override; + void write(ESM::ESMWriter& writer, Loading::Listener& progress) override; + void readRecord(ESM::ESMReader& reader, uint32_t type) override; - virtual void resetIdleTime(); + void resetIdleTime() override; - virtual void executeAction(int action); + void executeAction(int action) override; + bool controlsDisabled() override { return mControlsDisabled; } void applyHapticsLeftHand(float intensity) override {}; void applyHapticsRightHand(float intensity) override {}; - - virtual bool controlsDisabled() { return mControlsDisabled; } protected: void convertMousePosForMyGUI(int& x, int& y); diff --git a/apps/openmw/mwinput/keyboardmanager.hpp b/apps/openmw/mwinput/keyboardmanager.hpp index b7027220f..f97f6b9e6 100644 --- a/apps/openmw/mwinput/keyboardmanager.hpp +++ b/apps/openmw/mwinput/keyboardmanager.hpp @@ -15,9 +15,9 @@ namespace MWInput virtual ~KeyboardManager() = default; - virtual void textInput(const SDL_TextInputEvent &arg); - virtual void keyPressed(const SDL_KeyboardEvent &arg); - virtual void keyReleased(const SDL_KeyboardEvent &arg); + void textInput(const SDL_TextInputEvent &arg) override; + void keyPressed(const SDL_KeyboardEvent &arg) override; + void keyReleased(const SDL_KeyboardEvent &arg) override; private: BindingsManager* mBindingsManager; diff --git a/apps/openmw/mwinput/mousemanager.cpp b/apps/openmw/mwinput/mousemanager.cpp index 7b1a3b34d..2f80db522 100644 --- a/apps/openmw/mwinput/mousemanager.cpp +++ b/apps/openmw/mwinput/mousemanager.cpp @@ -93,6 +93,8 @@ namespace MWInput if (mMouseLookEnabled && !input->controlsDisabled()) { + MWBase::World* world = MWBase::Environment::get().getWorld(); + float x = arg.xrel * mCameraSensitivity * (mInvertX ? -1 : 1) / 256.f; float y = arg.yrel * mCameraSensitivity * (mInvertY ? -1 : 1) * mCameraYMultiplier / 256.f; @@ -102,19 +104,14 @@ namespace MWInput rot[2] = -x; // Only actually turn player when we're not in vanity mode - if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && input->getControlSwitch("playerlooking")) + if (!world->vanityRotateCamera(rot) && input->getControlSwitch("playerlooking")) { - MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer(); + MWWorld::Player& player = world->getPlayer(); 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 - { - MWBase::Environment::get().getWorld()->changeVanityModeScale(static_cast(arg.zrel)); - } } } diff --git a/apps/openmw/mwinput/mousemanager.hpp b/apps/openmw/mwinput/mousemanager.hpp index 23ef6cb5e..79f9ab545 100644 --- a/apps/openmw/mwinput/mousemanager.hpp +++ b/apps/openmw/mwinput/mousemanager.hpp @@ -23,10 +23,10 @@ namespace MWInput void updateCursorMode(); void update(float dt); - virtual void mouseMoved(const SDLUtil::MouseMotionEvent &arg); - virtual void mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id); - virtual void mouseReleased(const SDL_MouseButtonEvent &arg, Uint8 id); - virtual void mouseWheelMoved(const SDL_MouseWheelEvent &arg); + void mouseMoved(const SDLUtil::MouseMotionEvent &arg) override; + void mousePressed(const SDL_MouseButtonEvent &arg, Uint8 id) override; + void mouseReleased(const SDL_MouseButtonEvent &arg, Uint8 id) override; + void mouseWheelMoved(const SDL_MouseWheelEvent &arg) override; void processChangedSettings(const Settings::CategorySettingVector& changed); diff --git a/apps/openmw/mwinput/sensormanager.hpp b/apps/openmw/mwinput/sensormanager.hpp index 8f333ad31..75472d43b 100644 --- a/apps/openmw/mwinput/sensormanager.hpp +++ b/apps/openmw/mwinput/sensormanager.hpp @@ -29,8 +29,8 @@ namespace MWInput void update(float dt); - virtual void sensorUpdated(const SDL_SensorEvent &arg); - virtual void displayOrientationChanged(); + void sensorUpdated(const SDL_SensorEvent &arg) override; + void displayOrientationChanged() override; void processChangedSettings(const Settings::CategorySettingVector& changed); void setGuiCursorEnabled(bool enabled) { mGuiCursorEnabled = enabled; } diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 2ccffcc91..928293e64 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -210,9 +210,8 @@ namespace MWMechanics std::string name = it->second.mDisplayName; float magnitude = effectIt->mMagnitude; - if (magnitude) - visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), name, it->first, it->second.mCasterActorId, magnitude, effectIt->mTimeLeft, effectIt->mDuration); + visitor.visit(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), effectIt->mEffectIndex, name, it->first, it->second.mCasterActorId, magnitude, effectIt->mTimeLeft, effectIt->mDuration); } } } @@ -258,14 +257,14 @@ namespace MWMechanics mSpellsChanged = true; } - void ActiveSpells::purgeEffect(short effectId, const std::string& sourceId) + void ActiveSpells::purgeEffect(short effectId, const std::string& sourceId, int effectIndex) { for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); ++it) { for (std::vector::iterator effectIt = it->second.mEffects.begin(); effectIt != it->second.mEffects.end();) { - if (effectIt->mEffectId == effectId && it->first == sourceId) + if (effectIt->mEffectId == effectId && it->first == sourceId && (effectIndex < 0 || effectIndex == effectIt->mEffectIndex)) effectIt = it->second.mEffects.erase(effectIt); else ++effectIt; diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 9a1783bc9..4d36c717e 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -85,7 +85,7 @@ namespace MWMechanics void purgeEffect (short effectId); /// Remove all active effects with this effect id and source id - void purgeEffect (short effectId, const std::string& sourceId); + void purgeEffect (short effectId, const std::string& sourceId, int effectIndex=-1); /// Remove all active effects, if roll succeeds (for each effect) void purgeAll(float chance, bool spellOnly = false); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 93b0e0a89..4d7841010 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "../mwworld/esmstore.hpp" @@ -36,6 +37,7 @@ #include "aicombataction.hpp" #include "aifollow.hpp" #include "aipursue.hpp" +#include "aiwander.hpp" #include "actor.hpp" #include "summoning.hpp" #include "combat.hpp" @@ -88,13 +90,14 @@ class CheckActorCommanded : public MWMechanics::EffectSourceVisitor MWWorld::Ptr mActor; public: bool mCommanded; + CheckActorCommanded(const MWWorld::Ptr& actor) : mActor(actor) - , mCommanded(false){} + , mCommanded(false){} - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, - float magnitude, float remainingTime = -1, float totalTime = -1) + void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, + float magnitude, float remainingTime = -1, float totalTime = -1) override { if (((key.mId == ESM::MagicEffect::CommandHumanoid && mActor.getClass().isNpc()) || (key.mId == ESM::MagicEffect::CommandCreature && mActor.getTypeName() == typeid(ESM::Creature).name())) @@ -156,9 +159,9 @@ namespace MWMechanics GetStuntedMagickaDuration(const MWWorld::Ptr& actor) : mRemainingTime(0.f){} - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, - float magnitude, float remainingTime = -1, float totalTime = -1) + void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, + float magnitude, float remainingTime = -1, float totalTime = -1) override { if (mRemainingTime == -1) return; @@ -186,9 +189,9 @@ namespace MWMechanics { } - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, - float magnitude, float remainingTime = -1, float totalTime = -1) + void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, + float magnitude, float remainingTime = -1, float totalTime = -1) override { if (magnitude <= 0) return; @@ -206,9 +209,9 @@ namespace MWMechanics { public: - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, - float magnitude, float remainingTime = -1, float totalTime = -1) + void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, + float magnitude, float remainingTime = -1, float totalTime = -1) override { if (key.mId != ESM::MagicEffect::Corprus) return; @@ -231,9 +234,9 @@ namespace MWMechanics { } - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, - float magnitude, float remainingTime = -1, float totalTime = -1) + void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, + float magnitude, float remainingTime = -1, float totalTime = -1) override { if (mTrapped) return; @@ -423,7 +426,7 @@ namespace MWMechanics const osg::Vec3f actor2Pos(targetActor.getRefData().getPosition().asVec3()); float sqrDist = (actor1Pos - actor2Pos).length2(); - if (sqrDist > maxDistance*maxDistance) + if (sqrDist > std::min(maxDistance * maxDistance, sqrHeadTrackDistance)) return; // stop tracking when target is behind the actor @@ -431,10 +434,7 @@ namespace MWMechanics osg::Vec3f targetDirection(actor2Pos - actor1Pos); actorDirection.z() = 0; targetDirection.z() = 0; - actorDirection.normalize(); - targetDirection.normalize(); - if (std::acos(actorDirection * targetDirection) < osg::DegreesToRadians(90.f) - && sqrDist <= sqrHeadTrackDistance + if (actorDirection * targetDirection > 0 && MWBase::Environment::get().getWorld()->getLOS(actor, targetActor) // check LOS and awareness last as it's the most expensive function && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(targetActor, actor)) { @@ -472,8 +472,8 @@ namespace MWMechanics void Actors::updateMovementSpeed(const MWWorld::Ptr& actor) { - float previousSpeedFactor = actor.getClass().getMovementSettings(actor).mSpeedFactor; - float newSpeedFactor = 1.f; + if (mSmoothMovement) + return; CreatureStats &stats = actor.getClass().getCreatureStats(actor); MWMechanics::AiSequence& seq = stats.getAiSequence(); @@ -483,11 +483,15 @@ namespace MWMechanics osg::Vec3f targetPos = seq.getActivePackage().getDestination(); osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3(); float distance = (targetPos - actorPos).length(); - if (distance < DECELERATE_DISTANCE) - newSpeedFactor = std::max(0.7f, 0.1f * previousSpeedFactor * (distance/64.f + 2.f)); - } - actor.getClass().getMovementSettings(actor).mSpeedFactor = newSpeedFactor; + if (distance < DECELERATE_DISTANCE) + { + float speedCoef = std::max(0.7f, 0.2f + 0.8f * distance / DECELERATE_DISTANCE); + auto& movement = actor.getClass().getMovementSettings(actor); + movement.mPosition[0] *= speedCoef; + movement.mPosition[1] *= speedCoef; + } + } } void Actors::updateGreetingState(const MWWorld::Ptr& actor, Actor& actorState, bool turnOnly) @@ -586,8 +590,11 @@ namespace MWMechanics if (!actorState.isTurningToPlayer()) { - actorState.setAngleToPlayer(std::atan2(dir.x(), dir.y())); - actorState.setTurningToPlayer(true); + float angle = std::atan2(dir.x(), dir.y()); + actorState.setAngleToPlayer(angle); + float deltaAngle = Misc::normalizeAngle(angle - actor.getRefData().getPosition().rot[2]); + if (!mSmoothMovement || std::abs(deltaAngle) > osg::DegreesToRadians(60.f)) + actorState.setTurningToPlayer(true); } } @@ -894,9 +901,9 @@ namespace MWMechanics { } - virtual void visit (MWMechanics::EffectKey key, + void visit (MWMechanics::EffectKey key, int /*effectIndex*/, const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, - float magnitude, float remainingTime = -1, float /*totalTime*/ = -1) + float magnitude, float remainingTime = -1, float /*totalTime*/ = -1) override { if (magnitude > 0 && remainingTime > 0 && remainingTime < mDuration) { @@ -911,6 +918,7 @@ namespace MWMechanics { CreatureStats &creatureStats = ptr.getClass().getCreatureStats(ptr); const MagicEffects &effects = creatureStats.getMagicEffects(); + bool godmode = ptr == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); bool wasDead = creatureStats.isDead(); @@ -962,8 +970,11 @@ namespace MWMechanics for (int i = 0; i < 3; ++i) { DynamicStat stat = creatureStats.getDynamic(i); - stat.setCurrentModifier(effects.get(ESM::MagicEffect::FortifyHealth + i).getMagnitude() - - effects.get(ESM::MagicEffect::DrainHealth + i).getMagnitude(), + float fortify = effects.get(ESM::MagicEffect::FortifyHealth + i).getMagnitude(); + float drain = 0.f; + if (!godmode) + drain = effects.get(ESM::MagicEffect::DrainHealth + i).getMagnitude(); + stat.setCurrentModifier(fortify - drain, // Magicka can be decreased below zero due to a fortify effect wearing off // Fatigue can be decreased below zero meaning the actor will be knocked out i == 1 || i == 2); @@ -975,9 +986,14 @@ namespace MWMechanics for(int i = 0;i < ESM::Attribute::Length;++i) { AttributeValue stat = creatureStats.getAttribute(i); - stat.setModifier(static_cast(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).getMagnitude() - - effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).getMagnitude() - - effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).getMagnitude())); + float fortify = effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).getMagnitude(); + float drain = 0.f, absorb = 0.f; + if (!godmode) + { + drain = effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).getMagnitude(); + absorb = effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).getMagnitude(); + } + stat.setModifier(static_cast(fortify - drain - absorb)); creatureStats.setAttribute(i, stat); } @@ -1182,6 +1198,11 @@ namespace MWMechanics } } + // Summoned creature update visitor assumes the actor belongs to a cell. + // This assumption isn't always valid for the player character. + if (!ptr.isInCell()) + return; + bool hasSummonEffect = false; for (MagicEffects::Collection::const_iterator it = effects.begin(); it != effects.end(); ++it) { @@ -1196,6 +1217,7 @@ namespace MWMechanics { UpdateSummonedCreatures updateSummonedCreatures(ptr); creatureStats.getActiveSpells().visitEffectSources(updateSummonedCreatures); + creatureStats.getSpells().visitEffectSources(updateSummonedCreatures); if (ptr.getClass().hasInventoryStore(ptr)) ptr.getClass().getInventoryStore(ptr).visitEffectSources(updateSummonedCreatures); updateSummonedCreatures.process(mTimerDisposeSummonsCorpses == 0.f); @@ -1206,14 +1228,20 @@ namespace MWMechanics { NpcStats &npcStats = ptr.getClass().getNpcStats(ptr); const MagicEffects &effects = npcStats.getMagicEffects(); + bool godmode = ptr == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); // skills for(int i = 0;i < ESM::Skill::Length;++i) { SkillValue& skill = npcStats.getSkill(i); - skill.setModifier(static_cast(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).getMagnitude() - - effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).getMagnitude() - - effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).getMagnitude())); + float fortify = effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).getMagnitude(); + float drain = 0.f, absorb = 0.f; + if (!godmode) + { + drain = effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).getMagnitude(); + absorb = effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).getMagnitude(); + } + skill.setModifier(static_cast(fortify - drain - absorb)); } } @@ -1458,7 +1486,7 @@ namespace MWMechanics } } - Actors::Actors() + Actors::Actors() : mSmoothMovement(Settings::Manager::getBool("smooth movement", "Game")) { mTimerDisposeSummonsCorpses = 0.2f; // We should add a delay between summoned creature death and its corpse despawning @@ -1657,6 +1685,141 @@ namespace MWMechanics } + void Actors::predictAndAvoidCollisions() + { + const float minGap = 10.f; + const float maxDistForPartialAvoiding = 200.f; + const float maxDistForStrictAvoiding = 100.f; + const float maxTimeToCheck = 2.0f; + static const bool giveWayWhenIdle = Settings::Manager::getBool("NPCs give way", "Game"); + + MWWorld::Ptr player = getPlayer(); + MWBase::World* world = MWBase::Environment::get().getWorld(); + for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) + { + const MWWorld::Ptr& ptr = iter->first; + if (ptr == player) + continue; // Don't interfere with player controls. + + float maxSpeed = ptr.getClass().getMaxSpeed(ptr); + if (maxSpeed == 0.0) + continue; // Can't move, so there is no sense to predict collisions. + + Movement& movement = ptr.getClass().getMovementSettings(ptr); + osg::Vec2f origMovement(movement.mPosition[0], movement.mPosition[1]); + bool isMoving = origMovement.length2() > 0.01; + if (movement.mPosition[1] < 0) + continue; // Actors can not see others when move backward. + + // Moving NPCs always should avoid collisions. + // Standing NPCs give way to moving ones if they are not in combat (or pursue) mode and either + // follow player or have a AIWander package with non-empty wander area. + bool shouldAvoidCollision = isMoving; + bool shouldTurnToApproachingActor = !isMoving; + MWWorld::Ptr currentTarget; // Combat or pursue target (NPCs should not avoid collision with their targets). + for (const auto& package : ptr.getClass().getCreatureStats(ptr).getAiSequence()) + { + if (package->getTypeId() == AiPackageTypeId::Follow) + shouldAvoidCollision = true; + else if (package->getTypeId() == AiPackageTypeId::Wander && giveWayWhenIdle) + { + if (!dynamic_cast(package.get())->isStationary()) + shouldAvoidCollision = true; + } + else if (package->getTypeId() == AiPackageTypeId::Combat || package->getTypeId() == AiPackageTypeId::Pursue) + { + currentTarget = package->getTarget(); + shouldAvoidCollision = isMoving; + shouldTurnToApproachingActor = false; + break; + } + } + if (!shouldAvoidCollision) + continue; + + osg::Vec2f baseSpeed = origMovement * maxSpeed; + osg::Vec3f basePos = ptr.getRefData().getPosition().asVec3(); + float baseRotZ = ptr.getRefData().getPosition().rot[2]; + osg::Vec3f halfExtents = world->getHalfExtents(ptr); + float maxDistToCheck = isMoving ? maxDistForPartialAvoiding : maxDistForStrictAvoiding; + + float timeToCollision = maxTimeToCheck; + osg::Vec2f movementCorrection(0, 0); + float angleToApproachingActor = 0; + + // Iterate through all other actors and predict collisions. + for(PtrActorMap::iterator otherIter(mActors.begin()); otherIter != mActors.end(); ++otherIter) + { + const MWWorld::Ptr& otherPtr = otherIter->first; + if (otherPtr == ptr || otherPtr == currentTarget) + continue; + + osg::Vec3f otherHalfExtents = world->getHalfExtents(otherPtr); + osg::Vec3f deltaPos = otherPtr.getRefData().getPosition().asVec3() - basePos; + osg::Vec2f relPos = Misc::rotateVec2f(osg::Vec2f(deltaPos.x(), deltaPos.y()), baseRotZ); + float dist = deltaPos.length(); + + // Ignore actors which are not close enough or come from behind. + if (dist > maxDistToCheck || relPos.y() < 0) + continue; + + // Don't check for a collision if vertical distance is greater then the actor's height. + if (deltaPos.z() > halfExtents.z() * 2 || deltaPos.z() < -otherHalfExtents.z() * 2) + continue; + + osg::Vec3f speed = otherPtr.getClass().getMovementSettings(otherPtr).asVec3() * + otherPtr.getClass().getMaxSpeed(otherPtr); + float rotZ = otherPtr.getRefData().getPosition().rot[2]; + osg::Vec2f relSpeed = Misc::rotateVec2f(osg::Vec2f(speed.x(), speed.y()), baseRotZ - rotZ) - baseSpeed; + + float collisionDist = minGap + world->getHalfExtents(ptr).x() + world->getHalfExtents(otherPtr).x(); + collisionDist = std::min(collisionDist, relPos.length()); + + // Find the earliest `t` when |relPos + relSpeed * t| == collisionDist. + float vr = relPos.x() * relSpeed.x() + relPos.y() * relSpeed.y(); + float v2 = relSpeed.length2(); + float Dh = vr * vr - v2 * (relPos.length2() - collisionDist * collisionDist); + if (Dh <= 0 || v2 == 0) + continue; // No solution; distance is always >= collisionDist. + float t = (-vr - std::sqrt(Dh)) / v2; + + if (t < 0 || t > timeToCollision) + continue; + + // Check visibility and awareness last as it's expensive. + if (!MWBase::Environment::get().getWorld()->getLOS(otherPtr, ptr)) + continue; + if (!MWBase::Environment::get().getMechanicsManager()->awarenessCheck(otherPtr, ptr)) + continue; + + timeToCollision = t; + angleToApproachingActor = std::atan2(deltaPos.x(), deltaPos.y()); + osg::Vec2f posAtT = relPos + relSpeed * t; + float coef = (posAtT.x() * relSpeed.x() + posAtT.y() * relSpeed.y()) / (collisionDist * collisionDist * maxSpeed); + coef *= osg::clampBetween((maxDistForPartialAvoiding - dist) / (maxDistForPartialAvoiding - maxDistForStrictAvoiding), 0.f, 1.f); + movementCorrection = posAtT * coef; + if (otherPtr.getClass().getCreatureStats(otherPtr).isDead()) + // In case of dead body still try to go around (it looks natural), but reduce the correction twice. + movementCorrection.y() *= 0.5f; + } + + if (timeToCollision < maxTimeToCheck) + { + // Try to evade the nearest collision. + osg::Vec2f newMovement = origMovement + movementCorrection; + // Step to the side rather than backward. Otherwise player will be able to push the NPC far away from it's original location. + newMovement.y() = std::max(newMovement.y(), 0.f); + newMovement.normalize(); + if (isMoving) + newMovement *= origMovement.length(); // Keep the original speed. + movement.mPosition[0] = newMovement.x(); + movement.mPosition[1] = newMovement.y(); + if (shouldTurnToApproachingActor) + zTurn(ptr, angleToApproachingActor); + } + } + } + void Actors::update (float duration, bool paused) { if(!paused) @@ -1694,6 +1857,7 @@ namespace MWMechanics if (!playerHitAttemptActor.isInCell()) player.getClass().getCreatureStats(player).setHitAttemptActorId(-1); } + bool godmode = MWBase::Environment::get().getWorld()->getGodModeState(); // AI and magic effects update for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) @@ -1767,14 +1931,12 @@ namespace MWMechanics MWMechanics::CreatureStats& stats = iter->first.getClass().getCreatureStats(iter->first); bool firstPersonPlayer = isPlayer && world->isFirstPerson(); + bool inCombatOrPursue = stats.getAiSequence().isInCombat() || stats.getAiSequence().hasPackage(AiPackageTypeId::Pursue); // 1. Unconsious actor can not track target // 2. Actors in combat and pursue mode do not bother to headtrack // 3. Player character does not use headtracking in the 1st-person view - if (!stats.getKnockedDown() && - !stats.getAiSequence().isInCombat() && - !stats.getAiSequence().hasPackage(AiPackageTypeId::Pursue) && - !firstPersonPlayer) + if (!stats.getKnockedDown() && !firstPersonPlayer && !inCombatOrPursue) { for(PtrActorMap::iterator it(mActors.begin()); it != mActors.end(); ++it) { @@ -1784,6 +1946,17 @@ namespace MWMechanics } } + if (!stats.getKnockedDown() && !isPlayer && inCombatOrPursue) + { + // Actors in combat and pursue mode always look at their target. + for (const auto& package : stats.getAiSequence()) + { + headTrackTarget = package->getTarget(); + if (!headTrackTarget.isEmpty()) + break; + } + } + ctrl->setHeadTrackTarget(headTrackTarget); } @@ -1822,6 +1995,10 @@ namespace MWMechanics } } + static const bool avoidCollisions = Settings::Manager::getBool("NPCs avoid collisions", "Game"); + if (avoidCollisions) + predictAndAvoidCollisions(); + timerUpdateAITargets += duration; timerUpdateHeadTrack += duration; timerUpdateEquippedLight += duration; @@ -1861,7 +2038,7 @@ namespace MWMechanics iter->first.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor); const bool isDead = iter->first.getClass().getCreatureStats(iter->first).isDead(); - if (!isDead && iter->first.getClass().getCreatureStats(iter->first).isParalyzed()) + if (!isDead && (!godmode || !isPlayer) && iter->first.getClass().getCreatureStats(iter->first).isParalyzed()) ctrl->skipAnim(); // Handle player last, in case a cell transition occurs by casting a teleportation spell @@ -1973,10 +2150,6 @@ namespace MWMechanics // One case where we need this is to make sure bound items are removed upon death stats.modifyMagicEffects(MWMechanics::MagicEffects()); stats.getActiveSpells().clear(); - - if (!isPlayer) - stats.getSpells().clear(); - // Make sure spell effects are removed purgeSpellEffects(stats.getActorId()); @@ -2018,7 +2191,7 @@ namespace MWMechanics // Remove the summoned creature's summoned creatures as well MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); - std::map& creatureMap = stats.getSummonedCreatureMap(); + std::map& creatureMap = stats.getSummonedCreatureMap(); for (const auto& creature : creatureMap) cleanupSummonedCreature(stats, creature.second); creatureMap.clear(); @@ -2055,10 +2228,11 @@ namespace MWMechanics for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) { - iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration); - if (iter->first.getClass().getCreatureStats(iter->first).isDead()) + { + iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration); continue; + } if (!sleep || iter->first == player) restoreDynamicStats(iter->first, hours, sleep); @@ -2075,13 +2249,14 @@ namespace MWMechanics if (iter->first.getClass().isNpc()) calculateNpcStatModifiers(iter->first, duration); + iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration); + MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first); if (animation) { animation->removeEffects(); MWBase::Environment::get().getWorld()->applyLoopingParticles(iter->first); } - } fastForwardAi(); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index bd5a14c0d..9299d468c 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -63,6 +63,8 @@ namespace MWMechanics void purgeSpellEffects (int casterActorId); + void predictAndAvoidCollisions(); + public: Actors(); @@ -209,6 +211,7 @@ namespace MWMechanics float mTimerDisposeSummonsCorpses; float mActorsProcessingRange; + bool mSmoothMovement; }; } diff --git a/apps/openmw/mwmechanics/actorutil.hpp b/apps/openmw/mwmechanics/actorutil.hpp index cb77ef3ea..1e993f560 100644 --- a/apps/openmw/mwmechanics/actorutil.hpp +++ b/apps/openmw/mwmechanics/actorutil.hpp @@ -1,6 +1,9 @@ #ifndef OPENMW_MWMECHANICS_ACTORUTIL_H #define OPENMW_MWMECHANICS_ACTORUTIL_H +#include + +#include #include #include @@ -53,8 +56,35 @@ namespace MWMechanics MWBase::Environment::get().getWorld()->createOverrideRecord(copy); } + template + void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) + { + T copy = *MWBase::Environment::get().getWorld()->getStore().get().find(actorId); + for(auto& it : copy.mInventory.mList) + { + if(Misc::StringUtils::ciEqual(it.mItem, itemId)) + { + int sign = it.mCount < 1 ? -1 : 1; + it.mCount = sign * std::max(it.mCount * sign + amount, 0); + MWBase::Environment::get().getWorld()->createOverrideRecord(copy); + return; + } + } + if(amount > 0) + { + ESM::ContItem cont; + cont.mItem = itemId; + cont.mCount = amount; + copy.mInventory.mList.push_back(cont); + MWBase::Environment::get().getWorld()->createOverrideRecord(copy); + } + } + template void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value); template void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value); + template void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount); + template void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount); + template void modifyBaseInventory(const std::string& containerId, const std::string& itemId, int amount); } #endif diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 47f72efce..73a638563 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& neighbor : actors) + { + if (neighbor == getPlayer()) + continue; + + MWMechanics::AiSequence& seq = neighbor.getClass().getCreatureStats(neighbor).getAiSequence(); + if (seq.getTypeId() != MWMechanics::AiPackageTypeId::AvoidDoor) + seq.stack(MWMechanics::AiAvoidDoor(mDoorPtr), neighbor); } return false; diff --git a/apps/openmw/mwmechanics/aibreathe.cpp b/apps/openmw/mwmechanics/aibreathe.cpp index 15251e125..2740355b5 100644 --- a/apps/openmw/mwmechanics/aibreathe.cpp +++ b/apps/openmw/mwmechanics/aibreathe.cpp @@ -23,7 +23,7 @@ bool MWMechanics::AiBreathe::execute (const MWWorld::Ptr& actor, CharacterContro actorClass.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); actorClass.getMovementSettings(actor).mPosition[1] = 1; - smoothTurn(actor, -180, 0); + smoothTurn(actor, -osg::PI / 2, 0); return false; } diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 1ae27a9cb..b98d5ef49 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -5,6 +5,8 @@ #include +#include + #include #include "../mwphysics/collisiontype.hpp" @@ -238,27 +240,27 @@ namespace MWMechanics storage.mReadyToAttack = (currentAction->isAttackingOrSpell() && distToTarget <= rangeAttack && storage.mLOS); + if (isRangedCombat) + { + // rotate actor taking into account target movement direction and projectile speed + osg::Vec3f& lastTargetPos = storage.mLastTargetPos; + vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, AI_REACTION_TIME, (weapon ? weapon->mData.mType : 0), storage.mStrength); + lastTargetPos = vTargetPos; + + storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); + storage.mMovement.mRotation[2] = getZAngleToDir(vAimDir); + } + else + { + storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); + storage.mMovement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated + } + if (storage.mReadyToAttack) { storage.startCombatMove(isRangedCombat, distToTarget, rangeAttack, actor, target); // start new attack storage.startAttackIfReady(actor, characterController, weapon, isRangedCombat); - - if (isRangedCombat) - { - // rotate actor taking into account target movement direction and projectile speed - osg::Vec3f& lastTargetPos = storage.mLastTargetPos; - vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, AI_REACTION_TIME, (weapon ? weapon->mData.mType : 0), storage.mStrength); - lastTargetPos = vTargetPos; - - storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); - storage.mMovement.mRotation[2] = getZAngleToDir(vAimDir); - } - else - { - storage.mMovement.mRotation[0] = getXAngleToDir(vAimDir); - storage.mMovement.mRotation[2] = getZAngleToDir((vTargetPos-vActorPos)); // using vAimDir results in spastic movements since the head is animated - } } return false; } @@ -372,9 +374,13 @@ namespace MWMechanics void AiCombat::updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage) { // apply combat movement + float deltaAngle = storage.mMovement.mRotation[2] - actor.getRefData().getPosition().rot[2]; + osg::Vec2f movement = Misc::rotateVec2f( + osg::Vec2f(storage.mMovement.mPosition[0], storage.mMovement.mPosition[1]), -deltaAngle); + MWMechanics::Movement& actorMovementSettings = actor.getClass().getMovementSettings(actor); - actorMovementSettings.mPosition[0] = storage.mMovement.mPosition[0]; - actorMovementSettings.mPosition[1] = storage.mMovement.mPosition[1]; + actorMovementSettings.mPosition[0] = movement.x(); + actorMovementSettings.mPosition[1] = movement.y(); actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2]; rotateActorOnAxis(actor, 2, actorMovementSettings, storage); @@ -385,26 +391,11 @@ namespace MWMechanics MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage) { actorMovementSettings.mRotation[axis] = 0; - float& targetAngleRadians = storage.mMovement.mRotation[axis]; - if (targetAngleRadians != 0) - { - // Some attack animations contain small amount of movement. - // Since we use cone shapes for melee, we can use a threshold to avoid jittering - std::shared_ptr& currentAction = storage.mCurrentAction; - bool isRangedCombat = false; - currentAction->getCombatRange(isRangedCombat); - // Check if the actor now facing desired direction, no need to turn any more - if (isRangedCombat) - { - if (smoothTurn(actor, targetAngleRadians, axis)) - targetAngleRadians = 0; - } - else - { - if (smoothTurn(actor, targetAngleRadians, axis, osg::DegreesToRadians(3.f))) - targetAngleRadians = 0; - } - } + bool isRangedCombat = false; + storage.mCurrentAction->getCombatRange(isRangedCombat); + float eps = isRangedCombat ? osg::DegreesToRadians(0.5) : osg::DegreesToRadians(3.f); + float targetAngleRadians = storage.mMovement.mRotation[axis]; + smoothTurn(actor, targetAngleRadians, axis, eps); } MWWorld::Ptr AiCombat::getTarget() const @@ -489,12 +480,19 @@ namespace MWMechanics // Note: do not use for ranged combat yet since in couple with back up behaviour can move actor out of cliff else if (actor.getClass().isBipedal(actor)) { - // apply sideway movement (kind of dodging) with some probability - // if actor is within range of target's weapon - if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25) + float moveDuration = 0; + float angleToTarget = Misc::normalizeAngle(mMovement.mRotation[2] - actor.getRefData().getPosition().rot[2]); + // Apply a big side step if enemy tries to get around and come from behind. + // Otherwise apply a random side step (kind of dodging) with some probability + // if actor is within range of target's weapon. + if (std::abs(angleToTarget) > osg::PI / 4) + moveDuration = 0.2; + else if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25) + moveDuration = 0.1f + 0.1f * Misc::Rng::rollClosedProbability(); + if (moveDuration > 0) { mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right - mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability(); + mTimerCombatMove = moveDuration; mCombatMove = true; } } diff --git a/apps/openmw/mwmechanics/aicombataction.hpp b/apps/openmw/mwmechanics/aicombataction.hpp index cf7dc78fd..77a19f804 100644 --- a/apps/openmw/mwmechanics/aicombataction.hpp +++ b/apps/openmw/mwmechanics/aicombataction.hpp @@ -17,7 +17,7 @@ namespace MWMechanics virtual void prepare(const MWWorld::Ptr& actor) = 0; virtual float getCombatRange (bool& isRanged) const = 0; virtual float getActionCooldown() { return 0.f; } - virtual const ESM::Weapon* getWeapon() const { return nullptr; }; + virtual const ESM::Weapon* getWeapon() const { return nullptr; } virtual bool isAttackingOrSpell() const { return true; } virtual bool isFleeing() const { return false; } }; @@ -26,11 +26,11 @@ namespace MWMechanics { public: ActionFlee() {} - virtual void prepare(const MWWorld::Ptr& actor) {} - virtual float getCombatRange (bool& isRanged) const { return 0.0f; } - virtual float getActionCooldown() { return 3.0f; } - virtual bool isAttackingOrSpell() const { return false; } - virtual bool isFleeing() const { return true; } + void prepare(const MWWorld::Ptr& actor) override {} + float getCombatRange (bool& isRanged) const override { return 0.0f; } + float getActionCooldown() override { return 3.0f; } + bool isAttackingOrSpell() const override { return false; } + bool isFleeing() const override { return true; } }; class ActionSpell : public Action @@ -39,9 +39,9 @@ namespace MWMechanics ActionSpell(const std::string& spellId) : mSpellId(spellId) {} std::string mSpellId; /// Sets the given spell as selected on the actor's spell list. - virtual void prepare(const MWWorld::Ptr& actor); + void prepare(const MWWorld::Ptr& actor) override; - virtual float getCombatRange (bool& isRanged) const; + float getCombatRange (bool& isRanged) const override; }; class ActionEnchantedItem : public Action @@ -50,11 +50,11 @@ namespace MWMechanics ActionEnchantedItem(const MWWorld::ContainerStoreIterator& item) : mItem(item) {} MWWorld::ContainerStoreIterator mItem; /// Sets the given item as selected enchanted item in the actor's InventoryStore. - virtual void prepare(const MWWorld::Ptr& actor); - virtual float getCombatRange (bool& isRanged) const; + void prepare(const MWWorld::Ptr& actor) override; + float getCombatRange (bool& isRanged) const override; /// Since this action has no animation, apply a small cool down for using it - virtual float getActionCooldown() { return 0.75f; } + float getActionCooldown() override { return 0.75f; } }; class ActionPotion : public Action @@ -63,12 +63,12 @@ namespace MWMechanics ActionPotion(const MWWorld::Ptr& potion) : mPotion(potion) {} MWWorld::Ptr mPotion; /// Drinks the given potion. - virtual void prepare(const MWWorld::Ptr& actor); - virtual float getCombatRange (bool& isRanged) const; - virtual bool isAttackingOrSpell() const { return false; } + void prepare(const MWWorld::Ptr& actor) override; + float getCombatRange (bool& isRanged) const override; + bool isAttackingOrSpell() const override { return false; } /// Since this action has no animation, apply a small cool down for using it - virtual float getActionCooldown() { return 0.75f; } + float getActionCooldown() override { return 0.75f; } }; class ActionWeapon : public Action @@ -82,9 +82,9 @@ namespace MWMechanics ActionWeapon(const MWWorld::Ptr& weapon, const MWWorld::Ptr& ammo = MWWorld::Ptr()) : mAmmunition(ammo), mWeapon(weapon) {} /// Equips the given weapon. - virtual void prepare(const MWWorld::Ptr& actor); - virtual float getCombatRange (bool& isRanged) const; - virtual const ESM::Weapon* getWeapon() const; + void prepare(const MWWorld::Ptr& actor) override; + float getCombatRange (bool& isRanged) const override; + const ESM::Weapon* getWeapon() const override; }; std::shared_ptr prepareNextAction (const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy); 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/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index f7c07bde0..4bffd28ba 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -87,6 +88,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& //... But AI processing distance may increase in the future. if (isNearInactiveCell(position)) { + actor.getClass().getMovementSettings(actor).mPosition[0] = 0; actor.getClass().getMovementSettings(actor).mPosition[1] = 0; world->updateActorPath(actor, mPathFinder.getPath(), halfExtents, position, dest); return false; @@ -144,7 +146,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& mTimer = 0; } - const float actorTolerance = 2 * actor.getClass().getSpeed(actor) * duration + const float actorTolerance = 2 * actor.getClass().getMaxSpeed(actor) * duration + 1.2 * std::max(halfExtents.x(), halfExtents.y()); const float pointTolerance = std::max(MIN_TOLERANCE, actorTolerance); @@ -169,12 +171,34 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& } // turn to next path point by X,Z axes - zTurn(actor, mPathFinder.getZAngleToNext(position.x(), position.y())); + float zAngleToNext = mPathFinder.getZAngleToNext(position.x(), position.y()); + zTurn(actor, zAngleToNext); smoothTurn(actor, mPathFinder.getXAngleToNext(position.x(), position.y(), position.z()), 0); const auto destination = mPathFinder.getPath().empty() ? dest : mPathFinder.getPath().front(); mObstacleCheck.update(actor, destination, duration); + static const bool smoothMovement = Settings::Manager::getBool("smooth movement", "Game"); + if (smoothMovement) + { + const float smoothTurnReservedDist = 150; + auto& movement = actor.getClass().getMovementSettings(actor); + float distToNextSqr = osg::Vec2f(destination.x() - position.x(), destination.y() - position.y()).length2(); + float diffAngle = zAngleToNext - actor.getRefData().getPosition().rot[2]; + if (std::cos(diffAngle) < -0.1) + movement.mPosition[0] = movement.mPosition[1] = 0; + else if (distToNextSqr > smoothTurnReservedDist * smoothTurnReservedDist) + { // Go forward (and slowly turn towards the next path point) + movement.mPosition[0] = 0; + movement.mPosition[1] = 1; + } + else + { // Next path point is near, so use diagonal movement to follow the path precisely. + movement.mPosition[0] = std::sin(diffAngle); + movement.mPosition[1] = std::max(std::cos(diffAngle), 0.f); + } + } + // handle obstacles on the way evadeObstacles(actor); @@ -300,7 +324,7 @@ bool MWMechanics::AiPackage::checkWayIsClearForActor(const osg::Vec3f& startPoin if (canActorMoveByZAxis(actor)) return true; - const float actorSpeed = actor.getClass().getSpeed(actor); + const float actorSpeed = actor.getClass().getMaxSpeed(actor); const float maxAvoidDist = AI_REACTION_TIME * actorSpeed + actorSpeed / getAngularVelocity(actorSpeed) * 2; // *2 - for reliability const float distToTarget = osg::Vec2f(endPoint.x(), endPoint.y()).length(); @@ -360,7 +384,7 @@ bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position) bool MWMechanics::AiPackage::isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const osg::Vec3f& dest) { // get actor's shortest radius for moving in circle - float speed = actor.getClass().getSpeed(actor); + float speed = actor.getClass().getMaxSpeed(actor); speed += speed * 0.1f; // 10% real speed inaccuracy float radius = speed / getAngularVelocity(speed); diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 7aa2a9554..bfe860d6d 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -39,8 +39,7 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte if (target == MWWorld::Ptr() || !target.getRefData().getCount() || !target.getRefData().isEnabled()) return true; - if (!MWBase::Environment::get().getWorld()->getLOS(target, actor) - || !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(target, actor)) + if (isTargetMagicallyHidden(target) && !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(target, actor)) return false; if (target.getClass().getCreatureStats(target).isDead()) 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..375209a25 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -27,7 +27,7 @@ namespace MWMechanics { static const int COUNT_BEFORE_RESET = 10; - static const float DOOR_CHECK_INTERVAL = 1.5f; + static const float IDLE_POSITION_CHECK_INTERVAL = 1.5f; // to prevent overcrowding static const int DESTINATION_TOLERANCE = 64; @@ -96,6 +96,7 @@ namespace MWMechanics void stopMovement(const MWWorld::Ptr& actor) { + actor.getClass().getMovementSettings(actor).mPosition[0] = 0; actor.getClass().getMovementSettings(actor).mPosition[1] = 0; } @@ -424,15 +425,14 @@ namespace MWMechanics void AiWander::onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage) { - // Check if an idle actor is too close to a door - if so start walking - storage.mDoorCheckDuration += duration; + // Check if an idle actor is too far from all allowed nodes or too close to a door - if so start walking. + storage.mCheckIdlePositionTimer += duration; - if (storage.mDoorCheckDuration >= DOOR_CHECK_INTERVAL) + if (storage.mCheckIdlePositionTimer >= IDLE_POSITION_CHECK_INTERVAL && !isStationary()) { - storage.mDoorCheckDuration = 0; // restart timer - static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); - if (mDistance && // actor is not intended to be stationary - proximityToDoor(actor, distance*1.6f)) + storage.mCheckIdlePositionTimer = 0; // restart timer + static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance() * 1.6f; + if (proximityToDoor(actor, distance) || !isNearAllowedNode(actor, storage, distance)) { storage.setState(AiWanderStorage::Wander_MoveNow); storage.mTrimCurrentNode = false; // just in case @@ -451,6 +451,20 @@ namespace MWMechanics } } + bool AiWander::isNearAllowedNode(const MWWorld::Ptr& actor, const AiWanderStorage& storage, float distance) const + { + const osg::Vec3f actorPos = actor.getRefData().getPosition().asVec3(); + auto cell = actor.getCell()->getCell(); + for (const ESM::Pathgrid::Point& node : storage.mAllowedNodes) + { + osg::Vec3f point(node.mX, node.mY, node.mZ); + Misc::CoordinateConverter(cell).toWorld(point); + if ((actorPos - point).length2() < distance * distance) + return true; + } + return false; + } + void AiWander::onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage) { // Is there no destination or are we there yet? @@ -468,6 +482,9 @@ namespace MWMechanics void AiWander::onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage) { + // Wait while fully stop before starting idle animation (important if "smooth movement" is enabled). + if (actor.getClass().getCurrentSpeed(actor) > 0) + return; unsigned short idleAnimation = getRandomIdle(); storage.mIdleAnimation = idleAnimation; @@ -809,11 +826,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/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 4138c3dea..4165cebbd 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -53,7 +53,7 @@ namespace MWMechanics ESM::Pathgrid::Point mCurrentNode; bool mTrimCurrentNode; - float mDoorCheckDuration; + float mCheckIdlePositionTimer; int mStuckCount; AiWanderStorage(): @@ -66,7 +66,7 @@ namespace MWMechanics mPopulateAvailableNodes(true), mAllowedNodes(), mTrimCurrentNode(false), - mDoorCheckDuration(0), // TODO: maybe no longer needed + mCheckIdlePositionTimer(0), mStuckCount(0) {}; @@ -117,6 +117,8 @@ namespace MWMechanics return mDestination; } + bool isStationary() const { return mDistance == 0; } + private: void stopWalking(const MWWorld::Ptr& actor); @@ -137,6 +139,7 @@ namespace MWMechanics void wanderNearStart(const MWWorld::Ptr &actor, AiWanderStorage &storage, int wanderDistance); bool destinationIsAtWater(const MWWorld::Ptr &actor, const osg::Vec3f& destination); void completeManualWalking(const MWWorld::Ptr &actor, AiWanderStorage &storage); + bool isNearAllowedNode(const MWWorld::Ptr &actor, const AiWanderStorage& storage, float distance) const; const int mDistance; // how far the actor can wander from the spawn point const int mDuration; 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 4b938015b..11e2e8a32 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -21,6 +21,7 @@ #include +#include #include #include @@ -57,15 +58,6 @@ namespace { -// Wraps a value to (-PI, PI] -void wrap(float& rad) -{ - if (rad>0) - rad = std::fmod(rad+osg::PI, 2.0f*osg::PI)-osg::PI; - else - rad = std::fmod(rad-osg::PI, 2.0f*osg::PI)+osg::PI; -} - std::string getBestAttack (const ESM::Weapon* weapon) { int slash = (weapon->mData.mSlash[0] + weapon->mData.mSlash[1])/2; @@ -1320,6 +1312,8 @@ bool CharacterController::updateWeaponState(CharacterState& idle) 1.0f, "unequip start", "unequip stop", 0.0f, 0); mUpperBodyState = UpperCharState_UnEquipingWeap; + mAnimation->detachArrow(); + // If we do not have the "unequip detach" key, hide weapon manually. if (mAnimation->getTextKeyTime(weapgroup+": unequip detach") < 0) mAnimation->showWeapons(false); @@ -1807,7 +1801,9 @@ bool CharacterController::updateWeaponState(CharacterState& idle) mUpperBodyState = UpperCharState_MinAttackToMaxAttack; break; } - playSwishSound(0.0f); + + if(weapclass != ESM::WeaponType::Ranged && weapclass != ESM::WeaponType::Thrown) + playSwishSound(0.0f); } if(mAttackType == "shoot") @@ -1944,7 +1940,7 @@ void CharacterController::update(float duration, bool animationOnly) else if(!cls.getCreatureStats(mPtr).isDead()) { bool onground = world->isOnGround(mPtr); - bool incapacitated = (cls.getCreatureStats(mPtr).isParalyzed() || cls.getCreatureStats(mPtr).getKnockedDown()); + bool incapacitated = ((!godmode && cls.getCreatureStats(mPtr).isParalyzed()) || cls.getCreatureStats(mPtr).getKnockedDown()); bool inwater = world->isSwimming(mPtr); bool flying = world->isFlying(mPtr); bool solid = world->isActorCollisionEnabled(mPtr); @@ -1969,27 +1965,66 @@ void CharacterController::update(float duration, bool animationOnly) osg::Vec3f rot = cls.getRotationVector(mPtr); osg::Vec3f vec(movementSettings.asVec3()); + movementSettings.mSpeedFactor = std::min(vec.length(), 1.f); vec.normalize(); - float analogueMult = 1.0f; - if (isPlayer) + // TODO: Move this check to mwinput. + // Joystick analogue movement. + // Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used. + if (isPlayer && !isrunning && !sneak && !flying && movementSettings.mSpeedFactor <= 0.5f) + movementSettings.mSpeedFactor *= 2.f; + + static const bool smoothMovement = Settings::Manager::getBool("smooth movement", "Game"); + if (smoothMovement && !isFirstPersonPlayer) { - // TODO: Move this code to mwinput. - // Joystick analogue movement. - float xAxis = std::abs(movementSettings.mPosition[0]); - float yAxis = std::abs(movementSettings.mPosition[1]); - analogueMult = std::max(xAxis, yAxis); + static const float playerTurningCoef = 1.0 / std::max(0.01f, Settings::Manager::getFloat("smooth movement player turning delay", "Game")); + float angle = mPtr.getRefData().getPosition().rot[2]; + osg::Vec2f targetSpeed = Misc::rotateVec2f(osg::Vec2f(vec.x(), vec.y()), -angle) * movementSettings.mSpeedFactor; + osg::Vec2f delta = targetSpeed - mSmoothedSpeed; + float speedDelta = movementSettings.mSpeedFactor - mSmoothedSpeed.length(); + float deltaLen = delta.length(); - // Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used. - if(!isrunning && !sneak && !flying && analogueMult <= 0.5f) - analogueMult *= 2.f; + float maxDelta; + if (std::abs(speedDelta) < deltaLen / 2) + // Turning is smooth for player and less smooth for NPCs (otherwise NPC can miss a path point). + maxDelta = duration * (isPlayer ? playerTurningCoef : 6.f); + else if (isPlayer && speedDelta < -deltaLen / 2) + // As soon as controls are released, mwinput switches player from running to walking. + // So stopping should be instant for player, otherwise it causes a small twitch. + maxDelta = 1; + else // In all other cases speeding up and stopping are smooth. + maxDelta = duration * 3.f; - movementSettings.mSpeedFactor = analogueMult; + if (deltaLen > maxDelta) + delta *= maxDelta / deltaLen; + mSmoothedSpeed += delta; + + osg::Vec2f newSpeed = Misc::rotateVec2f(mSmoothedSpeed, angle); + movementSettings.mSpeedFactor = newSpeed.normalize(); + vec.x() = newSpeed.x(); + vec.y() = newSpeed.y(); + + const float eps = 0.001f; + if (movementSettings.mSpeedFactor < eps) + { + movementSettings.mSpeedFactor = 0; + vec.x() = 0; + vec.y() = 1; + } + else if ((vec.y() < 0) != mIsMovingBackward) + { + if (targetSpeed.length() < eps || (movementSettings.mPosition[1] < 0) == mIsMovingBackward) + vec.y() = mIsMovingBackward ? -eps : eps; + } + vec.normalize(); } float effectiveRotation = rot.z(); + bool canMove = cls.getMaxSpeed(mPtr) > 0; static const bool turnToMovementDirection = Settings::Manager::getBool("turn to movement direction", "Game"); - if (turnToMovementDirection && !isFirstPersonPlayer) + if (!turnToMovementDirection || isFirstPersonPlayer) + movementSettings.mIsStrafing = std::abs(vec.x()) > std::abs(vec.y()) * 2; + else if (canMove) { float targetMovementAngle = vec.y() >= 0 ? std::atan2(-vec.x(), vec.y()) : std::atan2(vec.x(), -vec.y()); movementSettings.mIsStrafing = (stats.getDrawState() != MWMechanics::DrawState_Nothing || inwater) @@ -2009,16 +2044,16 @@ void CharacterController::update(float duration, bool animationOnly) stats.setSideMovementAngle(stats.getSideMovementAngle() + delta); effectiveRotation += delta; } - else - movementSettings.mIsStrafing = std::abs(vec.x()) > std::abs(vec.y()) * 2; mAnimation->setLegsYawRadians(stats.getSideMovementAngle()); if (stats.getDrawState() == MWMechanics::DrawState_Nothing || inwater) mAnimation->setUpperBodyYawRadians(stats.getSideMovementAngle() / 2); else mAnimation->setUpperBodyYawRadians(stats.getSideMovementAngle() / 4); + if (smoothMovement && !isPlayer && !inwater) + mAnimation->setUpperBodyYawRadians(mAnimation->getUpperBodyYawRadians() + mAnimation->getHeadYaw() / 2); - speed = cls.getSpeed(mPtr); + speed = cls.getCurrentSpeed(mPtr); vec.x() *= speed; vec.y() *= speed; @@ -2088,7 +2123,7 @@ void CharacterController::update(float duration, bool animationOnly) } } fatigueLoss *= duration; - fatigueLoss *= analogueMult; + fatigueLoss *= movementSettings.mSpeedFactor; DynamicStat fatigue = cls.getCreatureStats(mPtr).getFatigue(); if (!godmode) @@ -2208,13 +2243,11 @@ void CharacterController::update(float duration, bool animationOnly) : (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack))); } - else if (effectiveRotation != 0.0f) + else { // Do not play turning animation for player if rotation speed is very slow. // Actual threshold should take framerate in account. - float rotationThreshold = 0.f; - if (isPlayer) - rotationThreshold = 0.015 * 60 * duration; + float rotationThreshold = (isPlayer ? 0.015f : 0.001f) * 60 * duration; // It seems only bipedal actors use turning animations. // Also do not use turning animations in the first-person view and when sneaking. @@ -2254,7 +2287,8 @@ void CharacterController::update(float duration, bool animationOnly) swimmingPitch += osg::clampBetween(targetSwimmingPitch - swimmingPitch, -maxSwimPitchDelta, maxSwimPitchDelta); mAnimation->setBodyPitchRadians(swimmingPitch); } - if (inwater && isPlayer && !isFirstPersonPlayer) + static const bool swimUpwardCorrection = Settings::Manager::getBool("swim upward correction", "Game"); + if (inwater && isPlayer && !isFirstPersonPlayer && swimUpwardCorrection) { static const float swimUpwardCoef = Settings::Manager::getFloat("swim upward coef", "Game"); static const float swimForwardCoef = sqrtf(1.0f - swimUpwardCoef * swimUpwardCoef); @@ -2676,11 +2710,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); } } @@ -2729,10 +2763,9 @@ void CharacterController::setVisibility(float visibility) void CharacterController::setAttackTypeBasedOnMovement() { float *move = mPtr.getClass().getMovementSettings(mPtr).mPosition; - - if (move[1] && !move[0]) // forward-backward + if (std::abs(move[1]) > std::abs(move[0]) + 0.2f) // forward-backward mAttackType = "thrust"; - else if (move[0] && !move[1]) //sideway + else if (std::abs(move[0]) > std::abs(move[1]) + 0.2f) // sideway mAttackType = "slash"; else mAttackType = "chop"; @@ -2927,22 +2960,21 @@ void CharacterController::updateHeadTracking(float duration) return; const osg::Vec3f actorDirection = mPtr.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0); - zAngleRadians = std::atan2(direction.x(), direction.y()) - std::atan2(actorDirection.x(), actorDirection.y()); - xAngleRadians = -std::asin(direction.z()); - - wrap(zAngleRadians); - wrap(xAngleRadians); - - xAngleRadians = std::min(xAngleRadians, osg::DegreesToRadians(40.f)); - xAngleRadians = std::max(xAngleRadians, osg::DegreesToRadians(-40.f)); - zAngleRadians = std::min(zAngleRadians, osg::DegreesToRadians(30.f)); - zAngleRadians = std::max(zAngleRadians, osg::DegreesToRadians(-30.f)); + zAngleRadians = std::atan2(actorDirection.x(), actorDirection.y()) - std::atan2(direction.x(), direction.y()); + xAngleRadians = std::asin(direction.z()); } + const double xLimit = osg::DegreesToRadians(40.0); + const double zLimit = osg::DegreesToRadians(30.0); + double zLimitOffset = mAnimation->getUpperBodyYawRadians(); + xAngleRadians = osg::clampBetween(Misc::normalizeAngle(xAngleRadians), -xLimit, xLimit); + zAngleRadians = osg::clampBetween(Misc::normalizeAngle(zAngleRadians), + -zLimit + zLimitOffset, zLimit + zLimitOffset); + float factor = duration*5; factor = std::min(factor, 1.f); - xAngleRadians = (1.f-factor) * mAnimation->getHeadPitch() + factor * (-xAngleRadians); - zAngleRadians = (1.f-factor) * mAnimation->getHeadYaw() + factor * (-zAngleRadians); + xAngleRadians = (1.f-factor) * mAnimation->getHeadPitch() + factor * xAngleRadians; + zAngleRadians = (1.f-factor) * mAnimation->getHeadYaw() + factor * zAngleRadians; mAnimation->setHeadPitch(xAngleRadians); mAnimation->setHeadYaw(zAngleRadians); diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 6092ca724..949affcfd 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -196,6 +196,7 @@ class CharacterController : public MWRender::Animation::TextKeyListener float mTimeUntilWake; bool mIsMovingBackward; + osg::Vec2f mSmoothedSpeed; void setAttackTypeBasedOnMovement(); @@ -240,7 +241,7 @@ public: CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim); virtual ~CharacterController(); - virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map); + void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map) override; // Be careful when to call this, see comment in Actors void updateContinuousVfx(); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 79b8e23de..1d5fe8347 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -683,7 +683,7 @@ namespace MWMechanics return mTimeOfDeath; } - std::map& CreatureStats::getSummonedCreatureMap() + std::map& CreatureStats::getSummonedCreatureMap() { return mSummonedCreatures; } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 5e91a1b5a..b2c0aec98 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -13,6 +13,7 @@ #include "drawstate.hpp" #include +#include namespace ESM { @@ -83,10 +84,8 @@ namespace MWMechanics // The difference between view direction and lower body direction. float mSideMovementAngle; - public: - typedef std::pair SummonKey; // private: - std::map mSummonedCreatures; // + std::map mSummonedCreatures; // // Contains ActorIds of summoned creatures with an expired lifetime that have not been deleted yet. // This may be necessary when the creature is in an inactive cell. @@ -235,7 +234,7 @@ namespace MWMechanics void setBlock(bool value); bool getBlock() const; - std::map& getSummonedCreatureMap(); // + std::map& getSummonedCreatureMap(); // std::vector& getSummonedCreatureGraveyard(); // ActorIds enum Flag diff --git a/apps/openmw/mwmechanics/disease.hpp b/apps/openmw/mwmechanics/disease.hpp index 0c5706775..7933c927e 100644 --- a/apps/openmw/mwmechanics/disease.hpp +++ b/apps/openmw/mwmechanics/disease.hpp @@ -40,7 +40,7 @@ namespace MWMechanics continue; float resist = 0.f; - if (spells.hasCorprusEffect(spell)) + if (Spells::hasCorprusEffect(spell)) resist = 1.f - 0.01f * (actorEffects.get(ESM::MagicEffect::ResistCorprusDisease).getMagnitude() - actorEffects.get(ESM::MagicEffect::WeaknessToCorprusDisease).getMagnitude()); else if (spell->mData.mType == ESM::Spell::ST_Disease) diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index c71516090..1717ba06f 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -281,7 +281,7 @@ namespace MWMechanics float priceMultipler = MWBase::Environment::get().getWorld()->getStore().get().find ("fEnchantmentValueMult")->mValue.getFloat(); int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mEnchanter, static_cast(getEnchantPoints() * priceMultipler), true); price *= getEnchantItemsCount() * getTypeMultiplier(); - return price; + return std::max(1, price); } int Enchanting::getGemCharge() const diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 697e2eda8..c8368101a 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -19,22 +19,22 @@ namespace MWMechanics { /// @return ID of resulting item, or empty if none - inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature) + inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, Misc::Rng::Seed& seed = Misc::Rng::getSeed()) { const std::vector& items = levItem->mList; const MWWorld::Ptr& player = getPlayer(); int playerLevel = player.getClass().getCreatureStats(player).getLevel(); - if (Misc::Rng::roll0to99() < levItem->mChanceNone) + if (Misc::Rng::roll0to99(seed) < levItem->mChanceNone) return std::string(); 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,19 +43,19 @@ 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()) return std::string(); - std::string item = candidates[Misc::Rng::rollDice(candidates.size())]; + std::string item = candidates[Misc::Rng::rollDice(candidates.size(), seed)]; // Vanilla doesn't fail on nonexistent items in levelled lists if (!MWBase::Environment::get().getWorld()->getStore().find(Misc::StringUtils::lowerCase(item))) @@ -74,9 +74,9 @@ namespace MWMechanics else { if (ref.getPtr().getTypeName() == typeid(ESM::ItemLevList).name()) - return getLevelledItem(ref.getPtr().get()->mBase, false); + return getLevelledItem(ref.getPtr().get()->mBase, false, seed); else - return getLevelledItem(ref.getPtr().get()->mBase, true); + return getLevelledItem(ref.getPtr().get()->mBase, true, seed); } } diff --git a/apps/openmw/mwmechanics/linkedeffects.cpp b/apps/openmw/mwmechanics/linkedeffects.cpp index 364358433..b0defac7d 100644 --- a/apps/openmw/mwmechanics/linkedeffects.cpp +++ b/apps/openmw/mwmechanics/linkedeffects.cpp @@ -58,6 +58,7 @@ namespace MWMechanics std::vector absorbEffects; ActiveSpells::ActiveEffect absorbEffect = appliedEffect; absorbEffect.mMagnitude *= -1; + absorbEffect.mEffectIndex = appliedEffect.mEffectIndex; absorbEffects.emplace_back(absorbEffect); // Morrowind negates reflected Absorb spells so the original caster won't be harmed. diff --git a/apps/openmw/mwmechanics/magiceffects.hpp b/apps/openmw/mwmechanics/magiceffects.hpp index 86f5a1804..12735a87f 100644 --- a/apps/openmw/mwmechanics/magiceffects.hpp +++ b/apps/openmw/mwmechanics/magiceffects.hpp @@ -74,8 +74,8 @@ namespace MWMechanics { virtual ~EffectSourceVisitor() { } - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, + virtual void visit (EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, float magnitude, float remainingTime = -1, float totalTime = -1) = 0; }; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index fd8902b37..872a66799 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -83,7 +83,7 @@ namespace MWMechanics // reset creatureStats.setLevel(player->mNpdt.mLevel); - creatureStats.getSpells().clear(); + creatureStats.getSpells().clear(true); creatureStats.modifyMagicEffects(MagicEffects()); for (int i=0; i<27; ++i) @@ -1045,6 +1045,7 @@ namespace MWMechanics void MechanicsManager::confiscateStolenItems(const MWWorld::Ptr &player, const MWWorld::Ptr &targetContainer) { MWWorld::ContainerStore& store = player.getClass().getContainerStore(player); + MWWorld::ContainerStore& containerStore = targetContainer.getClass().getContainerStore(targetContainer); for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) { StolenItemsMap::iterator stolenIt = mStolenItems.find(Misc::StringUtils::lowerCase(it->getCellRef().getRefId())); @@ -1065,7 +1066,7 @@ namespace MWMechanics int toMove = it->getRefData().getCount() - itemCount; - targetContainer.getClass().getContainerStore(targetContainer).add(*it, toMove, targetContainer); + containerStore.add(*it, toMove, targetContainer); store.remove(*it, toMove, player); } // TODO: unhardcode the locklevel diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index c546497bb..28f62b777 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -42,65 +42,65 @@ namespace MWMechanics MechanicsManager(); - virtual void add (const MWWorld::Ptr& ptr) override; + void add (const MWWorld::Ptr& ptr) override; ///< Register an object for management - virtual void remove (const MWWorld::Ptr& ptr) override; + void remove (const MWWorld::Ptr& ptr) override; ///< Deregister an object for management - virtual void updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) override; + void updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) override; ///< Moves an object to a new cell - virtual void drop(const MWWorld::CellStore *cellStore) override; + void drop(const MWWorld::CellStore *cellStore) override; ///< Deregister all objects in the given cell. - virtual void update (float duration, bool paused) override; + void update (float duration, bool paused) override; ///< Update objects /// /// \param paused In game type does not currently advance (this usually means some GUI /// component is up). - virtual void setPlayerName (const std::string& name) override; + void setPlayerName (const std::string& name) override; ///< Set player name. - virtual void setPlayerRace (const std::string& id, bool male, const std::string &head, const std::string &hair) override; + void setPlayerRace (const std::string& id, bool male, const std::string &head, const std::string &hair) override; ///< Set player race. - virtual void setPlayerBirthsign (const std::string& id) override; + void setPlayerBirthsign (const std::string& id) override; ///< Set player birthsign. - virtual void setPlayerClass (const std::string& id) override; + void setPlayerClass (const std::string& id) override; ///< Set player class to stock class. - virtual void setPlayerClass (const ESM::Class& class_) override; + void setPlayerClass (const ESM::Class& class_) override; ///< Set player class to custom class. - virtual void restoreDynamicStats(MWWorld::Ptr actor, double hours, bool sleep) override; + void restoreDynamicStats(MWWorld::Ptr actor, double hours, bool sleep) override; - virtual void rest(double hours, bool sleep) override; + void rest(double hours, bool sleep) override; ///< If the player is sleeping or waiting, this should be called every hour. /// @param sleep is the player sleeping or waiting? - virtual int getHoursToRest() const override; + int getHoursToRest() const override; ///< Calculate how many hours the player needs to rest in order to be fully healed - virtual int getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying) override; + int getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying) override; ///< This is used by every service to determine the price of objects given the trading skills of the player and NPC. - virtual int getDerivedDisposition(const MWWorld::Ptr& ptr, bool addTemporaryDispositionChange = true) override; + int getDerivedDisposition(const MWWorld::Ptr& ptr, bool addTemporaryDispositionChange = true) override; ///< Calculate the diposition of an NPC toward the player. - virtual int countDeaths (const std::string& id) const override; + int countDeaths (const std::string& id) const override; ///< Return the number of deaths for actors with the given ID. - virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, bool& success, float& tempChange, float& permChange) override; + void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type, bool& success, float& tempChange, float& permChange) override; ///< Perform a persuasion action on NPC /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! - virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) override; + bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) override; /// Makes \a ptr fight \a target. Also shouts a combat taunt. - virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) override; + void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) override; /** * @note victim may be empty @@ -109,127 +109,127 @@ namespace MWMechanics * If this parameter is false, it will be determined by a line-of-sight and awareness check. * @return was the crime seen? */ - virtual bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, + bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, OffenseType type, const std::string& factionId="", int arg=0, bool victimAware=false) override; /// @return false if the attack was considered a "friendly hit" and forgiven - virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) override; + bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) override; /// Notify that actor was killed, add a murder bounty if applicable /// @note No-op for non-player attackers - virtual void actorKilled (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) override; + void actorKilled (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) override; /// Utility to check if taking this item is illegal and calling commitCrime if so /// @param container The container the item is in; may be empty for an item in the world - virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container, + void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container, int count, bool alarm = true) override; /// Utility to check if unlocking this object is illegal and calling commitCrime if so - virtual void unlockAttempted (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) override; + void unlockAttempted (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) override; /// Attempt sleeping in a bed. If this is illegal, call commitCrime. /// @return was it illegal, and someone saw you doing it? Also returns fail when enemies are nearby - virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) override; + bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) override; - virtual void forceStateUpdate(const MWWorld::Ptr &ptr) override; + void forceStateUpdate(const MWWorld::Ptr &ptr) override; /// Attempt to play an animation group /// @return Success or error - virtual bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false) override; - virtual void skipAnimation(const MWWorld::Ptr& ptr) override; - virtual bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string &groupName) override; - virtual void persistAnimationStates() override; + bool playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number, bool persist=false) override; + void skipAnimation(const MWWorld::Ptr& ptr) override; + bool checkAnimationPlaying(const MWWorld::Ptr& ptr, const std::string &groupName) override; + void persistAnimationStates() override; /// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently /// paused we may want to do it manually (after equipping permanent enchantment) - virtual void updateMagicEffects (const MWWorld::Ptr& ptr) override; + void updateMagicEffects (const MWWorld::Ptr& ptr) override; - virtual void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector& objects) override; - virtual void getActorsInRange(const osg::Vec3f &position, float radius, std::vector &objects) override; + void getObjectsInRange (const osg::Vec3f& position, float radius, std::vector& objects) override; + void getActorsInRange(const osg::Vec3f &position, float radius, std::vector &objects) override; /// Check if there are actors in selected range - virtual bool isAnyActorInRange(const osg::Vec3f &position, float radius) override; + bool isAnyActorInRange(const osg::Vec3f &position, float radius) override; - virtual std::list getActorsSidingWith(const MWWorld::Ptr& actor) override; - virtual std::list getActorsFollowing(const MWWorld::Ptr& actor) override; - virtual std::list getActorsFollowingIndices(const MWWorld::Ptr& actor) override; + std::list getActorsSidingWith(const MWWorld::Ptr& actor) override; + std::list getActorsFollowing(const MWWorld::Ptr& actor) override; + std::list getActorsFollowingIndices(const MWWorld::Ptr& actor) override; - virtual std::list getActorsFighting(const MWWorld::Ptr& actor) override; - virtual std::list getEnemiesNearby(const MWWorld::Ptr& actor) override; + std::list getActorsFighting(const MWWorld::Ptr& actor) override; + std::list getEnemiesNearby(const MWWorld::Ptr& actor) override; /// Recursive version of getActorsFollowing - virtual void getActorsFollowing(const MWWorld::Ptr& actor, std::set& out) override; + void getActorsFollowing(const MWWorld::Ptr& actor, std::set& out) override; /// Recursive version of getActorsSidingWith - virtual void getActorsSidingWith(const MWWorld::Ptr& actor, std::set& out) override; + void getActorsSidingWith(const MWWorld::Ptr& actor, std::set& out) override; - virtual bool toggleAI() override; - virtual bool isAIActive() override; + bool toggleAI() override; + bool isAIActive() override; - virtual void playerLoaded() override; + void playerLoaded() override; - virtual bool onOpen(const MWWorld::Ptr& ptr) override; - virtual void onClose(const MWWorld::Ptr& ptr) override; + bool onOpen(const MWWorld::Ptr& ptr) override; + void onClose(const MWWorld::Ptr& ptr) override; - virtual int countSavedGameRecords() const override; + int countSavedGameRecords() const override; - virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const override; + void write (ESM::ESMWriter& writer, Loading::Listener& listener) const override; - virtual void readRecord (ESM::ESMReader& reader, uint32_t type) override; + void readRecord (ESM::ESMReader& reader, uint32_t type) override; - virtual void clear() override; + void clear() override; - virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) override; + bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) override; - virtual void resurrect(const MWWorld::Ptr& ptr) override; + void resurrect(const MWWorld::Ptr& ptr) override; - virtual bool isCastingSpell (const MWWorld::Ptr& ptr) const override; + bool isCastingSpell (const MWWorld::Ptr& ptr) const override; - virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const override; + bool isReadyToBlock (const MWWorld::Ptr& ptr) const override; /// Is \a ptr casting spell or using weapon now? - virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const override; + bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const override; - virtual void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell=false) override; + void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell=false) override; void processChangedSettings(const Settings::CategorySettingVector& settings) override; - virtual float getActorsProcessingRange() const override; + float getActorsProcessingRange() const override; - virtual void notifyDied(const MWWorld::Ptr& actor) override; + void notifyDied(const MWWorld::Ptr& actor) override; /// Check if the target actor was detected by an observer /// If the observer is a non-NPC, check all actors in AI processing distance as observers - virtual bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) override; + bool isActorDetected(const MWWorld::Ptr& actor, const MWWorld::Ptr& observer) override; - virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) override; + void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) override; /// List the owners that the player has stolen this item from (the owner can be an NPC or a faction). /// - virtual std::vector > getStolenItemOwners(const std::string& itemid) override; + std::vector > getStolenItemOwners(const std::string& itemid) override; /// Has the player stolen this item from the given owner? - virtual bool isItemStolenFrom(const std::string& itemid, const MWWorld::Ptr& ptr) override; + bool isItemStolenFrom(const std::string& itemid, const MWWorld::Ptr& ptr) override; - virtual bool isBoundItem(const MWWorld::Ptr& item) override; + bool isBoundItem(const MWWorld::Ptr& item) override; /// @return is \a ptr allowed to take/use \a target or is it a crime? - virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) override; + bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) override; - virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) override; - virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) override; + void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) override; + void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) override; - virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) override; + void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) override; - virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) override; + void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) override; - virtual bool isAttackPreparing(const MWWorld::Ptr& ptr) override; - virtual bool isRunning(const MWWorld::Ptr& ptr) override; - virtual bool isSneaking(const MWWorld::Ptr& ptr) override; + bool isAttackPreparing(const MWWorld::Ptr& ptr) override; + bool isRunning(const MWWorld::Ptr& ptr) override; + bool isSneaking(const MWWorld::Ptr& ptr) override; - virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const override; + void reportStats(unsigned int frameNumber, osg::Stats& stats) const override; - virtual int getGreetingTimer(const MWWorld::Ptr& ptr) const override; - virtual float getAngleToPlayer(const MWWorld::Ptr& ptr) const override; - virtual GreetingState getGreetingState(const MWWorld::Ptr& ptr) const override; - virtual bool isTurningToPlayer(const MWWorld::Ptr& ptr) const override; + int getGreetingTimer(const MWWorld::Ptr& ptr) const override; + float getAngleToPlayer(const MWWorld::Ptr& ptr) const override; + GreetingState getGreetingState(const MWWorld::Ptr& ptr) const override; + bool isTurningToPlayer(const MWWorld::Ptr& ptr) const override; - virtual void restoreStatsAfterCorprus(const MWWorld::Ptr& actor, const std::string& sourceId) override; + void restoreStatsAfterCorprus(const MWWorld::Ptr& actor, const std::string& sourceId) override; private: bool canCommitCrimeAgainst(const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker); diff --git a/apps/openmw/mwmechanics/movement.hpp b/apps/openmw/mwmechanics/movement.hpp index 86b970e60..57e106cde 100644 --- a/apps/openmw/mwmechanics/movement.hpp +++ b/apps/openmw/mwmechanics/movement.hpp @@ -8,8 +8,14 @@ namespace MWMechanics /// Desired movement for an actor struct Movement { + // Desired movement. Direction is relative to the current orientation. + // Length of the vector controls desired speed. 0 - stay, 0.5 - half-speed, 1.0 - max speed. float mPosition[3]; + // Desired rotation delta (euler angles). float mRotation[3]; + + // Controlled by CharacterController, should not be changed from other places. + // These fields can not be private fields in CharacterController, because Actor::getCurrentSpeed uses it. float mSpeedFactor; bool mIsStrafing; 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..88325ee7c 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 @@ -126,7 +122,7 @@ namespace MWMechanics if (mWalkState != WalkState::Evade) { - const float distSameSpot = DIST_SAME_SPOT * actor.getClass().getSpeed(actor) * duration; + const float distSameSpot = DIST_SAME_SPOT * actor.getClass().getCurrentSpeed(actor) * duration; const float prevDistance = (destination - mPrev).length(); const float currentDistance = (destination - position).length(); const float movedDistance = prevDistance - currentDistance; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 4d4b5be51..a82dcf717 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -88,6 +88,24 @@ namespace const auto halfExtents = world->getHalfExtents(actor); return 2.0 * halfExtents.z(); } + + // Returns true if turn in `p2` is less than 10 degrees and all the 3 points are almost on one line. + bool isAlmostStraight(const osg::Vec3f& p1, const osg::Vec3f& p2, const osg::Vec3f& p3, float pointTolerance) { + osg::Vec3f v1 = p1 - p2; + osg::Vec3f v3 = p3 - p2; + v1.z() = v3.z() = 0; + float dotProduct = v1.x() * v3.x() + v1.y() * v3.y(); + float crossProduct = v1.x() * v3.y() - v1.y() * v3.x(); + + // Check that the angle between v1 and v3 is less or equal than 10 degrees. + static const float cos170 = std::cos(osg::PI / 180 * 170); + bool checkAngle = dotProduct <= cos170 * v1.length() * v3.length(); + + // Check that distance from p2 to the line (p1, p3) is less or equal than `pointTolerance`. + bool checkDist = std::abs(crossProduct) <= pointTolerance * (p3 - p1).length() * 2; + + return checkAngle && checkDist; + } } namespace MWMechanics @@ -286,6 +304,11 @@ namespace MWMechanics while (mPath.size() > 1 && sqrDistanceIgnoreZ(mPath.front(), position) < pointTolerance * pointTolerance) mPath.pop_front(); + while (mPath.size() > 2 && isAlmostStraight(mPath[0], mPath[1], mPath[2], pointTolerance)) + mPath.erase(mPath.begin() + 1); + if (mPath.size() > 1 && isAlmostStraight(position, mPath[0], mPath[1], pointTolerance)) + mPath.pop_front(); + if (mPath.size() == 1 && sqrDistanceIgnoreZ(mPath.front(), position) < destinationTolerance * destinationTolerance) mPath.pop_front(); } diff --git a/apps/openmw/mwmechanics/repair.cpp b/apps/openmw/mwmechanics/repair.cpp index 389d00d85..81886ed9b 100644 --- a/apps/openmw/mwmechanics/repair.cpp +++ b/apps/openmw/mwmechanics/repair.cpp @@ -27,7 +27,8 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair) // reduce number of uses left int uses = mTool.getClass().getItemHealth(mTool); - mTool.getCellRef().setCharge(uses-1); + uses -= std::min(uses, 1); + mTool.getCellRef().setCharge(uses); MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index 001375feb..e642a7bb4 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -33,6 +33,10 @@ namespace MWMechanics !lock.getClass().hasToolTip(lock)) //If it's unlocked or can not be unlocked back out immediately return; + int uses = lockpick.getClass().getItemHealth(lockpick); + if (uses == 0) + return; + int lockStrength = lock.getCellRef().getLockLevel(); float pickQuality = lockpick.get()->mBase->mData.mQuality; @@ -61,9 +65,7 @@ namespace MWMechanics resultMessage = "#{sLockFail}"; } - int uses = lockpick.getClass().getItemHealth(lockpick); - --uses; - lockpick.getCellRef().setCharge(uses); + lockpick.getCellRef().setCharge(--uses); if (!uses) lockpick.getContainerStore()->remove(lockpick, 1, mActor); } @@ -71,7 +73,11 @@ namespace MWMechanics void Security::probeTrap(const MWWorld::Ptr &trap, const MWWorld::Ptr &probe, std::string& resultMessage, std::string& resultSound) { - if (trap.getCellRef().getTrap() == "") + if (trap.getCellRef().getTrap().empty()) + return; + + int uses = probe.getClass().getItemHealth(probe); + if (uses == 0) return; float probeQuality = probe.get()->mBase->mData.mQuality; @@ -104,9 +110,7 @@ namespace MWMechanics resultMessage = "#{sTrapFail}"; } - int uses = probe.getClass().getItemHealth(probe); - --uses; - probe.getCellRef().setCharge(uses); + probe.getCellRef().setCharge(--uses); if (!uses) probe.getContainerStore()->remove(probe, 1, mActor); } diff --git a/apps/openmw/mwmechanics/spellabsorption.cpp b/apps/openmw/mwmechanics/spellabsorption.cpp index f38fd78e2..bab290fda 100644 --- a/apps/openmw/mwmechanics/spellabsorption.cpp +++ b/apps/openmw/mwmechanics/spellabsorption.cpp @@ -12,6 +12,7 @@ #include "../mwworld/inventorystore.hpp" #include "creaturestats.hpp" +#include "spellutil.hpp" namespace MWMechanics { @@ -23,9 +24,9 @@ namespace MWMechanics GetAbsorptionProbability() = default; - virtual void visit (MWMechanics::EffectKey key, - const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, - float magnitude, float /*remainingTime*/, float /*totalTime*/) + void visit (MWMechanics::EffectKey key, int /*effectIndex*/, + const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, + float magnitude, float /*remainingTime*/, float /*totalTime*/) override { if (key.mId == ESM::MagicEffect::SpellAbsorption) { @@ -43,9 +44,9 @@ namespace MWMechanics } }; - bool absorbSpell (const ESM::Spell* spell, const MWWorld::Ptr& caster, const MWWorld::Ptr& target) + bool absorbSpell (const std::string& spellId, const MWWorld::Ptr& caster, const MWWorld::Ptr& target) { - if (!spell || caster == target || !target.getClass().isActor()) + if (spellId.empty() || target.isEmpty() || caster == target || !target.getClass().isActor()) return false; CreatureStats& stats = target.getClass().getCreatureStats(target); @@ -62,13 +63,27 @@ namespace MWMechanics if (Misc::Rng::roll0to99() >= chance) return false; - const ESM::Static* absorbStatic = MWBase::Environment::get().getWorld()->getStore().get().find("VFX_Absorb"); + const auto& esmStore = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Static* absorbStatic = esmStore.get().find("VFX_Absorb"); MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(target); if (animation && !absorbStatic->mModel.empty()) animation->addEffect( "meshes\\" + absorbStatic->mModel, ESM::MagicEffect::SpellAbsorption, false, std::string()); + const ESM::Spell* spell = esmStore.get().search(spellId); + int spellCost = 0; + if (spell) + { + spellCost = spell->mData.mCost; + } + else + { + const ESM::Enchantment* enchantment = esmStore.get().search(spellId); + if (enchantment) + spellCost = getEffectiveEnchantmentCastCost(static_cast(enchantment->mData.mCost), caster); + } + // Magicka is increased by the cost of the spell DynamicStat magicka = stats.getMagicka(); - magicka.setCurrent(magicka.getCurrent() + spell->mData.mCost); + magicka.setCurrent(magicka.getCurrent() + spellCost); stats.setMagicka(magicka); return true; } diff --git a/apps/openmw/mwmechanics/spellabsorption.hpp b/apps/openmw/mwmechanics/spellabsorption.hpp index 147090d96..0fe501df9 100644 --- a/apps/openmw/mwmechanics/spellabsorption.hpp +++ b/apps/openmw/mwmechanics/spellabsorption.hpp @@ -1,10 +1,7 @@ #ifndef MWMECHANICS_SPELLABSORPTION_H #define MWMECHANICS_SPELLABSORPTION_H -namespace ESM -{ - struct Spell; -} +#include namespace MWWorld { @@ -14,7 +11,7 @@ namespace MWWorld namespace MWMechanics { // Try to absorb a spell based on the magnitude of every Spell Absorption effect source on the target. - bool absorbSpell(const ESM::Spell* spell, const MWWorld::Ptr& caster, const MWWorld::Ptr& target); + bool absorbSpell(const std::string& spellId, const MWWorld::Ptr& caster, const MWWorld::Ptr& target); } #endif diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 9f7108239..81b3a353d 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -119,10 +119,11 @@ namespace MWMechanics // effects, we display a "can't re-cast" message // Try absorbing the spell. Some handling must still happen for absorbed effects. - bool absorbed = absorbSpell(spell, caster, target); + bool absorbed = absorbSpell(mId, caster, target); + int currentEffectIndex = 0; for (std::vector::const_iterator effectIt (effects.mList.begin()); - !target.isEmpty() && effectIt != effects.mList.end(); ++effectIt) + !target.isEmpty() && effectIt != effects.mList.end(); ++effectIt, ++currentEffectIndex) { if (effectIt->mRange != range) continue; @@ -189,6 +190,7 @@ namespace MWMechanics effect.mArg = MWMechanics::EffectKey(*effectIt).mArg; effect.mMagnitude = magnitude; effect.mTimeLeft = 0.f; + effect.mEffectIndex = currentEffectIndex; // Avoid applying absorb effects if the caster is the target // We still need the spell to be added @@ -268,7 +270,8 @@ namespace MWMechanics if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor()) { CreatureStats& targetStats = target.getClass().getCreatureStats(target); - std::map::iterator findCreature = targetStats.getSummonedCreatureMap().find(std::make_pair(effectIt->mEffectID, mId)); + ESM::SummonKey key(effectIt->mEffectID, mId, currentEffectIndex); + auto findCreature = targetStats.getSummonedCreatureMap().find(key); if (findCreature != targetStats.getSummonedCreatureMap().end()) { MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(target, findCreature->second); diff --git a/apps/openmw/mwmechanics/spelllist.cpp b/apps/openmw/mwmechanics/spelllist.cpp new file mode 100644 index 000000000..891b28619 --- /dev/null +++ b/apps/openmw/mwmechanics/spelllist.cpp @@ -0,0 +1,175 @@ +#include "spelllist.hpp" + +#include + +#include +#include + +#include "spells.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/esmstore.hpp" + +namespace +{ + template + const std::vector getSpellList(const std::string& id) + { + return MWBase::Environment::get().getWorld()->getStore().get().find(id)->mSpells.mList; + } + + template + bool withBaseRecord(const std::string& id, const std::function&)>& function) + { + T copy = *MWBase::Environment::get().getWorld()->getStore().get().find(id); + bool changed = function(copy.mSpells.mList); + if(changed) + MWBase::Environment::get().getWorld()->createOverrideRecord(copy); + return changed; + } +} + +namespace MWMechanics +{ + SpellList::SpellList(const std::string& id, int type) : mId(id), mType(type) {} + + bool SpellList::withBaseRecord(const std::function&)>& function) + { + switch(mType) + { + case ESM::REC_CREA: + return ::withBaseRecord(mId, function); + case ESM::REC_NPC_: + return ::withBaseRecord(mId, function); + default: + throw std::logic_error("failed to update base record for " + mId); + } + } + + const std::vector SpellList::getSpells() const + { + switch(mType) + { + case ESM::REC_CREA: + return getSpellList(mId); + case ESM::REC_NPC_: + return getSpellList(mId); + default: + throw std::logic_error("failed to get spell list for " + mId); + } + } + + const ESM::Spell* SpellList::getSpell(const std::string& id) + { + return MWBase::Environment::get().getWorld()->getStore().get().find(id); + } + + void SpellList::add (const ESM::Spell* spell) + { + auto& id = spell->mId; + bool changed = withBaseRecord([&] (auto& spells) + { + for(auto it : spells) + { + if(Misc::StringUtils::ciEqual(id, it)) + return false; + } + spells.push_back(id); + return true; + }); + if(changed) + { + for(auto listener : mListeners) + listener->addSpell(spell); + } + } + + void SpellList::remove (const ESM::Spell* spell) + { + auto& id = spell->mId; + bool changed = withBaseRecord([&] (auto& spells) + { + for(auto it = spells.begin(); it != spells.end(); it++) + { + if(Misc::StringUtils::ciEqual(id, *it)) + { + spells.erase(it); + return true; + } + } + return false; + }); + if(changed) + { + for(auto listener : mListeners) + listener->removeSpell(spell); + } + } + + void SpellList::removeAll (const std::vector& ids) + { + bool changed = withBaseRecord([&] (auto& spells) + { + const auto it = std::remove_if(spells.begin(), spells.end(), [&] (const auto& spell) + { + const auto isSpell = [&] (const auto& id) { return Misc::StringUtils::ciEqual(spell, id); }; + return ids.end() != std::find_if(ids.begin(), ids.end(), isSpell); + }); + if (it == spells.end()) + return false; + spells.erase(it, spells.end()); + return true; + }); + if(changed) + { + for(auto listener : mListeners) + { + for(auto& id : ids) + { + const auto spell = getSpell(id); + listener->removeSpell(spell); + } + } + } + } + + void SpellList::clear() + { + bool changed = withBaseRecord([] (auto& spells) + { + if(spells.empty()) + return false; + spells.clear(); + return true; + }); + if(changed) + { + for(auto listener : mListeners) + listener->removeAllSpells(); + } + } + + void SpellList::addListener(Spells* spells) + { + for(const auto ptr : mListeners) + { + if(ptr == spells) + return; + } + mListeners.push_back(spells); + } + + void SpellList::removeListener(Spells* spells) + { + for(auto it = mListeners.begin(); it != mListeners.end(); it++) + { + if(*it == spells) + { + mListeners.erase(it); + break; + } + } + } +} diff --git a/apps/openmw/mwmechanics/spelllist.hpp b/apps/openmw/mwmechanics/spelllist.hpp new file mode 100644 index 000000000..b01722fe8 --- /dev/null +++ b/apps/openmw/mwmechanics/spelllist.hpp @@ -0,0 +1,68 @@ +#ifndef GAME_MWMECHANICS_SPELLLIST_H +#define GAME_MWMECHANICS_SPELLLIST_H + +#include +#include +#include +#include +#include + +#include + +#include "magiceffects.hpp" + +namespace ESM +{ + struct SpellState; +} + +namespace MWMechanics +{ + struct SpellParams + { + std::map mEffectRands; // + std::set mPurgedEffects; // indices of purged effects + }; + + class Spells; + + /// Multiple instances of the same actor share the same spell list in Morrowind. + /// The most obvious result of this is that adding a spell or ability to one instance adds it to all instances. + /// @note The original game will only update visual effects associated with any added abilities for the originally targeted actor, + /// changing cells applies the update to all actors. + /// Aside from sharing the same active spell list, changes made to this list are also written to the actor's base record. + /// Interestingly, it is not just scripted changes that are persisted to the base record. Curing one instance's disease will cure all instances. + /// @note The original game is inconsistent in persisting this example; + /// saving and loading the game might reapply the cured disease depending on which instance was cured. + class SpellList + { + const std::string mId; + const int mType; + std::vector mListeners; + + bool withBaseRecord(const std::function&)>& function); + public: + SpellList(const std::string& id, int type); + + /// Get spell from ID, throws exception if not found + static const ESM::Spell* getSpell(const std::string& id); + + void add (const ESM::Spell* spell); + ///< Adding a spell that is already listed in *this is a no-op. + + void remove (const ESM::Spell* spell); + + void removeAll(const std::vector& spells); + + void clear(); + ///< Remove all spells of all types. + + void addListener(Spells* spells); + + void removeListener(Spells* spells); + + const std::vector getSpells() const; + }; +} + +#endif diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index ae7454f19..d292c015d 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -1,8 +1,10 @@ #include "spells.hpp" +#include #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -22,46 +24,44 @@ namespace MWMechanics { } - Spells::TIterator Spells::begin() const + std::map::const_iterator Spells::begin() const { return mSpells.begin(); } - Spells::TIterator Spells::end() const + std::map::const_iterator Spells::end() const { return mSpells.end(); } - const ESM::Spell* Spells::getSpell(const std::string& id) const - { - return MWBase::Environment::get().getWorld()->getStore().get().find(id); - } - void Spells::rebuildEffects() const { mEffects = MagicEffects(); mSourcedEffects.clear(); - for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) + for (const auto& iter : mSpells) { - const ESM::Spell *spell = iter->first; + const ESM::Spell *spell = iter.first; if (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight || spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse) { int i=0; - for (std::vector::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it) + for (const auto& effect : spell->mEffects.mList) { - if (iter->second.mPurgedEffects.find(i) != iter->second.mPurgedEffects.end()) + if (iter.second.mPurgedEffects.find(i) != iter.second.mPurgedEffects.end()) + { + ++i; continue; // effect was purged + } float random = 1.f; - if (iter->second.mEffectRands.find(i) != iter->second.mEffectRands.end()) - random = iter->second.mEffectRands.at(i); + if (iter.second.mEffectRands.find(i) != iter.second.mEffectRands.end()) + random = iter.second.mEffectRands.at(i); - float magnitude = it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random; - mEffects.add (*it, magnitude); - mSourcedEffects[spell].add(MWMechanics::EffectKey(*it), magnitude); + float magnitude = effect.mMagnMin + (effect.mMagnMax - effect.mMagnMin) * random; + mEffects.add (effect, magnitude); + mSourcedEffects[spell].add(MWMechanics::EffectKey(effect), magnitude); ++i; } @@ -71,7 +71,7 @@ namespace MWMechanics bool Spells::hasSpell(const std::string &spell) const { - return hasSpell(getSpell(spell)); + return hasSpell(SpellList::getSpell(spell)); } bool Spells::hasSpell(const ESM::Spell *spell) const @@ -80,6 +80,16 @@ namespace MWMechanics } void Spells::add (const ESM::Spell* spell) + { + mSpellList->add(spell); + } + + void Spells::add (const std::string& spellId) + { + add(SpellList::getSpell(spellId)); + } + + void Spells::addSpell(const ESM::Spell* spell) { if (mSpells.find (spell)==mSpells.end()) { @@ -101,31 +111,31 @@ namespace MWMechanics SpellParams params; params.mEffectRands = random; - mSpells.insert (std::make_pair (spell, params)); + mSpells.emplace(spell, params); mSpellsChanged = true; } } - void Spells::add (const std::string& spellId) - { - add(getSpell(spellId)); - } - void Spells::remove (const std::string& spellId) { - const ESM::Spell* spell = getSpell(spellId); - TContainer::iterator iter = mSpells.find (spell); - - if (iter!=mSpells.end()) - { - mSpells.erase (iter); - mSpellsChanged = true; - } + const auto spell = SpellList::getSpell(spellId); + removeSpell(spell); + mSpellList->remove(spell); if (spellId==mSelectedSpell) mSelectedSpell.clear(); } + void Spells::removeSpell(const ESM::Spell* spell) + { + const auto it = mSpells.find(spell); + if(it != mSpells.end()) + { + mSpells.erase(it); + mSpellsChanged = true; + } + } + MagicEffects Spells::getMagicEffects() const { if (mSpellsChanged) { @@ -135,12 +145,19 @@ namespace MWMechanics return mEffects; } - void Spells::clear() + void Spells::removeAllSpells() { mSpells.clear(); mSpellsChanged = true; } + void Spells::clear(bool modifyBase) + { + removeAllSpells(); + if(modifyBase) + mSpellList->clear(); + } + void Spells::setSelectedSpell (const std::string& spellId) { mSelectedSpell = spellId; @@ -166,101 +183,78 @@ namespace MWMechanics return false; } - bool Spells::hasCommonDisease() const + bool Spells::hasDisease(const ESM::Spell::SpellType type) const { - for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) + for (const auto& iter : mSpells) { - const ESM::Spell *spell = iter->first; - if (spell->mData.mType == ESM::Spell::ST_Disease) + const ESM::Spell *spell = iter.first; + if (spell->mData.mType == type) return true; } return false; } + bool Spells::hasCommonDisease() const + { + return hasDisease(ESM::Spell::ST_Disease); + } + bool Spells::hasBlightDisease() const { - for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) + return hasDisease(ESM::Spell::ST_Blight); + } + + void Spells::purge(const SpellFilter& filter) + { + std::vector purged; + for (auto iter = mSpells.begin(); iter!=mSpells.end();) { const ESM::Spell *spell = iter->first; - if (spell->mData.mType == ESM::Spell::ST_Blight) - return true; + if (filter(spell)) + { + mSpells.erase(iter++); + purged.push_back(spell->mId); + mSpellsChanged = true; + } + else + ++iter; } - - return false; + if(!purged.empty()) + mSpellList->removeAll(purged); } void Spells::purgeCommonDisease() { - for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();) - { - const ESM::Spell *spell = iter->first; - if (spell->mData.mType == ESM::Spell::ST_Disease) - { - mSpells.erase(iter++); - mSpellsChanged = true; - } - else - ++iter; - } + purge([](auto spell) { return spell->mData.mType == ESM::Spell::ST_Disease; }); } void Spells::purgeBlightDisease() { - for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();) - { - const ESM::Spell *spell = iter->first; - if (spell->mData.mType == ESM::Spell::ST_Blight && !hasCorprusEffect(spell)) - { - mSpells.erase(iter++); - mSpellsChanged = true; - } - else - ++iter; - } + purge([](auto spell) { return spell->mData.mType == ESM::Spell::ST_Blight && !hasCorprusEffect(spell); }); } void Spells::purgeCorprusDisease() { - for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();) - { - const ESM::Spell *spell = iter->first; - if (hasCorprusEffect(spell)) - { - mSpells.erase(iter++); - mSpellsChanged = true; - } - else - ++iter; - } + purge(&hasCorprusEffect); } void Spells::purgeCurses() { - for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();) - { - const ESM::Spell *spell = iter->first; - if (spell->mData.mType == ESM::Spell::ST_Curse) - { - mSpells.erase(iter++); - mSpellsChanged = true; - } - else - ++iter; - } + purge([](auto spell) { return spell->mData.mType == ESM::Spell::ST_Curse; }); } void Spells::removeEffects(const std::string &id) { if (isSpellActive(id)) { - for (TContainer::iterator spell = mSpells.begin(); spell != mSpells.end(); ++spell) + for (auto& spell : mSpells) { - if (spell->first == getSpell(id)) + if (spell.first == SpellList::getSpell(id)) { - for (long unsigned int i = 0; i != spell->first->mEffects.mList.size(); i++) + for (long unsigned int i = 0; i != spell.first->mEffects.mList.size(); i++) { - spell->second.mPurgedEffects.insert(i); + spell.second.mPurgedEffects.insert(i); } } } @@ -276,23 +270,22 @@ namespace MWMechanics mSpellsChanged = false; } - for (std::map::const_iterator it = mSourcedEffects.begin(); - it != mSourcedEffects.end(); ++it) + for (const auto& it : mSourcedEffects) { - const ESM::Spell * spell = it->first; - for (MagicEffects::Collection::const_iterator effectIt = it->second.begin(); - effectIt != it->second.end(); ++effectIt) + const ESM::Spell * spell = it.first; + for (const auto& effectIt : it.second) { - visitor.visit(effectIt->first, spell->mName, spell->mId, -1, effectIt->second.getMagnitude()); + // FIXME: since Spells merges effects with the same ID, there is no sense to use multiple effects with same ID here + visitor.visit(effectIt.first, -1, spell->mName, spell->mId, -1, effectIt.second.getMagnitude()); } } } bool Spells::hasCorprusEffect(const ESM::Spell *spell) { - for (std::vector::const_iterator effectIt = spell->mEffects.mList.begin(); effectIt != spell->mEffects.mList.end(); ++effectIt) + for (const auto& effectIt : spell->mEffects.mList) { - if (effectIt->mEffectID == ESM::MagicEffect::Corprus) + if (effectIt.mEffectID == ESM::MagicEffect::Corprus) { return true; } @@ -302,14 +295,14 @@ namespace MWMechanics void Spells::purgeEffect(int effectId) { - for (TContainer::iterator spellIt = mSpells.begin(); spellIt != mSpells.end(); ++spellIt) + for (auto& spellIt : mSpells) { int i = 0; - for (std::vector::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt) + for (auto& effectIt : spellIt.first->mEffects.mList) { - if (effectIt->mEffectID == effectId) + if (effectIt.mEffectID == effectId) { - spellIt->second.mPurgedEffects.insert(i); + spellIt.second.mPurgedEffects.insert(i); mSpellsChanged = true; } ++i; @@ -319,30 +312,31 @@ namespace MWMechanics void Spells::purgeEffect(int effectId, const std::string & sourceId) { - const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get().find(sourceId); - TContainer::iterator spellIt = mSpells.find(spell); + // Effect source may be not a spell + const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get().search(sourceId); + if (spell == nullptr) + return; + + auto spellIt = mSpells.find(spell); if (spellIt == mSpells.end()) return; - int i = 0; - for (std::vector::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt) + int index = 0; + for (auto& effectIt : spellIt->first->mEffects.mList) { - if (effectIt->mEffectID == effectId) + if (effectIt.mEffectID == effectId) { - spellIt->second.mPurgedEffects.insert(i); + spellIt->second.mPurgedEffects.insert(index); mSpellsChanged = true; } - ++i; + ++index; } } bool Spells::canUsePower(const ESM::Spell* spell) const { - std::map::const_iterator it = mUsedPowers.find(spell); - if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp()) - return true; - else - return false; + const auto it = mUsedPowers.find(spell); + return it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp(); } void Spells::usePower(const ESM::Spell* spell) @@ -352,6 +346,8 @@ namespace MWMechanics void Spells::readState(const ESM::SpellState &state, CreatureStats* creatureStats) { + const auto& baseSpells = mSpellList->getSpells(); + for (ESM::SpellState::TContainer::const_iterator it = state.mSpells.begin(); it != state.mSpells.end(); ++it) { // Discard spells that are no longer available due to changed content files @@ -365,6 +361,13 @@ namespace MWMechanics mSelectedSpell = it->first; } } + // Add spells from the base record + for(const std::string& id : baseSpells) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(id); + if(spell) + addSpell(spell); + } for (std::map::const_iterator it = state.mUsedPowers.begin(); it != state.mUsedPowers.end(); ++it) { @@ -436,17 +439,50 @@ namespace MWMechanics void Spells::writeState(ESM::SpellState &state) const { - for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) + const auto& baseSpells = mSpellList->getSpells(); + for (const auto& it : mSpells) { - ESM::SpellState::SpellParams params; - params.mEffectRands = it->second.mEffectRands; - params.mPurgedEffects = it->second.mPurgedEffects; - state.mSpells.insert(std::make_pair(it->first->mId, params)); + // Don't save spells and powers stored in the base record + if((it.first->mData.mType != ESM::Spell::ST_Spell && it.first->mData.mType != ESM::Spell::ST_Power) || + std::find(baseSpells.begin(), baseSpells.end(), it.first->mId) == baseSpells.end()) + { + ESM::SpellState::SpellParams params; + params.mEffectRands = it.second.mEffectRands; + params.mPurgedEffects = it.second.mPurgedEffects; + state.mSpells.emplace(it.first->mId, params); + } } state.mSelectedSpell = mSelectedSpell; - for (std::map::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it) - state.mUsedPowers[it->first->mId] = it->second.toEsm(); + for (const auto& it : mUsedPowers) + state.mUsedPowers[it.first->mId] = it.second.toEsm(); + } + + bool Spells::setSpells(const std::string& actorId) + { + bool result; + std::tie(mSpellList, result) = MWBase::Environment::get().getWorld()->getStore().getSpellList(actorId); + mSpellList->addListener(this); + addAllToInstance(mSpellList->getSpells()); + return result; + } + + void Spells::addAllToInstance(const std::vector& spells) + { + for(const std::string& id : spells) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(id); + if(spell) + addSpell(spell); + else + Log(Debug::Warning) << "Warning: ignoring nonexistent spell '" << id << "'"; + } + } + + Spells::~Spells() + { + if(mSpellList) + mSpellList->removeListener(this); } } diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index a4a599f8b..2f4049d2e 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -1,22 +1,19 @@ #ifndef GAME_MWMECHANICS_SPELLS_H #define GAME_MWMECHANICS_SPELLS_H +#include #include #include #include +#include -#include - -#include "../mwworld/ptr.hpp" #include "../mwworld/timestamp.hpp" #include "magiceffects.hpp" - +#include "spelllist.hpp" namespace ESM { - struct Spell; - struct SpellState; } @@ -32,37 +29,36 @@ namespace MWMechanics /// diseases. It also keeps track of used powers (which can only be used every 24h). class Spells { - public: - - typedef const ESM::Spell* SpellKey; - struct SpellParams - { - std::map mEffectRands; // - std::set mPurgedEffects; // indices of purged effects - }; - - typedef std::map TContainer; - typedef TContainer::const_iterator TIterator; - - private: - TContainer mSpells; + std::shared_ptr mSpellList; + std::map mSpells; // Note: this is the spell that's about to be cast, *not* the spell selected in the GUI (which may be different) std::string mSelectedSpell; - std::map mUsedPowers; + std::map mUsedPowers; mutable bool mSpellsChanged; mutable MagicEffects mEffects; - mutable std::map mSourcedEffects; + mutable std::map mSourcedEffects; void rebuildEffects() const; - /// Get spell from ID, throws exception if not found - const ESM::Spell* getSpell(const std::string& id) const; + bool hasDisease(const ESM::Spell::SpellType type) const; + using SpellFilter = bool (*)(const ESM::Spell*); + void purge(const SpellFilter& filter); + + void addSpell(const ESM::Spell* spell); + void removeSpell(const ESM::Spell* spell); + void removeAllSpells(); + + friend class SpellList; public: + using TIterator = std::map::const_iterator; + Spells(); + ~Spells(); + static bool hasCorprusEffect(const ESM::Spell *spell); void purgeEffect(int effectId); @@ -96,7 +92,7 @@ namespace MWMechanics MagicEffects getMagicEffects() const; ///< Return sum of magic effects resulting from abilities, blights, deseases and curses. - void clear(); + void clear(bool modifyBase = false); ///< Remove all spells of al types. void setSelectedSpell (const std::string& spellId); @@ -118,6 +114,10 @@ namespace MWMechanics void readState (const ESM::SpellState& state, CreatureStats* creatureStats); void writeState (ESM::SpellState& state) const; + + bool setSpells(const std::string& id); + + void addAllToInstance(const std::vector& spells); }; } diff --git a/apps/openmw/mwmechanics/steering.cpp b/apps/openmw/mwmechanics/steering.cpp index b08a90220..eaf37fbd2 100644 --- a/apps/openmw/mwmechanics/steering.cpp +++ b/apps/openmw/mwmechanics/steering.cpp @@ -1,5 +1,8 @@ #include "steering.hpp" +#include +#include + #include "../mwworld/class.hpp" #include "../mwworld/ptr.hpp" @@ -12,19 +15,8 @@ namespace MWMechanics bool smoothTurn(const MWWorld::Ptr& actor, float targetAngleRadians, int axis, float epsilonRadians) { - float currentAngle (actor.getRefData().getPosition().rot[axis]); - float diff (targetAngleRadians - currentAngle); - if (std::abs(diff) >= osg::DegreesToRadians(180.f)) - { - if (diff >= 0) - { - diff = diff - osg::DegreesToRadians(360.f); - } - else - { - diff = osg::DegreesToRadians(360.f) + diff; - } - } + MWMechanics::Movement& movement = actor.getClass().getMovementSettings(actor); + float diff = Misc::normalizeAngle(targetAngleRadians - actor.getRefData().getPosition().rot[axis]); float absDiff = std::abs(diff); // The turning animation actually moves you slightly, so the angle will be wrong again. @@ -32,11 +24,15 @@ bool smoothTurn(const MWWorld::Ptr& actor, float targetAngleRadians, int axis, f if (absDiff < epsilonRadians) return true; - float limit = getAngularVelocity(actor.getClass().getSpeed(actor)) * MWBase::Environment::get().getFrameDuration(); + float limit = getAngularVelocity(actor.getClass().getMaxSpeed(actor)) * MWBase::Environment::get().getFrameDuration(); + static const bool smoothMovement = Settings::Manager::getBool("smooth movement", "Game"); + if (smoothMovement) + limit *= std::min(absDiff / osg::PI + 0.1, 0.5); + if (absDiff > limit) diff = osg::sign(diff) * limit; - actor.getClass().getMovementSettings(actor).mRotation[axis] = diff; + movement.mRotation[axis] = diff; return false; } diff --git a/apps/openmw/mwmechanics/summoning.cpp b/apps/openmw/mwmechanics/summoning.cpp index 03fd0d681..0f699ccad 100644 --- a/apps/openmw/mwmechanics/summoning.cpp +++ b/apps/openmw/mwmechanics/summoning.cpp @@ -65,25 +65,25 @@ namespace MWMechanics { } - void UpdateSummonedCreatures::visit(EffectKey key, const std::string &sourceName, const std::string &sourceId, int casterActorId, float magnitude, float remainingTime, float totalTime) + void UpdateSummonedCreatures::visit(EffectKey key, int effectIndex, const std::string &sourceName, const std::string &sourceId, int casterActorId, float magnitude, float remainingTime, float totalTime) { if (isSummoningEffect(key.mId) && magnitude > 0) { - mActiveEffects.insert(std::make_pair(key.mId, sourceId)); + mActiveEffects.insert(ESM::SummonKey(key.mId, sourceId, effectIndex)); } } void UpdateSummonedCreatures::process(bool cleanup) { MWMechanics::CreatureStats& creatureStats = mActor.getClass().getCreatureStats(mActor); - std::map& creatureMap = creatureStats.getSummonedCreatureMap(); + std::map& creatureMap = creatureStats.getSummonedCreatureMap(); - for (std::set >::iterator it = mActiveEffects.begin(); it != mActiveEffects.end(); ++it) + for (std::set::iterator it = mActiveEffects.begin(); it != mActiveEffects.end(); ++it) { - bool found = creatureMap.find(std::make_pair(it->first, it->second)) != creatureMap.end(); + bool found = creatureMap.find(*it) != creatureMap.end(); if (!found) { - std::string creatureID = getSummonedCreature(it->first); + std::string creatureID = getSummonedCreature(it->mEffectId); if (!creatureID.empty()) { int creatureActorId = -1; @@ -115,13 +115,13 @@ namespace MWMechanics // still insert into creatureMap so we don't try to spawn again every frame, that would spam the warning log } - creatureMap.insert(std::make_pair(*it, creatureActorId)); + creatureMap.emplace(*it, creatureActorId); } } } // Update summon effects - for (std::map::iterator it = creatureMap.begin(); it != creatureMap.end(); ) + for (std::map::iterator it = creatureMap.begin(); it != creatureMap.end(); ) { bool found = mActiveEffects.find(it->first) != mActiveEffects.end(); if (!found) @@ -143,15 +143,17 @@ namespace MWMechanics if (!cleanup) return; - for (std::map::iterator it = creatureMap.begin(); it != creatureMap.end(); ) + for (std::map::iterator it = creatureMap.begin(); it != creatureMap.end(); ) { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->second); if (ptr.isEmpty() || (ptr.getClass().getCreatureStats(ptr).isDead() && ptr.getClass().getCreatureStats(ptr).isDeathAnimationFinished())) { // Purge the magic effect so a new creature can be summoned if desired - creatureStats.getActiveSpells().purgeEffect(it->first.first, it->first.second); + const ESM::SummonKey& key = it->first; + creatureStats.getActiveSpells().purgeEffect(key.mEffectId, key.mSourceId, key.mEffectIndex); + creatureStats.getSpells().purgeEffect(key.mEffectId, key.mSourceId); if (mActor.getClass().hasInventoryStore(mActor)) - mActor.getClass().getInventoryStore(mActor).purgeEffect(it->first.first, it->first.second); + mActor.getClass().getInventoryStore(mActor).purgeEffect(key.mEffectId, key.mSourceId, false, key.mEffectIndex); MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, it->second); creatureMap.erase(it++); diff --git a/apps/openmw/mwmechanics/summoning.hpp b/apps/openmw/mwmechanics/summoning.hpp index f24413120..7e787499e 100644 --- a/apps/openmw/mwmechanics/summoning.hpp +++ b/apps/openmw/mwmechanics/summoning.hpp @@ -5,6 +5,8 @@ #include "../mwworld/ptr.hpp" +#include + #include "magiceffects.hpp" namespace MWMechanics @@ -20,9 +22,9 @@ namespace MWMechanics UpdateSummonedCreatures(const MWWorld::Ptr& actor); virtual ~UpdateSummonedCreatures() = default; - virtual void visit (MWMechanics::EffectKey key, - const std::string& sourceName, const std::string& sourceId, int casterActorId, - float magnitude, float remainingTime = -1, float totalTime = -1); + void visit (MWMechanics::EffectKey key, int effectIndex, + const std::string& sourceName, const std::string& sourceId, int casterActorId, + float magnitude, float remainingTime = -1, float totalTime = -1) override; /// To call after all effect sources have been visited void process(bool cleanup); @@ -30,7 +32,7 @@ namespace MWMechanics private: MWWorld::Ptr mActor; - std::set > mActiveEffects; + std::set mActiveEffects; }; } diff --git a/apps/openmw/mwmechanics/tickableeffects.cpp b/apps/openmw/mwmechanics/tickableeffects.cpp index 31e8c150c..fa3b6ac20 100644 --- a/apps/openmw/mwmechanics/tickableeffects.cpp +++ b/apps/openmw/mwmechanics/tickableeffects.cpp @@ -68,11 +68,14 @@ namespace MWMechanics return false; bool receivedMagicDamage = false; + bool godmode = actor == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); switch (effectKey.mId) { case ESM::MagicEffect::DamageAttribute: { + if (godmode) + break; AttributeValue attr = creatureStats.getAttribute(effectKey.mArg); attr.damage(magnitude); creatureStats.setAttribute(effectKey.mArg, attr); @@ -91,6 +94,8 @@ namespace MWMechanics adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::RestoreHealth, magnitude); break; case ESM::MagicEffect::DamageHealth: + if (godmode) + break; receivedMagicDamage = true; adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude); break; @@ -98,25 +103,32 @@ namespace MWMechanics case ESM::MagicEffect::DamageMagicka: case ESM::MagicEffect::DamageFatigue: { + if (godmode) + break; int index = effectKey.mId-ESM::MagicEffect::DamageHealth; static const bool uncappedDamageFatigue = Settings::Manager::getBool("uncapped damage fatigue", "Game"); adjustDynamicStat(creatureStats, index, -magnitude, index == 2 && uncappedDamageFatigue); break; } case ESM::MagicEffect::AbsorbHealth: - if (magnitude > 0.f) - receivedMagicDamage = true; - adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude); - + if (!godmode || magnitude <= 0) + { + if (magnitude > 0.f) + receivedMagicDamage = true; + adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude); + } break; case ESM::MagicEffect::AbsorbMagicka: case ESM::MagicEffect::AbsorbFatigue: - adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude); + if (!godmode || magnitude <= 0) + adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude); break; case ESM::MagicEffect::DisintegrateArmor: { + if (godmode) + break; static const std::array priorities { MWWorld::InventoryStore::Slot_CarriedLeft, @@ -138,13 +150,14 @@ namespace MWMechanics break; } case ESM::MagicEffect::DisintegrateWeapon: - disintegrateSlot(actor, MWWorld::InventoryStore::Slot_CarriedRight, magnitude); + if (!godmode) + disintegrateSlot(actor, MWWorld::InventoryStore::Slot_CarriedRight, magnitude); break; case ESM::MagicEffect::SunDamage: { // isInCell shouldn't be needed, but updateActor called during game start - if (!actor.isInCell() || !actor.getCell()->isExterior()) + if (!actor.isInCell() || !actor.getCell()->isExterior() || godmode) break; float time = MWBase::Environment::get().getWorld()->getTimeStamp().getHour(); float timeDiff = std::min(7.f, std::max(0.f, std::abs(time - 13))); @@ -169,6 +182,8 @@ namespace MWMechanics case ESM::MagicEffect::FrostDamage: case ESM::MagicEffect::Poison: { + if (godmode) + break; adjustDynamicStat(creatureStats, 0, -magnitude); receivedMagicDamage = true; break; @@ -179,6 +194,8 @@ namespace MWMechanics { if (!actor.getClass().isNpc()) break; + if (godmode && effectKey.mId == ESM::MagicEffect::DamageSkill) + break; NpcStats &npcStats = actor.getClass().getNpcStats(actor); SkillValue& skill = npcStats.getSkill(effectKey.mArg); if (effectKey.mId == ESM::MagicEffect::RestoreSkill) diff --git a/apps/openmw/mwmechanics/typedaipackage.hpp b/apps/openmw/mwmechanics/typedaipackage.hpp index c959f4d68..d2d424326 100644 --- a/apps/openmw/mwmechanics/typedaipackage.hpp +++ b/apps/openmw/mwmechanics/typedaipackage.hpp @@ -18,7 +18,7 @@ namespace MWMechanics TypedAiPackage(Derived*) : AiPackage(Derived::getTypeId(), Derived::makeDefaultOptions()) {} - virtual std::unique_ptr clone() const override + std::unique_ptr clone() const override { return std::make_unique(*static_cast(this)); } diff --git a/apps/openmw/mwmechanics/weapontype.hpp b/apps/openmw/mwmechanics/weapontype.hpp index 32e321d45..056a1dbfd 100644 --- a/apps/openmw/mwmechanics/weapontype.hpp +++ b/apps/openmw/mwmechanics/weapontype.hpp @@ -239,7 +239,7 @@ namespace MWMechanics /* short group */ "", /* long group */ "", /* sound ID */ "Item Ammo", - /* attach bone */ "ArrowBone", + /* attach bone */ "Bip01 Arrow", /* sheath bone */ "", /* usage skill */ ESM::Skill::Marksman, /* weapon class*/ ESM::WeaponType::Ammo, diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index 0f8814aca..5caaba5c9 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -12,37 +12,35 @@ #include "../mwworld/class.hpp" #include "collisiontype.hpp" +#include "mtphysics.hpp" namespace MWPhysics { -Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr shape, btCollisionWorld* world) +Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler) : mCanWaterWalk(false), mWalkingOnWater(false) - , mCollisionObject(nullptr), mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false) + , mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBoxTranslate), mHalfExtents(shape->mCollisionBoxHalfExtents) + , mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false) , mInternalCollisionMode(true) , mExternalCollisionMode(true) - , mCollisionWorld(world) + , mTaskScheduler(scheduler) { mPtr = ptr; - mHalfExtents = shape->mCollisionBoxHalfExtents; - mMeshTranslation = shape->mCollisionBoxTranslate; - // We can not create actor without collisions - he will fall through the ground. // In this case we should autogenerate collision box based on mesh shape // (NPCs have bodyparts and use a different approach) if (!ptr.getClass().isNpc() && mHalfExtents.length2() == 0.f) { - const Resource::BulletShape* collisionShape = shape.get(); - if (collisionShape && collisionShape->mCollisionShape) + if (shape->mCollisionShape) { btTransform transform; transform.setIdentity(); btVector3 min; btVector3 max; - collisionShape->mCollisionShape->getAabb(transform, min, max); + shape->mCollisionShape->getAabb(transform, min, max); mHalfExtents.x() = (max[0] - min[0])/2.f; mHalfExtents.y() = (max[1] - min[1])/2.f; mHalfExtents.z() = (max[2] - min[2])/2.f; @@ -79,17 +77,18 @@ Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr updatePosition(); addCollisionMask(getCollisionMask()); + commitPositionChange(); } Actor::~Actor() { - if (mCollisionObject.get()) - mCollisionWorld->removeCollisionObject(mCollisionObject.get()); + if (mCollisionObject) + mTaskScheduler->removeCollisionObject(mCollisionObject.get()); } void Actor::enableCollisionMode(bool collision) { - mInternalCollisionMode = collision; + mInternalCollisionMode.store(collision, std::memory_order_release); } void Actor::enableCollisionBody(bool collision) @@ -103,16 +102,15 @@ void Actor::enableCollisionBody(bool collision) void Actor::addCollisionMask(int collisionMask) { - mCollisionWorld->addCollisionObject(mCollisionObject.get(), CollisionType_Actor, collisionMask); + mTaskScheduler->addCollisionObject(mCollisionObject.get(), CollisionType_Actor, collisionMask); } void Actor::updateCollisionMask() { - mCollisionWorld->removeCollisionObject(mCollisionObject.get()); - addCollisionMask(getCollisionMask()); + mTaskScheduler->setCollisionFilterMask(mCollisionObject.get(), getCollisionMask()); } -int Actor::getCollisionMask() +int Actor::getCollisionMask() const { int collisionMask = CollisionType_World | CollisionType_HeightMap; if (mExternalCollisionMode) @@ -120,58 +118,91 @@ int Actor::getCollisionMask() if (mCanWaterWalk) collisionMask |= CollisionType_Water; return collisionMask; - } void Actor::updatePosition() { + std::unique_lock lock(mPositionMutex); osg::Vec3f position = mPtr.getRefData().getPosition().asVec3(); mPosition = position; mPreviousPosition = position; + mTransformUpdatePending = true; updateCollisionObjectPosition(); } void Actor::updateCollisionObjectPosition() { - btTransform tr = mCollisionObject->getWorldTransform(); osg::Vec3f scaledTranslation = mRotation * osg::componentMultiply(mMeshTranslation, mScale); osg::Vec3f newPosition = scaledTranslation + mPosition; - tr.setOrigin(Misc::Convert::toBullet(newPosition)); - mCollisionObject->setWorldTransform(tr); + mLocalTransform.setOrigin(Misc::Convert::toBullet(newPosition)); + mLocalTransform.setRotation(Misc::Convert::toBullet(mRotation)); + +} + +void Actor::commitPositionChange() +{ + std::unique_lock lock(mPositionMutex); + if (mScaleUpdatePending) + { + mShape->setLocalScaling(Misc::Convert::toBullet(mScale)); + mScaleUpdatePending = false; + } + if (mTransformUpdatePending) + { + mCollisionObject->setWorldTransform(mLocalTransform); + mTransformUpdatePending = false; + } } osg::Vec3f Actor::getCollisionObjectPosition() const { - return Misc::Convert::toOsg(mCollisionObject->getWorldTransform().getOrigin()); + std::unique_lock lock(mPositionMutex); + return Misc::Convert::toOsg(mLocalTransform.getOrigin()); } -void Actor::setPosition(const osg::Vec3f &position) +void Actor::setPosition(const osg::Vec3f &position, bool updateCollisionObject) { - mPreviousPosition = mPosition; + std::unique_lock lock(mPositionMutex); + if (mTransformUpdatePending) + { + mCollisionObject->setWorldTransform(mLocalTransform); + mTransformUpdatePending = false; + } + else + { + mPreviousPosition = mPosition; - mPosition = position; - updateCollisionObjectPosition(); + mPosition = position; + if (updateCollisionObject) + { + updateCollisionObjectPosition(); + mCollisionObject->setWorldTransform(mLocalTransform); + } + } } osg::Vec3f Actor::getPosition() const { + std::unique_lock lock(mPositionMutex); return mPosition; } osg::Vec3f Actor::getPreviousPosition() const { + std::unique_lock lock(mPositionMutex); return mPreviousPosition; } void Actor::updateRotation () { - btTransform tr = mCollisionObject->getWorldTransform(); + std::unique_lock lock(mPositionMutex); + if (mRotation == mPtr.getRefData().getBaseNode()->getAttitude()) + return; mRotation = mPtr.getRefData().getBaseNode()->getAttitude(); - tr.setRotation(Misc::Convert::toBullet(mRotation)); - mCollisionObject->setWorldTransform(tr); + mTransformUpdatePending = true; updateCollisionObjectPosition(); } @@ -182,32 +213,37 @@ bool Actor::isRotationallyInvariant() const void Actor::updateScale() { + std::unique_lock lock(mPositionMutex); float scale = mPtr.getCellRef().getScale(); osg::Vec3f scaleVec(scale,scale,scale); mPtr.getClass().adjustScale(mPtr, scaleVec, false); mScale = scaleVec; - mShape->setLocalScaling(Misc::Convert::toBullet(mScale)); + mScaleUpdatePending = true; scaleVec = osg::Vec3f(scale,scale,scale); mPtr.getClass().adjustScale(mPtr, scaleVec, true); mRenderingScale = scaleVec; + mTransformUpdatePending = true; updateCollisionObjectPosition(); } osg::Vec3f Actor::getHalfExtents() const { + std::unique_lock lock(mPositionMutex); return osg::componentMultiply(mHalfExtents, mScale); } osg::Vec3f Actor::getOriginalHalfExtents() const { + std::unique_lock lock(mPositionMutex); return mHalfExtents; } osg::Vec3f Actor::getRenderingHalfExtents() const { + std::unique_lock lock(mPositionMutex); return osg::componentMultiply(mHalfExtents, mRenderingScale); } @@ -218,26 +254,27 @@ void Actor::setInertialForce(const osg::Vec3f &force) void Actor::setOnGround(bool grounded) { - mOnGround = grounded; + mOnGround.store(grounded, std::memory_order_release); } void Actor::setOnSlope(bool slope) { - mOnSlope = slope; + mOnSlope.store(slope, std::memory_order_release); } bool Actor::isWalkingOnWater() const { - return mWalkingOnWater; + return mWalkingOnWater.load(std::memory_order_acquire); } void Actor::setWalkingOnWater(bool walkingOnWater) { - mWalkingOnWater = walkingOnWater; + mWalkingOnWater.store(walkingOnWater, std::memory_order_release); } void Actor::setCanWaterWalk(bool waterWalk) { + std::unique_lock lock(mPositionMutex); if (waterWalk != mCanWaterWalk) { mCanWaterWalk = waterWalk; diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 8752f7fee..ef7b368b9 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -1,15 +1,17 @@ #ifndef OPENMW_MWPHYSICS_ACTOR_H #define OPENMW_MWPHYSICS_ACTOR_H +#include #include +#include #include "ptrholder.hpp" +#include #include #include #include -class btCollisionWorld; class btCollisionShape; class btCollisionObject; class btConvexShape; @@ -21,12 +23,13 @@ namespace Resource namespace MWPhysics { + class PhysicsTaskScheduler; - class Actor : public PtrHolder + class Actor final : public PtrHolder { public: - Actor(const MWWorld::Ptr& ptr, osg::ref_ptr shape, btCollisionWorld* world); - ~Actor(); + Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler); + ~Actor() override; /** * Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry. @@ -35,7 +38,7 @@ namespace MWPhysics bool getCollisionMode() const { - return mInternalCollisionMode; + return mInternalCollisionMode.load(std::memory_order_acquire); } btConvexShape* getConvexShape() const { return mConvexShape; } @@ -60,6 +63,7 @@ namespace MWPhysics void updatePosition(); void updateCollisionObjectPosition(); + void commitPositionChange(); /** * Returns the half extents of the collision body (scaled according to collision scale) @@ -79,8 +83,9 @@ namespace MWPhysics /** * Store the current position into mPreviousPosition, then move to this position. + * Optionally, inform the physics engine about the change of position. */ - void setPosition(const osg::Vec3f& position); + void setPosition(const osg::Vec3f& position, bool updateCollisionObject=true); osg::Vec3f getPosition() const; @@ -110,14 +115,14 @@ namespace MWPhysics bool getOnGround() const { - return mInternalCollisionMode && mOnGround; + return mInternalCollisionMode.load(std::memory_order_acquire) && mOnGround.load(std::memory_order_acquire); } void setOnSlope(bool slope); bool getOnSlope() const { - return mInternalCollisionMode && mOnSlope; + return mInternalCollisionMode.load(std::memory_order_acquire) && mOnSlope.load(std::memory_order_acquire); } btCollisionObject* getCollisionObject() const @@ -136,10 +141,10 @@ namespace MWPhysics /// Removes then re-adds the collision object to the dynamics world void updateCollisionMask(); void addCollisionMask(int collisionMask); - int getCollisionMask(); + int getCollisionMask() const; bool mCanWaterWalk; - bool mWalkingOnWater; + std::atomic mWalkingOnWater; bool mRotationallyInvariant; @@ -156,14 +161,18 @@ namespace MWPhysics osg::Vec3f mRenderingScale; osg::Vec3f mPosition; osg::Vec3f mPreviousPosition; + btTransform mLocalTransform; + bool mScaleUpdatePending; + bool mTransformUpdatePending; + mutable std::mutex mPositionMutex; osg::Vec3f mForce; - bool mOnGround; - bool mOnSlope; - bool mInternalCollisionMode; + std::atomic mOnGround; + std::atomic mOnSlope; + std::atomic mInternalCollisionMode; bool mExternalCollisionMode; - btCollisionWorld* mCollisionWorld; + PhysicsTaskScheduler* mTaskScheduler; Actor(const Actor&); Actor& operator=(const Actor&); diff --git a/apps/openmw/mwphysics/closestnotmeconvexresultcallback.hpp b/apps/openmw/mwphysics/closestnotmeconvexresultcallback.hpp index e4e960ab8..97aaa64a1 100644 --- a/apps/openmw/mwphysics/closestnotmeconvexresultcallback.hpp +++ b/apps/openmw/mwphysics/closestnotmeconvexresultcallback.hpp @@ -12,7 +12,7 @@ namespace MWPhysics public: ClosestNotMeConvexResultCallback(const btCollisionObject *me, const btVector3 &motion, btScalar minCollisionDot); - virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace); + btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) override; protected: const btCollisionObject *mMe; diff --git a/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp b/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp index 3d2c5704b..23d52998c 100644 --- a/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp +++ b/apps/openmw/mwphysics/closestnotmerayresultcallback.hpp @@ -14,7 +14,7 @@ namespace MWPhysics public: ClosestNotMeRayResultCallback(const btCollisionObject* me, const std::vector& targets, const btVector3& from, const btVector3& to); - virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace); + btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) override; private: const btCollisionObject* mMe; const std::vector mTargets; diff --git a/apps/openmw/mwphysics/contacttestresultcallback.hpp b/apps/openmw/mwphysics/contacttestresultcallback.hpp index 0f469127d..03fc36299 100644 --- a/apps/openmw/mwphysics/contacttestresultcallback.hpp +++ b/apps/openmw/mwphysics/contacttestresultcallback.hpp @@ -19,9 +19,9 @@ namespace MWPhysics public: ContactTestResultCallback(const btCollisionObject* testedAgainst); - virtual btScalar addSingleResult(btManifoldPoint& cp, + btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* col0Wrap,int partId0,int index0, - const btCollisionObjectWrapper* col1Wrap,int partId1,int index1); + const btCollisionObjectWrapper* col1Wrap,int partId1,int index1) override; std::vector mResult; }; diff --git a/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp b/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp index f1107046b..9b2e97e65 100644 --- a/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp +++ b/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp @@ -24,9 +24,9 @@ namespace MWPhysics DeepestNotMeContactTestResultCallback(const btCollisionObject* me, const std::vector& targets, const btVector3 &origin); - virtual btScalar addSingleResult(btManifoldPoint& cp, + btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* col0Wrap,int partId0,int index0, - const btCollisionObjectWrapper* col1Wrap,int partId1,int index1); + const btCollisionObjectWrapper* col1Wrap,int partId1,int index1) override; }; } diff --git a/apps/openmw/mwphysics/movementsolver.cpp b/apps/openmw/mwphysics/movementsolver.cpp index 228f3c0a8..f4511ba57 100644 --- a/apps/openmw/mwphysics/movementsolver.cpp +++ b/apps/openmw/mwphysics/movementsolver.cpp @@ -10,13 +10,8 @@ #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" -#include "../mwmechanics/actorutil.hpp" -#include "../mwmechanics/creaturestats.hpp" -#include "../mwmechanics/movement.hpp" - #include "../mwworld/class.hpp" #include "../mwworld/esmstore.hpp" -#include "../mwworld/player.hpp" #include "../mwworld/refdata.hpp" #ifdef USE_OPENXR @@ -24,11 +19,14 @@ #include "../mwvr/vrcamera.hpp" #include "../mwvr/vrenvironment.hpp" #include "../mwrender/renderingmanager.hpp" +#include "../mwworld/player.hpp" +#include "../mwmechanics/actorutil.hpp" #endif #include "actor.hpp" #include "collisiontype.hpp" #include "constants.hpp" +#include "physicssystem.hpp" #include "stepper.hpp" #include "trace.h" @@ -85,15 +83,17 @@ namespace MWPhysics return tracer.mEndPos-offset + osg::Vec3f(0.f, 0.f, sGroundOffset); } - osg::Vec3f MovementSolver::move(osg::Vec3f position, const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time, - bool isFlying, float waterlevel, float slowFall, const btCollisionWorld* collisionWorld, - std::map& standingCollisionTracker) + void MovementSolver::move(ActorFrameData& actor, float time, const btCollisionWorld* collisionWorld, + WorldFrameData& worldData) { - ESM::Position refpos = ptr.getRefData().getPosition(); + auto* physicActor = actor.mActorRaw; + auto ptr = actor.mPtr; + ESM::Position refpos = actor.mRefpos; + // Early-out for totally static creatures // (Not sure if gravity should still apply?) if (!ptr.getClass().isMobile(ptr)) - return position; + return; const bool isPlayer = (ptr == MWMechanics::getPlayer()); auto* world = MWBase::Environment::get().getWorld(); @@ -134,9 +134,10 @@ namespace MWPhysics // Anything to collide with? if(!physicActor->getCollisionMode()) { - return position + (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * + actor.mPosition += (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1)) - ) * movement * time; + ) * actor.mMovement * time; + return; } const btCollisionObject *colobj = physicActor->getCollisionObject(); @@ -146,23 +147,23 @@ namespace MWPhysics // That means the collision shape used for moving this actor is in a different spot than the collision shape // other actors are using to collide against this actor. // While this is strictly speaking wrong, it's needed for MW compatibility. - position.z() += halfExtents.z(); + actor.mPosition.z() += halfExtents.z(); static const float fSwimHeightScale = world->getStore().get().find("fSwimHeightScale")->mValue.getFloat(); - float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale); + float swimlevel = actor.mWaterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale); ActorTracer tracer; osg::Vec3f inertia = physicActor->getInertialForce(); osg::Vec3f velocity; - if (position.z() < swimlevel || isFlying) + if (actor.mPosition.z() < swimlevel || actor.mFlying) { - velocity = (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))) * movement; + velocity = (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))) * actor.mMovement; } else { - velocity = (osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))) * movement; + velocity = (osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))) * actor.mMovement; if ((velocity.z() > 0.f && physicActor->getOnGround() && !physicActor->getOnSlope()) || (velocity.z() > 0.f && velocity.z() + inertia.z() <= -velocity.z() && physicActor->getOnSlope())) @@ -172,37 +173,16 @@ namespace MWPhysics } // dead actors underwater will float to the surface, if the CharacterController tells us to do so - if (movement.z() > 0 && ptr.getClass().getCreatureStats(ptr).isDead() && position.z() < swimlevel) + if (actor.mMovement.z() > 0 && actor.mIsDead && actor.mPosition.z() < swimlevel) velocity = osg::Vec3f(0,0,1) * 25; - if (ptr.getClass().getMovementSettings(ptr).mPosition[2]) - { - // Advance acrobatics and set flag for GetPCJumping - if (isPlayer) - { - ptr.getClass().skillUsageSucceeded(ptr, ESM::Skill::Acrobatics, 0); - world->getPlayer().setJumping(true); - } - - // Decrease fatigue - if (!isPlayer || !world->getGodModeState()) - { - const MWWorld::Store &gmst = world->getStore().get(); - const float fFatigueJumpBase = gmst.find("fFatigueJumpBase")->mValue.getFloat(); - const float fFatigueJumpMult = gmst.find("fFatigueJumpMult")->mValue.getFloat(); - const float normalizedEncumbrance = std::min(1.f, ptr.getClass().getNormalizedEncumbrance(ptr)); - const float fatigueDecrease = fFatigueJumpBase + normalizedEncumbrance * fFatigueJumpMult; - MWMechanics::DynamicStat fatigue = ptr.getClass().getCreatureStats(ptr).getFatigue(); - fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease); - ptr.getClass().getCreatureStats(ptr).setFatigue(fatigue); - } - ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0; - } + if (actor.mWantJump) + actor.mDidJump = true; // Now that we have the effective movement vector, apply wind forces to it - if (world->isInStorm()) + if (worldData.mIsInStorm) { - osg::Vec3f stormDirection = world->getStormDirection(); + osg::Vec3f stormDirection = worldData.mStormDirection; float angleDegrees = osg::RadiansToDegrees(std::acos(stormDirection * velocity / (stormDirection.length() * velocity.length()))); static const float fStromWalkMult = world->getStore().get().find("fStromWalkMult")->mValue.getFloat(); velocity *= 1.f-(fStromWalkMult * (angleDegrees/180.f)); @@ -210,7 +190,7 @@ namespace MWPhysics Stepper stepper(collisionWorld, colobj); osg::Vec3f origVelocity = velocity; - osg::Vec3f newPosition = position; + osg::Vec3f newPosition = actor.mPosition; #ifdef USE_OPENXR // Catch the player character up to the real world position of the player. @@ -280,7 +260,7 @@ namespace MWPhysics } // Try not to lose any tracking - osg::Vec3 moved = newPosition - position; + osg::Vec3 moved = newPosition - actor.mPosition; headOffset.x() -= moved.x(); headOffset.y() -= moved.y(); inputManager->setHeadOffset(headOffset); @@ -298,7 +278,7 @@ namespace MWPhysics osg::Vec3f nextpos = newPosition + velocity * remainingTime; // If not able to fly, don't allow to swim up into the air - if(!isFlying && nextpos.z() > swimlevel && newPosition.z() < swimlevel) + if(!actor.mFlying && nextpos.z() > swimlevel && newPosition.z() < swimlevel) { const osg::Vec3f down(0,0,-1); velocity = slide(velocity, down); @@ -351,7 +331,7 @@ namespace MWPhysics if (result) { // don't let pure water creatures move out of water after stepMove - if (ptr.getClass().isPureWaterCreature(ptr) && newPosition.z() + halfExtents.z() > waterlevel) + if (ptr.getClass().isPureWaterCreature(ptr) && newPosition.z() + halfExtents.z() > actor.mWaterlevel) newPosition = oldPosition; } else @@ -361,7 +341,7 @@ namespace MWPhysics // Do not allow sliding upward if there is gravity. // Stepping will have taken care of that. - if(!(newPosition.z() < swimlevel || isFlying)) + if(!(newPosition.z() < swimlevel || actor.mFlying)) newVelocity.z() = std::min(newVelocity.z(), 0.0f); if ((newVelocity-velocity).length2() < 0.01) @@ -385,11 +365,11 @@ namespace MWPhysics const btCollisionObject* standingOn = tracer.mHitObject; PtrHolder* ptrHolder = static_cast(standingOn->getUserPointer()); if (ptrHolder) - standingCollisionTracker[ptr] = ptrHolder->getPtr(); + actor.mStandingOn = ptrHolder->getPtr(); if (standingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water) physicActor->setWalkingOnWater(true); - if (!isFlying) + if (!actor.mFlying) newPosition.z() = tracer.mEndPos.z() + sGroundOffset; isOnGround = true; @@ -408,7 +388,7 @@ namespace MWPhysics btVector3 aabbMin, aabbMax; tracer.mHitObject->getCollisionShape()->getAabb(tracer.mHitObject->getWorldTransform(), aabbMin, aabbMax); btVector3 center = (aabbMin + aabbMax) / 2.f; - inertia = osg::Vec3f(position.x() - center.x(), position.y() - center.y(), 0); + inertia = osg::Vec3f(actor.mPosition.x() - center.x(), actor.mPosition.y() - center.y(), 0); inertia.normalize(); inertia *= 100; } @@ -418,16 +398,16 @@ namespace MWPhysics } } - if((isOnGround && !isOnSlope) || newPosition.z() < swimlevel || isFlying) + if((isOnGround && !isOnSlope) || newPosition.z() < swimlevel || actor.mFlying) physicActor->setInertialForce(osg::Vec3f(0.f, 0.f, 0.f)); else { inertia.z() -= time * Constants::GravityConst * Constants::UnitsPerMeter; if (inertia.z() < 0) - inertia.z() *= slowFall; - if (slowFall < 1.f) { - inertia.x() *= slowFall; - inertia.y() *= slowFall; + inertia.z() *= actor.mSlowFall; + if (actor.mSlowFall < 1.f) { + inertia.x() *= actor.mSlowFall; + inertia.y() *= actor.mSlowFall; } physicActor->setInertialForce(inertia); } @@ -435,6 +415,6 @@ namespace MWPhysics physicActor->setOnSlope(isOnSlope); newPosition.z() -= halfExtents.z(); // remove what was added at the beginning - return newPosition; + actor.mPosition = newPosition; } } diff --git a/apps/openmw/mwphysics/movementsolver.hpp b/apps/openmw/mwphysics/movementsolver.hpp index 54a417fa7..75fba1cf0 100644 --- a/apps/openmw/mwphysics/movementsolver.hpp +++ b/apps/openmw/mwphysics/movementsolver.hpp @@ -5,13 +5,18 @@ #include -#include "../mwworld/ptr.hpp" - class btCollisionWorld; +namespace MWWorld +{ + class Ptr; +} + namespace MWPhysics { class Actor; + struct ActorFrameData; + struct WorldFrameData; class MovementSolver { @@ -31,9 +36,7 @@ namespace MWPhysics public: static osg::Vec3f traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, Actor* actor, btCollisionWorld* collisionWorld, float maxHeight); - static osg::Vec3f move(osg::Vec3f position, const MWWorld::Ptr &ptr, Actor* physicActor, const osg::Vec3f &movement, float time, - bool isFlying, float waterlevel, float slowFall, const btCollisionWorld* collisionWorld, - std::map& standingCollisionTracker); + static void move(ActorFrameData& actor, float time, const btCollisionWorld* collisionWorld, WorldFrameData& worldData); }; } diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp new file mode 100644 index 000000000..1ad0ae9c0 --- /dev/null +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -0,0 +1,544 @@ +#include +#include + +#include "components/debug/debuglog.hpp" +#include +#include "components/misc/convert.hpp" +#include "components/settings/settings.hpp" +#include "../mwmechanics/actorutil.hpp" +#include "../mwmechanics/movement.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" + +#include "actor.hpp" +#include "movementsolver.hpp" +#include "mtphysics.hpp" +#include "object.hpp" +#include "physicssystem.hpp" + +namespace +{ + /// @brief A scoped lock that is either shared or exclusive depending on configuration + template + class MaybeSharedLock + { + public: + /// @param mutex a shared mutex + /// @param canBeSharedLock decide wether the lock will be shared or exclusive + MaybeSharedLock(Mutex& mutex, bool canBeSharedLock) : mMutex(mutex), mCanBeSharedLock(canBeSharedLock) + { + if (mCanBeSharedLock) + mMutex.lock_shared(); + else + mMutex.lock(); + } + + ~MaybeSharedLock() + { + if (mCanBeSharedLock) + mMutex.unlock_shared(); + else + mMutex.unlock(); + } + private: + Mutex& mMutex; + bool mCanBeSharedLock; + }; + + void handleFall(MWPhysics::ActorFrameData& actorData, bool simulationPerformed) + { + const float heightDiff = actorData.mPosition.z() - actorData.mOldHeight; + + const bool isStillOnGround = (simulationPerformed && actorData.mWasOnGround && actorData.mActorRaw->getOnGround()); + + if (isStillOnGround || actorData.mFlying || actorData.mSwimming || actorData.mSlowFall < 1) + actorData.mNeedLand = true; + else if (heightDiff < 0) + actorData.mFallHeight += heightDiff; + } + + void handleJump(const MWWorld::Ptr &ptr) + { + const bool isPlayer = (ptr == MWMechanics::getPlayer()); + // Advance acrobatics and set flag for GetPCJumping + if (isPlayer) + { + ptr.getClass().skillUsageSucceeded(ptr, ESM::Skill::Acrobatics, 0); + MWBase::Environment::get().getWorld()->getPlayer().setJumping(true); + } + + // Decrease fatigue + if (!isPlayer || !MWBase::Environment::get().getWorld()->getGodModeState()) + { + const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); + const float fFatigueJumpBase = gmst.find("fFatigueJumpBase")->mValue.getFloat(); + const float fFatigueJumpMult = gmst.find("fFatigueJumpMult")->mValue.getFloat(); + const float normalizedEncumbrance = std::min(1.f, ptr.getClass().getNormalizedEncumbrance(ptr)); + const float fatigueDecrease = fFatigueJumpBase + normalizedEncumbrance * fFatigueJumpMult; + MWMechanics::DynamicStat fatigue = ptr.getClass().getCreatureStats(ptr).getFatigue(); + fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease); + ptr.getClass().getCreatureStats(ptr).setFatigue(fatigue); + } + ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0; + } + + void updateStandingCollision(MWPhysics::ActorFrameData& actorData, MWPhysics::CollisionMap& standingCollisions) + { + if (!actorData.mStandingOn.isEmpty()) + standingCollisions[actorData.mPtr] = actorData.mStandingOn; + else + standingCollisions.erase(actorData.mPtr); + } + + void updateMechanics(MWPhysics::ActorFrameData& actorData) + { + if (actorData.mDidJump) + handleJump(actorData.mPtr); + + MWMechanics::CreatureStats& stats = actorData.mPtr.getClass().getCreatureStats(actorData.mPtr); + if (actorData.mNeedLand) + stats.land(actorData.mPtr == MWMechanics::getPlayer() && (actorData.mFlying || actorData.mSwimming)); + else if (actorData.mFallHeight < 0) + stats.addToFallHeight(-actorData.mFallHeight); + } + + osg::Vec3f interpolateMovements(const MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt) + { + const float interpolationFactor = timeAccum / physicsDt; + return actorData.mPosition * interpolationFactor + actorData.mActorRaw->getPreviousPosition() * (1.f - interpolationFactor); + } + + struct WorldFrameData + { + WorldFrameData() : mIsInStorm(MWBase::Environment::get().getWorld()->isInStorm()) + , mStormDirection(MWBase::Environment::get().getWorld()->getStormDirection()) + {} + + bool mIsInStorm; + osg::Vec3f mStormDirection; + }; + + namespace Config + { + /// @return either the number of thread as configured by the user, or 1 if Bullet doesn't support multithreading + int computeNumThreads(bool& threadSafeBullet) + { + int wantedThread = Settings::Manager::getInt("async num threads", "Physics"); + + auto broad = std::make_unique(); + auto maxSupportedThreads = broad->m_rayTestStacks.size(); + threadSafeBullet = (maxSupportedThreads > 1); + if (!threadSafeBullet && wantedThread > 1) + { + Log(Debug::Warning) << "Bullet was not compiled with multithreading support, 1 async thread will be used"; + return 1; + } + return std::max(0, wantedThread); + } + } +} + +namespace MWPhysics +{ + PhysicsTaskScheduler::PhysicsTaskScheduler(float physicsDt, std::shared_ptr collisionWorld) + : mPhysicsDt(physicsDt) + , mCollisionWorld(std::move(collisionWorld)) + , mNumJobs(0) + , mRemainingSteps(0) + , mLOSCacheExpiry(Settings::Manager::getInt("lineofsight keep inactive cache", "Physics")) + , mDeferAabbUpdate(Settings::Manager::getBool("defer aabb update", "Physics")) + , mNewFrame(false) + , mAdvanceSimulation(false) + , mQuit(false) + , mNextJob(0) + , mNextLOS(0) + { + mNumThreads = Config::computeNumThreads(mThreadSafeBullet); + + if (mNumThreads >= 1) + { + for (int i = 0; i < mNumThreads; ++i) + mThreads.emplace_back([&] { worker(); } ); + } + else + { + mLOSCacheExpiry = -1; + mDeferAabbUpdate = false; + } + + mPreStepBarrier = std::make_unique(mNumThreads, [&]() + { + updateAabbs(); + }); + + mPostStepBarrier = std::make_unique(mNumThreads, [&]() + { + if (mRemainingSteps) + --mRemainingSteps; + mNextJob.store(0, std::memory_order_release); + updateActorsPositions(); + }); + + mPostSimBarrier = std::make_unique(mNumThreads, [&]() + { + udpateActorsAabbs(); + mNewFrame = false; + if (mLOSCacheExpiry >= 0) + { + std::unique_lock lock(mLOSCacheMutex); + mLOSCache.erase( + std::remove_if(mLOSCache.begin(), mLOSCache.end(), + [](const LOSRequest& req) { return req.mStale; }), + mLOSCache.end()); + } + }); + } + + PhysicsTaskScheduler::~PhysicsTaskScheduler() + { + std::unique_lock lock(mSimulationMutex); + mQuit = true; + mNumJobs = 0; + mRemainingSteps = 0; + lock.unlock(); + mHasJob.notify_all(); + for (auto& thread : mThreads) + thread.join(); + } + + const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector&& actorsData, CollisionMap& standingCollisions, bool skipSimulation) + { + // This function run in the main thread. + // While the mSimulationMutex is held, background physics threads can't run. + + std::unique_lock lock(mSimulationMutex); + + // start by finishing previous background computation + if (mNumThreads != 0) + { + if (mAdvanceSimulation) + standingCollisions.clear(); + + for (auto& data : mActorsFrameData) + { + // Ignore actors that were deleted while the background thread was running + if (!data.mActor.lock()) + continue; + + updateMechanics(data); + if (mAdvanceSimulation) + updateStandingCollision(data, standingCollisions); + } + } + + // init + mRemainingSteps = numSteps; + mTimeAccum = timeAccum; + mActorsFrameData = std::move(actorsData); + mAdvanceSimulation = (mRemainingSteps != 0); + mNewFrame = true; + mNumJobs = mActorsFrameData.size(); + mNextLOS.store(0, std::memory_order_relaxed); + mNextJob.store(0, std::memory_order_release); + + if (mAdvanceSimulation) + mWorldFrameData = std::make_unique(); + + // update each actor position based on latest data + for (auto& data : mActorsFrameData) + data.updatePosition(); + + // we are asked to skip the simulation (load a savegame for instance) + // just return the actors' reference position without applying the movements + if (skipSimulation) + { + standingCollisions.clear(); + mMovementResults.clear(); + for (const auto& m : mActorsFrameData) + mMovementResults[m.mPtr] = m.mPosition; + return mMovementResults; + } + + if (mNumThreads == 0) + { + mMovementResults.clear(); + syncComputation(); + + if (mAdvanceSimulation) + { + standingCollisions.clear(); + for (auto& data : mActorsFrameData) + updateStandingCollision(data, standingCollisions); + } + return mMovementResults; + } + + // Remove actors that were deleted while the background thread was running + for (auto& data : mActorsFrameData) + { + if (!data.mActor.lock()) + mMovementResults.erase(data.mPtr); + } + std::swap(mMovementResults, mPreviousMovementResults); + + // mMovementResults is shared between all workers instance + // pre-allocate all nodes so that we don't need synchronization + mMovementResults.clear(); + for (const auto& m : mActorsFrameData) + mMovementResults[m.mPtr] = m.mPosition; + + lock.unlock(); + mHasJob.notify_all(); + return mPreviousMovementResults; + } + + void PhysicsTaskScheduler::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const + { + MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); + mCollisionWorld->rayTest(rayFromWorld, rayToWorld, resultCallback); + } + + void PhysicsTaskScheduler::convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, btCollisionWorld::ConvexResultCallback& resultCallback) const + { + MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); + mCollisionWorld->convexSweepTest(castShape, from, to, resultCallback); + } + + void PhysicsTaskScheduler::contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback) + { + std::shared_lock lock(mCollisionWorldMutex); + mCollisionWorld->contactTest(colObj, resultCallback); + } + + boost::optional PhysicsTaskScheduler::getHitPoint(const btTransform& from, btCollisionObject* target) + { + MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); + // target the collision object's world origin, this should be the center of the collision object + btTransform rayTo; + rayTo.setIdentity(); + rayTo.setOrigin(target->getWorldTransform().getOrigin()); + + btCollisionWorld::ClosestRayResultCallback cb(from.getOrigin(), rayTo.getOrigin()); + + mCollisionWorld->rayTestSingle(from, rayTo, target, target->getCollisionShape(), target->getWorldTransform(), cb); + if (!cb.hasHit()) + // didn't hit the target. this could happen if point is already inside the collision box + return boost::none; + return {cb.m_hitPointWorld}; + } + + void PhysicsTaskScheduler::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) + { + std::shared_lock lock(mCollisionWorldMutex); + mCollisionWorld->getBroadphase()->aabbTest(aabbMin, aabbMax, callback); + } + + void PhysicsTaskScheduler::getAabb(const btCollisionObject* obj, btVector3& min, btVector3& max) + { + std::shared_lock lock(mCollisionWorldMutex); + obj->getCollisionShape()->getAabb(obj->getWorldTransform(), min, max); + } + + void PhysicsTaskScheduler::setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask) + { + std::unique_lock lock(mCollisionWorldMutex); + collisionObject->getBroadphaseHandle()->m_collisionFilterMask = collisionFilterMask; + } + + void PhysicsTaskScheduler::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask) + { + std::unique_lock lock(mCollisionWorldMutex); + mCollisionWorld->addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask); + } + + void PhysicsTaskScheduler::removeCollisionObject(btCollisionObject* collisionObject) + { + std::unique_lock lock(mCollisionWorldMutex); + mCollisionWorld->removeCollisionObject(collisionObject); + } + + void PhysicsTaskScheduler::updateSingleAabb(std::weak_ptr ptr) + { + if (mDeferAabbUpdate) + { + std::unique_lock lock(mUpdateAabbMutex); + mUpdateAabb.insert(std::move(ptr)); + } + else + { + std::unique_lock lock(mCollisionWorldMutex); + updatePtrAabb(ptr); + } + } + + bool PhysicsTaskScheduler::getLineOfSight(const std::weak_ptr& actor1, const std::weak_ptr& actor2) + { + std::unique_lock lock(mLOSCacheMutex); + + auto actorPtr1 = actor1.lock(); + auto actorPtr2 = actor2.lock(); + if (!actorPtr1 || !actorPtr2) + return false; + + auto req = LOSRequest(actor1, actor2); + auto result = std::find(mLOSCache.begin(), mLOSCache.end(), req); + if (result == mLOSCache.end()) + { + req.mResult = hasLineOfSight(actorPtr1.get(), actorPtr2.get()); + if (mLOSCacheExpiry >= 0) + mLOSCache.push_back(req); + return req.mResult; + } + result->mAge = 0; + return result->mResult; + } + + void PhysicsTaskScheduler::refreshLOSCache() + { + std::shared_lock lock(mLOSCacheMutex); + int job = 0; + int numLOS = mLOSCache.size(); + while ((job = mNextLOS.fetch_add(1, std::memory_order_relaxed)) < numLOS) + { + auto& req = mLOSCache[job]; + auto actorPtr1 = req.mActors[0].lock(); + auto actorPtr2 = req.mActors[1].lock(); + + if (req.mAge++ > mLOSCacheExpiry || !actorPtr1 || !actorPtr2) + req.mStale = true; + else + req.mResult = hasLineOfSight(actorPtr1.get(), actorPtr2.get()); + } + + } + + void PhysicsTaskScheduler::updateAabbs() + { + std::unique_lock lock1(mCollisionWorldMutex, std::defer_lock); + std::unique_lock lock2(mUpdateAabbMutex, std::defer_lock); + std::lock(lock1, lock2); + std::for_each(mUpdateAabb.begin(), mUpdateAabb.end(), + [this](const std::weak_ptr& ptr) { updatePtrAabb(ptr); }); + mUpdateAabb.clear(); + } + + void PhysicsTaskScheduler::updatePtrAabb(const std::weak_ptr& ptr) + { + if (const auto p = ptr.lock()) + { + if (const auto actor = std::dynamic_pointer_cast(p)) + { + actor->commitPositionChange(); + mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); + } + else if (const auto object = std::dynamic_pointer_cast(p)) + { + object->commitPositionChange(); + mCollisionWorld->updateSingleAabb(object->getCollisionObject()); + } + }; + } + + void PhysicsTaskScheduler::worker() + { + std::shared_lock lock(mSimulationMutex); + while (!mQuit) + { + if (!mNewFrame) + mHasJob.wait(lock, [&]() { return mQuit || mNewFrame; }); + + if (mDeferAabbUpdate) + mPreStepBarrier->wait(); + + int job = 0; + while (mRemainingSteps && (job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs) + { + MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); + if(const auto actor = mActorsFrameData[job].mActor.lock()) + MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld.get(), *mWorldFrameData); + } + + mPostStepBarrier->wait(); + + if (!mRemainingSteps) + { + while ((job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs) + { + if(const auto actor = mActorsFrameData[job].mActor.lock()) + { + auto& actorData = mActorsFrameData[job]; + handleFall(actorData, mAdvanceSimulation); + mMovementResults[actorData.mPtr] = interpolateMovements(actorData, mTimeAccum, mPhysicsDt); + } + } + + if (mLOSCacheExpiry >= 0) + refreshLOSCache(); + mPostSimBarrier->wait(); + } + } + } + + void PhysicsTaskScheduler::updateActorsPositions() + { + std::unique_lock lock(mCollisionWorldMutex); + for (auto& actorData : mActorsFrameData) + { + if(const auto actor = actorData.mActor.lock()) + { + if (actorData.mPosition == actor->getPosition()) + actor->setPosition(actorData.mPosition, false); // update previous position to make sure interpolation is correct + else + { + actorData.mPositionChanged = true; + actor->setPosition(actorData.mPosition); + } + } + } + } + + void PhysicsTaskScheduler::udpateActorsAabbs() + { + std::unique_lock lock(mCollisionWorldMutex); + for (const auto& actorData : mActorsFrameData) + if (actorData.mPositionChanged) + { + if(const auto actor = actorData.mActor.lock()) + mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); + } + } + + bool PhysicsTaskScheduler::hasLineOfSight(const Actor* actor1, const Actor* actor2) + { + btVector3 pos1 = Misc::Convert::toBullet(actor1->getCollisionObjectPosition() + osg::Vec3f(0,0,actor1->getHalfExtents().z() * 0.9)); // eye level + btVector3 pos2 = Misc::Convert::toBullet(actor2->getCollisionObjectPosition() + osg::Vec3f(0,0,actor2->getHalfExtents().z() * 0.9)); + + btCollisionWorld::ClosestRayResultCallback resultCallback(pos1, pos2); + resultCallback.m_collisionFilterGroup = 0xFF; + resultCallback.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap|CollisionType_Door; + + MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); + mCollisionWorld->rayTest(pos1, pos2, resultCallback); + + return !resultCallback.hasHit(); + } + + void PhysicsTaskScheduler::syncComputation() + { + while (mRemainingSteps--) + { + for (auto& actorData : mActorsFrameData) + MovementSolver::move(actorData, mPhysicsDt, mCollisionWorld.get(), *mWorldFrameData); + + updateActorsPositions(); + } + + for (auto& actorData : mActorsFrameData) + { + handleFall(actorData, mAdvanceSimulation); + mMovementResults[actorData.mPtr] = interpolateMovements(actorData, mTimeAccum, mPhysicsDt); + updateMechanics(actorData); + } + udpateActorsAabbs(); + } +} diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp new file mode 100644 index 000000000..4862393f3 --- /dev/null +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -0,0 +1,94 @@ +#ifndef OPENMW_MWPHYSICS_MTPHYSICS_H +#define OPENMW_MWPHYSICS_MTPHYSICS_H + +#include +#include +#include +#include + +#include +#include + +#include "physicssystem.hpp" +#include "ptrholder.hpp" + +namespace Misc +{ + class Barrier; +} + +namespace MWPhysics +{ + class PhysicsTaskScheduler + { + public: + PhysicsTaskScheduler(float physicsDt, std::shared_ptr collisionWorld); + ~PhysicsTaskScheduler(); + + /// @brief move actors taking into account desired movements and collisions + /// @param numSteps how much simulation step to run + /// @param timeAccum accumulated time from previous run to interpolate movements + /// @param actorsData per actor data needed to compute new positions + /// @return new position of each actor + const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector&& actorsData, CollisionMap& standingCollisions, bool skip); + + // Thread safe wrappers + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; + void convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, btCollisionWorld::ConvexResultCallback& resultCallback) const; + void contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback); + boost::optional getHitPoint(const btTransform& from, btCollisionObject* target); + void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); + void getAabb(const btCollisionObject* obj, btVector3& min, btVector3& max); + void setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask); + void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask); + void removeCollisionObject(btCollisionObject* collisionObject); + void updateSingleAabb(std::weak_ptr ptr); + bool getLineOfSight(const std::weak_ptr& actor1, const std::weak_ptr& actor2); + + private: + void syncComputation(); + void worker(); + void updateActorsPositions(); + void udpateActorsAabbs(); + bool hasLineOfSight(const Actor* actor1, const Actor* actor2); + void refreshLOSCache(); + void updateAabbs(); + void updatePtrAabb(const std::weak_ptr& ptr); + + std::unique_ptr mWorldFrameData; + std::vector mActorsFrameData; + PtrPositionList mMovementResults; + PtrPositionList mPreviousMovementResults; + const float mPhysicsDt; + float mTimeAccum; + std::shared_ptr mCollisionWorld; + std::vector mLOSCache; + std::set, std::owner_less>> mUpdateAabb; + + // TODO: use std::experimental::flex_barrier or std::barrier once it becomes a thing + std::unique_ptr mPreStepBarrier; + std::unique_ptr mPostStepBarrier; + std::unique_ptr mPostSimBarrier; + + int mNumThreads; + int mNumJobs; + int mRemainingSteps; + int mLOSCacheExpiry; + bool mDeferAabbUpdate; + bool mNewFrame; + bool mAdvanceSimulation; + bool mThreadSafeBullet; + bool mQuit; + std::atomic mNextJob; + std::atomic mNextLOS; + std::vector mThreads; + + mutable std::shared_timed_mutex mSimulationMutex; + mutable std::shared_timed_mutex mCollisionWorldMutex; + mutable std::shared_timed_mutex mLOSCacheMutex; + mutable std::mutex mUpdateAabbMutex; + std::condition_variable_any mHasJob; + }; + +} +#endif diff --git a/apps/openmw/mwphysics/object.cpp b/apps/openmw/mwphysics/object.cpp index f95a67823..c822bbcbe 100644 --- a/apps/openmw/mwphysics/object.cpp +++ b/apps/openmw/mwphysics/object.cpp @@ -1,4 +1,5 @@ #include "object.hpp" +#include "mtphysics.hpp" #include #include @@ -8,15 +9,15 @@ #include #include -#include #include namespace MWPhysics { - Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance) + Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance, PhysicsTaskScheduler* scheduler) : mShapeInstance(shapeInstance) , mSolid(true) + , mTaskScheduler(scheduler) { mPtr = ptr; @@ -29,6 +30,13 @@ namespace MWPhysics setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude())); const float* pos = ptr.getRefData().getPosition().pos; setOrigin(btVector3(pos[0], pos[1], pos[2])); + commitPositionChange(); + } + + Object::~Object() + { + if (mCollisionObject) + mTaskScheduler->removeCollisionObject(mCollisionObject.get()); } const Resource::BulletShapeInstance* Object::getShapeInstance() const @@ -38,17 +46,38 @@ namespace MWPhysics void Object::setScale(float scale) { - mShapeInstance->setLocalScaling(btVector3(scale, scale, scale)); + std::unique_lock lock(mPositionMutex); + mScale = { scale,scale,scale }; + mScaleUpdatePending = true; } void Object::setRotation(const btQuaternion& quat) { - mCollisionObject->getWorldTransform().setRotation(quat); + std::unique_lock lock(mPositionMutex); + mLocalTransform.setRotation(quat); + mTransformUpdatePending = true; } void Object::setOrigin(const btVector3& vec) { - mCollisionObject->getWorldTransform().setOrigin(vec); + std::unique_lock lock(mPositionMutex); + mLocalTransform.setOrigin(vec); + mTransformUpdatePending = true; + } + + void Object::commitPositionChange() + { + std::unique_lock lock(mPositionMutex); + if (mScaleUpdatePending) + { + mShapeInstance->setLocalScaling(mScale); + mScaleUpdatePending = false; + } + if (mTransformUpdatePending) + { + mCollisionObject->setWorldTransform(mLocalTransform); + mTransformUpdatePending = false; + } } btCollisionObject* Object::getCollisionObject() @@ -61,6 +90,12 @@ namespace MWPhysics return mCollisionObject.get(); } + btTransform Object::getTransform() const + { + std::unique_lock lock(mPositionMutex); + return mLocalTransform; + } + bool Object::isSolid() const { return mSolid; @@ -76,10 +111,10 @@ namespace MWPhysics return !mShapeInstance->mAnimatedShapes.empty(); } - void Object::animateCollisionShapes(btCollisionWorld* collisionWorld) + bool Object::animateCollisionShapes() { if (mShapeInstance->mAnimatedShapes.empty()) - return; + return false; assert (mShapeInstance->getCollisionShape()->isCompound()); @@ -100,7 +135,7 @@ namespace MWPhysics // Remove nonexistent nodes from animated shapes map and early out mShapeInstance->mAnimatedShapes.erase(recIndex); - return; + return false; } osg::NodePath nodePath = visitor.mFoundPath; nodePath.erase(nodePath.begin()); @@ -122,7 +157,6 @@ namespace MWPhysics if (!(transform == compound->getChildTransform(shapeIndex))) compound->updateChildTransform(shapeIndex, transform); } - - collisionWorld->updateSingleAabb(mCollisionObject.get()); + return true; } } diff --git a/apps/openmw/mwphysics/object.hpp b/apps/openmw/mwphysics/object.hpp index b948433e3..876e35651 100644 --- a/apps/openmw/mwphysics/object.hpp +++ b/apps/openmw/mwphysics/object.hpp @@ -3,10 +3,12 @@ #include "ptrholder.hpp" +#include #include #include #include +#include namespace Resource { @@ -14,34 +16,46 @@ namespace Resource } class btCollisionObject; -class btCollisionWorld; class btQuaternion; class btVector3; namespace MWPhysics { - class Object : public PtrHolder + class PhysicsTaskScheduler; + + class Object final : public PtrHolder { public: - Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance); + Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance, PhysicsTaskScheduler* scheduler); + ~Object() override; const Resource::BulletShapeInstance* getShapeInstance() const; void setScale(float scale); void setRotation(const btQuaternion& quat); void setOrigin(const btVector3& vec); + void commitPositionChange(); btCollisionObject* getCollisionObject(); const btCollisionObject* getCollisionObject() const; + btTransform getTransform() const; /// Return solid flag. Not used by the object itself, true by default. bool isSolid() const; void setSolid(bool solid); bool isAnimated() const; - void animateCollisionShapes(btCollisionWorld* collisionWorld); + /// @brief update object shape + /// @return true if shape changed + bool animateCollisionShapes(); private: std::unique_ptr mCollisionObject; osg::ref_ptr mShapeInstance; std::map mRecIndexToNodePath; bool mSolid; + btVector3 mScale; + btTransform mLocalTransform; + bool mScaleUpdatePending; + bool mTransformUpdatePending; + mutable std::mutex mPositionMutex; + PhysicsTaskScheduler* mTaskScheduler; }; } diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index d423830b1..00068c1e6 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -31,6 +31,7 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/actorutil.hpp" +#include "../mwmechanics/movement.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/cellstore.hpp" @@ -50,6 +51,7 @@ #include "contacttestresultcallback.hpp" #include "constants.hpp" #include "movementsolver.hpp" +#include "mtphysics.hpp" namespace MWPhysics { @@ -65,11 +67,11 @@ namespace MWPhysics { mResourceSystem->addResourceManager(mShapeManager.get()); - mCollisionConfiguration = new btDefaultCollisionConfiguration(); - mDispatcher = new btCollisionDispatcher(mCollisionConfiguration); - mBroadphase = new btDbvtBroadphase(); + mCollisionConfiguration = std::make_unique(); + mDispatcher = std::make_unique(mCollisionConfiguration.get()); + mBroadphase = std::make_unique(); - mCollisionWorld = new btCollisionWorld(mDispatcher, mBroadphase, mCollisionConfiguration); + mCollisionWorld = std::make_shared(mDispatcher.get(), mBroadphase.get(), mCollisionConfiguration.get()); // Don't update AABBs of all objects every frame. Most objects in MW are static, so we don't need this. // Should a "static" object ever be moved, we have to update its AABB manually using DynamicsWorld::updateSingleAabb. @@ -86,36 +88,26 @@ namespace MWPhysics Log(Debug::Warning) << "Warning: using custom physics framerate (" << physFramerate << " FPS)."; } } + + mTaskScheduler = std::make_unique(mPhysicsDt, mCollisionWorld); } PhysicsSystem::~PhysicsSystem() { mResourceSystem->removeResourceManager(mShapeManager.get()); - if (mWaterCollisionObject.get()) - mCollisionWorld->removeCollisionObject(mWaterCollisionObject.get()); + if (mWaterCollisionObject) + mTaskScheduler->removeCollisionObject(mWaterCollisionObject.get()); for (auto& heightField : mHeightFields) { - mCollisionWorld->removeCollisionObject(heightField.second->getCollisionObject()); + mTaskScheduler->removeCollisionObject(heightField.second->getCollisionObject()); delete heightField.second; } - for (auto& object : mObjects) - { - mCollisionWorld->removeCollisionObject(object.second->getCollisionObject()); - delete object.second; - } + mObjects.clear(); + mActors.clear(); - for (auto& actor : mActors) - { - delete actor.second; - } - - delete mCollisionWorld; - delete mCollisionConfiguration; - delete mDispatcher; - delete mBroadphase; } void PhysicsSystem::setUnrefQueue(SceneUtil::UnrefQueue *unrefQueue) @@ -132,13 +124,13 @@ namespace MWPhysics { mDebugDrawEnabled = !mDebugDrawEnabled; - if (mDebugDrawEnabled && !mDebugDrawer.get()) + if (mDebugDrawEnabled && !mDebugDrawer) { - mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mCollisionWorld)); + mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mCollisionWorld.get())); mCollisionWorld->setDebugDrawer(mDebugDrawer.get()); mDebugDrawer->setDebugMode(mDebugDrawEnabled); } - else if (mDebugDrawer.get()) + else if (mDebugDrawer) mDebugDrawer->setDebugMode(mDebugDrawEnabled); return mDebugDrawEnabled; } @@ -175,11 +167,11 @@ namespace MWPhysics std::pair PhysicsSystem::getHitContact(const MWWorld::ConstPtr& actor, const osg::Vec3f &origin, const osg::Quat &orient, - float queryDistance, std::vector targets) + float queryDistance, std::vector& targets) { // First of all, try to hit where you aim to int hitmask = CollisionType_World | CollisionType_Door | CollisionType_HeightMap | CollisionType_Actor; - RayResult result = castRay(origin, origin + (orient * osg::Vec3f(0.0f, queryDistance, 0.0f)), actor, targets, hitmask, CollisionType_Actor); + RayCastingResult result = castRay(origin, origin + (orient * osg::Vec3f(0.0f, queryDistance, 0.0f)), actor, targets, hitmask, CollisionType_Actor); if (result.mHit) { @@ -221,7 +213,7 @@ namespace MWPhysics DeepestNotMeContactTestResultCallback resultCallback(me, targetCollisionObjects, Misc::Convert::toBullet(origin)); resultCallback.m_collisionFilterGroup = CollisionType_Actor; resultCallback.m_collisionFilterMask = CollisionType_World | CollisionType_Door | CollisionType_HeightMap | CollisionType_Actor; - mCollisionWorld->contactTest(&object, resultCallback); + mTaskScheduler->contactTest(&object, resultCallback); if (resultCallback.mObject) { @@ -245,25 +237,22 @@ namespace MWPhysics rayFrom.setIdentity(); rayFrom.setOrigin(Misc::Convert::toBullet(point)); - // target the collision object's world origin, this should be the center of the collision object - btTransform rayTo; - rayTo.setIdentity(); - rayTo.setOrigin(targetCollisionObj->getWorldTransform().getOrigin()); + auto hitpoint = mTaskScheduler->getHitPoint(rayFrom, targetCollisionObj); + if (hitpoint) + return (point - Misc::Convert::toOsg(hitpoint.get())).length(); - btCollisionWorld::ClosestRayResultCallback cb(rayFrom.getOrigin(), rayTo.getOrigin()); - - btCollisionWorld::rayTestSingle(rayFrom, rayTo, targetCollisionObj, targetCollisionObj->getCollisionShape(), targetCollisionObj->getWorldTransform(), cb); - if (!cb.hasHit()) - { - // didn't hit the target. this could happen if point is already inside the collision box - return 0.f; - } - else - return (point - Misc::Convert::toOsg(cb.m_hitPointWorld)).length(); + // didn't hit the target. this could happen if point is already inside the collision box + return 0.f; } - PhysicsSystem::RayResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore, std::vector targets, int mask, int group) const + RayCastingResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore, std::vector targets, int mask, int group) const { + if (from == to) + { + RayCastingResult result; + result.mHit = false; + return result; + } btVector3 btFrom = Misc::Convert::toBullet(from); btVector3 btTo = Misc::Convert::toBullet(to); @@ -297,9 +286,9 @@ namespace MWPhysics resultCallback.m_collisionFilterGroup = group; resultCallback.m_collisionFilterMask = mask; - mCollisionWorld->rayTest(btFrom, btTo, resultCallback); + mTaskScheduler->rayTest(btFrom, btTo, resultCallback); - RayResult result; + RayCastingResult result; result.mHit = resultCallback.hasHit(); if (resultCallback.hasHit()) { @@ -311,7 +300,7 @@ namespace MWPhysics return result; } - PhysicsSystem::RayResult PhysicsSystem::castSphere(const osg::Vec3f &from, const osg::Vec3f &to, float radius) + RayCastingResult PhysicsSystem::castSphere(const osg::Vec3f &from, const osg::Vec3f &to, float radius) const { btCollisionWorld::ClosestConvexResultCallback callback(Misc::Convert::toBullet(from), Misc::Convert::toBullet(to)); callback.m_collisionFilterGroup = 0xff; @@ -323,9 +312,9 @@ namespace MWPhysics btTransform from_ (btrot, Misc::Convert::toBullet(from)); btTransform to_ (btrot, Misc::Convert::toBullet(to)); - mCollisionWorld->convexSweepTest(&shape, from_, to_, callback); + mTaskScheduler->convexSweepTest(&shape, from_, to_, callback); - RayResult result; + RayCastingResult result; result.mHit = callback.hasHit(); if (result.mHit) { @@ -337,18 +326,15 @@ namespace MWPhysics bool PhysicsSystem::getLineOfSight(const MWWorld::ConstPtr &actor1, const MWWorld::ConstPtr &actor2) const { - const Actor* physactor1 = getActor(actor1); - const Actor* physactor2 = getActor(actor2); + const auto getWeakPtr = [&](const MWWorld::ConstPtr &ptr) -> std::weak_ptr + { + const auto found = mActors.find(ptr); + if (found != mActors.end()) + return { found->second }; + return {}; + }; - if (!physactor1 || !physactor2) - return false; - - osg::Vec3f pos1 (physactor1->getCollisionObjectPosition() + osg::Vec3f(0,0,physactor1->getHalfExtents().z() * 0.9)); // eye level - osg::Vec3f pos2 (physactor2->getCollisionObjectPosition() + osg::Vec3f(0,0,physactor2->getHalfExtents().z() * 0.9)); - - RayResult result = castRay(pos1, pos2, MWWorld::ConstPtr(), std::vector(), CollisionType_World|CollisionType_HeightMap|CollisionType_Door); - - return !result.mHit; + return mTaskScheduler->getLineOfSight(getWeakPtr(actor1), getWeakPtr(actor2)); } bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor) @@ -367,7 +353,7 @@ namespace MWPhysics const osg::Vec3f startingPosition(actorPosition.x(), actorPosition.y(), actorPosition.z() + halfZ); const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + halfZ); ActorTracer tracer; - tracer.doTrace(physicActor->getCollisionObject(), startingPosition, destinationPosition, mCollisionWorld); + tracer.doTrace(physicActor->getCollisionObject(), startingPosition, destinationPosition, mCollisionWorld.get()); return (tracer.mFraction >= 1.0f); } @@ -402,7 +388,7 @@ namespace MWPhysics const Object * physobject = getObject(object); if (!physobject) return osg::BoundingBox(); btVector3 min, max; - physobject->getCollisionObject()->getCollisionShape()->getAabb(physobject->getCollisionObject()->getWorldTransform(), min, max); + mTaskScheduler->getAabb(physobject->getCollisionObject(), min, max); return osg::BoundingBox(Misc::Convert::toOsg(min), Misc::Convert::toOsg(max)); } @@ -428,7 +414,7 @@ namespace MWPhysics ContactTestResultCallback resultCallback (me); resultCallback.m_collisionFilterGroup = collisionGroup; resultCallback.m_collisionFilterMask = collisionMask; - mCollisionWorld->contactTest(me, resultCallback); + mTaskScheduler->contactTest(me, resultCallback); return resultCallback.mResult; } @@ -438,7 +424,7 @@ namespace MWPhysics if (found == mActors.end()) return ptr.getRefData().getPosition().asVec3(); else - return MovementSolver::traceDown(ptr, position, found->second, mCollisionWorld, maxHeight); + return MovementSolver::traceDown(ptr, position, found->second.get(), mCollisionWorld.get(), maxHeight); } void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject) @@ -446,7 +432,7 @@ namespace MWPhysics HeightField *heightfield = new HeightField(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject); mHeightFields[std::make_pair(x,y)] = heightfield; - mCollisionWorld->addCollisionObject(heightfield->getCollisionObject(), CollisionType_HeightMap, + mTaskScheduler->addCollisionObject(heightfield->getCollisionObject(), CollisionType_HeightMap, CollisionType_Actor|CollisionType_Projectile); } @@ -455,7 +441,7 @@ namespace MWPhysics HeightFieldMap::iterator heightfield = mHeightFields.find(std::make_pair(x,y)); if(heightfield != mHeightFields.end()) { - mCollisionWorld->removeCollisionObject(heightfield->second->getCollisionObject()); + mTaskScheduler->removeCollisionObject(heightfield->second->getCollisionObject()); delete heightfield->second; mHeightFields.erase(heightfield); } @@ -475,13 +461,13 @@ namespace MWPhysics if (!shapeInstance || !shapeInstance->getCollisionShape()) return; - Object *obj = new Object(ptr, shapeInstance); + auto obj = std::make_shared(ptr, shapeInstance, mTaskScheduler.get()); mObjects.emplace(ptr, obj); if (obj->isAnimated()) - mAnimatedObjects.insert(obj); + mAnimatedObjects.insert(obj.get()); - mCollisionWorld->addCollisionObject(obj->getCollisionObject(), collisionType, + mTaskScheduler->addCollisionObject(obj->getCollisionObject(), collisionType, CollisionType_Actor|CollisionType_HeightMap|CollisionType_Projectile); } @@ -490,21 +476,17 @@ namespace MWPhysics ObjectMap::iterator found = mObjects.find(ptr); if (found != mObjects.end()) { - mCollisionWorld->removeCollisionObject(found->second->getCollisionObject()); - if (mUnrefQueue.get()) mUnrefQueue->push(found->second->getShapeInstance()); - mAnimatedObjects.erase(found->second); + mAnimatedObjects.erase(found->second.get()); - delete found->second; mObjects.erase(found); } ActorMap::iterator foundActor = mActors.find(ptr); if (foundActor != mActors.end()) { - delete foundActor->second; mActors.erase(foundActor); } } @@ -530,19 +512,19 @@ namespace MWPhysics ObjectMap::iterator found = mObjects.find(old); if (found != mObjects.end()) { - Object* obj = found->second; + auto obj = found->second; obj->updatePtr(updated); mObjects.erase(found); - mObjects.emplace(updated, obj); + mObjects.emplace(updated, std::move(obj)); } ActorMap::iterator foundActor = mActors.find(old); if (foundActor != mActors.end()) { - Actor* actor = foundActor->second; + auto actor = foundActor->second; actor->updatePtr(updated); mActors.erase(foundActor); - mActors.emplace(updated, actor); + mActors.emplace(updated, std::move(actor)); } updateCollisionMapPtr(mStandingCollisions, old, updated); @@ -552,7 +534,7 @@ namespace MWPhysics { ActorMap::iterator found = mActors.find(ptr); if (found != mActors.end()) - return found->second; + return found->second.get(); return nullptr; } @@ -560,7 +542,7 @@ namespace MWPhysics { ActorMap::const_iterator found = mActors.find(ptr); if (found != mActors.end()) - return found->second; + return found->second.get(); return nullptr; } @@ -568,7 +550,7 @@ namespace MWPhysics { ObjectMap::const_iterator found = mObjects.find(ptr); if (found != mObjects.end()) - return found->second; + return found->second.get(); return nullptr; } @@ -579,14 +561,14 @@ namespace MWPhysics { float scale = ptr.getCellRef().getScale(); found->second->setScale(scale); - mCollisionWorld->updateSingleAabb(found->second->getCollisionObject()); + mTaskScheduler->updateSingleAabb(found->second); return; } ActorMap::iterator foundActor = mActors.find(ptr); if (foundActor != mActors.end()) { foundActor->second->updateScale(); - mCollisionWorld->updateSingleAabb(foundActor->second->getCollisionObject()); + mTaskScheduler->updateSingleAabb(foundActor->second); return; } } @@ -597,7 +579,7 @@ namespace MWPhysics if (found != mObjects.end()) { found->second->setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude())); - mCollisionWorld->updateSingleAabb(found->second->getCollisionObject()); + mTaskScheduler->updateSingleAabb(found->second); return; } ActorMap::iterator foundActor = mActors.find(ptr); @@ -606,7 +588,7 @@ namespace MWPhysics if (!foundActor->second->isRotationallyInvariant()) { foundActor->second->updateRotation(); - mCollisionWorld->updateSingleAabb(foundActor->second->getCollisionObject()); + mTaskScheduler->updateSingleAabb(foundActor->second); } return; } @@ -618,14 +600,14 @@ namespace MWPhysics if (found != mObjects.end()) { found->second->setOrigin(Misc::Convert::toBullet(ptr.getRefData().getPosition().asVec3())); - mCollisionWorld->updateSingleAabb(found->second->getCollisionObject()); + mTaskScheduler->updateSingleAabb(found->second); return; } ActorMap::iterator foundActor = mActors.find(ptr); if (foundActor != mActors.end()) { foundActor->second->updatePosition(); - mCollisionWorld->updateSingleAabb(foundActor->second->getCollisionObject()); + mTaskScheduler->updateSingleAabb(foundActor->second); return; } } @@ -633,11 +615,9 @@ namespace MWPhysics void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh) { osg::ref_ptr shape = mShapeManager->getShape(mesh); - if (!shape) - return; // Try to get shape from basic model as fallback for creatures - if (!ptr.getClass().isNpc() && shape->mCollisionBoxHalfExtents.length2() == 0) + if (!ptr.getClass().isNpc() && shape && shape->mCollisionBoxHalfExtents.length2() == 0) { const std::string fallbackModel = ptr.getClass().getModel(ptr); if (fallbackModel != mesh) @@ -646,8 +626,11 @@ namespace MWPhysics } } - Actor* actor = new Actor(ptr, shape, mCollisionWorld); - mActors.emplace(ptr, actor); + if (!shape) + return; + + auto actor = std::make_shared(ptr, shape, mTaskScheduler.get()); + mActors.emplace(ptr, std::move(actor)); } bool PhysicsSystem::toggleCollisionMode() @@ -685,99 +668,76 @@ namespace MWPhysics mStandingCollisions.clear(); } - const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt) + const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation) { - mMovementResults.clear(); - mTimeAccum += dt; const int maxAllowedSteps = 20; - int numSteps = mTimeAccum / (mPhysicsDt); + int numSteps = mTimeAccum / mPhysicsDt; numSteps = std::min(numSteps, maxAllowedSteps); mTimeAccum -= numSteps * mPhysicsDt; - if (numSteps) - { - // Collision events should be available on every frame - mStandingCollisions.clear(); - } + return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(), mStandingCollisions, skipSimulation); + } - const MWWorld::Ptr player = MWMechanics::getPlayer(); + std::vector PhysicsSystem::prepareFrameData() + { + std::vector actorsFrameData; + actorsFrameData.reserve(mMovementQueue.size()); const MWBase::World *world = MWBase::Environment::get().getWorld(); - for(auto& movementItem : mMovementQueue) + for (const auto& m : mMovementQueue) { - ActorMap::iterator foundActor = mActors.find(movementItem.first); + const auto& character = m.first; + const auto& movement = m.second; + const auto foundActor = mActors.find(character); if (foundActor == mActors.end()) // actor was already removed from the scene + { + mStandingCollisions.erase(character); continue; - Actor* physicActor = foundActor->second; + } + auto physicActor = foundActor->second; float waterlevel = -std::numeric_limits::max(); - const MWWorld::CellStore *cell = movementItem.first.getCell(); + const MWWorld::CellStore *cell = character.getCell(); if(cell->getCell()->hasWater()) waterlevel = cell->getWaterLevel(); - const MWMechanics::MagicEffects& effects = movementItem.first.getClass().getCreatureStats(movementItem.first).getMagicEffects(); + const MWMechanics::MagicEffects& effects = character.getClass().getCreatureStats(character).getMagicEffects(); bool waterCollision = false; + bool moveToWaterSurface = false; if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude()) { - if (!world->isUnderwater(movementItem.first.getCell(), osg::Vec3f(movementItem.first.getRefData().getPosition().asVec3()))) + if (!world->isUnderwater(character.getCell(), osg::Vec3f(character.getRefData().getPosition().asVec3()))) waterCollision = true; - else if (physicActor->getCollisionMode() && canMoveToWaterSurface(movementItem.first, waterlevel)) + else if (physicActor->getCollisionMode() && canMoveToWaterSurface(character, waterlevel)) { - const osg::Vec3f actorPosition = physicActor->getPosition(); - physicActor->setPosition(osg::Vec3f(actorPosition.x(), actorPosition.y(), waterlevel)); + moveToWaterSurface = true; waterCollision = true; } } + physicActor->setCanWaterWalk(waterCollision); // Slow fall reduces fall speed by a factor of (effect magnitude / 200) - float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f)); + const float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f)); - bool flying = world->isFlying(movementItem.first); - bool swimming = world->isSwimming(movementItem.first); - - bool wasOnGround = physicActor->getOnGround(); - osg::Vec3f position = physicActor->getPosition(); - float oldHeight = position.z(); - bool positionChanged = false; - for (int i=0; igetPtr(), physicActor, movementItem.second, mPhysicsDt, - flying, waterlevel, slowFall, mCollisionWorld, mStandingCollisions); - if (position != physicActor->getPosition()) - positionChanged = true; - physicActor->setPosition(position); // always set even if unchanged to make sure interpolation is correct - } - if (positionChanged) - mCollisionWorld->updateSingleAabb(physicActor->getCollisionObject()); - - float interpolationFactor = mTimeAccum / mPhysicsDt; - osg::Vec3f interpolated = position * interpolationFactor + physicActor->getPreviousPosition() * (1.f - interpolationFactor); - - float heightDiff = position.z() - oldHeight; - - MWMechanics::CreatureStats& stats = movementItem.first.getClass().getCreatureStats(movementItem.first); - bool isStillOnGround = (numSteps > 0 && wasOnGround && physicActor->getOnGround()); - if (isStillOnGround || flying || swimming || slowFall < 1) - stats.land(movementItem.first == player && (flying || swimming)); - else if (heightDiff < 0) - stats.addToFallHeight(-heightDiff); - - mMovementResults.emplace_back(movementItem.first, interpolated); + actorsFrameData.emplace_back(std::move(physicActor), character, mStandingCollisions[character], moveToWaterSurface, movement, slowFall, waterlevel); } - mMovementQueue.clear(); - - return mMovementResults; + return actorsFrameData; } - void PhysicsSystem::stepSimulation(float dt) + void PhysicsSystem::stepSimulation() { - for (Object* animatedObject : mAnimatedObjects) - animatedObject->animateCollisionShapes(mCollisionWorld); + for (Object* animatedObject : mAnimatedObjects) + if (animatedObject->animateCollisionShapes()) + { + auto obj = mObjects.find(animatedObject->getPtr()); + assert(obj != mObjects.end()); + mTaskScheduler->updateSingleAabb(obj->second); + } #ifndef BT_NO_PROFILE CProfileManager::Reset(); @@ -789,12 +749,13 @@ namespace MWPhysics { ObjectMap::iterator found = mObjects.find(object); if (found != mObjects.end()) - found->second->animateCollisionShapes(mCollisionWorld); + if (found->second->animateCollisionShapes()) + mTaskScheduler->updateSingleAabb(found->second); } void PhysicsSystem::debugDraw() { - if (mDebugDrawer.get()) + if (mDebugDrawer) mDebugDrawer->step(); } @@ -859,9 +820,9 @@ namespace MWPhysics void PhysicsSystem::updateWater() { - if (mWaterCollisionObject.get()) + if (mWaterCollisionObject) { - mCollisionWorld->removeCollisionObject(mWaterCollisionObject.get()); + mTaskScheduler->removeCollisionObject(mWaterCollisionObject.get()); } if (!mWaterEnabled) @@ -873,7 +834,7 @@ namespace MWPhysics mWaterCollisionObject.reset(new btCollisionObject()); mWaterCollisionShape.reset(new btStaticPlaneShape(btVector3(0,0,1), mWaterHeight)); mWaterCollisionObject->setCollisionShape(mWaterCollisionShape.get()); - mCollisionWorld->addCollisionObject(mWaterCollisionObject.get(), CollisionType_Water, + mTaskScheduler->addCollisionObject(mWaterCollisionObject.get(), CollisionType_Water, CollisionType_Actor); } @@ -889,7 +850,7 @@ namespace MWPhysics const int mask = MWPhysics::CollisionType_Actor; const int group = 0xff; HasSphereCollisionCallback callback(bulletPosition, radius, object, mask, group); - mCollisionWorld->getBroadphase()->aabbTest(aabbMin, aabbMax, callback); + mTaskScheduler->aabbTest(aabbMin, aabbMax, callback); return callback.getResult(); } @@ -899,4 +860,61 @@ namespace MWPhysics stats.setAttribute(frameNumber, "Physics Objects", mObjects.size()); stats.setAttribute(frameNumber, "Physics HeightFields", mHeightFields.size()); } + + ActorFrameData::ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr character, const MWWorld::Ptr standingOn, + bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel) + : mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn), + mPositionChanged(false), mDidJump(false), mNeedLand(false), mMoveToWaterSurface(moveToWaterSurface), + mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(movement), mPosition(), mRefpos() + { + const MWBase::World *world = MWBase::Environment::get().getWorld(); + mPtr = actor->getPtr(); + mFlying = world->isFlying(character); + mSwimming = world->isSwimming(character); + mWantJump = mPtr.getClass().getMovementSettings(mPtr).mPosition[2] != 0; + mIsDead = mPtr.getClass().getCreatureStats(mPtr).isDead(); + mWasOnGround = actor->getOnGround(); + } + + void ActorFrameData::updatePosition() + { + mPosition = mActorRaw->getPosition(); + if (mMoveToWaterSurface) + { + mPosition.z() = mWaterlevel; + mActorRaw->setPosition(mPosition); + } + mOldHeight = mPosition.z(); + mRefpos = mPtr.getRefData().getPosition(); + } + + WorldFrameData::WorldFrameData() + : mIsInStorm(MWBase::Environment::get().getWorld()->isInStorm()) + , mStormDirection(MWBase::Environment::get().getWorld()->getStormDirection()) + {} + + LOSRequest::LOSRequest(const std::weak_ptr& a1, const std::weak_ptr& a2) + : mResult(false), mStale(false), mAge(0) + { + // we use raw actor pointer pair to uniquely identify request + // sort the pointer value in ascending order to not duplicate equivalent requests, eg. getLOS(A, B) and getLOS(B, A) + auto* raw1 = a1.lock().get(); + auto* raw2 = a2.lock().get(); + assert(raw1 != raw2); + if (raw1 < raw2) + { + mActors = {a1, a2}; + mRawActors = {raw1, raw2}; + } + else + { + mActors = {a2, a1}; + mRawActors = {raw2, raw1}; + } + } + + bool operator==(const LOSRequest& lhs, const LOSRequest& rhs) noexcept + { + return lhs.mRawActors == rhs.mRawActors; + } } diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 32d460b1d..f89a29cae 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_MWPHYSICS_PHYSICSSYSTEM_H #define OPENMW_MWPHYSICS_PHYSICSSYSTEM_H +#include #include #include #include @@ -13,6 +14,7 @@ #include "../mwworld/ptr.hpp" #include "collisiontype.hpp" +#include "raycasting.hpp" namespace osg { @@ -46,17 +48,63 @@ class btCollisionShape; namespace MWPhysics { - typedef std::vector > PtrVelocityList; + using PtrPositionList = std::map; + using CollisionMap = std::map; class HeightField; class Object; class Actor; + class PhysicsTaskScheduler; - class PhysicsSystem + struct LOSRequest + { + LOSRequest(const std::weak_ptr& a1, const std::weak_ptr& a2); + std::array, 2> mActors; + std::array mRawActors; + bool mResult; + bool mStale; + int mAge; + }; + bool operator==(const LOSRequest& lhs, const LOSRequest& rhs) noexcept; + + struct ActorFrameData + { + ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr character, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel); + void updatePosition(); + std::weak_ptr mActor; + Actor* mActorRaw; + MWWorld::Ptr mPtr; + MWWorld::Ptr mStandingOn; + bool mFlying; + bool mSwimming; + bool mPositionChanged; + bool mWasOnGround; + bool mWantJump; + bool mDidJump; + bool mIsDead; + bool mNeedLand; + bool mMoveToWaterSurface; + float mWaterlevel; + float mSlowFall; + float mOldHeight; + float mFallHeight; + osg::Vec3f mMovement; + osg::Vec3f mPosition; + ESM::Position mRefpos; + }; + + struct WorldFrameData + { + WorldFrameData(); + bool mIsInStorm; + osg::Vec3f mStormDirection; + }; + + class PhysicsSystem : public RayCastingInterface { public: PhysicsSystem (Resource::ResourceSystem* resourceSystem, osg::ref_ptr parentNode); - ~PhysicsSystem (); + virtual ~PhysicsSystem (); void setUnrefQueue(SceneUtil::UnrefQueue* unrefQueue); @@ -92,7 +140,7 @@ namespace MWPhysics bool toggleCollisionMode(); - void stepSimulation(float dt); + void stepSimulation(); void debugDraw(); std::vector getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with @@ -101,32 +149,24 @@ namespace MWPhysics std::pair getHitContact(const MWWorld::ConstPtr& actor, const osg::Vec3f &origin, const osg::Quat &orientation, - float queryDistance, std::vector targets = std::vector()); + float queryDistance, std::vector& targets); /// Get distance from \a point to the collision shape of \a target. Uses a raycast to find where the /// target vector hits the collision shape and then calculates distance from the intersection point. /// This can be used to find out how much nearer we need to move to the target for a "getHitContact" to be successful. /// \note Only Actor targets are supported at the moment. - float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const; - - struct RayResult - { - bool mHit; - osg::Vec3f mHitPos; - osg::Vec3f mHitNormal; - MWWorld::Ptr mHitObject; - }; + float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const final; /// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors. - RayResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(), + RayCastingResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(), std::vector targets = std::vector(), - int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const; + int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const final; - RayResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius); + RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const final; /// Return true if actor1 can see actor2. - bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const; + bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const final; bool isOnGround (const MWWorld::Ptr& actor); @@ -153,7 +193,7 @@ namespace MWPhysics void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity); /// Apply all queued movements, then clear the list. - const PtrVelocityList& applyQueuedMovement(float dt); + const PtrPositionList& applyQueuedMovement(float dt, bool skipSimulation); /// Clear the queued movements list without applying. void clearQueuedMovement(); @@ -197,39 +237,41 @@ namespace MWPhysics void updateWater(); + std::vector prepareFrameData(); + osg::ref_ptr mUnrefQueue; - btBroadphaseInterface* mBroadphase; - btDefaultCollisionConfiguration* mCollisionConfiguration; - btCollisionDispatcher* mDispatcher; - btCollisionWorld* mCollisionWorld; + std::unique_ptr mBroadphase; + std::unique_ptr mCollisionConfiguration; + std::unique_ptr mDispatcher; + std::shared_ptr mCollisionWorld; + std::unique_ptr mTaskScheduler; std::unique_ptr mShapeManager; Resource::ResourceSystem* mResourceSystem; - typedef std::map ObjectMap; + using ObjectMap = std::map>; ObjectMap mObjects; std::set mAnimatedObjects; // stores pointers to elements in mObjects - typedef std::map ActorMap; + using ActorMap = std::map>; ActorMap mActors; - typedef std::map, HeightField*> HeightFieldMap; + using HeightFieldMap = std::map, HeightField *>; HeightFieldMap mHeightFields; bool mDebugDrawEnabled; // Tracks standing collisions happening during a single frame. // This will detect standing on an object, but won't detect running e.g. against a wall. - typedef std::map CollisionMap; CollisionMap mStandingCollisions; // replaces all occurrences of 'old' in the map by 'updated', no matter if it's a key or value void updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated); + using PtrVelocityList = std::vector>; PtrVelocityList mMovementQueue; - PtrVelocityList mMovementResults; float mTimeAccum; diff --git a/apps/openmw/mwphysics/raycasting.hpp b/apps/openmw/mwphysics/raycasting.hpp new file mode 100644 index 000000000..7afbe9321 --- /dev/null +++ b/apps/openmw/mwphysics/raycasting.hpp @@ -0,0 +1,41 @@ +#ifndef OPENMW_MWPHYSICS_RAYCASTING_H +#define OPENMW_MWPHYSICS_RAYCASTING_H + +#include + +#include "../mwworld/ptr.hpp" + +#include "collisiontype.hpp" + +namespace MWPhysics +{ + struct RayCastingResult + { + bool mHit; + osg::Vec3f mHitPos; + osg::Vec3f mHitNormal; + MWWorld::Ptr mHitObject; + }; + + class RayCastingInterface + { + public: + /// Get distance from \a point to the collision shape of \a target. Uses a raycast to find where the + /// target vector hits the collision shape and then calculates distance from the intersection point. + /// This can be used to find out how much nearer we need to move to the target for a "getHitContact" to be successful. + /// \note Only Actor targets are supported at the moment. + virtual float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const = 0; + + /// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors. + virtual RayCastingResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(), + std::vector targets = std::vector(), + int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const = 0; + + virtual RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const = 0; + + /// Return true if actor1 can see actor2. + virtual bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const = 0; + }; +} + +#endif diff --git a/apps/openmw/mwrender/actoranimation.hpp b/apps/openmw/mwrender/actoranimation.hpp index 14c687a5d..86929a18a 100644 --- a/apps/openmw/mwrender/actoranimation.hpp +++ b/apps/openmw/mwrender/actoranimation.hpp @@ -35,11 +35,11 @@ class ActorAnimation : public Animation, public MWWorld::ContainerStoreListener ActorAnimation(const MWWorld::Ptr &ptr, osg::ref_ptr parentNode, Resource::ResourceSystem* resourceSystem); virtual ~ActorAnimation(); - virtual void itemAdded(const MWWorld::ConstPtr& item, int count); - virtual void itemRemoved(const MWWorld::ConstPtr& item, int count); + void itemAdded(const MWWorld::ConstPtr& item, int count) override; + void itemRemoved(const MWWorld::ConstPtr& item, int count) override; virtual bool isArrowAttached() const { return false; } - virtual bool useShieldAnimations() const; - bool updateCarriedLeftVisible(const int weaptype) const; + bool useShieldAnimations() const override; + bool updateCarriedLeftVisible(const int weaptype) const override; protected: osg::Group* getBoneByName(const std::string& boneName); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 7870d30fe..6b93d9a17 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -63,7 +63,7 @@ namespace : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) { } - virtual void apply(osg::Node &node) + void apply(osg::Node &node) override { if (dynamic_cast(&node)) mToRemove.push_back(&node); @@ -71,7 +71,7 @@ namespace traverse(node); } - virtual void apply(osg::Drawable& drw) + void apply(osg::Drawable& drw) override { if (osgParticle::ParticleSystem* partsys = dynamic_cast(&drw)) mToRemove.push_back(partsys); @@ -99,7 +99,7 @@ namespace { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { unsigned int state = MWBase::Environment::get().getWorld()->getNightDayMode(); const unsigned int newState = node->asGroup()->getNumChildren() > state ? state : 0; @@ -124,7 +124,7 @@ namespace : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) { } - virtual void apply(osg::Switch &switchNode) + void apply(osg::Switch &switchNode) override { if (switchNode.getName() == Constants::NightDayLabel) switchNode.addUpdateCallback(new DayNightCallback()); @@ -141,7 +141,7 @@ namespace { } - virtual void apply(osg::Switch& node) + void apply(osg::Switch& node) override { if (node.getName() == Constants::HerbalismLabel) { @@ -236,7 +236,7 @@ namespace { } - void apply(osg::Node& node) + void apply(osg::Node& node) override { if (SceneUtil::hasUserDescription(&node, "CustomBone")) { @@ -261,12 +261,12 @@ namespace { } - virtual void apply(osg::Node &node) + void apply(osg::Node &node) override { traverse(node); } - virtual void apply(osg::Group &group) + void apply(osg::Group &group) override { traverse(group); @@ -285,12 +285,12 @@ namespace } } - virtual void apply(osg::MatrixTransform &node) + void apply(osg::MatrixTransform &node) override { traverse(node); } - virtual void apply(osg::Geometry&) + void apply(osg::Geometry&) override { } }; @@ -314,12 +314,12 @@ namespace { } - virtual void apply(osg::Node &node) + void apply(osg::Node &node) override { traverse(node); } - virtual void apply(osg::Group &group) + void apply(osg::Group &group) override { traverse(group); @@ -338,12 +338,12 @@ namespace } } - virtual void apply(osg::MatrixTransform &node) + void apply(osg::MatrixTransform &node) override { traverse(node); } - virtual void apply(osg::Geometry&) + void apply(osg::Geometry&) override { } @@ -369,12 +369,12 @@ namespace { } - virtual void apply(osg::Node &node) + void apply(osg::Node &node) override { traverse(node); } - virtual void apply(osg::Group &group) + void apply(osg::Group &group) override { osg::Callback* callback = group.getUpdateCallback(); if (callback) @@ -391,12 +391,12 @@ namespace traverse(group); } - virtual void apply(osg::MatrixTransform &node) + void apply(osg::MatrixTransform &node) override { traverse(node); } - virtual void apply(osg::Geometry&) + void apply(osg::Geometry&) override { } @@ -408,20 +408,20 @@ namespace class CleanObjectRootVisitor : public RemoveVisitor { public: - virtual void apply(osg::Drawable& drw) + void apply(osg::Drawable& drw) override { applyDrawable(drw); } - virtual void apply(osg::Group& node) + void apply(osg::Group& node) override { applyNode(node); } - virtual void apply(osg::MatrixTransform& node) + void apply(osg::MatrixTransform& node) override { applyNode(node); } - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { applyNode(node); } @@ -462,16 +462,16 @@ namespace class RemoveTriBipVisitor : public RemoveVisitor { public: - virtual void apply(osg::Drawable& drw) + void apply(osg::Drawable& drw) override { applyImpl(drw); } - virtual void apply(osg::Group& node) + void apply(osg::Group& node) override { traverse(node); } - virtual void apply(osg::MatrixTransform& node) + void apply(osg::MatrixTransform& node) override { traverse(node); } @@ -506,7 +506,7 @@ namespace MWRender } protected: - virtual void setDefaults(osg::StateSet* stateset) + void setDefaults(osg::StateSet* stateset) override { osg::BlendFunc* blendfunc (new osg::BlendFunc); stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); @@ -526,7 +526,7 @@ namespace MWRender stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) + void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override { osg::Material* material = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); material->setAlpha(osg::Material::FRONT_AND_BACK, mAlpha); @@ -587,7 +587,7 @@ namespace MWRender class ResetAccumRootCallback : public osg::NodeCallback { public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osg::MatrixTransform* transform = static_cast(node); diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 35705faaa..2f2b2612d 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -45,7 +45,7 @@ class EffectAnimationTime : public SceneUtil::ControllerSource private: float mTime; public: - virtual float getValue(osg::NodeVisitor* nv); + float getValue(osg::NodeVisitor* nv) override; void addTime(float duration); void resetTime(float time); @@ -173,13 +173,13 @@ protected: std::shared_ptr getTimePtr() const { return mTimePtr; } - virtual float getValue(osg::NodeVisitor* nv); + float getValue(osg::NodeVisitor* nv) override; }; class NullAnimationTime : public SceneUtil::ControllerSource { public: - virtual float getValue(osg::NodeVisitor *nv) + float getValue(osg::NodeVisitor *nv) override { return 0.f; } @@ -474,6 +474,7 @@ public: void setAlpha(float alpha); virtual void setPitchFactor(float factor) {} virtual void attachArrow() {} + virtual void detachArrow() {} virtual void releaseArrow(float attackStrength) {} virtual void enableHeadAnimation(bool enable) {} // TODO: move outside of this class @@ -505,7 +506,7 @@ class ObjectAnimation : public Animation { public: ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem, bool animated, bool allowLight); - bool canBeHarvested() const; + bool canBeHarvested() const override; }; class UpdateVfxCallback : public osg::NodeCallback @@ -521,7 +522,7 @@ public: bool mFinished; EffectParams mParams; - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + void operator()(osg::Node* node, osg::NodeVisitor* nv) override; private: double mStartingTime; diff --git a/apps/openmw/mwrender/bulletdebugdraw.hpp b/apps/openmw/mwrender/bulletdebugdraw.hpp index 30da3aa72..30cabc4f9 100644 --- a/apps/openmw/mwrender/bulletdebugdraw.hpp +++ b/apps/openmw/mwrender/bulletdebugdraw.hpp @@ -39,19 +39,19 @@ public: void step(); - void drawLine(const btVector3& from,const btVector3& to,const btVector3& color); + void drawLine(const btVector3& from,const btVector3& to,const btVector3& color) override; - void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color); + void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) override; - void reportErrorWarning(const char* warningString); + void reportErrorWarning(const char* warningString) override; - void draw3dText(const btVector3& location,const char* textString) {} + void draw3dText(const btVector3& location,const char* textString) override {} //0 for off, anything else for on. - void setDebugMode(int isOn); + void setDebugMode(int isOn) override; //0 for off, anything else for on. - int getDebugMode() const; + int getDebugMode() const override; }; diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 6305cc421..c16324115 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -2,12 +2,14 @@ #include +#include #include #include #include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" #include "../mwworld/class.hpp" #include "../mwworld/ptr.hpp" @@ -17,6 +19,8 @@ #include "../mwmechanics/movement.hpp" #include "../mwmechanics/npcstats.hpp" +#include "../mwphysics/raycasting.hpp" + #include "npcanimation.hpp" namespace @@ -30,7 +34,7 @@ public: { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osg::Camera* cam = static_cast(node); @@ -79,6 +83,7 @@ namespace MWRender mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")), mDynamicCameraDistanceEnabled(false), mShowCrosshairInThirdPersonMode(false), + mHeadBobbingEnabled(Settings::Manager::getBool("head bobbing", "Camera")), mDeferredRotation(osg::Vec3f()), mDeferredRotationDisabled(false) { @@ -103,7 +108,9 @@ namespace MWRender osg::Matrix worldMat = osg::computeLocalToWorld(nodepaths[0]); osg::Vec3d position = worldMat.getTrans(); - if (!isFirstPerson()) + if (isFirstPerson()) + position.z() += mHeadBobbingOffset; + else { position.z() += mHeight * mHeightScale; @@ -149,8 +156,7 @@ namespace MWRender void Camera::getOrientation(osg::Quat& orientation) const { - orientation = osg::Quat(getPitch(), osg::Vec3d(1, 0, 0)) - * osg::Quat(getYaw(), osg::Vec3d(0, 0, 1)); + orientation = osg::Quat(mRoll, osg::Vec3d(0, 1, 0)) * osg::Quat(mPitch, osg::Vec3d(1, 0, 0)) * osg::Quat(mYaw, osg::Vec3d(0, 0, 1)); } void Camera::updateCamera(osg::Camera *cam) @@ -167,6 +173,24 @@ namespace MWRender cam->setViewMatrixAsLookAt(position, position + forward, up); } + void Camera::updateHeadBobbing(float duration) { + static const float doubleStepLength = Settings::Manager::getFloat("head bobbing step", "Camera") * 2; + static const float stepHeight = Settings::Manager::getFloat("head bobbing height", "Camera"); + static const float maxRoll = osg::DegreesToRadians(Settings::Manager::getFloat("head bobbing roll", "Camera")); + + if (MWBase::Environment::get().getWorld()->isOnGround(mTrackingPtr)) + mHeadBobbingWeight = std::min(mHeadBobbingWeight + duration * 5, 1.f); + else + mHeadBobbingWeight = std::max(mHeadBobbingWeight - duration * 5, 0.f); + + float doubleStepState = mTotalMovement / doubleStepLength - std::floor(mTotalMovement / doubleStepLength); // from 0 to 1 during 2 steps + float stepState = std::abs(doubleStepState * 4 - 2) - 1; // from -1 to 1 on even steps and from 1 to -1 on odd steps + float effect = (1 - std::cos(stepState * osg::DegreesToRadians(30.f))) * 7.5f; // range from 0 to 1 + float coef = std::min(mSmoothedSpeed / 300.f, 1.f) * mHeadBobbingWeight; + mHeadBobbingOffset = (0.5f - effect) * coef * stepHeight; // range from -stepHeight/2 to stepHeight/2 + mRoll = osg::sign(stepState) * effect * coef * maxRoll; // range from -maxRoll to maxRoll + } + void Camera::reset() { togglePreviewMode(false); @@ -217,9 +241,16 @@ namespace MWRender if(mMode == Mode::Vanity) rotateCamera(0.f, 0.f, osg::DegreesToRadians(3.f * duration), true); - updateFocalPointOffset(duration); + if (isFirstPerson() && mHeadBobbingEnabled) + updateHeadBobbing(duration); + else + mRoll = mHeadBobbingOffset = 0; - float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); + updateFocalPointOffset(duration); + updatePosition(); + + float speed = mTrackingPtr.getClass().getCurrentSpeed(mTrackingPtr); + mTotalMovement += speed * duration; speed /= (1.f + speed / 500.f); float maxDelta = 300.f * duration; mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); @@ -228,11 +259,47 @@ namespace MWRender updateStandingPreviewMode(); } + void Camera::updatePosition() + { + mFocalPointAdjustment = osg::Vec3d(); + if (isFirstPerson()) + return; + + const float cameraObstacleLimit = 5.0f; + const float focalObstacleLimit = 10.f; + + const auto* rayCasting = MWBase::Environment::get().getWorld()->getRayCasting(); + + // Adjust focal point to prevent clipping. + osg::Vec3d focal = getFocalPoint(); + osg::Vec3d focalOffset = getFocalPointOffset(); + float offsetLen = focalOffset.length(); + if (offsetLen > 0) + { + MWPhysics::RayCastingResult result = rayCasting->castSphere(focal - focalOffset, focal, focalObstacleLimit); + if (result.mHit) + { + double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen; + mFocalPointAdjustment = focalOffset * std::max(-1.0, adjustmentCoef); + } + } + + // Calculate camera distance. + mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection(); + if (mDynamicCameraDistanceEnabled) + mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance); + osg::Vec3d cameraPos; + getPosition(focal, cameraPos); + MWPhysics::RayCastingResult result = rayCasting->castSphere(focal, cameraPos, cameraObstacleLimit); + if (result.mHit) + mCameraDistance = (result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length(); + } + void Camera::updateStandingPreviewMode() { if (!mStandingPreviewAllowed) return; - float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); + float speed = mTrackingPtr.getClass().getCurrentSpeed(mTrackingPtr); bool combat = mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing; bool standingStill = speed == 0 && !combat && !mFirstPersonView; @@ -379,12 +446,7 @@ namespace MWRender void Camera::setYaw(float angle) { - if (angle > osg::PI) { - angle -= osg::PI*2; - } else if (angle < -osg::PI) { - angle += osg::PI*2; - } - mYaw = angle; + mYaw = Misc::normalizeAngle(angle); } void Camera::setPitch(float angle) @@ -401,27 +463,24 @@ namespace MWRender return mCameraDistance; } - void Camera::updateBaseCameraDistance(float dist, bool adjust) + void Camera::adjustCameraDistance(float delta) { - if (isFirstPerson()) - return; + if (!isFirstPerson()) + { + if(isNearest() && delta < 0.f && getMode() != Mode::Preview && getMode() != Mode::Vanity) + toggleViewMode(); + else + mBaseCameraDistance = std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance) + delta; + } + else if (delta > 0.f) + { + toggleViewMode(); + mBaseCameraDistance = 0; + } - if (adjust) - dist += std::min(mCameraDistance - getCameraDistanceCorrection(), mBaseCameraDistance); - - mIsNearest = dist <= mNearest; - mBaseCameraDistance = osg::clampBetween(dist, mNearest, mFurthest); + mIsNearest = mBaseCameraDistance <= mNearest; + mBaseCameraDistance = osg::clampBetween(mBaseCameraDistance, mNearest, mFurthest); Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance); - setCameraDistance(); - } - - void Camera::setCameraDistance(float dist, bool adjust) - { - if (isFirstPerson()) - return; - if (adjust) - dist += mCameraDistance; - mCameraDistance = osg::clampBetween(dist, 10.f, mFurthest); } float Camera::getCameraDistanceCorrection() const @@ -437,16 +496,6 @@ namespace MWRender return pitchCorrection + speedCorrection; } - void Camera::setCameraDistance() - { - mFocalPointAdjustment = osg::Vec3d(); - if (isFirstPerson()) - return; - mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection(); - if (mDynamicCameraDistanceEnabled) - mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance); - } - void Camera::setAnimation(NpcAnimation *anim) { mAnimation = anim; @@ -534,16 +583,8 @@ namespace MWRender 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; + mDeferredRotation.x() = Misc::normalizeAngle(-ptr.getRefData().getPosition().rot[0] - mPitch); + mDeferredRotation.z() = Misc::normalizeAngle(-ptr.getRefData().getPosition().rot[2] - mYaw); } } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 7e7b1ab9b..f59b4a3d2 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -47,7 +47,7 @@ namespace MWRender bool mIsNearest; float mHeight, mBaseCameraDistance; - float mPitch, mYaw; + float mPitch, mYaw, mRoll; bool mVanityToggleQueued; bool mVanityToggleQueuedValue; @@ -73,7 +73,14 @@ namespace MWRender bool mDynamicCameraDistanceEnabled; bool mShowCrosshairInThirdPersonMode; + bool mHeadBobbingEnabled; + float mHeadBobbingOffset; + float mHeadBobbingWeight = 0; // Value from 0 to 1 for smooth enabling/disabling. + float mTotalMovement = 0; // Needed for head bobbing. + void updateHeadBobbing(float duration); + void updateFocalPointOffset(float duration); + void updatePosition(); float getCameraDistanceCorrection() const; osg::ref_ptr mUpdateCallback; @@ -139,17 +146,8 @@ namespace MWRender void update(float duration, bool paused=false); - /// Set base camera distance for current mode. Don't work on 1st person view. - /// \param adjust Indicates should distance be adjusted or set. - void updateBaseCameraDistance(float dist, bool adjust = false); - - /// Set camera distance for current mode. Don't work on 1st person view. - /// \param adjust Indicates should distance be adjusted or set. - /// Default distance can be restored with setCameraDistance(). - void setCameraDistance(float dist, bool adjust = false); - - /// Restore default camera distance and offset for current mode. - void setCameraDistance(); + /// Adds distDelta to the camera distance. Switches 3rd/1st person view if distance is less than limit. + void adjustCameraDistance(float distDelta); float getCameraDistance() const; @@ -159,7 +157,6 @@ namespace MWRender osg::Vec3d getFocalPoint() const; osg::Vec3d getFocalPointOffset() const; - void adjustFocalPoint(osg::Vec3d adjustment) { mFocalPointAdjustment = adjustment; } /// Stores focal and camera world positions in passed arguments virtual void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const; diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index b2552e598..89db3e5f4 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -41,7 +41,7 @@ namespace MWRender { } - virtual void operator () (osg::Node* node, osg::NodeVisitor* nv) + void operator () (osg::Node* node, osg::NodeVisitor* nv) override { if (!mRendered) { @@ -89,7 +89,7 @@ namespace MWRender { } - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { if (osg::StateSet* stateset = node.getStateSet()) { @@ -432,7 +432,7 @@ namespace MWRender { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osg::Camera* cam = static_cast(node); diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index b71bffb62..3eb968846 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -86,7 +86,7 @@ namespace MWRender protected: osg::ref_ptr mViewport; - virtual void onSetup(); + void onSetup() override; }; class UpdateCameraCallback; @@ -98,8 +98,8 @@ namespace MWRender protected: - virtual bool renderHeadOnly() { return true; } - virtual void onSetup(); + bool renderHeadOnly() override { return true; } + void onSetup() override; public: RaceSelectionPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem); diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 489a7a987..f1df6c90f 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -208,6 +208,12 @@ bool CreatureWeaponAnimation::isArrowAttached() const return mAmmunition != nullptr; } +void CreatureWeaponAnimation::detachArrow() +{ + WeaponAnimation::detachArrow(mPtr); + updateQuiver(); +} + void CreatureWeaponAnimation::attachArrow() { WeaponAnimation::attachArrow(mPtr); @@ -246,11 +252,15 @@ osg::Group *CreatureWeaponAnimation::getArrowBone() int type = weapon->get()->mBase->mData.mType; int ammoType = MWMechanics::getWeaponType(type)->mAmmoType; - SceneUtil::FindByNameVisitor findVisitor (MWMechanics::getWeaponType(ammoType)->mAttachBone); - - mWeapon->getNode()->accept(findVisitor); - - return findVisitor.mFoundNode; + // Try to find and attachment bone in actor's skeleton, otherwise fall back to the ArrowBone in weapon's mesh + osg::Group* bone = getBoneByName(MWMechanics::getWeaponType(ammoType)->mAttachBone); + if (bone == nullptr) + { + SceneUtil::FindByNameVisitor findVisitor ("ArrowBone"); + mWeapon->getNode()->accept(findVisitor); + bone = findVisitor.mFoundNode; + } + return bone; } osg::Node *CreatureWeaponAnimation::getWeaponNode() diff --git a/apps/openmw/mwrender/creatureanimation.hpp b/apps/openmw/mwrender/creatureanimation.hpp index cdcdafe24..9169e4102 100644 --- a/apps/openmw/mwrender/creatureanimation.hpp +++ b/apps/openmw/mwrender/creatureanimation.hpp @@ -28,36 +28,37 @@ namespace MWRender CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem); virtual ~CreatureWeaponAnimation() {} - virtual void equipmentChanged() { updateParts(); } + void equipmentChanged() override { updateParts(); } - virtual void showWeapons(bool showWeapon); + void showWeapons(bool showWeapon) override; - virtual bool getCarriedLeftShown() const { return mShowCarriedLeft; } - virtual void showCarriedLeft(bool show); + bool getCarriedLeftShown() const override { return mShowCarriedLeft; } + void showCarriedLeft(bool show) override; void updateParts(); void updatePart(PartHolderPtr& scene, int slot); - virtual void attachArrow(); - virtual void releaseArrow(float attackStrength); + void attachArrow() override; + void detachArrow() override; + void releaseArrow(float attackStrength) override; // WeaponAnimation - virtual osg::Group* getArrowBone(); - virtual osg::Node* getWeaponNode(); - virtual Resource::ResourceSystem* getResourceSystem(); - virtual void showWeapon(bool show) { showWeapons(show); } - virtual void setWeaponGroup(const std::string& group, bool relativeDuration) { mWeaponAnimationTime->setGroup(group, relativeDuration); } + osg::Group* getArrowBone() override; + osg::Node* getWeaponNode() override; + Resource::ResourceSystem* getResourceSystem() override; + void showWeapon(bool show) override { showWeapons(show); } + void setWeaponGroup(const std::string& group, bool relativeDuration) override { mWeaponAnimationTime->setGroup(group, relativeDuration); } - virtual void addControllers(); + void addControllers() override; - virtual osg::Vec3f runAnimation(float duration); + osg::Vec3f runAnimation(float duration) override; /// A relative factor (0-1) that decides if and how much the skeleton should be pitched /// to indicate the facing orientation of the character. - virtual void setPitchFactor(float factor) { mPitchFactor = factor; } + void setPitchFactor(float factor) override { mPitchFactor = factor; } protected: - virtual bool isArrowAttached() const; + bool isArrowAttached() const override; private: PartHolderPtr mWeapon; diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index afa83a1d7..ba300accb 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -70,7 +70,7 @@ namespace { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { if (mRendered) { @@ -105,7 +105,7 @@ namespace MWRender { } - virtual void doWork() + void doWork() override { osg::ref_ptr image = new osg::Image; image->allocateImage(mWidth, mHeight, 1, GL_RGB, GL_UNSIGNED_BYTE); diff --git a/apps/openmw/mwrender/landmanager.hpp b/apps/openmw/mwrender/landmanager.hpp index 0d37097d8..ea73f11c2 100644 --- a/apps/openmw/mwrender/landmanager.hpp +++ b/apps/openmw/mwrender/landmanager.hpp @@ -23,7 +23,7 @@ namespace MWRender /// @note Will return nullptr if not found. osg::ref_ptr getLand(int x, int y); - virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const; + void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; private: int mLoadFlags; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index aaa797ef1..feefb29f5 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -39,7 +39,7 @@ namespace { } - virtual void operator()(osg::Node* node, osg::NodeVisitor*) + void operator()(osg::Node* node, osg::NodeVisitor*) override { if (mRendered) node->setNodeMask(0); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index c0b18dc89..b11ee5007 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -145,7 +145,7 @@ public: void setBlinkStart(float value); void setBlinkStop(float value); - virtual float getValue(osg::NodeVisitor* nv); + float getValue(osg::NodeVisitor* nv) override; }; // -------------------------------------------------------------------------------- @@ -166,7 +166,7 @@ public: mOffset = offset; } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osg::MatrixTransform* transform = static_cast(node); osg::Matrix matrix = transform->getMatrix(); @@ -363,6 +363,7 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) mViewMode = viewMode; MWBase::Environment::get().getWorld()->scaleObject(mPtr, mPtr.getCellRef().getScale()); // apply race height after view change + mAmmunition.reset(); rebuild(); setRenderBin(); } @@ -377,7 +378,7 @@ public: mDepth->setWriteMask(true); } - virtual void drawImplementation(osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous) + void drawImplementation(osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous) override { renderInfo.getState()->applyAttribute(mDepth); @@ -399,7 +400,7 @@ public: { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); float fov, aspect, zNear, zFar; @@ -1051,6 +1052,12 @@ void NpcAnimation::attachArrow() updateQuiver(); } +void NpcAnimation::detachArrow() +{ + WeaponAnimation::detachArrow(mPtr); + updateQuiver(); +} + void NpcAnimation::releaseArrow(float attackStrength) { WeaponAnimation::releaseArrow(mPtr, attackStrength); @@ -1071,10 +1078,15 @@ osg::Group* NpcAnimation::getArrowBone() int type = weapon->get()->mBase->mData.mType; int ammoType = MWMechanics::getWeaponType(type)->mAmmoType; - SceneUtil::FindByNameVisitor findVisitor (MWMechanics::getWeaponType(ammoType)->mAttachBone); - part->getNode()->accept(findVisitor); - - return findVisitor.mFoundNode; + // Try to find and attachment bone in actor's skeleton, otherwise fall back to the ArrowBone in weapon's mesh + osg::Group* bone = getBoneByName(MWMechanics::getWeaponType(ammoType)->mAttachBone); + if (bone == nullptr) + { + SceneUtil::FindByNameVisitor findVisitor ("ArrowBone"); + part->getNode()->accept(findVisitor); + bone = findVisitor.mFoundNode; + } + return bone; } osg::Node* NpcAnimation::getWeaponNode() diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index d56954237..76cd4cc05 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -33,8 +33,8 @@ class NpcAnimation : , public MWWorld::InventoryStoreListener { public: - virtual void equipmentChanged(); - virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew); + void equipmentChanged() override; + void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew) override; public: typedef std::map PartBoneMap; @@ -109,9 +109,9 @@ protected: static NpcType getNpcType(const MWWorld::Ptr& ptr); protected: - virtual void addControllers(); - virtual bool isArrowAttached() const; - virtual std::string getShieldMesh(MWWorld::ConstPtr shield) const; + void addControllers() override; + bool isArrowAttached() const override; + std::string getShieldMesh(MWWorld::ConstPtr shield) const override; public: /** @@ -127,34 +127,35 @@ public: bool disableSounds = false, ViewMode viewMode=VM_Normal, float firstPersonFieldOfView=55.f); virtual ~NpcAnimation(); - virtual void enableHeadAnimation(bool enable); + void enableHeadAnimation(bool enable) override; /// 1: the first person meshes follow the camera's rotation completely /// 0: the first person meshes follow the camera with a reduced factor, so you can look down at your own hands - virtual void setAccurateAiming(bool enabled); + void setAccurateAiming(bool enabled) override; - virtual void setWeaponGroup(const std::string& group, bool relativeDuration); + void setWeaponGroup(const std::string& group, bool relativeDuration) override; - virtual osg::Vec3f runAnimation(float timepassed); + osg::Vec3f runAnimation(float timepassed) override; /// A relative factor (0-1) that decides if and how much the skeleton should be pitched /// to indicate the facing orientation of the character. - virtual void setPitchFactor(float factor) { mPitchFactor = factor; } + void setPitchFactor(float factor) override { mPitchFactor = factor; } - virtual void showWeapons(bool showWeapon); + void showWeapons(bool showWeapon) override; - virtual bool getCarriedLeftShown() const { return mShowCarriedLeft; } - virtual void showCarriedLeft(bool show); + bool getCarriedLeftShown() const override { return mShowCarriedLeft; } + void showCarriedLeft(bool show) override; - virtual void attachArrow(); - virtual void releaseArrow(float attackStrength); + void attachArrow() override; + void detachArrow() override; + void releaseArrow(float attackStrength) override; - virtual osg::Group* getArrowBone(); - virtual osg::Node* getWeaponNode(); - virtual Resource::ResourceSystem* getResourceSystem(); + osg::Group* getArrowBone() override; + osg::Node* getWeaponNode() override; + Resource::ResourceSystem* getResourceSystem() override; // WeaponAnimation - virtual void showWeapon(bool show) { showWeapons(show); } + void showWeapon(bool show) override { showWeapons(show); } virtual void setViewMode(ViewMode viewMode); @@ -166,12 +167,12 @@ public: /// Get the inventory slot that the given node path leads into, or -1 if not found. int getSlot(const osg::NodePath& path) const; - virtual void setVampire(bool vampire); + void setVampire(bool vampire) override; /// Set a translation offset (in object root space) to apply to meshes when in first person mode. void setFirstPersonOffset(const osg::Vec3f& offset); - virtual void updatePtr(const MWWorld::Ptr& updated); + void updatePtr(const MWWorld::Ptr& updated) override; /// Get a list of body parts that may be used by an NPC of given race and gender. /// @note This is a fixed size list, one list item for each ESM::PartReferenceType, may contain nullptr body parts. diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 0f7e1c422..f74455d59 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -89,11 +89,11 @@ namespace MWRender class CanOptimizeCallback : public SceneUtil::Optimizer::IsOperationPermissibleForObjectCallback { public: - virtual bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Drawable* node,unsigned int option) const + bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Drawable* node,unsigned int option) const override { return true; } - virtual bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Node* node,unsigned int option) const + bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Node* node,unsigned int option) const override { return (node->getDataVariance() != osg::Object::DYNAMIC); } @@ -119,7 +119,7 @@ namespace MWRender } } - virtual osg::Node* operator() (const osg::Node* node) const + osg::Node* operator() (const osg::Node* node) const override { if (const osg::Drawable* d = node->asDrawable()) return operator()(d); @@ -222,7 +222,7 @@ namespace MWRender matrixTransform->setMatrix(newMatrix); } - virtual osg::Drawable* operator() (const osg::Drawable* drawable) const + osg::Drawable* operator() (const osg::Drawable* drawable) const override { if (dynamic_cast(drawable)) return nullptr; @@ -243,7 +243,7 @@ namespace MWRender else return const_cast(drawable); } - virtual osg::Callback* operator() (const osg::Callback* callback) const + osg::Callback* operator() (const osg::Callback* callback) const override { return nullptr; } @@ -281,15 +281,17 @@ namespace MWRender unsigned int mNumVerts = 0; }; - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { if (node.getStateSet()) mCurrentStateSet = node.getStateSet(); traverse(node); } - virtual void apply(osg::Geometry& geom) + void apply(osg::Geometry& geom) override { - mResult.mNumVerts += geom.getVertexArray()->getNumElements(); + if (osg::Array* array = geom.getVertexArray()) + mResult.mNumVerts += array->getNumElements(); + ++mResult.mStateSetCounter[mCurrentStateSet]; ++mGlobalStateSetCounter[mCurrentStateSet]; } @@ -326,7 +328,7 @@ namespace MWRender { public: DebugVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {} - virtual void apply(osg::Drawable& node) + void apply(osg::Drawable& node) override { osg::ref_ptr m (new osg::Material); osg::Vec4f color(Misc::Rng::rollProbability(), Misc::Rng::rollProbability(), Misc::Rng::rollProbability(), 0.f); @@ -347,7 +349,7 @@ namespace MWRender public: AddRefnumMarkerVisitor(const ESM::RefNum &refnum) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), mRefnum(refnum) {} ESM::RefNum mRefnum; - virtual void apply(osg::Geometry &node) + void apply(osg::Geometry &node) override { osg::ref_ptr marker (new RefnumMarker); marker->mRefnum = mRefnum; diff --git a/apps/openmw/mwrender/objectpaging.hpp b/apps/openmw/mwrender/objectpaging.hpp index 18fa30289..ff32dadd4 100644 --- a/apps/openmw/mwrender/objectpaging.hpp +++ b/apps/openmw/mwrender/objectpaging.hpp @@ -31,7 +31,7 @@ namespace MWRender osg::ref_ptr createChunk(float size, const osg::Vec2f& center, bool activeGrid, const osg::Vec3f& viewPoint, bool compile); - virtual unsigned int getNodeMask() override; + unsigned int getNodeMask() override; /// @return true if view needs rebuild bool enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, const osg::Vec2i& cell, bool enabled); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c89751ca4..561ad2e0e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -97,7 +97,7 @@ namespace MWRender { } - virtual void setDefaults(osg::StateSet *stateset) + void setDefaults(osg::StateSet *stateset) override { osg::LightModel* lightModel = new osg::LightModel; stateset->setAttribute(lightModel, osg::StateAttribute::ON); @@ -114,7 +114,7 @@ namespace MWRender stateset->removeAttribute(osg::StateAttribute::POLYGONMODE); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor*) + void apply(osg::StateSet* stateset, osg::NodeVisitor*) override { osg::LightModel* lightModel = static_cast(stateset->getAttribute(osg::StateAttribute::LIGHTMODEL)); lightModel->setAmbientIntensity(mAmbientColor); @@ -174,7 +174,7 @@ namespace MWRender { } - virtual void doWork() + void doWork() override { try { @@ -383,6 +383,7 @@ namespace MWRender mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance)); + mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("simpleWater", false)); mUniformNear = mRootNode->getOrCreateStateSet()->getUniform("near"); mUniformFar = mRootNode->getOrCreateStateSet()->getUniform("far"); @@ -712,7 +713,7 @@ namespace MWRender Log(Debug::Verbose) << "NotifyDrawCompletedCallback: " << mFrame; } - virtual void operator () (osg::RenderInfo& renderInfo) const + void operator () (osg::RenderInfo& renderInfo) const override { std::lock_guard lock(mMutex); if (renderInfo.getState()->getFrameStamp()->getFrameNumber() >= mFrame) @@ -939,7 +940,7 @@ namespace MWRender : mWidth(width), mHeight(height), mImage(image) { } - virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* /*drawable*/) const + void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* /*drawable*/) const override { int screenW = renderInfo.getCurrentCamera()->getViewport()->width(); int screenH = renderInfo.getCurrentCamera()->getViewport()->height(); @@ -1364,82 +1365,6 @@ namespace MWRender return mTerrain->getHeightAt(pos); } - bool RenderingManager::vanityRotateCamera(const float *rot) - { - if(!mCamera->isVanityOrPreviewModeEnabled()) - return false; - - mCamera->rotateCamera(rot[0], 0.f, rot[2], true); - return true; - } - - void RenderingManager::setCameraDistance(float dist, bool adjust, bool override) - { - if(!mCamera->isVanityOrPreviewModeEnabled() && !mCamera->isFirstPerson()) - { - if(mCamera->isNearest() && dist > 0.f) - mCamera->toggleViewMode(); - else if (override) - mCamera->updateBaseCameraDistance(-dist / 120.f * 10, adjust); - else - mCamera->setCameraDistance(-dist / 120.f * 10, adjust); - } - else if(mCamera->isFirstPerson() && dist < 0.f) - { - mCamera->toggleViewMode(); - if (override) - mCamera->updateBaseCameraDistance(0.f, false); - else - mCamera->setCameraDistance(0.f, false); - } - } - - void RenderingManager::resetCamera() - { - mCamera->reset(); - } - - float RenderingManager::getCameraDistance() const - { - return mCamera->getCameraDistance(); - } - - Camera* RenderingManager::getCamera() - { - return mCamera.get(); - } - - const osg::Vec3f &RenderingManager::getCameraPosition() const - { - return mCurrentCameraPos; - } - - void RenderingManager::togglePOV(bool force) - { - mCamera->toggleViewMode(force); - } - - void RenderingManager::togglePreviewMode(bool enable) - { - mCamera->togglePreviewMode(enable); - } - - bool RenderingManager::toggleVanityMode(bool enable) - { - return mCamera->toggleVanityMode(enable); - } - - void RenderingManager::allowVanityMode(bool allow) - { - mCamera->allowVanityMode(allow); - } - - void RenderingManager::changeVanityModeScale(float factor) - { - if(mCamera->isVanityOrPreviewModeEnabled()) - mCamera->updateBaseCameraDistance(-factor/120.f*10, true); - } - void RenderingManager::overrideFieldOfView(float val) { if (mFieldOfViewOverridden != true || mFieldOfViewOverride != val) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index d4244713a..daadeff04 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -113,7 +113,7 @@ namespace MWRender osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation(); - MWRender::Objects& getObjects(); + MWRender::Objects& getObjects() override; Resource::ResourceSystem* getResourceSystem(); @@ -217,17 +217,8 @@ namespace MWRender float getTerrainHeightAt(const osg::Vec3f& pos); // camera stuff - bool vanityRotateCamera(const float *rot); - void setCameraDistance(float dist, bool adjust, bool override); - void resetCamera(); - float getCameraDistance() const; - Camera* getCamera(); - const osg::Vec3f& getCameraPosition() const; - void togglePOV(bool force = false); - void togglePreviewMode(bool enable); - bool toggleVanityMode(bool enable); - void allowVanityMode(bool allow); - void changeVanityModeScale(float factor); + Camera* getCamera() { return mCamera.get(); } + const osg::Vec3f& getCameraPosition() const { return mCurrentCameraPos; } /// temporarily override the field of view with given value. void overrideFieldOfView(float val); diff --git a/apps/openmw/mwrender/rotatecontroller.hpp b/apps/openmw/mwrender/rotatecontroller.hpp index 456a6dd20..9d4080ac6 100644 --- a/apps/openmw/mwrender/rotatecontroller.hpp +++ b/apps/openmw/mwrender/rotatecontroller.hpp @@ -20,7 +20,7 @@ public: void setRotate(const osg::Quat& rotate); - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + void operator()(osg::Node* node, osg::NodeVisitor* nv) override; protected: osg::Quat getWorldOrientation(osg::Node* node); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 10fc630bd..7ba490b92 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -119,12 +119,12 @@ public: } protected: - virtual void setDefaults(osg::StateSet* stateset) + void setDefaults(osg::StateSet* stateset) override { stateset->setAttributeAndModes(createAlphaTrackingUnlitMaterial(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) + void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override { osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); mat->setEmission(osg::Material::FRONT_AND_BACK, mEmissionColor); @@ -149,7 +149,7 @@ public: } protected: - virtual void setDefaults(osg::StateSet* stateset) + void setDefaults(osg::StateSet* stateset) override { osg::ref_ptr texEnv (new osg::TexEnvCombine); texEnv->setCombine_Alpha(osg::TexEnvCombine::MODULATE); @@ -162,7 +162,7 @@ protected: stateset->setTextureAttributeAndModes(1, texEnv, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) + void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/) override { osg::TexEnvCombine* texEnv = static_cast(stateset->getTextureAttribute(1, osg::StateAttribute::TEXENV)); texEnv->setConstantColor(mColor); @@ -201,7 +201,7 @@ public: } protected: - virtual void setDefaults(osg::StateSet *stateset) + void setDefaults(osg::StateSet *stateset) override { osg::ref_ptr texmat (new osg::TexMat); stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON); @@ -223,7 +223,7 @@ protected: stateset->setTextureMode(1, GL_TEXTURE_2D, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); } - virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) + void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) override { osg::TexMat* texMat = static_cast(stateset->getTextureAttribute(0, osg::StateAttribute::TEXMAT)); texMat->setMatrix(osg::Matrix::translate(osg::Vec3f(0, -mAnimationTimer, 0.f))); @@ -272,7 +272,7 @@ public: return mViewPoint; } - virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const + bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const override { if (nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { @@ -291,7 +291,7 @@ public: } } - osg::BoundingSphere computeBound() const + osg::BoundingSphere computeBound() const override { return osg::BoundingSphere(osg::Vec3f(0,0,0), 0); } @@ -299,7 +299,7 @@ public: class CullCallback : public osg::NodeCallback { public: - virtual void operator() (osg::Node* node, osg::NodeVisitor* nv) + void operator() (osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); @@ -351,7 +351,7 @@ public: { } - void apply(osg::Drawable& drw) + void apply(osg::Drawable& drw) override { osg::Geometry* geom = drw.asGeometry(); if (!geom) @@ -409,7 +409,7 @@ public: return mEnabled && viewPoint.z() < mWaterLevel; } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { if (isUnderwater()) return; @@ -521,7 +521,7 @@ public: mUpdater->mColor.b() = color.b(); } - virtual void adjustTransparency(const float ratio) + void adjustTransparency(const float ratio) override { mUpdater->mColor.a() = ratio; if (mSunGlareCallback) @@ -550,7 +550,7 @@ private: class DummyComputeBoundCallback : public osg::Node::ComputeBoundingSphereCallback { public: - virtual osg::BoundingSphere computeBound(const osg::Node& node) const { return osg::BoundingSphere(); } + osg::BoundingSphere computeBound(const osg::Node& node) const override { return osg::BoundingSphere(); } }; /// @param queryVisible If true, queries the amount of visible pixels. If false, queries the total amount of pixels. @@ -701,12 +701,12 @@ private: { } - virtual void setDefaults(osg::StateSet* stateset) + void setDefaults(osg::StateSet* stateset) override { stateset->setAttributeAndModes(createUnlitMaterial(), osg::StateAttribute::ON); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor*) + void apply(osg::StateSet* stateset, osg::NodeVisitor*) override { osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mColor.a())); @@ -766,7 +766,7 @@ private: { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); @@ -851,7 +851,7 @@ private: mColor[i] = std::min(1.f, mColor[i]); } - virtual void operator ()(osg::Node* node, osg::NodeVisitor* nv) + void operator ()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); @@ -955,7 +955,7 @@ public: mGeom->removeUpdateCallback(mUpdater); } - virtual void adjustTransparency(const float ratio) + void adjustTransparency(const float ratio) override { mUpdater->mTransparency *= ratio; } @@ -1026,7 +1026,7 @@ private: { } - virtual void setDefaults(osg::StateSet* stateset) + void setDefaults(osg::StateSet* stateset) override { stateset->setTextureAttributeAndModes(0, mPhaseTex, osg::StateAttribute::ON); osg::ref_ptr texEnv = new osg::TexEnvCombine; @@ -1050,7 +1050,7 @@ private: stateset->setAttributeAndModes(createUnlitMaterial(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor*) + void apply(osg::StateSet* stateset, osg::NodeVisitor*) override { osg::TexEnvCombine* texEnv = static_cast(stateset->getTextureAttribute(0, osg::StateAttribute::TEXENV)); texEnv->setConstantColor(mMoonColor * mShadowBlend); @@ -1226,7 +1226,7 @@ void SkyManager::create() class RainCounter : public osgParticle::ConstantRateCounter { public: - virtual int numParticlesToCreate(double dt) const + int numParticlesToCreate(double dt) const override { // limit dt to avoid large particle emissions if there are jumps in the simulation time // 0.2 seconds is the same cap as used in Engine's frame loop @@ -1243,7 +1243,7 @@ public: { } - virtual void shoot(osgParticle::Particle* particle) const + void shoot(osgParticle::Particle* particle) const override { particle->setVelocity(mVelocity); particle->setAngle(osg::Vec3f(-mAngle, 0, (Misc::Rng::rollProbability() * 2 - 1) * osg::PI)); @@ -1259,11 +1259,11 @@ public: mAngle = angle; } - virtual osg::Object* cloneType() const + osg::Object* cloneType() const override { return new RainShooter; } - virtual osg::Object* clone(const osg::CopyOp &) const + osg::Object* clone(const osg::CopyOp &) const override { return new RainShooter(*this); } @@ -1289,14 +1289,14 @@ public: mAlpha = alpha; } - virtual void setDefaults(osg::StateSet* stateset) + void setDefaults(osg::StateSet* stateset) override { // need to create a deep copy of StateAttributes we will modify osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); stateset->setAttribute(osg::clone(mat, osg::CopyOp::DEEP_COPY_ALL), osg::StateAttribute::ON); } - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) + void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override { osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha)); @@ -1315,7 +1315,7 @@ public: mAlphaUpdate = alphaUpdate; } - virtual void apply(osg::Node &node) + void apply(osg::Node &node) override { if (osg::StateSet* stateset = node.getStateSet()) { @@ -1368,7 +1368,7 @@ public: { } - virtual void setDefaults(osg::StateSet* stateset) + void setDefaults(osg::StateSet* stateset) override { osg::ref_ptr mat (new osg::Material); mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); @@ -1377,7 +1377,7 @@ public: stateset->setAttributeAndModes(mat, osg::StateAttribute::ON); } - virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) + void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) override { AlphaFader::apply(stateset,nv); *mAlphaUpdate = mAlpha * 2.0; // mAlpha is limited to 0.6 so multiply by 2 to reach full intensity @@ -1400,21 +1400,21 @@ public: mPreviousCameraPosition = getCameraPosition(); } - virtual osg::Object *cloneType() const override + osg::Object *cloneType() const override { return nullptr; } - virtual osg::Object *clone(const osg::CopyOp &op) const override + osg::Object *clone(const osg::CopyOp &op) const override { return nullptr; } - virtual void operate(osgParticle::Particle *P, double dt) override + void operate(osgParticle::Particle *P, double dt) override { } - virtual void operateParticles(osgParticle::ParticleSystem *ps, double dt) override + void operateParticles(osgParticle::ParticleSystem *ps, double dt) override { osg::Vec3 position = getCameraPosition(); osg::Vec3 positionDifference = position - mPreviousCameraPosition; diff --git a/apps/openmw/mwrender/terrainstorage.hpp b/apps/openmw/mwrender/terrainstorage.hpp index 14bed7b7b..90bf42b84 100644 --- a/apps/openmw/mwrender/terrainstorage.hpp +++ b/apps/openmw/mwrender/terrainstorage.hpp @@ -17,16 +17,16 @@ namespace MWRender { public: - TerrainStorage(Resource::ResourceSystem* resourceSystem, const std::string& normalMapPattern = "", const std::string& normalHeightMapPatteern = "", bool autoUseNormalMaps = false, const std::string& specularMapPattern = "", bool autoUseSpecularMaps = false); + TerrainStorage(Resource::ResourceSystem* resourceSystem, const std::string& normalMapPattern = "", const std::string& normalHeightMapPattern = "", bool autoUseNormalMaps = false, const std::string& specularMapPattern = "", bool autoUseSpecularMaps = false); ~TerrainStorage(); - virtual osg::ref_ptr getLand (int cellX, int cellY) override; - virtual const ESM::LandTexture* getLandTexture(int index, short plugin) override; + osg::ref_ptr getLand (int cellX, int cellY) override; + const ESM::LandTexture* getLandTexture(int index, short plugin) override; - virtual bool hasData(int cellX, int cellY) override; + bool hasData(int cellX, int cellY) override; /// Get bounds of the whole terrain in cell units - virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY) override; + void getBounds(float& minX, float& maxX, float& minY, float& maxY) override; LandManager* getLandManager() const; diff --git a/apps/openmw/mwrender/util.cpp b/apps/openmw/mwrender/util.cpp index b7ff3e962..a224f47e3 100644 --- a/apps/openmw/mwrender/util.cpp +++ b/apps/openmw/mwrender/util.cpp @@ -22,7 +22,7 @@ class TextureOverrideVisitor : public osg::NodeVisitor { } - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { int index = 0; osg::ref_ptr nodePtr(&node); diff --git a/apps/openmw/mwrender/util.hpp b/apps/openmw/mwrender/util.hpp index c2c036890..6847b08fe 100644 --- a/apps/openmw/mwrender/util.hpp +++ b/apps/openmw/mwrender/util.hpp @@ -29,7 +29,7 @@ namespace MWRender class NoTraverseCallback : public osg::NodeCallback { public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { // no traverse() } diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp index 4d708afe0..799e34c99 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() @@ -89,17 +89,21 @@ namespace MWRender 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); + playerPos + sideOffset, orient * osg::Vec3d(1, 0, 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); + playerPos - sideOffset, orient * osg::Vec3d(-1, 0, 0), limitToSwitchBack + 1); + float rayRightForward = world->getDistToNearestRayHit( + playerPos + sideOffset, orient * osg::Vec3d(1, 3, 0), limitToSwitchBack + 1); + float rayLeftForward = world->getDistToNearestRayHit( + playerPos - sideOffset, orient * osg::Vec3d(-1, 3, 0), limitToSwitchBack + 1); + float distRight = std::min(rayRight, rayRightForward); + float distLeft = std::min(rayLeft, rayLeftForward); - if (rayLeft < limitToSwitch && rayRight > limitToSwitchBack) + if (distLeft < limitToSwitch && distRight > limitToSwitchBack) mMode = Mode::RightShoulder; - else if (rayRight < limitToSwitch && rayLeft > limitToSwitchBack) + else if (distRight < limitToSwitch && distLeft > limitToSwitchBack) mMode = Mode::LeftShoulder; - else if (rayLeft > limitToSwitchBack && rayRight > limitToSwitchBack && rayForward > limitToSwitchBack) + else if (distRight > limitToSwitchBack && distLeft > limitToSwitchBack) mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index b8e2cacd7..b569f1bfa 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -65,7 +65,7 @@ class ClipCullNode : public osg::Group { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); @@ -98,7 +98,7 @@ class ClipCullNode : public osg::Group { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); osg::Vec3d eyePoint = cv->getEyePoint(); @@ -168,7 +168,7 @@ class InheritViewPointCallback : public osg::NodeCallback public: InheritViewPointCallback() {} - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); osg::ref_ptr modelViewMatrix = new osg::RefMatrix(*cv->getModelViewMatrix()); @@ -184,7 +184,7 @@ public: class FudgeCallback : public osg::NodeCallback { public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); @@ -408,7 +408,7 @@ private: class DepthClampCallback : public osg::Drawable::DrawCallback { public: - virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const + void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const override { static bool supported = osg::isGLExtensionOrVersionSupported(renderInfo.getState()->getContextID(), "GL_ARB_depth_clamp", 3.3); if (!supported) @@ -443,8 +443,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem mWaterGeom = SceneUtil::createWaterGeometry(Constants::CellSizeInUnits*150, 40, 900); mWaterGeom->setDrawCallback(new DepthClampCallback); mWaterGeom->setNodeMask(Mask_Water); - mWaterGeom->setName("Water Geometry"); - //mWaterGeom->setDataVariance(osg::Object::STATIC); + mWaterGeom->setDataVariance(osg::Object::STATIC); mWaterNode = new osg::PositionAttitudeTransform; mWaterNode->setName("Water Root"); @@ -455,7 +454,6 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem osg::ref_ptr geom2 (osg::clone(mWaterGeom.get(), osg::CopyOp::DEEP_COPY_NODES)); createSimpleWaterStateSet(geom2, Fallback::Map::getFloat("Water_Map_Alpha")); geom2->setNodeMask(Mask_SimpleWater); - geom2->setName("Water Geometry Fallback"); mWaterNode->addChild(geom2); mSceneRoot->addChild(mWaterNode); diff --git a/apps/openmw/mwrender/weaponanimation.cpp b/apps/openmw/mwrender/weaponanimation.cpp index ef7a9bf22..54b239105 100644 --- a/apps/openmw/mwrender/weaponanimation.cpp +++ b/apps/openmw/mwrender/weaponanimation.cpp @@ -103,6 +103,11 @@ void WeaponAnimation::attachArrow(MWWorld::Ptr actor) } } +void WeaponAnimation::detachArrow(MWWorld::Ptr actor) +{ + mAmmunition.reset(); +} + void WeaponAnimation::releaseArrow(MWWorld::Ptr actor, float attackStrength) { MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor); diff --git a/apps/openmw/mwrender/weaponanimation.hpp b/apps/openmw/mwrender/weaponanimation.hpp index a1988703c..d02107333 100644 --- a/apps/openmw/mwrender/weaponanimation.hpp +++ b/apps/openmw/mwrender/weaponanimation.hpp @@ -23,7 +23,7 @@ namespace MWRender void setGroup(const std::string& group, bool relativeTime); void updateStartTime(); - virtual float getValue(osg::NodeVisitor* nv); + float getValue(osg::NodeVisitor* nv) override; }; /// Handles attach & release of projectiles for ranged weapons @@ -36,6 +36,8 @@ namespace MWRender /// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op. void attachArrow(MWWorld::Ptr actor); + void detachArrow(MWWorld::Ptr actor); + /// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op. void releaseArrow(MWWorld::Ptr actor, float attackStrength); diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 2e426701c..499c2f672 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -40,7 +40,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -61,7 +61,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -89,7 +89,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -123,7 +123,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -165,7 +165,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -180,7 +180,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -237,7 +237,7 @@ namespace MWScript public: OpGetAiSetting(MWMechanics::CreatureStats::AiSetting index) : mIndex(index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -251,7 +251,7 @@ namespace MWScript public: OpModAiSetting(MWMechanics::CreatureStats::AiSetting index) : mIndex(index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; @@ -270,7 +270,7 @@ namespace MWScript public: OpSetAiSetting(MWMechanics::CreatureStats::AiSetting index) : mIndex(index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; @@ -288,7 +288,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -322,7 +322,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -358,7 +358,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -373,7 +373,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr observer = R()(runtime, false); // required=false @@ -395,7 +395,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr source = R()(runtime); @@ -418,7 +418,7 @@ namespace MWScript class OpGetTarget : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime &runtime) + void execute (Interpreter::Runtime &runtime) override { MWWorld::Ptr actor = R()(runtime); std::string testedTargetId = runtime.getStringLiteral (runtime[0].mInteger); @@ -448,7 +448,7 @@ namespace MWScript class OpStartCombat : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime &runtime) + void execute (Interpreter::Runtime &runtime) override { MWWorld::Ptr actor = R()(runtime); std::string targetID = runtime.getStringLiteral (runtime[0].mInteger); @@ -464,7 +464,7 @@ namespace MWScript class OpStopCombat : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr actor = R()(runtime); MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor); @@ -476,7 +476,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getMechanicsManager()->toggleAI(); @@ -488,7 +488,7 @@ namespace MWScript class OpFace : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime& runtime) + void execute(Interpreter::Runtime& runtime) override { MWWorld::Ptr actor = R()(runtime); diff --git a/apps/openmw/mwscript/animationextensions.cpp b/apps/openmw/mwscript/animationextensions.cpp index 6e959c0c0..8bb6cc6ad 100644 --- a/apps/openmw/mwscript/animationextensions.cpp +++ b/apps/openmw/mwscript/animationextensions.cpp @@ -24,7 +24,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -37,7 +37,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -67,7 +67,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 13ef98c63..356428156 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -30,7 +30,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getWorld()->hasCellChanged() ? 1 : 0); } @@ -40,7 +40,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { if (MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_NoGame) { @@ -63,7 +63,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { if (MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_NoGame) { @@ -86,7 +86,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string cell = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -114,7 +114,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { Interpreter::Type_Integer x = runtime[0].mInteger; runtime.pop(); @@ -140,7 +140,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { if (!MWMechanics::getPlayer().isInCell()) { @@ -159,7 +159,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -185,7 +185,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { if (!MWMechanics::getPlayer().isInCell()) { @@ -206,7 +206,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { Interpreter::Type_Float level = runtime[0].mFloat; @@ -229,7 +229,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { Interpreter::Type_Float level = runtime[0].mFloat; diff --git a/apps/openmw/mwscript/compilercontext.hpp b/apps/openmw/mwscript/compilercontext.hpp index ca7efd77a..00b10ea06 100644 --- a/apps/openmw/mwscript/compilercontext.hpp +++ b/apps/openmw/mwscript/compilercontext.hpp @@ -25,22 +25,22 @@ namespace MWScript CompilerContext (Type type); /// Is the compiler allowed to declare local variables? - virtual bool canDeclareLocals() const; + bool canDeclareLocals() const override; /// 'l: long, 's': short, 'f': float, ' ': does not exist. - virtual char getGlobalType (const std::string& name) const; + char getGlobalType (const std::string& name) const override; - virtual std::pair getMemberType (const std::string& name, - const std::string& id) const; + std::pair getMemberType (const std::string& name, + const std::string& id) const override; ///< Return type of member variable \a name in script \a id or in script of reference of /// \a id /// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist. /// second: true: script of reference - virtual bool isId (const std::string& name) const; + bool isId (const std::string& name) const override; ///< Does \a name match an ID, that can be referenced? - virtual bool isJournalId (const std::string& name) const; + bool isJournalId (const std::string& name) const override; ///< Does \a name match a journal ID? }; } diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 7116b1c9f..2e78fe374 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -19,15 +19,60 @@ #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" +#include "../mwclass/container.hpp" + #include "../mwworld/action.hpp" #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/inventorystore.hpp" +#include "../mwworld/manualref.hpp" #include "../mwmechanics/actorutil.hpp" +#include "../mwmechanics/levelledlist.hpp" #include "ref.hpp" +namespace +{ + void addToStore(const MWWorld::Ptr& itemPtr, int count, MWWorld::Ptr& ptr, MWWorld::ContainerStore& store, bool resolve = true) + { + if (itemPtr.getClass().getScript(itemPtr).empty()) + { + store.add (itemPtr, count, ptr, true, resolve); + } + else + { + // Adding just one item per time to make sure there isn't a stack of scripted items + for (int i = 0; i < count; i++) + store.add (itemPtr, 1, ptr, true, resolve); + } + } + + void addRandomToStore(const MWWorld::Ptr& itemPtr, int count, MWWorld::Ptr& owner, MWWorld::ContainerStore& store, bool topLevel = true) + { + if(itemPtr.getTypeName() == typeid(ESM::ItemLevList).name()) + { + const ESM::ItemLevList* levItemList = itemPtr.get()->mBase; + + if(topLevel && count > 1 && levItemList->mFlags & ESM::ItemLevList::Each) + { + for(int i = 0; i < count; i++) + addRandomToStore(itemPtr, 1, owner, store, true); + } + else + { + std::string itemId = MWMechanics::getLevelledItem(itemPtr.get()->mBase, false); + if (itemId.empty()) + return; + MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), itemId, 1); + addRandomToStore(manualRef.getPtr(), count, owner, store, false); + } + } + else + addToStore(itemPtr, count, owner, store); + } +} + namespace MWScript { namespace Container @@ -37,7 +82,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -60,19 +105,52 @@ namespace MWScript || ::Misc::StringUtils::ciEqual(item, "gold_100")) item = "gold_001"; - MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); - // Create a Ptr for the first added item to recover the item name later - MWWorld::Ptr itemPtr = *store.add (item, 1, ptr); - if (itemPtr.getClass().getScript(itemPtr).empty()) + // Check if "item" can be placed in a container + MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), item, 1); + MWWorld::Ptr itemPtr = manualRef.getPtr(); + bool isLevelledList = itemPtr.getClass().getTypeName() == typeid(ESM::ItemLevList).name(); + if(!isLevelledList) + MWWorld::ContainerStore::getType(itemPtr); + + // Explicit calls to non-unique actors affect the base record + if(!R::implicit && ptr.getClass().isActor() && MWBase::Environment::get().getWorld()->getStore().getRefCount(ptr.getCellRef().getRefId()) > 1) { - store.add (item, count-1, ptr); + ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, count); + return; } + + // Calls to unresolved containers affect the base record + if(ptr.getClass().getTypeName() == typeid(ESM::Container).name() && (!ptr.getRefData().getCustomData() || + !ptr.getClass().getContainerStore(ptr).isResolved())) + { + ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, count); + const ESM::Container* baseRecord = MWBase::Environment::get().getWorld()->getStore().get().find(ptr.getCellRef().getRefId()); + const auto& ptrs = MWBase::Environment::get().getWorld()->getAll(ptr.getCellRef().getRefId()); + for(const auto& container : ptrs) + { + // use the new base record + container.get()->mBase = baseRecord; + if(container.getRefData().getCustomData()) + { + auto& store = container.getClass().getContainerStore(container); + if(isLevelledList) + { + if(store.isResolved()) + { + addRandomToStore(itemPtr, count, ptr, store); + } + } + else + addToStore(itemPtr, count, ptr, store, store.isResolved()); + } + } + return; + } + MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr); + if(isLevelledList) + addRandomToStore(itemPtr, count, ptr, store); else - { - // Adding just one item per time to make sure there isn't a stack of scripted items - for (int i = 1; i < count; i++) - store.add (item, 1, ptr); - } + addToStore(itemPtr, count, ptr, store); // Spawn a messagebox (only for items added to player's inventory and if player is talking to someone) if (ptr == MWBase::Environment::get().getWorld ()->getPlayerPtr() ) @@ -100,7 +178,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -124,7 +202,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -147,6 +225,32 @@ namespace MWScript || ::Misc::StringUtils::ciEqual(item, "gold_100")) item = "gold_001"; + // Explicit calls to non-unique actors affect the base record + if(!R::implicit && ptr.getClass().isActor() && MWBase::Environment::get().getWorld()->getStore().getRefCount(ptr.getCellRef().getRefId()) > 1) + { + ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, -count); + return; + } + // Calls to unresolved containers affect the base record instead + else if(ptr.getClass().getTypeName() == typeid(ESM::Container).name() && + (!ptr.getRefData().getCustomData() || !ptr.getClass().getContainerStore(ptr).isResolved())) + { + ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, -count); + const ESM::Container* baseRecord = MWBase::Environment::get().getWorld()->getStore().get().find(ptr.getCellRef().getRefId()); + const auto& ptrs = MWBase::Environment::get().getWorld()->getAll(ptr.getCellRef().getRefId()); + for(const auto& container : ptrs) + { + container.get()->mBase = baseRecord; + if(container.getRefData().getCustomData()) + { + auto& store = container.getClass().getContainerStore(container); + // Note that unlike AddItem, RemoveItem only removes from unresolved containers + if(!store.isResolved()) + store.remove(item, count, ptr, false); + } + } + return; + } MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); std::string itemName; @@ -188,7 +292,7 @@ namespace MWScript { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -225,7 +329,7 @@ namespace MWScript { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -298,7 +402,7 @@ namespace MWScript { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -324,7 +428,7 @@ namespace MWScript { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -348,7 +452,7 @@ namespace MWScript { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr ptr = R()(runtime); diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 956792863..5362759e1 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -35,7 +35,7 @@ namespace MWScript : mControl (control), mEnable (enable) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get() .getInputManager() @@ -53,7 +53,7 @@ namespace MWScript : mControl (control) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push(!MWBase::Environment::get().getInputManager()->getControlSwitch (mControl)); } @@ -63,7 +63,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleCollisionMode(); @@ -80,7 +80,7 @@ namespace MWScript OpClearMovementFlag (MWMechanics::CreatureStats::Flag flag) : mFlag (flag) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -97,7 +97,7 @@ namespace MWScript OpSetMovementFlag (MWMechanics::CreatureStats::Flag flag) : mFlag (flag) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -110,7 +110,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -124,7 +124,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -138,7 +138,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -152,7 +152,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -165,7 +165,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); @@ -183,7 +183,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); runtime.push(MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr)); diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index 25c7f518e..b99a043bf 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -28,7 +28,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime, false); // required=false if (ptr.isEmpty()) @@ -57,7 +57,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string quest = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -73,7 +73,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string quest = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -89,7 +89,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string topic = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -102,7 +102,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWBase::DialogueManager* dialogue = MWBase::Environment::get().getDialogueManager(); while(arg0>0) @@ -127,7 +127,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -150,7 +150,7 @@ namespace MWScript { public: - virtual void execute(Interpreter::Runtime& runtime) + void execute(Interpreter::Runtime& runtime) override { MWBase::Environment::get().getDialogueManager()->goodbye(); } @@ -161,7 +161,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; @@ -176,7 +176,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer value = runtime[0].mInteger; @@ -191,7 +191,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -204,7 +204,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -218,7 +218,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -237,7 +237,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -254,7 +254,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string faction1 = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -273,7 +273,7 @@ namespace MWScript class OpClearInfoActor : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index a7865f0ae..41f153b28 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -299,6 +299,15 @@ namespace MWScript return iter->second->mLocals; } + const Locals* GlobalScripts::getLocalsIfPresent (const std::string& name) const + { + std::string name2 = ::Misc::StringUtils::lowerCase (name); + auto iter = mScripts.find (name2); + if (iter==mScripts.end()) + return nullptr; + return &iter->second->mLocals; + } + void GlobalScripts::updatePtrs(const MWWorld::Ptr& base, const MWWorld::Ptr& updated) { MatchPtrVisitor visitor(base); diff --git a/apps/openmw/mwscript/globalscripts.hpp b/apps/openmw/mwscript/globalscripts.hpp index 36d89a7eb..c5c5a9a45 100644 --- a/apps/openmw/mwscript/globalscripts.hpp +++ b/apps/openmw/mwscript/globalscripts.hpp @@ -82,6 +82,8 @@ namespace MWScript ///< If the script \a name has not been added as a global script yet, it is added /// automatically, but is not set to running state. + const Locals* getLocalsIfPresent (const std::string& name) const; + void updatePtrs(const MWWorld::Ptr& base, const MWWorld::Ptr& updated); ///< Update the Ptrs stored in mTarget. Should be called after the reference has been moved to a new cell. }; diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 64f45b4c0..cb1e5cd91 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -30,7 +30,7 @@ namespace MWScript OpEnableWindow (MWGui::GuiWindow window) : mWindow (window) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWindowManager()->allow (mWindow); } @@ -40,7 +40,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWindowManager()->enableRest(); } @@ -50,7 +50,7 @@ namespace MWScript class OpShowRestMenu : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr bed = R()(runtime, false); @@ -70,7 +70,7 @@ namespace MWScript : mDialogue (dialogue) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWindowManager()->pushGuiMode(mDialogue); } @@ -80,7 +80,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getWindowManager()->readPressedButton()); } @@ -90,7 +90,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.getContext().report(MWBase::Environment::get().getWindowManager()->toggleFogOfWar() ? "Fog of war -> On" : "Fog of war -> Off"); @@ -101,7 +101,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.getContext().report(MWBase::Environment::get().getWindowManager()->toggleFullHelp() ? "Full help -> On" : "Full help -> Off"); @@ -112,7 +112,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string cell = (runtime.getStringLiteral (runtime[0].mInteger)); ::Misc::StringUtils::lowerCaseInPlace(cell); @@ -143,7 +143,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { const MWWorld::Store &cells = MWBase::Environment::get().getWorld ()->getStore().get(); @@ -166,7 +166,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { int arg=0; if(arg0>0) @@ -206,7 +206,7 @@ namespace MWScript class OpToggleMenus : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { bool state = MWBase::Environment::get().getWindowManager()->toggleHud(); runtime.getContext().report(state ? "GUI -> On" : "GUI -> Off"); diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 62febb33d..f3895c8b6 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -225,15 +225,13 @@ namespace MWScript std::vector InterpreterContext::getGlobals() const { - std::vector ids; - const MWWorld::Store& globals = MWBase::Environment::get().getWorld()->getStore().get(); - for (MWWorld::Store::iterator iter = globals.begin(); iter!=globals.end(); - ++iter) + std::vector ids; + for (auto& globalVariable : globals) { - ids.push_back (iter->mId); + ids.emplace_back(globalVariable.mId); } return ids; @@ -245,22 +243,22 @@ namespace MWScript return world->getGlobalVariableType(name); } - std::string InterpreterContext::getActionBinding(const std::string& action) const + std::string InterpreterContext::getActionBinding(const std::string& targetAction) const { MWBase::InputManager* input = MWBase::Environment::get().getInputManager(); std::vector actions = input->getActionKeySorting (); - for (std::vector::const_iterator it = actions.begin(); it != actions.end(); ++it) + for (const int action : actions) { - std::string desc = input->getActionDescription (*it); + std::string desc = input->getActionDescription (action); if(desc == "") continue; - if(desc == action) + if(desc == targetAction) { if(input->joystickLastUsed()) - return input->getActionControllerBindingName(*it); + return input->getActionControllerBindingName(action); else - return input->getActionKeyBindingName (*it); + return input->getActionKeyBindingName(action); } } diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index e7c2790ce..c1481d6d0 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -57,82 +57,82 @@ namespace MWScript InterpreterContext (MWScript::Locals *locals, const MWWorld::Ptr& reference); ///< The ownership of \a locals is not transferred. 0-pointer allowed. - virtual int getLocalShort (int index) const; + int getLocalShort (int index) const override; - virtual int getLocalLong (int index) const; + int getLocalLong (int index) const override; - virtual float getLocalFloat (int index) const; + float getLocalFloat (int index) const override; - virtual void setLocalShort (int index, int value); + void setLocalShort (int index, int value) override; - virtual void setLocalLong (int index, int value); + void setLocalLong (int index, int value) override; - virtual void setLocalFloat (int index, float value); + void setLocalFloat (int index, float value) override; using Interpreter::Context::messageBox; - virtual void messageBox (const std::string& message, - const std::vector& buttons); + void messageBox (const std::string& message, + const std::vector& buttons) override; - virtual void report (const std::string& message); + void report (const std::string& message) override; ///< By default, do nothing. - virtual int getGlobalShort (const std::string& name) const; + int getGlobalShort (const std::string& name) const override; - virtual int getGlobalLong (const std::string& name) const; + int getGlobalLong (const std::string& name) const override; - virtual float getGlobalFloat (const std::string& name) const; + float getGlobalFloat (const std::string& name) const override; - virtual void setGlobalShort (const std::string& name, int value); + void setGlobalShort (const std::string& name, int value) override; - virtual void setGlobalLong (const std::string& name, int value); + void setGlobalLong (const std::string& name, int value) override; - virtual void setGlobalFloat (const std::string& name, float value); + void setGlobalFloat (const std::string& name, float value) override; - virtual std::vector getGlobals () const; + std::vector getGlobals () const override; - virtual char getGlobalType (const std::string& name) const; + char getGlobalType (const std::string& name) const override; - virtual std::string getActionBinding(const std::string& action) const; + std::string getActionBinding(const std::string& action) const override; - virtual std::string getActorName() const; + std::string getActorName() const override; - virtual std::string getNPCRace() const; + std::string getNPCRace() const override; - virtual std::string getNPCClass() const; + std::string getNPCClass() const override; - virtual std::string getNPCFaction() const; + std::string getNPCFaction() const override; - virtual std::string getNPCRank() const; + std::string getNPCRank() const override; - virtual std::string getPCName() const; + std::string getPCName() const override; - virtual std::string getPCRace() const; + std::string getPCRace() const override; - virtual std::string getPCClass() const; + std::string getPCClass() const override; - virtual std::string getPCRank() const; + std::string getPCRank() const override; - virtual std::string getPCNextRank() const; + std::string getPCNextRank() const override; - virtual int getPCBounty() const; + int getPCBounty() const override; - virtual std::string getCurrentCellName() const; + std::string getCurrentCellName() const override; void executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor); ///< Execute the activation action for this ptr. If ptr is mActivated, mark activation as handled. - virtual int getMemberShort (const std::string& id, const std::string& name, bool global) const; + int getMemberShort (const std::string& id, const std::string& name, bool global) const override; - virtual int getMemberLong (const std::string& id, const std::string& name, bool global) const; + int getMemberLong (const std::string& id, const std::string& name, bool global) const override; - virtual float getMemberFloat (const std::string& id, const std::string& name, bool global) const; + float getMemberFloat (const std::string& id, const std::string& name, bool global) const override; - virtual void setMemberShort (const std::string& id, const std::string& name, int value, bool global); + void setMemberShort (const std::string& id, const std::string& name, int value, bool global) override; - virtual void setMemberLong (const std::string& id, const std::string& name, int value, bool global); + void setMemberLong (const std::string& id, const std::string& name, int value, bool global) override; - virtual void setMemberFloat (const std::string& id, const std::string& name, float value, bool global); + void setMemberFloat (const std::string& id, const std::string& name, float value, bool global) override; MWWorld::Ptr getReference(bool required=true); ///< Reference, that the script is running from (can be empty) diff --git a/apps/openmw/mwscript/locals.cpp b/apps/openmw/mwscript/locals.cpp index 699200590..381d73ec8 100644 --- a/apps/openmw/mwscript/locals.cpp +++ b/apps/openmw/mwscript/locals.cpp @@ -1,4 +1,5 @@ #include "locals.hpp" +#include "globalscripts.hpp" #include #include @@ -33,15 +34,25 @@ namespace MWScript if (mInitialised) return false; - const Compiler::Locals& locals = - MWBase::Environment::get().getScriptManager()->getLocals (script.mId); + const Locals* global = MWBase::Environment::get().getScriptManager()->getGlobalScripts().getLocalsIfPresent(script.mId); + if(global) + { + mShorts = global->mShorts; + mLongs = global->mLongs; + mFloats = global->mFloats; + } + else + { + const Compiler::Locals& locals = + MWBase::Environment::get().getScriptManager()->getLocals (script.mId); - mShorts.clear(); - mShorts.resize (locals.get ('s').size(), 0); - mLongs.clear(); - mLongs.resize (locals.get ('l').size(), 0); - mFloats.clear(); - mFloats.resize (locals.get ('f').size(), 0); + mShorts.clear(); + mShorts.resize (locals.get ('s').size(), 0); + mLongs.clear(); + mLongs.resize (locals.get ('l').size(), 0); + mFloats.clear(); + mFloats.resize (locals.get ('f').size(), 0); + } mInitialised = true; return true; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 0dd0287a7..a288d6673 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -45,9 +45,9 @@ namespace void addToLevList(ESM::LevelledListBase* list, const std::string& itemId, int level) { - for (std::vector::iterator it = list->mList.begin(); it != list->mList.end(); ++it) + for (auto& levelItem : list->mList) { - if (it->mLevel == level && itemId == it->mId) + if (levelItem.mLevel == level && itemId == levelItem.mId) return; } @@ -84,7 +84,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getWindowManager()->isGuiMode()); } @@ -94,7 +94,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { Interpreter::Type_Integer limit = runtime[0].mInteger; runtime.pop(); @@ -112,7 +112,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr target = R()(runtime, false); std::string name = runtime.getStringLiteral (runtime[0].mInteger); @@ -125,7 +125,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -137,7 +137,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -149,7 +149,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getFrameDuration()); } @@ -160,7 +160,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); MWBase::Environment::get().getWorld()->enable (ptr); @@ -172,7 +172,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); MWBase::Environment::get().getWorld()->disable (ptr); @@ -184,7 +184,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); runtime.push (!ptr.getRefData().isEnabled()); @@ -195,7 +195,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -211,7 +211,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getWindowManager ()->getPlayerSleeping()); } @@ -221,7 +221,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::World* world = MWBase::Environment::get().getWorld(); runtime.push (world->getPlayer().getJumping()); @@ -232,7 +232,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWindowManager ()->wakeUpPlayer(); } @@ -242,7 +242,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (0); } @@ -253,7 +253,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -266,7 +266,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { InterpreterContext& context = static_cast (runtime.getContext()); @@ -283,7 +283,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -314,7 +314,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -326,7 +326,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_CollisionDebug); @@ -341,7 +341,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_CollisionDebug); @@ -355,7 +355,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_Wireframe); @@ -369,7 +369,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleBorders(); @@ -382,7 +382,7 @@ namespace MWScript class OpTogglePathgrid : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_Pathgrid); @@ -396,7 +396,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { Interpreter::Type_Float time = runtime[0].mFloat; runtime.pop(); @@ -409,7 +409,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { Interpreter::Type_Float time = runtime[0].mFloat; runtime.pop(); @@ -422,7 +422,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { Interpreter::Type_Float alpha = runtime[0].mFloat; runtime.pop(); @@ -438,7 +438,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.getContext().report(MWBase::Environment::get().getWorld()->toggleWater() ? "Water -> On" : "Water -> Off"); @@ -449,7 +449,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.getContext().report(MWBase::Environment::get().getWorld()->toggleWorld() ? "World -> On" : "World -> Off"); @@ -460,7 +460,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { // We are ignoring the DontSaveObject statement for now. Probably not worth // bothering with. The incompatibility we are creating should be marginal at most. @@ -471,7 +471,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { if (!MWBase::Environment::get().getWorld()->isFirstPerson()) MWBase::Environment::get().getWorld()->togglePOV(true); @@ -480,7 +480,7 @@ namespace MWScript class OpPcForce3rdPerson : public Interpreter::Opcode0 { - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { if (MWBase::Environment::get().getWorld()->isFirstPerson()) MWBase::Environment::get().getWorld()->togglePOV(true); @@ -490,7 +490,7 @@ namespace MWScript class OpPcGet3rdPerson : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime& runtime) + void execute(Interpreter::Runtime& runtime) override { runtime.push(!MWBase::Environment::get().getWorld()->isFirstPerson()); } @@ -502,7 +502,7 @@ namespace MWScript public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -522,7 +522,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -535,7 +535,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -563,9 +563,9 @@ namespace MWScript effects += store.getMagicEffects(); } - for (MWMechanics::MagicEffects::Collection::const_iterator it = effects.begin(); it != effects.end(); ++it) + for (const auto& activeEffect : effects) { - if (it->first.mId == key && it->second.getModifier() > 0) + if (activeEffect.first.mId == key && activeEffect.second.getModifier() > 0) { runtime.push(1); return; @@ -580,7 +580,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -612,7 +612,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -643,7 +643,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -730,7 +730,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -760,7 +760,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -773,7 +773,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -787,7 +787,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -800,7 +800,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); std::string id = runtime.getStringLiteral(runtime[0].mInteger); @@ -821,7 +821,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push(MWBase::Environment::get().getWorld()->getTimeStamp().getHour()); } @@ -832,7 +832,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); int parameter = runtime[0].mInteger; @@ -851,7 +851,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { float param = runtime[0].mFloat; runtime.pop(); @@ -865,7 +865,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { } }; @@ -875,7 +875,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); runtime.push (MWBase::Environment::get().getWorld()->getPlayerStandingOn(ptr)); @@ -887,7 +887,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); runtime.push (MWBase::Environment::get().getWorld()->getActorStandingOn(ptr)); @@ -899,7 +899,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); runtime.push (MWBase::Environment::get().getWorld()->getPlayerCollidingWith(ptr)); @@ -911,7 +911,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); runtime.push (MWBase::Environment::get().getWorld()->getActorCollidingWith(ptr)); @@ -923,7 +923,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); float healthDiffPerSecond = runtime[0].mFloat; @@ -938,7 +938,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); float healthDiffPerSecond = runtime[0].mFloat; @@ -952,7 +952,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push(MWBase::Environment::get().getWorld()->getWindSpeed()); } @@ -963,7 +963,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -982,7 +982,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1001,7 +1001,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::World *world = MWBase::Environment::get().getWorld(); world->enableTeleporting(Enable); @@ -1013,7 +1013,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::World *world = MWBase::Environment::get().getWorld(); world->enableLevitation(Enable); @@ -1025,7 +1025,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime, false); std::string var = runtime.getStringLiteral(runtime[0].mInteger); @@ -1162,7 +1162,7 @@ namespace MWScript } public: - virtual void execute(Interpreter::Runtime& runtime) + void execute(Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime, false); if (!ptr.isEmpty()) @@ -1178,7 +1178,7 @@ namespace MWScript class OpToggleScripts : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleScripts(); @@ -1189,7 +1189,7 @@ namespace MWScript class OpToggleGodMode : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleGodMode(); @@ -1201,7 +1201,7 @@ namespace MWScript class OpCast : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1247,7 +1247,7 @@ namespace MWScript class OpExplodeSpell : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1284,7 +1284,7 @@ namespace MWScript class OpGoToJail : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::World* world = MWBase::Environment::get().getWorld(); world->goToJail(); @@ -1294,7 +1294,7 @@ namespace MWScript class OpPayFine : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr player = MWMechanics::getPlayer(); player.getClass().getNpcStats(player).setBounty(0); @@ -1306,7 +1306,7 @@ namespace MWScript class OpPayFineThief : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr player = MWMechanics::getPlayer(); player.getClass().getNpcStats(player).setBounty(0); @@ -1318,7 +1318,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime &runtime) + void execute (Interpreter::Runtime &runtime) override { runtime.push (MWBase::Environment::get().getWorld()->isPlayerInJail()); } @@ -1328,7 +1328,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime &runtime) + void execute (Interpreter::Runtime &runtime) override { runtime.push (MWBase::Environment::get().getWorld()->isPlayerTraveling()); } @@ -1338,7 +1338,7 @@ namespace MWScript class OpBetaComment : public Interpreter::Opcode1 { public: - virtual void execute(Interpreter::Runtime &runtime, unsigned int arg0) + void execute(Interpreter::Runtime &runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime); @@ -1400,7 +1400,7 @@ namespace MWScript class OpAddToLevCreature : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { const std::string& levId = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); @@ -1418,7 +1418,7 @@ namespace MWScript class OpRemoveFromLevCreature : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { const std::string& levId = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); @@ -1436,7 +1436,7 @@ namespace MWScript class OpAddToLevItem : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { const std::string& levId = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); @@ -1454,7 +1454,7 @@ namespace MWScript class OpRemoveFromLevItem : public Interpreter::Opcode0 { public: - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { const std::string& levId = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); @@ -1473,7 +1473,7 @@ namespace MWScript class OpShowSceneGraph : public Interpreter::Opcode1 { public: - virtual void execute(Interpreter::Runtime &runtime, unsigned int arg0) + void execute(Interpreter::Runtime &runtime, unsigned int arg0) override { MWWorld::Ptr ptr = R()(runtime, false); @@ -1498,7 +1498,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_NavMesh); @@ -1512,7 +1512,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_ActorsPaths); @@ -1526,7 +1526,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { const auto navMeshNumber = runtime[0].mInteger; runtime.pop(); @@ -1546,7 +1546,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { // Broken in vanilla and deliberately no-op. runtime.push(0); @@ -1557,7 +1557,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_RecastMesh); diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index 0077b7cd0..e1652b311 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -149,18 +149,17 @@ namespace MWScript int count = 0; int success = 0; - const MWWorld::Store& scripts = mStore.get(); - - for (MWWorld::Store::iterator iter = scripts.begin(); - iter != scripts.end(); ++iter) + for (auto& script : mStore.get()) + { if (!std::binary_search (mScriptBlacklist.begin(), mScriptBlacklist.end(), - Misc::StringUtils::lowerCase (iter->mId))) + Misc::StringUtils::lowerCase(script.mId))) { ++count; - if (compile (iter->mId)) + if (compile(script.mId)) ++success; } + } return std::make_pair (count, success); } @@ -195,7 +194,7 @@ namespace MWScript scanner.scan (parser); std::map::iterator iter = - mOtherLocals.insert (std::make_pair (name2, locals)).first; + mOtherLocals.emplace(name2, locals).first; return iter->second; } diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 50cc7afa8..7ddcd2489 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -68,23 +68,23 @@ namespace MWScript Compiler::Context& compilerContext, int warningsMode, const std::vector& scriptBlacklist); - virtual void clear(); + void clear() override; - virtual bool run (const std::string& name, Interpreter::Context& interpreterContext); + bool run (const std::string& name, Interpreter::Context& interpreterContext) override; ///< Run the script with the given name (compile first, if not compiled yet) - virtual bool compile (const std::string& name); + bool compile (const std::string& name) override; ///< Compile script with the given namen /// \return Success? - virtual std::pair compileAll(); + std::pair compileAll() override; ///< Compile all scripts /// \return count, success - virtual const Compiler::Locals& getLocals (const std::string& name); + const Compiler::Locals& getLocals (const std::string& name) override; ///< Return locals for script \a name. - virtual GlobalScripts& getGlobalScripts(); + GlobalScripts& getGlobalScripts() override; }; } diff --git a/apps/openmw/mwscript/skyextensions.cpp b/apps/openmw/mwscript/skyextensions.cpp index efcef6827..2b6bf826f 100644 --- a/apps/openmw/mwscript/skyextensions.cpp +++ b/apps/openmw/mwscript/skyextensions.cpp @@ -21,7 +21,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { bool enabled = MWBase::Environment::get().getWorld()->toggleSky(); @@ -33,7 +33,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWorld()->setMoonColour (false); } @@ -43,7 +43,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWorld()->setMoonColour (true); } @@ -53,7 +53,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getWorld()->getMasserPhase()); } @@ -63,7 +63,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getWorld()->getSecundaPhase()); } @@ -73,7 +73,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.push (MWBase::Environment::get().getWorld()->getCurrentWeather()); } @@ -83,7 +83,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string region = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -99,7 +99,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { std::string region = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); diff --git a/apps/openmw/mwscript/soundextensions.cpp b/apps/openmw/mwscript/soundextensions.cpp index fe6f7bac3..6eab758f1 100644 --- a/apps/openmw/mwscript/soundextensions.cpp +++ b/apps/openmw/mwscript/soundextensions.cpp @@ -26,7 +26,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -51,7 +51,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -63,7 +63,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -76,7 +76,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -89,7 +89,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string sound = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -113,7 +113,7 @@ namespace MWScript OpPlaySound3D (bool loop) : mLoop (loop) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -136,7 +136,7 @@ namespace MWScript OpPlaySoundVP3D (bool loop) : mLoop (loop) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -162,7 +162,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -178,7 +178,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 37751c6d4..58a943e1a 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -51,7 +51,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -69,7 +69,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -91,7 +91,7 @@ namespace MWScript OpGetAttribute (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -114,7 +114,7 @@ namespace MWScript OpSetAttribute (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -136,7 +136,7 @@ namespace MWScript OpModAttribute (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -172,7 +172,7 @@ namespace MWScript OpGetDynamic (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Float value; @@ -201,7 +201,7 @@ namespace MWScript OpSetDynamic (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -227,7 +227,7 @@ namespace MWScript OpModDynamic (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { int peek = R::implicit ? 0 : runtime[0].mInteger; @@ -277,7 +277,7 @@ namespace MWScript OpModCurrentDynamic (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -315,7 +315,7 @@ namespace MWScript OpGetDynamicGetRatio (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -341,7 +341,7 @@ namespace MWScript OpGetSkill (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -360,7 +360,7 @@ namespace MWScript OpSetSkill (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -382,7 +382,7 @@ namespace MWScript OpModSkill (int index) : mIndex (index) {} - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -411,7 +411,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); @@ -423,7 +423,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); @@ -441,7 +441,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); @@ -456,7 +456,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -481,7 +481,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -517,7 +517,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -534,7 +534,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -550,7 +550,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -572,7 +572,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr actor = R()(runtime, false); @@ -604,7 +604,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr actor = R()(runtime, false); @@ -643,7 +643,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr actor = R()(runtime, false); @@ -675,7 +675,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr ptr = R()(runtime, false); @@ -717,7 +717,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -737,7 +737,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -754,7 +754,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -769,7 +769,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string id = runtime.getStringLiteral (runtime[0].mInteger); runtime[0].mInteger = MWBase::Environment::get().getMechanicsManager()->countDeaths (id); @@ -781,7 +781,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr ptr = R()(runtime, false); @@ -813,7 +813,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr ptr = R()(runtime, false); @@ -847,7 +847,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr ptr = R()(runtime, false); @@ -883,7 +883,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -896,7 +896,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -909,7 +909,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::ConstPtr ptr = R()(runtime); @@ -928,7 +928,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayerPtr(); @@ -941,7 +941,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr ptr = R()(runtime, false); @@ -973,7 +973,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr ptr = R()(runtime, false); @@ -1000,7 +1000,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + void execute (Interpreter::Runtime& runtime, unsigned int arg0) override { MWWorld::ConstPtr ptr = R()(runtime, false); @@ -1025,7 +1025,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1060,7 +1060,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1097,7 +1097,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1116,7 +1116,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1135,7 +1135,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1151,7 +1151,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); runtime.push(ptr.getClass().getNpcStats(ptr).isWerewolf()); @@ -1163,7 +1163,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptr, set); @@ -1175,7 +1175,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); MWBase::Environment::get().getMechanicsManager()->applyWerewolfAcrobatics(ptr); @@ -1187,7 +1187,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1217,7 +1217,7 @@ namespace MWScript class OpGetStat : public Interpreter::Opcode0 { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { // dummy runtime.push(0); @@ -1237,7 +1237,7 @@ namespace MWScript { } - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -1272,7 +1272,7 @@ namespace MWScript { } - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr ptr = R()(runtime); MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects(); @@ -1307,7 +1307,7 @@ namespace MWScript { } - virtual void execute(Interpreter::Runtime &runtime) + void execute(Interpreter::Runtime &runtime) override { MWWorld::Ptr ptr = R()(runtime); MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 7bb9093c1..ce45729b3 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -44,7 +44,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr from = R()(runtime); std::string name = runtime.getStringLiteral (runtime[0].mInteger); @@ -101,7 +101,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -117,7 +117,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); runtime.push(ptr.getCellRef().getScale()); @@ -129,7 +129,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -146,7 +146,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -159,12 +159,20 @@ namespace MWScript float ay = ptr.getRefData().getPosition().rot[1]; float az = ptr.getRefData().getPosition().rot[2]; + // XYZ axis use the inverse (XYZ) rotation order like vanilla SetAngle. + // UWV axis use the standard (ZYX) rotation order like TESCS/OpenMW-CS and the rest of the game. if (axis == "x") - MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az); + MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az,MWBase::RotationFlag_inverseOrder); else if (axis == "y") - MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az); + MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az,MWBase::RotationFlag_inverseOrder); else if (axis == "z") - MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle); + MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle,MWBase::RotationFlag_inverseOrder); + else if (axis == "u") + MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az,MWBase::RotationFlag_none); + else if (axis == "w") + MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az,MWBase::RotationFlag_none); + else if (axis == "v") + MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle,MWBase::RotationFlag_none); } }; @@ -173,7 +181,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -200,7 +208,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -227,7 +235,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -254,7 +262,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -310,7 +318,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -337,7 +345,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -404,7 +412,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -457,7 +465,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string itemID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -510,7 +518,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { std::string itemID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); @@ -557,7 +565,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr actor = pc ? MWMechanics::getPlayer() @@ -598,7 +606,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { const MWWorld::Ptr& ptr = R()(runtime); @@ -625,7 +633,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -661,7 +669,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -686,7 +694,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { const MWWorld::Ptr& ptr = R()(runtime); @@ -735,7 +743,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); @@ -771,7 +779,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWorld()->resetActors(); } @@ -781,7 +789,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { MWBase::Environment::get().getWorld()->fixPosition(); } diff --git a/apps/openmw/mwscript/userextensions.cpp b/apps/openmw/mwscript/userextensions.cpp index 165a93062..3f443304d 100644 --- a/apps/openmw/mwscript/userextensions.cpp +++ b/apps/openmw/mwscript/userextensions.cpp @@ -21,7 +21,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.getContext().report ("user1: not in use"); } @@ -31,7 +31,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { runtime.getContext().report ("user2: not in use"); } @@ -42,7 +42,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { // MWWorld::Ptr ptr = R()(runtime); @@ -55,7 +55,7 @@ namespace MWScript { public: - virtual void execute (Interpreter::Runtime& runtime) + void execute (Interpreter::Runtime& runtime) override { // MWWorld::Ptr ptr = R()(runtime); diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index b0bfd52e1..d8c1c928e 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -57,13 +57,13 @@ namespace MWSound private: // MovieAudioDecoder overrides - virtual double getAudioClock() + double getAudioClock() override { return (double)getSampleOffset()/(double)mAudioContext->sample_rate - MWBase::Environment::get().getSoundManager()->getTrackTimeDelay(mAudioTrack); } - virtual void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate) + void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate) override { if (sampleFormat == AV_SAMPLE_FMT_U8P || sampleFormat == AV_SAMPLE_FMT_U8) sampleFormat = AV_SAMPLE_FMT_U8; diff --git a/apps/openmw/mwsound/movieaudiofactory.hpp b/apps/openmw/mwsound/movieaudiofactory.hpp index 6ec49a4d3..63b8fd7e9 100644 --- a/apps/openmw/mwsound/movieaudiofactory.hpp +++ b/apps/openmw/mwsound/movieaudiofactory.hpp @@ -8,7 +8,7 @@ namespace MWSound class MovieAudioFactory : public Video::MovieAudioFactory { - virtual std::shared_ptr createDecoder(Video::VideoState* videoState); + std::shared_ptr createDecoder(Video::VideoState* videoState) override; }; } diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index 6039d97d6..d9ca924a7 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -59,41 +59,41 @@ namespace MWSound OpenAL_Output(const OpenAL_Output &rhs); public: - virtual std::vector enumerate(); - virtual bool init(const std::string &devname, const std::string &hrtfname, HrtfMode hrtfmode); - virtual void deinit(); + std::vector enumerate() override; + bool init(const std::string &devname, const std::string &hrtfname, HrtfMode hrtfmode) override; + void deinit() override; - virtual std::vector enumerateHrtf(); - virtual void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode); + std::vector enumerateHrtf() override; + void setHrtf(const std::string &hrtfname, HrtfMode hrtfmode) override; - virtual std::pair loadSound(const std::string &fname); - virtual size_t unloadSound(Sound_Handle data); + std::pair loadSound(const std::string &fname) override; + size_t unloadSound(Sound_Handle data) override; - virtual bool playSound(Sound *sound, Sound_Handle data, float offset); - virtual bool playSound3D(Sound *sound, Sound_Handle data, float offset); - virtual void finishSound(Sound *sound); - virtual bool isSoundPlaying(Sound *sound); - virtual void updateSound(Sound *sound); + bool playSound(Sound *sound, Sound_Handle data, float offset) override; + bool playSound3D(Sound *sound, Sound_Handle data, float offset) override; + void finishSound(Sound *sound) override; + bool isSoundPlaying(Sound *sound) override; + void updateSound(Sound *sound) override; - virtual bool streamSound(DecoderPtr decoder, Stream *sound, bool getLoudnessData=false); - virtual bool streamSound3D(DecoderPtr decoder, Stream *sound, bool getLoudnessData); - virtual void finishStream(Stream *sound); - virtual double getStreamDelay(Stream *sound); - virtual double getStreamOffset(Stream *sound); - virtual float getStreamLoudness(Stream *sound); - virtual bool isStreamPlaying(Stream *sound); - virtual void updateStream(Stream *sound); + bool streamSound(DecoderPtr decoder, Stream *sound, bool getLoudnessData=false) override; + bool streamSound3D(DecoderPtr decoder, Stream *sound, bool getLoudnessData) override; + void finishStream(Stream *sound) override; + double getStreamDelay(Stream *sound) override; + double getStreamOffset(Stream *sound) override; + float getStreamLoudness(Stream *sound) override; + bool isStreamPlaying(Stream *sound) override; + void updateStream(Stream *sound) override; - virtual void startUpdate(); - virtual void finishUpdate(); + void startUpdate() override; + void finishUpdate() override; - virtual void updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdir, const osg::Vec3f &updir, Environment env); + void updateListener(const osg::Vec3f &pos, const osg::Vec3f &atdir, const osg::Vec3f &updir, Environment env) override; - virtual void pauseSounds(int types); - virtual void resumeSounds(int types); + void pauseSounds(int types) override; + void resumeSounds(int types) override; - virtual void pauseActiveDevice(); - virtual void resumeActiveDevice(); + void pauseActiveDevice() override; + void resumeActiveDevice() override; OpenAL_Output(SoundManager &mgr); virtual ~OpenAL_Output(); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index b3f612d7d..37b099c02 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -169,111 +169,111 @@ namespace MWSound SoundManager(const VFS::Manager* vfs, bool useSound); virtual ~SoundManager(); - virtual void processChangedSettings(const Settings::CategorySettingVector& settings); + void processChangedSettings(const Settings::CategorySettingVector& settings) override; - virtual void stopMusic(); + void stopMusic() override; ///< Stops music if it's playing - virtual void streamMusic(const std::string& filename); + void streamMusic(const std::string& filename) override; ///< Play a soundifle /// \param filename name of a sound file in "Music/" in the data directory. - virtual bool isMusicPlaying(); + bool isMusicPlaying() override; ///< Returns true if music is playing - virtual void playPlaylist(const std::string &playlist); + void playPlaylist(const std::string &playlist) override; ///< Start playing music from the selected folder /// \param name of the folder that contains the playlist - virtual void playTitleMusic(); + void playTitleMusic() override; ///< Start playing title music - virtual void say(const MWWorld::ConstPtr &reference, const std::string& filename); + void say(const MWWorld::ConstPtr &reference, const std::string& filename) override; ///< Make an actor say some text. /// \param filename name of a sound file in "Sound/" in the data directory. - virtual void say(const std::string& filename); + void say(const std::string& filename) override; ///< Say some text, without an actor ref /// \param filename name of a sound file in "Sound/" in the data directory. - virtual bool sayActive(const MWWorld::ConstPtr &reference=MWWorld::ConstPtr()) const; + bool sayActive(const MWWorld::ConstPtr &reference=MWWorld::ConstPtr()) const override; ///< Is actor not speaking? - virtual bool sayDone(const MWWorld::ConstPtr &reference=MWWorld::ConstPtr()) const; + bool sayDone(const MWWorld::ConstPtr &reference=MWWorld::ConstPtr()) const override; ///< For scripting backward compatibility - virtual void stopSay(const MWWorld::ConstPtr &reference=MWWorld::ConstPtr()); + void stopSay(const MWWorld::ConstPtr &reference=MWWorld::ConstPtr()) override; ///< Stop an actor speaking - virtual float getSaySoundLoudness(const MWWorld::ConstPtr& reference) const; + float getSaySoundLoudness(const MWWorld::ConstPtr& reference) const override; ///< Check the currently playing say sound for this actor /// and get an average loudness value (scale [0,1]) at the current time position. /// If the actor is not saying anything, returns 0. - virtual Stream *playTrack(const DecoderPtr& decoder, Type type); + Stream *playTrack(const DecoderPtr& decoder, Type type) override; ///< Play a 2D audio track, using a custom decoder - virtual void stopTrack(Stream *stream); + void stopTrack(Stream *stream) override; ///< Stop the given audio track from playing - virtual double getTrackTimeDelay(Stream *stream); + double getTrackTimeDelay(Stream *stream) override; ///< Retives the time delay, in seconds, of the audio track (must be a sound /// returned by \ref playTrack). Only intended to be called by the track /// decoder's read method. - virtual Sound *playSound(const std::string& soundId, float volume, float pitch, Type type=Type::Sfx, PlayMode mode=PlayMode::Normal, float offset=0); + Sound *playSound(const std::string& soundId, float volume, float pitch, Type type=Type::Sfx, PlayMode mode=PlayMode::Normal, float offset=0) override; ///< Play a sound, independently of 3D-position ///< @param offset Number of seconds into the sound to start playback. - virtual Sound *playSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, + Sound *playSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, float volume, float pitch, Type type=Type::Sfx, - PlayMode mode=PlayMode::Normal, float offset=0); + PlayMode mode=PlayMode::Normal, float offset=0) override; ///< Play a 3D sound attached to an MWWorld::Ptr. Will be updated automatically with the Ptr's position, unless Play_NoTrack is specified. ///< @param offset Number of seconds into the sound to start playback. - virtual Sound *playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, - float volume, float pitch, Type type, PlayMode mode, float offset=0); + Sound *playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, + float volume, float pitch, Type type, PlayMode mode, float offset=0) override; ///< Play a 3D sound at \a initialPos. If the sound should be moving, it must be updated using Sound::setPosition. ///< @param offset Number of seconds into the sound to start playback. - virtual void stopSound(Sound *sound); + void stopSound(Sound *sound) override; ///< Stop the given sound from playing /// @note no-op if \a sound is null - virtual void stopSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId); + void stopSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId) override; ///< Stop the given object from playing the given sound, - virtual void stopSound3D(const MWWorld::ConstPtr &reference); + void stopSound3D(const MWWorld::ConstPtr &reference) override; ///< Stop the given object from playing all sounds. - virtual void stopSound(const MWWorld::CellStore *cell); + void stopSound(const MWWorld::CellStore *cell) override; ///< Stop all sounds for the given cell. - virtual void fadeOutSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, float duration); + void fadeOutSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, float duration) override; ///< Fade out given sound (that is already playing) of given object ///< @param reference Reference to object, whose sound is faded out ///< @param soundId ID of the sound to fade out. ///< @param duration Time until volume reaches 0. - virtual bool getSoundPlaying(const MWWorld::ConstPtr &reference, const std::string& soundId) const; + bool getSoundPlaying(const MWWorld::ConstPtr &reference, const std::string& soundId) const override; ///< Is the given sound currently playing on the given object? - virtual void pauseSounds(MWSound::BlockerType blocker, int types=int(Type::Mask)); + void pauseSounds(MWSound::BlockerType blocker, int types=int(Type::Mask)) override; ///< Pauses all currently playing sounds, including music. - virtual void resumeSounds(MWSound::BlockerType blocker); + void resumeSounds(MWSound::BlockerType blocker) override; ///< Resumes all previously paused sounds. - virtual void pausePlayback(); - virtual void resumePlayback(); + void pausePlayback() override; + void resumePlayback() override; - virtual void update(float duration); + void update(float duration) override; - virtual void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up, bool underwater); + void setListenerPosDir(const osg::Vec3f &pos, const osg::Vec3f &dir, const osg::Vec3f &up, bool underwater) override; - virtual void updatePtr (const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated); + void updatePtr (const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) override; - virtual void clear(); + void clear() override; }; } diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index d71fae850..11984b7f5 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -33,27 +33,27 @@ namespace MWState StateManager (const boost::filesystem::path& saves, const std::string& game); - virtual void requestQuit(); + void requestQuit() override; - virtual bool hasQuitRequest() const; + bool hasQuitRequest() const override; - virtual void askLoadRecent(); + void askLoadRecent() override; - virtual State getState() const; + State getState() const override; - virtual void newGame (bool bypass = false); + void newGame (bool bypass = false) override; ///< Start a new game. /// /// \param bypass Skip new game mechanics. - virtual void endGame(); + void endGame() override; - virtual void resumeGame(); + void resumeGame() override; - virtual void deleteGame (const MWState::Character *character, const MWState::Slot *slot); + void deleteGame (const MWState::Character *character, const MWState::Slot *slot) override; ///< Delete a saved game slot from this character. If all save slots are deleted, the character will be deleted too. - virtual void saveGame (const std::string& description, const Slot *slot = 0); + void saveGame (const std::string& description, const Slot *slot = 0) override; ///< Write a saved game to \a slot or create a new slot if \a slot == 0. /// /// \note Slot must belong to the current character. @@ -61,30 +61,30 @@ namespace MWState ///Saves a file, using supplied filename, overwritting if needed /** This is mostly used for quicksaving and autosaving, for they use the same name over and over again \param name Name of save, defaults to "Quicksave"**/ - virtual void quickSave(std::string name = "Quicksave"); + void quickSave(std::string name = "Quicksave") override; ///Loads the last saved file /** Used for quickload **/ - virtual void quickLoad(); + void quickLoad() override; - virtual void loadGame (const std::string& filepath); + void loadGame (const std::string& filepath) override; ///< Load a saved game directly from the given file path. This will search the CharacterManager /// for a Character containing this save file, and set this Character current if one was found. /// Otherwise, a new Character will be created. - virtual void loadGame (const Character *character, const std::string &filepath); + void loadGame (const Character *character, const std::string &filepath) override; ///< Load a saved game file belonging to the given character. - virtual Character *getCurrentCharacter (); + Character *getCurrentCharacter () override; ///< @note May return null. - virtual CharacterIterator characterBegin(); + CharacterIterator characterBegin() override; ///< Any call to SaveGame and getCurrentCharacter can invalidate the returned /// iterator. - virtual CharacterIterator characterEnd(); + CharacterIterator characterEnd() override; - virtual void update (float duration); + void update (float duration) override; }; } diff --git a/apps/openmw/mwvr/openxrmanagerimpl.cpp b/apps/openmw/mwvr/openxrmanagerimpl.cpp index 70594fd41..51db454de 100644 --- a/apps/openmw/mwvr/openxrmanagerimpl.cpp +++ b/apps/openmw/mwvr/openxrmanagerimpl.cpp @@ -581,7 +581,7 @@ namespace MWVR void OpenXRManagerImpl::handleEvents() { - std::unique_lock lock(mEventMutex); + std::unique_lock lock(mMutex); xrQueueEvents(); @@ -784,11 +784,13 @@ namespace MWVR void OpenXRManagerImpl::xrResourceAcquired() { + std::unique_lock lock(mMutex); mAcquiredResources++; } void OpenXRManagerImpl::xrResourceReleased() { + std::unique_lock lock(mMutex); if (mAcquiredResources == 0) throw std::logic_error("Releasing a nonexistent resource"); mAcquiredResources--; diff --git a/apps/openmw/mwvr/openxrmanagerimpl.hpp b/apps/openmw/mwvr/openxrmanagerimpl.hpp index c4cc0a6c2..f8aa7fa20 100644 --- a/apps/openmw/mwvr/openxrmanagerimpl.hpp +++ b/apps/openmw/mwvr/openxrmanagerimpl.hpp @@ -113,8 +113,7 @@ namespace MWVR bool mAppShouldReadInput = false; uint32_t mAcquiredResources = 0; - std::mutex mFrameStateMutex{}; - std::mutex mEventMutex{}; + std::mutex mMutex{}; std::set mAvailableExtensions; std::set mEnabledExtensions; std::queue mEventQueue; diff --git a/apps/openmw/mwvr/vrgui.cpp b/apps/openmw/mwvr/vrgui.cpp index 94caa4393..165ca06fe 100644 --- a/apps/openmw/mwvr/vrgui.cpp +++ b/apps/openmw/mwvr/vrgui.cpp @@ -471,6 +471,7 @@ namespace MWVR LayerConfig gDefaultConfig = createDefaultConfig(1); LayerConfig gVideoPlayerConfig = createDefaultConfig(1, true, SizingMode::Fixed); LayerConfig gLoadingScreenConfig = createDefaultConfig(1, true, SizingMode::Fixed); + LayerConfig gMainMenuConfig = createDefaultConfig(1, true); LayerConfig gJournalBooksConfig = createDefaultConfig(2, false, SizingMode::Fixed); LayerConfig gDefaultWindowsConfig = createDefaultConfig(3, true); LayerConfig gMessageBoxConfig = createDefaultConfig(6, false, SizingMode::Auto);; @@ -550,6 +551,7 @@ namespace MWVR {"DialogueWindow", gDialogueWindowConfig}, {"MessageBox", gMessageBoxConfig}, {"Windows", gDefaultWindowsConfig}, + {"MainMenu", gMainMenuConfig}, {"Notification", gNotificationConfig}, {"InputBlocker", gVideoPlayerConfig}, {"LoadingScreen", gLoadingScreenConfig}, diff --git a/apps/openmw/mwworld/actionalchemy.hpp b/apps/openmw/mwworld/actionalchemy.hpp index 0f79d5c2d..194ef308b 100644 --- a/apps/openmw/mwworld/actionalchemy.hpp +++ b/apps/openmw/mwworld/actionalchemy.hpp @@ -8,7 +8,7 @@ namespace MWWorld class ActionAlchemy : public Action { bool mForce; - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: ActionAlchemy(bool force=false); diff --git a/apps/openmw/mwworld/actionapply.hpp b/apps/openmw/mwworld/actionapply.hpp index 4a1d2aefa..4350b7af4 100644 --- a/apps/openmw/mwworld/actionapply.hpp +++ b/apps/openmw/mwworld/actionapply.hpp @@ -11,7 +11,7 @@ namespace MWWorld { std::string mId; - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: @@ -24,7 +24,7 @@ namespace MWWorld int mSkillIndex; int mUsageType; - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: diff --git a/apps/openmw/mwworld/actiondoor.hpp b/apps/openmw/mwworld/actiondoor.hpp index 2dc5ad8c1..4be61f576 100644 --- a/apps/openmw/mwworld/actiondoor.hpp +++ b/apps/openmw/mwworld/actiondoor.hpp @@ -8,7 +8,7 @@ namespace MWWorld { class ActionDoor : public Action { - virtual void executeImp (const MWWorld::Ptr& actor); + void executeImp (const MWWorld::Ptr& actor) override; public: ActionDoor (const Ptr& object); diff --git a/apps/openmw/mwworld/actioneat.hpp b/apps/openmw/mwworld/actioneat.hpp index db21ffa17..ddc231d99 100644 --- a/apps/openmw/mwworld/actioneat.hpp +++ b/apps/openmw/mwworld/actioneat.hpp @@ -7,7 +7,7 @@ namespace MWWorld { class ActionEat : public Action { - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: diff --git a/apps/openmw/mwworld/actionequip.hpp b/apps/openmw/mwworld/actionequip.hpp index 1b5e52dd8..1ac3cb236 100644 --- a/apps/openmw/mwworld/actionequip.hpp +++ b/apps/openmw/mwworld/actionequip.hpp @@ -9,7 +9,7 @@ namespace MWWorld { bool mForce; - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: /// @param item to equip diff --git a/apps/openmw/mwworld/actionharvest.cpp b/apps/openmw/mwworld/actionharvest.cpp index ff35938b2..c9468c715 100644 --- a/apps/openmw/mwworld/actionharvest.cpp +++ b/apps/openmw/mwworld/actionharvest.cpp @@ -29,6 +29,7 @@ namespace MWWorld MWWorld::Ptr target = getTarget(); MWWorld::ContainerStore& store = target.getClass().getContainerStore (target); + store.resolve(); MWWorld::ContainerStore& actorStore = actor.getClass().getContainerStore(actor); std::map takenMap; for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) diff --git a/apps/openmw/mwworld/actionharvest.hpp b/apps/openmw/mwworld/actionharvest.hpp index b93ff7f10..2edc2f34e 100644 --- a/apps/openmw/mwworld/actionharvest.hpp +++ b/apps/openmw/mwworld/actionharvest.hpp @@ -8,7 +8,7 @@ namespace MWWorld { class ActionHarvest : public Action { - virtual void executeImp (const MWWorld::Ptr& actor); + void executeImp (const MWWorld::Ptr& actor) override; public: ActionHarvest (const Ptr& container); diff --git a/apps/openmw/mwworld/actionopen.hpp b/apps/openmw/mwworld/actionopen.hpp index e36b971a2..e9f76c4d7 100644 --- a/apps/openmw/mwworld/actionopen.hpp +++ b/apps/openmw/mwworld/actionopen.hpp @@ -7,7 +7,7 @@ namespace MWWorld { class ActionOpen : public Action { - virtual void executeImp (const MWWorld::Ptr& actor); + void executeImp (const MWWorld::Ptr& actor) override; public: ActionOpen (const Ptr& container); diff --git a/apps/openmw/mwworld/actionread.hpp b/apps/openmw/mwworld/actionread.hpp index 7c4d7d2f4..6387933eb 100644 --- a/apps/openmw/mwworld/actionread.hpp +++ b/apps/openmw/mwworld/actionread.hpp @@ -7,7 +7,7 @@ namespace MWWorld { class ActionRead : public Action { - virtual void executeImp (const MWWorld::Ptr& actor); + void executeImp (const MWWorld::Ptr& actor) override; public: /// @param book or scroll to read diff --git a/apps/openmw/mwworld/actionrepair.hpp b/apps/openmw/mwworld/actionrepair.hpp index fc64522d8..218077f5d 100644 --- a/apps/openmw/mwworld/actionrepair.hpp +++ b/apps/openmw/mwworld/actionrepair.hpp @@ -9,7 +9,7 @@ namespace MWWorld { bool mForce; - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: /// @param item repair hammer diff --git a/apps/openmw/mwworld/actionsoulgem.hpp b/apps/openmw/mwworld/actionsoulgem.hpp index 6a8f220bc..d2b14c912 100644 --- a/apps/openmw/mwworld/actionsoulgem.hpp +++ b/apps/openmw/mwworld/actionsoulgem.hpp @@ -7,7 +7,7 @@ namespace MWWorld { class ActionSoulgem : public Action { - virtual void executeImp (const MWWorld::Ptr& actor); + void executeImp (const MWWorld::Ptr& actor) override; public: /// @param soulgem to use diff --git a/apps/openmw/mwworld/actiontake.hpp b/apps/openmw/mwworld/actiontake.hpp index fb8d2f4ce..bb9c0d380 100644 --- a/apps/openmw/mwworld/actiontake.hpp +++ b/apps/openmw/mwworld/actiontake.hpp @@ -7,7 +7,7 @@ namespace MWWorld { class ActionTake : public Action { - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: diff --git a/apps/openmw/mwworld/actiontalk.hpp b/apps/openmw/mwworld/actiontalk.hpp index 01738a0bb..6dd70380f 100644 --- a/apps/openmw/mwworld/actiontalk.hpp +++ b/apps/openmw/mwworld/actiontalk.hpp @@ -7,7 +7,7 @@ namespace MWWorld { class ActionTalk : public Action { - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index f54edc8cb..9cd8469a3 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -24,7 +24,7 @@ namespace MWWorld { // Find any NPCs that are following the actor and teleport them with him std::set followers; - getFollowersToTeleport(actor, followers); + getFollowers(actor, followers, true); for (std::set::iterator it = followers.begin(); it != followers.end(); ++it) teleport(*it); @@ -47,7 +47,9 @@ namespace MWWorld } else { - if (mCellName.empty()) + if (actor.getClass().getCreatureStats(actor).getAiSequence().isInCombat(world->getPlayerPtr())) + actor.getClass().getCreatureStats(actor).getAiSequence().stopCombat(); + else if (mCellName.empty()) { int cellX; int cellY; @@ -60,7 +62,7 @@ namespace MWWorld } } - void ActionTeleport::getFollowersToTeleport(const MWWorld::Ptr& actor, std::set& out) { + void ActionTeleport::getFollowers(const MWWorld::Ptr& actor, std::set& out, bool includeHostiles) { std::set followers; MWBase::Environment::get().getMechanicsManager()->getActorsFollowing(actor, followers); @@ -69,11 +71,17 @@ namespace MWWorld MWWorld::Ptr follower = *it; std::string script = follower.getClass().getScript(follower); + + if (!includeHostiles && follower.getClass().getCreatureStats(follower).getAiSequence().isInCombat(actor)) + continue; + if (!script.empty() && follower.getRefData().getLocals().getIntVar(script, "stayoutside") == 1) continue; - if ((follower.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3()).length2() <= 800*800) - out.insert(follower); + if ((follower.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3()).length2() > 800 * 800) + continue; + + out.emplace(follower); } } } diff --git a/apps/openmw/mwworld/actionteleport.hpp b/apps/openmw/mwworld/actionteleport.hpp index c58218750..0a981a418 100644 --- a/apps/openmw/mwworld/actionteleport.hpp +++ b/apps/openmw/mwworld/actionteleport.hpp @@ -17,7 +17,7 @@ namespace MWWorld bool mTeleportFollowers; /// Teleports this actor and also teleports anyone following that actor. - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; /// Teleports only the given actor (internal use). void teleport(const Ptr &actor); @@ -28,8 +28,9 @@ namespace MWWorld /// @param teleportFollowers Whether to teleport any following actors of the target actor as well. ActionTeleport (const std::string& cellName, const ESM::Position& position, bool teleportFollowers); - /// Outputs every actor follower who is in teleport range and wasn't ordered to not enter interiors - static void getFollowersToTeleport(const MWWorld::Ptr& actor, std::set& out); + /// @param includeHostiles If true, include hostile followers (which won't actually be teleported) in the output, + /// e.g. so that the teleport action can calm them. + static void getFollowers(const MWWorld::Ptr& actor, std::set& out, bool includeHostiles = false); }; } diff --git a/apps/openmw/mwworld/actiontrap.hpp b/apps/openmw/mwworld/actiontrap.hpp index 5b0d429c4..fe51959d1 100644 --- a/apps/openmw/mwworld/actiontrap.hpp +++ b/apps/openmw/mwworld/actiontrap.hpp @@ -12,7 +12,7 @@ namespace MWWorld std::string mSpellId; MWWorld::Ptr mTrapSource; - virtual void executeImp (const Ptr& actor); + void executeImp (const Ptr& actor) override; public: diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index bee6a957d..c6f71df6c 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -69,13 +69,13 @@ namespace MWWorld cell->forEach(visitor); } - virtual void abort() + void abort() override { mAbort = true; } /// Preload work to be called from the worker thread. - virtual void doWork() + void doWork() override { if (mIsExterior) { @@ -177,7 +177,7 @@ namespace MWWorld return true; } - virtual void doWork() + void doWork() override { for (unsigned int i=0; iupdateCache(mReferenceTime); } diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index bf107b422..94c78b433 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -16,6 +16,50 @@ #include "containerstore.hpp" #include "cellstore.hpp" +namespace +{ + template + bool forEachInStore(const std::string& id, Visitor&& visitor, std::map& cellStore) + { + for(auto& cell : cellStore) + { + if(cell.second.getState() == MWWorld::CellStore::State_Unloaded) + cell.second.preload(); + if(cell.second.getState() == MWWorld::CellStore::State_Preloaded) + { + if(cell.second.hasId(id)) + { + cell.second.load(); + } + else + continue; + } + bool cont = cell.second.forEach([&] (MWWorld::Ptr ptr) + { + if(*ptr.getCellRef().getRefIdPtr() == id) + { + return visitor(ptr); + } + return true; + }); + if(!cont) + return false; + } + return true; + } + + struct PtrCollector + { + std::vector mPtrs; + + bool operator()(MWWorld::Ptr ptr) + { + mPtrs.emplace_back(ptr); + return true; + } + }; +} + MWWorld::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) { if (cell->mData.mFlags & ESM::Cell::Interior) @@ -330,6 +374,14 @@ void MWWorld::Cells::getInteriorPtrs(const std::string &name, std::vector MWWorld::Cells::getAll(const std::string& id) +{ + PtrCollector visitor; + if(forEachInStore(id, visitor, mInteriors)) + forEachInStore(id, visitor, mExteriors); + return visitor.mPtrs; +} + int MWWorld::Cells::countSavedGameRecords() const { int count = 0; @@ -376,7 +428,7 @@ public: MWWorld::Cells& mCells; - virtual MWWorld::CellStore* getCellStore(const ESM::CellId& cellId) + MWWorld::CellStore* getCellStore(const ESM::CellId& cellId) override { try { diff --git a/apps/openmw/mwworld/cells.hpp b/apps/openmw/mwworld/cells.hpp index 3e64ad975..90ede409b 100644 --- a/apps/openmw/mwworld/cells.hpp +++ b/apps/openmw/mwworld/cells.hpp @@ -80,6 +80,8 @@ namespace MWWorld /// @note name must be lower case void getInteriorPtrs (const std::string& name, std::vector& out); + std::vector getAll(const std::string& id); + int countSavedGameRecords() const; void write (ESM::ESMWriter& writer, Loading::Listener& progress) const; diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 2cda83e17..14b96b27c 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -1030,7 +1030,8 @@ namespace MWWorld for (CellRefList::List::iterator it (mContainers.mList.begin()); it!=mContainers.mList.end(); ++it) { Ptr ptr = getCurrentPtr(&*it); - if (!ptr.isEmpty() && ptr.getRefData().getCustomData() != nullptr && ptr.getRefData().getCount() > 0) + if (!ptr.isEmpty() && ptr.getRefData().getCustomData() != nullptr && ptr.getRefData().getCount() > 0 + && ptr.getClass().getContainerStore(ptr).isResolved()) { ptr.getClass().getContainerStore(ptr).rechargeItems(duration); } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 733e10085..0cdf5748d 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -159,7 +159,12 @@ namespace MWWorld return ""; } - float Class::getSpeed (const Ptr& ptr) const + float Class::getMaxSpeed (const Ptr& ptr) const + { + return 0; + } + + float Class::getCurrentSpeed (const Ptr& ptr) const { return 0; } @@ -522,6 +527,11 @@ namespace MWWorld throw std::runtime_error ("class does not have creature stats"); } + void Class::modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const + { + throw std::runtime_error ("class does not have an inventory store"); + } + float Class::getWalkSpeed(const Ptr& /*ptr*/) const { return 0; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 23bf97fc2..aac50b0c2 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -175,8 +175,15 @@ namespace MWWorld ///< Return name of the script attached to ptr (default implementation: return an empty /// string). - virtual float getSpeed (const Ptr& ptr) const; - ///< Return movement speed. + virtual float getWalkSpeed(const Ptr& ptr) const; + virtual float getRunSpeed(const Ptr& ptr) const; + virtual float getSwimSpeed(const Ptr& ptr) const; + + /// Return maximal movement speed for the current state. + virtual float getMaxSpeed(const Ptr& ptr) const; + + /// Return current movement speed. + virtual float getCurrentSpeed(const Ptr& ptr) const; virtual float getJump(const MWWorld::Ptr &ptr) const; ///< Return jump velocity (not accounting for movement) @@ -185,7 +192,7 @@ namespace MWWorld ///< Return desired movement. virtual osg::Vec3f getRotationVector (const Ptr& ptr) const; - ///< Return desired rotations, as euler angles. + ///< Return desired rotations, as euler angles. Sets getMovementSettings(ptr).mRotation to zero. virtual std::pair, bool> getEquipmentSlots (const ConstPtr& ptr) const; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object @@ -349,8 +356,6 @@ namespace MWWorld virtual void respawn (const MWWorld::Ptr& ptr) const {} - virtual void restock (const MWWorld::Ptr& ptr) const {} - /// Returns sound id virtual std::string getSound(const MWWorld::ConstPtr& ptr) const; @@ -366,11 +371,7 @@ namespace MWWorld virtual void setBaseAISetting(const std::string& id, MWMechanics::CreatureStats::AiSetting setting, int value) const; - virtual float getWalkSpeed(const Ptr& ptr) const; - - virtual float getRunSpeed(const Ptr& ptr) const; - - virtual float getSwimSpeed(const Ptr& ptr) const; + virtual void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const; }; } diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 6337ca440..3852b1abe 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -23,6 +23,21 @@ namespace { + void addScripts(MWWorld::ContainerStore& store, MWWorld::CellStore* cell) + { + auto& scripts = MWBase::Environment::get().getWorld()->getLocalScripts(); + for(const MWWorld::Ptr& ptr : store) + { + const std::string& script = ptr.getClass().getScript(ptr); + if(!script.empty()) + { + MWWorld::Ptr item = ptr; + item.mCell = cell; + scripts.add(script, item); + } + } + } + template float getTotalWeight (const MWWorld::CellRefList& cellRefList) { @@ -44,6 +59,7 @@ namespace MWWorld::Ptr searchId (MWWorld::CellRefList& list, const std::string& id, MWWorld::ContainerStore *store) { + store->resolve(); std::string id2 = Misc::StringUtils::lowerCase (id); for (typename MWWorld::CellRefList::List::iterator iter (list.mList.begin()); @@ -61,6 +77,18 @@ namespace } } +MWWorld::ResolutionListener::~ResolutionListener() +{ + if(!mStore.mModified && mStore.mResolved && !mStore.mPtr.isEmpty()) + { + for(const MWWorld::Ptr& ptr : mStore) + ptr.getRefData().setCount(0); + mStore.fillNonRandom(mStore.mPtr.get()->mBase->mInventory, "", mStore.mSeed); + addScripts(mStore, mStore.mPtr.mCell); + mStore.mResolved = false; + } +} + template MWWorld::ContainerStoreIterator MWWorld::ContainerStore::getState (CellRefList& collection, const ESM::ObjectState& state) @@ -119,7 +147,11 @@ MWWorld::ContainerStore::ContainerStore() : mListener(nullptr) , mRechargingItemsUpToDate(false) , mCachedWeight (0) - , mWeightUpToDate (false) {} + , mWeightUpToDate (false) + , mModified(false) + , mResolved(false) + , mSeed() + , mPtr() {} MWWorld::ContainerStore::~ContainerStore() {} @@ -153,22 +185,12 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end() return ContainerStoreIterator (this); } -int MWWorld::ContainerStore::count(const std::string &id) +int MWWorld::ContainerStore::count(const std::string &id) const { int total=0; - for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter) - if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id)) - total += iter->getRefData().getCount(); - return total; -} - -int MWWorld::ContainerStore::restockCount(const std::string &id) -{ - int total=0; - for (MWWorld::ContainerStoreIterator iter (begin()); iter!=end(); ++iter) - if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), id)) - if (iter->getCellRef().getSoul().empty()) - total += iter->getRefData().getCount(); + for (const auto& iter : *this) + if (Misc::StringUtils::ciEqual(iter.getCellRef().getRefId(), id)) + total += iter.getRefData().getCount(); return total; } @@ -185,9 +207,10 @@ void MWWorld::ContainerStore::setContListener(MWWorld::ContainerStoreListener* l MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container, int count) { + resolve(); if (ptr.getRefData().getCount() <= count) return end(); - MWWorld::ContainerStoreIterator it = addNewStack(ptr, ptr.getRefData().getCount()-count); + MWWorld::ContainerStoreIterator it = addNewStack(ptr, subtractItems(ptr.getRefData().getCount(false), count)); const std::string script = it->getClass().getScript(*it); if (!script.empty()) MWBase::Environment::get().getWorld()->getLocalScripts().add(script, *it); @@ -199,6 +222,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::unstack(const Ptr &ptr, MWWorld::ContainerStoreIterator MWWorld::ContainerStore::restack(const MWWorld::Ptr& item) { + resolve(); MWWorld::ContainerStoreIterator retval = end(); for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter) { @@ -216,7 +240,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::restack(const MWWorld:: { if (stacks(*iter, item)) { - iter->getRefData().setCount(iter->getRefData().getCount() + item.getRefData().getCount()); + iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), item.getRefData().getCount(false))); item.getRefData().setCount(0); retval = iter; break; @@ -266,11 +290,11 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string & return add(ref.getPtr(), count, actorPtr); } -MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool /*allowAutoEquip*/) +MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool /*allowAutoEquip*/, bool resolve) { Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr(); - MWWorld::ContainerStoreIterator it = addImp(itemPtr, count); + MWWorld::ContainerStoreIterator it = addImp(itemPtr, count, resolve); // The copy of the original item we just made MWWorld::Ptr item = *it; @@ -328,8 +352,10 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr return it; } -MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, int count) +MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, int count, bool markModified) { + if(markModified) + resolve(); int type = getType(ptr); const MWWorld::ESMStore &esmStore = @@ -345,7 +371,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, { if (Misc::StringUtils::ciEqual((*iter).getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) { - iter->getRefData().setCount(iter->getRefData().getCount() + realCount); + iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), realCount)); flagAsModified(); return iter; } @@ -361,7 +387,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr, if (stacks(*iter, ptr)) { // stack - iter->getRefData().setCount( iter->getRefData().getCount() + count ); + iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), count)); flagAsModified(); return iter; @@ -437,13 +463,15 @@ void MWWorld::ContainerStore::updateRechargingItems() } } -int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor) +int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor, bool resolveFirst) { + if(resolveFirst) + resolve(); int toRemove = count; for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter) if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId)) - toRemove -= remove(*iter, toRemove, actor); + toRemove -= removeImp(*iter, toRemove, actor); flagAsModified(); @@ -465,7 +493,13 @@ bool MWWorld::ContainerStore::hasVisibleItems() const int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor) { assert(this == item.getContainerStore()); + resolve(); + return removeImp(item, count, actor); +} + +int MWWorld::ContainerStore::removeImp(const Ptr& item, int count, const Ptr& actor) +{ int toRemove = count; RefData& itemRef = item.getRefData(); @@ -476,7 +510,7 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor } else { - itemRef.setCount(itemRef.getCount() - toRemove); + itemRef.setCount(subtractItems(itemRef.getCount(false), toRemove)); toRemove = 0; } @@ -490,20 +524,33 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor return count - toRemove; } -void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner) +void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Seed& seed) { - for (std::vector::const_iterator iter (items.mList.begin()); iter!=items.mList.end(); - ++iter) + for (const ESM::ContItem& iter : items.mList) { - std::string id = Misc::StringUtils::lowerCase(iter->mItem); - addInitialItem(id, owner, iter->mCount); + std::string id = Misc::StringUtils::lowerCase(iter.mItem); + addInitialItem(id, owner, iter.mCount, &seed); } flagAsModified(); + mResolved = true; } -void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, - int count, bool topLevel, const std::string& levItem) +void MWWorld::ContainerStore::fillNonRandom (const ESM::InventoryList& items, const std::string& owner, unsigned int seed) +{ + mSeed = seed; + for (const ESM::ContItem& iter : items.mList) + { + std::string id = Misc::StringUtils::lowerCase(iter.mItem); + addInitialItem(id, owner, iter.mCount, nullptr); + } + + flagAsModified(); + mResolved = false; +} + +void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, + Misc::Rng::Seed* seed, bool topLevel) { if (count == 0) return; //Don't restock with nothing. try @@ -511,13 +558,13 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std:: ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); if (ref.getPtr().getClass().getScript(ref.getPtr()).empty()) { - addInitialItemImp(ref.getPtr(), owner, count, topLevel, levItem); + addInitialItemImp(ref.getPtr(), owner, count, seed, topLevel); } else { // Adding just one item per time to make sure there isn't a stack of scripted items - for (int i = 0; i < abs(count); i++) - addInitialItemImp(ref.getPtr(), owner, count < 0 ? -1 : 1, topLevel, levItem); + for (int i = 0; i < std::abs(count); i++) + addInitialItemImp(ref.getPtr(), owner, count < 0 ? -1 : 1, seed, topLevel); } } catch (const std::exception& e) @@ -526,137 +573,43 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std:: } } -void MWWorld::ContainerStore::addInitialItemImp(const MWWorld::Ptr& ptr, const std::string& owner, - int count, bool topLevel, const std::string& levItem) +void MWWorld::ContainerStore::addInitialItemImp(const MWWorld::Ptr& ptr, const std::string& owner, int count, + Misc::Rng::Seed* seed, bool topLevel) { if (ptr.getTypeName()==typeid (ESM::ItemLevList).name()) { + if(!seed) + return; const ESM::ItemLevList* levItemList = ptr.get()->mBase; if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each) { for (int i=0; i 0 ? 1 : -1, true, levItemList->mId); + addInitialItem(ptr.getCellRef().getRefId(), owner, count > 0 ? 1 : -1, seed, true); return; } else { - std::string itemId = MWMechanics::getLevelledItem(ptr.get()->mBase, false); + std::string itemId = MWMechanics::getLevelledItem(ptr.get()->mBase, false, *seed); if (itemId.empty()) return; - addInitialItem(itemId, owner, count, false, levItemList->mId); + addInitialItem(itemId, owner, count, seed, false); } } else { - // A negative count indicates restocking items - // For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks - if (!levItem.empty() && count < 0) - { - //If there is no item in map, insert it - std::map, int>::iterator itemInMap = - mLevelledItemMap.insert(std::make_pair(std::make_pair(ptr.getCellRef().getRefId(), levItem), 0)).first; - //Update spawned count - itemInMap->second += std::abs(count); - } - count = std::abs(count); - ptr.getCellRef().setOwner(owner); - addImp (ptr, count); + addImp (ptr, count, false); } } -void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner) -{ - //allowedForReplace - Holds information about how many items from the list were not sold; - // Hence, tells us how many items we don't need to restock. - //allowedForReplace[list] <- How many items we should generate(how many of these were sold) - std::map allowedForReplace; - - //Check which lists need restocking: - for (std::map, int>::iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end();) - { - int spawnedCount = it->second; //How many items should be in shop originally - int itemCount = restockCount(it->first.first); //How many items are there in shop now - //If something was not sold - if(itemCount >= spawnedCount) - { - const std::string& parent = it->first.second; - // Security check for old saves: - //If item is imported from old save(doesn't have an parent) and wasn't sold - if(parent == "") - { - //Remove it, from shop, - remove(it->first.first, itemCount, ptr);//ptr is the NPC - //And remove it from map, so that when we restock, the new item will have proper parent. - mLevelledItemMap.erase(it++); - continue; - } - //Create the entry if it does not exist yet - std::map::iterator listInMap = allowedForReplace.insert( - std::make_pair(it->first.second, 0)).first; - //And signal that we don't need to restock item from this list - listInMap->second += std::abs(itemCount); - } - //If every of the item was sold - else if (itemCount == 0) - { - mLevelledItemMap.erase(it++); - continue; - } - //If some was sold, but some remain - else - { - //Create entry if it does not exist yet - std::map::iterator listInMap = allowedForReplace.insert( - std::make_pair(it->first.second, 0)).first; - //And signal that we don't need to restock all items from this list - listInMap->second += std::abs(itemCount); - //And update itemCount so we don't mistake it next time. - it->second = itemCount; - } - ++it; - } - - //Restock: - //For every item that NPC could have - for (std::vector::const_iterator it = items.mList.begin(); it != items.mList.end(); ++it) - { - //If he shouldn't have it restocked, don't restock it. - if (it->mCount >= 0) - continue; - - std::string itemOrList = Misc::StringUtils::lowerCase(it->mItem); - - //If it's levelled list, restock if there's need to do so. - if (MWBase::Environment::get().getWorld()->getStore().get().search(it->mItem)) - { - std::map::iterator listInMap = allowedForReplace.find(itemOrList); - - int restockNum = std::abs(it->mCount); - //If we know we must restock less, take it into account - if(listInMap != allowedForReplace.end()) - restockNum -= std::min(restockNum, listInMap->second); - //restock - addInitialItem(itemOrList, owner, -restockNum, true); - } - else - { - //Restocking static item - just restock to the max count - int currentCount = restockCount(itemOrList); - if (currentCount < std::abs(it->mCount)) - addInitialItem(itemOrList, owner, -(std::abs(it->mCount) - currentCount), true); - } - } - flagAsModified(); -} - void MWWorld::ContainerStore::clear() { for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) iter->getRefData().setCount (0); flagAsModified(); + mModified = true; } void MWWorld::ContainerStore::flagAsModified() @@ -665,6 +618,45 @@ void MWWorld::ContainerStore::flagAsModified() mRechargingItemsUpToDate = false; } +bool MWWorld::ContainerStore::isResolved() const +{ + return mResolved; +} + +void MWWorld::ContainerStore::resolve() +{ + if(!mResolved && !mPtr.isEmpty()) + { + for(const MWWorld::Ptr& ptr : *this) + ptr.getRefData().setCount(0); + Misc::Rng::Seed seed{mSeed}; + fill(mPtr.get()->mBase->mInventory, "", seed); + addScripts(*this, mPtr.mCell); + } + mModified = true; +} + +MWWorld::ResolutionHandle MWWorld::ContainerStore::resolveTemporarily() +{ + if(mModified) + return {}; + std::shared_ptr listener = mResolutionListener.lock(); + if(!listener) + { + listener = std::make_shared(*this); + mResolutionListener = listener; + } + if(!mResolved && !mPtr.isEmpty()) + { + for(const MWWorld::Ptr& ptr : *this) + ptr.getRefData().setCount(0); + Misc::Rng::Seed seed{mSeed}; + fill(mPtr.get()->mBase->mInventory, "", seed); + addScripts(*this, mPtr.mCell); + } + return {listener}; +} + float MWWorld::ContainerStore::getWeight() const { if (!mWeightUpToDate) @@ -761,6 +753,7 @@ MWWorld::Ptr MWWorld::ContainerStore::findReplacement(const std::string& id) MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id) { + resolve(); { Ptr ptr = searchId (potions, id, this); if (!ptr.isEmpty()) @@ -836,6 +829,22 @@ MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id) return Ptr(); } +int MWWorld::ContainerStore::addItems(int count1, int count2) +{ + int sum = std::abs(count1) + std::abs(count2); + if(count1 < 0 || count2 < 0) + return -sum; + return sum; +} + +int MWWorld::ContainerStore::subtractItems(int count1, int count2) +{ + int sum = std::abs(count1) - std::abs(count2); + if(count1 < 0 || count2 < 0) + return -sum; + return sum; +} + void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const { state.mItems.clear(); @@ -853,13 +862,13 @@ void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const storeStates (repairs, state, index); storeStates (weapons, state, index, true); storeStates (lights, state, index, true); - - state.mLevelledItemMap = mLevelledItemMap; } void MWWorld::ContainerStore::readState (const ESM::InventoryState& inventory) { clear(); + mModified = true; + mResolved = true; int index = 0; for (std::vector::const_iterator @@ -893,9 +902,6 @@ void MWWorld::ContainerStore::readState (const ESM::InventoryState& inventory) break; } } - - - mLevelledItemMap = inventory.mLevelledItemMap; } template diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index f2858c5aa..9092d41fc 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -18,6 +19,8 @@ #include #include +#include + #include "ptr.hpp" #include "cellreflist.hpp" @@ -27,6 +30,11 @@ namespace ESM struct InventoryState; } +namespace MWClass +{ + class Container; +} + namespace MWWorld { class ContainerStore; @@ -37,6 +45,21 @@ namespace MWWorld typedef ContainerStoreIteratorBase ContainerStoreIterator; typedef ContainerStoreIteratorBase ConstContainerStoreIterator; + class ResolutionListener + { + ContainerStore& mStore; + public: + ResolutionListener(ContainerStore& store) : mStore(store) {} + ~ResolutionListener(); + }; + + class ResolutionHandle + { + std::shared_ptr mListener; + public: + ResolutionHandle(std::shared_ptr listener) : mListener(listener) {} + ResolutionHandle() {} + }; class ContainerStoreListener { @@ -93,15 +116,20 @@ namespace MWWorld MWWorld::CellRefList repairs; MWWorld::CellRefList weapons; - std::map, int> mLevelledItemMap; - ///< Stores result of levelled item spawns. <(refId, spawningGroup), count> - /// This is used to restock levelled items(s) if the old item was sold. - mutable float mCachedWeight; mutable bool mWeightUpToDate; - ContainerStoreIterator addImp (const Ptr& ptr, int count); - void addInitialItem (const std::string& id, const std::string& owner, int count, bool topLevel=true, const std::string& levItem = ""); - void addInitialItemImp (const MWWorld::Ptr& ptr, const std::string& owner, int count, bool topLevel=true, const std::string& levItem = ""); + + bool mModified; + bool mResolved; + unsigned int mSeed; + MWWorld::Ptr mPtr; + std::weak_ptr mResolutionListener; + + ContainerStoreIterator addImp (const Ptr& ptr, int count, bool markModified = true); + void addInitialItem (const std::string& id, const std::string& owner, int count, Misc::Rng::Seed* seed, bool topLevel=true); + void addInitialItemImp (const MWWorld::Ptr& ptr, const std::string& owner, int count, Misc::Rng::Seed* seed, bool topLevel=true); + + int removeImp(const Ptr& item, int count, const Ptr& actor); template ContainerStoreIterator getState (CellRefList& collection, @@ -139,7 +167,7 @@ namespace MWWorld bool hasVisibleItems() const; - virtual ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip = true); + virtual ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip = true, bool resolve = true); ///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed) /// /// \note The item pointed to is not required to exist beyond this function call. @@ -152,7 +180,7 @@ namespace MWWorld ContainerStoreIterator add(const std::string& id, int count, const Ptr& actorPtr); ///< Utility to construct a ManualRef and call add(ptr, count, actorPtr, true) - int remove(const std::string& itemId, int count, const Ptr& actor); + int remove(const std::string& itemId, int count, const Ptr& actor, bool resolve = true); ///< Remove \a count item(s) designated by \a itemId from this container. /// /// @return the number of items actually removed @@ -175,31 +203,31 @@ namespace MWWorld /// If a compatible stack is found, the item's count is added to that stack, then the original is deleted. /// @return If the item was stacked, return the stack, otherwise return the old (untouched) item. - int count (const std::string& id); + int count (const std::string& id) const; ///< @return How many items with refID \a id are in this container? - int restockCount (const std::string& id); - ///< Item count with restock adjustments (such as ignoring filled soul gems). - /// @return How many items with refID \a id are in this container? - ContainerStoreListener* getContListener() const; void setContListener(ContainerStoreListener* listener); - protected: ContainerStoreIterator addNewStack (const ConstPtr& ptr, int count); ///< Add the item to this container (do not try to stack it onto existing items) virtual void flagAsModified(); + /// + and - operations that can deal with negative stacks + /// Note that negativity is infectious + static int addItems(int count1, int count2); + static int subtractItems(int count1, int count2); public: virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const; ///< @return true if the two specified objects can stack with each other - void fill (const ESM::InventoryList& items, const std::string& owner); + void fill (const ESM::InventoryList& items, const std::string& owner, Misc::Rng::Seed& seed = Misc::Rng::getSeed()); ///< Insert items into *this. - void restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner); + void fillNonRandom (const ESM::InventoryList& items, const std::string& owner, unsigned int seed); + ///< Insert items into *this, excluding leveled items virtual void clear(); ///< Empty container. @@ -220,8 +248,15 @@ namespace MWWorld virtual void readState (const ESM::InventoryState& state); + bool isResolved() const; + + void resolve(); + ResolutionHandle resolveTemporarily(); + friend class ContainerStoreIteratorBase; friend class ContainerStoreIteratorBase; + friend class ResolutionListener; + friend class MWClass::Container; }; diff --git a/apps/openmw/mwworld/esmloader.hpp b/apps/openmw/mwworld/esmloader.hpp index b96af707c..506105beb 100644 --- a/apps/openmw/mwworld/esmloader.hpp +++ b/apps/openmw/mwworld/esmloader.hpp @@ -25,7 +25,7 @@ struct EsmLoader : public ContentLoader EsmLoader(MWWorld::ESMStore& store, std::vector& readers, ToUTF8::Utf8Encoder* encoder, Loading::Listener& listener); - void load(const boost::filesystem::path& filepath, int& index); + void load(const boost::filesystem::path& filepath, int& index) override; private: std::vector& mEsm; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 278b8532e..aea9a5e4f 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -9,6 +9,47 @@ #include #include +#include "../mwmechanics/spelllist.hpp" + +namespace +{ + void readRefs(const ESM::Cell& cell, std::map& refs, std::vector& readers) + { + for (size_t i = 0; i < cell.mContextList.size(); i++) + { + size_t index = cell.mContextList[i].index; + if (readers.size() <= index) + readers.resize(index + 1); + cell.restore(readers[index], i); + ESM::CellRef ref; + ref.mRefNum.mContentFile = ESM::RefNum::RefNum_NoContentFile; + bool deleted = false; + while(cell.getNextRef(readers[index], ref, deleted)) + { + if(deleted) + refs.erase(ref.mRefNum); + else if (std::find(cell.mMovedRefs.begin(), cell.mMovedRefs.end(), ref.mRefNum) == cell.mMovedRefs.end()) + { + Misc::StringUtils::lowerCaseInPlace(ref.mRefID); + refs[ref.mRefNum] = ref.mRefID; + } + } + } + for(const auto& it : cell.mLeasedRefs) + { + bool deleted = it.second; + if(deleted) + refs.erase(it.first.mRefNum); + else + { + ESM::CellRef ref = it.first; + Misc::StringUtils::lowerCaseInPlace(ref.mRefID); + refs[ref.mRefNum] = ref.mRefID; + } + } + } +} + namespace MWWorld { @@ -146,7 +187,33 @@ void ESMStore::setUp(bool validateRecords) mDialogs.setUp(); if (validateRecords) + { validate(); + countRecords(); + } +} + +void ESMStore::countRecords() +{ + if(!mRefCount.empty()) + return; + std::map refs; + std::vector readers; + for(auto it = mCells.intBegin(); it != mCells.intEnd(); it++) + readRefs(*it, refs, readers); + for(auto it = mCells.extBegin(); it != mCells.extEnd(); it++) + readRefs(*it, refs, readers); + for(const auto& pair : refs) + mRefCount[pair.second]++; +} + +int ESMStore::getRefCount(const std::string& id) const +{ + const std::string lowerId = Misc::StringUtils::lowerCase(id); + auto it = mRefCount.find(lowerId); + if(it == mRefCount.end()) + return 0; + return it->second; } void ESMStore::validate() @@ -344,4 +411,23 @@ void ESMStore::validate() throw std::runtime_error ("Invalid player record (race or class unavailable"); } + std::pair, bool> ESMStore::getSpellList(const std::string& originalId) const + { + const std::string id = Misc::StringUtils::lowerCase(originalId); + auto result = mSpellListCache.find(id); + std::shared_ptr ptr; + if (result != mSpellListCache.end()) + ptr = result->second.lock(); + if (!ptr) + { + int type = find(id); + ptr = std::make_shared(id, type); + if (result != mSpellListCache.end()) + result->second = ptr; + else + mSpellListCache.insert({id, ptr}); + return {ptr, false}; + } + return {ptr, true}; + } } // end namespace diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 24364bfb1..99db96ac1 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_MWWORLD_ESMSTORE_H #define OPENMW_MWWORLD_ESMSTORE_H +#include #include #include @@ -12,6 +13,11 @@ namespace Loading class Listener; } +namespace MWMechanics +{ + class SpellList; +} + namespace MWWorld { class ESMStore @@ -70,15 +76,20 @@ namespace MWWorld std::map mIds; std::map mStaticIds; + std::map mRefCount; + std::map mStores; ESM::NPC mPlayerTemplate; unsigned int mDynamicCount; + mutable std::map > mSpellListCache; + /// Validate entries in store after setup void validate(); + void countRecords(); public: /// \todo replace with SharedIterator typedef std::map::const_iterator iterator; @@ -252,6 +263,13 @@ namespace MWWorld // To be called when we are done with dynamic record loading void checkPlayer(); + + /// @return The number of instances defined in the base files. Excludes changes from the save file. + int getRefCount(const std::string& id) const; + + /// Actors with the same ID share spells, abilities, etc. + /// @return The shared spell list to use for this actor and whether or not it has already been initialized. + std::pair, bool> getSpellList(const std::string& id) const; }; template <> diff --git a/apps/openmw/mwworld/failedaction.hpp b/apps/openmw/mwworld/failedaction.hpp index bafbb6f2d..2a201cdb3 100644 --- a/apps/openmw/mwworld/failedaction.hpp +++ b/apps/openmw/mwworld/failedaction.hpp @@ -10,7 +10,7 @@ namespace MWWorld { std::string mMessage; - virtual void executeImp(const Ptr &actor); + void executeImp(const Ptr &actor) override; public: FailedAction(const std::string &message = std::string(), const Ptr& target = Ptr()); diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index ada211470..c2785579b 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -86,8 +86,9 @@ void MWWorld::InventoryStore::readEquipmentState(const MWWorld::ContainerStoreIt // unstack if required if (!allowedSlots.second && iter->getRefData().getCount() > 1) { - MWWorld::ContainerStoreIterator newIter = addNewStack(*iter, 1); - iter->getRefData().setCount(iter->getRefData().getCount()-1); + int count = iter->getRefData().getCount(false); + MWWorld::ContainerStoreIterator newIter = addNewStack(*iter, count > 0 ? 1 : -1); + iter->getRefData().setCount(subtractItems(count, 1)); mSlots[slot] = newIter; } else @@ -131,9 +132,9 @@ MWWorld::InventoryStore& MWWorld::InventoryStore::operator= (const InventoryStor return *this; } -MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip) +MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip, bool resolve) { - const MWWorld::ContainerStoreIterator& retVal = MWWorld::ContainerStore::add(itemPtr, count, actorPtr, allowAutoEquip); + const MWWorld::ContainerStoreIterator& retVal = MWWorld::ContainerStore::add(itemPtr, count, actorPtr, allowAutoEquip, resolve); // Auto-equip items if an armor/clothing item is added, but not for the player nor werewolves if (allowAutoEquip && actorPtr != MWMechanics::getPlayer() @@ -850,8 +851,8 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItemQuantity(con { if (stacks(*iter, item) && !isEquipped(*iter)) { - iter->getRefData().setCount(iter->getRefData().getCount() + count); - item.getRefData().setCount(item.getRefData().getCount() - count); + iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), count)); + item.getRefData().setCount(subtractItems(item.getRefData().getCount(false), count)); return iter; } } @@ -917,7 +918,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito float magnitude = effect.mMagnMin + (effect.mMagnMax - effect.mMagnMin) * params.mRandom; magnitude *= params.mMultiplier; if (magnitude > 0) - visitor.visit(MWMechanics::EffectKey(effect), (**iter).getClass().getName(**iter), (**iter).getCellRef().getRefId(), -1, magnitude); + visitor.visit(MWMechanics::EffectKey(effect), i-1, (**iter).getClass().getName(**iter), (**iter).getCellRef().getRefId(), -1, magnitude); } } } @@ -931,7 +932,7 @@ void MWWorld::InventoryStore::purgeEffect(short effectId, bool wholeSpell) } } -void MWWorld::InventoryStore::purgeEffect(short effectId, const std::string &sourceId, bool wholeSpell) +void MWWorld::InventoryStore::purgeEffect(short effectId, const std::string &sourceId, bool wholeSpell, int effectIndex) { TEffectMagnitudes::iterator effectMagnitudeIt = mPermanentMagicEffectMagnitudes.find(sourceId); if (effectMagnitudeIt == mPermanentMagicEffectMagnitudes.end()) @@ -964,6 +965,9 @@ void MWWorld::InventoryStore::purgeEffect(short effectId, const std::string &sou if (effectIt->mEffectID != effectId) continue; + if (effectIndex >= 0 && effectIndex != i) + continue; + if (wholeSpell) { mPermanentMagicEffectMagnitudes.erase(sourceId); diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index d597e5f30..12306f809 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -110,8 +110,8 @@ namespace MWWorld void fireEquipmentChangedEvent(const Ptr& actor); - virtual void storeEquipmentState (const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const; - virtual void readEquipmentState (const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState& inventory); + void storeEquipmentState (const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const override; + void readEquipmentState (const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState& inventory) override; ContainerStoreIterator findSlot (int slot) const; @@ -123,9 +123,9 @@ namespace MWWorld InventoryStore& operator= (const InventoryStore& store); - virtual InventoryStore* clone() { return new InventoryStore(*this); } + InventoryStore* clone() override { return new InventoryStore(*this); } - virtual ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip = true); + ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool allowAutoEquip = true, bool resolve = true) override; ///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed) /// Auto-equip items if specific conditions are fulfilled and allowAutoEquip is true (see the implementation). /// @@ -162,13 +162,13 @@ namespace MWWorld const MWMechanics::MagicEffects& getMagicEffects() const; ///< Return magic effects from worn items. - virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const; + bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const override; ///< @return true if the two specified objects can stack with each other virtual int remove(const std::string& itemId, int count, const Ptr& actor); virtual int remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement); - virtual int remove(const Ptr& item, int count, const Ptr& actor); + int remove(const Ptr& item, int count, const Ptr& actor) override; virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement); ///< Remove \a count item(s) designated by \a item from this inventory. /// @@ -206,15 +206,15 @@ namespace MWWorld void purgeEffect (short effectId, bool wholeSpell = false); ///< Remove a magic effect - void purgeEffect (short effectId, const std::string& sourceId, bool wholeSpell = false); + void purgeEffect (short effectId, const std::string& sourceId, bool wholeSpell = false, int effectIndex=-1); ///< Remove a magic effect - virtual void clear(); + void clear() override; ///< Empty container. - virtual void writeState (ESM::InventoryState& state) const; + void writeState (ESM::InventoryState& state) const override; - virtual void readState (const ESM::InventoryState& state); + void readState (const ESM::InventoryState& state) override; }; } diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 4b61c0a08..414fde42b 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -87,12 +87,12 @@ namespace MWWorld // The object that this instance is based on. const X* mBase; - virtual void load (const ESM::ObjectState& state); + void load (const ESM::ObjectState& state) override; ///< Load state into a LiveCellRef, that has already been initialised with base and class. /// /// \attention Must not be called with an invalid \a state. - virtual void save (ESM::ObjectState& state) const; + void save (ESM::ObjectState& state) const override; ///< Save LiveCellRef state into \a state. static bool checkState (const ESM::ObjectState& state); diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index a727b4b3a..8a511030d 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -45,7 +45,7 @@ namespace // Ignore containers without generated content if (containerPtr.getTypeName() == typeid(ESM::Container).name() && containerPtr.getRefData().getCustomData() == nullptr) - return false; + return true; MWWorld::ContainerStore& container = containerPtr.getClass().getContainerStore(containerPtr); for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it) diff --git a/apps/openmw/mwworld/nullaction.hpp b/apps/openmw/mwworld/nullaction.hpp index 5461d8711..4ee1115e5 100644 --- a/apps/openmw/mwworld/nullaction.hpp +++ b/apps/openmw/mwworld/nullaction.hpp @@ -8,9 +8,9 @@ namespace MWWorld /// \brief Action: do nothing class NullAction : public Action { - virtual void executeImp (const Ptr& actor) {} + void executeImp (const Ptr& actor) override {} - virtual bool isNullAction() { return true; } + bool isNullAction() override { return true; } }; } diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 1ee6ebe1f..3e37088a7 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -235,7 +235,8 @@ namespace MWWorld MWWorld::Ptr player = getPlayer(); const MWMechanics::NpcStats &playerStats = player.getClass().getNpcStats(player); - if (playerStats.isParalyzed() || playerStats.getKnockedDown() || playerStats.isDead()) + bool godmode = MWBase::Environment::get().getWorld()->getGodModeState(); + if ((!godmode && playerStats.isParalyzed()) || playerStats.getKnockedDown() || playerStats.isDead()) return; MWWorld::Ptr toActivate = MWBase::Environment::get().getWorld()->getFacedObject(); diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index a1c27d041..b80ab49ba 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -171,7 +171,7 @@ namespace MWWorld { } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osg::PositionAttitudeTransform* transform = static_cast(node); @@ -438,7 +438,7 @@ namespace MWWorld // Check for impact // TODO: use a proper btRigidBody / btGhostObject? - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile); + MWPhysics::RayCastingResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile); bool hit = false; if (result.mHit) @@ -514,7 +514,7 @@ namespace MWWorld // Check for impact // TODO: use a proper btRigidBody / btGhostObject? - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile); + MWPhysics::RayCastingResult result = mPhysics->castRay(pos, newPos, caster, targetActors, 0xff, MWPhysics::CollisionType_Projectile); bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), newPos); diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index f6fa3556f..a5f8ef4b1 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -146,8 +146,10 @@ namespace MWWorld return mBaseNode; } - int RefData::getCount() const + int RefData::getCount(bool absolute) const { + if(absolute) + return std::abs(mCount); return mCount; } diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 6a59d9797..738a6d53a 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -86,7 +86,7 @@ namespace MWWorld /// Set base node (can be a null pointer). void setBaseNode (SceneUtil::PositionAttitudeTransform* base); - int getCount() const; + int getCount(bool absolute = true) const; void setLocals (const ESM::Script& script); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 64316789f..bbf41ad2e 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -152,7 +152,7 @@ namespace ? btVector3(distanceFromDoor, 0, 0) : btVector3(0, distanceFromDoor, 0); - const auto& transform = object->getCollisionObject()->getWorldTransform(); + const auto transform = object->getTransform(); const btTransform closedDoorTransform( Misc::Convert::toBullet(makeObjectOsgQuat(ptr.getCellRef().getPosition())), transform.getOrigin() @@ -187,7 +187,7 @@ namespace *object->getShapeInstance()->getCollisionShape(), object->getShapeInstance()->getAvoidCollisionShape() }, - object->getCollisionObject()->getWorldTransform() + object->getTransform() ); } } @@ -961,7 +961,7 @@ namespace MWWorld { } - virtual void doWork() + void doWork() override { try { diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index f119fa928..d2406b602 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -163,8 +163,8 @@ namespace MWWorld typedef SharedIterator iterator; // setUp needs to be called again after - virtual void clearDynamic(); - void setUp(); + void clearDynamic() override; + void setUp() override; const T *search(const std::string &id) const; const T *searchStatic(const std::string &id) const; @@ -186,22 +186,22 @@ namespace MWWorld iterator begin() const; iterator end() const; - size_t getSize() const; - int getDynamicSize() const; + size_t getSize() const override; + int getDynamicSize() const override; /// @note The record identifiers are listed in the order that the records were defined by the content files. - void listIdentifier(std::vector &list) const; + void listIdentifier(std::vector &list) const override; T *insert(const T &item); T *insertStatic(const T &item); - bool eraseStatic(const std::string &id); + bool eraseStatic(const std::string &id) override; bool erase(const std::string &id); bool erase(const T &item); - RecordId load(ESM::ESMReader &esm); - void write(ESM::ESMWriter& writer, Loading::Listener& progress) const; - RecordId read(ESM::ESMReader& reader); + RecordId load(ESM::ESMReader &esm) override; + void write(ESM::ESMWriter& writer, Loading::Listener& progress) const override; + RecordId read(ESM::ESMReader& reader) override; }; template <> @@ -224,11 +224,11 @@ namespace MWWorld /// Resize the internal store to hold at least \a num plugins. void resize(size_t num); - size_t getSize() const; + size_t getSize() const override; size_t getSize(size_t plugin) const; RecordId load(ESM::ESMReader &esm, size_t plugin); - RecordId load(ESM::ESMReader &esm); + RecordId load(ESM::ESMReader &esm) override; iterator begin(size_t plugin) const; iterator end(size_t plugin) const; @@ -244,7 +244,7 @@ namespace MWWorld virtual ~Store(); - size_t getSize() const; + size_t getSize() const override; iterator begin() const; iterator end() const; @@ -253,8 +253,8 @@ namespace MWWorld const ESM::Land *search(int x, int y) const; const ESM::Land *find(int x, int y) const; - RecordId load(ESM::ESMReader &esm); - void setUp(); + RecordId load(ESM::ESMReader &esm) override; + void setUp() override; private: bool mBuilt = false; }; @@ -304,10 +304,10 @@ namespace MWWorld const ESM::Cell *find(const std::string &id) const; const ESM::Cell *find(int x, int y) const; - virtual void clearDynamic(); - void setUp(); + void clearDynamic() override; + void setUp() override; - RecordId load(ESM::ESMReader &esm); + RecordId load(ESM::ESMReader &esm) override; iterator intBegin() const; iterator intEnd() const; @@ -320,11 +320,11 @@ namespace MWWorld // Return the northernmost cell in the easternmost column. const ESM::Cell *searchExtByRegion(const std::string &id) const; - size_t getSize() const; + size_t getSize() const override; size_t getExtSize() const; size_t getIntSize() const; - void listIdentifier(std::vector &list) const; + void listIdentifier(std::vector &list) const override; ESM::Cell *insert(const ESM::Cell &cell); @@ -351,10 +351,10 @@ namespace MWWorld Store(); void setCells(Store& cells); - RecordId load(ESM::ESMReader &esm); - size_t getSize() const; + RecordId load(ESM::ESMReader &esm) override; + size_t getSize() const override; - void setUp(); + void setUp() override; const ESM::Pathgrid *search(int x, int y) const; const ESM::Pathgrid *search(const std::string& name) const; @@ -412,13 +412,13 @@ namespace MWWorld const ESM::WeaponType *search(const int id) const; const ESM::WeaponType *find(const int id) const; - RecordId load(ESM::ESMReader &esm) { return RecordId(0, false); } + RecordId load(ESM::ESMReader &esm) override { return RecordId(0, false); } ESM::WeaponType* insert(const ESM::WeaponType &weaponType); - void setUp(); + void setUp() override; - size_t getSize() const; + size_t getSize() const override; iterator begin() const; iterator end() const; }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 68d1507ce..234947c32 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -109,7 +109,7 @@ namespace MWWorld return mLoaders.insert(std::make_pair(extension, loader)).second; } - void load(const boost::filesystem::path& filepath, int& index) + void load(const boost::filesystem::path& filepath, int& index) override { LoadersContainer::iterator it(mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string()))); if (it != mLoaders.end()) @@ -151,7 +151,7 @@ namespace MWWorld const std::string& resourcePath, const std::string& userDataPath) : mResourceSystem(resourceSystem), mLocalScripts (mStore), mCells (mStore, mEsm), mSky (true), - mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles), + mGodMode(false), mScriptsEnabled(true), mDiscardMovements(true), mContentFiles (contentFiles), mUserDataPath(userDataPath), mShouldUpdateNavigator(false), mActivationDistanceOverride (activationDistanceOverride), mStartCell(startCell), mDistanceToFacedObject(-1.f), mTeleportEnabled(true), @@ -232,7 +232,7 @@ namespace MWWorld setupPlayer(); renderPlayer(); - mRendering->resetCamera(); + mRendering->getCamera()->reset(); // we don't want old weather to persist on a new game // Note that if reset later, the initial ChangeWeather that the chargen script calls will be lost. @@ -941,6 +941,7 @@ namespace MWWorld void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) { mPhysics->clearQueuedMovement(); + mDiscardMovements = true; if (changeEvent && mCurrentWorldSpace != cellName) { @@ -966,6 +967,7 @@ namespace MWWorld void World::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) { mPhysics->clearQueuedMovement(); + mDiscardMovements = true; if (changeEvent && mCurrentWorldSpace != ESM::CellId::sDefaultWorldspace) { @@ -1535,24 +1537,23 @@ namespace MWWorld void World::doPhysics(float duration) { - mPhysics->stepSimulation(duration); + mPhysics->stepSimulation(); processDoors(duration); mProjectileManager->update(duration); - const MWPhysics::PtrVelocityList &results = mPhysics->applyQueuedMovement(duration); - MWPhysics::PtrVelocityList::const_iterator player(results.end()); - for(MWPhysics::PtrVelocityList::const_iterator iter(results.begin());iter != results.end();++iter) + const auto results = mPhysics->applyQueuedMovement(duration, mDiscardMovements); + mDiscardMovements = false; + + for(const auto& result : results) { - if(iter->first == getPlayerPtr()) - { - // Handle player last, in case a cell transition occurs - player = iter; - continue; - } - moveObjectImp(iter->first, iter->second.x(), iter->second.y(), iter->second.z(), false); + // Handle player last, in case a cell transition occurs + if(result.first != getPlayerPtr()) + moveObjectImp(result.first, result.second.x(), result.second.y(), result.second.z(), false); } - if(player != results.end()) + + const auto player = results.find(getPlayerPtr()); + if (player != results.end()) moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false); } @@ -1580,7 +1581,12 @@ namespace MWWorld *object->getShapeInstance()->getCollisionShape(), object->getShapeInstance()->getAvoidCollisionShape() }; - return mNavigator->updateObject(DetourNavigator::ObjectId(object), shapes, object->getCollisionObject()->getWorldTransform()); + return mNavigator->updateObject(DetourNavigator::ObjectId(object), shapes, object->getTransform()); + } + + const MWPhysics::RayCastingInterface* World::getRayCasting() const + { + return mPhysics.get(); } bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2) @@ -1595,7 +1601,7 @@ namespace MWWorld osg::Vec3f a(x1,y1,z1); osg::Vec3f b(x2,y2,z2); - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector(), mask); + MWPhysics::RayCastingResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector(), mask); return result.mHit; } @@ -1770,6 +1776,11 @@ namespace MWWorld return mStore.overrideRecord(record); } + const ESM::Container *World::createOverrideRecord(const ESM::Container &record) + { + return mStore.overrideRecord(record); + } + const ESM::NPC *World::createRecord(const ESM::NPC &record) { bool update = false; @@ -1899,42 +1910,14 @@ namespace MWWorld else mRendering->getCamera()->setSneakOffset(0.f); - int blind = static_cast(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude()); + int blind = 0; + auto& magicEffects = player.getClass().getCreatureStats(player).getMagicEffects(); + if (!mGodMode) + blind = static_cast(magicEffects.get(ESM::MagicEffect::Blind).getMagnitude()); MWBase::Environment::get().getWindowManager()->setBlindness(std::max(0, std::min(100, blind))); - int nightEye = static_cast(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude()); + int nightEye = static_cast(magicEffects.get(ESM::MagicEffect::NightEye).getMagnitude()); mRendering->setNightEyeFactor(std::min(1.f, (nightEye/100.f))); - - auto* camera = mRendering->getCamera(); - camera->setCameraDistance(); - if(!mRendering->getCamera()->isFirstPerson()) - { - 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(); - float offsetLen = focalOffset.length(); - if (offsetLen > 0) - { - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit); - if (result.mHit) - { - double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen; - if (adjustmentCoef < -1) - adjustmentCoef = -1; - camera->adjustFocalPoint(focalOffset * adjustmentCoef); - } - } - - // Adjust camera position. - osg::Vec3d cameraPos; - camera->getPosition(focal, cameraPos); - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal, cameraPos, cameraObstacleLimit); - if (result.mHit) - mRendering->getCamera()->setCameraDistance((result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length(), false); - } } void World::preloadSpells() @@ -2025,7 +2008,7 @@ namespace MWWorld MWWorld::Ptr World::getFacedObject(float maxDistance, bool ignorePlayer) { - const float camDist = mRendering->getCameraDistance(); + const float camDist = mRendering->getCamera()->getCameraDistance(); maxDistance += camDist; MWWorld::Ptr facedObject; MWRender::RayResult rayToObject; @@ -2245,6 +2228,8 @@ namespace MWWorld Ptr World::copyObjectToCell(const ConstPtr &object, CellStore* cell, ESM::Position pos, int count, bool adjustPos) { + if (!cell) + throw std::runtime_error("copyObjectToCell(): cannot copy object to null cell"); if (cell->isExterior()) { int cellX, cellY; @@ -2428,22 +2413,27 @@ namespace MWWorld void World::togglePOV(bool force) { - mRendering->togglePOV(force); + mRendering->getCamera()->toggleViewMode(force); } bool World::isFirstPerson() const { return mRendering->getCamera()->isFirstPerson(); } + + bool World::isPreviewModeEnabled() const + { + return mRendering->getCamera()->getMode() == MWRender::Camera::Mode::Preview; + } void World::togglePreviewMode(bool enable) { - mRendering->togglePreviewMode(enable); + mRendering->getCamera()->togglePreviewMode(enable); } bool World::toggleVanityMode(bool enable) { - return mRendering->toggleVanityMode(enable); + return mRendering->getCamera()->toggleVanityMode(enable); } void World::disableDeferredPreviewRotation() @@ -2458,22 +2448,21 @@ namespace MWWorld void World::allowVanityMode(bool allow) { - mRendering->allowVanityMode(allow); - } - - void World::changeVanityModeScale(float factor) - { - mRendering->changeVanityModeScale(factor); + mRendering->getCamera()->allowVanityMode(allow); } bool World::vanityRotateCamera(float * rot) { - return mRendering->vanityRotateCamera(rot); + if(!mRendering->getCamera()->isVanityOrPreviewModeEnabled()) + return false; + + mRendering->getCamera()->rotateCamera(rot[0], 0.f, rot[2], true); + return true; } - void World::setCameraDistance(float dist, bool adjust, bool override_) + void World::adjustCameraDistance(float dist) { - mRendering->setCameraDistance(dist, adjust, override_); + mRendering->getCamera()->adjustCameraDistance(dist); } void World::setupPlayer() @@ -2796,7 +2785,7 @@ namespace MWWorld if (includeWater) { collisionTypes |= MWPhysics::CollisionType_Water; } - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(from, to, MWWorld::Ptr(), std::vector(), collisionTypes); + MWPhysics::RayCastingResult result = mPhysics->castRay(from, to, MWWorld::Ptr(), std::vector(), collisionTypes); if (!result.mHit) return maxDist; @@ -3171,7 +3160,7 @@ namespace MWWorld actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors); // Check for impact, if yes, handle hit, if not, launch projectile - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(sourcePos, worldPos, actor, targetActors, 0xff, MWPhysics::CollisionType_Projectile); + MWPhysics::RayCastingResult result = mPhysics->castRay(sourcePos, worldPos, actor, targetActors, 0xff, MWPhysics::CollisionType_Projectile); if (result.mHit) MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength); else @@ -3194,9 +3183,9 @@ namespace MWWorld { } - virtual void visit (MWMechanics::EffectKey key, + void visit (MWMechanics::EffectKey key, int /*effectIndex*/, const std::string& /*sourceName*/, const std::string& /*sourceId*/, int /*casterActorId*/, - float /*magnitude*/, float /*remainingTime*/ = -1, float /*totalTime*/ = -1) + float /*magnitude*/, float /*remainingTime*/ = -1, float /*totalTime*/ = -1) override { const ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); const auto magicEffect = store.get().find(key.mId); @@ -3686,8 +3675,11 @@ namespace MWWorld std::string World::exportSceneGraph(const Ptr &ptr) { std::string file = mUserDataPath + "/openmw.osgt"; - mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); - mWorldScene->removeFromPagedRefs(ptr); + if (!ptr.isEmpty()) + { + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + mWorldScene->removeFromPagedRefs(ptr); + } mRendering->exportSceneGraph(ptr, file, "Ascii"); return file; } @@ -3956,7 +3948,7 @@ namespace MWWorld btVector3 aabbMax; object->getShapeInstance()->getCollisionShape()->getAabb(btTransform::getIdentity(), aabbMin, aabbMax); - const auto toLocal = object->getCollisionObject()->getWorldTransform().inverse(); + const auto toLocal = object->getTransform().inverse(); const auto localFrom = toLocal(Misc::Convert::toBullet(position)); const auto localTo = toLocal(Misc::Convert::toBullet(destination)); @@ -4070,4 +4062,9 @@ namespace MWWorld ESM::EpochTimeStamp currentDate = mCurrentDate->getEpochTimeStamp(); mRendering->skySetDate(currentDate.mDay, currentDate.mMonth); } + + std::vector World::getAll(const std::string& id) + { + return mCells.getAll(id); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 7a451fcd8..820d89806 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -104,6 +104,7 @@ namespace MWWorld bool mSky; bool mGodMode; bool mScriptsEnabled; + bool mDiscardMovements; std::vector mContentFiles; std::string mUserDataPath; @@ -291,9 +292,9 @@ namespace MWWorld ///< Return a pointer to a liveCellRef with the given name. /// \param activeOnly do non search inactive cells. - Ptr searchPtr (const std::string& name, bool activeOnly, bool searchInContainers = true) override; + Ptr searchPtr (const std::string& name, bool activeOnly, bool searchInContainers = false) override; ///< Return a pointer to a liveCellRef with the given name. - /// \param activeOnly do non search inactive cells. + /// \param activeOnly do not search inactive cells. Ptr searchPtrViaActorId (int actorId) override; ///< Search is limited to the active cells. @@ -414,6 +415,8 @@ namespace MWWorld void updateAnimatedCollisionShape(const Ptr &ptr) override; + const MWPhysics::RayCastingInterface* getRayCasting() const override; + bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, int mask) override; ///< cast a Ray and return true if there is an object in the ray path. @@ -489,6 +492,10 @@ namespace MWWorld ///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID. /// \return pointer to created record + const ESM::Container *createOverrideRecord (const ESM::Container& record) override; + ///< Write this record to the ESM store, allowing it to override a pre-existing record with the same ID. + /// \return pointer to created record + void update (float duration, bool paused) override; void updatePhysics (float duration, bool paused) override; @@ -528,17 +535,15 @@ namespace MWWorld void togglePOV(bool force = false) override; bool isFirstPerson() const override; + bool isPreviewModeEnabled() const override; void togglePreviewMode(bool enable) override; bool toggleVanityMode(bool enable) override; void allowVanityMode(bool allow) override; - - void changeVanityModeScale(float factor) override; - bool vanityRotateCamera(float * rot) override; - void setCameraDistance(float dist, bool adjust = false, bool override = true) override; + void adjustCameraDistance(float dist) override; void applyDeferredPreviewRotationToPlayer(float dt) override; void disableDeferredPreviewRotation() override; @@ -750,6 +755,8 @@ namespace MWWorld bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const override; void reportStats(unsigned int frameNumber, osg::Stats& stats) const override; + + std::vector getAll(const std::string& id) override; }; } diff --git a/apps/openmw_test_suite/esm/test_fixed_string.cpp b/apps/openmw_test_suite/esm/test_fixed_string.cpp index dc88a5f63..bd598cc93 100644 --- a/apps/openmw_test_suite/esm/test_fixed_string.cpp +++ b/apps/openmw_test_suite/esm/test_fixed_string.cpp @@ -97,7 +97,6 @@ TEST(EsmFixedString, struct_size) ASSERT_EQ(4, sizeof(ESM::NAME)); ASSERT_EQ(32, sizeof(ESM::NAME32)); ASSERT_EQ(64, sizeof(ESM::NAME64)); - ASSERT_EQ(256, sizeof(ESM::NAME256)); } TEST(EsmFixedString, is_pod) @@ -105,5 +104,4 @@ TEST(EsmFixedString, is_pod) ASSERT_TRUE(std::is_pod::value); ASSERT_TRUE(std::is_pod::value); ASSERT_TRUE(std::is_pod::value); - ASSERT_TRUE(std::is_pod::value); } diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index 63e4bd6af..60f60adb3 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -8,6 +8,12 @@ #include #include "apps/openmw/mwworld/esmstore.hpp" +#include "apps/openmw/mwmechanics/spelllist.hpp" + +namespace MWMechanics +{ + SpellList::SpellList(const std::string& id, int type) : mId(id), mType(type) {} +} static Loading::Listener dummyListener; diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index 30903b897..72dcd3066 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -244,6 +244,7 @@ namespace void init(Nif::Named& value) { value.extra = Nif::ExtraPtr(nullptr); + value.extralist = Nif::ExtraList(); value.controller = Nif::ControllerPtr(nullptr); } diff --git a/apps/openmw_test_suite/shader/shadermanager.cpp b/apps/openmw_test_suite/shader/shadermanager.cpp index e823d5fe2..a25e5e9ba 100644 --- a/apps/openmw_test_suite/shader/shadermanager.cpp +++ b/apps/openmw_test_suite/shader/shadermanager.cpp @@ -92,7 +92,7 @@ namespace "\n" "void bar() { foo() }\n" "\n" - "#line 2 0\n" + "#line 1 0\n" "\n" "void main() { bar() }\n"; EXPECT_EQ(shader->getShaderSource(), expected); diff --git a/apps/wizard/componentselectionpage.hpp b/apps/wizard/componentselectionpage.hpp index ca4347108..2509b9f5e 100644 --- a/apps/wizard/componentselectionpage.hpp +++ b/apps/wizard/componentselectionpage.hpp @@ -15,8 +15,8 @@ namespace Wizard public: ComponentSelectionPage(QWidget *parent); - int nextId() const; - virtual bool validatePage(); + int nextId() const override; + bool validatePage() override; private slots: void updateButton(QListWidgetItem *item); @@ -25,7 +25,7 @@ namespace Wizard MainWizard *mWizard; protected: - void initializePage(); + void initializePage() override; }; diff --git a/apps/wizard/conclusionpage.hpp b/apps/wizard/conclusionpage.hpp index 0e9abed72..f5f27dfca 100644 --- a/apps/wizard/conclusionpage.hpp +++ b/apps/wizard/conclusionpage.hpp @@ -15,13 +15,13 @@ namespace Wizard public: ConclusionPage(QWidget *parent); - int nextId() const; + int nextId() const override; private: MainWizard *mWizard; protected: - void initializePage(); + void initializePage() override; }; diff --git a/apps/wizard/existinginstallationpage.hpp b/apps/wizard/existinginstallationpage.hpp index 601295464..bb229e249 100644 --- a/apps/wizard/existinginstallationpage.hpp +++ b/apps/wizard/existinginstallationpage.hpp @@ -15,9 +15,9 @@ namespace Wizard public: ExistingInstallationPage(QWidget *parent); - int nextId() const; - virtual bool isComplete() const; - virtual bool validatePage(); + int nextId() const override; + bool isComplete() const override; + bool validatePage() override; private slots: void on_browseButton_clicked(); @@ -28,7 +28,7 @@ namespace Wizard MainWizard *mWizard; protected: - void initializePage(); + void initializePage() override; }; diff --git a/apps/wizard/importpage.hpp b/apps/wizard/importpage.hpp index 386cd59af..412d39ac1 100644 --- a/apps/wizard/importpage.hpp +++ b/apps/wizard/importpage.hpp @@ -15,7 +15,7 @@ namespace Wizard public: ImportPage(QWidget *parent); - int nextId() const; + int nextId() const override; private: MainWizard *mWizard; diff --git a/apps/wizard/installationpage.hpp b/apps/wizard/installationpage.hpp index 822cd21cd..cc1ccf559 100644 --- a/apps/wizard/installationpage.hpp +++ b/apps/wizard/installationpage.hpp @@ -22,8 +22,8 @@ namespace Wizard InstallationPage(QWidget *parent); ~InstallationPage(); - int nextId() const; - virtual bool isComplete() const; + int nextId() const override; + bool isComplete() const override; private: MainWizard *mWizard; @@ -41,7 +41,7 @@ namespace Wizard void installationError(const QString &text, const QString &details); protected: - void initializePage(); + void initializePage() override; }; diff --git a/apps/wizard/installationtargetpage.hpp b/apps/wizard/installationtargetpage.hpp index ca3b505b7..7cba29573 100644 --- a/apps/wizard/installationtargetpage.hpp +++ b/apps/wizard/installationtargetpage.hpp @@ -20,8 +20,8 @@ namespace Wizard public: InstallationTargetPage(QWidget *parent, const Files::ConfigurationManager &cfg); - int nextId() const; - virtual bool validatePage(); + int nextId() const override; + bool validatePage() override; private slots: void on_browseButton_clicked(); @@ -31,7 +31,7 @@ namespace Wizard const Files::ConfigurationManager &mCfgMgr; protected: - void initializePage(); + void initializePage() override; }; diff --git a/apps/wizard/intropage.hpp b/apps/wizard/intropage.hpp index 4ad9b4111..c8cd69016 100644 --- a/apps/wizard/intropage.hpp +++ b/apps/wizard/intropage.hpp @@ -15,7 +15,7 @@ namespace Wizard public: IntroPage(QWidget *parent); - int nextId() const; + int nextId() const override; private: MainWizard *mWizard; diff --git a/apps/wizard/languageselectionpage.hpp b/apps/wizard/languageselectionpage.hpp index abc3edb98..cc86ba9b3 100644 --- a/apps/wizard/languageselectionpage.hpp +++ b/apps/wizard/languageselectionpage.hpp @@ -15,13 +15,13 @@ namespace Wizard public: LanguageSelectionPage(QWidget *parent); - int nextId() const; + int nextId() const override; private: MainWizard *mWizard; protected: - void initializePage(); + void initializePage() override; }; } diff --git a/apps/wizard/mainwizard.hpp b/apps/wizard/mainwizard.hpp index a05013d98..8d9623baa 100644 --- a/apps/wizard/mainwizard.hpp +++ b/apps/wizard/mainwizard.hpp @@ -81,8 +81,8 @@ namespace Wizard void importerStarted(); void importerFinished(int exitCode, QProcess::ExitStatus exitStatus); - void accept(); - void reject(); + void accept() override; + void reject() override; }; diff --git a/apps/wizard/methodselectionpage.hpp b/apps/wizard/methodselectionpage.hpp index 60941c651..c189ea171 100644 --- a/apps/wizard/methodselectionpage.hpp +++ b/apps/wizard/methodselectionpage.hpp @@ -15,7 +15,7 @@ namespace Wizard public: MethodSelectionPage(QWidget *parent); - int nextId() const; + int nextId() const override; private: MainWizard *mWizard; diff --git a/cmake/FindLZ4.cmake b/cmake/FindLZ4.cmake new file mode 100644 index 000000000..ec854c6b1 --- /dev/null +++ b/cmake/FindLZ4.cmake @@ -0,0 +1,130 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindLZ4 +------- + +Find the LZ4 include directory and library. + +Use this module by invoking find_package with the form:: + +.. code-block:: cmake + + find_package(LZ4 + [version] # Minimum version e.g. 1.8.0 + [REQUIRED] # Fail with error if LZ4 is not found + ) + +Imported targets +^^^^^^^^^^^^^^^^ + +This module defines the following :prop_tgt:`IMPORTED` targets: + +.. variable:: LZ4::LZ4 + + Imported target for using the LZ4 library, if found. + +Result variables +^^^^^^^^^^^^^^^^ + +.. variable:: LZ4_FOUND + + Set to true if LZ4 library found, otherwise false or undefined. + +.. variable:: LZ4_INCLUDE_DIRS + + Paths to include directories listed in one variable for use by LZ4 client. + +.. variable:: LZ4_LIBRARIES + + Paths to libraries to linked against to use LZ4. + +.. variable:: LZ4_VERSION + + The version string of LZ4 found. + +Cache variables +^^^^^^^^^^^^^^^ + +For users who wish to edit and control the module behavior, this module +reads hints about search locations from the following variables:: + +.. variable:: LZ4_INCLUDE_DIR + + Path to LZ4 include directory with ``lz4.h`` header. + +.. variable:: LZ4_LIBRARY + + Path to LZ4 library to be linked. + +NOTE: The variables above should not usually be used in CMakeLists.txt files! + +#]=======================================================================] + +### Find library ############################################################## + +if(NOT LZ4_LIBRARY) + find_library(LZ4_LIBRARY_RELEASE NAMES lz4) + find_library(LZ4_LIBRARY_DEBUG NAMES lz4d) + + include(SelectLibraryConfigurations) + select_library_configurations(LZ4) +else() + file(TO_CMAKE_PATH "${LZ4_LIBRARY}" LZ4_LIBRARY) +endif() + +### Find include directory #################################################### +find_path(LZ4_INCLUDE_DIR NAMES lz4.h) + +if(LZ4_INCLUDE_DIR AND EXISTS "${LZ4_INCLUDE_DIR}/lz4.h") + file(STRINGS "${LZ4_INCLUDE_DIR}/lz4.h" _lz4_h_contents + REGEX "#define LZ4_VERSION_[A-Z]+[ ]+[0-9]+") + string(REGEX REPLACE "#define LZ4_VERSION_MAJOR[ ]+([0-9]+).+" "\\1" + LZ4_VERSION_MAJOR "${_lz4_h_contents}") + string(REGEX REPLACE ".+#define LZ4_VERSION_MINOR[ ]+([0-9]+).+" "\\1" + LZ4_VERSION_MINOR "${_lz4_h_contents}") + string(REGEX REPLACE ".+#define LZ4_VERSION_RELEASE[ ]+([0-9]+).*" "\\1" + LZ4_VERSION_RELEASE "${_lz4_h_contents}") + set(LZ4_VERSION "${LZ4_VERSION_MAJOR}.${LZ4_VERSION_MINOR}.${LZ4_VERSION_RELEASE}") + unset(_lz4_h_contents) +endif() + +### Set result variables ###################################################### +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LZ4 DEFAULT_MSG + LZ4_LIBRARY LZ4_INCLUDE_DIR LZ4_VERSION) + +mark_as_advanced(LZ4_INCLUDE_DIR LZ4_LIBRARY) + +set(LZ4_LIBRARIES ${LZ4_LIBRARY}) +set(LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR}) + +### Import targets ############################################################ +if(LZ4_FOUND) + if(NOT TARGET LZ4::LZ4) + add_library(LZ4::LZ4 UNKNOWN IMPORTED) + set_target_properties(LZ4::LZ4 PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + INTERFACE_INCLUDE_DIRECTORIES "${LZ4_INCLUDE_DIR}") + + if(LZ4_LIBRARY_RELEASE) + set_property(TARGET LZ4::LZ4 APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(LZ4::LZ4 PROPERTIES + IMPORTED_LOCATION_RELEASE "${LZ4_LIBRARY_RELEASE}") + endif() + + if(LZ4_LIBRARY_DEBUG) + set_property(TARGET LZ4::LZ4 APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(LZ4::LZ4 PROPERTIES + IMPORTED_LOCATION_DEBUG "${LZ4_LIBRARY_DEBUG}") + endif() + + if(NOT LZ4_LIBRARY_RELEASE AND NOT LZ4_LIBRARY_DEBUG) + set_property(TARGET LZ4::LZ4 APPEND PROPERTY + IMPORTED_LOCATION "${LZ4_LIBRARY}") + endif() + endif() +endif() diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 86d657792..69d8145f0 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -59,7 +59,7 @@ add_component_dir (nif ) add_component_dir (nifosg - nifloader controller particle userdata + nifloader controller particle matrixtransform ) add_component_dir (nifbullet @@ -86,11 +86,11 @@ add_component_dir (esmterrain ) add_component_dir (misc - gcd constants utf8stream stringops resourcehelpers rng messageformatparser weakcache + constants utf8stream stringops resourcehelpers rng messageformatparser weakcache ) add_component_dir (debug - debugging debuglog + debugging debuglog gldebug ) IF(NOT WIN32 AND NOT APPLE) @@ -233,7 +233,7 @@ target_link_libraries(components ${SDL2_LIBRARIES} ${OPENGL_gl_LIBRARY} ${MyGUI_LIBRARIES} - ${BSAOPTHASH_LIBRARIES} + LZ4::LZ4 RecastNavigation::DebugUtils RecastNavigation::Detour RecastNavigation::Recast diff --git a/components/bsa/compressedbsafile.cpp b/components/bsa/compressedbsafile.cpp index d0bebe3c1..adc98c454 100644 --- a/components/bsa/compressedbsafile.cpp +++ b/components/bsa/compressedbsafile.cpp @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -132,8 +134,11 @@ void CompressedBSAFile::readHeader() input.read(reinterpret_cast(header), 36); - if(header[0] != 0x00415342 /*"BSA\x00"*/ || (header[1] != 0x67 /*TES4*/ && header[1] != 0x68 /*TES5*/)) - fail("Unrecognized TES4 BSA header"); + if (header[0] != 0x00415342) /*"BSA\x00"*/ + fail("Unrecognized compressed BSA format"); + mVersion = header[1]; + if (mVersion != 0x67 /*TES4*/ && mVersion != 0x68 /*FO3, FNV, TES5*/ && mVersion != 0x69 /*SSE*/) + fail("Unrecognized compressed BSA version"); // header[2] is offset, should be 36 = 0x24 which is the size of the header @@ -158,7 +163,8 @@ void CompressedBSAFile::readHeader() // header[8]; // fileFlags : an opportunity to optimize here mCompressedByDefault = (archiveFlags & 0x4) != 0; - mEmbeddedFileNames = header[1] == 0x68 /*TES5*/ && (archiveFlags & 0x100) != 0; + if (mVersion == 0x68 || mVersion == 0x69) /*FO3, FNV, TES5, SSE*/ + mEmbeddedFileNames = (archiveFlags & 0x100) != 0; } // folder records @@ -168,7 +174,14 @@ void CompressedBSAFile::readHeader() { input.read(reinterpret_cast(&hash), 8); input.read(reinterpret_cast(&fr.count), 4); // not sure purpose of count - input.read(reinterpret_cast(&fr.offset), 4); // not sure purpose of offset + if (mVersion == 0x69) // SSE + { + std::uint32_t unknown; + input.read(reinterpret_cast(&unknown), 4); + input.read(reinterpret_cast(&fr.offset), 8); + } + else + input.read(reinterpret_cast(&fr.offset), 4); // not sure purpose of offset std::map::const_iterator lb = mFolders.lower_bound(hash); if (lb != mFolders.end() && !(mFolders.key_comp()(hash, lb->first))) @@ -327,32 +340,56 @@ Files::IStreamPtr CompressedBSAFile::getFile(const char* file) Files::IStreamPtr CompressedBSAFile::getFile(const FileRecord& fileRecord) { - if (fileRecord.isCompressed(mCompressedByDefault)) { - Files::IStreamPtr streamPtr = Files::openConstrainedFileStream(mFilename.c_str(), fileRecord.offset, fileRecord.getSizeWithoutCompressionFlag()); + size_t size = fileRecord.getSizeWithoutCompressionFlag(); + size_t uncompressedSize = size; + bool compressed = fileRecord.isCompressed(mCompressedByDefault); + Files::IStreamPtr streamPtr = Files::openConstrainedFileStream(mFilename.c_str(), fileRecord.offset, size); + std::istream* fileStream = streamPtr.get(); + if (mEmbeddedFileNames) + { + // Skip over the embedded file name + char length = 0; + fileStream->read(&length, 1); + fileStream->ignore(length); + size -= length + sizeof(char); + } + if (compressed) + { + fileStream->read(reinterpret_cast(&uncompressedSize), sizeof(uint32_t)); + size -= sizeof(uint32_t); + } + std::shared_ptr memoryStreamPtr = std::make_shared(uncompressedSize); - std::istream* fileStream = streamPtr.get(); + if (compressed) + { + if (mVersion != 0x69) // Non-SSE: zlib + { + boost::iostreams::filtering_streambuf inputStreamBuf; + inputStreamBuf.push(boost::iostreams::zlib_decompressor()); + inputStreamBuf.push(*fileStream); - if (mEmbeddedFileNames) { - std::string embeddedFileName; - getBZString(embeddedFileName, *fileStream); + boost::iostreams::basic_array_sink sr(memoryStreamPtr->getRawData(), uncompressedSize); + boost::iostreams::copy(inputStreamBuf, sr); } - - uint32_t uncompressedSize = 0u; - fileStream->read(reinterpret_cast(&uncompressedSize), sizeof(uncompressedSize)); - - boost::iostreams::filtering_streambuf inputStreamBuf; - inputStreamBuf.push(boost::iostreams::zlib_decompressor()); - inputStreamBuf.push(*fileStream); - - std::shared_ptr memoryStreamPtr = std::make_shared(uncompressedSize); - - boost::iostreams::basic_array_sink sr(memoryStreamPtr->getRawData(), uncompressedSize); - boost::iostreams::copy(inputStreamBuf, sr); - - return std::shared_ptr(memoryStreamPtr, (std::istream*)memoryStreamPtr.get()); + else // SSE: lz4 + { + boost::scoped_array buffer(new char[size]); + fileStream->read(buffer.get(), size); + LZ4F_decompressionContext_t context = nullptr; + LZ4F_createDecompressionContext(&context, LZ4F_VERSION); + LZ4F_decompressOptions_t options = {}; + LZ4F_decompress(context, memoryStreamPtr->getRawData(), &uncompressedSize, buffer.get(), &size, &options); + LZ4F_errorCode_t errorCode = LZ4F_freeDecompressionContext(context); + if (LZ4F_isError(errorCode)) + fail("LZ4 decompression error (file " + mFilename + "): " + LZ4F_getErrorName(errorCode)); + } + } + else + { + fileStream->read(memoryStreamPtr->getRawData(), size); } - return Files::openConstrainedFileStream(mFilename.c_str(), fileRecord.offset, fileRecord.size); + return std::shared_ptr(memoryStreamPtr, (std::istream*)memoryStreamPtr.get()); } BsaVersion CompressedBSAFile::detectVersion(std::string filePath) diff --git a/components/bsa/compressedbsafile.hpp b/components/bsa/compressedbsafile.hpp index a22d6e149..f3ad584d8 100644 --- a/components/bsa/compressedbsafile.hpp +++ b/components/bsa/compressedbsafile.hpp @@ -64,10 +64,12 @@ namespace Bsa //if each file record begins with BZ string with file name bool mEmbeddedFileNames; + std::uint32_t mVersion{0u}; + struct FolderRecord { std::uint32_t count; - std::uint32_t offset; + std::uint64_t offset; std::map files; }; std::map mFolders; @@ -88,10 +90,10 @@ namespace Bsa static BsaVersion detectVersion(std::string filePath); /// Read header information from the input source - virtual void readHeader(); + void readHeader() override; - Files::IStreamPtr getFile(const char* filePath); - Files::IStreamPtr getFile(const FileStruct* fileStruct); + Files::IStreamPtr getFile(const char* filePath) override; + Files::IStreamPtr getFile(const FileStruct* fileStruct) override; }; } diff --git a/components/bullethelpers/processtrianglecallback.hpp b/components/bullethelpers/processtrianglecallback.hpp index ee005b459..b0d156754 100644 --- a/components/bullethelpers/processtrianglecallback.hpp +++ b/components/bullethelpers/processtrianglecallback.hpp @@ -15,7 +15,7 @@ namespace BulletHelpers : mImpl(std::move(impl)) {} - void processTriangle(btVector3* triangle, int partId, int triangleIndex) override final + void processTriangle(btVector3* triangle, int partId, int triangleIndex) final { return mImpl(triangle, partId, triangleIndex); } diff --git a/components/compiler/controlparser.hpp b/components/compiler/controlparser.hpp index 59958fd90..fad8025b4 100644 --- a/components/compiler/controlparser.hpp +++ b/components/compiler/controlparser.hpp @@ -54,20 +54,20 @@ namespace Compiler void appendCode (std::vector& code) const; ///< store generated code in \a code. - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - void reset(); + void reset() override; ///< Reset parser to clean state. }; } diff --git a/components/compiler/declarationparser.hpp b/components/compiler/declarationparser.hpp index 43dd83570..c04f1dc26 100644 --- a/components/compiler/declarationparser.hpp +++ b/components/compiler/declarationparser.hpp @@ -22,20 +22,20 @@ namespace Compiler DeclarationParser (ErrorHandler& errorHandler, const Context& context, Locals& locals); - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - void reset(); + void reset() override; }; } diff --git a/components/compiler/discardparser.hpp b/components/compiler/discardparser.hpp index 2a7ed5544..15e06756e 100644 --- a/components/compiler/discardparser.hpp +++ b/components/compiler/discardparser.hpp @@ -21,24 +21,24 @@ namespace Compiler DiscardParser (ErrorHandler& errorHandler, const Context& context); - virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner); + bool parseInt (int value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle an int token. /// \return fetch another token? - virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner); + bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a float token. /// \return fetch another token? - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - virtual void reset(); + void reset() override; ///< Reset parser to clean state. /// Returns TokenLoc object for value. If no value has been parsed, the TokenLoc diff --git a/components/compiler/exception.hpp b/components/compiler/exception.hpp index 33bad7590..f21f2e586 100644 --- a/components/compiler/exception.hpp +++ b/components/compiler/exception.hpp @@ -10,8 +10,8 @@ namespace Compiler class SourceException : public std::exception { public: - - virtual const char *what() const throw() { return "Compile error";} + + const char *what() const noexcept override { return "Compile error";} ///< Return error message }; @@ -20,18 +20,18 @@ namespace Compiler class FileException : public SourceException { public: - - virtual const char *what() const throw() { return "Can't read file"; } + + const char *what() const noexcept final { return "Can't read file"; } ///< Return error message }; /// \brief Exception: EOF condition encountered class EOFException : public SourceException - { + { public: - - virtual const char *what() const throw() { return "End of file"; } + + const char *what() const noexcept final { return "End of file"; } ///< Return error message }; } diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index dd8259ee1..0e8ad88c6 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -67,28 +67,28 @@ namespace Compiler char getType() const; ///< Return type of parsed expression ('l' integer, 'f' float) - virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner); + bool parseInt (int value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle an int token. /// \return fetch another token? - virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner); + bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a float token. /// \return fetch another token? - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - void reset(); + void reset() override; ///< Reset parser to clean state. char append (std::vector& code); diff --git a/components/compiler/fileparser.hpp b/components/compiler/fileparser.hpp index 00f96cff0..b08ec9cdd 100644 --- a/components/compiler/fileparser.hpp +++ b/components/compiler/fileparser.hpp @@ -36,23 +36,23 @@ namespace Compiler const Locals& getLocals() const; ///< get local variable declarations. - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - virtual void parseEOF (Scanner& scanner); + void parseEOF (Scanner& scanner) override; ///< Handle EOF token. - void reset(); + void reset() override; ///< Reset parser to clean state. }; } diff --git a/components/compiler/junkparser.hpp b/components/compiler/junkparser.hpp index 6dfbd97af..0b42d4693 100644 --- a/components/compiler/junkparser.hpp +++ b/components/compiler/junkparser.hpp @@ -15,24 +15,24 @@ namespace Compiler JunkParser (ErrorHandler& errorHandler, const Context& context, int ignoreKeyword = -1); - virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner); + bool parseInt (int value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle an int token. /// \return fetch another token? - virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner); + bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a float token. /// \return fetch another token? - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? }; diff --git a/components/compiler/lineparser.hpp b/components/compiler/lineparser.hpp index cc32b9592..c434792d1 100644 --- a/components/compiler/lineparser.hpp +++ b/components/compiler/lineparser.hpp @@ -51,28 +51,28 @@ namespace Compiler ///< \param allowExpression Allow lines consisting of a naked expression /// (result is send to the messagebox interface) - virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner); + bool parseInt (int value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle an int token. /// \return fetch another token? - virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner); + bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a float token. /// \return fetch another token? - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - void reset(); + void reset() override; ///< Reset parser to clean state. }; @@ -82,11 +82,11 @@ namespace Compiler std::string mArguments; protected: - virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision, Notation notation); - virtual void visitedCharacter(char c) {} + void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision, Notation notation) override; + void visitedCharacter(char c) override {} public: - virtual void process(const std::string& message) + void process(const std::string& message) override { mArguments.clear(); ::Misc::MessageFormatParser::process(message); diff --git a/components/compiler/nullerrorhandler.hpp b/components/compiler/nullerrorhandler.hpp index 3dcff9250..d689fba63 100644 --- a/components/compiler/nullerrorhandler.hpp +++ b/components/compiler/nullerrorhandler.hpp @@ -9,10 +9,10 @@ namespace Compiler class NullErrorHandler : public ErrorHandler { - virtual void report (const std::string& message, const TokenLoc& loc, Type type); + void report (const std::string& message, const TokenLoc& loc, Type type) override; ///< Report error to the user. - virtual void report (const std::string& message, Type type); + void report (const std::string& message, Type type) override; ///< Report a file related error }; } diff --git a/components/compiler/quickfileparser.hpp b/components/compiler/quickfileparser.hpp index 440d91038..95e6b401c 100644 --- a/components/compiler/quickfileparser.hpp +++ b/components/compiler/quickfileparser.hpp @@ -17,20 +17,20 @@ namespace Compiler QuickFileParser (ErrorHandler& errorHandler, const Context& context, Locals& locals); - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - virtual void parseEOF (Scanner& scanner); + void parseEOF (Scanner& scanner) override; ///< Handle EOF token. }; } diff --git a/components/compiler/scriptparser.hpp b/components/compiler/scriptparser.hpp index edabb9c5c..d6dfe768c 100644 --- a/components/compiler/scriptparser.hpp +++ b/components/compiler/scriptparser.hpp @@ -29,23 +29,23 @@ namespace Compiler void getCode (std::vector& code) const; ///< store generated code in \a code. - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? - virtual void parseEOF (Scanner& scanner); + void parseEOF (Scanner& scanner) override; ///< Handle EOF token. - void reset(); + void reset() override; ///< Reset parser to clean state. }; } diff --git a/components/compiler/skipparser.hpp b/components/compiler/skipparser.hpp index 239c8bb02..4be90f3a1 100644 --- a/components/compiler/skipparser.hpp +++ b/components/compiler/skipparser.hpp @@ -15,24 +15,24 @@ namespace Compiler SkipParser (ErrorHandler& errorHandler, const Context& context); - virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner); + bool parseInt (int value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle an int token. /// \return fetch another token? - virtual bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner); + bool parseFloat (float value, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a float token. /// \return fetch another token? - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? }; diff --git a/components/compiler/streamerrorhandler.hpp b/components/compiler/streamerrorhandler.hpp index 1f3b6e1ec..ad3416695 100644 --- a/components/compiler/streamerrorhandler.hpp +++ b/components/compiler/streamerrorhandler.hpp @@ -20,10 +20,10 @@ namespace Compiler StreamErrorHandler (const StreamErrorHandler&); StreamErrorHandler& operator= (const StreamErrorHandler&); - virtual void report (const std::string& message, const TokenLoc& loc, Type type); + void report (const std::string& message, const TokenLoc& loc, Type type) override; ///< Report error to the user. - virtual void report (const std::string& message, Type type); + void report (const std::string& message, Type type) override; ///< Report a file related error public: diff --git a/components/compiler/stringparser.hpp b/components/compiler/stringparser.hpp index 72dab0580..197662836 100644 --- a/components/compiler/stringparser.hpp +++ b/components/compiler/stringparser.hpp @@ -30,16 +30,16 @@ namespace Compiler StringParser (ErrorHandler& errorHandler, const Context& context, Literals& literals); - virtual bool parseName (const std::string& name, const TokenLoc& loc, - Scanner& scanner); + bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) override; ///< Handle a name token. /// \return fetch another token? - virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner); + bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a keyword token. /// \return fetch another token? - virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) override; ///< Handle a special character token. /// \return fetch another token? @@ -49,7 +49,7 @@ namespace Compiler void smashCase(); ///< Transform all scanned strings to lower case - void reset(); + void reset() override; ///< Reset parser to clean state (this includes the smashCase function). /// Returns TokenLoc object for string. If no string has been parsed, the TokenLoc diff --git a/components/contentselector/model/contentmodel.hpp b/components/contentselector/model/contentmodel.hpp index 80cd6e4c3..030865b35 100644 --- a/components/contentselector/model/contentmodel.hpp +++ b/components/contentselector/model/contentmodel.hpp @@ -28,20 +28,20 @@ namespace ContentSelectorModel void setEncoding(const QString &encoding); - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + QVariant data(const QModelIndex &index, int role) const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()); - bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()); + bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override; + bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override; - Qt::DropActions supportedDropActions() const; - QStringList mimeTypes() const; - QMimeData *mimeData(const QModelIndexList &indexes) const; - bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + Qt::DropActions supportedDropActions() const override; + QStringList mimeTypes() const override; + QMimeData *mimeData(const QModelIndexList &indexes) const override; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; void addFiles(const QString &path); void clearFiles(); diff --git a/components/contentselector/model/modelitem.hpp b/components/contentselector/model/modelitem.hpp index 57214b09c..e4ea7acc6 100644 --- a/components/contentselector/model/modelitem.hpp +++ b/components/contentselector/model/modelitem.hpp @@ -26,7 +26,7 @@ namespace ContentSelectorModel void appendChild(ModelItem *child); void removeChild(int row); - bool hasFormat(const QString &mimetype) const; + bool hasFormat(const QString &mimetype) const override; //virtual bool acceptChild(ModelItem *child); 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); diff --git a/components/contentselector/view/combobox.hpp b/components/contentselector/view/combobox.hpp index e3888af2c..c57a5f116 100644 --- a/components/contentselector/view/combobox.hpp +++ b/components/contentselector/view/combobox.hpp @@ -22,7 +22,7 @@ namespace ContentSelectorView QString mPlaceholderText; protected: - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; QRegExpValidator *mValidator; }; } diff --git a/components/debug/debugging.hpp b/components/debug/debugging.hpp index 1cae4b006..39390446f 100644 --- a/components/debug/debugging.hpp +++ b/components/debug/debugging.hpp @@ -89,7 +89,7 @@ namespace Debug mColors[NoLevel] = Reset; } - virtual std::streamsize writeImpl(const char *str, std::streamsize size, Level debugLevel) + std::streamsize writeImpl(const char *str, std::streamsize size, Level debugLevel) override { out.write (str, size); out.flush(); diff --git a/components/debug/gldebug.cpp b/components/debug/gldebug.cpp new file mode 100644 index 000000000..3c5ec728a --- /dev/null +++ b/components/debug/gldebug.cpp @@ -0,0 +1,164 @@ +// This file is based heavily on code from https://github.com/ThermalPixel/osgdemos/blob/master/osgdebug/EnableGLDebugOperation.cpp +// The original licence is included below: +/* +Copyright (c) 2014, Andreas Klein +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +#include "gldebug.hpp" + +#include + +#include + +// OpenGL constants not provided by OSG: +#include + +void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) +{ +#ifdef GL_DEBUG_OUTPUT + std::string srcStr; + switch (source) + { + case GL_DEBUG_SOURCE_API: + srcStr = "API"; + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + srcStr = "WINDOW_SYSTEM"; + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + srcStr = "SHADER_COMPILER"; + break; + case GL_DEBUG_SOURCE_THIRD_PARTY: + srcStr = "THIRD_PARTY"; + break; + case GL_DEBUG_SOURCE_APPLICATION: + srcStr = "APPLICATION"; + break; + case GL_DEBUG_SOURCE_OTHER: + srcStr = "OTHER"; + break; + default: + srcStr = "UNDEFINED"; + break; + } + + std::string typeStr; + + Debug::Level logSeverity = Debug::Warning; + switch (type) + { + case GL_DEBUG_TYPE_ERROR: + typeStr = "ERROR"; + logSeverity = Debug::Error; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + typeStr = "DEPRECATED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + typeStr = "UNDEFINED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_PORTABILITY: + typeStr = "PORTABILITY"; + break; + case GL_DEBUG_TYPE_PERFORMANCE: + typeStr = "PERFORMANCE"; + break; + case GL_DEBUG_TYPE_OTHER: + typeStr = "OTHER"; + break; + default: + typeStr = "UNDEFINED"; + break; + } + + Log(logSeverity) << "OpenGL " << typeStr << " [" << srcStr << "]: " << message; +#endif +} + +void enableGLDebugExtension(unsigned int contextID) +{ +#ifdef GL_DEBUG_OUTPUT + typedef void (GL_APIENTRY *DEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam); + typedef void (GL_APIENTRY *GLDebugMessageControlFunction)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); + typedef void (GL_APIENTRY *GLDebugMessageCallbackFunction)(DEBUGPROC, const void* userParam); + + GLDebugMessageControlFunction glDebugMessageControl = nullptr; + GLDebugMessageCallbackFunction glDebugMessageCallback = nullptr; + + if (osg::isGLExtensionSupported(contextID, "GL_KHR_debug")) + { + osg::setGLExtensionFuncPtr(glDebugMessageCallback, "glDebugMessageCallback"); + osg::setGLExtensionFuncPtr(glDebugMessageControl, "glDebugMessageControl"); + } + else if (osg::isGLExtensionSupported(contextID, "GL_ARB_debug_output")) + { + osg::setGLExtensionFuncPtr(glDebugMessageCallback, "glDebugMessageCallbackARB"); + osg::setGLExtensionFuncPtr(glDebugMessageControl, "glDebugMessageControlARB"); + } + else if (osg::isGLExtensionSupported(contextID, "GL_AMD_debug_output")) + { + osg::setGLExtensionFuncPtr(glDebugMessageCallback, "glDebugMessageCallbackAMD"); + osg::setGLExtensionFuncPtr(glDebugMessageControl, "glDebugMessageControlAMD"); + } + + if (glDebugMessageCallback && glDebugMessageControl) + { + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, true); + glDebugMessageCallback(debugCallback, nullptr); + + Log(Debug::Info) << "OpenGL debug callback attached."; + } + else +#endif + Log(Debug::Error) << "Unable to attach OpenGL debug callback."; +} + +Debug::EnableGLDebugOperation::EnableGLDebugOperation() : osg::GraphicsOperation("EnableGLDebugOperation", false) +{ +} + +void Debug::EnableGLDebugOperation::operator()(osg::GraphicsContext* graphicsContext) +{ + OpenThreads::ScopedLock lock(mMutex); + + unsigned int contextID = graphicsContext->getState()->getContextID(); + enableGLDebugExtension(contextID); +} + +bool Debug::shouldDebugOpenGL() +{ + const char* env = std::getenv("OPENMW_DEBUG_OPENGL"); + if (!env) + return false; + std::string str(env); + if (str.length() == 0) + return true; + + return str.find("OFF") == std::string::npos && str.find("0") == std::string::npos && str.find("NO") == std::string::npos; +} diff --git a/components/debug/gldebug.hpp b/components/debug/gldebug.hpp new file mode 100644 index 000000000..8be747afe --- /dev/null +++ b/components/debug/gldebug.hpp @@ -0,0 +1,21 @@ +#ifndef OPENMW_COMPONENTS_DEBUG_GLDEBUG_H +#define OPENMW_COMPONENTS_DEBUG_GLDEBUG_H + +#include + +namespace Debug +{ + class EnableGLDebugOperation : public osg::GraphicsOperation + { + public: + EnableGLDebugOperation(); + + void operator()(osg::GraphicsContext* graphicsContext) override; + + private: + OpenThreads::Mutex mMutex; + }; + + bool shouldDebugOpenGL(); +} +#endif diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 0683a43bc..878b8130a 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -38,8 +38,14 @@ namespace DetourNavigator return stream << "failed"; case UpdateNavMeshStatus::lost: return stream << "lost"; + case UpdateNavMeshStatus::cached: + return stream << "cached"; + case UpdateNavMeshStatus::unchanged: + return stream << "unchanged"; + case UpdateNavMeshStatus::restored: + return stream << "restored"; } - return stream << "unknown"; + return stream << "unknown(" << static_cast(value) << ")"; } AsyncNavMeshUpdater::AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager, @@ -126,7 +132,7 @@ namespace DetourNavigator mNavMeshTilesCache.reportStats(frameNumber, stats); } - void AsyncNavMeshUpdater::process() throw() + void AsyncNavMeshUpdater::process() noexcept { Log(Debug::Debug) << "Start process navigator jobs by thread=" << std::this_thread::get_id(); while (!mShouldStop) diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index 4debcd6cd..26f886512 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -113,7 +113,7 @@ namespace DetourNavigator std::map mThreadsQueues; std::vector mThreads; - void process() throw(); + void process() noexcept; bool processJob(const Job& job); diff --git a/components/detournavigator/findrandompointaroundcircle.cpp b/components/detournavigator/findrandompointaroundcircle.cpp index 3888c59fe..263dba68e 100644 --- a/components/detournavigator/findrandompointaroundcircle.cpp +++ b/components/detournavigator/findrandompointaroundcircle.cpp @@ -36,7 +36,7 @@ namespace DetourNavigator dtPolyRef resultRef = 0; osg::Vec3f resultPosition; navMeshQuery.findRandomPointAroundCircle(startRef, start.ptr(), maxRadius, &queryFilter, - &Misc::Rng::rollProbability, &resultRef, resultPosition.ptr()); + []() { return Misc::Rng::rollProbability(); }, &resultRef, resultPosition.ptr()); if (resultRef == 0) return boost::optional(); diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index beee95113..7c7dcf186 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -559,6 +559,7 @@ namespace DetourNavigator } auto cachedNavMeshData = navMeshTilesCache.get(agentHalfExtents, changedTile, *recastMesh, offMeshConnections); + bool cached = static_cast(cachedNavMeshData); if (!cachedNavMeshData) { @@ -584,6 +585,7 @@ namespace DetourNavigator { cachedNavMeshData = navMeshTilesCache.get(agentHalfExtents, changedTile, *recastMesh, offMeshConnections); + cached = static_cast(cachedNavMeshData); } if (!cachedNavMeshData) @@ -593,6 +595,8 @@ namespace DetourNavigator } } - return navMeshCacheItem->lock()->updateTile(changedTile, std::move(cachedNavMeshData)); + const auto updateStatus = navMeshCacheItem->lock()->updateTile(changedTile, std::move(cachedNavMeshData)); + + return UpdateNavMeshStatusBuilder(updateStatus).cached(cached).getResult(); } } diff --git a/components/detournavigator/navmeshcacheitem.hpp b/components/detournavigator/navmeshcacheitem.hpp index f13341397..76f74f266 100644 --- a/components/detournavigator/navmeshcacheitem.hpp +++ b/components/detournavigator/navmeshcacheitem.hpp @@ -22,6 +22,9 @@ namespace DetourNavigator replaced = removed | added, failed = 1 << 2, lost = removed | failed, + cached = 1 << 3, + unchanged = replaced | cached, + restored = added | cached, }; inline bool isSuccess(UpdateNavMeshStatus value) @@ -34,6 +37,9 @@ namespace DetourNavigator public: UpdateNavMeshStatusBuilder() = default; + explicit UpdateNavMeshStatusBuilder(UpdateNavMeshStatus value) + : mResult(value) {} + UpdateNavMeshStatusBuilder removed(bool value) { if (value) @@ -61,6 +67,15 @@ namespace DetourNavigator return *this; } + UpdateNavMeshStatusBuilder cached(bool value) + { + if (value) + set(UpdateNavMeshStatus::cached); + else + unset(UpdateNavMeshStatus::cached); + return *this; + } + UpdateNavMeshStatus getResult() const { return mResult; @@ -143,7 +158,7 @@ namespace DetourNavigator UpdateNavMeshStatus removeTile(const TilePosition& position) { - const auto removed = dtStatusSucceed(removeTileImpl(position)); + const auto removed = removeTileImpl(position); if (removed) removeUsedTile(position); return UpdateNavMeshStatusBuilder().removed(removed).getResult(); @@ -181,13 +196,15 @@ namespace DetourNavigator return mImpl->addTile(data, size, doNotTransferOwnership, lastRef, result); } - dtStatus removeTileImpl(const TilePosition& position) + bool removeTileImpl(const TilePosition& position) { const int layer = 0; const auto tileRef = mImpl->getTileRefAt(position.x(), position.y(), layer); + if (tileRef == 0) + return false; unsigned char** const data = nullptr; int* const dataSize = nullptr; - return mImpl->removeTile(tileRef, data, dataSize); + return dtStatusSucceed(mImpl->removeTile(tileRef, data, dataSize)); } }; diff --git a/components/detournavigator/navmeshtilescache.cpp b/components/detournavigator/navmeshtilescache.cpp index 466d2e708..f554cd414 100644 --- a/components/detournavigator/navmeshtilescache.cpp +++ b/components/detournavigator/navmeshtilescache.cpp @@ -9,42 +9,32 @@ namespace DetourNavigator { namespace { - inline std::string makeNavMeshKey(const RecastMesh& recastMesh, + inline std::vector makeNavMeshKey(const RecastMesh& recastMesh, const std::vector& offMeshConnections) { - std::string result; - result.reserve( - recastMesh.getIndices().size() * sizeof(int) - + recastMesh.getVertices().size() * sizeof(float) - + recastMesh.getAreaTypes().size() * sizeof(AreaType) - + recastMesh.getWater().size() * sizeof(RecastMesh::Water) - + offMeshConnections.size() * sizeof(OffMeshConnection) - ); - std::copy( - reinterpret_cast(recastMesh.getIndices().data()), - reinterpret_cast(recastMesh.getIndices().data() + recastMesh.getIndices().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(recastMesh.getVertices().data()), - reinterpret_cast(recastMesh.getVertices().data() + recastMesh.getVertices().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(recastMesh.getAreaTypes().data()), - reinterpret_cast(recastMesh.getAreaTypes().data() + recastMesh.getAreaTypes().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(recastMesh.getWater().data()), - reinterpret_cast(recastMesh.getWater().data() + recastMesh.getWater().size()), - std::back_inserter(result) - ); - std::copy( - reinterpret_cast(offMeshConnections.data()), - reinterpret_cast(offMeshConnections.data() + offMeshConnections.size()), - std::back_inserter(result) - ); + const std::size_t indicesSize = recastMesh.getIndices().size() * sizeof(int); + const std::size_t verticesSize = recastMesh.getVertices().size() * sizeof(float); + const std::size_t areaTypesSize = recastMesh.getAreaTypes().size() * sizeof(AreaType); + const std::size_t waterSize = recastMesh.getWater().size() * sizeof(RecastMesh::Water); + const std::size_t offMeshConnectionsSize = offMeshConnections.size() * sizeof(OffMeshConnection); + + std::vector result(indicesSize + verticesSize + areaTypesSize + waterSize + offMeshConnectionsSize); + unsigned char* dst = result.data(); + + std::memcpy(dst, recastMesh.getIndices().data(), indicesSize); + dst += indicesSize; + + std::memcpy(dst, recastMesh.getVertices().data(), verticesSize); + dst += verticesSize; + + std::memcpy(dst, recastMesh.getAreaTypes().data(), areaTypesSize); + dst += areaTypesSize; + + std::memcpy(dst, recastMesh.getWater().data(), waterSize); + dst += waterSize; + + std::memcpy(dst, offMeshConnections.data(), offMeshConnectionsSize); + return result; } } @@ -189,8 +179,8 @@ namespace DetourNavigator { struct CompareBytes { - const char* mRhsIt; - const char* mRhsEnd; + const unsigned char* mRhsIt; + const unsigned char* const mRhsEnd; template int operator ()(const std::vector& lhs) @@ -225,7 +215,7 @@ namespace DetourNavigator }; } - int NavMeshTilesCache::RecastMeshKeyView::compare(const std::string& other) const + int NavMeshTilesCache::RecastMeshKeyView::compare(const std::vector& other) const { CompareBytes compareBytes {other.data(), other.data() + other.size()}; diff --git a/components/detournavigator/navmeshtilescache.hpp b/components/detournavigator/navmeshtilescache.hpp index 57f57a56f..064d9e185 100644 --- a/components/detournavigator/navmeshtilescache.hpp +++ b/components/detournavigator/navmeshtilescache.hpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include namespace osg { @@ -33,10 +35,10 @@ namespace DetourNavigator std::atomic mUseCount; osg::Vec3f mAgentHalfExtents; TilePosition mChangedTile; - std::string mNavMeshKey; + std::vector mNavMeshKey; NavMeshData mNavMeshData; - Item(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile, std::string navMeshKey) + Item(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile, std::vector&& navMeshKey) : mUseCount(0) , mAgentHalfExtents(agentHalfExtents) , mChangedTile(changedTile) @@ -120,19 +122,32 @@ namespace DetourNavigator virtual ~KeyView() = default; - KeyView(const std::string& value) + KeyView(const std::vector& value) : mValue(&value) {} - const std::string& getValue() const + const std::vector& getValue() const { assert(mValue); return *mValue; } - virtual int compare(const std::string& other) const + virtual int compare(const std::vector& other) const { assert(mValue); - return mValue->compare(other); + + const auto valueSize = mValue->size(); + const auto otherSize = other.size(); + + if (const auto result = std::memcmp(mValue->data(), other.data(), std::min(valueSize, otherSize))) + return result; + + if (valueSize < otherSize) + return -1; + + if (valueSize > otherSize) + return 1; + + return 0; } virtual bool isLess(const KeyView& other) const @@ -147,7 +162,7 @@ namespace DetourNavigator } private: - const std::string* mValue = nullptr; + const std::vector* mValue = nullptr; }; class RecastMeshKeyView : public KeyView @@ -156,7 +171,7 @@ namespace DetourNavigator RecastMeshKeyView(const RecastMesh& recastMesh, const std::vector& offMeshConnections) : mRecastMesh(recastMesh), mOffMeshConnections(offMeshConnections) {} - int compare(const std::string& other) const override; + int compare(const std::vector& other) const override; bool isLess(const KeyView& other) const override { diff --git a/components/detournavigator/objectid.hpp b/components/detournavigator/objectid.hpp index 6ddcc9169..9c4b5b271 100644 --- a/components/detournavigator/objectid.hpp +++ b/components/detournavigator/objectid.hpp @@ -10,22 +10,22 @@ namespace DetourNavigator { public: template - explicit ObjectId(T* value) throw() + explicit ObjectId(T* value) noexcept : mValue(reinterpret_cast(value)) { } - std::size_t value() const throw() + std::size_t value() const noexcept { return mValue; } - friend bool operator <(const ObjectId lhs, const ObjectId rhs) throw() + friend bool operator <(const ObjectId lhs, const ObjectId rhs) noexcept { return lhs.mValue < rhs.mValue; } - friend bool operator ==(const ObjectId lhs, const ObjectId rhs) throw() + friend bool operator ==(const ObjectId lhs, const ObjectId rhs) noexcept { return lhs.mValue == rhs.mValue; } @@ -40,7 +40,7 @@ namespace std template <> struct hash { - std::size_t operator ()(const DetourNavigator::ObjectId value) const throw() + std::size_t operator ()(const DetourNavigator::ObjectId value) const noexcept { return value.value(); } diff --git a/components/esm/activespells.cpp b/components/esm/activespells.cpp index 46558ceb7..4017a4933 100644 --- a/components/esm/activespells.cpp +++ b/components/esm/activespells.cpp @@ -24,6 +24,7 @@ namespace ESM esm.writeHNT ("ARG_", effectIt->mArg); esm.writeHNT ("MAGN", effectIt->mMagnitude); esm.writeHNT ("DURA", effectIt->mDuration); + esm.writeHNT ("EIND", effectIt->mEffectIndex); esm.writeHNT ("LEFT", effectIt->mTimeLeft); } } @@ -53,6 +54,8 @@ namespace ESM esm.getHNOT(effect.mArg, "ARG_"); esm.getHNT (effect.mMagnitude, "MAGN"); esm.getHNT (effect.mDuration, "DURA"); + effect.mEffectIndex = -1; + esm.getHNOT (effect.mEffectIndex, "EIND"); if (format < 9) effect.mTimeLeft = effect.mDuration; else diff --git a/components/esm/activespells.hpp b/components/esm/activespells.hpp index 20b2f652d..1b7f8b319 100644 --- a/components/esm/activespells.hpp +++ b/components/esm/activespells.hpp @@ -22,6 +22,7 @@ namespace ESM int mArg; // skill or attribute float mDuration; float mTimeLeft; + int mEffectIndex; }; // format 0, saved games only diff --git a/components/esm/creaturestats.cpp b/components/esm/creaturestats.cpp index 6f0b36f8d..cb383992c 100644 --- a/components/esm/creaturestats.cpp +++ b/components/esm/creaturestats.cpp @@ -115,9 +115,11 @@ void ESM::CreatureStats::load (ESMReader &esm) int magicEffect; esm.getHT(magicEffect); std::string source = esm.getHNOString("SOUR"); + int effectIndex = -1; + esm.getHNOT (effectIndex, "EIND"); int actorId; esm.getHNT (actorId, "ACID"); - mSummonedCreatureMap[std::make_pair(magicEffect, source)] = actorId; + mSummonedCreatureMap[SummonKey(magicEffect, source, effectIndex)] = actorId; } while (esm.isNextSub("GRAV")) @@ -212,16 +214,19 @@ void ESM::CreatureStats::save (ESMWriter &esm) const mAiSequence.save(esm); mMagicEffects.save(esm); - for (std::map, int>::const_iterator it = mSummonedCreatureMap.begin(); it != mSummonedCreatureMap.end(); ++it) + for (const auto& summon : mSummonedCreatureMap) { - esm.writeHNT ("SUMM", it->first.first); - esm.writeHNString ("SOUR", it->first.second); - esm.writeHNT ("ACID", it->second); + esm.writeHNT ("SUMM", summon.first.mEffectId); + esm.writeHNString ("SOUR", summon.first.mSourceId); + int effectIndex = summon.first.mEffectIndex; + if (effectIndex != -1) + esm.writeHNT ("EIND", effectIndex); + esm.writeHNT ("ACID", summon.second); } - for (std::vector::const_iterator it = mSummonGraveyard.begin(); it != mSummonGraveyard.end(); ++it) + for (int key : mSummonGraveyard) { - esm.writeHNT ("GRAV", *it); + esm.writeHNT ("GRAV", key); } esm.writeHNT("AISE", mHasAiSettings); @@ -231,11 +236,11 @@ void ESM::CreatureStats::save (ESMWriter &esm) const mAiSettings[i].save(esm); } - for (std::map::const_iterator it = mCorprusSpells.begin(); it != mCorprusSpells.end(); ++it) + for (const auto& corprusSpell : mCorprusSpells) { - esm.writeHNString("CORP", it->first); + esm.writeHNString("CORP", corprusSpell.first); - const CorprusStats & stats = it->second; + const CorprusStats & stats = corprusSpell.second; esm.writeHNT("WORS", stats.mWorsenings); esm.writeHNT("TIME", stats.mNextWorsening); } diff --git a/components/esm/creaturestats.hpp b/components/esm/creaturestats.hpp index 79a576587..13bc50008 100644 --- a/components/esm/creaturestats.hpp +++ b/components/esm/creaturestats.hpp @@ -39,7 +39,7 @@ namespace ESM bool mHasAiSettings; StatState mAiSettings[4]; - std::map, int> mSummonedCreatureMap; + std::map mSummonedCreatureMap; std::vector mSummonGraveyard; ESM::TimeStamp mTradeTime; diff --git a/components/esm/esmcommon.hpp b/components/esm/esmcommon.hpp index f7a8bf126..232a24fcf 100644 --- a/components/esm/esmcommon.hpp +++ b/components/esm/esmcommon.hpp @@ -6,7 +6,6 @@ #include #include -#include namespace ESM { @@ -57,11 +56,16 @@ public: } bool operator!=(const std::string& str) const { return !( (*this) == str ); } - size_t data_size() const { return size; } + static size_t data_size() { return size; } size_t length() const { return strnlen(self()->ro_data(), size); } std::string toString() const { return std::string(self()->ro_data(), this->length()); } - void assign(const std::string& value) { std::strncpy(self()->rw_data(), value.c_str(), size); } + void assign(const std::string& value) + { + std::strncpy(self()->rw_data(), value.c_str(), size-1); + self()->rw_data()[size-1] = '\0'; + } + void clear() { this->assign(""); } private: DERIVED const* self() const @@ -103,6 +107,20 @@ struct FIXED_STRING<4> : public FIXED_STRING_BASE bool operator==(uint32_t v) const { return v == intval; } bool operator!=(uint32_t v) const { return v != intval; } + void assign(const std::string& value) + { + intval = 0; + size_t length = value.size(); + if (length == 0) return; + data[0] = value[0]; + if (length == 1) return; + data[1] = value[1]; + if (length == 2) return; + data[2] = value[2]; + if (length == 3) return; + data[3] = value[3]; + } + char const* ro_data() const { return data; } char* rw_data() { return data; } }; @@ -110,7 +128,6 @@ struct FIXED_STRING<4> : public FIXED_STRING_BASE typedef FIXED_STRING<4> NAME; typedef FIXED_STRING<32> NAME32; typedef FIXED_STRING<64> NAME64; -typedef FIXED_STRING<256> NAME256; /* This struct defines a file 'context' which can be saved and later restored by an ESMReader instance. It will save the position within diff --git a/components/esm/inventorystate.cpp b/components/esm/inventorystate.cpp index fe54762c5..2392d263f 100644 --- a/components/esm/inventorystate.cpp +++ b/components/esm/inventorystate.cpp @@ -3,6 +3,8 @@ #include "esmreader.hpp" #include "esmwriter.hpp" +#include + void ESM::InventoryState::load (ESMReader &esm) { // obsolete @@ -106,6 +108,19 @@ void ESM::InventoryState::load (ESMReader &esm) mSelectedEnchantItem = -1; esm.getHNOT(mSelectedEnchantItem, "SELE"); + + // Old saves had restocking levelled items in a special map + // This turns items from that map into negative quantities + for(const auto& entry : mLevelledItemMap) + { + const std::string& id = entry.first.first; + const int count = entry.second; + for(auto& item : mItems) + { + if(item.mCount == count && Misc::StringUtils::ciEqual(id, item.mRef.mRefID)) + item.mCount = -count; + } + } } void ESM::InventoryState::save (ESMWriter &esm) const diff --git a/components/esm/magiceffects.hpp b/components/esm/magiceffects.hpp index 2a6052caa..a931c68fa 100644 --- a/components/esm/magiceffects.hpp +++ b/components/esm/magiceffects.hpp @@ -2,6 +2,7 @@ #define COMPONENTS_ESM_MAGICEFFECTS_H #include +#include namespace ESM { @@ -18,6 +19,41 @@ namespace ESM void save (ESMWriter &esm) const; }; + struct SummonKey + { + SummonKey(int effectId, const std::string& sourceId, int index) + { + mEffectId = effectId; + mSourceId = sourceId; + mEffectIndex = index; + } + + bool operator==(const SummonKey &other) const + { + return mEffectId == other.mEffectId && + mSourceId == other.mSourceId && + mEffectIndex == other.mEffectIndex; + } + + bool operator<(const SummonKey &other) const + { + if (mEffectId < other.mEffectId) + return true; + if (mEffectId > other.mEffectId) + return false; + + if (mSourceId < other.mSourceId) + return true; + if (mSourceId > other.mSourceId) + return false; + + return mEffectIndex < other.mEffectIndex; + } + + int mEffectId; + std::string mSourceId; + int mEffectIndex; + }; } #endif diff --git a/components/esm/savedgame.cpp b/components/esm/savedgame.cpp index 76695dbe8..9edcb1a67 100644 --- a/components/esm/savedgame.cpp +++ b/components/esm/savedgame.cpp @@ -4,7 +4,7 @@ #include "esmwriter.hpp" unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE; -int ESM::SavedGame::sCurrentFormat = 12; +int ESM::SavedGame::sCurrentFormat = 15; void ESM::SavedGame::load (ESMReader &esm) { diff --git a/components/esm/variantimp.hpp b/components/esm/variantimp.hpp index 1dc20c21f..e7ac722b1 100644 --- a/components/esm/variantimp.hpp +++ b/components/esm/variantimp.hpp @@ -75,25 +75,25 @@ namespace ESM ///< Calling the constructor with an incompatible data type will result in a silent /// default initialisation. - virtual VariantDataBase *clone() const; + VariantDataBase *clone() const override; - virtual std::string getString (bool default_ = false) const; + std::string getString (bool default_ = false) const override; ///< Will throw an exception, if value can not be represented as a string. /// /// \note Numeric values are not converted to strings. /// /// \param default_ Return a default value instead of throwing an exception. - virtual void setString (const std::string& value); + void setString (const std::string& value) override; ///< Will throw an exception, if type is not compatible with string. - virtual void read (ESMReader& esm, Variant::Format format, VarType type); + void read (ESMReader& esm, Variant::Format format, VarType type) override; ///< If \a type is not supported by \a format, an exception is thrown via ESMReader::fail - virtual void write (ESMWriter& esm, Variant::Format format, VarType type) const; + void write (ESMWriter& esm, Variant::Format format, VarType type) const override; ///< If \a type is not supported by \a format, an exception is thrown. - virtual bool isEqual (const VariantDataBase& value) const; + bool isEqual (const VariantDataBase& value) const override; ///< If the (C++) type of \a value does not match the type of *this, an exception is thrown. }; @@ -107,32 +107,32 @@ namespace ESM ///< Calling the constructor with an incompatible data type will result in a silent /// default initialisation. - virtual VariantDataBase *clone() const; + VariantDataBase *clone() const override; - virtual int getInteger (bool default_ = false) const; + int getInteger (bool default_ = false) const override; ///< Will throw an exception, if value can not be represented as an integer (implicit /// casting of float values is permitted). /// /// \param default_ Return a default value instead of throwing an exception. - virtual float getFloat (bool default_ = false) const; + float getFloat (bool default_ = false) const override; ///< Will throw an exception, if value can not be represented as a float value. /// /// \param default_ Return a default value instead of throwing an exception. - virtual void setInteger (int value); + void setInteger (int value) override; ///< Will throw an exception, if type is not compatible with integer. - virtual void setFloat (float value); + void setFloat (float value) override; ///< Will throw an exception, if type is not compatible with float. - virtual void read (ESMReader& esm, Variant::Format format, VarType type); + void read (ESMReader& esm, Variant::Format format, VarType type) override; ///< If \a type is not supported by \a format, an exception is thrown via ESMReader::fail - virtual void write (ESMWriter& esm, Variant::Format format, VarType type) const; + void write (ESMWriter& esm, Variant::Format format, VarType type) const override; ///< If \a type is not supported by \a format, an exception is thrown. - virtual bool isEqual (const VariantDataBase& value) const; + bool isEqual (const VariantDataBase& value) const override; ///< If the (C++) type of \a value does not match the type of *this, an exception is thrown. }; @@ -146,32 +146,32 @@ namespace ESM ///< Calling the constructor with an incompatible data type will result in a silent /// default initialisation. - virtual VariantDataBase *clone() const; + VariantDataBase *clone() const override; - virtual int getInteger (bool default_ = false) const; + int getInteger (bool default_ = false) const override; ///< Will throw an exception, if value can not be represented as an integer (implicit /// casting of float values is permitted). /// /// \param default_ Return a default value instead of throwing an exception. - virtual float getFloat (bool default_ = false) const; + float getFloat (bool default_ = false) const override; ///< Will throw an exception, if value can not be represented as a float value. /// /// \param default_ Return a default value instead of throwing an exception. - virtual void setInteger (int value); + void setInteger (int value) override; ///< Will throw an exception, if type is not compatible with integer. - virtual void setFloat (float value); + void setFloat (float value) override; ///< Will throw an exception, if type is not compatible with float. - virtual void read (ESMReader& esm, Variant::Format format, VarType type); + void read (ESMReader& esm, Variant::Format format, VarType type) override; ///< If \a type is not supported by \a format, an exception is thrown via ESMReader::fail - virtual void write (ESMWriter& esm, Variant::Format format, VarType type) const; + void write (ESMWriter& esm, Variant::Format format, VarType type) const override; ///< If \a type is not supported by \a format, an exception is thrown. - virtual bool isEqual (const VariantDataBase& value) const; + bool isEqual (const VariantDataBase& value) const override; ///< If the (C++) type of \a value does not match the type of *this, an exception is thrown. }; } diff --git a/components/esmterrain/storage.hpp b/components/esmterrain/storage.hpp index c64531140..68e71574e 100644 --- a/components/esmterrain/storage.hpp +++ b/components/esmterrain/storage.hpp @@ -60,7 +60,7 @@ namespace ESMTerrain virtual osg::ref_ptr getLand (int cellX, int cellY)= 0; virtual const ESM::LandTexture* getLandTexture(int index, short plugin) = 0; /// Get bounds of the whole terrain in cell units - virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY) = 0; + void getBounds(float& minX, float& maxX, float& minY, float& maxY) override = 0; /// Get the minimum and maximum heights of a terrain region. /// @note Will only be called for chunks with size = minBatchSize, i.e. leafs of the quad tree. @@ -70,7 +70,7 @@ namespace ESMTerrain /// @param min min height will be stored here /// @param max max height will be stored here /// @return true if there was data available for this terrain chunk - virtual bool getMinMaxHeights (float size, const osg::Vec2f& center, float& min, float& max); + bool getMinMaxHeights (float size, const osg::Vec2f& center, float& min, float& max) override; /// Fill vertex buffers for a terrain chunk. /// @note May be called from background threads. Make sure to only call thread-safe functions from here! @@ -82,10 +82,10 @@ namespace ESMTerrain /// @param positions buffer to write vertices /// @param normals buffer to write vertex normals /// @param colours buffer to write vertex colours - virtual void fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center, + void fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center, osg::ref_ptr positions, osg::ref_ptr normals, - osg::ref_ptr colours); + osg::ref_ptr colours) override; /// Create textures holding layer blend values for a terrain chunk. /// @note The terrain chunk shouldn't be larger than one cell since otherwise we might @@ -95,18 +95,18 @@ namespace ESMTerrain /// @param chunkCenter center of the chunk in cell units /// @param blendmaps created blendmaps will be written here /// @param layerList names of the layer textures used will be written here - virtual void getBlendmaps (float chunkSize, const osg::Vec2f& chunkCenter, ImageVector& blendmaps, - std::vector& layerList); + void getBlendmaps (float chunkSize, const osg::Vec2f& chunkCenter, ImageVector& blendmaps, + std::vector& layerList) override; - virtual float getHeightAt (const osg::Vec3f& worldPos); + float getHeightAt (const osg::Vec3f& worldPos) override; /// Get the transformation factor for mapping cell units to world units. - virtual float getCellWorldSize(); + float getCellWorldSize() override; /// Get the number of vertices on one side for each cell. Should be (power of two)+1 - virtual int getCellVertices(); + int getCellVertices() override; - virtual int getBlendmapScale(float chunkSize); + int getBlendmapScale(float chunkSize) override; float getVertexHeight (const ESM::Land::LandData* data, int x, int y) { diff --git a/components/files/constrainedfilestream.cpp b/components/files/constrainedfilestream.cpp index 419af0d6c..d2802218f 100644 --- a/components/files/constrainedfilestream.cpp +++ b/components/files/constrainedfilestream.cpp @@ -37,7 +37,7 @@ namespace Files mOrigin = start; } - virtual int_type underflow() + int_type underflow() override { if(gptr() == egptr()) { @@ -53,7 +53,7 @@ namespace Files return traits_type::to_int_type(*gptr()); } - virtual pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) + pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) override { if((mode&std::ios_base::out) || !(mode&std::ios_base::in)) return traits_type::eof(); @@ -86,7 +86,7 @@ namespace Files return newPos; } - virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode) + pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override { if((mode&std::ios_base::out) || !(mode&std::ios_base::in)) return traits_type::eof(); diff --git a/components/interpreter/controlopcodes.hpp b/components/interpreter/controlopcodes.hpp index caa755989..fdf929161 100644 --- a/components/interpreter/controlopcodes.hpp +++ b/components/interpreter/controlopcodes.hpp @@ -12,7 +12,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { runtime.setPC (-1); } @@ -22,7 +22,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; runtime.pop(); @@ -36,7 +36,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; runtime.pop(); @@ -50,7 +50,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime, unsigned int arg0) + void execute (Runtime& runtime, unsigned int arg0) override { if (arg0==0) throw std::logic_error ("infinite loop"); @@ -63,7 +63,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime, unsigned int arg0) + void execute (Runtime& runtime, unsigned int arg0) override { if (arg0==0) throw std::logic_error ("infinite loop"); diff --git a/components/interpreter/genericopcodes.hpp b/components/interpreter/genericopcodes.hpp index 44ef3fc6b..ca08027ae 100644 --- a/components/interpreter/genericopcodes.hpp +++ b/components/interpreter/genericopcodes.hpp @@ -10,7 +10,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime, unsigned int arg0) + void execute (Runtime& runtime, unsigned int arg0) override { runtime.push (static_cast (arg0)); } @@ -20,7 +20,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; Type_Float floatValue = static_cast (data); @@ -32,7 +32,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float data = runtime[0].mFloat; Type_Integer integerValue = static_cast (data); @@ -44,7 +44,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; data = -data; @@ -56,7 +56,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float data = runtime[0].mFloat; data = -data; @@ -68,7 +68,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[1].mInteger; Type_Float floatValue = static_cast (data); @@ -80,7 +80,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float data = runtime[1].mFloat; Type_Integer integerValue = static_cast (data); diff --git a/components/interpreter/localopcodes.hpp b/components/interpreter/localopcodes.hpp index 7844a9ea7..0227327b3 100644 --- a/components/interpreter/localopcodes.hpp +++ b/components/interpreter/localopcodes.hpp @@ -11,7 +11,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; int index = runtime[1].mInteger; @@ -27,7 +27,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; int index = runtime[1].mInteger; @@ -43,7 +43,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float data = runtime[0].mFloat; int index = runtime[1].mInteger; @@ -59,7 +59,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer intValue = runtime.getIntegerLiteral (runtime[0].mInteger); runtime[0].mInteger = intValue; @@ -70,7 +70,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float floatValue = runtime.getFloatLiteral (runtime[0].mInteger); runtime[0].mFloat = floatValue; @@ -81,7 +81,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { int index = runtime[0].mInteger; int value = runtime.getContext().getLocalShort (index); @@ -93,7 +93,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { int index = runtime[0].mInteger; int value = runtime.getContext().getLocalLong (index); @@ -105,7 +105,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { int index = runtime[0].mInteger; float value = runtime.getContext().getLocalFloat (index); @@ -117,7 +117,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; int index = runtime[1].mInteger; @@ -135,7 +135,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; int index = runtime[1].mInteger; @@ -153,7 +153,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float data = runtime[0].mFloat; int index = runtime[1].mInteger; @@ -171,7 +171,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); @@ -184,7 +184,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); @@ -197,7 +197,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { int index = runtime[0].mInteger; std::string name = runtime.getStringLiteral (index); @@ -214,7 +214,7 @@ namespace Interpreter OpStoreMemberShort (bool global) : mGlobal (global) {} - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; Type_Integer index = runtime[1].mInteger; @@ -238,7 +238,7 @@ namespace Interpreter OpStoreMemberLong (bool global) : mGlobal (global) {} - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer data = runtime[0].mInteger; Type_Integer index = runtime[1].mInteger; @@ -262,7 +262,7 @@ namespace Interpreter OpStoreMemberFloat (bool global) : mGlobal (global) {} - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float data = runtime[0].mFloat; Type_Integer index = runtime[1].mInteger; @@ -286,7 +286,7 @@ namespace Interpreter OpFetchMemberShort (bool global) : mGlobal (global) {} - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer index = runtime[0].mInteger; std::string id = runtime.getStringLiteral (index); @@ -307,7 +307,7 @@ namespace Interpreter OpFetchMemberLong (bool global) : mGlobal (global) {} - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer index = runtime[0].mInteger; std::string id = runtime.getStringLiteral (index); @@ -328,7 +328,7 @@ namespace Interpreter OpFetchMemberFloat (bool global) : mGlobal (global) {} - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Integer index = runtime[0].mInteger; std::string id = runtime.getStringLiteral (index); diff --git a/components/interpreter/mathopcodes.hpp b/components/interpreter/mathopcodes.hpp index 14d5d98df..42cb486b9 100644 --- a/components/interpreter/mathopcodes.hpp +++ b/components/interpreter/mathopcodes.hpp @@ -14,7 +14,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { T result = getData (runtime[1]) + getData (runtime[0]); @@ -29,7 +29,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { T result = getData (runtime[1]) - getData (runtime[0]); @@ -44,7 +44,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { T result = getData (runtime[1]) * getData (runtime[0]); @@ -59,7 +59,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { T left = getData (runtime[0]); @@ -78,7 +78,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { Type_Float value = runtime[0].mFloat; @@ -97,7 +97,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { int result = C() (getData (runtime[1]), getData (runtime[0])); diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 07bd84ec9..5a9311346 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -22,7 +22,7 @@ namespace Interpreter Runtime& mRuntime; protected: - virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision, Notation notation) + void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision, Notation notation) override { std::ostringstream out; out.fill(padding); @@ -86,7 +86,7 @@ namespace Interpreter } } - virtual void visitedCharacter(char c) + void visitedCharacter(char c) override { mFormattedMessage += c; } @@ -97,7 +97,7 @@ namespace Interpreter { } - virtual void process(const std::string& message) + void process(const std::string& message) override { mFormattedMessage.clear(); MessageFormatParser::process(message); @@ -123,7 +123,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime, unsigned int arg0) + void execute (Runtime& runtime, unsigned int arg0) override { // message int index = runtime[0].mInteger; @@ -153,7 +153,7 @@ namespace Interpreter { public: - virtual void execute (Runtime& runtime) + void execute (Runtime& runtime) override { // message int index = runtime[0].mInteger; diff --git a/components/misc/barrier.hpp b/components/misc/barrier.hpp new file mode 100644 index 000000000..7259b8452 --- /dev/null +++ b/components/misc/barrier.hpp @@ -0,0 +1,51 @@ +#ifndef OPENMW_BARRIER_H +#define OPENMW_BARRIER_H + +#include +#include +#include + +namespace Misc +{ + /// @brief Synchronize several threads + class Barrier + { + public: + using BarrierCallback = std::function; + /// @param count number of threads to wait on + /// @param func callable to be executed once after all threads have met + Barrier(int count, BarrierCallback&& func) : mThreadCount(count), mRendezvousCount(0), mGeneration(0) + , mFunc(std::forward(func)) + {} + + /// @brief stop execution of threads until count distinct threads reach this point + void wait() + { + std::unique_lock lock(mMutex); + + ++mRendezvousCount; + const int currentGeneration = mGeneration; + if (mRendezvousCount == mThreadCount) + { + ++mGeneration; + mRendezvousCount = 0; + mFunc(); + mRendezvous.notify_all(); + } + else + { + mRendezvous.wait(lock, [&]() { return mGeneration != currentGeneration; }); + } + } + + private: + int mThreadCount; + int mRendezvousCount; + int mGeneration; + mutable std::mutex mMutex; + std::condition_variable mRendezvous; + BarrierCallback mFunc; + }; +} + +#endif diff --git a/components/misc/gcd.hpp b/components/misc/gcd.hpp deleted file mode 100644 index fd9e972e7..000000000 --- a/components/misc/gcd.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef MISC_GCD_H -#define MISC_GCD_H - -namespace Misc -{ - // TODO: replace to the std::gcd() when the C++17 will be available. - int gcd(int a, int b) - { - return b == 0 ? a : gcd(b, a % b); - } -} - -#endif diff --git a/components/misc/mathutil.hpp b/components/misc/mathutil.hpp new file mode 100644 index 000000000..2f7f446b5 --- /dev/null +++ b/components/misc/mathutil.hpp @@ -0,0 +1,27 @@ +#ifndef MISC_MATHUTIL_H +#define MISC_MATHUTIL_H + +#include +#include + +namespace Misc +{ + + /// Normalizes given angle to the range [-PI, PI]. E.g. PI*3/2 -> -PI/2. + inline double normalizeAngle(double angle) + { + double fullTurns = angle / (2 * osg::PI) + 0.5; + return (fullTurns - floor(fullTurns) - 0.5) * (2 * osg::PI); + } + + /// Rotates given 2d vector counterclockwise. Angle is in radians. + inline osg::Vec2f rotateVec2f(osg::Vec2f vec, float angle) + { + float s = std::sin(angle); + float c = std::cos(angle); + return osg::Vec2f(vec.x() * c + vec.y() * -s, vec.x() * s + vec.y() * c); + } + +} + +#endif diff --git a/components/misc/rng.cpp b/components/misc/rng.cpp index 09279e85e..23d820448 100644 --- a/components/misc/rng.cpp +++ b/components/misc/rng.cpp @@ -3,29 +3,44 @@ #include #include +namespace +{ + Misc::Rng::Seed sSeed; +} + namespace Misc { - std::mt19937 Rng::generator = std::mt19937(); + Rng::Seed::Seed() {} + + Rng::Seed::Seed(unsigned int seed) + { + mGenerator.seed(seed); + } + + Rng::Seed& Rng::getSeed() + { + return sSeed; + } void Rng::init(unsigned int seed) { - generator.seed(seed); + sSeed.mGenerator.seed(seed); } - float Rng::rollProbability() + float Rng::rollProbability(Seed& seed) { - return std::uniform_real_distribution(0, 1 - std::numeric_limits::epsilon())(generator); + return std::uniform_real_distribution(0, 1 - std::numeric_limits::epsilon())(seed.mGenerator); } - float Rng::rollClosedProbability() + float Rng::rollClosedProbability(Seed& seed) { - return std::uniform_real_distribution(0, 1)(generator); + return std::uniform_real_distribution(0, 1)(seed.mGenerator); } - int Rng::rollDice(int max) + int Rng::rollDice(int max, Seed& seed) { - return max > 0 ? std::uniform_int_distribution(0, max - 1)(generator) : 0; + return max > 0 ? std::uniform_int_distribution(0, max - 1)(seed.mGenerator) : 0; } unsigned int Rng::generateDefaultSeed() diff --git a/components/misc/rng.hpp b/components/misc/rng.hpp index 65a554cf2..8efca438d 100644 --- a/components/misc/rng.hpp +++ b/components/misc/rng.hpp @@ -13,24 +13,32 @@ namespace Misc class Rng { public: + class Seed + { + std::mt19937 mGenerator; + public: + Seed(); + Seed(const Seed&) = delete; + Seed(unsigned int seed); + friend class Rng; + }; - /// create a RNG - static std::mt19937 generator; + static Seed& getSeed(); /// seed the RNG static void init(unsigned int seed = generateDefaultSeed()); /// return value in range [0.0f, 1.0f) <- note open upper range. - static float rollProbability(); + static float rollProbability(Seed& seed = getSeed()); /// return value in range [0.0f, 1.0f] <- note closed upper range. - static float rollClosedProbability(); + static float rollClosedProbability(Seed& seed = getSeed()); /// return value in range [0, max) <- note open upper range. - static int rollDice(int max); + static int rollDice(int max, Seed& seed = getSeed()); /// return value in range [0, 99] - static int roll0to99() { return rollDice(100); } + static int roll0to99(Seed& seed = getSeed()) { return rollDice(100, seed); } /// returns default seed for RNG static unsigned int generateDefaultSeed(); diff --git a/components/myguiplatform/myguidatamanager.hpp b/components/myguiplatform/myguidatamanager.hpp index 5002f0fb7..a97c6ad2e 100644 --- a/components/myguiplatform/myguidatamanager.hpp +++ b/components/myguiplatform/myguidatamanager.hpp @@ -18,28 +18,28 @@ public: /** Get data stream from specified resource name. @param _name Resource name (usually file name). */ - virtual MyGUI::IDataStream* getData(const std::string& _name); + MyGUI::IDataStream* getData(const std::string& _name) override; /** Free data stream. @param _data Data stream. */ - virtual void freeData(MyGUI::IDataStream* _data); + void freeData(MyGUI::IDataStream* _data) override; /** Is data with specified name exist. @param _name Resource name. */ - virtual bool isDataExist(const std::string& _name); + bool isDataExist(const std::string& _name) override; /** Get all data names with names that matches pattern. @param _pattern Pattern to match (for example "*.layout"). */ - virtual const MyGUI::VectorString& getDataListNames(const std::string& _pattern); + const MyGUI::VectorString& getDataListNames(const std::string& _pattern) override; /** Get full path to data. @param _name Resource name. @return Return full path to specified data. */ - virtual const std::string& getDataPath(const std::string& _name); + const std::string& getDataPath(const std::string& _name) override; private: std::string mResourcePath; diff --git a/components/myguiplatform/myguiloglistener.hpp b/components/myguiplatform/myguiloglistener.hpp index 70dfc4ecf..4bab20ac9 100644 --- a/components/myguiplatform/myguiloglistener.hpp +++ b/components/myguiplatform/myguiloglistener.hpp @@ -24,11 +24,11 @@ namespace osgMyGUI ~CustomLogListener() {} - virtual void open(); - virtual void close(); - virtual void flush(); + void open() override; + void close() override; + void flush() override; - virtual void log(const std::string& _section, MyGUI::LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line); + void log(const std::string& _section, MyGUI::LogLevel _level, const struct tm* _time, const std::string& _message, const char* _file, int _line) override; const std::string& getFileName() const { return mFileName; } diff --git a/components/myguiplatform/myguirendermanager.cpp b/components/myguiplatform/myguirendermanager.cpp index c636208e8..b1fdabe41 100644 --- a/components/myguiplatform/myguirendermanager.cpp +++ b/components/myguiplatform/myguirendermanager.cpp @@ -66,7 +66,7 @@ public: mRenderManager = renderManager; } - virtual void update(osg::NodeVisitor*, osg::Drawable*) + void update(osg::NodeVisitor*, osg::Drawable*) override { if (mRenderManager) mRenderManager->update(); @@ -96,7 +96,7 @@ public: mFilter = filter; } - virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const; + bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const override; private: GUICamera* mCamera; @@ -104,7 +104,7 @@ public: }; // Stage 2: execute the draw calls. Run during the Draw traversal. May run in parallel with the update traversal of the next frame. - virtual void drawImplementation(osg::RenderInfo &renderInfo) const + void drawImplementation(osg::RenderInfo &renderInfo) const override { osg::State *state = renderInfo.getState(); @@ -273,11 +273,11 @@ public: osg::Array* getVertexArray(); osg::VertexBufferObject* getVertexBuffer(); - virtual void setVertexCount(size_t count); - virtual size_t getVertexCount(); + void setVertexCount(size_t count) override; + size_t getVertexCount() override; - virtual MyGUI::Vertex *lock(); - virtual void unlock(); + MyGUI::Vertex *lock() override; + void unlock() override; }; diff --git a/components/myguiplatform/myguirendermanager.hpp b/components/myguiplatform/myguirendermanager.hpp index 2c4f1279b..553bc012a 100644 --- a/components/myguiplatform/myguirendermanager.hpp +++ b/components/myguiplatform/myguirendermanager.hpp @@ -53,6 +53,8 @@ class RenderManager : public MyGUI::RenderManager MyGUI::IntSize mViewSize; MyGUI::VertexColourType mVertexFormat; + MyGUI::RenderTargetInfo mInfo; + typedef std::map MapTexture; MapTexture mTextures; @@ -80,33 +82,41 @@ public: { return static_cast(MyGUI::RenderManager::getInstancePtr()); } /** @see RenderManager::getViewSize */ - virtual const MyGUI::IntSize& getViewSize() const { return mViewSize; } + const MyGUI::IntSize& getViewSize() const override { return mViewSize; } /** @see RenderManager::getVertexFormat */ - virtual MyGUI::VertexColourType getVertexFormat() { return mVertexFormat; } + MyGUI::VertexColourType getVertexFormat() override { return mVertexFormat; } /** @see RenderManager::isFormatSupported */ - virtual bool isFormatSupported(MyGUI::PixelFormat format, MyGUI::TextureUsage usage); + bool isFormatSupported(MyGUI::PixelFormat format, MyGUI::TextureUsage usage) override; /** @see RenderManager::createVertexBuffer */ - virtual MyGUI::IVertexBuffer* createVertexBuffer(); + MyGUI::IVertexBuffer* createVertexBuffer() override; /** @see RenderManager::destroyVertexBuffer */ - virtual void destroyVertexBuffer(MyGUI::IVertexBuffer *buffer); + void destroyVertexBuffer(MyGUI::IVertexBuffer *buffer) override; /** @see RenderManager::createTexture */ - virtual MyGUI::ITexture* createTexture(const std::string &name); + MyGUI::ITexture* createTexture(const std::string &name) override; /** @see RenderManager::destroyTexture */ - virtual void destroyTexture(MyGUI::ITexture* _texture); + void destroyTexture(MyGUI::ITexture* _texture) override; /** @see RenderManager::getTexture */ - virtual MyGUI::ITexture* getTexture(const std::string &name); + MyGUI::ITexture* getTexture(const std::string &name) override; // Called by the update traversal void update(); bool checkTexture(MyGUI::ITexture* _texture); + // setViewSize() is a part of MyGUI::RenderManager interface since 3.4.0 release +#if MYGUI_VERSION < MYGUI_DEFINE_VERSION(3,4,0) void setViewSize(int width, int height); +#else + void setViewSize(int width, int height) override; +#endif +/*internal:*/ + + void collectDrawCalls(); osg::ref_ptr createGUICamera(int order, std::string layerFilter); void deleteGUICamera(GUICamera* camera); }; diff --git a/components/myguiplatform/myguitexture.hpp b/components/myguiplatform/myguitexture.hpp index 48f2ed265..6baeb7459 100644 --- a/components/myguiplatform/myguitexture.hpp +++ b/components/myguiplatform/myguitexture.hpp @@ -37,26 +37,26 @@ namespace osgMyGUI OSGTexture(osg::Texture2D* texture); virtual ~OSGTexture(); - virtual const std::string& getName() const { return mName; } + const std::string& getName() const override { return mName; } - virtual void createManual(int width, int height, MyGUI::TextureUsage usage, MyGUI::PixelFormat format); - virtual void loadFromFile(const std::string &fname); - virtual void saveToFile(const std::string &fname); + void createManual(int width, int height, MyGUI::TextureUsage usage, MyGUI::PixelFormat format) override; + void loadFromFile(const std::string &fname) override; + void saveToFile(const std::string &fname) override; - virtual void destroy(); + void destroy() override; - virtual void* lock(MyGUI::TextureUsage access); - virtual void unlock(); - virtual bool isLocked(); + void* lock(MyGUI::TextureUsage access) override; + void unlock() override; + bool isLocked() override; - virtual int getWidth(); - virtual int getHeight(); + int getWidth() override; + int getHeight() override; - virtual MyGUI::PixelFormat getFormat() { return mFormat; } - virtual MyGUI::TextureUsage getUsage() { return mUsage; } - virtual size_t getNumElemBytes() { return mNumElemBytes; } + MyGUI::PixelFormat getFormat() override { return mFormat; } + MyGUI::TextureUsage getUsage() override { return mUsage; } + size_t getNumElemBytes() override { return mNumElemBytes; } - virtual MyGUI::IRenderTarget *getRenderTarget(); + MyGUI::IRenderTarget *getRenderTarget() override; /*internal:*/ osg::Texture2D *getTexture() const { return mTexture.get(); } diff --git a/components/myguiplatform/scalinglayer.cpp b/components/myguiplatform/scalinglayer.cpp index ee9de349e..07a5161b2 100644 --- a/components/myguiplatform/scalinglayer.cpp +++ b/components/myguiplatform/scalinglayer.cpp @@ -22,22 +22,22 @@ namespace osgMyGUI { } - virtual void begin() + void begin() override { mTarget->begin(); } - virtual void end() + void end() override { mTarget->end(); } - virtual void doRender(MyGUI::IVertexBuffer* _buffer, MyGUI::ITexture* _texture, size_t _count) + void doRender(MyGUI::IVertexBuffer* _buffer, MyGUI::ITexture* _texture, size_t _count) override { mTarget->doRender(_buffer, _texture, _count); } - virtual const MyGUI::RenderTargetInfo& getInfo() + const MyGUI::RenderTargetInfo& getInfo() override { mInfo = mTarget->getInfo(); mInfo.hOffset = mHOffset; diff --git a/components/nif/base.hpp b/components/nif/base.hpp index 6e26f525e..711272abb 100644 --- a/components/nif/base.hpp +++ b/components/nif/base.hpp @@ -14,15 +14,21 @@ namespace Nif class Extra : public Record { public: + std::string name; ExtraPtr next; // Next extra data record in the list - void read(NIFStream *nif) + void read(NIFStream *nif) override { - next.read(nif); - nif->getUInt(); // Size of the record + if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0)) + name = nif->getString(); + else if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0)) + { + next.read(nif); + nif->getUInt(); // Size of the record + } } - void post(NIFFile *nif) { next.post(nif); } + void post(NIFFile *nif) override { next.post(nif); } }; class Controller : public Record @@ -34,8 +40,8 @@ public: float timeStart, timeStop; NamedPtr target; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; /// Has name, extra-data and controller @@ -44,18 +50,23 @@ class Named : public Record public: std::string name; ExtraPtr extra; + ExtraList extralist; ControllerPtr controller; - void read(NIFStream *nif) + void read(NIFStream *nif) override { name = nif->getString(); - extra.read(nif); + if (nif->getVersion() < NIFStream::generateVersion(10,0,1,0)) + extra.read(nif); + else + extralist.read(nif); controller.read(nif); } - void post(NIFFile *nif) + void post(NIFFile *nif) override { extra.post(nif); + extralist.post(nif); controller.post(nif); } }; diff --git a/components/nif/controlled.cpp b/components/nif/controlled.cpp index 0b5c32a10..ab2b8dc17 100644 --- a/components/nif/controlled.cpp +++ b/components/nif/controlled.cpp @@ -14,16 +14,31 @@ namespace Nif if (external) filename = nif->getString(); else - internal = nif->getChar(); - - if (!external && internal) + { + if (nif->getVersion() <= NIFStream::generateVersion(10,0,1,3)) + internal = nif->getChar(); + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + filename = nif->getString(); // Original file path of the internal texture + } + if (nif->getVersion() <= NIFStream::generateVersion(10,0,1,3)) + { + if (!external && internal) + data.read(nif); + } + else + { data.read(nif); + } pixel = nif->getUInt(); mipmap = nif->getUInt(); alpha = nif->getUInt(); nif->getChar(); // always 1 + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,103)) + nif->getBoolean(); // Direct rendering + if (nif->getVersion() >= NIFStream::generateVersion(20,2,0,4)) + nif->getBoolean(); // NiPersistentSrcTextureRendererData is used instead of NiPixelData } void NiSourceTexture::post(NIFFile *nif) @@ -79,6 +94,12 @@ namespace Nif NiParticleModifier::read(nif); mBounceFactor = nif->getFloat(); + if (nif->getVersion() >= NIFStream::generateVersion(4,2,2,0)) + { + // Unused in NifSkope. Need to figure out what these do. + /*bool spawnOnCollision = */nif->getBoolean(); + /*bool dieOnCollision = */nif->getBoolean(); + } } void NiPlanarCollider::read(NIFStream *nif) diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index 8396eae04..57d538f83 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -62,8 +62,8 @@ public: */ unsigned int alpha; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; struct NiParticleModifier : public Record @@ -71,8 +71,8 @@ struct NiParticleModifier : public Record NiParticleModifierPtr next; ControllerPtr controller; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiParticleGrowFade : public NiParticleModifier @@ -81,7 +81,7 @@ public: float growTime; float fadeTime; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiParticleColorModifier : public NiParticleModifier @@ -89,8 +89,8 @@ class NiParticleColorModifier : public NiParticleModifier public: NiColorDataPtr data; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiGravity : public NiParticleModifier @@ -105,20 +105,20 @@ public: osg::Vec3f mPosition; osg::Vec3f mDirection; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; struct NiParticleCollider : public NiParticleModifier { float mBounceFactor; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; // NiPinaColada class NiPlanarCollider : public NiParticleCollider { public: - void read(NIFStream *nif); + void read(NIFStream *nif) override; osg::Vec3f mPlaneNormal; float mPlaneDistance; @@ -130,13 +130,13 @@ public: float mRadius; osg::Vec3f mCenter; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiParticleRotation : public NiParticleModifier { public: - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index c63c83676..07699239e 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -97,7 +97,10 @@ namespace Nif // 01: Diffuse // 10: Specular // 11: Emissive - targetColor = (flags >> 4) & 3; + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + targetColor = nif->getUShort() & 3; + else + targetColor = (flags >> 4) & 3; data.read(nif); } @@ -110,6 +113,8 @@ namespace Nif void NiLookAtController::read(NIFStream *nif) { Controller::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + lookAtFlags = nif->getUShort(); target.read(nif); } @@ -165,25 +170,13 @@ namespace Nif data.post(nif); } - void NiAlphaController::read(NIFStream *nif) + void NiFloatInterpController::read(NIFStream *nif) { Controller::read(nif); data.read(nif); } - void NiAlphaController::post(NIFFile *nif) - { - Controller::post(nif); - data.post(nif); - } - - void NiRollController::read(NIFStream *nif) - { - Controller::read(nif); - data.read(nif); - } - - void NiRollController::post(NIFFile *nif) + void NiFloatInterpController::post(NIFFile *nif) { Controller::post(nif); data.post(nif); @@ -192,6 +185,8 @@ namespace Nif void NiGeomMorpherController::read(NIFStream *nif) { Controller::read(nif); + if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD) + /*bool updateNormals = !!*/nif->getUShort(); data.read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) /*bool alwaysActive = */nif->getChar(); // Always 0 @@ -219,8 +214,11 @@ namespace Nif { Controller::read(nif); mTexSlot = nif->getUInt(); - /*unknown=*/nif->getUInt();/*0?*/ - mDelta = nif->getFloat(); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) + { + timeStart = nif->getFloat(); + mDelta = nif->getFloat(); + } mSources.read(nif); } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 41dd14fac..54cf9bf8f 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -75,8 +75,8 @@ public: NiParticleModifierPtr affectors; NiParticleModifierPtr colliders; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; using NiBSPArrayController = NiParticleSystemController; @@ -86,8 +86,8 @@ public: NiPosDataPtr data; unsigned int targetColor; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiPathController : public Controller @@ -110,17 +110,18 @@ public: float maxBankAngle, smoothing; short followAxis; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiLookAtController : public Controller { public: NodePtr target; + unsigned short lookAtFlags{0}; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiUVController : public Controller @@ -129,8 +130,8 @@ public: NiUVDataPtr data; unsigned int uvSet; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiKeyframeController : public Controller @@ -138,35 +139,28 @@ class NiKeyframeController : public Controller public: NiKeyframeDataPtr data; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; -class NiAlphaController : public Controller +struct NiFloatInterpController : public Controller { -public: NiFloatDataPtr data; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; -class NiRollController : public Controller -{ -public: - NiFloatDataPtr data; - - void read(NIFStream *nif); - void post(NIFFile *nif); -}; +class NiAlphaController : public NiFloatInterpController { }; +class NiRollController : public NiFloatInterpController { }; class NiGeomMorpherController : public Controller { public: NiMorphDataPtr data; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiVisController : public Controller @@ -174,8 +168,8 @@ class NiVisController : public Controller public: NiVisDataPtr data; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiFlipController : public Controller @@ -185,8 +179,8 @@ public: float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources NiSourceTextureList mSources; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; } // Namespace diff --git a/components/nif/data.cpp b/components/nif/data.cpp index afb304bad..91b3beba4 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -33,13 +33,33 @@ void NiSkinInstance::post(NIFFile *nif) void NiGeometryData::read(NIFStream *nif) { + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,114)) + nif->getInt(); // Group ID. (Almost?) always 0. + int verts = nif->getUShort(); + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + nif->skip(2); // Keep flags and compress flags + if (nif->getBoolean()) nif->getVector3s(vertices, verts); + unsigned int dataFlags = 0; + if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0)) + dataFlags = nif->getUShort(); + + if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3) + nif->getUInt(); // Material CRC + if (nif->getBoolean()) + { nif->getVector3s(normals, verts); + if (dataFlags & 0x1000) + { + nif->getVector3s(tangents, verts); + nif->getVector3s(bitangents, verts); + } + } center = nif->getVector3(); radius = nif->getFloat(); @@ -47,14 +67,27 @@ void NiGeometryData::read(NIFStream *nif) if (nif->getBoolean()) nif->getVector4s(colors, verts); - // In Morrowind this field only corresponds to the number of UV sets. - // NifTools research is inaccurate. - int uvs = nif->getUShort(); - - if(nif->getInt()) + // Only the first 6 bits are used as a count. I think the rest are + // flags of some sort. + unsigned int numUVs = dataFlags; + if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0)) { - uvlist.resize(uvs); - for(int i = 0;i < uvs;i++) + numUVs = nif->getUShort(); + // In Morrowind this field only corresponds to the number of UV sets. + // NifTools research is inaccurate. + if (nif->getVersion() > NIFFile::NIFVersion::VER_MW) + numUVs &= 0x3f; + } + if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 0) + numUVs &= 0x1; + + bool hasUVs = true; + if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW) + hasUVs = nif->getBoolean(); + if (hasUVs) + { + uvlist.resize(numUVs); + for (unsigned int i = 0; i < numUVs; i++) { nif->getVector2s(uvlist[i], verts); // flip the texture coordinates to convert them to the OpenGL convention of bottom-left image origin @@ -64,6 +97,12 @@ void NiGeometryData::read(NIFStream *nif) } } } + + if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0)) + nif->getUShort(); // Consistency flags + + if (nif->getVersion() >= NIFStream::generateVersion(20,0,0,4)) + nif->skip(4); // Additional data } void NiTriShapeData::read(NIFStream *nif) @@ -75,13 +114,17 @@ void NiTriShapeData::read(NIFStream *nif) // We have three times as many vertices as triangles, so this // is always equal to tris*3. int cnt = nif->getInt(); - nif->getUShorts(triangles, cnt); + bool hasTriangles = true; + if (nif->getVersion() > NIFFile::NIFVersion::VER_OB_OLD) + hasTriangles = nif->getBoolean(); + if (hasTriangles) + nif->getUShorts(triangles, cnt); // Read the match list, which lists the vertices that are equal to // vertices. We don't actually need need this for anything, so // just skip it. - int verts = nif->getUShort(); - for(int i=0;i < verts;i++) + unsigned short verts = nif->getUShort(); + for (unsigned short i=0; i < verts; i++) { // Number of vertices matching vertex 'i' int num = nif->getUShort(); @@ -101,7 +144,11 @@ void NiTriStripsData::read(NIFStream *nif) std::vector lengths; nif->getUShorts(lengths, numStrips); - if (!numStrips) + // "Has Strips" flag. Exceptionally useful. + bool hasStrips = true; + if (nif->getVersion() > NIFFile::NIFVersion::VER_OB_OLD) + hasStrips = nif->getBoolean(); + if (!hasStrips || !numStrips) return; strips.resize(numStrips); @@ -140,27 +187,37 @@ void NiAutoNormalParticlesData::read(NIFStream *nif) NiGeometryData::read(nif); // Should always match the number of vertices - numParticles = nif->getUShort(); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW) + numParticles = nif->getUShort(); - particleRadius = nif->getFloat(); + if (nif->getVersion() <= NIFStream::generateVersion(10,0,1,0)) + std::fill(particleRadii.begin(), particleRadii.end(), nif->getFloat()); + else if (nif->getBoolean()) + nif->getFloats(particleRadii, vertices.size()); activeCount = nif->getUShort(); + // Particle sizes if (nif->getBoolean()) - { - // Particle sizes nif->getFloats(sizes, vertices.size()); + + if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0) && nif->getBoolean()) + nif->getQuaternions(rotations, vertices.size()); + if (nif->getVersion() >= NIFStream::generateVersion(20,0,0,4)) + { + if (nif->getBoolean()) + nif->getFloats(rotationAngles, vertices.size()); + if (nif->getBoolean()) + nif->getVector3s(rotationAxes, vertices.size()); } + } void NiRotatingParticlesData::read(NIFStream *nif) { NiAutoNormalParticlesData::read(nif); - if (nif->getBoolean()) - { - // Rotation quaternions. + if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0) && nif->getBoolean()) nif->getQuaternions(rotations, vertices.size()); - } } void NiPosData::read(NIFStream *nif) @@ -188,12 +245,27 @@ void NiPixelData::read(NIFStream *nif) { fmt = (Format)nif->getUInt(); - for (unsigned int i = 0; i < 4; ++i) - colorMask[i] = nif->getUInt(); - bpp = nif->getUInt(); + if (nif->getVersion() < NIFStream::generateVersion(10,4,0,2)) + { + for (unsigned int i = 0; i < 4; ++i) + colorMask[i] = nif->getUInt(); + bpp = nif->getUInt(); + nif->skip(8); // "Old Fast Compare". Whatever that means. + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + pixelTiling = nif->getUInt(); + } + else // TODO: see if anything from here needs to be implemented + { + bpp = nif->getChar(); + nif->skip(4); // Renderer hint + nif->skip(4); // Extra data + nif->skip(4); // Flags + pixelTiling = nif->getUInt(); + if (nif->getVersion() >= NIFStream::generateVersion(20,3,0,4)) + sRGB = nif->getBoolean(); + nif->skip(4*10); // Channel data + } - // 8 bytes of "Old Fast Compare". Whatever that means. - nif->skip(8); palette.read(nif); numberOfMipmaps = nif->getUInt(); @@ -213,8 +285,10 @@ void NiPixelData::read(NIFStream *nif) // Read the data unsigned int numPixels = nif->getUInt(); - if (numPixels) - nif->getUChars(data, numPixels); + bool hasFaces = nif->getVersion() >= NIFStream::generateVersion(10,4,0,2); + unsigned int numFaces = hasFaces ? nif->getUInt() : 1; + if (numPixels && numFaces) + nif->getUChars(data, numPixels * numFaces); } void NiPixelData::post(NIFFile *nif) @@ -249,6 +323,10 @@ void NiSkinData::read(NIFStream *nif) if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFStream::generateVersion(10,1,0,0)) nif->skip(4); // NiSkinPartition link + // Has vertex weights flag + if (nif->getVersion() > NIFStream::generateVersion(4,2,1,0) && !nif->getBoolean()) + return; + bones.resize(boneNum); for (BoneInfo &bi : bones) { @@ -272,7 +350,7 @@ void NiMorphData::read(NIFStream *nif) { int morphCount = nif->getInt(); int vertCount = nif->getInt(); - /*relative targets?*/nif->getChar(); + nif->getChar(); // Relative targets, always 1 mMorphs.resize(morphCount); for(int i = 0;i < morphCount;i++) @@ -290,7 +368,8 @@ void NiKeyframeData::read(NIFStream *nif) if(mRotations->mInterpolationType == InterpolationType_XYZ) { //Chomp unused float - nif->getFloat(); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,0)) + nif->getFloat(); mXRotations = std::make_shared(); mYRotations = std::make_shared(); mZRotations = std::make_shared(); diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 66b3f693a..0ba544645 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -35,13 +35,13 @@ namespace Nif class NiGeometryData : public Record { public: - std::vector vertices, normals; + std::vector vertices, normals, tangents, bitangents; std::vector colors; std::vector< std::vector > uvlist; osg::Vec3f center; float radius; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiTriShapeData : public NiGeometryData @@ -50,7 +50,7 @@ public: // Triangles, three vertex indices per triangle std::vector triangles; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiTriStripsData : public NiGeometryData @@ -59,7 +59,7 @@ public: // Triangle strips, series of vertex indices. std::vector> strips; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; struct NiLinesData : public NiGeometryData @@ -67,29 +67,27 @@ struct NiLinesData : public NiGeometryData // Lines, series of indices that correspond to connected vertices. std::vector lines; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiAutoNormalParticlesData : public NiGeometryData { public: - int numParticles; - - float particleRadius; + int numParticles{0}; int activeCount; - std::vector sizes; + std::vector particleRadii, sizes, rotationAngles; + std::vector rotations; + std::vector rotationAxes; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiRotatingParticlesData : public NiAutoNormalParticlesData { public: - std::vector rotations; - - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiPosData : public Record @@ -97,7 +95,7 @@ class NiPosData : public Record public: Vector3KeyMapPtr mKeyList; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiUVData : public Record @@ -105,7 +103,7 @@ class NiUVData : public Record public: FloatKeyMapPtr mKeyList[4]; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiFloatData : public Record @@ -113,7 +111,7 @@ class NiFloatData : public Record public: FloatKeyMapPtr mKeyList; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiPixelData : public Record @@ -133,7 +131,8 @@ public: Format fmt; unsigned int colorMask[4]; - unsigned int bpp; + unsigned int bpp, pixelTiling{0}; + bool sRGB{false}; NiPalettePtr palette; unsigned int numberOfMipmaps; @@ -147,8 +146,8 @@ public: std::vector data; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiColorData : public Record @@ -156,7 +155,7 @@ class NiColorData : public Record public: Vector4KeyMapPtr mKeyMap; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiVisData : public Record @@ -168,7 +167,7 @@ public: }; std::vector mVis; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiSkinInstance : public Record @@ -178,8 +177,8 @@ public: NodePtr root; NodeList bones; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiSkinData : public Record @@ -202,7 +201,7 @@ public: Transformation trafo; std::vector bones; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; struct NiMorphData : public Record @@ -213,7 +212,7 @@ struct NiMorphData : public Record }; std::vector mMorphs; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; @@ -229,7 +228,7 @@ struct NiKeyframeData : public Record Vector3KeyMapPtr mTranslations; FloatKeyMapPtr mScales; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiPalette : public Record @@ -238,7 +237,7 @@ public: // 32-bit RGBA colors that correspond to 8-bit indices std::vector colors; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; } // Namespace diff --git a/components/nif/effect.cpp b/components/nif/effect.cpp index 7947e301d..c12eb6c1b 100644 --- a/components/nif/effect.cpp +++ b/components/nif/effect.cpp @@ -28,6 +28,10 @@ void NiTextureEffect::read(NIFStream *nif) // Texture Filtering nif->skip(4); + // Max anisotropy samples + if (nif->getVersion() >= NIFStream::generateVersion(20,5,0,4)) + nif->skip(2); + clamp = nif->getUInt(); textureType = (TextureType)nif->getUInt(); @@ -36,14 +40,12 @@ void NiTextureEffect::read(NIFStream *nif) texture.read(nif); - /* - byte = 0 - vector4 = [1,0,0,0] - short = 0 - short = -75 - short = 0 - */ - nif->skip(23); + nif->skip(1); // Use clipping plane + nif->skip(16); // Clipping plane dimensions vector + if (nif->getVersion() <= NIFStream::generateVersion(10,2,0,0)) + nif->skip(4); // PS2-specific shorts + if (nif->getVersion() <= NIFStream::generateVersion(4,1,0,12)) + nif->skip(2); // Unknown short } void NiTextureEffect::post(NIFFile *nif) diff --git a/components/nif/effect.hpp b/components/nif/effect.hpp index 453e4b04c..32eb3d80d 100644 --- a/components/nif/effect.hpp +++ b/components/nif/effect.hpp @@ -31,9 +31,12 @@ namespace Nif struct NiDynamicEffect : public Node { - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); + if (nif->getVersion() >= nif->generateVersion(10,1,0,106) + && nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4) + nif->getBoolean(); // Switch state unsigned int numAffectedNodes = nif->getUInt(); for (unsigned int i=0; igetUInt(); // ref to another Node @@ -48,7 +51,7 @@ struct NiLight : NiDynamicEffect osg::Vec3f diffuse; osg::Vec3f specular; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; struct NiPointLight : public NiLight @@ -57,14 +60,14 @@ struct NiPointLight : public NiLight float linearAttenuation; float quadraticAttenuation; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; struct NiSpotLight : public NiPointLight { float cutoff; float exponent; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; struct NiTextureEffect : NiDynamicEffect @@ -91,8 +94,8 @@ struct NiTextureEffect : NiDynamicEffect }; CoordGenType coordGenType; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; } // Namespace diff --git a/components/nif/extra.cpp b/components/nif/extra.cpp index cb654d5a0..d08e5d738 100644 --- a/components/nif/extra.cpp +++ b/components/nif/extra.cpp @@ -29,6 +29,56 @@ void NiVertWeightsExtraData::read(NIFStream *nif) nif->skip(nif->getUShort() * sizeof(float)); // vertex weights I guess } +void NiIntegerExtraData::read(NIFStream *nif) +{ + Extra::read(nif); + + data = nif->getUInt(); +} + +void NiIntegersExtraData::read(NIFStream *nif) +{ + Extra::read(nif); + + unsigned int num = nif->getUInt(); + if (num) + nif->getUInts(data, num); +} + +void NiBinaryExtraData::read(NIFStream *nif) +{ + Extra::read(nif); + unsigned int size = nif->getUInt(); + if (size) + nif->getChars(data, size); +} + +void NiBooleanExtraData::read(NIFStream *nif) +{ + Extra::read(nif); + data = nif->getBoolean(); +} + +void NiVectorExtraData::read(NIFStream *nif) +{ + Extra::read(nif); + data = nif->getVector4(); +} + +void NiFloatExtraData::read(NIFStream *nif) +{ + Extra::read(nif); + + data = nif->getFloat(); +} + +void NiFloatsExtraData::read(NIFStream *nif) +{ + Extra::read(nif); + unsigned int num = nif->getUInt(); + if (num) + nif->getFloats(data, num); +} } diff --git a/components/nif/extra.hpp b/components/nif/extra.hpp index d935add55..3be627004 100644 --- a/components/nif/extra.hpp +++ b/components/nif/extra.hpp @@ -32,7 +32,7 @@ namespace Nif class NiVertWeightsExtraData : public Extra { public: - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiTextKeyExtraData : public Extra @@ -45,7 +45,7 @@ public: }; std::vector list; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; class NiStringExtraData : public Extra @@ -57,7 +57,56 @@ public: */ std::string string; - void read(NIFStream *nif); + void read(NIFStream *nif) override; +}; + +struct NiIntegerExtraData : public Extra +{ + unsigned int data; + + void read(NIFStream *nif) override; +}; + +struct NiIntegersExtraData : public Extra +{ + std::vector data; + + void read(NIFStream *nif) override; +}; + +struct NiBinaryExtraData : public Extra +{ + std::vector data; + + void read(NIFStream *nif) override; +}; + +struct NiBooleanExtraData : public Extra +{ + bool data; + + void read(NIFStream *nif) override; +}; + +struct NiVectorExtraData : public Extra +{ + osg::Vec4f data; + + void read(NIFStream *nif) override; +}; + +struct NiFloatExtraData : public Extra +{ + float data; + + void read(NIFStream *nif) override; +}; + +struct NiFloatsExtraData : public Extra +{ + std::vector data; + + void read(NIFStream *nif) override; }; } // Namespace diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index b33f0c051..8d65753d2 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -16,108 +16,106 @@ NIFFile::NIFFile(Files::IStreamPtr stream, const std::string &name) NIFFile::~NIFFile() { - for (std::vector::iterator it = records.begin() ; it != records.end(); ++it) - { - delete *it; - } + for (Record* record : records) + delete record; } template static Record* construct() { return new NodeType; } struct RecordFactoryEntry { - typedef Record* (*create_t) (); + using create_t = Record* (*)(); create_t mCreate; RecordType mType; }; -///Helper function for adding records to the factory map -static std::pair makeEntry(std::string recName, Record* (*create_t) (), RecordType type) -{ - RecordFactoryEntry anEntry = {create_t,type}; - return std::make_pair(recName, anEntry); -} - ///These are all the record types we know how to read. static std::map makeFactory() { - std::map newFactory; - newFactory.insert(makeEntry("NiNode", &construct , RC_NiNode )); - newFactory.insert(makeEntry("NiSwitchNode", &construct , RC_NiSwitchNode )); - newFactory.insert(makeEntry("NiLODNode", &construct , RC_NiLODNode )); - newFactory.insert(makeEntry("AvoidNode", &construct , RC_AvoidNode )); - newFactory.insert(makeEntry("NiCollisionSwitch", &construct , RC_NiCollisionSwitch )); - newFactory.insert(makeEntry("NiBSParticleNode", &construct , RC_NiBSParticleNode )); - newFactory.insert(makeEntry("NiBSAnimationNode", &construct , RC_NiBSAnimationNode )); - newFactory.insert(makeEntry("NiBillboardNode", &construct , RC_NiBillboardNode )); - newFactory.insert(makeEntry("NiTriShape", &construct , RC_NiTriShape )); - newFactory.insert(makeEntry("NiTriStrips", &construct , RC_NiTriStrips )); - newFactory.insert(makeEntry("NiLines", &construct , RC_NiLines )); - newFactory.insert(makeEntry("NiRotatingParticles", &construct , RC_NiRotatingParticles )); - newFactory.insert(makeEntry("NiAutoNormalParticles", &construct , RC_NiAutoNormalParticles )); - newFactory.insert(makeEntry("NiCamera", &construct , RC_NiCamera )); - newFactory.insert(makeEntry("RootCollisionNode", &construct , RC_RootCollisionNode )); - newFactory.insert(makeEntry("NiTexturingProperty", &construct , RC_NiTexturingProperty )); - newFactory.insert(makeEntry("NiFogProperty", &construct , RC_NiFogProperty )); - newFactory.insert(makeEntry("NiMaterialProperty", &construct , RC_NiMaterialProperty )); - newFactory.insert(makeEntry("NiZBufferProperty", &construct , RC_NiZBufferProperty )); - newFactory.insert(makeEntry("NiAlphaProperty", &construct , RC_NiAlphaProperty )); - newFactory.insert(makeEntry("NiVertexColorProperty", &construct , RC_NiVertexColorProperty )); - newFactory.insert(makeEntry("NiShadeProperty", &construct , RC_NiShadeProperty )); - newFactory.insert(makeEntry("NiDitherProperty", &construct , RC_NiDitherProperty )); - newFactory.insert(makeEntry("NiWireframeProperty", &construct , RC_NiWireframeProperty )); - newFactory.insert(makeEntry("NiSpecularProperty", &construct , RC_NiSpecularProperty )); - newFactory.insert(makeEntry("NiStencilProperty", &construct , RC_NiStencilProperty )); - newFactory.insert(makeEntry("NiVisController", &construct , RC_NiVisController )); - newFactory.insert(makeEntry("NiGeomMorpherController", &construct , RC_NiGeomMorpherController )); - newFactory.insert(makeEntry("NiKeyframeController", &construct , RC_NiKeyframeController )); - newFactory.insert(makeEntry("NiAlphaController", &construct , RC_NiAlphaController )); - newFactory.insert(makeEntry("NiRollController", &construct , RC_NiRollController )); - newFactory.insert(makeEntry("NiUVController", &construct , RC_NiUVController )); - newFactory.insert(makeEntry("NiPathController", &construct , RC_NiPathController )); - newFactory.insert(makeEntry("NiMaterialColorController", &construct , RC_NiMaterialColorController )); - newFactory.insert(makeEntry("NiBSPArrayController", &construct , RC_NiBSPArrayController )); - newFactory.insert(makeEntry("NiParticleSystemController", &construct , RC_NiParticleSystemController )); - newFactory.insert(makeEntry("NiFlipController", &construct , RC_NiFlipController )); - newFactory.insert(makeEntry("NiAmbientLight", &construct , RC_NiLight )); - newFactory.insert(makeEntry("NiDirectionalLight", &construct , RC_NiLight )); - newFactory.insert(makeEntry("NiPointLight", &construct , RC_NiLight )); - newFactory.insert(makeEntry("NiSpotLight", &construct , RC_NiLight )); - newFactory.insert(makeEntry("NiTextureEffect", &construct , RC_NiTextureEffect )); - newFactory.insert(makeEntry("NiVertWeightsExtraData", &construct , RC_NiVertWeightsExtraData )); - newFactory.insert(makeEntry("NiTextKeyExtraData", &construct , RC_NiTextKeyExtraData )); - newFactory.insert(makeEntry("NiStringExtraData", &construct , RC_NiStringExtraData )); - newFactory.insert(makeEntry("NiGravity", &construct , RC_NiGravity )); - newFactory.insert(makeEntry("NiPlanarCollider", &construct , RC_NiPlanarCollider )); - newFactory.insert(makeEntry("NiSphericalCollider", &construct , RC_NiSphericalCollider )); - newFactory.insert(makeEntry("NiParticleGrowFade", &construct , RC_NiParticleGrowFade )); - newFactory.insert(makeEntry("NiParticleColorModifier", &construct , RC_NiParticleColorModifier )); - newFactory.insert(makeEntry("NiParticleRotation", &construct , RC_NiParticleRotation )); - newFactory.insert(makeEntry("NiFloatData", &construct , RC_NiFloatData )); - newFactory.insert(makeEntry("NiTriShapeData", &construct , RC_NiTriShapeData )); - newFactory.insert(makeEntry("NiTriStripsData", &construct , RC_NiTriStripsData )); - newFactory.insert(makeEntry("NiLinesData", &construct , RC_NiLinesData )); - newFactory.insert(makeEntry("NiVisData", &construct , RC_NiVisData )); - newFactory.insert(makeEntry("NiColorData", &construct , RC_NiColorData )); - newFactory.insert(makeEntry("NiPixelData", &construct , RC_NiPixelData )); - newFactory.insert(makeEntry("NiMorphData", &construct , RC_NiMorphData )); - newFactory.insert(makeEntry("NiKeyframeData", &construct , RC_NiKeyframeData )); - newFactory.insert(makeEntry("NiSkinData", &construct , RC_NiSkinData )); - newFactory.insert(makeEntry("NiUVData", &construct , RC_NiUVData )); - newFactory.insert(makeEntry("NiPosData", &construct , RC_NiPosData )); - newFactory.insert(makeEntry("NiRotatingParticlesData", &construct , RC_NiRotatingParticlesData )); - newFactory.insert(makeEntry("NiAutoNormalParticlesData", &construct , RC_NiAutoNormalParticlesData )); - newFactory.insert(makeEntry("NiSequenceStreamHelper", &construct , RC_NiSequenceStreamHelper )); - newFactory.insert(makeEntry("NiSourceTexture", &construct , RC_NiSourceTexture )); - newFactory.insert(makeEntry("NiSkinInstance", &construct , RC_NiSkinInstance )); - newFactory.insert(makeEntry("NiLookAtController", &construct , RC_NiLookAtController )); - newFactory.insert(makeEntry("NiPalette", &construct , RC_NiPalette )); - return newFactory; + std::map factory; + factory["NiNode"] = {&construct , RC_NiNode }; + factory["NiSwitchNode"] = {&construct , RC_NiSwitchNode }; + factory["NiLODNode"] = {&construct , RC_NiLODNode }; + factory["AvoidNode"] = {&construct , RC_AvoidNode }; + factory["NiCollisionSwitch"] = {&construct , RC_NiCollisionSwitch }; + factory["NiBSParticleNode"] = {&construct , RC_NiBSParticleNode }; + factory["NiBSAnimationNode"] = {&construct , RC_NiBSAnimationNode }; + factory["NiBillboardNode"] = {&construct , RC_NiBillboardNode }; + factory["NiTriShape"] = {&construct , RC_NiTriShape }; + factory["NiTriStrips"] = {&construct , RC_NiTriStrips }; + factory["NiLines"] = {&construct , RC_NiLines }; + factory["NiRotatingParticles"] = {&construct , RC_NiRotatingParticles }; + factory["NiAutoNormalParticles"] = {&construct , RC_NiAutoNormalParticles }; + factory["NiCamera"] = {&construct , RC_NiCamera }; + factory["RootCollisionNode"] = {&construct , RC_RootCollisionNode }; + factory["NiTexturingProperty"] = {&construct , RC_NiTexturingProperty }; + factory["NiFogProperty"] = {&construct , RC_NiFogProperty }; + factory["NiMaterialProperty"] = {&construct , RC_NiMaterialProperty }; + factory["NiZBufferProperty"] = {&construct , RC_NiZBufferProperty }; + factory["NiAlphaProperty"] = {&construct , RC_NiAlphaProperty }; + factory["NiVertexColorProperty"] = {&construct , RC_NiVertexColorProperty }; + factory["NiShadeProperty"] = {&construct , RC_NiShadeProperty }; + factory["NiDitherProperty"] = {&construct , RC_NiDitherProperty }; + factory["NiWireframeProperty"] = {&construct , RC_NiWireframeProperty }; + factory["NiSpecularProperty"] = {&construct , RC_NiSpecularProperty }; + factory["NiStencilProperty"] = {&construct , RC_NiStencilProperty }; + factory["NiVisController"] = {&construct , RC_NiVisController }; + factory["NiGeomMorpherController"] = {&construct , RC_NiGeomMorpherController }; + factory["NiKeyframeController"] = {&construct , RC_NiKeyframeController }; + factory["NiAlphaController"] = {&construct , RC_NiAlphaController }; + factory["NiRollController"] = {&construct , RC_NiRollController }; + factory["NiUVController"] = {&construct , RC_NiUVController }; + factory["NiPathController"] = {&construct , RC_NiPathController }; + factory["NiMaterialColorController"] = {&construct , RC_NiMaterialColorController }; + factory["NiBSPArrayController"] = {&construct , RC_NiBSPArrayController }; + factory["NiParticleSystemController"] = {&construct , RC_NiParticleSystemController }; + factory["NiFlipController"] = {&construct , RC_NiFlipController }; + factory["NiAmbientLight"] = {&construct , RC_NiLight }; + factory["NiDirectionalLight"] = {&construct , RC_NiLight }; + factory["NiPointLight"] = {&construct , RC_NiLight }; + factory["NiSpotLight"] = {&construct , RC_NiLight }; + factory["NiTextureEffect"] = {&construct , RC_NiTextureEffect }; + factory["NiVertWeightsExtraData"] = {&construct , RC_NiVertWeightsExtraData }; + factory["NiTextKeyExtraData"] = {&construct , RC_NiTextKeyExtraData }; + factory["NiStringExtraData"] = {&construct , RC_NiStringExtraData }; + factory["NiGravity"] = {&construct , RC_NiGravity }; + factory["NiPlanarCollider"] = {&construct , RC_NiPlanarCollider }; + factory["NiSphericalCollider"] = {&construct , RC_NiSphericalCollider }; + factory["NiParticleGrowFade"] = {&construct , RC_NiParticleGrowFade }; + factory["NiParticleColorModifier"] = {&construct , RC_NiParticleColorModifier }; + factory["NiParticleRotation"] = {&construct , RC_NiParticleRotation }; + factory["NiFloatData"] = {&construct , RC_NiFloatData }; + factory["NiTriShapeData"] = {&construct , RC_NiTriShapeData }; + factory["NiTriStripsData"] = {&construct , RC_NiTriStripsData }; + factory["NiLinesData"] = {&construct , RC_NiLinesData }; + factory["NiVisData"] = {&construct , RC_NiVisData }; + factory["NiColorData"] = {&construct , RC_NiColorData }; + factory["NiPixelData"] = {&construct , RC_NiPixelData }; + factory["NiMorphData"] = {&construct , RC_NiMorphData }; + factory["NiKeyframeData"] = {&construct , RC_NiKeyframeData }; + factory["NiSkinData"] = {&construct , RC_NiSkinData }; + factory["NiUVData"] = {&construct , RC_NiUVData }; + factory["NiPosData"] = {&construct , RC_NiPosData }; + factory["NiRotatingParticlesData"] = {&construct , RC_NiRotatingParticlesData }; + factory["NiAutoNormalParticlesData"] = {&construct , RC_NiAutoNormalParticlesData }; + factory["NiSequenceStreamHelper"] = {&construct , RC_NiSequenceStreamHelper }; + factory["NiSourceTexture"] = {&construct , RC_NiSourceTexture }; + factory["NiSkinInstance"] = {&construct , RC_NiSkinInstance }; + factory["NiLookAtController"] = {&construct , RC_NiLookAtController }; + factory["NiPalette"] = {&construct , RC_NiPalette }; + factory["NiIntegerExtraData"] = {&construct , RC_NiIntegerExtraData }; + factory["NiIntegersExtraData"] = {&construct , RC_NiIntegersExtraData }; + factory["NiBinaryExtraData"] = {&construct , RC_NiBinaryExtraData }; + factory["NiBooleanExtraData"] = {&construct , RC_NiBooleanExtraData }; + factory["NiVectorExtraData"] = {&construct , RC_NiVectorExtraData }; + factory["NiColorExtraData"] = {&construct , RC_NiColorExtraData }; + factory["NiFloatExtraData"] = {&construct , RC_NiFloatExtraData }; + factory["NiFloatsExtraData"] = {&construct , RC_NiFloatsExtraData }; + return factory; } - ///Make the factory map used for parsing the file static const std::map factories = makeFactory(); @@ -148,15 +146,77 @@ void NIFFile::parse(Files::IStreamPtr stream) // It's not used by Morrowind assets but Morrowind supports it. if(ver != NIFStream::generateVersion(4,0,0,0) && ver != VER_MW) fail("Unsupported NIF version: " + printVersion(ver)); + + // NIF data endianness + if (ver >= NIFStream::generateVersion(20,0,0,4)) + { + unsigned char endianness = nif.getChar(); + if (endianness == 0) + fail("Big endian NIF files are unsupported"); + } + + // User version + if (ver > NIFStream::generateVersion(10,0,1,8)) + userVer = nif.getUInt(); + // Number of records - size_t recNum = nif.getInt(); + size_t recNum = nif.getUInt(); records.resize(recNum); + // Bethesda stream header + // It contains Bethesda format version and (useless) export information + if (ver == VER_OB_OLD || + (userVer >= 3 && ((ver == VER_OB || ver == VER_BGS) + || (ver >= NIFStream::generateVersion(10,1,0,0) && ver <= NIFStream::generateVersion(20,0,0,4) && userVer <= 11)))) + { + bethVer = nif.getUInt(); + nif.getExportString(); // Author + if (bethVer > BETHVER_FO4) + nif.getUInt(); // Unknown + nif.getExportString(); // Process script + nif.getExportString(); // Export script + if (bethVer == BETHVER_FO4) + nif.getExportString(); // Max file path + } + + std::vector recTypes; + std::vector recTypeIndices; + + const bool hasRecTypeListings = ver >= NIFStream::generateVersion(5,0,0,1); + if (hasRecTypeListings) + { + unsigned short recTypeNum = nif.getUShort(); + if (recTypeNum) // Record type list + nif.getSizedStrings(recTypes, recTypeNum); + if (recNum) // Record type mapping for each record + nif.getUShorts(recTypeIndices, recNum); + if (ver >= NIFStream::generateVersion(5,0,0,6)) // Groups + { + if (ver >= NIFStream::generateVersion(20,1,0,1)) // String table + { + if (ver >= NIFStream::generateVersion(20,2,0,5) && recNum) // Record sizes + { + std::vector recSizes; // Currently unused + nif.getUInts(recSizes, recNum); + } + unsigned int stringNum = nif.getUInt(); + nif.getUInt(); // Max string length + if (stringNum) + nif.getSizedStrings(strings, stringNum); + } + std::vector groups; // Currently unused + unsigned int groupNum = nif.getUInt(); + if (groupNum) + nif.getUInts(groups, groupNum); + } + } + + const bool hasRecordSeparators = ver >= NIFStream::generateVersion(10,0,0,0) && ver < NIFStream::generateVersion(10,2,0,0); for(size_t i = 0;i < recNum;i++) { Record *r = nullptr; - std::string rec = nif.getString(); + std::string rec = hasRecTypeListings ? recTypes[recTypeIndices[i]] : nif.getString(); if(rec.empty()) { std::stringstream error; @@ -164,6 +224,17 @@ void NIFFile::parse(Files::IStreamPtr stream) fail(error.str()); } + // Record separator. Some Havok records in Oblivion do not have it. + if (hasRecordSeparators && rec.compare(0, 3, "bhk")) + { + if (nif.getInt()) + { + std::stringstream warning; + warning << "Record number " << i << " out of " << recNum << " is preceded by a non-zero separator."; + warn(warning.str()); + } + } + std::map::const_iterator entry = factories.find(rec); if (entry != factories.end()) @@ -201,8 +272,8 @@ void NIFFile::parse(Files::IStreamPtr stream) } // Once parsing is done, do post-processing. - for(size_t i=0; ipost(this); + for (Record* record : records) + record->post(this); } void NIFFile::setUseSkinning(bool skinning) diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index 333d8a7cf..4c10327e1 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -26,11 +26,11 @@ enum InterpolationType template struct KeyT { T mValue; + T mInTan; // Only for Quadratic interpolation, and never for QuaternionKeyList + T mOutTan; // Only for Quadratic interpolation, and never for QuaternionKeyList - // FIXME: Implement Quadratic and TBC interpolation + // FIXME: Implement TBC interpolation /* - T mForwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList - T mBackwardValue; // Only for Quadratic interpolation, and never for QuaternionKeyList float mTension; // Only for TBC interpolation float mBias; // Only for TBC interpolation float mContinuity; // Only for TBC interpolation @@ -136,8 +136,8 @@ private: static void readQuadratic(NIFStream &nif, KeyT &key) { readValue(nif, key); - /*key.mForwardValue = */(nif.*getValue)(); - /*key.mBackwardValue = */(nif.*getValue)(); + key.mInTan = (nif.*getValue)(); + key.mOutTan = (nif.*getValue)(); } static void readQuadratic(NIFStream &nif, KeyT &key) diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index 44be4b241..69f1a905b 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -25,18 +25,19 @@ namespace Nif return t; } - ///Currently specific for 4.0.0.2 and earlier + ///Booleans in 4.0.0.2 (Morrowind format) and earlier are 4 byte, while in 4.1.0.0+ they're 1 byte. bool NIFStream::getBoolean() { - return getInt() != 0; + return getVersion() < generateVersion(4,1,0,0) ? getInt() != 0 : getChar() != 0; } - ///Read in a string, either from the string table using the index (currently absent) or from the stream using the specified length + ///Read in a string, either from the string table using the index or from the stream using the specified length std::string NIFStream::getString() { - return getSizedString(); + return getVersion() < generateVersion(20,1,0,1) ? getSizedString() : file->getString(getUInt()); } + // Convenience utility functions: get the versions of the currently read file unsigned int NIFStream::getVersion() const { return file->getVersion(); } unsigned int NIFStream::getUserVersion() const { return file->getBethVersion(); } diff --git a/components/nif/node.hpp b/components/nif/node.hpp index e605df32a..72adfe06c 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -30,21 +30,24 @@ public: PropertyList props; // Bounding box info - bool hasBounds; + bool hasBounds{false}; osg::Vec3f boundPos; Matrix3 boundRot; osg::Vec3f boundXYZ; // Box size - void read(NIFStream *nif) + void read(NIFStream *nif) override { Named::read(nif); - flags = nif->getUShort(); + flags = nif->getBethVersion() <= 26 ? nif->getUShort() : nif->getUInt(); trafo = nif->getTrafo(); - velocity = nif->getVector3(); - props.read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0)) + velocity = nif->getVector3(); + if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) + props.read(nif); - hasBounds = nif->getBoolean(); + if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0)) + hasBounds = nif->getBoolean(); if(hasBounds) { nif->getInt(); // always 1 @@ -52,13 +55,16 @@ public: boundRot = nif->getMatrix3(); boundXYZ = nif->getVector3(); } + // Reference to the collision object in Gamebryo files. + if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0)) + nif->skip(4); parent = nullptr; isBone = false; } - void post(NIFFile *nif) + void post(NIFFile *nif) override { Named::post(nif); props.post(nif); @@ -98,11 +104,12 @@ struct NiNode : Node ControllerFlag_Active = 0x8 }; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); children.read(nif); - effects.read(nif); + if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4) + effects.read(nif); // Discard transformations for the root node, otherwise some meshes // occasionally get wrong orientation. Only for NiNode-s for now, but @@ -113,7 +120,7 @@ struct NiNode : Node } } - void post(NIFFile *nif) + void post(NIFFile *nif) override { Node::post(nif); children.post(nif); @@ -130,7 +137,39 @@ struct NiNode : Node struct NiGeometry : Node { + struct MaterialData + { + std::vector materialNames; + std::vector materialExtraData; + unsigned int activeMaterial{0}; + bool materialNeedsUpdate{false}; + void read(NIFStream *nif) + { + if (nif->getVersion() <= NIFStream::generateVersion(10,0,1,0)) + return; + unsigned int numMaterials = 0; + if (nif->getVersion() <= NIFStream::generateVersion(20,1,0,3)) + numMaterials = nif->getBoolean(); // Has Shader + else if (nif->getVersion() >= NIFStream::generateVersion(20,2,0,5)) + numMaterials = nif->getUInt(); + if (numMaterials) + { + nif->getStrings(materialNames, numMaterials); + nif->getInts(materialExtraData, numMaterials); + } + if (nif->getVersion() >= NIFStream::generateVersion(20,2,0,5)) + activeMaterial = nif->getUInt(); + if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS) + { + materialNeedsUpdate = nif->getBoolean(); + if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3) + nif->skip(8); + } + } + }; + NiSkinInstancePtr skin; + MaterialData materialData; }; struct NiTriShape : NiGeometry @@ -144,14 +183,15 @@ struct NiTriShape : NiGeometry NiTriShapeDataPtr data; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); data.read(nif); skin.read(nif); + materialData.read(nif); } - void post(NIFFile *nif) + void post(NIFFile *nif) override { Node::post(nif); data.post(nif); @@ -165,14 +205,15 @@ struct NiTriStrips : NiGeometry { NiTriStripsDataPtr data; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); data.read(nif); skin.read(nif); + materialData.read(nif); } - void post(NIFFile *nif) + void post(NIFFile *nif) override { Node::post(nif); data.post(nif); @@ -186,14 +227,14 @@ struct NiLines : NiGeometry { NiLinesDataPtr data; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); data.read(nif); skin.read(nif); } - void post(NIFFile *nif) + void post(NIFFile *nif) override { Node::post(nif); data.post(nif); @@ -207,6 +248,8 @@ struct NiCamera : Node { struct Camera { + unsigned short cameraFlags{0}; + // Camera frustrum float left, right, top, bottom, nearDist, farDist; @@ -216,15 +259,21 @@ struct NiCamera : Node // Level of detail modifier float LOD; + // Orthographic projection usage flag + bool orthographic{false}; + void read(NIFStream *nif) { + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + cameraFlags = nif->getUShort(); left = nif->getFloat(); right = nif->getFloat(); top = nif->getFloat(); bottom = nif->getFloat(); nearDist = nif->getFloat(); farDist = nif->getFloat(); - + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + orthographic = nif->getBoolean(); vleft = nif->getFloat(); vright = nif->getFloat(); vtop = nif->getFloat(); @@ -235,7 +284,7 @@ struct NiCamera : Node }; Camera cam; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); @@ -243,6 +292,8 @@ struct NiCamera : Node nif->getInt(); // -1 nif->getInt(); // 0 + if (nif->getVersion() >= NIFStream::generateVersion(4,2,1,0)) + nif->getInt(); // 0 } }; @@ -250,14 +301,14 @@ struct NiAutoNormalParticles : Node { NiAutoNormalParticlesDataPtr data; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); data.read(nif); nif->getInt(); // -1 } - void post(NIFFile *nif) + void post(NIFFile *nif) override { Node::post(nif); data.post(nif); @@ -268,14 +319,14 @@ struct NiRotatingParticles : Node { NiRotatingParticlesDataPtr data; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Node::read(nif); data.read(nif); nif->getInt(); // -1 } - void post(NIFFile *nif) + void post(NIFFile *nif) override { Node::post(nif); data.post(nif); @@ -285,11 +336,14 @@ struct NiRotatingParticles : Node // A node used as the base to switch between child nodes, such as for LOD levels. struct NiSwitchNode : public NiNode { + unsigned int switchFlags{0}; unsigned int initialIndex; - void read(NIFStream *nif) + void read(NIFStream *nif) override { NiNode::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + switchFlags = nif->getUShort(); initialIndex = nif->getUInt(); } }; @@ -305,11 +359,17 @@ struct NiLODNode : public NiSwitchNode }; std::vector lodLevels; - void read(NIFStream *nif) + void read(NIFStream *nif) override { NiSwitchNode::read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFStream::generateVersion(10,0,1,0)) lodCenter = nif->getVector3(); + else if (nif->getVersion() > NIFStream::generateVersion(10,0,1,0)) + { + nif->skip(4); // NiLODData, unsupported at the moment + return; + } + unsigned int numLodLevels = nif->getUInt(); for (unsigned int i=0; igetUShort(); -} - void NiTexturingProperty::Texture::read(NIFStream *nif) { inUse = nif->getBoolean(); if(!inUse) return; texture.read(nif); - clamp = nif->getUInt(); - nif->skip(4); // Filter mode. Ignoring because global filtering settings are more sensible - uvSet = nif->getUInt(); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + clamp = nif->getInt(); + nif->skip(4); // Filter mode. Ignoring because global filtering settings are more sensible + } + else + { + clamp = nif->getUShort() & 0xF; + } + // Max anisotropy. I assume we'll always only use the global anisotropy setting. + if (nif->getVersion() >= NIFStream::generateVersion(20,5,0,4)) + nif->getUShort(); + + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + uvSet = nif->getUInt(); // Two PS2-specific shorts. - nif->skip(4); - nif->skip(2); // Unknown short + if (nif->getVersion() < NIFStream::generateVersion(10,4,0,2)) + nif->skip(4); + if (nif->getVersion() <= NIFStream::generateVersion(4,1,0,18)) + nif->skip(2); // Unknown short + else if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + { + if (nif->getBoolean()) // Has texture transform + { + nif->getVector2(); // UV translation + nif->getVector2(); // UV scale + nif->getFloat(); // W axis rotation + nif->getUInt(); // Transform method + nif->getVector2(); // Texture rotation origin + } + } } void NiTexturingProperty::Texture::post(NIFFile *nif) @@ -35,7 +54,10 @@ void NiTexturingProperty::Texture::post(NIFFile *nif) void NiTexturingProperty::read(NIFStream *nif) { Property::read(nif); - apply = nif->getUInt(); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD || nif->getVersion() >= NIFStream::generateVersion(20,1,0,2)) + flags = nif->getUShort(); + if (nif->getVersion() <= NIFStream::generateVersion(20,1,0,1)) + apply = nif->getUInt(); unsigned int numTextures = nif->getUInt(); @@ -51,32 +73,53 @@ void NiTexturingProperty::read(NIFStream *nif) envMapLumaBias = nif->getVector2(); bumpMapMatrix = nif->getVector4(); } + else if (i == 7 && textures[7].inUse && nif->getVersion() >= NIFStream::generateVersion(20,2,0,5)) + /*float parallaxOffset = */nif->getFloat(); + } + + if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0)) + { + unsigned int numShaderTextures = nif->getUInt(); + shaderTextures.resize(numShaderTextures); + for (unsigned int i = 0; i < numShaderTextures; i++) + { + shaderTextures[i].read(nif); + if (shaderTextures[i].inUse) + nif->getUInt(); // Unique identifier + } } } void NiTexturingProperty::post(NIFFile *nif) { Property::post(nif); - for(int i = 0;i < 7;i++) + for (size_t i = 0; i < textures.size(); i++) textures[i].post(nif); + for (size_t i = 0; i < shaderTextures.size(); i++) + shaderTextures[i].post(nif); } void NiFogProperty::read(NIFStream *nif) { Property::read(nif); - + mFlags = nif->getUShort(); mFogDepth = nif->getFloat(); mColour = nif->getVector3(); } void S_MaterialProperty::read(NIFStream *nif) { - ambient = nif->getVector3(); - diffuse = nif->getVector3(); + if (nif->getBethVersion() < 26) + { + ambient = nif->getVector3(); + diffuse = nif->getVector3(); + } specular = nif->getVector3(); emissive = nif->getVector3(); glossiness = nif->getFloat(); alpha = nif->getFloat(); + if (nif->getBethVersion() > 21) + emissive *= nif->getFloat(); } void S_VertexColorProperty::read(NIFStream *nif) @@ -92,14 +135,29 @@ void S_AlphaProperty::read(NIFStream *nif) void S_StencilProperty::read(NIFStream *nif) { - enabled = nif->getChar(); - compareFunc = nif->getInt(); - stencilRef = nif->getUInt(); - stencilMask = nif->getUInt(); - failAction = nif->getInt(); - zFailAction = nif->getInt(); - zPassAction = nif->getInt(); - drawMode = nif->getInt(); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + enabled = nif->getChar(); + compareFunc = nif->getInt(); + stencilRef = nif->getUInt(); + stencilMask = nif->getUInt(); + failAction = nif->getInt(); + zFailAction = nif->getInt(); + zPassAction = nif->getInt(); + drawMode = nif->getInt(); + } + else + { + unsigned short flags = nif->getUShort(); + enabled = flags & 0x1; + failAction = (flags >> 1) & 0x7; + zFailAction = (flags >> 4) & 0x7; + zPassAction = (flags >> 7) & 0x7; + drawMode = (flags >> 10) & 0x3; + compareFunc = (flags >> 12) & 0x7; + stencilRef = nif->getUInt(); + stencilMask = nif->getUInt(); + } } diff --git a/components/nif/property.hpp b/components/nif/property.hpp index c72dbf6ba..c821b7c37 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -29,18 +29,13 @@ namespace Nif { -class Property : public Named -{ -public: - // The meaning of these depends on the actual property type. - unsigned int flags; - - void read(NIFStream *nif); -}; +class Property : public Named { }; class NiTexturingProperty : public Property { public: + unsigned short flags{0u}; + // A sub-texture struct Texture { @@ -92,39 +87,92 @@ public: }; std::vector textures; + std::vector shaderTextures; osg::Vec2f envMapLumaBias; osg::Vec4f bumpMapMatrix; - void read(NIFStream *nif); - void post(NIFFile *nif); + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; }; class NiFogProperty : public Property { public: + unsigned short mFlags; float mFogDepth; osg::Vec3f mColour; - void read(NIFStream *nif); + void read(NIFStream *nif) override; }; -// These contain no other data than the 'flags' field in Property -class NiShadeProperty : public Property { }; -class NiDitherProperty : public Property { }; -class NiZBufferProperty : public Property { }; -class NiSpecularProperty : public Property { }; -class NiWireframeProperty : public Property { }; +// These contain no other data than the 'flags' field +struct NiShadeProperty : public Property +{ + unsigned short flags{0u}; + void read(NIFStream *nif) override + { + Property::read(nif); + if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) + flags = nif->getUShort(); + } +}; + +struct NiDitherProperty : public Property +{ + unsigned short flags; + void read(NIFStream* nif) override + { + Property::read(nif); + flags = nif->getUShort(); + } +}; + +struct NiZBufferProperty : public Property +{ + unsigned short flags; + unsigned int testFunction; + void read(NIFStream *nif) override + { + Property::read(nif); + flags = nif->getUShort(); + testFunction = (flags >> 2) & 0x7; + if (nif->getVersion() >= NIFStream::generateVersion(4,1,0,12) && nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + testFunction = nif->getUInt(); + } +}; + +struct NiSpecularProperty : public Property +{ + unsigned short flags; + void read(NIFStream* nif) override + { + Property::read(nif); + flags = nif->getUShort(); + } +}; + +struct NiWireframeProperty : public Property +{ + unsigned short flags; + void read(NIFStream* nif) override + { + Property::read(nif); + flags = nif->getUShort(); + } +}; // The rest are all struct-based template struct StructPropT : Property { T data; + unsigned short flags; - void read(NIFStream *nif) + void read(NIFStream *nif) override { Property::read(nif); + flags = nif->getUShort(); data.read(nif); } }; @@ -132,7 +180,8 @@ struct StructPropT : Property struct S_MaterialProperty { // The vector components are R,G,B - osg::Vec3f ambient, diffuse, specular, emissive; + osg::Vec3f ambient{1.f,1.f,1.f}, diffuse{1.f,1.f,1.f}; + osg::Vec3f specular, emissive; float glossiness, alpha; void read(NIFStream *nif); @@ -246,9 +295,35 @@ struct S_StencilProperty }; class NiAlphaProperty : public StructPropT { }; -class NiMaterialProperty : public StructPropT { }; class NiVertexColorProperty : public StructPropT { }; -class NiStencilProperty : public StructPropT { }; +struct NiStencilProperty : public Property +{ + S_StencilProperty data; + unsigned short flags{0u}; + + void read(NIFStream *nif) override + { + Property::read(nif); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD) + flags = nif->getUShort(); + data.read(nif); + } +}; + +struct NiMaterialProperty : public Property +{ + S_MaterialProperty data; + unsigned short flags{0u}; + + void read(NIFStream *nif) override + { + Property::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(3,0,0,0) + && nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD) + flags = nif->getUShort(); + data.read(nif); + } +}; } // Namespace #endif diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 67202d2fe..f9bb613a0 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -101,7 +101,15 @@ enum RecordType RC_RootCollisionNode, RC_NiSphericalCollider, RC_NiLookAtController, - RC_NiPalette + RC_NiPalette, + RC_NiIntegerExtraData, + RC_NiIntegersExtraData, + RC_NiBinaryExtraData, + RC_NiBooleanExtraData, + RC_NiVectorExtraData, + RC_NiColorExtraData, + RC_NiFloatExtraData, + RC_NiFloatsExtraData }; /// Base class for all records diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 3c95394a6..0f4c4a5bd 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -4,14 +4,13 @@ #include #include #include -#include #include #include #include -#include "userdata.hpp" +#include "matrixtransform.hpp" namespace NifOsg { @@ -119,13 +118,12 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv) { if (hasInput()) { - osg::MatrixTransform* trans = static_cast(node); + NifOsg::MatrixTransform* trans = static_cast(node); osg::Matrix mat = trans->getMatrix(); float time = getInputValue(nv); - NodeUserData* userdata = static_cast(trans->getUserDataContainer()->getUserObject(0)); - Nif::Matrix3& rot = userdata->mRotationScale; + Nif::Matrix3& rot = trans->mRotationScale; bool setRot = false; if(!mRotations.empty()) @@ -140,18 +138,18 @@ void KeyframeController::operator() (osg::Node* node, osg::NodeVisitor* nv) } else { - // no rotation specified, use the previous value from the UserData + // no rotation specified, use the previous value for (int i=0;i<3;++i) for (int j=0;j<3;++j) mat(j,i) = rot.mValues[i][j]; // NB column/row major difference } - if (setRot) // copy the new values back to the UserData + if (setRot) // copy the new values back for (int i=0;i<3;++i) for (int j=0;j<3;++j) rot.mValues[i][j] = mat(j,i); // NB column/row major difference - float& scale = userdata->mScale; + float& scale = trans->mScale; if(!mScales.empty()) scale = mScales.interpKey(time); @@ -199,7 +197,6 @@ void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable float val = 0; if (!(*it).empty()) val = it->interpKey(input); - val = std::max(0.f, std::min(1.f, val)); SceneUtil::MorphGeometry::MorphTarget& target = morphGeom->getMorphTarget(i); if (target.getWeight() != val) @@ -313,11 +310,6 @@ void VisController::operator() (osg::Node* node, osg::NodeVisitor* nv) RollController::RollController(const Nif::NiFloatData *data) : mData(data->mKeyList, 1.f) - , mStartingTime(0) -{ -} - -RollController::RollController() : mStartingTime(0) { } @@ -325,7 +317,7 @@ RollController::RollController(const RollController ©, const osg::CopyOp &co : osg::NodeCallback(copy, copyop) , Controller(copy) , mData(copy.mData) - , mStartingTime(0) + , mStartingTime(copy.mStartingTime) { } @@ -452,7 +444,7 @@ void MaterialColorController::apply(osg::StateSet *stateset, osg::NodeVisitor *n } FlipController::FlipController(const Nif::NiFlipController *ctrl, const std::vector >& textures) - : mTexSlot(ctrl->mTexSlot) + : mTexSlot(0) // always affects diffuse , mDelta(ctrl->mDelta) , mTextures(textures) { @@ -465,12 +457,6 @@ FlipController::FlipController(int texSlot, float delta, const std::vector #include -#include //UVController +#include -// FlipController #include -#include #include #include @@ -22,8 +20,6 @@ namespace osg { - class Node; - class StateSet; class Material; } @@ -114,6 +110,24 @@ namespace NifOsg { case Nif::InterpolationType_Constant: return fraction > 0.5f ? b.mValue : a.mValue; + case Nif::InterpolationType_Quadratic: + { + // Using a cubic Hermite spline. + // b1(t) = 2t^3 - 3t^2 + 1 + // b2(t) = -2t^3 + 3t^2 + // b3(t) = t^3 - 2t^2 + t + // b4(t) = t^3 - t^2 + // f(t) = a.mValue * b1(t) + b.mValue * b2(t) + a.mOutTan * b3(t) + b.mInTan * b4(t) + const float t = fraction; + const float t2 = t * t; + const float t3 = t2 * t; + const float b1 = 2.f * t3 - 3.f * t2 + 1; + const float b2 = -2.f * t3 + 3.f * t2; + const float b3 = t3 - 2.f * t2 + t; + const float b4 = t3 - t2; + return a.mValue * b1 + b.mValue * b2 + a.mOutTan * b3 + b.mInTan * b4; + } + // TODO: Implement TBC interpolation default: return a.mValue + ((b.mValue - a.mValue) * fraction); } @@ -124,6 +138,7 @@ namespace NifOsg { case Nif::InterpolationType_Constant: return fraction > 0.5f ? b.mValue : a.mValue; + // TODO: Implement Quadratic and TBC interpolation default: { osg::Quat result; @@ -164,9 +179,9 @@ namespace NifOsg public: ControllerFunction(const Nif::Controller *ctrl); - float calculate(float value) const; + float calculate(float value) const override; - virtual float getMaximum() const; + float getMaximum() const override; }; /// Must be set on a SceneUtil::MorphGeometry. @@ -179,7 +194,7 @@ namespace NifOsg META_Object(NifOsg, GeomMorpherController) - virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable); + void update(osg::NodeVisitor* nv, osg::Drawable* drawable) override; private: std::vector mKeyFrames; @@ -196,7 +211,7 @@ namespace NifOsg virtual osg::Vec3f getTranslation(float time) const; - virtual void operator() (osg::Node*, osg::NodeVisitor*); + void operator() (osg::Node*, osg::NodeVisitor*) override; private: QuaternionInterpolator mRotations; @@ -220,8 +235,8 @@ namespace NifOsg META_Object(NifOsg,UVController) - virtual void setDefaults(osg::StateSet* stateset); - virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv); + void setDefaults(osg::StateSet* stateset) override; + void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) override; private: FloatInterpolator mUTrans; @@ -246,21 +261,21 @@ namespace NifOsg META_Object(NifOsg, VisController) - virtual void operator() (osg::Node* node, osg::NodeVisitor* nv); + void operator() (osg::Node* node, osg::NodeVisitor* nv) override; }; class RollController : public osg::NodeCallback, public SceneUtil::Controller { private: FloatInterpolator mData; - double mStartingTime; + double mStartingTime{0}; public: RollController(const Nif::NiFloatData *data); - RollController(); + RollController() = default; RollController(const RollController& copy, const osg::CopyOp& copyop); - virtual void operator() (osg::Node* node, osg::NodeVisitor* nv); + void operator() (osg::Node* node, osg::NodeVisitor* nv) override; META_Object(NifOsg, RollController) }; @@ -275,9 +290,9 @@ namespace NifOsg AlphaController(); AlphaController(const AlphaController& copy, const osg::CopyOp& copyop); - virtual void setDefaults(osg::StateSet* stateset); + void setDefaults(osg::StateSet* stateset) override; - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv); + void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override; META_Object(NifOsg, AlphaController) }; @@ -298,9 +313,9 @@ namespace NifOsg META_Object(NifOsg, MaterialColorController) - virtual void setDefaults(osg::StateSet* stateset); + void setDefaults(osg::StateSet* stateset) override; - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv); + void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override; private: Vec3Interpolator mData; @@ -311,21 +326,21 @@ namespace NifOsg class FlipController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller { private: - int mTexSlot; - float mDelta; + int mTexSlot{0}; + float mDelta{0.f}; std::vector > mTextures; public: FlipController(const Nif::NiFlipController* ctrl, const std::vector >& textures); FlipController(int texSlot, float delta, const std::vector >& textures); - FlipController(); + FlipController() = default; FlipController(const FlipController& copy, const osg::CopyOp& copyop); META_Object(NifOsg, FlipController) std::vector >& getTextures() { return mTextures; } - virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv); + void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) override; }; class ParticleSystemController : public osg::NodeCallback, public SceneUtil::Controller @@ -337,7 +352,7 @@ namespace NifOsg META_Object(NifOsg, ParticleSystemController) - virtual void operator() (osg::Node* node, osg::NodeVisitor* nv); + void operator() (osg::Node* node, osg::NodeVisitor* nv) override; private: float mEmitStart; @@ -353,7 +368,7 @@ namespace NifOsg META_Object(NifOsg, PathController) - virtual void operator() (osg::Node*, osg::NodeVisitor*); + void operator() (osg::Node*, osg::NodeVisitor*) override; private: Vec3Interpolator mPath; diff --git a/components/nifosg/matrixtransform.cpp b/components/nifosg/matrixtransform.cpp new file mode 100644 index 000000000..bc461b9c1 --- /dev/null +++ b/components/nifosg/matrixtransform.cpp @@ -0,0 +1,23 @@ +#include "matrixtransform.hpp" + +namespace NifOsg +{ + MatrixTransform::MatrixTransform() + : osg::MatrixTransform() + { + } + + MatrixTransform::MatrixTransform(const Nif::Transformation &trafo) + : osg::MatrixTransform(trafo.toMatrix()) + , mScale(trafo.scale) + , mRotationScale(trafo.rotation) + { + } + + MatrixTransform::MatrixTransform(const MatrixTransform ©, const osg::CopyOp ©op) + : osg::MatrixTransform(copy, copyop) + , mScale(copy.mScale) + , mRotationScale(copy.mRotationScale) + { + } +} diff --git a/components/nifosg/matrixtransform.hpp b/components/nifosg/matrixtransform.hpp new file mode 100644 index 000000000..975f71c62 --- /dev/null +++ b/components/nifosg/matrixtransform.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_COMPONENTS_NIFOSG_MATRIXTRANSFORM_H +#define OPENMW_COMPONENTS_NIFOSG_MATRIXTRANSFORM_H + +#include + +#include + +namespace NifOsg +{ + + class MatrixTransform : public osg::MatrixTransform + { + public: + MatrixTransform(); + MatrixTransform(const Nif::Transformation &trafo); + MatrixTransform(const MatrixTransform ©, const osg::CopyOp ©op); + + META_Node(NifOsg, MatrixTransform) + + // Hack: account for Transform differences between OSG and NIFs. + // OSG uses a 4x4 matrix, NIF's use a 3x3 rotationScale, float scale, and vec3 position. + // Decomposing the original components from the 4x4 matrix isn't possible, which causes + // problems when a KeyframeController wants to change only one of these components. So + // we store the scale and rotation components separately here. + float mScale{0.f}; + Nif::Matrix3 mRotationScale; + }; + +} + +#endif diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 8266b5e01..65f62346d 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -43,8 +42,9 @@ #include #include +#include "matrixtransform.hpp" +#include "nodeindexholder.hpp" #include "particle.hpp" -#include "userdata.hpp" namespace { @@ -102,7 +102,7 @@ namespace META_Object(NifOsg, BillboardCallback) - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgUtil::CullVisitor* cv = static_cast(nv); @@ -170,31 +170,6 @@ namespace namespace NifOsg { - class CollisionSwitch : public osg::MatrixTransform - { - public: - CollisionSwitch() : osg::MatrixTransform() - { - } - - CollisionSwitch(const CollisionSwitch& copy, const osg::CopyOp& copyop) - : osg::MatrixTransform(copy, copyop) - { - } - - META_Node(NifOsg, CollisionSwitch) - - CollisionSwitch(const osg::Matrixf& transformations, bool enabled) : osg::MatrixTransform(transformations) - { - setEnabled(enabled); - } - - void setEnabled(bool enabled) - { - setNodeMask(enabled ? ~0 : Loader::getIntersectionDisabledNodeMask()); - } - }; - bool Loader::sShowMarkers = false; void Loader::setShowMarkers(bool show) @@ -501,14 +476,6 @@ namespace NifOsg case Nif::RC_NiBillboardNode: dataVariance = osg::Object::DYNAMIC; break; - case Nif::RC_NiCollisionSwitch: - { - bool enabled = nifNode->flags & Nif::NiNode::Flag_ActiveCollision; - node = new CollisionSwitch(nifNode->trafo.toMatrix(), enabled); - // This matrix transform must not be combined with another matrix transform. - dataVariance = osg::Object::DYNAMIC; - break; - } default: // The Root node can be created as a Group if no transformation is required. // This takes advantage of the fact root nodes can't have additional controllers @@ -521,7 +488,14 @@ namespace NifOsg break; } if (!node) - node = new osg::MatrixTransform(nifNode->trafo.toMatrix()); + node = new NifOsg::MatrixTransform(nifNode->trafo); + + if (nifNode->recType == Nif::RC_NiCollisionSwitch && !(nifNode->flags & Nif::NiNode::Flag_ActiveCollision)) + { + node->setNodeMask(Loader::getIntersectionDisabledNodeMask()); + // This node must not be combined with another node. + dataVariance = osg::Object::DYNAMIC; + } node->setDataVariance(dataVariance); @@ -549,14 +523,11 @@ namespace NifOsg if (!rootNode) rootNode = node; - // UserData used for a variety of features: + // The original NIF record index is used for a variety of features: // - finding the correct emitter node for a particle system // - establishing connections to the animated collision shapes, which are handled in a separate loader // - finding a random child NiNode in NiBspArrayController - // - storing the previous 3x3 rotation and scale values for when a KeyframeController wants to - // change only certain elements of the 4x4 transform - node->getOrCreateUserDataContainer()->addUserObject( - new NodeUserData(nifNode->recIndex, nifNode->trafo.scale, nifNode->trafo.rotation)); + node->getOrCreateUserDataContainer()->addUserObject(new NodeIndexHolder(nifNode->recIndex)); for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next) { @@ -654,8 +625,8 @@ namespace NifOsg bool isAnimated = false; handleNodeControllers(nifNode, node, animflags, isAnimated); hasAnimatedParents |= isAnimated; - // Make sure empty nodes are not optimized away so the physics system can find them. - if (isAnimated || (hasAnimatedParents && (skipMeshes || hasMarkers))) + // Make sure empty nodes and animated shapes are not optimized away so the physics system can find them. + if (isAnimated || (hasAnimatedParents && ((skipMeshes || hasMarkers) || isGeometry))) node->setDataVariance(osg::Object::DYNAMIC); // LOD and Switch nodes must be wrapped by a transform (the current node) to support transformations properly @@ -828,22 +799,23 @@ namespace NifOsg { const Nif::NiFlipController* flipctrl = static_cast(ctrl.getPtr()); std::vector > textures; + + // inherit wrap settings from the target slot + osg::Texture2D* inherit = dynamic_cast(stateset->getTextureAttribute(0, osg::StateAttribute::TEXTURE)); + osg::Texture2D::WrapMode wrapS = osg::Texture2D::REPEAT; + osg::Texture2D::WrapMode wrapT = osg::Texture2D::REPEAT; + if (inherit) + { + wrapS = inherit->getWrap(osg::Texture2D::WRAP_S); + wrapT = inherit->getWrap(osg::Texture2D::WRAP_T); + } + for (unsigned int i=0; imSources.length(); ++i) { Nif::NiSourceTexturePtr st = flipctrl->mSources[i]; if (st.empty()) continue; - // inherit wrap settings from the target slot - osg::Texture2D* inherit = dynamic_cast(stateset->getTextureAttribute(flipctrl->mTexSlot, osg::StateAttribute::TEXTURE)); - osg::Texture2D::WrapMode wrapS = osg::Texture2D::CLAMP_TO_EDGE; - osg::Texture2D::WrapMode wrapT = osg::Texture2D::CLAMP_TO_EDGE; - if (inherit) - { - wrapS = inherit->getWrap(osg::Texture2D::WRAP_S); - wrapT = inherit->getWrap(osg::Texture2D::WRAP_T); - } - osg::ref_ptr image (handleSourceTexture(st.getPtr(), imageManager)); osg::ref_ptr texture (new osg::Texture2D(image)); if (image) @@ -1480,7 +1452,7 @@ namespace NifOsg // If this loop is changed such that the base texture isn't guaranteed to end up in texture unit 0, the shadow casting shader will need to be updated accordingly. for (size_t i=0; itextures.size(); ++i) { - if (texprop->textures[i].inUse) + if (texprop->textures[i].inUse || (i == Nif::NiTexturingProperty::BaseTexture && !texprop->controller.empty())) { switch(i) { @@ -1506,32 +1478,46 @@ namespace NifOsg } } - const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i]; - if(tex.texture.empty() && texprop->controller.empty()) - { - if (i == 0) - Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName << "\" in " << mFilename; - continue; - } - + unsigned int uvSet = 0; // create a new texture, will later attempt to share using the SharedStateManager osg::ref_ptr texture2d; - if (!tex.texture.empty()) + if (texprop->textures[i].inUse) { - const Nif::NiSourceTexture *st = tex.texture.getPtr(); - osg::ref_ptr image = handleSourceTexture(st, imageManager); - texture2d = new osg::Texture2D(image); - if (image) - texture2d->setTextureSize(image->s(), image->t()); + const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i]; + if(tex.texture.empty() && texprop->controller.empty()) + { + if (i == 0) + Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName << "\" in " << mFilename; + continue; + } + + if (!tex.texture.empty()) + { + const Nif::NiSourceTexture *st = tex.texture.getPtr(); + osg::ref_ptr image = handleSourceTexture(st, imageManager); + texture2d = new osg::Texture2D(image); + if (image) + texture2d->setTextureSize(image->s(), image->t()); + } + else + texture2d = new osg::Texture2D; + + bool wrapT = tex.clamp & 0x1; + bool wrapS = (tex.clamp >> 1) & 0x1; + + texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE); + texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE); + + uvSet = tex.uvSet; } else + { + // Texture only comes from NiFlipController, so tex is ignored, set defaults texture2d = new osg::Texture2D; - - bool wrapT = tex.clamp & 0x1; - bool wrapS = (tex.clamp >> 1) & 0x1; - - texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE); - texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE); + texture2d->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + texture2d->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + uvSet = 0; + } unsigned int texUnit = boundTextures.size(); @@ -1619,7 +1605,7 @@ namespace NifOsg break; } - boundTextures.push_back(tex.uvSet); + boundTextures.push_back(uvSet); } } handleTextureControllers(texprop, composite, imageManager, stateset, animflags); @@ -1746,7 +1732,7 @@ namespace NifOsg osg::StateSet* stateset = node->getOrCreateStateSet(); // Specular lighting is enabled by default, but there's a quirk... - int specFlags = 1; + bool specEnabled = true; osg::ref_ptr mat (new osg::Material); mat->setColorMode(hasVertexColors ? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF); @@ -1765,7 +1751,8 @@ namespace NifOsg case Nif::RC_NiSpecularProperty: { // Specular property can turn specular lighting off. - specFlags = property->flags; + auto specprop = static_cast(property); + specEnabled = specprop->flags & 1; break; } case Nif::RC_NiMaterialProperty: @@ -1849,7 +1836,7 @@ namespace NifOsg } // While NetImmerse and Gamebryo support specular lighting, Morrowind has its support disabled. - if (mVersion <= Nif::NIFFile::NIFVersion::VER_MW || specFlags == 0) + if (mVersion <= Nif::NIFFile::NIFVersion::VER_MW || !specEnabled) mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f,0.f,0.f,0.f)); if (lightmode == 0) diff --git a/components/nifosg/nodeindexholder.hpp b/components/nifosg/nodeindexholder.hpp new file mode 100644 index 000000000..e7d4f0db3 --- /dev/null +++ b/components/nifosg/nodeindexholder.hpp @@ -0,0 +1,35 @@ +#ifndef OPENMW_COMPONENTS_NIFOSG_NODEINDEXHOLDER_H +#define OPENMW_COMPONENTS_NIFOSG_NODEINDEXHOLDER_H + +#include + +namespace NifOsg +{ + + class NodeIndexHolder : public osg::Object + { + public: + NodeIndexHolder() = default; + NodeIndexHolder(int index) + : mIndex(index) + { + } + NodeIndexHolder(const NodeIndexHolder& copy, const osg::CopyOp& copyop) + : Object(copy, copyop) + , mIndex(copy.mIndex) + { + } + + META_Object(NifOsg, NodeIndexHolder) + + int getIndex() const { return mIndex; } + + private: + + // NIF record index + int mIndex{0}; + }; + +} + +#endif diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index f71dcdd96..0cbc3f22b 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -11,7 +11,7 @@ #include #include -#include "userdata.hpp" +#include "nodeindexholder.hpp" namespace NifOsg { @@ -383,8 +383,8 @@ void FindGroupByRecIndex::applyNode(osg::Node &searchNode) { if (searchNode.getUserDataContainer() && searchNode.getUserDataContainer()->getNumUserObjects()) { - NodeUserData* holder = dynamic_cast(searchNode.getUserDataContainer()->getUserObject(0)); - if (holder && holder->mIndex == mRecIndex) + NodeIndexHolder* holder = dynamic_cast(searchNode.getUserDataContainer()->getUserObject(0)); + if (holder && holder->getIndex() == mRecIndex) { osg::Group* group = searchNode.asGroup(); if (!group) diff --git a/components/nifosg/particle.hpp b/components/nifosg/particle.hpp index d71cbb9f5..724a8a721 100644 --- a/components/nifosg/particle.hpp +++ b/components/nifosg/particle.hpp @@ -32,11 +32,11 @@ namespace NifOsg META_Object(NifOsg, ParticleSystem) - virtual osgParticle::Particle* createParticle(const osgParticle::Particle *ptemplate); + osgParticle::Particle* createParticle(const osgParticle::Particle *ptemplate) override; void setQuota(int quota); - virtual void drawImplementation(osg::RenderInfo& renderInfo) const; + void drawImplementation(osg::RenderInfo& renderInfo) const override; private: int mQuota; @@ -70,7 +70,7 @@ namespace NifOsg META_Object(NifOsg, InverseWorldMatrix) - void operator()(osg::Node* node, osg::NodeVisitor* nv); + void operator()(osg::Node* node, osg::NodeVisitor* nv) override; }; class ParticleShooter : public osgParticle::Shooter @@ -85,7 +85,7 @@ namespace NifOsg META_Object(NifOsg, ParticleShooter) - virtual void shoot(osgParticle::Particle* particle) const; + void shoot(osgParticle::Particle* particle) const override; private: float mMinSpeed; @@ -107,8 +107,8 @@ namespace NifOsg META_Object(NifOsg, PlanarCollider) - virtual void beginOperate(osgParticle::Program* program); - virtual void operate(osgParticle::Particle* particle, double dt); + void beginOperate(osgParticle::Program* program) override; + void operate(osgParticle::Particle* particle, double dt) override; private: float mBounceFactor; @@ -125,8 +125,8 @@ namespace NifOsg META_Object(NifOsg, SphericalCollider) - virtual void beginOperate(osgParticle::Program* program); - virtual void operate(osgParticle::Particle* particle, double dt); + void beginOperate(osgParticle::Program* program) override; + void operate(osgParticle::Particle* particle, double dt) override; private: float mBounceFactor; osg::BoundingSphere mSphere; @@ -144,8 +144,8 @@ namespace NifOsg META_Object(NifOsg, GrowFadeAffector) - virtual void beginOperate(osgParticle::Program* program); - virtual void operate(osgParticle::Particle* particle, double dt); + void beginOperate(osgParticle::Program* program) override; + void operate(osgParticle::Particle* particle, double dt) override; private: float mGrowTime; @@ -165,7 +165,7 @@ namespace NifOsg META_Object(NifOsg, ParticleColorAffector) - virtual void operate(osgParticle::Particle* particle, double dt); + void operate(osgParticle::Particle* particle, double dt) override; private: Vec4Interpolator mData; @@ -182,8 +182,8 @@ namespace NifOsg META_Object(NifOsg, GravityAffector) - virtual void operate(osgParticle::Particle* particle, double dt); - virtual void beginOperate(osgParticle::Program *); + void operate(osgParticle::Particle* particle, double dt) override; + void beginOperate(osgParticle::Program *) override ; private: float mForce; @@ -206,12 +206,12 @@ namespace NifOsg public: FindGroupByRecIndex(int recIndex); - virtual void apply(osg::Node &node); + void apply(osg::Node &node) override; // Technically not required as the default implementation would trickle down to apply(Node&) anyway, // but we'll shortcut instead to avoid the chain of virtual function calls - virtual void apply(osg::MatrixTransform& node); - virtual void apply(osg::Geometry& node); + void apply(osg::MatrixTransform& node) override; + void apply(osg::Geometry& node) override; void applyNode(osg::Node& searchNode); @@ -231,7 +231,7 @@ namespace NifOsg META_Object(NifOsg, Emitter) - virtual void emitParticles(double dt); + void emitParticles(double dt) override; void setShooter(osgParticle::Shooter* shooter); void setPlacer(osgParticle::Placer* placer); diff --git a/components/nifosg/userdata.hpp b/components/nifosg/userdata.hpp deleted file mode 100644 index 42fcaff47..000000000 --- a/components/nifosg/userdata.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef OPENMW_COMPONENTS_NIFOSG_USERDATA_H -#define OPENMW_COMPONENTS_NIFOSG_USERDATA_H - -#include - -#include - -namespace NifOsg -{ - - // Note if you are copying a scene graph with this user data you should use the DEEP_COPY_USERDATA copyop. - class NodeUserData : public osg::Object - { - public: - NodeUserData(int index, float scale, const Nif::Matrix3& rotationScale) - : mIndex(index), mScale(scale), mRotationScale(rotationScale) - { - } - NodeUserData() - : mIndex(0), mScale(0) - { - } - NodeUserData(const NodeUserData& copy, const osg::CopyOp& copyop) - : Object(copy, copyop) - , mIndex(copy.mIndex) - , mScale(copy.mScale) - , mRotationScale(copy.mRotationScale) - { - } - - META_Object(NifOsg, NodeUserData) - - // NIF record index - int mIndex; - - // Hack: account for Transform differences between OSG and NIFs. - // OSG uses a 4x4 matrix, NIF's use a 3x3 rotationScale, float scale, and vec3 position. - // Decomposing the original components from the 4x4 matrix isn't possible, which causes - // problems when a KeyframeController wants to change only one of these components. So - // we store the scale and rotation components separately here. - // Note for a cleaner solution it would be possible to write a custom Transform node - float mScale; - Nif::Matrix3 mRotationScale; - }; - -} - -#endif diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index 4193cd5b4..bcadf51c4 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -68,7 +68,7 @@ public: } - virtual void apply(osg::Drawable &drawable) + void apply(osg::Drawable &drawable) override { if (!mTriangleMesh) mTriangleMesh.reset(new btTriangleMesh); diff --git a/components/resource/bulletshapemanager.hpp b/components/resource/bulletshapemanager.hpp index 8ae2b531f..7b1289e45 100644 --- a/components/resource/bulletshapemanager.hpp +++ b/components/resource/bulletshapemanager.hpp @@ -40,11 +40,11 @@ namespace Resource osg::ref_ptr getInstance(const std::string& name); /// @see ResourceManager::updateCache - virtual void updateCache(double referenceTime); + void updateCache(double referenceTime) override; - virtual void clearCache(); + void clearCache() override; - void reportStats(unsigned int frameNumber, osg::Stats *stats) const; + void reportStats(unsigned int frameNumber, osg::Stats *stats) const override; private: osg::ref_ptr createInstance(const std::string& name); diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index 41ce999e0..ff6fb04a6 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -115,6 +115,29 @@ namespace Resource return mWarningImage; } + bool killAlpha = false; + if (reader->supportedExtensions().count("tga")) + { + // Morrowind ignores the alpha channel of 16bpp TGA files even when the header says not to + unsigned char header[18]; + stream->read((char*)header, 18); + if (stream->gcount() != 18) + { + Log(Debug::Error) << "Error loading " << filename << ": couldn't read TGA header"; + mCache->addEntryToObjectCache(normalized, mWarningImage); + return mWarningImage; + } + int type = header[2]; + int depth; + if (type == 1 || type == 9) + depth = header[7]; + else + depth = header[16]; + int alphaBPP = header[17] & 0x0F; + killAlpha = depth == 16 && alphaBPP == 1; + stream->seekg(0); + } + osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions); if (!result.success()) { @@ -149,6 +172,18 @@ namespace Resource image = newImage; } } + else if (killAlpha) + { + osg::ref_ptr newImage = new osg::Image; + newImage->setFileName(image->getFileName()); + newImage->allocateImage(image->s(), image->t(), image->r(), GL_RGB, GL_UNSIGNED_BYTE); + // OSG just won't write the alpha as there's nowhere to put it. + for (int s = 0; s < image->s(); ++s) + for (int t = 0; t < image->t(); ++t) + for (int r = 0; r < image->r(); ++r) + newImage->setColor(image->getColor(s, t, r), s, t, r); + image = newImage; + } mCache->addEntryToObjectCache(normalized, image); return image; diff --git a/components/resource/imagemanager.hpp b/components/resource/imagemanager.hpp index 8eea4a70b..64954af54 100644 --- a/components/resource/imagemanager.hpp +++ b/components/resource/imagemanager.hpp @@ -32,7 +32,7 @@ namespace Resource osg::Image* getWarningImage(); - void reportStats(unsigned int frameNumber, osg::Stats* stats) const; + void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; private: osg::ref_ptr mWarningImage; diff --git a/components/resource/keyframemanager.hpp b/components/resource/keyframemanager.hpp index 3496342fa..fe1c4014e 100644 --- a/components/resource/keyframemanager.hpp +++ b/components/resource/keyframemanager.hpp @@ -23,7 +23,7 @@ namespace Resource /// @note Throws an exception if the resource is not found. osg::ref_ptr get(const std::string& name); - void reportStats(unsigned int frameNumber, osg::Stats* stats) const; + void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; }; } diff --git a/components/resource/niffilemanager.hpp b/components/resource/niffilemanager.hpp index c783bb7e0..d88aefd63 100644 --- a/components/resource/niffilemanager.hpp +++ b/components/resource/niffilemanager.hpp @@ -23,7 +23,7 @@ namespace Resource /// to be done in advance by other managers accessing the NifFileManager. Nif::NIFFilePtr get(const std::string& name); - void reportStats(unsigned int frameNumber, osg::Stats *stats) const; + void reportStats(unsigned int frameNumber, osg::Stats *stats) const override; }; } diff --git a/components/resource/resourcemanager.hpp b/components/resource/resourcemanager.hpp index a5ae27c6a..ccb065e3b 100644 --- a/components/resource/resourcemanager.hpp +++ b/components/resource/resourcemanager.hpp @@ -48,23 +48,23 @@ namespace Resource virtual ~GenericResourceManager() {} /// Clear cache entries that have not been referenced for longer than expiryDelay. - virtual void updateCache(double referenceTime) + void updateCache(double referenceTime) override { mCache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime); mCache->removeExpiredObjectsInCache(referenceTime - mExpiryDelay); } /// Clear all cache entries. - virtual void clearCache() { mCache->clear(); } + void clearCache() override { mCache->clear(); } /// How long to keep objects in cache after no longer being referenced. - void setExpiryDelay (double expiryDelay) { mExpiryDelay = expiryDelay; } + void setExpiryDelay (double expiryDelay) override { mExpiryDelay = expiryDelay; } const VFS::Manager* getVFS() const { return mVFS; } - virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const {} + void reportStats(unsigned int frameNumber, osg::Stats* stats) const override {} - virtual void releaseGLObjects(osg::State* state) { mCache->releaseGLObjects(state); } + void releaseGLObjects(osg::State* state) override { mCache->releaseGLObjects(state); } protected: const VFS::Manager* mVFS; diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index ca6c7c895..b87446351 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -40,7 +40,7 @@ namespace class InitWorldSpaceParticlesCallback : public osg::NodeCallback { public: - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { osgParticle::ParticleSystem* partsys = static_cast(node); @@ -91,7 +91,7 @@ namespace && partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace"); } - void apply(osg::Drawable& drw) + void apply(osg::Drawable& drw) override { if (osgParticle::ParticleSystem* partsys = dynamic_cast(&drw)) { @@ -143,7 +143,7 @@ namespace Resource { } - virtual void visit(osg::Node& node, SceneUtil::Controller& ctrl) + void visit(osg::Node& node, SceneUtil::Controller& ctrl) override { if (NifOsg::FlipController* flipctrl = dynamic_cast(&ctrl)) { @@ -175,7 +175,7 @@ namespace Resource { } - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { osg::StateSet* stateset = node.getStateSet(); if (stateset) @@ -316,7 +316,7 @@ namespace Resource { } - virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options) + osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options) override { try { @@ -400,7 +400,7 @@ namespace Resource return it != reservedNames.end(); } - virtual bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Drawable* node,unsigned int option) const + bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Drawable* node,unsigned int option) const override { if (option & SceneUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS) { @@ -412,7 +412,7 @@ namespace Resource return (option & optimizer->getPermissibleOptimizationsForObject(node))!=0; } - virtual bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Node* node,unsigned int option) const + bool isOperationPermissibleForObjectImplementation(const SceneUtil::Optimizer* optimizer, const osg::Node* node,unsigned int option) const override { if (node->getNumDescriptions()>0) return false; if (node->getDataVariance() == osg::Object::DYNAMIC) return false; diff --git a/components/resource/stats.cpp b/components/resource/stats.cpp index 147970add..942bd92d8 100644 --- a/components/resource/stats.cpp +++ b/components/resource/stats.cpp @@ -211,7 +211,7 @@ public: { } - virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const + void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const override { if (!mStats) return; diff --git a/components/resource/stats.hpp b/components/resource/stats.hpp index 8f04ee10d..9fa583cca 100644 --- a/components/resource/stats.hpp +++ b/components/resource/stats.hpp @@ -29,7 +29,7 @@ namespace Resource void setKey(int key) { _key = key; } int getKey() const { return _key; } - bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa); + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override; void setWindowSize(int w, int h); @@ -39,7 +39,7 @@ namespace Resource void setUpScene(osgViewer::ViewerBase* viewer); /** Get the keyboard and mouse usage of this manipulator.*/ - virtual void getUsage(osg::ApplicationUsage& usage) const; + void getUsage(osg::ApplicationUsage& usage) const override; private: osg::ref_ptr _switch; diff --git a/components/sceneutil/attach.cpp b/components/sceneutil/attach.cpp index c438e705d..597c7adf4 100644 --- a/components/sceneutil/attach.cpp +++ b/components/sceneutil/attach.cpp @@ -30,20 +30,20 @@ namespace SceneUtil mFilter2 = "tri " + mFilter; } - virtual void apply(osg::MatrixTransform& node) + void apply(osg::MatrixTransform& node) override { traverse(node); } - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { traverse(node); } - virtual void apply(osg::Group& node) + void apply(osg::Group& node) override { traverse(node); } - virtual void apply(osg::Drawable& drawable) + void apply(osg::Drawable& drawable) override { if (!filterMatches(drawable.getName())) return; @@ -64,7 +64,7 @@ namespace SceneUtil for (const osg::ref_ptr& node : mToCopy) { if (node->getNumParents() > 1) - Log(Debug::Error) << "Error CopyRigVisitor: node has multiple parents"; + Log(Debug::Error) << "Error CopyRigVisitor: node has " << node->getNumParents() << " parents"; while (node->getNumParents()) node->getParent(0)->removeChild(node); diff --git a/components/sceneutil/clone.cpp b/components/sceneutil/clone.cpp index c3261515d..1de7bfd91 100644 --- a/components/sceneutil/clone.cpp +++ b/components/sceneutil/clone.cpp @@ -6,8 +6,6 @@ #include #include -#include - #include #include @@ -22,15 +20,6 @@ namespace SceneUtil | osg::CopyOp::DEEP_COPY_USERDATA); } - osg::Object* CopyOp::operator ()(const osg::Object* node) const - { - // We should copy node transformations when we copy node - if (dynamic_cast(node)) - return static_cast(node->clone(*this)); - - return osg::CopyOp::operator()(node); - } - osg::Node* CopyOp::operator ()(const osg::Node* node) const { if (const osgParticle::ParticleProcessor* processor = dynamic_cast(node)) diff --git a/components/sceneutil/clone.hpp b/components/sceneutil/clone.hpp index cf6d79e68..1cf00c9e5 100644 --- a/components/sceneutil/clone.hpp +++ b/components/sceneutil/clone.hpp @@ -27,10 +27,8 @@ namespace SceneUtil virtual osgParticle::ParticleSystem* operator() (const osgParticle::ParticleSystem* partsys) const; virtual osgParticle::ParticleProcessor* operator() (const osgParticle::ParticleProcessor* processor) const; - virtual osg::Node* operator() (const osg::Node* node) const; - virtual osg::Drawable* operator() (const osg::Drawable* drawable) const; - - virtual osg::Object* operator ()(const osg::Object* node) const; + osg::Node* operator() (const osg::Node* node) const override; + osg::Drawable* operator() (const osg::Drawable* drawable) const override; private: // maps new pointers to their old pointers diff --git a/components/sceneutil/controller.hpp b/components/sceneutil/controller.hpp index d02b65cf1..2656d654e 100644 --- a/components/sceneutil/controller.hpp +++ b/components/sceneutil/controller.hpp @@ -18,7 +18,7 @@ namespace SceneUtil { public: FrameTimeSource(); - virtual float getValue(osg::NodeVisitor* nv); + float getValue(osg::NodeVisitor* nv) override; }; /// @note ControllerFunctions may be shared - you should not hold any state in it. That is why all its methods are declared const. @@ -63,12 +63,12 @@ namespace SceneUtil public: ControllerVisitor(); - virtual void apply(osg::Node& node); + void apply(osg::Node& node) override; // Technically not required as the default implementation would trickle down to apply(Node&) anyway, // but we'll shortcut instead to avoid the chain of virtual function calls - virtual void apply(osg::MatrixTransform& node); - virtual void apply(osg::Geometry& node); + void apply(osg::MatrixTransform& node) override; + void apply(osg::Geometry& node) override; void applyNode(osg::Node& node); @@ -83,7 +83,7 @@ namespace SceneUtil /// Assign the wanted ControllerSource. May be overridden in derived classes. /// By default assigns the ControllerSource passed to the constructor of this class if no ControllerSource is assigned to that controller yet. - virtual void visit(osg::Node& node, Controller& ctrl); + void visit(osg::Node& node, Controller& ctrl) override; private: std::shared_ptr mToAssign; @@ -95,7 +95,7 @@ namespace SceneUtil public: FindMaxControllerLengthVisitor(); - virtual void visit(osg::Node& , Controller& ctrl); + void visit(osg::Node& , Controller& ctrl) override; float getMaxLength() const; diff --git a/components/sceneutil/lightcontroller.hpp b/components/sceneutil/lightcontroller.hpp index 3292ae541..36b2e868e 100644 --- a/components/sceneutil/lightcontroller.hpp +++ b/components/sceneutil/lightcontroller.hpp @@ -26,7 +26,7 @@ namespace SceneUtil void setDiffuse(const osg::Vec4f& color); - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + void operator()(osg::Node* node, osg::NodeVisitor* nv) override; private: LightType mType; diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 415bdae3a..7f1be2eea 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -31,26 +31,26 @@ namespace SceneUtil LightStateAttribute(const LightStateAttribute& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY) : osg::StateAttribute(copy,copyop), mIndex(copy.mIndex), mLights(copy.mLights) {} - unsigned int getMember() const + unsigned int getMember() const override { return mIndex; } - virtual bool getModeUsage(ModeUsage & usage) const + bool getModeUsage(ModeUsage & usage) const override { for (unsigned int i=0; i(node); lightManager->update(); @@ -295,30 +295,30 @@ namespace SceneUtil DisableLight(const DisableLight& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY) : osg::StateAttribute(copy,copyop), mIndex(copy.mIndex) {} - virtual osg::Object* cloneType() const { return new DisableLight(mIndex); } - virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new DisableLight(*this,copyop); } - virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=nullptr; } - virtual const char* libraryName() const { return "SceneUtil"; } - virtual const char* className() const { return "DisableLight"; } - virtual Type getType() const { return LIGHT; } + osg::Object* cloneType() const override { return new DisableLight(mIndex); } + osg::Object* clone(const osg::CopyOp& copyop) const override { return new DisableLight(*this,copyop); } + bool isSameKindAs(const osg::Object* obj) const override { return dynamic_cast(obj)!=nullptr; } + const char* libraryName() const override { return "SceneUtil"; } + const char* className() const override { return "DisableLight"; } + Type getType() const override { return LIGHT; } - unsigned int getMember() const + unsigned int getMember() const override { return mIndex; } - virtual bool getModeUsage(ModeUsage & usage) const + bool getModeUsage(ModeUsage & usage) const override { usage.usesMode(GL_LIGHT0 + mIndex); return true; } - virtual int compare(const StateAttribute &sa) const + int compare(const StateAttribute &sa) const override { throw std::runtime_error("DisableLight::compare: unimplemented"); } - virtual void apply(osg::State& state) const + void apply(osg::State& state) const override { int lightNum = GL_LIGHT0 + mIndex; glLightfv( lightNum, GL_AMBIENT, mnullptr.ptr() ); diff --git a/components/sceneutil/lightmanager.hpp b/components/sceneutil/lightmanager.hpp index ea6c640c4..c370f1b7f 100644 --- a/components/sceneutil/lightmanager.hpp +++ b/components/sceneutil/lightmanager.hpp @@ -172,7 +172,7 @@ namespace SceneUtil META_Object(SceneUtil, LightListCallback) - void operator()(osg::Node* node, osg::NodeVisitor* nv); + void operator()(osg::Node* node, osg::NodeVisitor* nv) override; bool pushLightState(osg::Node* node, osgUtil::CullVisitor* nv); diff --git a/components/sceneutil/morphgeometry.hpp b/components/sceneutil/morphgeometry.hpp index ba3b40961..6c492ad15 100644 --- a/components/sceneutil/morphgeometry.hpp +++ b/components/sceneutil/morphgeometry.hpp @@ -22,7 +22,7 @@ namespace SceneUtil void setSourceGeometry(osg::ref_ptr sourceGeom); // Currently empty as this is difficult to implement. Technically we would need to compile both internal geometries in separate frames but this method is only called once. Alternatively we could compile just the static parts of the model. - virtual void compileGLObjects(osg::RenderInfo& renderInfo) const {} + void compileGLObjects(osg::RenderInfo& renderInfo) const override {} class MorphTarget { @@ -59,11 +59,11 @@ namespace SceneUtil osg::ref_ptr getSourceGeometry() const; - virtual void accept(osg::NodeVisitor &nv); - virtual bool supports(const osg::PrimitiveFunctor&) const { return true; } - virtual void accept(osg::PrimitiveFunctor&) const; + void accept(osg::NodeVisitor &nv) override; + bool supports(const osg::PrimitiveFunctor&) const override { return true; } + void accept(osg::PrimitiveFunctor&) const override; - virtual osg::BoundingBox computeBoundingBox() const; + osg::BoundingBox computeBoundingBox() const override; private: void cull(osg::NodeVisitor* nv); diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index e221e7a36..f1fca5dfc 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -236,7 +236,7 @@ class VDSMCameraCullCallback : public osg::NodeCallback VDSMCameraCullCallback(MWShadowTechnique* vdsm, osg::Polytope& polytope); - virtual void operator()(osg::Node*, osg::NodeVisitor* nv); + void operator()(osg::Node*, osg::NodeVisitor* nv) override; osg::RefMatrix* getProjectionMatrix() { return _projectionMatrix.get(); } osgUtil::RenderStage* getRenderStage() { return _renderStage.get(); } @@ -749,7 +749,8 @@ MWShadowTechnique::ViewDependentData::ViewDependentData(MWShadowTechnique* vdsm) _viewDependentShadowMap(vdsm) { OSG_INFO<<"ViewDependentData::ViewDependentData()"<_traversalNumber = rhs->_traversalNumber; lhs->_viewDependentShadowMap = rhs->_viewDependentShadowMap; - lhs->_stateset->clear(); + lhs->getStateSet()->clear(); lhs->_lightDataList = rhs->_lightDataList; lhs->_numValidShadows = rhs->_numValidShadows; @@ -1373,9 +1375,7 @@ void SceneUtil::MWShadowTechnique::castShadows(osgUtil::CullVisitor& cv, ViewDep std::string validRegionUniformName = "validRegionMatrix" + std::to_string(sm_i); osg::ref_ptr validRegionUniform; - std::lock_guard lock(_accessUniformsAndProgramMutex); - - for (auto uniform : _uniforms) + for (auto uniform : _uniforms[cv.getTraversalNumber() % 2]) { if (uniform->getName() == validRegionUniformName) validRegionUniform = uniform; @@ -1384,7 +1384,7 @@ void SceneUtil::MWShadowTechnique::castShadows(osgUtil::CullVisitor& cv, ViewDep if (!validRegionUniform) { validRegionUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, validRegionUniformName); - _uniforms.push_back(validRegionUniform); + _uniforms[cv.getTraversalNumber() % 2].push_back(validRegionUniform); } validRegionUniform->set(validRegionMatrix); @@ -1524,6 +1524,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) if (doCastShadow) { + vdd->setTraversalNumber(vdd->getTraversalNumber() + 1); castShadows(cv, vdd); } @@ -1602,8 +1603,6 @@ void MWShadowTechnique::createShaders() unsigned int _baseTextureUnit = 0; - std::lock_guard lock(_accessUniformsAndProgramMutex); - _shadowCastingStateSet = new osg::StateSet; ShadowSettings* settings = getShadowedScene()->getShadowSettings(); @@ -1636,15 +1635,20 @@ void MWShadowTechnique::createShaders() _shadowCastingStateSet->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - _uniforms.clear(); osg::ref_ptr baseTextureSampler = new osg::Uniform("baseTexture",(int)_baseTextureUnit); - _uniforms.push_back(baseTextureSampler.get()); - osg::ref_ptr baseTextureUnit = new osg::Uniform("baseTextureUnit",(int)_baseTextureUnit); - _uniforms.push_back(baseTextureUnit.get()); - _uniforms.push_back(new osg::Uniform("maximumShadowMapDistance", (float)settings->getMaximumShadowMapDistance())); - _uniforms.push_back(new osg::Uniform("shadowFadeStart", (float)_shadowFadeStart)); + osg::ref_ptr maxDistance = new osg::Uniform("maximumShadowMapDistance", (float)settings->getMaximumShadowMapDistance()); + osg::ref_ptr fadeStart = new osg::Uniform("shadowFadeStart", (float)_shadowFadeStart); + + for (auto& perFrameUniformList : _uniforms) + { + perFrameUniformList.clear(); + perFrameUniformList.push_back(baseTextureSampler); + perFrameUniformList.push_back(baseTextureUnit.get()); + perFrameUniformList.push_back(maxDistance); + perFrameUniformList.push_back(fadeStart); + } for(unsigned int sm_i=0; sm_igetNumShadowMapsPerLight(); ++sm_i) { @@ -1652,14 +1656,16 @@ void MWShadowTechnique::createShaders() std::stringstream sstr; sstr<<"shadowTexture"< shadowTextureSampler = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i)); - _uniforms.push_back(shadowTextureSampler.get()); + for (auto& perFrameUniformList : _uniforms) + perFrameUniformList.push_back(shadowTextureSampler.get()); } { std::stringstream sstr; sstr<<"shadowTextureUnit"< shadowTextureUnit = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i)); - _uniforms.push_back(shadowTextureUnit.get()); + for (auto& perFrameUniformList : _uniforms) + perFrameUniformList.push_back(shadowTextureUnit.get()); } } @@ -3119,18 +3125,14 @@ osg::StateSet* MWShadowTechnique::selectStateSetForRenderingShadow(ViewDependent osg::ref_ptr stateset = vdd.getStateSet(); - std::lock_guard lock(_accessUniformsAndProgramMutex); + stateset->clear(); - vdd.getStateSet()->clear(); + stateset->setTextureAttributeAndModes(0, _fallbackBaseTexture.get(), osg::StateAttribute::ON); - vdd.getStateSet()->setTextureAttributeAndModes(0, _fallbackBaseTexture.get(), osg::StateAttribute::ON); - - for(Uniforms::const_iterator itr=_uniforms.begin(); - itr!=_uniforms.end(); - ++itr) + for(const auto& uniform : _uniforms[vdd.getTraversalNumber() % 2]) { - OSG_INFO<<"addUniform("<<(*itr)->getName()<<")"<addUniform(itr->get()); + OSG_INFO<<"addUniform("<getName()<<")"<addUniform(uniform); } if (_program.valid()) @@ -3186,7 +3188,7 @@ osg::StateSet* MWShadowTechnique::selectStateSetForRenderingShadow(ViewDependent stateset->setTextureMode(sd._textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); } - return vdd.getStateSet(); + return stateset; } void MWShadowTechnique::resizeGLObjectBuffers(unsigned int /*maxSize*/) @@ -3216,7 +3218,7 @@ class DoubleBufferCallback : public osg::Callback public: DoubleBufferCallback(osg::NodeList &children) : mChildren(children) {} - virtual bool run(osg::Object* node, osg::Object* visitor) override + bool run(osg::Object* node, osg::Object* visitor) override { // We can't use a static cast as NodeVisitor virtually inherits from Object osg::ref_ptr nodeVisitor = visitor->asNodeVisitor(); @@ -3243,12 +3245,12 @@ SceneUtil::MWShadowTechnique::DebugHUD::DebugHUD(int numberOfShadowMapsPerLight) fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, debugFrustumFragmentShaderSource); frustumProgram->addShader(fragmentShader); - for (int i = 0; i < 2; ++i) + for (auto& frustumGeometry : mFrustumGeometries) { - mFrustumGeometries.emplace_back(new osg::Geometry()); - mFrustumGeometries[i]->setCullingActive(false); + frustumGeometry = new osg::Geometry(); + frustumGeometry->setCullingActive(false); - mFrustumGeometries[i]->getOrCreateStateSet()->setAttributeAndModes(frustumProgram, osg::StateAttribute::ON); + frustumGeometry->getOrCreateStateSet()->setAttributeAndModes(frustumProgram, osg::StateAttribute::ON); } osg::ref_ptr frustumDrawElements = new osg::DrawElementsUShort(osg::PrimitiveSet::LINE_STRIP); @@ -3284,12 +3286,14 @@ void SceneUtil::MWShadowTechnique::DebugHUD::draw(osg::ref_ptr t // It might be possible to change shadow settings at runtime if (shadowMapNumber > mDebugCameras.size()) addAnotherShadowMap(); - - mFrustumUniforms[shadowMapNumber]->set(matrix); - osg::ref_ptr stateSet = mDebugGeometry[shadowMapNumber]->getOrCreateStateSet(); + osg::ref_ptr stateSet = new osg::StateSet(); stateSet->setTextureAttributeAndModes(sDebugTextureUnit, texture, osg::StateAttribute::ON); + auto frustumUniform = mFrustumUniforms[cv.getTraversalNumber() % 2][shadowMapNumber]; + frustumUniform->set(matrix); + stateSet->addUniform(frustumUniform); + // Some of these calls may be superfluous. unsigned int traversalMask = cv.getTraversalMask(); cv.setTraversalMask(mDebugGeometry[shadowMapNumber]->getNodeMask()); @@ -3344,6 +3348,6 @@ void SceneUtil::MWShadowTechnique::DebugHUD::addAnotherShadowMap() mFrustumTransforms[shadowMapNumber]->setCullingActive(false); mDebugCameras[shadowMapNumber]->addChild(mFrustumTransforms[shadowMapNumber]); - mFrustumUniforms.push_back(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "transform")); - mFrustumTransforms[shadowMapNumber]->getOrCreateStateSet()->addUniform(mFrustumUniforms[shadowMapNumber]); + for(auto& uniformVector : mFrustumUniforms) + uniformVector.push_back(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "transform")); } diff --git a/components/sceneutil/mwshadowtechnique.hpp b/components/sceneutil/mwshadowtechnique.hpp index 8bfe34c11..7e0d74d2e 100644 --- a/components/sceneutil/mwshadowtechnique.hpp +++ b/components/sceneutil/mwshadowtechnique.hpp @@ -19,6 +19,7 @@ #ifndef COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H #define COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H 1 +#include #include #include @@ -45,24 +46,24 @@ namespace SceneUtil { META_Object(SceneUtil, MWShadowTechnique); /** initialize the ShadowedScene and local cached data structures.*/ - virtual void init(); + void init() override; /** run the update traversal of the ShadowedScene and update any loca chached data structures.*/ - virtual void update(osg::NodeVisitor& nv); + void update(osg::NodeVisitor& nv) override; /** run the cull traversal of the ShadowedScene and set up the rendering for this ShadowTechnique.*/ - virtual void cull(osgUtil::CullVisitor& cv); + void cull(osgUtil::CullVisitor& cv) override; /** Resize any per context GLObject buffers to specified size. */ - virtual void resizeGLObjectBuffers(unsigned int maxSize); + void resizeGLObjectBuffers(unsigned int maxSize) override; /** If State is non-zero, this function releases any associated OpenGL objects for * the specified graphics context. Otherwise, releases OpenGL objects * for all graphics contexts. */ - virtual void releaseGLObjects(osg::State* = 0) const; + void releaseGLObjects(osg::State* = 0) const override; /** Clean scene graph from any shadow technique specific nodes, state and drawables.*/ - virtual void cleanSceneGraph(); + void cleanSceneGraph() override; virtual void enableShadows(); @@ -91,19 +92,19 @@ namespace SceneUtil { public: ComputeLightSpaceBounds(osg::Viewport* viewport, const osg::Matrixd& projectionMatrix, osg::Matrixd& viewMatrix); - void apply(osg::Node& node); + void apply(osg::Node& node) override; - void apply(osg::Drawable& drawable); + void apply(osg::Drawable& drawable) override; void apply(Terrain::QuadTreeWorld& quadTreeWorld); - void apply(osg::Billboard&); + void apply(osg::Billboard&) override; - void apply(osg::Projection&); + void apply(osg::Projection&) override; - void apply(osg::Transform& transform); + void apply(osg::Transform& transform) override; - void apply(osg::Camera&); + void apply(osg::Camera&) override; using osg::NodeVisitor::apply; @@ -213,7 +214,7 @@ namespace SceneUtil { ShadowDataList& getShadowDataList() { return _shadowDataList; } - osg::StateSet* getStateSet() { return _stateset.get(); } + osg::StateSet* getStateSet() { return _stateset[_traversalNumber % 2].get(); } virtual void releaseGLObjects(osg::State* = 0) const; @@ -221,18 +222,23 @@ namespace SceneUtil { void setNumValidShadows(unsigned int numValidShadows) { _numValidShadows = numValidShadows; } + void setTraversalNumber(unsigned int traversalNumber) { _traversalNumber = traversalNumber; } + + unsigned int getTraversalNumber() { return _traversalNumber; } + protected: friend class MWShadowTechnique; virtual ~ViewDependentData() {} MWShadowTechnique* _viewDependentShadowMap; - osg::ref_ptr _stateset; + std::array, 2> _stateset; LightDataList _lightDataList; ShadowDataList _shadowDataList; unsigned int _numValidShadows; + unsigned int _traversalNumber; }; virtual ViewDependentData* createViewDependentData(osgUtil::CullVisitor* cv); @@ -292,8 +298,7 @@ namespace SceneUtil { osg::ref_ptr _fallbackShadowMapTexture; typedef std::vector< osg::ref_ptr > Uniforms; - mutable std::mutex _accessUniformsAndProgramMutex; - Uniforms _uniforms; + std::array _uniforms; osg::ref_ptr _program; bool _enableShadows; @@ -327,8 +332,8 @@ namespace SceneUtil { osg::ref_ptr mDebugProgram; std::vector> mDebugGeometry; std::vector> mFrustumTransforms; - std::vector> mFrustumUniforms; - std::vector> mFrustumGeometries; + std::array>, 2> mFrustumUniforms; + std::array, 2> mFrustumGeometries; }; osg::ref_ptr _debugHud; diff --git a/components/sceneutil/optimizer.cpp b/components/sceneutil/optimizer.cpp index b9da2d1c8..b48ceda40 100644 --- a/components/sceneutil/optimizer.cpp +++ b/components/sceneutil/optimizer.cpp @@ -160,7 +160,7 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor setTraversalMode(osg::NodeVisitor::TRAVERSE_PARENTS); } - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { if (node.getNumParents()) { @@ -173,7 +173,7 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor } } - virtual void apply(osg::LOD& lod) + void apply(osg::LOD& lod) override { _currentObjectList.push_back(&lod); @@ -182,23 +182,22 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor _currentObjectList.pop_back(); } - virtual void apply(osg::Transform& transform) + void apply(osg::Transform& transform) override { // for all current objects associated this transform with them. registerWithCurrentObjects(&transform); } - virtual void apply(osg::Geode& geode) + void apply(osg::Geode& geode) override { traverse(geode); } - virtual void apply(osg::Billboard& geode) + void apply(osg::Billboard& geode) override { traverse(geode); } - void collectDataFor(osg::Node* node) { _currentObjectList.push_back(node); @@ -1605,41 +1604,40 @@ class MergeArrayVisitor : public osg::ArrayVisitor lhs->insert(lhs->end(),rhs.begin(),rhs.end()); } - virtual void apply(osg::Array&) { OSG_WARN << "Warning: Optimizer's MergeArrayVisitor cannot merge Array type." << std::endl; } + void apply(osg::Array&) override { OSG_WARN << "Warning: Optimizer's MergeArrayVisitor cannot merge Array type." << std::endl; } + void apply(osg::ByteArray& rhs) override { _merge(rhs); } + void apply(osg::ShortArray& rhs) override { _merge(rhs); } + void apply(osg::IntArray& rhs) override { _merge(rhs); } + void apply(osg::UByteArray& rhs) override { _merge(rhs); } + void apply(osg::UShortArray& rhs) override { _merge(rhs); } + void apply(osg::UIntArray& rhs) override { _merge(rhs); } - virtual void apply(osg::ByteArray& rhs) { _merge(rhs); } - virtual void apply(osg::ShortArray& rhs) { _merge(rhs); } - virtual void apply(osg::IntArray& rhs) { _merge(rhs); } - virtual void apply(osg::UByteArray& rhs) { _merge(rhs); } - virtual void apply(osg::UShortArray& rhs) { _merge(rhs); } - virtual void apply(osg::UIntArray& rhs) { _merge(rhs); } + void apply(osg::Vec4ubArray& rhs) override { _merge(rhs); } + void apply(osg::Vec3ubArray& rhs) override{ _merge(rhs); } + void apply(osg::Vec2ubArray& rhs) override { _merge(rhs); } - virtual void apply(osg::Vec4ubArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec3ubArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec2ubArray& rhs) { _merge(rhs); } + void apply(osg::Vec4usArray& rhs) override { _merge(rhs); } + void apply(osg::Vec3usArray& rhs) override { _merge(rhs); } + void apply(osg::Vec2usArray& rhs) override { _merge(rhs); } - virtual void apply(osg::Vec4usArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec3usArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec2usArray& rhs) { _merge(rhs); } + void apply(osg::FloatArray& rhs) override { _merge(rhs); } + void apply(osg::Vec2Array& rhs) override { _merge(rhs); } + void apply(osg::Vec3Array& rhs) override { _merge(rhs); } + void apply(osg::Vec4Array& rhs) override { _merge(rhs); } - virtual void apply(osg::FloatArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec2Array& rhs) { _merge(rhs); } - virtual void apply(osg::Vec3Array& rhs) { _merge(rhs); } - virtual void apply(osg::Vec4Array& rhs) { _merge(rhs); } + void apply(osg::DoubleArray& rhs) override { _merge(rhs); } + void apply(osg::Vec2dArray& rhs) override { _merge(rhs); } + void apply(osg::Vec3dArray& rhs) override { _merge(rhs); } + void apply(osg::Vec4dArray& rhs) override { _merge(rhs); } - virtual void apply(osg::DoubleArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec2dArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec3dArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec4dArray& rhs) { _merge(rhs); } + void apply(osg::Vec2bArray& rhs) override { _merge(rhs); } + void apply(osg::Vec3bArray& rhs) override { _merge(rhs); } + void apply(osg::Vec4bArray& rhs) override { _merge(rhs); } - virtual void apply(osg::Vec2bArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec3bArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec4bArray& rhs) { _merge(rhs); } - - virtual void apply(osg::Vec2sArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec3sArray& rhs) { _merge(rhs); } - virtual void apply(osg::Vec4sArray& rhs) { _merge(rhs); } + void apply(osg::Vec2sArray& rhs) override { _merge(rhs); } + void apply(osg::Vec3sArray& rhs) override { _merge(rhs); } + void apply(osg::Vec4sArray& rhs) override { _merge(rhs); } }; bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs) diff --git a/components/sceneutil/optimizer.hpp b/components/sceneutil/optimizer.hpp index d7c83e898..2d6293e23 100644 --- a/components/sceneutil/optimizer.hpp +++ b/components/sceneutil/optimizer.hpp @@ -273,10 +273,10 @@ class Optimizer FlattenStaticTransformsVisitor(Optimizer* optimizer=0): BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {} - virtual void apply(osg::Node& geode); - virtual void apply(osg::Drawable& drawable); - virtual void apply(osg::Billboard& geode); - virtual void apply(osg::Transform& transform); + void apply(osg::Node& geode) override; + void apply(osg::Drawable& drawable) override; + void apply(osg::Billboard& geode) override; + void apply(osg::Transform& transform) override; bool removeTransforms(osg::Node* nodeWeCannotRemove); @@ -304,7 +304,7 @@ class Optimizer CombineStaticTransformsVisitor(Optimizer* optimizer=0): BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {} - virtual void apply(osg::MatrixTransform& transform); + void apply(osg::MatrixTransform& transform) override; bool removeTransforms(osg::Node* nodeWeCannotRemove); @@ -326,7 +326,7 @@ class Optimizer RemoveEmptyNodesVisitor(Optimizer* optimizer=0): BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {} - virtual void apply(osg::Group& group); + void apply(osg::Group& group) override; void removeEmptyNodes(); @@ -343,10 +343,10 @@ class Optimizer RemoveRedundantNodesVisitor(Optimizer* optimizer=0): BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {} - virtual void apply(osg::Group& group); - virtual void apply(osg::Transform& transform); - virtual void apply(osg::LOD& lod); - virtual void apply(osg::Switch& switchNode); + void apply(osg::Group& group) override; + void apply(osg::Transform& transform) override; + void apply(osg::LOD& lod) override; + void apply(osg::Switch& switchNode) override; bool isOperationPermissible(osg::Node& node); @@ -365,9 +365,9 @@ class Optimizer bool isOperationPermissible(osg::Group& node); - virtual void apply(osg::Group& group); - virtual void apply(osg::LOD& lod); - virtual void apply(osg::Switch& switchNode); + void apply(osg::Group& group) override; + void apply(osg::LOD& lod) override; + void apply(osg::Switch& switchNode) override; }; class MergeGeometryVisitor : public BaseOptimizerVisitor @@ -402,8 +402,8 @@ class Optimizer void popStateSet(); void checkAlphaBlendingActive(); - virtual void apply(osg::Group& group); - virtual void apply(osg::Billboard&) { /* don't do anything*/ } + void apply(osg::Group& group) override; + void apply(osg::Billboard&) override { /* don't do anything*/ } bool mergeGroup(osg::Group& group); diff --git a/components/sceneutil/positionattitudetransform.hpp b/components/sceneutil/positionattitudetransform.hpp index b6f92ee84..9513c0e36 100644 --- a/components/sceneutil/positionattitudetransform.hpp +++ b/components/sceneutil/positionattitudetransform.hpp @@ -25,22 +25,17 @@ class PositionAttitudeTransform : public osg::Transform inline void setPosition(const osg::Vec3f& pos) { _position = pos; dirtyBound(); } inline const osg::Vec3f& getPosition() const { return _position; } - inline void setAttitude(const osg::Quat& quat) { _attitude = quat; dirtyBound(); } inline const osg::Quat& getAttitude() const { return _attitude; } - inline void setScale(const osg::Vec3f& scale) { _scale = scale; dirtyBound(); } inline const osg::Vec3f& getScale() const { return _scale; } - - - virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const; - virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const; + bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const override; + bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const override; protected : - virtual ~PositionAttitudeTransform() {} osg::Vec3f _position; diff --git a/components/sceneutil/riggeometry.hpp b/components/sceneutil/riggeometry.hpp index 801c172b3..e01583399 100644 --- a/components/sceneutil/riggeometry.hpp +++ b/components/sceneutil/riggeometry.hpp @@ -23,7 +23,7 @@ namespace SceneUtil META_Object(SceneUtil, RigGeometry) // Currently empty as this is difficult to implement. Technically we would need to compile both internal geometries in separate frames but this method is only called once. Alternatively we could compile just the static parts of the model. - virtual void compileGLObjects(osg::RenderInfo& renderInfo) const {} + void compileGLObjects(osg::RenderInfo& renderInfo) const override {} struct BoneInfluence { @@ -46,22 +46,22 @@ namespace SceneUtil osg::ref_ptr getSourceGeometry() const; - virtual void accept(osg::NodeVisitor &nv); - virtual bool supports(const osg::PrimitiveFunctor&) const { return true; } - virtual void accept(osg::PrimitiveFunctor&) const; + void accept(osg::NodeVisitor &nv) override; + bool supports(const osg::PrimitiveFunctor&) const override{ return true; } + void accept(osg::PrimitiveFunctor&) const override; struct CopyBoundingBoxCallback : osg::Drawable::ComputeBoundingBoxCallback { osg::BoundingBox boundingBox; - virtual osg::BoundingBox computeBound(const osg::Drawable&) const override { return boundingBox; } + osg::BoundingBox computeBound(const osg::Drawable&) const override { return boundingBox; } }; struct CopyBoundingSphereCallback : osg::Node::ComputeBoundingSphereCallback { osg::BoundingSphere boundingSphere; - virtual osg::BoundingSphere computeBound(const osg::Node&) const override { return boundingSphere; } + osg::BoundingSphere computeBound(const osg::Node&) const override { return boundingSphere; } }; private: diff --git a/components/sceneutil/serialize.cpp b/components/sceneutil/serialize.cpp index 60f096a72..9e7aa83f6 100644 --- a/components/sceneutil/serialize.cpp +++ b/components/sceneutil/serialize.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include #include @@ -74,6 +76,15 @@ public: } }; +class MatrixTransformSerializer : public osgDB::ObjectWrapper +{ +public: + MatrixTransformSerializer() + : osgDB::ObjectWrapper(createInstanceFunc, "NifOsg::MatrixTransform", "osg::Object osg::Node osg::Transform osg::MatrixTransform NifOsg::MatrixTransform") + { + } +}; + osgDB::ObjectWrapper* makeDummySerializer(const std::string& classname) { return new osgDB::ObjectWrapper(createInstanceFunc, classname, "osg::Object"); @@ -100,6 +111,7 @@ void registerSerializers() mgr->addWrapper(new MorphGeometrySerializer); mgr->addWrapper(new LightManagerSerializer); mgr->addWrapper(new CameraRelativeTransformSerializer); + mgr->addWrapper(new MatrixTransformSerializer); // Don't serialize Geometry data as we are more interested in the overall structure rather than tons of vertex data that would make the file large and hard to read. mgr->removeWrapper(mgr->findWrapper("osg::Geometry")); @@ -118,7 +130,6 @@ void registerSerializers() "SceneUtil::StateSetUpdater", "SceneUtil::DisableLight", "SceneUtil::MWShadowTechnique", - "NifOsg::NodeUserData", "NifOsg::FlipController", "NifOsg::KeyframeController", "NifOsg::TextKeyMapHolder", @@ -131,7 +142,9 @@ void registerSerializers() "NifOsg::StaticBoundingBoxCallback", "NifOsg::GeomMorpherController", "NifOsg::UpdateMorphGeometry", - "NifOsg::CollisionSwitch", + "NifOsg::UVController", + "NifOsg::VisController", + "NifOsg::NodeIndexHolder", "osgMyGUI::Drawable", "osg::DrawCallback", "osgOQ::ClearQueriesCallback", diff --git a/components/sceneutil/skeleton.cpp b/components/sceneutil/skeleton.cpp index 9be440d93..40f524e0a 100644 --- a/components/sceneutil/skeleton.cpp +++ b/components/sceneutil/skeleton.cpp @@ -18,7 +18,7 @@ public: { } - void apply(osg::Transform &node) + void apply(osg::Transform &node) override { osg::MatrixTransform* bone = node.asMatrixTransform(); if (!bone) diff --git a/components/sceneutil/skeleton.hpp b/components/sceneutil/skeleton.hpp index 1d8069f8e..22988dfd5 100644 --- a/components/sceneutil/skeleton.hpp +++ b/components/sceneutil/skeleton.hpp @@ -60,12 +60,12 @@ namespace SceneUtil bool getActive() const; - void traverse(osg::NodeVisitor& nv); + void traverse(osg::NodeVisitor& nv) override; void markDirty(); - virtual void childInserted(unsigned int); - virtual void childRemoved(unsigned int, unsigned int); + void childInserted(unsigned int) override; + void childRemoved(unsigned int, unsigned int) override; private: // The root bone is not a "real" bone, it has no corresponding node in the scene graph. diff --git a/components/sceneutil/statesetupdater.hpp b/components/sceneutil/statesetupdater.hpp index d12316fb2..25e50acfd 100644 --- a/components/sceneutil/statesetupdater.hpp +++ b/components/sceneutil/statesetupdater.hpp @@ -24,7 +24,7 @@ namespace SceneUtil META_Object(SceneUtil, StateSetUpdater) - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + void operator()(osg::Node* node, osg::NodeVisitor* nv) override; /// Apply state - to override in derived classes /// @note Due to the double buffering approach you *have* to apply all state @@ -57,11 +57,11 @@ namespace SceneUtil void addController(StateSetUpdater* ctrl); - virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv); + void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override; protected: - virtual void setDefaults(osg::StateSet *stateset); + void setDefaults(osg::StateSet *stateset) override; std::vector > mCtrls; }; diff --git a/components/sceneutil/unrefqueue.hpp b/components/sceneutil/unrefqueue.hpp index 7155e669c..84372d28c 100644 --- a/components/sceneutil/unrefqueue.hpp +++ b/components/sceneutil/unrefqueue.hpp @@ -16,7 +16,7 @@ namespace SceneUtil { public: std::deque > mObjects; - virtual void doWork(); + void doWork() override; }; /// @brief Handles unreferencing of objects through the WorkQueue. Typical use scenario diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index ff46329e5..a23f3f109 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -24,7 +24,7 @@ public: { } - virtual void apply(osg::Node& node) + void apply(osg::Node& node) override { if (osg::StateSet* stateset = node.getStateSet()) mLowestUnusedTexUnit = std::max(mLowestUnusedTexUnit, int(stateset->getTextureAttributeList().size())); diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index 5cc8e3a9d..303d609f5 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -19,10 +19,10 @@ namespace SceneUtil GlowUpdater(int texUnit, const osg::Vec4f& color, const std::vector >& textures, osg::Node* node, float duration, Resource::ResourceSystem* resourcesystem); - virtual void setDefaults(osg::StateSet *stateset); + void setDefaults(osg::StateSet *stateset) override; void removeTexture(osg::StateSet* stateset); - virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv); + void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) override; bool isPermanentGlowUpdater(); diff --git a/components/sceneutil/visitor.hpp b/components/sceneutil/visitor.hpp index e1b2a0088..67b8a375c 100644 --- a/components/sceneutil/visitor.hpp +++ b/components/sceneutil/visitor.hpp @@ -20,9 +20,9 @@ namespace SceneUtil { } - virtual void apply(osg::Group& group); - virtual void apply(osg::MatrixTransform& node); - virtual void apply(osg::Geometry& node); + void apply(osg::Group& group) override; + void apply(osg::MatrixTransform& node) override; + void apply(osg::Geometry& node) override; bool checkGroup(osg::Group& group); @@ -39,7 +39,7 @@ namespace SceneUtil { } - virtual void apply(osg::Node &node); + void apply(osg::Node &node) override; std::string mNameToFind; std::vector mFoundNodes; @@ -54,9 +54,9 @@ namespace SceneUtil { } - virtual void apply(osg::MatrixTransform& node); + void apply(osg::MatrixTransform& node) override; - virtual void apply(osg::Drawable& drw); + void apply(osg::Drawable& drw) override; }; /// Maps names to nodes @@ -71,7 +71,7 @@ namespace SceneUtil { } - void apply(osg::MatrixTransform& trans); + void apply(osg::MatrixTransform& trans) override; private: NodeMap& mMap; @@ -100,10 +100,10 @@ namespace SceneUtil class CleanObjectRootVisitor : public RemoveVisitor { public: - virtual void apply(osg::Drawable& drw); - virtual void apply(osg::Group& node); - virtual void apply(osg::MatrixTransform& node); - virtual void apply(osg::Node& node); + void apply(osg::Drawable& drw) override; + void apply(osg::Group& node) override; + void apply(osg::MatrixTransform& node) override; + void apply(osg::Node& node) override; void applyNode(osg::Node& node); void applyDrawable(osg::Node& node); @@ -112,9 +112,9 @@ namespace SceneUtil class RemoveTriBipVisitor : public RemoveVisitor { public: - virtual void apply(osg::Drawable& drw); - virtual void apply(osg::Group& node); - virtual void apply(osg::MatrixTransform& node); + void apply(osg::Drawable& drw) override; + void apply(osg::Group& node) override; + void apply(osg::MatrixTransform& node) override; void applyImpl(osg::Node& node); }; diff --git a/components/sceneutil/waterutil.cpp b/components/sceneutil/waterutil.cpp index 3a17963af..8a434105c 100644 --- a/components/sceneutil/waterutil.cpp +++ b/components/sceneutil/waterutil.cpp @@ -10,7 +10,7 @@ namespace SceneUtil // disable nonsense test against a worldsize bb what will always pass class WaterBoundCallback : public osg::Drawable::ComputeBoundingBoxCallback { - virtual osg::BoundingBox computeBound(const osg::Drawable&) const { return osg::BoundingBox(); } + osg::BoundingBox computeBound(const osg::Drawable&) const override { return osg::BoundingBox(); } }; osg::ref_ptr createWaterGeometry(float size, int segments, float textureRepeats) diff --git a/components/sdlutil/sdlgraphicswindow.cpp b/components/sdlutil/sdlgraphicswindow.cpp index cd5e80c31..0a1951700 100644 --- a/components/sdlutil/sdlgraphicswindow.cpp +++ b/components/sdlutil/sdlgraphicswindow.cpp @@ -118,6 +118,29 @@ void GraphicsWindowSDL2::init() setSwapInterval(_traits->vsync); + // Update traits with what we've actually been given + // Use intermediate to avoid signed/unsigned mismatch + int intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &intermediateLocation); + _traits->red = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &intermediateLocation); + _traits->green = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &intermediateLocation); + _traits->blue = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &intermediateLocation); + _traits->alpha = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &intermediateLocation); + _traits->depth = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &intermediateLocation); + _traits->stencil = intermediateLocation; + + SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &intermediateLocation); + _traits->doubleBuffer = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &intermediateLocation); + _traits->sampleBuffers = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &intermediateLocation); + _traits->samples = intermediateLocation; + SDL_GL_MakeCurrent(oldWin, oldCtx); mValid = true; diff --git a/components/sdlutil/sdlgraphicswindow.hpp b/components/sdlutil/sdlgraphicswindow.hpp index dd8076776..01a97e754 100644 --- a/components/sdlutil/sdlgraphicswindow.hpp +++ b/components/sdlutil/sdlgraphicswindow.hpp @@ -24,53 +24,53 @@ class GraphicsWindowSDL2 : public osgViewer::GraphicsWindow public: GraphicsWindowSDL2(osg::GraphicsContext::Traits *traits); - virtual bool isSameKindAs(const Object* object) const { return dynamic_cast(object)!=0; } - virtual const char* libraryName() const { return "osgViewer"; } - virtual const char* className() const { return "GraphicsWindowSDL2"; } + bool isSameKindAs(const Object* object) const override { return dynamic_cast(object)!=0; } + const char* libraryName() const override { return "osgViewer"; } + const char* className() const override { return "GraphicsWindowSDL2"; } - virtual bool valid() const { return mValid; } + bool valid() const override { return mValid; } /** Realise the GraphicsContext.*/ - virtual bool realizeImplementation(); + bool realizeImplementation()override ; /** Return true if the graphics context has been realised and is ready to use.*/ - virtual bool isRealizedImplementation() const { return mRealized; } + bool isRealizedImplementation() const override { return mRealized; } /** Close the graphics context.*/ - virtual void closeImplementation(); + void closeImplementation() override; /** Make this graphics context current.*/ - virtual bool makeCurrentImplementation(); + bool makeCurrentImplementation() override; /** Release the graphics context.*/ - virtual bool releaseContextImplementation(); + bool releaseContextImplementation() override; /** Swap the front and back buffers.*/ - virtual void swapBuffersImplementation(); + void swapBuffersImplementation() override; /** Set sync-to-vblank. */ - virtual void setSyncToVBlank(bool on); + void setSyncToVBlank(bool on) override; /** Set Window decoration.*/ - virtual bool setWindowDecorationImplementation(bool flag); + bool setWindowDecorationImplementation(bool flag) override; /** Raise specified window */ - virtual void raiseWindow(); + void raiseWindow() override; /** Set the window's position and size.*/ - virtual bool setWindowRectangleImplementation(int x, int y, int width, int height); + bool setWindowRectangleImplementation(int x, int y, int width, int height) override; /** Set the name of the window */ - virtual void setWindowName(const std::string &name); + void setWindowName(const std::string &name) override; /** Set mouse cursor to a specific shape.*/ - virtual void setCursor(MouseCursor cursor); + void setCursor(MouseCursor cursor) override; /** Get focus.*/ - virtual void grabFocus() {} + void grabFocus() override {} /** Get focus on if the pointer is in this window.*/ - virtual void grabFocusIfPointerInWindow() {} + void grabFocusIfPointerInWindow() override {} /** WindowData is used to pass in the SDL2 window handle attached to the GraphicsContext::Traits structure. */ struct WindowData : public osg::Referenced diff --git a/components/sdlutil/sdlvideowrapper.cpp b/components/sdlutil/sdlvideowrapper.cpp index c2963be86..b3ba98ee3 100644 --- a/components/sdlutil/sdlvideowrapper.cpp +++ b/components/sdlutil/sdlvideowrapper.cpp @@ -88,7 +88,37 @@ namespace SDLUtil { SDL_SetWindowSize(mWindow, width, height); SDL_SetWindowBordered(mWindow, windowBorder ? SDL_TRUE : SDL_FALSE); + + centerWindow(); } } + void VideoWrapper::centerWindow() + { + // Resize breaks the sdl window in some cases; see issue: #5539 + SDL_Rect rect{}; + int x = 0; + int y = 0; + int w = 0; + int h = 0; + auto index = SDL_GetWindowDisplayIndex(mWindow); + SDL_GetDisplayBounds(index, &rect); + SDL_GetWindowSize(mWindow, &w, &h); + + x = rect.x; + y = rect.y; + + // Center dimensions that do not fill the screen + if (w < rect.w) + { + x = rect.x + rect.w / 2 - w / 2; + } + if (h < rect.h) + { + y = rect.y + rect.h / 2 - h / 2; + } + + SDL_SetWindowPosition(mWindow, x, y); + } + } diff --git a/components/sdlutil/sdlvideowrapper.hpp b/components/sdlutil/sdlvideowrapper.hpp index 77f0b8039..3866c3ec3 100644 --- a/components/sdlutil/sdlvideowrapper.hpp +++ b/components/sdlutil/sdlvideowrapper.hpp @@ -27,6 +27,8 @@ namespace SDLUtil void setVideoMode(int width, int height, bool fullscreen, bool windowBorder); + void centerWindow(); + private: SDL_Window* mWindow; osg::ref_ptr mViewer; 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); }; } diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 490c9d438..bfaa11282 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -34,6 +34,9 @@ namespace Shader foundPos = source.find_first_of("\n\r", foundPos); foundPos = source.find_first_not_of("\n\r", foundPos); + if (foundPos == std::string::npos) + break; + size_t lineDirectivePosition = source.rfind("#line", foundPos); int lineNumber; if (lineDirectivePosition != std::string::npos) @@ -58,45 +61,39 @@ namespace Shader return true; } - bool parseIncludes(boost::filesystem::path shaderPath, std::string& source, const std::string& templateName) + // Recursively replaces include statements with the actual source of the included files. + // Adjusts #line statements accordingly and detects cyclic includes. + // includingFiles is the set of files that include this file directly or indirectly, and is intentionally not a reference to allow automatic cleanup. + static bool parseIncludes(boost::filesystem::path shaderPath, std::string& source, const std::string& fileName, int& fileNumber, std::set includingFiles) { + // An include is cyclic if it is being included by itself + if (includingFiles.insert(shaderPath/fileName).second == false) + { + Log(Debug::Error) << "Shader " << fileName << " error: Detected cyclic #includes"; + return false; + } + Misc::StringUtils::replaceAll(source, "\r\n", "\n"); - std::set includedFiles; size_t foundPos = 0; - int fileNumber = 1; while ((foundPos = source.find("#include")) != std::string::npos) { size_t start = source.find('"', foundPos); - if (start == std::string::npos || start == source.size()-1) + if (start == std::string::npos || start == source.size() - 1) { - Log(Debug::Error) << "Shader " << templateName << " error: Invalid #include"; + Log(Debug::Error) << "Shader " << fileName << " error: Invalid #include"; return false; } - size_t end = source.find('"', start+1); + size_t end = source.find('"', start + 1); if (end == std::string::npos) { - Log(Debug::Error) << "Shader " << templateName << " error: Invalid #include"; + Log(Debug::Error) << "Shader " << fileName << " error: Invalid #include"; return false; } - std::string includeFilename = source.substr(start+1, end-(start+1)); + std::string includeFilename = source.substr(start + 1, end - (start + 1)); boost::filesystem::path includePath = shaderPath / includeFilename; - boost::filesystem::ifstream includeFstream; - includeFstream.open(includePath); - if (includeFstream.fail()) - { - Log(Debug::Error) << "Shader " << templateName << " error: Failed to open include " << includePath.string(); - return false; - } - - std::stringstream buffer; - buffer << includeFstream.rdbuf(); - std::string stringRepresentation = buffer.str(); - addLineDirectivesAfterConditionalBlocks(stringRepresentation); - - // insert #line directives so we get correct line numbers in compiler errors - int includedFileNumber = fileNumber++; + // Determine the line number that will be used for the #line directive following the included source size_t lineDirectivePosition = source.rfind("#line", foundPos); int lineNumber; if (lineDirectivePosition != std::string::npos) @@ -109,20 +106,34 @@ namespace Shader else { lineDirectivePosition = 0; - lineNumber = 1; + lineNumber = 0; } lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n'); + // Include the file recursively + boost::filesystem::ifstream includeFstream; + includeFstream.open(includePath); + if (includeFstream.fail()) + { + Log(Debug::Error) << "Shader " << fileName << " error: Failed to open include " << includePath.string(); + return false; + } + int includedFileNumber = fileNumber++; + + std::stringstream buffer; + buffer << includeFstream.rdbuf(); + std::string stringRepresentation = buffer.str(); + if (!addLineDirectivesAfterConditionalBlocks(stringRepresentation) + || !parseIncludes(shaderPath, stringRepresentation, includeFilename, fileNumber, includingFiles)) + { + Log(Debug::Error) << "In file included from " << fileName << "." << lineNumber; + return false; + } + std::stringstream toInsert; toInsert << "#line 0 " << includedFileNumber << "\n" << stringRepresentation << "\n#line " << lineNumber << " 0\n"; - source.replace(foundPos, (end-foundPos+1), toInsert.str()); - - if (includedFiles.insert(includePath).second == false) - { - Log(Debug::Error) << "Shader " << templateName << " error: Detected cyclic #includes"; - return false; - } + source.replace(foundPos, (end - foundPos + 1), toInsert.str()); } return true; } @@ -279,21 +290,22 @@ namespace Shader TemplateMap::iterator templateIt = mShaderTemplates.find(templateName); if (templateIt == mShaderTemplates.end()) { - boost::filesystem::path p = (boost::filesystem::path(mPath) / templateName); + boost::filesystem::path path = (boost::filesystem::path(mPath) / templateName); boost::filesystem::ifstream stream; - stream.open(p); + stream.open(path); if (stream.fail()) { - Log(Debug::Error) << "Failed to open " << p.string(); + Log(Debug::Error) << "Failed to open " << path.string(); return nullptr; } std::stringstream buffer; buffer << stream.rdbuf(); // parse includes + int fileNumber = 1; std::string source = buffer.str(); if (!addLineDirectivesAfterConditionalBlocks(source) - || !parseIncludes(boost::filesystem::path(mPath), source, templateName)) + || !parseIncludes(boost::filesystem::path(mPath), source, templateName, fileNumber, {})) return nullptr; templateIt = mShaderTemplates.insert(std::make_pair(templateName, source)).first; diff --git a/components/shader/shadervisitor.hpp b/components/shader/shadervisitor.hpp index 8e35f1d9c..bf1022180 100644 --- a/components/shader/shadervisitor.hpp +++ b/components/shader/shadervisitor.hpp @@ -38,10 +38,10 @@ namespace Shader void setSpecularMapPattern(const std::string& pattern); - virtual void apply(osg::Node& node); + void apply(osg::Node& node) override; - virtual void apply(osg::Drawable& drawable); - virtual void apply(osg::Geometry& geometry); + void apply(osg::Drawable& drawable) override; + void apply(osg::Geometry& geometry) override; void applyStateSet(osg::ref_ptr stateset, osg::Node& node); diff --git a/components/terrain/chunkmanager.hpp b/components/terrain/chunkmanager.hpp index 02a782c62..118df698f 100644 --- a/components/terrain/chunkmanager.hpp +++ b/components/terrain/chunkmanager.hpp @@ -42,7 +42,7 @@ namespace Terrain void setMaxCompositeGeometrySize(float maxCompGeometrySize) { mMaxCompGeometrySize = maxCompGeometrySize; } void setNodeMask(unsigned int mask) { mNodeMask = mask; } - virtual unsigned int getNodeMask() override { return mNodeMask; } + unsigned int getNodeMask() override { return mNodeMask; } void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; diff --git a/components/terrain/compositemaprenderer.hpp b/components/terrain/compositemaprenderer.hpp index 9d5719c23..257173af4 100644 --- a/components/terrain/compositemaprenderer.hpp +++ b/components/terrain/compositemaprenderer.hpp @@ -41,7 +41,7 @@ namespace Terrain CompositeMapRenderer(); ~CompositeMapRenderer(); - virtual void drawImplementation(osg::RenderInfo& renderInfo) const; + void drawImplementation(osg::RenderInfo& renderInfo) const override; void compile(CompositeMap& compositeMap, osg::RenderInfo& renderInfo, double* timeLeft) const; diff --git a/components/terrain/quadtreenode.hpp b/components/terrain/quadtreenode.hpp index a309d91fc..7ae59b92f 100644 --- a/components/terrain/quadtreenode.hpp +++ b/components/terrain/quadtreenode.hpp @@ -42,7 +42,7 @@ namespace Terrain inline QuadTreeNode* getParent() { return mParent; } inline QuadTreeNode* getChild(unsigned int i) { return static_cast(Group::getChild(i)); } - inline unsigned int getNumChildren() const { return _children.size(); } + inline unsigned int getNumChildren() const override { return _children.size(); } // osg::Group::addChild() does a lot of unrelated stuff, but we just really want to add a child node. void addChildNode(QuadTreeNode* child) diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index ca1dcb08c..57c09000c 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -61,7 +61,7 @@ public: { } - virtual ReturnValue isSufficientDetail(QuadTreeNode* node, float dist) + ReturnValue isSufficientDetail(QuadTreeNode* node, float dist) override { const osg::Vec2f& center = node->getCenter(); bool activeGrid = (center.x() > mActiveGrid.x() && center.y() > mActiveGrid.y() && center.x() < mActiveGrid.z() && center.y() < mActiveGrid.w()); @@ -106,7 +106,7 @@ public: mWorld = world; } - virtual void accept(osg::NodeVisitor &nv) + void accept(osg::NodeVisitor &nv) override { if (!nv.validNodeMask(*this)) return; diff --git a/components/terrain/terraindrawable.hpp b/components/terrain/terraindrawable.hpp index a84200f66..dbfdd3c80 100644 --- a/components/terrain/terraindrawable.hpp +++ b/components/terrain/terraindrawable.hpp @@ -30,17 +30,17 @@ namespace Terrain class TerrainDrawable : public osg::Geometry { public: - virtual osg::Object* cloneType() const { return new TerrainDrawable (); } - virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new TerrainDrawable (*this,copyop); } - virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=nullptr; } - virtual const char* className() const { return "TerrainDrawable"; } - virtual const char* libraryName() const { return "Terrain"; } + osg::Object* cloneType() const override { return new TerrainDrawable (); } + osg::Object* clone(const osg::CopyOp& copyop) const override { return new TerrainDrawable (*this,copyop); } + bool isSameKindAs(const osg::Object* obj) const override { return dynamic_cast(obj)!=nullptr; } + const char* className() const override { return "TerrainDrawable"; } + const char* libraryName() const override { return "Terrain"; } TerrainDrawable(); ~TerrainDrawable(); // has to be defined in the cpp file because we only forward declared some members. TerrainDrawable(const TerrainDrawable& copy, const osg::CopyOp& copyop); - virtual void accept(osg::NodeVisitor &nv); + void accept(osg::NodeVisitor &nv) override; void cull(osgUtil::CullVisitor* cv); typedef std::vector > PassVector; @@ -50,7 +50,7 @@ namespace Terrain void createClusterCullingCallback(); - virtual void compileGLObjects(osg::RenderInfo& renderInfo) const; + void compileGLObjects(osg::RenderInfo& renderInfo) const override; void setupWaterBoundingBox(float waterheight, float margin); const osg::BoundingBox& getWaterBoundingBox() const { return mWaterBoundingBox; } diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index 5f99cd97e..679597971 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -17,7 +17,7 @@ class MyView : public View public: osg::ref_ptr mLoaded; - virtual void reset() {} + void reset() override {} }; TerrainGrid::TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask, int borderMask) diff --git a/components/terrain/terraingrid.hpp b/components/terrain/terraingrid.hpp index 8b36448c1..f8b0fb259 100644 --- a/components/terrain/terraingrid.hpp +++ b/components/terrain/terraingrid.hpp @@ -17,15 +17,15 @@ namespace Terrain TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0, int borderMask=0); ~TerrainGrid(); - virtual void cacheCell(View* view, int x, int y); + void cacheCell(View* view, int x, int y) override; /// @note Not thread safe. - virtual void loadCell(int x, int y); + void loadCell(int x, int y) override; /// @note Not thread safe. - virtual void unloadCell(int x, int y); + void unloadCell(int x, int y) override; - View* createView(); + View* createView() override; protected: bool isGridEmpty() const { return mGrid.empty(); } diff --git a/components/terrain/texturemanager.hpp b/components/terrain/texturemanager.hpp index e1205606e..46c363055 100644 --- a/components/terrain/texturemanager.hpp +++ b/components/terrain/texturemanager.hpp @@ -27,7 +27,7 @@ namespace Terrain osg::ref_ptr getTexture(const std::string& name); - virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const; + void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; private: Resource::SceneManager* mSceneManager; diff --git a/components/terrain/viewdata.hpp b/components/terrain/viewdata.hpp index 400d9fbbe..028935258 100644 --- a/components/terrain/viewdata.hpp +++ b/components/terrain/viewdata.hpp @@ -21,7 +21,7 @@ namespace Terrain void add(QuadTreeNode* node); - void reset(); + void reset() override; bool suitableToUse(const osg::Vec4i& activeGrid) const; diff --git a/components/terrain/world.hpp b/components/terrain/world.hpp index 9f08454c8..d94125100 100644 --- a/components/terrain/world.hpp +++ b/components/terrain/world.hpp @@ -70,7 +70,7 @@ namespace Terrain return mMask; } - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + void operator()(osg::Node* node, osg::NodeVisitor* nv) override { if (mLowZ <= mHighZ) traverse(node, nv); diff --git a/components/vfs/bsaarchive.hpp b/components/vfs/bsaarchive.hpp index a87f278c7..65a9db16c 100644 --- a/components/vfs/bsaarchive.hpp +++ b/components/vfs/bsaarchive.hpp @@ -12,7 +12,7 @@ namespace VFS public: BsaArchiveFile(const Bsa::BSAFile::FileStruct* info, Bsa::BSAFile* bsa); - virtual Files::IStreamPtr open(); + Files::IStreamPtr open() override; const Bsa::BSAFile::FileStruct* mInfo; Bsa::BSAFile* mFile; @@ -23,7 +23,7 @@ namespace VFS public: BsaArchive(const std::string& filename); virtual ~BsaArchive(); - virtual void listResources(std::map& out, char (*normalize_function) (char)); + void listResources(std::map& out, char (*normalize_function) (char)) override; private: std::unique_ptr mFile; diff --git a/components/vfs/filesystemarchive.hpp b/components/vfs/filesystemarchive.hpp index 6c8e1b82b..d228ba87c 100644 --- a/components/vfs/filesystemarchive.hpp +++ b/components/vfs/filesystemarchive.hpp @@ -11,7 +11,7 @@ namespace VFS public: FileSystemArchiveFile(const std::string& path); - virtual Files::IStreamPtr open(); + Files::IStreamPtr open() override; private: std::string mPath; @@ -23,7 +23,7 @@ namespace VFS public: FileSystemArchive(const std::string& path); - virtual void listResources(std::map& out, char (*normalize_function) (char)); + void listResources(std::map& out, char (*normalize_function) (char)) override; private: diff --git a/components/widgets/fontwrapper.hpp b/components/widgets/fontwrapper.hpp index 8b0011dda..daa69f920 100644 --- a/components/widgets/fontwrapper.hpp +++ b/components/widgets/fontwrapper.hpp @@ -11,14 +11,14 @@ namespace Gui class FontWrapper : public T { public: - virtual void setFontName(const std::string& name) + void setFontName(const std::string& name) override { T::setFontName(name); T::setPropertyOverride ("FontHeight", getFontSize()); } protected: - virtual void setPropertyOverride(const std::string& _key, const std::string& _value) + void setPropertyOverride(const std::string& _key, const std::string& _value) override { T::setPropertyOverride (_key, _value); diff --git a/docs/source/manuals/installation/install-game-files.rst b/docs/source/manuals/installation/install-game-files.rst index ac3688e88..538cfd4c6 100644 --- a/docs/source/manuals/installation/install-game-files.rst +++ b/docs/source/manuals/installation/install-game-files.rst @@ -105,6 +105,19 @@ If you are running macOS, you can also download Morrowind through Steam: #. Launch the Steam client and let it download. You can then find ``Morrowind.esm`` at ``~/Library/Application Support/Steam/steamapps/common/The Elder Scrolls III - Morrowind/Data Files/`` +Linux +---- +Debian/Ubuntu - using "Steam Proton" & "OpenMW launcher". +---- +#. Install Steam from "Ubuntu Software" Center +#. Enable Proton (basically WINE under the hood). This is done in the Steam client menu drop down. Select, "Steam | Settings" then in the "SteamPlay" section check the box next to "enable steam play for all other titles" +#. Now Morrowind should be selectable in your game list (as long as you own it). You can install it like any other game, choose to install it and remember the directory path of the location you pick. +#. Once the game files are installed, we can now install the open OpenMW Engine. I used "OpenMW launcher" from "Ubuntu Software" Center this has a wizard to help with the basic setup of OpenMW. +#. Launch "OpenMW launcher" and follow the setup wizard, when asked, point it at the location you installed Morrowind to, we will be looking for the directory that contains the Morrowing.esm file, for example '/steam library/steamapps/common/Morrowind/Data Files/'. +#. Everything should now be in place, click that big "PLAY" button and fire up OpenMW. + +Nb. Bloodmoon.esm needs to be below Tribunal.esm in your datafiles list, if you dont have the right order a red "!" will apear next to the filename in the datafiles section of the OpenMW launcher, just drag bloodmoon below tribunal to fix it. + Wine ---- diff --git a/docs/source/reference/modding/extended.rst b/docs/source/reference/modding/extended.rst index bf2b2b74f..9e8db49fd 100644 --- a/docs/source/reference/modding/extended.rst +++ b/docs/source/reference/modding/extended.rst @@ -242,33 +242,39 @@ Every weapon type has an attack animation group and a suffix for the movement an For example, long blades use ``weapononehand`` attack animation group, ``idle1h`` idle animation group, ``jump1h`` jumping animation group, etc. This is the full table of supported animation groups: -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Weapon type | Animation group | Movement suffix | Attack (fallback) | Suffix (fallback) | -+===============+===================+==================+======================+=======================+ -| Short blade | shortbladeonehand | 1s | weapononehand | 1h | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Long blade 1H | weapononehand | 1h | | | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Long blade 2H | weapontwohand | 2c | | | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Blunt 1H | bluntonehand | 1b | weapononehand | 1h | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Blunt 2H | blunttwohand | 2b | weapontwohand | 2c | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Axe 1H | bluntonehand | 1b | weapononehand | 1h | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Axe 2H | blunttwohand | 2b | weapontwohand | 2c | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Blunt 2H wide | weapontwowide | 2w | weapontwohand | 2c | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Spear | weapontwowide | 2w | weapontwohand | 2c | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Bow | bowandarrow | bow | | 1h | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Crossbow | crossbow | crossbow | | 1h | -+---------------+-------------------+------------------+----------------------+-----------------------+ -| Thrown | throwweapon | 1t | | 1h | -+---------------+-------------------+------------------+----------------------+-----------------------+ ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Weapon type | Animation group | Movement suffix | Attack (fallback) | Suffix (fallback) | Attach bone | ++===============+===================+==================+======================+=======================+=======================+ +| Short blade | shortbladeonehand | 1s | weapononehand | 1h | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Long blade 1H | weapononehand | 1h | | | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Long blade 2H | weapontwohand | 2c | | | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Blunt 1H | bluntonehand | 1b | weapononehand | 1h | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Blunt 2H | blunttwohand | 2b | weapontwohand | 2c | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Axe 1H | bluntonehand | 1b | weapononehand | 1h | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Axe 2H | blunttwohand | 2b | weapontwohand | 2c | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Blunt 2H wide | weapontwowide | 2w | weapontwohand | 2c | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Spear | weapontwowide | 2w | weapontwohand | 2c | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Bow | bowandarrow | bow | | 1h | Weapon Bone Left | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Crossbow | crossbow | crossbow | | 1h | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ +| Thrown | throwweapon | 1t | | 1h | Weapon Bone | ++---------------+-------------------+------------------+----------------------+-----------------------+-----------------------+ + +Note that bows can be attached to the "Weapon Bone Left" bone if it is present in shooter's skeleton, and if it is not, "Weapon Bone" is used as a fallback. + +Also it is possible to add a "Bip01 Arrow" bone to actor skeletons. In this case OpenMW attaches arrows to this bone instead of ArrowBone in the bow mesh. +Such approach allows to implement better shooting animations (for example, beast races have tail, so quivers should be attached under different angle and +default arrow fetching animation does not look good). .. _`Graphic Herbalism`: https://www.nexusmods.com/morrowind/mods/46599 .. _`OpenMW Containers Animated`: https://www.nexusmods.com/morrowind/mods/46232 diff --git a/docs/source/reference/modding/paths.rst b/docs/source/reference/modding/paths.rst index ea9b6c416..97cfe37a5 100644 --- a/docs/source/reference/modding/paths.rst +++ b/docs/source/reference/modding/paths.rst @@ -43,16 +43,16 @@ Savegames Screenshots ----------- -+--------------+-----------------------------------------------------------------------------------------------+ -| OS | Location | -+==============+===============================================================================================+ -| Linux | ``$HOME/.local/share/openmw`` | -+--------------+-----------------------------------------------------------------------------------------------+ -| Mac | ``$HOME/Library/Application\ Support/openmw`` | -+--------------+---------------+-------------------------------------------------------------------------------+ -| Windows | File Explorer | ``Documents\My Games\OpenMW`` | -| | | | -| | PowerShell | ``Join-Path ([environment]::GetFolderPath("mydocuments")) "My Games\OpenMW"`` | -| | | | -| | Example | ``C:\Users\Username\Documents\My Games\OpenMW`` | -+--------------+---------------+-------------------------------------------------------------------------------+ ++--------------+-----------------------------------------------------------------------------------------------------------+ +| OS | Location | ++==============+===========================================================================================================+ +| Linux | ``$HOME/.local/share/openmw/screenshots`` | ++--------------+-----------------------------------------------------------------------------------------------------------+ +| Mac | ``$HOME/Library/Application\ Support/openmw/screenshots`` | ++--------------+---------------+-------------------------------------------------------------------------------------------+ +| Windows | File Explorer | ``Documents\My Games\OpenMW\screenshots`` | +| | | | +| | PowerShell | ``Join-Path ([environment]::GetFolderPath("mydocuments")) "My Games\OpenMW\screenshots"`` | +| | | | +| | Example | ``C:\Users\Username\Documents\My Games\OpenMW\screenshots`` | ++--------------+---------------+-------------------------------------------------------------------------------------------+ diff --git a/docs/source/reference/modding/settings/GUI.rst b/docs/source/reference/modding/settings/GUI.rst index bbe6b8336..349a98697 100644 --- a/docs/source/reference/modding/settings/GUI.rst +++ b/docs/source/reference/modding/settings/GUI.rst @@ -148,7 +148,8 @@ color topic enable :Range: True/False :Default: False -Control wether additionnal formatting will be applied to dialogs topic. See 'color topic specific' and 'color topic exhausted' for details. +This setting controls whether the topics available in the dialogue topic list are coloured according to their state. +See 'color topic specific' and 'color topic exhausted' for details. color topic specific -------------------- @@ -157,11 +158,11 @@ color topic specific :Range: 0.0 to 1.0 :Default: empty -This setting overrides the color of keywords in the dialogue topic window. +This setting overrides the colour of dialogue topics that have a response unique to the actors speaking. The value is composed of four floating point values representing the red, green, blue and alpha channels. The alpha value is currently ignored. -The color is overriden if the actor is about to give an answer that is unique to him (that is, dialogue with their object ID in the Actor field) that wasn't seen yet. +A topic response is considered unique if its Actor filter field contains the speaking actor's object ID and hasn't yet been read. color topic exhausted --------------------- @@ -170,8 +171,8 @@ color topic exhausted :Range: 0.0 to 1.0 :Default: empty -This setting overrides the color of keywords in the dialogue topic window. +This setting overrides the colour of dialogue topics which have been "exhausted" by the player. The value is composed of four floating point values representing the red, green, blue and alpha channels. The alpha value is currently ignored. -The color is overridden if the next actor responses to the topic keyword has already been seen by the player. +A topic is considered "exhausted" if the response the player is about to see has already been seen. diff --git a/docs/source/reference/modding/settings/camera.rst b/docs/source/reference/modding/settings/camera.rst index 18b6754a7..5701947dc 100644 --- a/docs/source/reference/modding/settings/camera.rst +++ b/docs/source/reference/modding/settings/camera.rst @@ -136,7 +136,7 @@ This setting controls third person view mode. False: View is centered on the character's head. Crosshair is hidden. True: In non-combat mode camera is positioned behind the character's shoulder. Crosshair is visible in third person mode as well. -This setting can only be configured by editing the settings configuration file. +This setting can be controlled in Advanced tab of the launcher. view over shoulder offset ------------------------- @@ -160,7 +160,7 @@ auto switch shoulder 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. +This setting can be controlled in Advanced tab of the launcher. zoom out when move coef ----------------------- @@ -181,9 +181,10 @@ preview if stand still :Range: True/False :Default: False +Makes difference only in third person mode. 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. +This setting can be controlled in Advanced tab of the launcher. deferred preview rotation ------------------------- @@ -196,5 +197,52 @@ 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 be controlled in Advanced tab of the launcher. + +head bobbing +------------ + +:Type: boolean +:Range: True/False +:Default: False + +Enables head bobbing when move in first person mode. + +This setting can be controlled in Advanced tab of the launcher. + +head bobbing step +----------------- + +:Type: floating point +:Range: >0 +:Default: 90.0 + +Makes diffence only in first person mode if 'head bobbing' is enabled. +Length of each step. + +This setting can only be configured by editing the settings configuration file. + +head bobbing height +------------------- + +:Type: floating point +:Range: Any +:Default: 3.0 + +Makes diffence only in first person mode if 'head bobbing' is enabled. +Amplitude of the head bobbing. + +This setting can only be configured by editing the settings configuration file. + +head bobbing roll +----------------- + +:Type: floating point +:Range: 0-90 +:Default: 0.2 + +Makes diffence only in first person mode if 'head bobbing' is enabled. +Maximum roll angle in degrees. + This setting can only be configured by editing the settings configuration file. diff --git a/docs/source/reference/modding/settings/fog.rst b/docs/source/reference/modding/settings/fog.rst new file mode 100644 index 000000000..10ab0bbe3 --- /dev/null +++ b/docs/source/reference/modding/settings/fog.rst @@ -0,0 +1,115 @@ +Fog Settings +############ + +use distant fog +--------------- + +:Type: boolean +:Range: True/False +:Default: False + +This setting overhauls the behavior of fog calculations. + +Normally the fog start and end distance are proportional to the viewing distance +and use the fog depth set in the fallback settings. + +Enabling this setting separates the fog distance from the viewing distance and fallback settings and makes fog distance +and apparent density dependent on the weather and the current location according to the settings below. + +Unfortunately specific weather-dependent fog factor and offset parameters are currently hard-coded. +They are based off the default settings of MGE XE. + ++--------------+------------+--------+ +| Weather Type | Fog Factor | Offset | ++==============+============+========+ +| Clear | 1.0 | 0.0 | ++--------------+------------+--------+ +| Cloudy | 0.9 | 0.0 | ++--------------+------------+--------+ +| Foggy | 0.2 | 0.3 | ++--------------+------------+--------+ +| Overcast | 0.7 | 0.0 | ++--------------+------------+--------+ +| Rain | 0.5 | 0.1 | ++--------------+------------+--------+ +| Thunderstorm | 0.5 | 0.2 | ++--------------+------------+--------+ +| Ashstorm | 0.2 | 0.5 | ++--------------+------------+--------+ +| Blight | 0.2 | 0.6 | ++--------------+------------+--------+ +| Snow | 0.5 | 0.4 | ++--------------+------------+--------+ +| Blizzard | 0.16 | 0.7 | ++--------------+------------+--------+ + +Non-underwater fog start and end distance are calculated like this according to these parameters:: + + fog start distance = fog factor * (base fog start distance - fog offset * base fog end distance) + fog end distance = fog factor * (1.0 - fog offset) * base fog end distance + +Underwater fog distance is used as-is. + +A negative fog start distance means that the fog starts behind the camera +so the entirety of the scene will be at least partially fogged. + +A negative fog end distance means that the fog ends behind the camera +so the entirety of the scene will be completely submerged in the fog. + +Fog end distance should be larger than the fog start distance. + +This setting and all further settings can only be configured by editing the settings configuration file. + +distant land fog start +---------------------- + +:Type: floating point +:Range: The whole range of 32-bit floating point +:Default: 16384 (2 cells) + +This is the base fog start distance used for distant fog calculations in exterior locations. + +distant land fog end +-------------------- + +:Type: floating point +:Range: The whole range of 32-bit floating point +:Default: 40960 (5 cells) + +This is the base fog end distance used for distant fog calculations in exterior locations. + +distant underwater fog start +---------------------------- + +:Type: floating point +:Range: The whole range of 32-bit floating point +:Default: -4096 + +This is the base fog start distance used for distant fog calculations in underwater locations. + +distant underwater fog end +-------------------------- + +:Type: floating point +:Range: The whole range of 32-bit floating point +:Default: 2457.6 + +This is the base fog end distance used for distant fog calculations in underwater locations. + +distant interior fog start +-------------------------- + +:Type: floating point +:Range: The whole range of 32-bit floating point +:Default: 0 + +This is the base fog start distance used for distant fog calculations in interior locations. + +distant interior fog end +------------------------ + +:Type: floating point +:Range: The whole range of 32-bit floating point +:Default: 16384 (2 cells) + +This is the base fog end distance used for distant fog calculations in interior locations. diff --git a/docs/source/reference/modding/settings/game.rst b/docs/source/reference/modding/settings/game.rst index 8d0b0dfc1..fd93eba61 100644 --- a/docs/source/reference/modding/settings/game.rst +++ b/docs/source/reference/modding/settings/game.rst @@ -327,18 +327,76 @@ Affects side and diagonal movement. Enabling this setting makes movement more re If disabled then the whole character's body is pointed to the direction of view. Diagonal movement has no special animation and causes sliding. -If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it also changes straight right and straight left movement. +If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it changes straight right and straight left movement as well. Also turns the whole body up or down when swimming according to the movement direction. + +This setting can be controlled in Advanced tab of the launcher. + +smooth movement +--------------- + +:Type: boolean +:Range: True/False +:Default: False + +Makes NPCs and player movement more smooth. + +Recommended to use with "turn to movement direction" enabled. + +This setting can be controlled in Advanced tab of the launcher. + +smooth movement player turning delay +------------------------------------ + +:Type: floating point +:Range: >= 0.01 +:Default: 0.333 + +Max delay of turning (in seconds) if player drastically changes direction on the run. Makes sense only if "smooth movement" is enabled. This setting can only be configured by editing the settings configuration file. +NPCs avoid collisions +--------------------- + +:Type: boolean +:Range: True/False +:Default: False + +If enabled NPCs apply evasion maneuver to avoid collisions with others. + +This setting can be controlled in Advanced tab of the launcher. + +NPCs give way +------------- + +:Type: boolean +:Range: True/False +:Default: True + +Standing NPCs give way to moving ones. Works only if 'NPCs avoid collisions' is enabled. + +This setting can only be configured by editing the settings configuration file. + +swim upward correction +---------------------- + +:Type: boolean +:Range: True/False +:Default: False + +Makes player swim a bit upward from the line of sight. Applies only in third person mode. Intended to make simpler swimming without diving. + +This setting can be controlled in Advanced tab of the launcher. + swim upward coef ---------------- :Type: floating point :Range: -1.0 to 1.0 -:Default: 0.0 +:Default: 0.2 -Makes player swim a bit upward (or downward in case of negative value) from the line of sight. Intended to make simpler swimming without diving. Recommened range of values is from 0.0 to 0.2. +Regulates strength of the "swim upward correction" effect (if enabled). +Makes player swim a bit upward (or downward in case of negative value) from the line of sight. Recommened range of values is from 0.0 to 0.25. This setting can only be configured by editing the settings configuration file. @@ -356,3 +414,17 @@ If disabled then the 3 best skills of trainers and the training limits take into If enabled then the 3 best skills of trainers and the training limits are based on the trainer base skills. This setting can be controlled in Advanced tab of the launcher. + +always allow stealing from knocked out actors +--------------------------------------------- + +:Type: boolean +:Range: True/False +:Default: False + +By Bethesda's design, in the latest released version of Morrowind pickpocketing is impossible during combat, +even if the fighting NPC is knocked out. + +This setting allows the player to steal items from fighting NPCs that were knocked out if enabled. + +This setting can be controlled in Advanced tab of the launcher. diff --git a/docs/source/reference/modding/settings/general.rst b/docs/source/reference/modding/settings/general.rst index be253d613..c885f77aa 100644 --- a/docs/source/reference/modding/settings/general.rst +++ b/docs/source/reference/modding/settings/general.rst @@ -29,7 +29,7 @@ Specify the format for screen shots taken by pressing the screen shot key (bound This setting should be the file extension commonly associated with the desired format. The formats supported will be determined at compilation, but "jpg", "png", and "tga" should be allowed. -This setting can only be configured by editing the settings configuration file. +This setting can be configured in Advanced tab of the launcher. texture mag filter ------------------ @@ -58,4 +58,4 @@ texture mipmap Set the texture mipmap type to control the method mipmaps are created. Mipmapping is a way of reducing the processing power needed during minification -by pregenerating a series of smaller textures. \ No newline at end of file +by pregenerating a series of smaller textures. diff --git a/docs/source/reference/modding/settings/index.rst b/docs/source/reference/modding/settings/index.rst index 53b097a54..2261fe8e1 100644 --- a/docs/source/reference/modding/settings/index.rst +++ b/docs/source/reference/modding/settings/index.rst @@ -41,6 +41,7 @@ The ranges included with each setting are the physically possible ranges, not re camera cells + fog map GUI HUD @@ -56,3 +57,4 @@ The ranges included with each setting are the physically possible ranges, not re water windows navigator + physics diff --git a/docs/source/reference/modding/settings/physics.rst b/docs/source/reference/modding/settings/physics.rst new file mode 100644 index 000000000..59aba91aa --- /dev/null +++ b/docs/source/reference/modding/settings/physics.rst @@ -0,0 +1,37 @@ +Physics Settings +################ + +async num threads +----------------- + +:Type: integer +:Range: >= 0 +:Default: 0 + +Determines how many threads will be spawned to compute physics update in the background (that is, process actors movement). A value of 0 means that the update will be performed in the main thread. +A value greater than 1 requires the Bullet library be compiled with multithreading support. If that's not the case, a warning will be written in ``openmw.log`` and a value of 1 will be used. + +lineofsight keep inactive cache +------------------------------- + +:Type: integer +:Range: >= -1 +:Default: 0 + +The line of sight determines if 2 actors can see each other (without taking into account game mechanics such as invisibility or sneaking). It is used by some scripts (the getLOS function), by the AI (to determine if an actor should start combat or chase an opponent) and for functionnalities such as greetings or turning NPC head toward an object. +This parameters determine for how long a cache of request should be kept warm. It depends on :ref:`async num threads` being > 0, otherwise a value of -1 will be used. If a request is not found in the cache, it is always fulfilled immediately. In case Bullet is compiled without multithreading support, non-cached requests involve blocking the async thread(s), which might hurt performance. +A value of -1 means no caching. +A value of 0 means that for as long as a request is made (after the first one), it will be preemptively "refreshed" in the async thread, without blocking neither the main thread nor the async thread. +Any value > 0 is the number of frames for which the values are kept in cache even if the results was not requested again. +If Bullet is compiled with multithreading support, requests are non blocking, it is better to set this parameter to -1. + +defer aabb update +----------------- + +:Type: boolean +:Range: True/False +:Default: True + +Axis-aligned bounding box (aabb for short) are used by Bullet for collision detection. They should be updated anytime a physical object is modified (for instance moved) for collision detection to be correct. +This parameter control wether the update should be done as soon as the object is modified (the default), which involves blocking the async thread(s), or queue the modifications to update them as a batch before the collision detections. It depends on :ref:`async num threads` being > 0, otherwise it will be disabled. +Disabling this parameter is intended as an aid for debugging collisions detection issues. diff --git a/extern/oics/tinyxml.h b/extern/oics/tinyxml.h index 7237825c5..7b5daedf9 100644 --- a/extern/oics/tinyxml.h +++ b/extern/oics/tinyxml.h @@ -865,10 +865,11 @@ public: /* Attribute parsing starts: first letter of the name returns: the next char after the value end quote */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { + void Print( FILE* cfile, int depth ) const override + { Print( cfile, depth, 0 ); } void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; @@ -1112,21 +1113,21 @@ public: const char* GetText() const; /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; + TiXmlNode* Clone() const override; // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; + void Print( FILE* cfile, int depth ) const override; /* Attribtue parsing starts: next char past '<' returns: next char past '>' */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlElement* ToElement() const override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlElement* ToElement() override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + bool Accept( TiXmlVisitor* visitor ) const override; protected: @@ -1135,7 +1136,7 @@ protected: // Used to be public [internal use] #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ) override; #endif /* [internal use] Reads the "value" of the element -- another element, or text. @@ -1166,28 +1167,28 @@ public: virtual ~TiXmlComment() {} /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; + TiXmlNode* Clone() const override; // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; + void Print( FILE* cfile, int depth ) const override; /* Attribtue parsing starts: at the ! of the !-- returns: next char past '>' */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlComment* ToComment() const override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlComment* ToComment() override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + bool Accept( TiXmlVisitor* visitor ) const override; protected: void CopyTo( TiXmlComment* target ) const; // used to be public #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ) override; #endif // virtual void StreamOut( TIXML_OSTREAM * out ) const; @@ -1229,31 +1230,31 @@ public: void operator=( const TiXmlText& base ) { base.CopyTo( this ); } // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; + void Print( FILE* cfile, int depth ) const override; /// Queries whether this represents text using a CDATA section. bool CDATA() const { return cdata; } /// Turns on or off a CDATA representation of text. void SetCDATA( bool _cdata ) { cdata = _cdata; } - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlText* ToText() const override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlText* ToText() override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ - virtual bool Accept( TiXmlVisitor* content ) const; + bool Accept( TiXmlVisitor* content ) const override; protected : /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; + TiXmlNode* Clone() const override; void CopyTo( TiXmlText* target ) const; bool Blank() const; // returns true if all white space and new lines // [internal use] #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ) override; #endif private: @@ -1305,27 +1306,28 @@ public: const char *Standalone() const { return standalone.c_str (); } /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; + TiXmlNode* Clone() const override; // Print this declaration to a FILE stream. virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { + void Print( FILE* cfile, int depth ) const override + { Print( cfile, depth, 0 ); } - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlDeclaration* ToDeclaration() const override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlDeclaration* ToDeclaration()override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + bool Accept( TiXmlVisitor* visitor ) const override; protected: void CopyTo( TiXmlDeclaration* target ) const; // used to be public #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ) override; #endif private: @@ -1353,24 +1355,24 @@ public: void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; + TiXmlNode* Clone() const override; // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; + void Print( FILE* cfile, int depth ) const override; - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) override; - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlUnknown* ToUnknown() const override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlUnknown* ToUnknown()override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ - virtual bool Accept( TiXmlVisitor* content ) const; + bool Accept( TiXmlVisitor* content ) const override; protected: void CopyTo( TiXmlUnknown* target ) const; #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ) override; #endif private: @@ -1439,7 +1441,7 @@ public: method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml to use that encoding, regardless of what TinyXml might otherwise try to detect. */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) override; /** Get the root element -- the only top level element -- of the document. In well formed XML, there should only be one. TinyXml is tolerant of @@ -1521,22 +1523,22 @@ public: //char* PrintToMemory() const; /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; + void Print( FILE* cfile, int depth = 0 ) const override; // [internal use] void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + const TiXmlDocument* ToDocument() const override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlDocument* ToDocument() override { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ - virtual bool Accept( TiXmlVisitor* content ) const; + bool Accept( TiXmlVisitor* content ) const override; protected : // [internal use] - virtual TiXmlNode* Clone() const; + TiXmlNode* Clone() const override; #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ) override; #endif private: @@ -1736,16 +1738,16 @@ public: TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), buffer(), indent( " " ), lineBreak( "\n" ) {} - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); + bool VisitEnter( const TiXmlDocument& doc ) override; + bool VisitExit( const TiXmlDocument& doc ) override; - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); + bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) override; + bool VisitExit( const TiXmlElement& element ) override; - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); + bool Visit( const TiXmlDeclaration& declaration ) override; + bool Visit( const TiXmlText& text ) override; + bool Visit( const TiXmlComment& comment ) override; + bool Visit( const TiXmlUnknown& unknown ) override; /** Set the indent characters for printing. By default 4 spaces but tab (\t) is also useful, or null/empty string for no indentation. diff --git a/extern/osgQt/GraphicsWindowQt b/extern/osgQt/GraphicsWindowQt index 5b1e53734..18fcb754f 100644 --- a/extern/osgQt/GraphicsWindowQt +++ b/extern/osgQt/GraphicsWindowQt @@ -84,10 +84,10 @@ protected: qreal _devicePixelRatio; - virtual void resizeEvent( QResizeEvent* event ); - virtual void moveEvent( QMoveEvent* event ); - virtual void glDraw(); - virtual bool event( QEvent* event ); + void resizeEvent( QResizeEvent* event ) override; + void moveEvent( QMoveEvent* event ) override; + void glDraw() override; + bool event( QEvent* event ) override; }; class GraphicsWindowQt : public osgViewer::GraphicsWindow @@ -118,28 +118,28 @@ public: static void qglFormat2traits( const QGLFormat& format, osg::GraphicsContext::Traits* traits ); static osg::GraphicsContext::Traits* createTraits( const QGLWidget* widget ); - virtual bool setWindowRectangleImplementation( int x, int y, int width, int height ); - virtual void getWindowRectangle( int& x, int& y, int& width, int& height ); - virtual bool setWindowDecorationImplementation( bool windowDecoration ); - virtual bool getWindowDecoration() const; - virtual void grabFocus(); - virtual void grabFocusIfPointerInWindow(); - virtual void raiseWindow(); - virtual void setWindowName( const std::string& name ); - virtual std::string getWindowName(); - virtual void useCursor( bool cursorOn ); - virtual void setCursor( MouseCursor cursor ); + bool setWindowRectangleImplementation( int x, int y, int width, int height ) override; + void getWindowRectangle( int& x, int& y, int& width, int& height ) override; + bool setWindowDecorationImplementation( bool windowDecoration ) override; + bool getWindowDecoration() const override; + void grabFocus() override; + void grabFocusIfPointerInWindow( )override; + void raiseWindow() override; + void setWindowName( const std::string& name ) override; + std::string getWindowName() override; + void useCursor( bool cursorOn ) override; + void setCursor( MouseCursor cursor ) override; - virtual bool valid() const; - virtual bool realizeImplementation(); - virtual bool isRealizedImplementation() const; - virtual void closeImplementation(); - virtual bool makeCurrentImplementation(); - virtual bool releaseContextImplementation(); - virtual void swapBuffersImplementation(); - virtual void runOperations(); + bool valid() const override; + bool realizeImplementation() override; + bool isRealizedImplementation() const override; + void closeImplementation() override; + bool makeCurrentImplementation() override; + bool releaseContextImplementation() override; + void swapBuffersImplementation() override; + void runOperations() override; - virtual void requestWarpPointer( float x, float y ); + void requestWarpPointer( float x, float y ) override; protected: diff --git a/extern/osgQt/GraphicsWindowQt.cpp b/extern/osgQt/GraphicsWindowQt.cpp index 784cf9179..4755ad4a8 100644 --- a/extern/osgQt/GraphicsWindowQt.cpp +++ b/extern/osgQt/GraphicsWindowQt.cpp @@ -564,7 +564,7 @@ public: } // Return the number of screens present in the system - virtual unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& /*si*/ ) + unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& /*si*/ ) override { OSG_WARN << "osgQt: getNumScreens() not implemented yet." << std::endl; return 0; @@ -572,26 +572,26 @@ public: // Return the resolution of specified screen // (0,0) is returned if screen is unknown - virtual void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, osg::GraphicsContext::ScreenSettings & /*resolution*/ ) + void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, osg::GraphicsContext::ScreenSettings & /*resolution*/ ) override { OSG_WARN << "osgQt: getScreenSettings() not implemented yet." << std::endl; } // Set the resolution for given screen - virtual bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, const osg::GraphicsContext::ScreenSettings & /*resolution*/ ) + bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, const osg::GraphicsContext::ScreenSettings & /*resolution*/ ) override { OSG_WARN << "osgQt: setScreenSettings() not implemented yet." << std::endl; return false; } // Enumerates available resolutions - virtual void enumerateScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*screenIdentifier*/, osg::GraphicsContext::ScreenSettingsList & /*resolution*/ ) + void enumerateScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*screenIdentifier*/, osg::GraphicsContext::ScreenSettingsList & /*resolution*/ ) override { OSG_WARN << "osgQt: enumerateScreenSettings() not implemented yet." << std::endl; } // Create a graphics context with given traits - virtual osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits ) + osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits ) override { if (traits->pbuffer) { diff --git a/extern/recastnavigation/CMakeLists.txt b/extern/recastnavigation/CMakeLists.txt index 4952e51da..0d31c2e36 100644 --- a/extern/recastnavigation/CMakeLists.txt +++ b/extern/recastnavigation/CMakeLists.txt @@ -1,5 +1,10 @@ cmake_minimum_required(VERSION 3.0) +# for link time optimization, remove if cmake version is >= 3.9 +if(POLICY CMP0069) + cmake_policy(SET CMP0069 NEW) +endif() + project(RecastNavigation) # lib versions diff --git a/extern/recastnavigation/DebugUtils/Include/DebugDraw.h b/extern/recastnavigation/DebugUtils/Include/DebugDraw.h index 00b544d1c..f47df0b7b 100644 --- a/extern/recastnavigation/DebugUtils/Include/DebugDraw.h +++ b/extern/recastnavigation/DebugUtils/Include/DebugDraw.h @@ -206,11 +206,11 @@ class duDisplayList : public duDebugDraw public: duDisplayList(int cap = 512); ~duDisplayList(); - virtual void depthMask(bool state); - virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f); - virtual void vertex(const float x, const float y, const float z, unsigned int color); - virtual void vertex(const float* pos, unsigned int color); - virtual void end(); + void depthMask(bool state) override; + void begin(duDebugDrawPrimitives prim, float size = 1.0f) override; + void vertex(const float x, const float y, const float z, unsigned int color) override; + void vertex(const float* pos, unsigned int color) override; + void end() override; void clear(); void draw(struct duDebugDraw* dd); private: diff --git a/extern/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp b/extern/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp index 839ee1e81..265b10b34 100644 --- a/extern/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp +++ b/extern/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp @@ -640,7 +640,7 @@ public: dtPolyRef nearestRef() const { return m_nearestRef; } const float* nearestPoint() const { return m_nearestPoint; } - void process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count) + void process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count) override { dtIgnoreUnused(polys); @@ -842,7 +842,7 @@ public: int numCollected() const { return m_numCollected; } bool overflowed() const { return m_overflow; } - void process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count) + void process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count) override { dtIgnoreUnused(tile); dtIgnoreUnused(polys); diff --git a/files/mygui/DejaVu Font License.txt b/files/mygui/DejaVuFontLicense.txt similarity index 100% rename from files/mygui/DejaVu Font License.txt rename to files/mygui/DejaVuFontLicense.txt diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index a98efe07c..c28865502 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -6,13 +6,14 @@ + - + diff --git a/files/mygui/openmw_layers_vr.xml b/files/mygui/openmw_layers_vr.xml index bbcd2ef94..fcb81f66d 100644 --- a/files/mygui/openmw_layers_vr.xml +++ b/files/mygui/openmw_layers_vr.xml @@ -13,10 +13,11 @@ - + - + + diff --git a/files/mygui/openmw_mainmenu.layout b/files/mygui/openmw_mainmenu.layout index c4d88ff85..533ba1317 100644 --- a/files/mygui/openmw_mainmenu.layout +++ b/files/mygui/openmw_mainmenu.layout @@ -2,7 +2,7 @@ - + diff --git a/files/openmw.appdata.xml b/files/openmw.appdata.xml index edbeb1a27..f4bdb5c91 100644 --- a/files/openmw.appdata.xml +++ b/files/openmw.appdata.xml @@ -5,8 +5,8 @@ Copyright 2020 Bret Curtis --> org.openmw.launcher.desktop - CC0-1.0 - GPL-3.0 and MIT + GPL-3+ + GPL-3+ OpenMW Unofficial open source engine re-implementation of the game Morrowind diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 1eeabfbf0..9c2071096 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -54,6 +54,18 @@ preview if stand still = false # Rotate the character to the view direction after exiting preview mode. deferred preview rotation = true +# Enables head bobbing in first person mode +head bobbing = false + +# Length of each step +head bobbing step = 90.0 + +# Amplitude of the bobbing effect +head bobbing height = 3.0 + +# Maximum camera roll angle (degrees) +head bobbing roll = 0.2 + [Cells] # Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled. @@ -325,12 +337,30 @@ uncapped damage fatigue = false # Turn lower body to movement direction. 'true' makes diagonal movement more realistic. turn to movement direction = false -# Makes player swim a bit upward (or downward in case of negative value) from the line of sight. -swim upward coef = 0.0 +# Makes all movements of NPCs and player more smooth. +smooth movement = false + +# Max delay of turning (in seconds) if player drastically changes direction on the run. +smooth movement player turning delay = 0.333 + +# All actors avoid collisions with other actors. +NPCs avoid collisions = false + +# Give way to moving actors when idle. Requires 'NPCs avoid collisions' to be enabled. +NPCs give way = true + +# Makes player swim a bit upward from the line of sight. +swim upward correction = false + +# Strength of the 'swim upward correction' effect (if enabled). +swim upward coef = 0.2 # Make the training skills proposed by a trainer based on its base attribute instead of its modified ones trainers training skills based on base skill = false +# Make stealing items from NPCs that were knocked down possible during combat. +always allow stealing from knocked out actors = false + [General] # Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16). @@ -902,6 +932,18 @@ object shadows = false # Allow shadows indoors. Due to limitations with Morrowind's data, only actors can cast shadows indoors, which some might feel is distracting. enable indoor shadows = true +[Physics] +# how much background thread to use in the physics solver. 0 to disable (i.e solver run in the main thread) +async num threads = 0 + +# maintain a cache of lineofsight request in the bacground physics thread +# determines for how much frames an inactive lineofsight request should be kept updated in the cache +# -1 to disable (i.e the LOS will be calculated only on request) +lineofsight keep inactive cache = 0 + +# wether to defer aabb update till before collision detection +defer aabb update = true + [VR] # Should match your real height in the format meters.centimeters. This is used to scale your position within the vr stage to better match your character. real height = 1.85 diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 142cd7259..c678ffbba 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -2,282 +2,778 @@ AdvancedPage + + + 0 + 0 + 617 + 487 + + - - - true + + + 0 - + + + Game Mechanics + + + + + + + + <html><head/><body><p>Make enchanted weaponry without Magical flag bypass normal weapons resistance, like in Morrowind.</p></body></html> + + + Enchanted weapons are magical + + + + + + + <html><head/><body><p>Makes player swim a bit upward from the line of sight. Applies only in third person mode. Intended to make simpler swimming without diving.</p></body></html> + + + Swim upward correction + + + + + + + <html><head/><body><p>If enabled NPCs apply evasion maneuver to avoid collisions with others.</p></body></html> + + + NPCs avoid collisions + + + + + + + <html><head/><body><p>Enable navigator. When enabled background threads are started to build nav mesh for world geometry. Pathfinding system uses nav mesh to build paths. When disabled only pathgrid is used to build paths. Single-core CPU systems may have big performance impact on exiting interior location and moving across exterior world. May slightly affect performance on multi-core CPU systems. Multi-core CPU systems may have different latency for nav mesh update depending on other settings and system performance. Moving across external world, entering/exiting location produce nav mesh update. NPC and creatures may not be able to find path before nav mesh is built around them. Try to disable this if you want to have old fashioned AI which doesn’t know where to go when you stand behind that stone and casting a firebolt.</p></body></html> + + + Build nav mesh for world geometry + + + + + + + <html><head/><body><p>This setting causes the behavior of the sneak key (bound to Ctrl by default) to toggle sneaking on and off rather than requiring the key to be held down while sneaking. Players that spend significant time sneaking may find the character easier to control with this option enabled. </p></body></html> + + + Toggle sneak + + + + + + + <html><head/><body><p>Make disposition change of merchants caused by trading permanent.</p></body></html> + + + Permanent barter disposition changes + + + + + + + <html><head/><body><p>Don't use race weight in NPC movement speed calculations.</p></body></html> + + + Racial variation in speed fix + + + + + + + <html><head/><body><p>Make Damage Fatigue magic effect uncapped like Drain Fatigue effect.</p><p>This means that unlike Morrowind you will be able to knock down actors using this effect.</p></body></html> + + + Uncapped Damage Fatigue + + + + + + + <html><head/><body><p>If this setting is true, the player is allowed to loot actors (e.g. summoned creatures) during death animation, if they are not in combat. In this case we have to increment death counter and run disposed actor's script instantly.</p><p>If this setting is false, player has to wait until end of death animation in all cases. Makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder. Conflicts with mannequin mods, which use SkipAnim to prevent end of death animation.</p></body></html> + + + Can loot during death animation + + + + + + + <html><head/><body><p>Make the value of filled soul gems dependent only on soul magnitude.</p></body></html> + + + Soulgem values rebalance + + + + + + + <html><head/><body><p>Make player followers and escorters start combat with enemies who have started combat with them or the player. Otherwise they wait for the enemies or the player to do an attack first.</p></body></html> + + + Followers defend immediately + + + + + + + <html><head/><body><p>Effects of reflected Absorb spells are not mirrored -- like in Morrowind.</p></body></html> + + + Classic reflected Absorb spells behavior + + + + + + + <html><head/><body><p>Make stealing items from NPCs that were knocked down possible during combat.</p></body></html> + + + Always allow stealing from knocked out actors + + + + + + + + + <html><head/><body><p>Allow non-standard ammunition solely to bypass normal weapon resistance or weakness.</p></body></html> + + + Only appropriate ammunition bypasses normal weapon resistance + + + + + + + + + Factor strength into hand-to-hand combat: + + + + + + + 0 + + + + Off + + + + + Affect werewolves + + + + + Do not affect werewolves + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + <html><head/><body><p>How many threads will be spawned to compute physics update in the background. A value of 0 means that the update will be performed in the main thread.</p><p>A value greater than 1 requires the Bullet library be compiled with multithreading support.</p></body></html> + + + Background physics threads + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Visuals + + + + + + + + <html><head/><body><p>Affects side and diagonal movement. Enabling this setting makes movement more realistic.</p><p>If disabled then the whole character's body is pointed to the direction of view. Diagonal movement has no special animation and causes sliding.</p><p>If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it changes straight right and straight left movement as well. Also turns the whole body up or down when swimming according to the movement direction.</p></body></html> + + + Turn to movement direction + + + + + + + <html><head/><body><p>Makes NPCs and player movement more smooth. Recommended to use with "turn to movement direction" enabled.</p></body></html> + + + Smooth movement + + + + + + + <html><head/><body><p>If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells.</p></body></html> + + + Distant land + + + + + + + <html><head/><body><p>See 'auto use object normal maps'. Affects terrain.</p></body></html> + + + Auto use terrain normal maps + + + + + + + <html><head/><body><p>If a file with pattern 'terrain specular map pattern' exists, use that file as a 'diffuse specular' map. The texture must contain the layer colour in the RGB channel (as usual), and a specular multiplier in the alpha channel.</p></body></html> + + + Auto use terrain specular maps + + + + + + + <html><head/><body><p>Use object paging for active cells grid.</p></body></html> + + + Active grid object paging + + + + + + + <html><head/><body><p>Use casting animations for magic items, just as for spells.</p></body></html> + + + Use magic item animation + + + + + + + <html><head/><body><p>Load per-group KF-files and skeleton files from Animations folder</p></body></html> + + + Use additional animation sources + + + + + + + <html><head/><body><p>If this option is enabled, normal maps are automatically recognized and used if they are named appropriately +(see 'normal map pattern', e.g. for a base texture foo.dds, the normal map texture would have to be named foo_n.dds). +If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file (.nif or .osg file). Affects objects.</p></body></html> + + + Auto use object normal maps + + + + + + + <html><head/><body><p>Normally environment map reflections aren't affected by lighting, which makes environment-mapped (and thus bump-mapped objects) glow in the dark. +Morrowind Code Patch includes an option to remedy that by doing environment-mapping before applying lighting, this is the equivalent of that option. +Affected objects will use shaders. +</p></body></html> + + + Bump/reflect map local lighting + + + + + + + + + Viewing distance + + + + + + + Cells + + + 0.000000000000000 + + + 0.500000000000000 + + + + + + + + + <html><head/><body><p>If this option is enabled, specular maps are automatically recognized and used if they are named appropriately +(see 'specular map pattern', e.g. for a base texture foo.dds, +the specular map texture would have to be named foo_spec.dds). +If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file +(.osg file, not supported in .nif files). Affects objects.</p></body></html> + + + Auto use object specular maps + + + + + + + <html><head/><body><p>By default, the fog becomes thicker proportionally to your distance from the clipping plane set at the clipping distance, which causes distortion at the edges of the screen. +This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV.</p></body></html> + + + Radial fog + + + + + + + + + 20 + + + + + false + + + <html><head/><body><p>Render holstered weapons (with quivers and scabbards), requires modded assets.</p></body></html> + + + Weapon sheathing + + + + + + + false + + + <html><head/><body><p>Render holstered shield, requires modded assets.</p></body></html> + + + Shield sheathing + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Camera + + + + + + <html><head/><body><p>This setting controls third person view mode.</p><p>False: View is centered on the character's head. Crosshair is hidden. +True: In non-combat mode camera is positioned behind the character's shoulder. Crosshair is visible in third person mode as well. +</p></body></html> + + + View over the shoulder + + + + + + + <html><head/><body><p>When player is close to an obstacle, automatically switches camera to the shoulder that is farther away from the obstacle.</p></body></html> + + + Auto switch shoulder + + + + + + + 20 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Default shoulder: + + + + + + + 0 + + + + Right + + + + + Left + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + <html><head/><body><p>If enabled then the character rotation is not synchonized with the camera rotation while the character doesn't move and not in combat mode.</p></body></html> + + + Preview if stand still + + + + + + + <html><head/><body><p>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.</p></body></html> + + + Deferred preview rotation + + + + + + + <html><head/><body><p>Enables head bobbing when move in first person mode.</p></body></html> + + + Head bobbing in 1st person mode + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + Interface + + + + + + + + Show owned: + + + + + + + 1 + + + + Off + + + + + Tool Tip Only + + + + + Crosshair Only + + + + + Tool Tip and Crosshair + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + <html><head/><body><p>Show the remaining duration of magic effects and lights if this setting is true. The remaining duration is displayed in the tooltip by hovering over the magical effect. </p><p>The default value is false.</p></body></html> + + + Show effect duration + + + + + + + <html><head/><body><p>Whether or not the chance of success will be displayed in the enchanting menu.</p><p>The default value is false.</p></body></html> + + + Show enchant chance + + + + + + + <html><head/><body><p>If this setting is true, melee weapons reach and speed will be shown on item tooltip.</p><p>The default value is false.</p></body></html> + + + Show melee info + + + + + + + <html><head/><body><p>If this setting is true, damage bonus of arrows and bolts will be shown on item tooltip.</p><p>The default value is false.</p></body></html> + + + Show projectile damage + + + + + + + <html><head/><body><p>If this setting is true, dialogue topics will have a different color if the topic is specific to the NPC you're talking to or the topic was previously seen. Color can be changed in settings.cfg.</p><p>The default value is false.</p></body></html> + + + Change dialogue topic color + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Bug Fixes + + + + + + <html><head/><body><p>Prevents merchants from equipping items that are sold to them.</p></body></html> + + + Merchant equipping fix + + + + + + + <html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html> + + + Trainers choose their training skills based on their base skill points + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + Miscellaneous + - - - - Game Mechanics - - - - - - <html><head/><body><p>If this setting is true, the player is allowed to loot actors (e.g. summoned creatures) during death animation, if they are not in combat. In this case we have to increment death counter and run disposed actor's script instantly.</p><p>If this setting is false, player has to wait until end of death animation in all cases. Makes using of summoned creatures exploit (looting summoned Dremoras and Golden Saints for expensive weapons) a lot harder. Conflicts with mannequin mods, which use SkipAnim to prevent end of death animation.</p></body></html> - - - Can loot during death animation - - - - - - - <html><head/><body><p>Make player followers and escorters start combat with enemies who have started combat with them or the player. Otherwise they wait for the enemies or the player to do an attack first.</p></body></html> - - - Followers attack on sight - - - - - - - <html><head/><body><p>Prevents merchants from equipping items that are sold to them.</p></body></html> - - - Prevent merchant equipping - - - - - - - <html><head/><body><p>Make the value of filled soul gems dependent only on soul magnitude.</p></body></html> - - - Rebalance soul gem values - - - - - - - <html><head/><body><p>Make enchanted weaponry without Magical flag bypass normal weapons resistance, like in Morrowind.</p></body></html> - - - Enchanted weapons are magical - - - - - - - <html><head/><body><p>Make disposition change of merchants caused by trading permanent.</p></body></html> - - - Barter disposition change is permanent - - - - - - - <html><head/><body><p>Effects of reflected Absorb spells are not mirrored -- like in Morrowind.</p></body></html> - - - Classic reflected Absorb spells behavior - - - - - - - <html><head/><body><p>Allow non-standard ammunition solely to bypass normal weapon resistance or weakness.</p></body></html> - - - Only appropriate ammunition bypasses normal weapon resistance - - - - - - - <html><head/><body><p>Factor strength into hand-to-hand damage calculations, as the MCP formula: damage * (strength / 40).</p><p>The default value is Off.</p></body></html> - - - - -1 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Factor strength into hand-to-hand combat: - - - - - - - 0 - - - - Off - - - - - Affect werewolves - - - - - Do not affect werewolves - - - - - - - - - - - <html><head/><body><p>Use casting animations for magic items, just as for spells.</p></body></html> - - - Use magic item animation - - - - - - - <html><head/><body><p>Don't use race weight in NPC movement speed calculations.</p></body></html> - - - Normalise race speed - - - - - - - <html><head/><body><p>Load per-group KF-files and skeleton files from Animations folder</p></body></html> - - - Use additional animation sources - - - - - - - - 6 - - - 20 - - - 0 - - - 0 - - - 0 - - - - - false - - - <html><head/><body><p>Render holstered weapons (with quivers and scabbards), requires modded assets.</p></body></html> - - - Weapon sheathing - - - - - - - false - - - <html><head/><body><p>Render holstered shield, requires modded assets.</p></body></html> - - - Shield sheathing - - - - - - - - - - <html><head/><body><p>Make Damage Fatigue magic effect uncapped like Drain Fatigue effect.</p><p>This means that unlike Morrowind you will be able to knock down actors using this effect.</p></body></html> - - - Uncapped Damage Fatigue - - - - - - - <html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html> - - - Trainers choose their training skills based on their base skill points - - - - - - - - - - Input - - - - - - <html><head/><body><p>OpenMW will capture control of the cursor if this setting is true.</p><p>In “look mode”, OpenMW will center the cursor regardless of the value of this setting (since the cursor/crosshair is always centered in the OpenMW window). However, in GUI mode, this setting determines the behavior when the cursor is moved outside the OpenMW window. If true, the cursor movement stops at the edge of the window preventing access to other applications. If false, the cursor is allowed to move freely on the desktop.</p><p>This setting does not apply to the screen where escape has been pressed, where the cursor is never captured. Regardless of this setting “Alt-Tab” or some other operating system dependent key sequence can be used to allow the operating system to regain control of the mouse cursor. This setting interacts with the minimize on focus loss setting by affecting what counts as a focus loss. Specifically on a two-screen configuration it may be more convenient to access the second screen with setting disabled.</p><p>Note for developers: it’s desirable to have this setting disabled when running the game in a debugger, to prevent the mouse cursor from becoming unusable when the game pauses on a breakpoint.</p></body></html> - - - Grab cursor - - - - - - - <html><head/><body><p>This setting causes the behavior of the sneak key (bound to Ctrl by default) to toggle sneaking on and off rather than requiring the key to be held down while sneaking. Players that spend significant time sneaking may find the character easier to control with this option enabled. </p></body></html> - - - Toggle sneak - - - - - - @@ -294,249 +790,24 @@ - - - - <html><head/><body><p>This setting determines how many quicksave and autosave slots you can have at a time. If greater than 1, quicksaves will be sequentially created each time you quicksave. Once the maximum number of quicksaves has been reached, the oldest quicksave will be recycled the next time you perform a quicksave.</p></body></html> - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Maximum Quicksaves - - - - - - - 1 - - - - - - - - - - - - - Testing - - - - - These settings are intended for testing mods and will cause issues if used for normal gameplay. - - - true - - - - - - - Qt::Horizontal - - - - - - - Skip menu and generate default character - - - - - + - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - + - Start default character at + Maximum Quicksaves - - - default cell + + + 1 - - - - Run script after startup: - - - - - - - - - - - - Browse… - - - - - - - - - - - - User Interface - - - - - - <html><head/><body><p>Show the remaining duration of magic effects and lights if this setting is true. The remaining duration is displayed in the tooltip by hovering over the magical effect. </p><p>The default value is false.</p></body></html> - - - Show effect duration - - - - - - - <html><head/><body><p>Whether or not the chance of success will be displayed in the enchanting menu.</p><p>The default value is false.</p></body></html> - - - Show enchant chance - - - - - - - <html><head/><body><p>If this setting is true, melee weapons reach and speed will be shown on item tooltip.</p><p>The default value is false.</p></body></html> - - - Show melee info - - - - - - - <html><head/><body><p>If this setting is true, damage bonus of arrows and bolts will be shown on item tooltip.</p><p>The default value is false.</p></body></html> - - - Show projectile damage - - - - - - - <html><head/><body><p>If this setting is true, dialogue topics will have a different color if the topic is specific to the NPC you're talking to or the topic was previously seen. Color can be changed in settings.cfg.</p><p>The default value is false.</p></body></html> - - - Change dialogue topic color - - - - - - - <html><head/><body><p>Enable visual clues for items owned by NPCs when the crosshair is on the object.</p><p>The default value is Off.</p></body></html> - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Show owned: - - - - - - - 1 - - - - Off - - - - - Tool Tip Only - - - - - Crosshair Only - - - - - Tool Tip and Crosshair - - - - - - - @@ -546,59 +817,161 @@ Other - - - - <html><head/><body><p>Specify the format for screen shots taken by pressing the screen shot key (bound to F12 by default). This setting should be the file extension commonly associated with the desired format. The formats supported will be determined at compilation, but “jpg”, “png”, and “tga” should be allowed.</p></body></html> - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - + + + + + + Screenshot Format + + + + + + - Screenshot Format + JPG - - - - - - - JPG - - - - - PNG - - - - - TGA - - - - - - + + + + PNG + + + + + TGA + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + Testing + + + + + + These settings are intended for testing mods and will cause issues if used for normal gameplay. + + + true + + + + + + + Qt::Horizontal + + + + + + + <html><head/><body><p>OpenMW will capture control of the cursor if this setting is true.</p><p>In “look mode”, OpenMW will center the cursor regardless of the value of this setting (since the cursor/crosshair is always centered in the OpenMW window). However, in GUI mode, this setting determines the behavior when the cursor is moved outside the OpenMW window. If true, the cursor movement stops at the edge of the window preventing access to other applications. If false, the cursor is allowed to move freely on the desktop.</p><p>This setting does not apply to the screen where escape has been pressed, where the cursor is never captured. Regardless of this setting “Alt-Tab” or some other operating system dependent key sequence can be used to allow the operating system to regain control of the mouse cursor. This setting interacts with the minimize on focus loss setting by affecting what counts as a focus loss. Specifically on a two-screen configuration it may be more convenient to access the second screen with setting disabled.</p><p>Note for developers: it’s desirable to have this setting disabled when running the game in a debugger, to prevent the mouse cursor from becoming unusable when the game pauses on a breakpoint.</p></body></html> + + + Grab cursor + + + + + + + Skip menu and generate default character + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 0 + 0 + + + + + + + + Start default character at + + + + + + + default cell + + + + + + + + + Run script after startup: + + + + + + + + + + + + Browse… + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + diff --git a/files/ui/graphicspage.ui b/files/ui/graphicspage.ui index cfa2c800c..5ec72611f 100644 --- a/files/ui/graphicspage.ui +++ b/files/ui/graphicspage.ui @@ -11,7 +11,7 @@ - + 0