diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 41fa39b78d..3c4f4c45a7 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -73,7 +73,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Building Dependencies - run: CI/before_install.osx.sh + run: CI/before_install.macos.sh - name: Prime ccache uses: hendrikmuhs/ccache-action@v1 @@ -82,11 +82,9 @@ jobs: max-size: 1000M - name: Configure - run: CI/before_script.osx.sh + run: CI/before_script.macos.sh - name: Build - run: | - cd build - make -j $(sysctl -n hw.logicalcpu) package + run: CI/macos/build.sh Output-Envs: name: Read .env file and expose it as output diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d55e554905..52fa51d299 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -507,14 +507,15 @@ Ubuntu_GCC_integration_tests_asan: paths: - ccache/ script: - - CI/before_install.osx.sh + - CI/before_install.macos.sh - export CCACHE_BASEDIR="$(pwd)" - export CCACHE_DIR="$(pwd)/ccache" - mkdir -pv "${CCACHE_DIR}" - - ccache -z -M "${CCACHE_SIZE}" - - CI/before_script.osx.sh - - cd build; make -j $(sysctl -n hw.logicalcpu) package - - for dmg in *.dmg; do mv "$dmg" "${dmg%.dmg}_${CI_COMMIT_REF_NAME##*/}.dmg"; done + - CI/macos/ccache_prep.sh + - CI/before_script.macos.sh + - CI/macos/build.sh + - cd build + - for dmg in *.dmg; do mv "$dmg" "${dmg%.dmg}_${DMG_IDENTIFIER}_${CI_COMMIT_REF_NAME##*/}.dmg"; done - | if [[ -n "${AWS_ACCESS_KEY_ID}" ]]; then echo "[default]" > ~/.s3cfg @@ -529,11 +530,23 @@ Ubuntu_GCC_integration_tests_asan: s3cmd put "${dmg}" s3://openmw-artifacts/${artifactDirectory} done fi - - ccache -s + - ../CI/macos/ccache_save.sh artifacts: paths: - build/OpenMW-*.dmg +macOS14_Xcode15_amd64: + extends: .MacOS + image: macos-14-xcode-15 + tags: + - saas-macos-medium-m1 + cache: + key: macOS14_Xcode15_amd64.v2 + variables: + CCACHE_SIZE: 3G + DMG_IDENTIFIER: amd64 + MACOS_AMD64: true + macOS14_Xcode15_arm64: extends: .MacOS image: macos-14-xcode-15 @@ -542,6 +555,7 @@ macOS14_Xcode15_arm64: cache: key: macOS14_Xcode15_arm64.v1 variables: + DMG_IDENTIFIER: arm64 CCACHE_SIZE: 3G .Compress_And_Upload_Symbols_Base: @@ -968,7 +982,7 @@ Windows_MSBuild_CacheInit: - flatpak build-bundle ./repo openmw.flatpak org.openmw.OpenMW.devel cache: key: flatpak - paths: + paths: - ".flatpak-builder" artifacts: untracked: false diff --git a/CHANGELOG.md b/CHANGELOG.md index fa0c43be25..8310cb8c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +0.50.0 +------ + + 0.49.0 ------ @@ -236,6 +240,8 @@ Bug #8465: Blue screen w/ antialiasing and post-processing on macOS Bug #8503: Camera does not handle NaN gracefully Bug #8541: Lua: util.color:asHex produces wrong output for some colors + Bug #8567: Token replacement does not work via CLI and relative paths passed via the command line are not relative to the CWD + Bug #8576: Crash on exit when unresolving containers with scripted items Feature #1415: Infinite fall failsafe Feature #2566: Handle NAM9 records for manual cell references Feature #3501: OpenMW-CS: Instance Editing - Shortcuts for axial locking diff --git a/CI/before_install.macos.sh b/CI/before_install.macos.sh new file mode 100755 index 0000000000..f466dd06a7 --- /dev/null +++ b/CI/before_install.macos.sh @@ -0,0 +1,11 @@ +#!/bin/sh -ex + +export HOMEBREW_NO_EMOJI=1 +export HOMEBREW_NO_INSTALL_CLEANUP=1 +export HOMEBREW_AUTOREMOVE=1 + +if [[ "${MACOS_AMD64}" ]]; then + ./CI/macos/before_install.amd64.sh +else + ./CI/macos/before_install.arm64.sh +fi diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh deleted file mode 100755 index 30822f5d00..0000000000 --- a/CI/before_install.osx.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -ex - -export HOMEBREW_NO_EMOJI=1 -export HOMEBREW_NO_INSTALL_CLEANUP=1 -export HOMEBREW_AUTOREMOVE=1 - -brew tap --repair -brew update --quiet - -brew install curl xquartz gd fontconfig freetype harfbuzz brotli s3cmd - -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@6 - -# Install deps -brew install openal-soft icu4c yaml-cpp sqlite - -ccache --version -cmake --version -qmake --version - -if [[ "${MACOS_AMD64}" ]]; then - curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240802.zip -o ~/openmw-deps.zip - unzip -o ~/openmw-deps.zip -d /tmp > /dev/null -else - curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240818-arm64.tar.xz -o ~/openmw-deps.tar.xz - tar xf ~/openmw-deps.tar.xz -C /tmp > /dev/null -fi diff --git a/CI/before_script.macos.sh b/CI/before_script.macos.sh new file mode 100755 index 0000000000..50adab234d --- /dev/null +++ b/CI/before_script.macos.sh @@ -0,0 +1,77 @@ +#!/bin/sh -e + +# Silence a git warning +git config --global advice.detachedHead false + +rm -fr build +mkdir build +cd build + +DEPENDENCIES_ROOT="/tmp/openmw-deps" + +if [[ "${MACOS_AMD64}" ]]; then + QT_PATH=$(arch -x86_64 /usr/local/bin/brew --prefix qt@6) + ICU_PATH=$(arch -x86_64 /usr/local/bin/brew --prefix icu4c) + OPENAL_PATH=$(arch -x86_64 /usr/local/bin/brew --prefix openal-soft) + CCACHE_EXECUTABLE=$(arch -x86_64 /usr/local/bin/brew --prefix ccache)/bin/ccache +else + QT_PATH=$(brew --prefix qt@6) + ICU_PATH=$(brew --prefix icu4c) + OPENAL_PATH=$(brew --prefix openal-soft) + CCACHE_EXECUTABLE=$(brew --prefix ccache)/bin/ccache +fi + +declare -a CMAKE_CONF_OPTS=( +-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH;$OPENAL_PATH" +-D CMAKE_C_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" +-D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" +-D CMAKE_CXX_FLAGS="-stdlib=libc++" +-D CMAKE_C_COMPILER="clang" +-D CMAKE_CXX_COMPILER="clang++" +-D CMAKE_OSX_DEPLOYMENT_TARGET="13.6" +-D OPENMW_USE_SYSTEM_RECASTNAVIGATION=TRUE +-D Boost_INCLUDE_DIR="$DEPENDENCIES_ROOT/include" +-D OSGPlugins_LIB_DIR="$DEPENDENCIES_ROOT/lib/osgPlugins-3.6.5" +-D ICU_ROOT="$ICU_PATH" +-D OPENMW_OSX_DEPLOYMENT=TRUE +) + +declare -a BUILD_OPTS=( +-D BUILD_OPENMW=TRUE +-D BUILD_OPENCS=TRUE +-D BUILD_ESMTOOL=TRUE +-D BUILD_BSATOOL=TRUE +-D BUILD_ESSIMPORTER=TRUE +-D BUILD_NIFTEST=TRUE +-D BUILD_NAVMESHTOOL=TRUE +-D BUILD_BULLETOBJECTTOOL=TRUE +-G"Unix Makefiles" +) + +if [[ "${MACOS_AMD64}" ]]; then + CMAKE_CONF_OPTS+=( + -D CMAKE_OSX_ARCHITECTURES="x86_64" + ) +fi + +if [[ "${CMAKE_BUILD_TYPE}" ]]; then + CMAKE_CONF_OPTS+=( + -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + ) +else + CMAKE_CONF_OPTS+=( + -D CMAKE_BUILD_TYPE=RelWithDebInfo + ) +fi + +if [[ "${MACOS_AMD64}" ]]; then + arch -x86_64 cmake \ + "${CMAKE_CONF_OPTS[@]}" \ + "${BUILD_OPTS[@]}" \ + .. +else + cmake \ + "${CMAKE_CONF_OPTS[@]}" \ + "${BUILD_OPTS[@]}" \ + .. +fi diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh deleted file mode 100755 index 9be91f1632..0000000000 --- a/CI/before_script.osx.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh -e - -# Silence a git warning -git config --global advice.detachedHead false - -rm -fr build -mkdir build -cd build - -DEPENDENCIES_ROOT="/tmp/openmw-deps" - -QT_PATH=$(brew --prefix qt@6) -ICU_PATH=$(brew --prefix icu4c) -OPENAL_PATH=$(brew --prefix openal-soft) -CCACHE_EXECUTABLE=$(brew --prefix ccache)/bin/ccache - -declare -a CMAKE_CONF_OPTS=( --D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH;$OPENAL_PATH" --D CMAKE_C_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" --D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" --D CMAKE_CXX_FLAGS="-stdlib=libc++" --D CMAKE_C_COMPILER="clang" --D CMAKE_CXX_COMPILER="clang++" --D CMAKE_OSX_DEPLOYMENT_TARGET="13.6" --D OPENMW_USE_SYSTEM_RECASTNAVIGATION=TRUE --D Boost_INCLUDE_DIR="$DEPENDENCIES_ROOT/include" --D OSGPlugins_LIB_DIR="$DEPENDENCIES_ROOT/lib/osgPlugins-3.6.5" --D ICU_ROOT="$ICU_PATH" --D OPENMW_OSX_DEPLOYMENT=TRUE -) - -if [[ "${CMAKE_BUILD_TYPE}" ]]; then - CMAKE_CONF_OPTS+=( - -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - ) -else - CMAKE_CONF_OPTS+=( - -D CMAKE_BUILD_TYPE=RelWithDebInfo - ) -fi - -cmake \ -"${CMAKE_CONF_OPTS[@]}" \ --D BUILD_OPENMW=TRUE \ --D BUILD_OPENCS=TRUE \ --D BUILD_ESMTOOL=TRUE \ --D BUILD_BSATOOL=TRUE \ --D BUILD_ESSIMPORTER=TRUE \ --D BUILD_NIFTEST=TRUE \ --D BUILD_NAVMESHTOOL=TRUE \ --D BUILD_BULLETOBJECTTOOL=TRUE \ --G"Unix Makefiles" \ -.. diff --git a/CI/check_file_names.sh b/CI/check_file_names.sh index b04416659e..2a0f421cc9 100755 --- a/CI/check_file_names.sh +++ b/CI/check_file_names.sh @@ -1,7 +1,6 @@ #!/bin/bash -ex git ls-files -- ':(exclude)extern/' '*.cpp' '*.hpp' '*.h' | - grep -vP '/[a-z0-9]+\.(cpp|hpp|h)$' | - grep -vFf CI/file_name_exceptions.txt && + grep -vP '/[a-z0-9]+\.(cpp|hpp|h)$' && ( echo 'File names do not follow the naming convention, see https://wiki.openmw.org/index.php?title=Naming_Conventions#Files'; exit -1 ) exit 0 diff --git a/CI/file_name_exceptions.txt b/CI/file_name_exceptions.txt deleted file mode 100644 index 14d106169b..0000000000 --- a/CI/file_name_exceptions.txt +++ /dev/null @@ -1,48 +0,0 @@ -apps/openmw/android_main.cpp -apps/openmw/mwsound/efx-presets.h -apps/openmw/mwsound/ffmpeg_decoder.cpp -apps/openmw/mwsound/ffmpeg_decoder.hpp -apps/openmw/mwsound/openal_output.cpp -apps/openmw/mwsound/openal_output.hpp -apps/openmw/mwsound/sound_buffer.cpp -apps/openmw/mwsound/sound_buffer.hpp -apps/openmw/mwsound/sound_decoder.hpp -apps/openmw/mwsound/sound_output.hpp -apps/components_tests/esm/test_fixed_string.cpp -apps/components_tests/files/conversion_tests.cpp -apps/components_tests/lua/test_async.cpp -apps/components_tests/lua/test_configuration.cpp -apps/components_tests/lua/test_l10n.cpp -apps/components_tests/lua/test_lua.cpp -apps/components_tests/lua/test_scriptscontainer.cpp -apps/components_tests/lua/test_serialization.cpp -apps/components_tests/lua/test_storage.cpp -apps/components_tests/lua/test_ui_content.cpp -apps/components_tests/lua/test_utilpackage.cpp -apps/components_tests/lua/test_inputactions.cpp -apps/components_tests/lua/test_yaml.cpp -apps/components_tests/misc/test_endianness.cpp -apps/components_tests/misc/test_resourcehelpers.cpp -apps/components_tests/misc/test_stringops.cpp -apps/openmw_tests/mwdialogue/test_keywordsearch.cpp -apps/openmw_tests/mwscript/test_scripts.cpp -apps/openmw_tests/mwscript/test_utils.hpp -apps/openmw_tests/mwworld/test_store.cpp -components/bsa/bsa_file.cpp -components/bsa/bsa_file.hpp -components/crashcatcher/windows_crashcatcher.cpp -components/crashcatcher/windows_crashcatcher.hpp -components/crashcatcher/windows_crashmonitor.cpp -components/crashcatcher/windows_crashmonitor.hpp -components/crashcatcher/windows_crashshm.hpp -components/fx/lexer_types.hpp -components/fx/parse_constants.hpp -components/platform/file.posix.cpp -components/platform/file.stdio.cpp -components/platform/file.win32.cpp -components/sdlutil/gl4es_init.cpp -components/sdlutil/gl4es_init.h -components/to_utf8/gen_iconv.cpp -components/to_utf8/tables_gen.hpp -components/to_utf8/to_utf8.cpp -components/to_utf8/to_utf8.hpp diff --git a/CI/macos/before_install.amd64.sh b/CI/macos/before_install.amd64.sh new file mode 100755 index 0000000000..642f2c2c62 --- /dev/null +++ b/CI/macos/before_install.amd64.sh @@ -0,0 +1,8 @@ +#!/bin/sh -ex + +arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + +arch -x86_64 /usr/local/bin/brew install curl xquartz gd fontconfig freetype harfbuzz brotli s3cmd ccache cmake qt@6 openal-soft icu4c yaml-cpp sqlite + +curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240802.zip -o ~/openmw-deps.zip +unzip -o ~/openmw-deps.zip -d /tmp > /dev/null diff --git a/CI/macos/before_install.arm64.sh b/CI/macos/before_install.arm64.sh new file mode 100755 index 0000000000..84120dfba2 --- /dev/null +++ b/CI/macos/before_install.arm64.sh @@ -0,0 +1,16 @@ +#!/bin/sh -ex + +brew tap --repair +brew update --quiet + +brew install curl xquartz gd fontconfig freetype harfbuzz brotli s3cmd + +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@6 + +# Install deps +brew install openal-soft icu4c yaml-cpp sqlite + +curl -fSL -R -J https://gitlab.com/OpenMW/openmw-deps/-/raw/main/macos/openmw-deps-20240818-arm64.tar.xz -o ~/openmw-deps.tar.xz +tar xf ~/openmw-deps.tar.xz -C /tmp > /dev/null diff --git a/CI/macos/build.sh b/CI/macos/build.sh new file mode 100755 index 0000000000..64986717ce --- /dev/null +++ b/CI/macos/build.sh @@ -0,0 +1,9 @@ +#!/bin/sh -ex + +cd build + +if [[ "${MACOS_AMD64}" ]]; then + arch -x86_64 make -j $(sysctl -n hw.logicalcpu) package +else + make -j $(sysctl -n hw.logicalcpu) package +fi diff --git a/CI/macos/ccache_prep.sh b/CI/macos/ccache_prep.sh new file mode 100755 index 0000000000..abd0103be0 --- /dev/null +++ b/CI/macos/ccache_prep.sh @@ -0,0 +1,7 @@ +#!/bin/sh -ex + +if [[ "${MACOS_AMD64}" ]]; then + arch -x86_64 ccache -z -M "${CCACHE_SIZE}" +else + ccache -z -M "${CCACHE_SIZE}" +fi diff --git a/CI/macos/ccache_save.sh b/CI/macos/ccache_save.sh new file mode 100755 index 0000000000..d06d16fb0c --- /dev/null +++ b/CI/macos/ccache_save.sh @@ -0,0 +1,7 @@ +#!/bin/sh -ex + +if [[ "${MACOS_AMD64}" ]]; then + arch -x86_64 ccache -s +else + ccache -s +fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dd4f0ac27..a7d7bf9b3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ endif() message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) -set(OPENMW_VERSION_MINOR 49) +set(OPENMW_VERSION_MINOR 50) set(OPENMW_VERSION_RELEASE 0) set(OPENMW_LUA_API_REVISION 76) set(OPENMW_POSTPROCESSING_API_REVISION 2) diff --git a/README.md b/README.md index bca5851c7b..f65f74e9d8 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ OpenMW is an open-source open-world RPG game engine that supports playing Morrow OpenMW also comes with OpenMW-CS, a replacement for Bethesda's Construction Set. -* Version: 0.49.0 +* Version: 0.50.0 * License: GPLv3 (see [LICENSE](https://gitlab.com/OpenMW/openmw/-/raw/master/LICENSE) for more information) * Website: https://www.openmw.org * IRC: #openmw on irc.libera.chat diff --git a/apps/bulletobjecttool/main.cpp b/apps/bulletobjecttool/main.cpp index 5cb275a53d..5cacedd07e 100644 --- a/apps/bulletobjecttool/main.cpp +++ b/apps/bulletobjecttool/main.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -125,6 +125,7 @@ namespace } Files::ConfigurationManager config; + config.processPaths(variables, std::filesystem::current_path()); config.readConfiguration(variables, desc); Debug::setupLogging(config.getLogPath(), applicationName); diff --git a/apps/components_tests/CMakeLists.txt b/apps/components_tests/CMakeLists.txt index 22bb542538..7595681313 100644 --- a/apps/components_tests/CMakeLists.txt +++ b/apps/components_tests/CMakeLists.txt @@ -4,29 +4,28 @@ include_directories(SYSTEM ${GMOCK_INCLUDE_DIRS}) file(GLOB UNITTEST_SRC_FILES main.cpp - esm/test_fixed_string.cpp - esm/variant.cpp + esm/testfixedstring.cpp esm/testrefid.cpp + esm/variant.cpp - lua/test_lua.cpp - lua/test_scriptscontainer.cpp - lua/test_utilpackage.cpp - lua/test_serialization.cpp - lua/test_configuration.cpp - lua/test_l10n.cpp - lua/test_storage.cpp - lua/test_async.cpp - lua/test_inputactions.cpp - lua/test_yaml.cpp - - lua/test_ui_content.cpp + lua/testasync.cpp + lua/testconfiguration.cpp + lua/testinputactions.cpp + lua/testl10n.cpp + lua/testlua.cpp + lua/testscriptscontainer.cpp + lua/testserialization.cpp + lua/teststorage.cpp + lua/testuicontent.cpp + lua/testutilpackage.cpp + lua/testyaml.cpp misc/compression.cpp misc/progressreporter.cpp - misc/test_endianness.cpp - misc/test_resourcehelpers.cpp - misc/test_stringops.cpp + misc/testendianness.cpp misc/testmathutil.cpp + misc/testresourcehelpers.cpp + misc/teststringops.cpp nifloader/testbulletnifloader.cpp @@ -64,8 +63,8 @@ file(GLOB UNITTEST_SRC_FILES esmloader/esmdata.cpp esmloader/record.cpp + files/conversiontests.cpp files/hash.cpp - files/conversion_tests.cpp toutf8/toutf8.cpp diff --git a/apps/components_tests/esm/test_fixed_string.cpp b/apps/components_tests/esm/testfixedstring.cpp similarity index 100% rename from apps/components_tests/esm/test_fixed_string.cpp rename to apps/components_tests/esm/testfixedstring.cpp diff --git a/apps/components_tests/esmloader/load.cpp b/apps/components_tests/esmloader/load.cpp index 20e06507d1..e5e1b15876 100644 --- a/apps/components_tests/esmloader/load.cpp +++ b/apps/components_tests/esmloader/load.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include diff --git a/apps/components_tests/files/conversion_tests.cpp b/apps/components_tests/files/conversiontests.cpp similarity index 100% rename from apps/components_tests/files/conversion_tests.cpp rename to apps/components_tests/files/conversiontests.cpp diff --git a/apps/components_tests/lua/test_async.cpp b/apps/components_tests/lua/testasync.cpp similarity index 100% rename from apps/components_tests/lua/test_async.cpp rename to apps/components_tests/lua/testasync.cpp diff --git a/apps/components_tests/lua/test_configuration.cpp b/apps/components_tests/lua/testconfiguration.cpp similarity index 100% rename from apps/components_tests/lua/test_configuration.cpp rename to apps/components_tests/lua/testconfiguration.cpp diff --git a/apps/components_tests/lua/test_inputactions.cpp b/apps/components_tests/lua/testinputactions.cpp similarity index 100% rename from apps/components_tests/lua/test_inputactions.cpp rename to apps/components_tests/lua/testinputactions.cpp diff --git a/apps/components_tests/lua/test_l10n.cpp b/apps/components_tests/lua/testl10n.cpp similarity index 100% rename from apps/components_tests/lua/test_l10n.cpp rename to apps/components_tests/lua/testl10n.cpp diff --git a/apps/components_tests/lua/test_lua.cpp b/apps/components_tests/lua/testlua.cpp similarity index 100% rename from apps/components_tests/lua/test_lua.cpp rename to apps/components_tests/lua/testlua.cpp diff --git a/apps/components_tests/lua/test_scriptscontainer.cpp b/apps/components_tests/lua/testscriptscontainer.cpp similarity index 100% rename from apps/components_tests/lua/test_scriptscontainer.cpp rename to apps/components_tests/lua/testscriptscontainer.cpp diff --git a/apps/components_tests/lua/test_serialization.cpp b/apps/components_tests/lua/testserialization.cpp similarity index 100% rename from apps/components_tests/lua/test_serialization.cpp rename to apps/components_tests/lua/testserialization.cpp diff --git a/apps/components_tests/lua/test_storage.cpp b/apps/components_tests/lua/teststorage.cpp similarity index 100% rename from apps/components_tests/lua/test_storage.cpp rename to apps/components_tests/lua/teststorage.cpp diff --git a/apps/components_tests/lua/test_ui_content.cpp b/apps/components_tests/lua/testuicontent.cpp similarity index 100% rename from apps/components_tests/lua/test_ui_content.cpp rename to apps/components_tests/lua/testuicontent.cpp diff --git a/apps/components_tests/lua/test_utilpackage.cpp b/apps/components_tests/lua/testutilpackage.cpp similarity index 100% rename from apps/components_tests/lua/test_utilpackage.cpp rename to apps/components_tests/lua/testutilpackage.cpp diff --git a/apps/components_tests/lua/test_yaml.cpp b/apps/components_tests/lua/testyaml.cpp similarity index 100% rename from apps/components_tests/lua/test_yaml.cpp rename to apps/components_tests/lua/testyaml.cpp diff --git a/apps/components_tests/misc/test_endianness.cpp b/apps/components_tests/misc/testendianness.cpp similarity index 100% rename from apps/components_tests/misc/test_endianness.cpp rename to apps/components_tests/misc/testendianness.cpp diff --git a/apps/components_tests/misc/test_resourcehelpers.cpp b/apps/components_tests/misc/testresourcehelpers.cpp similarity index 100% rename from apps/components_tests/misc/test_resourcehelpers.cpp rename to apps/components_tests/misc/testresourcehelpers.cpp diff --git a/apps/components_tests/misc/test_stringops.cpp b/apps/components_tests/misc/teststringops.cpp similarity index 100% rename from apps/components_tests/misc/test_stringops.cpp rename to apps/components_tests/misc/teststringops.cpp diff --git a/apps/components_tests/toutf8/toutf8.cpp b/apps/components_tests/toutf8/toutf8.cpp index 704ee6742d..3c84da65ee 100644 --- a/apps/components_tests/toutf8/toutf8.cpp +++ b/apps/components_tests/toutf8/toutf8.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index 5b657da573..4ff632a217 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include namespace EsmTool { diff --git a/apps/essimporter/importer.cpp b/apps/essimporter/importer.cpp index 5cc9a8259b..cf04fee163 100644 --- a/apps/essimporter/importer.cpp +++ b/apps/essimporter/importer.cpp @@ -25,7 +25,7 @@ #include -#include +#include #include "importercontext.hpp" diff --git a/apps/essimporter/main.cpp b/apps/essimporter/main.cpp index f0833e9d81..50e11e2c5a 100644 --- a/apps/essimporter/main.cpp +++ b/apps/essimporter/main.cpp @@ -40,6 +40,7 @@ Allowed options)"); bpo::notify(variables); Files::ConfigurationManager cfgManager(true); + cfgManager.processPaths(variables, std::filesystem::current_path()); cfgManager.readConfiguration(variables, desc); const auto& essFile = variables["mwsave"].as(); diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 4c42caf5a3..342670713c 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include class MwIniImporter { diff --git a/apps/navmeshtool/main.cpp b/apps/navmeshtool/main.cpp index e148e60d54..08ed10c3b3 100644 --- a/apps/navmeshtool/main.cpp +++ b/apps/navmeshtool/main.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -143,6 +143,7 @@ namespace NavMeshTool } Files::ConfigurationManager config; + config.processPaths(variables, std::filesystem::current_path()); config.readConfiguration(variables, desc); Debug::setupLogging(config.getLogPath(), applicationName); diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 8781f54154..ab361e7568 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "view/doc/viewmanager.hpp" diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 60516cdc8c..ac8f06712c 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include "../world/data.hpp" #include "../world/idcompletionmanager.hpp" diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 2c9ee1e98e..53caf04a0a 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include "loader.hpp" diff --git a/apps/opencs/model/doc/runner.cpp b/apps/opencs/model/doc/runner.cpp index d647d6b498..4019fbfe57 100644 --- a/apps/opencs/model/doc/runner.cpp +++ b/apps/opencs/model/doc/runner.cpp @@ -2,11 +2,8 @@ #include -#if defined(Q_OS_MAC) #include #include -#endif - #include #include #include @@ -55,16 +52,17 @@ void CSMDoc::Runner::start(bool delayed) QString path = "openmw"; #ifdef Q_OS_WIN - path.append(QString(".exe")); -#elif defined(Q_OS_MAC) - QDir dir(QCoreApplication::applicationDirPath()); - dir.cdUp(); - dir.cdUp(); - dir.cdUp(); - path = dir.absoluteFilePath(path.prepend("OpenMW.app/Contents/MacOS/")); -#else - path.prepend(QString("./")); + path.append(QLatin1String(".exe")); #endif + QDir dir(QCoreApplication::applicationDirPath()); +#ifdef Q_OS_MAC + // the CS and engine are in separate .app directories + dir.cdUp(); + dir.cdUp(); + dir.cdUp(); + path.prepend("OpenMW.app/Contents/MacOS/"); +#endif + path = dir.absoluteFilePath(path); mStartup = new QTemporaryFile(this); mStartup->open(); diff --git a/apps/opencs/model/doc/saving.hpp b/apps/opencs/model/doc/saving.hpp index 5dcdbb6803..6197798fdf 100644 --- a/apps/opencs/model/doc/saving.hpp +++ b/apps/opencs/model/doc/saving.hpp @@ -3,7 +3,7 @@ #include -#include +#include #include "operation.hpp" #include "savingstate.hpp" diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index c42dff0366..af8caa2c4d 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace CSMDoc { diff --git a/apps/opencs/model/prefs/shortcutmanager.cpp b/apps/opencs/model/prefs/shortcutmanager.cpp index d6686d31d9..ac032efffb 100644 --- a/apps/opencs/model/prefs/shortcutmanager.cpp +++ b/apps/opencs/model/prefs/shortcutmanager.cpp @@ -78,7 +78,7 @@ namespace CSMPrefs } } - bool ShortcutManager::getModifier(const std::string& name, int& modifier) const + bool ShortcutManager::getModifier(std::string_view name, int& modifier) const { ModifierMap::const_iterator item = mModifiers.find(name); if (item != mModifiers.end()) @@ -175,14 +175,14 @@ namespace CSMPrefs return concat; } - void ShortcutManager::convertFromString(const std::string& data, QKeySequence& sequence) const + void ShortcutManager::convertFromString(std::string_view data, QKeySequence& sequence) const { const int MaxKeys = 4; // A limitation of QKeySequence size_t end = data.find(';'); size_t size = std::min(end, data.size()); - std::string value = data.substr(0, size); + std::string_view value = data.substr(0, size); size_t start = 0; int keyPos = 0; @@ -195,7 +195,7 @@ namespace CSMPrefs end = data.find('+', start); end = std::min(end, value.size()); - std::string name = value.substr(start, end - start); + std::string_view name = value.substr(start, end - start); if (name == "Ctrl") { @@ -242,12 +242,12 @@ namespace CSMPrefs sequence = QKeySequence(keys[0], keys[1], keys[2], keys[3]); } - void ShortcutManager::convertFromString(const std::string& data, int& modifier) const + void ShortcutManager::convertFromString(std::string_view data, int& modifier) const { size_t start = data.find(';') + 1; start = std::min(start, data.size()); - std::string name = data.substr(start); + std::string_view name = data.substr(start); KeyMap::const_iterator searchResult = mKeys.find(name); if (searchResult != mKeys.end()) { @@ -259,7 +259,7 @@ namespace CSMPrefs } } - void ShortcutManager::convertFromString(const std::string& data, QKeySequence& sequence, int& modifier) const + void ShortcutManager::convertFromString(std::string_view data, QKeySequence& sequence, int& modifier) const { convertFromString(data, sequence); convertFromString(data, modifier); diff --git a/apps/opencs/model/prefs/shortcutmanager.hpp b/apps/opencs/model/prefs/shortcutmanager.hpp index 0cfe3ad86a..fa25876660 100644 --- a/apps/opencs/model/prefs/shortcutmanager.hpp +++ b/apps/opencs/model/prefs/shortcutmanager.hpp @@ -31,7 +31,7 @@ namespace CSMPrefs bool getSequence(std::string_view name, QKeySequence& sequence) const; void setSequence(std::string_view name, const QKeySequence& sequence); - bool getModifier(const std::string& name, int& modifier) const; + bool getModifier(std::string_view name, int& modifier) const; void setModifier(std::string_view name, int modifier); std::string convertToString(const QKeySequence& sequence) const; @@ -39,10 +39,10 @@ namespace CSMPrefs std::string convertToString(const QKeySequence& sequence, int modifier) const; - void convertFromString(const std::string& data, QKeySequence& sequence) const; - void convertFromString(const std::string& data, int& modifier) const; + void convertFromString(std::string_view data, QKeySequence& sequence) const; + void convertFromString(std::string_view data, int& modifier) const; - void convertFromString(const std::string& data, QKeySequence& sequence, int& modifier) const; + void convertFromString(std::string_view data, QKeySequence& sequence, int& modifier) const; /// Replaces "{sequence-name}" or "{modifier-name}" with the appropriate text QString processToolTip(const QString& toolTip) const; @@ -53,7 +53,7 @@ namespace CSMPrefs typedef std::map> SequenceMap; typedef std::map> ModifierMap; typedef std::map NameMap; - typedef std::map KeyMap; + typedef std::map> KeyMap; ShortcutMap mShortcuts; SequenceMap mSequences; diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index f0af163bf2..5c32ddb68b 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -498,7 +498,7 @@ CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut( // Setup with actual data QKeySequence sequence; - getShortcutManager().convertFromString(value, sequence); + getShortcutManager().convertFromString(value.get(), sequence); getShortcutManager().setSequence(value.mName, sequence); CSMPrefs::ShortcutSetting* setting diff --git a/apps/opencs/model/tools/mergeoperation.hpp b/apps/opencs/model/tools/mergeoperation.hpp index 2cce2bec0d..c50a7eefb0 100644 --- a/apps/opencs/model/tools/mergeoperation.hpp +++ b/apps/opencs/model/tools/mergeoperation.hpp @@ -3,7 +3,7 @@ #include -#include +#include #include "../doc/operation.hpp" diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 42f06858b1..40cc799c81 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include "../doc/stage.hpp" diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index c9e8937c90..939dea9bb8 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -6,7 +6,7 @@ #include -#include +#include #include diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 237b746746..c119541381 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "cell.hpp" #include "idcollection.hpp" diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index fb085f075a..03872a3d6c 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -171,16 +171,18 @@ osg::Vec3f CSVRender::InstanceMode::getProjectionSpaceCoords(const osg::Vec3f& p osg::Vec3f CSVRender::InstanceMode::getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart) { - osg::Matrix viewMatrix; - viewMatrix.invert(getWorldspaceWidget().getCamera()->getViewMatrix()); - osg::Matrix projMatrix; - projMatrix.invert(getWorldspaceWidget().getCamera()->getProjectionMatrix()); - osg::Matrix combined = projMatrix * viewMatrix; + const osg::Matrix viewMatrix = getWorldspaceWidget().getCamera()->getViewMatrix(); + const osg::Matrix projMatrix = getWorldspaceWidget().getCamera()->getProjectionMatrix(); + const osg::Matrix combined = osg::Matrix::inverse(viewMatrix * projMatrix); /* calculate viewport normalized coordinates note: is there a reason to use getCamera()->getViewport()->computeWindowMatrix() instead? */ - float x = (point.x() * 2) / getWorldspaceWidget().getCamera()->getViewport()->width() - 1.0f; - float y = 1.0f - (point.y() * 2) / getWorldspaceWidget().getCamera()->getViewport()->height(); + const float scale = getWorldspaceWidget().devicePixelRatioF(); + const osg::Viewport* viewport = getWorldspaceWidget().getCamera()->getViewport(); + float x = point.x() * scale / viewport->width(); + float y = point.y() * scale / viewport->height(); + x = x * 2.0f - 1.0f; + y = 1.0f - y * 2.0f; osg::Vec3f mousePlanePoint = osg::Vec3f(x, y, dragStart.z()) * combined; diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 399514cab4..330551f91a 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -15,7 +15,7 @@ set(OPENMW_HEADERS profile.hpp ) -source_group(apps/openmw FILES main.cpp android_main.cpp ${OPENMW_SOURCES} ${OPENMW_HEADERS} ${OPENMW_RESOURCES}) +source_group(apps/openmw FILES main.cpp androidmain.cpp ${OPENMW_SOURCES} ${OPENMW_HEADERS} ${OPENMW_RESOURCES}) add_openmw_dir (mwrender actors objects renderingmanager animation rotatecontroller sky skyutil npcanimation esm4npcanimation vismask @@ -71,8 +71,8 @@ add_openmw_dir (mwlua ) add_openmw_dir (mwsound - soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output - loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater + soundmanagerimp openaloutput ffmpegdecoder sound soundbuffer sounddecoder soundoutput + loudness movieaudiofactory alext efx efxpresets regionsoundselector watersoundupdater ) add_openmw_dir (mwworld @@ -127,7 +127,7 @@ if(BUILD_OPENMW) if (ANDROID) add_library(openmw SHARED main.cpp - android_main.cpp + androidmain.cpp ) else() openmw_add_executable(openmw @@ -138,6 +138,12 @@ if(BUILD_OPENMW) endif() target_link_libraries(openmw openmw-lib) + + # Workaround necessary to ensure osgAnimation::MatrixLinearSampler dynamic casts work under Clang + # NOTE: it's unclear whether the broken behavior is spec-compliant + if (CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set_target_properties(openmw PROPERTIES ENABLE_EXPORTS ON) + endif() endif() # Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING diff --git a/apps/openmw/android_main.cpp b/apps/openmw/androidmain.cpp similarity index 100% rename from apps/openmw/android_main.cpp rename to apps/openmw/androidmain.cpp diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 7dc372f269..0f82e953c1 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -404,8 +404,8 @@ OMW::Engine::~Engine() mMechanicsManager = nullptr; mDialogueManager = nullptr; mJournal = nullptr; - mScriptManager = nullptr; mWindowManager = nullptr; + mScriptManager = nullptr; mWorld = nullptr; mStereoManager = nullptr; mSoundManager = nullptr; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 812a6ffd85..12b327c222 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -61,6 +61,8 @@ bool parseOptions(int argc, char** argv, OMW::Engine& engine, Files::Configurati return false; } + cfgMgr.processPaths(variables, std::filesystem::current_path()); + cfgMgr.readConfiguration(variables, desc); Debug::setupLogging(cfgMgr.getLogPath(), "OpenMW"); diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index 5f96a4e095..532bc771ba 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -39,8 +39,8 @@ namespace MWSound class Sound; class Stream; - struct Sound_Decoder; - typedef std::shared_ptr DecoderPtr; + struct SoundDecoder; + typedef std::shared_ptr DecoderPtr; /* These must all fit together */ enum class PlayMode diff --git a/apps/openmw/mwdialogue/filter.cpp b/apps/openmw/mwdialogue/filter.cpp index 295d690ce5..b7d4a1361c 100644 --- a/apps/openmw/mwdialogue/filter.cpp +++ b/apps/openmw/mwdialogue/filter.cpp @@ -265,10 +265,6 @@ bool MWDialogue::Filter::testFunctionLocal(const MWDialogue::SelectWrapper& sele bool MWDialogue::Filter::testSelectStruct(const SelectWrapper& select) const { - if (select.isNpcOnly() && (mActor.getType() != ESM::NPC::sRecordId)) - // If the actor is a creature, we pass all conditions only applicable to NPCs. - return true; - if (select.getFunction() == ESM::DialogueCondition::Function_Choice && mChoice == -1) // If not currently in a choice, we reject all conditions that test against choices. return false; @@ -305,9 +301,13 @@ bool MWDialogue::Filter::testSelectStructNumeric(const SelectWrapper& select) co switch (select.getFunction()) { case ESM::DialogueCondition::Function_Global: - + { + const auto& world = MWBase::Environment::get().getWorld(); + if (world->getGlobalVariableType(select.getName()) == ' ') + return true; // ignore this filter if the global doesn't exist // internally all globals are float :( - return select.selectCompare(MWBase::Environment::get().getWorld()->getGlobalFloat(select.getName())); + return select.selectCompare(world->getGlobalFloat(select.getName())); + } case ESM::DialogueCondition::Function_Local: { @@ -504,7 +504,8 @@ int MWDialogue::Filter::getSelectStructInteger(const SelectWrapper& select) cons return MWBase::Environment::get().getWorld()->getCurrentWeather(); case ESM::DialogueCondition::Function_Reputation: - + if (!mActor.getClass().isNpc()) + return 0; return mActor.getClass().getNpcStats(mActor).getReputation(); case ESM::DialogueCondition::Function_FactionRankDifference: @@ -586,11 +587,11 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con case ESM::DialogueCondition::Function_NotClass: - return mActor.get()->mBase->mClass != select.getId(); + return !mActor.getClass().isNpc() || mActor.get()->mBase->mClass != select.getId(); case ESM::DialogueCondition::Function_NotRace: - return mActor.get()->mBase->mRace != select.getId(); + return !mActor.getClass().isNpc() || mActor.get()->mBase->mRace != select.getId(); case ESM::DialogueCondition::Function_NotCell: { @@ -598,12 +599,14 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con return !Misc::StringUtils::ciStartsWith(actorCell, select.getCellName()); } case ESM::DialogueCondition::Function_SameSex: - + if (!mActor.getClass().isNpc()) + return false; return (player.get()->mBase->mFlags & ESM::NPC::Female) == (mActor.get()->mBase->mFlags & ESM::NPC::Female); case ESM::DialogueCondition::Function_SameRace: - + if (!mActor.getClass().isNpc()) + return false; return mActor.get()->mBase->mRace == player.get()->mBase->mRace; case ESM::DialogueCondition::Function_SameFaction: @@ -668,7 +671,7 @@ bool MWDialogue::Filter::getSelectStructBoolean(const SelectWrapper& select) con case ESM::DialogueCondition::Function_Werewolf: - return mActor.getClass().getNpcStats(mActor).isWerewolf(); + return mActor.getClass().isNpc() && mActor.getClass().getNpcStats(mActor).isWerewolf(); default: diff --git a/apps/openmw/mwdialogue/selectwrapper.cpp b/apps/openmw/mwdialogue/selectwrapper.cpp index 02c9d29b59..f9469bf9a9 100644 --- a/apps/openmw/mwdialogue/selectwrapper.cpp +++ b/apps/openmw/mwdialogue/selectwrapper.cpp @@ -247,29 +247,6 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const }; } -bool MWDialogue::SelectWrapper::isNpcOnly() const -{ - switch (mSelect.mFunction) - { - case ESM::DialogueCondition::Function_NotFaction: - case ESM::DialogueCondition::Function_NotClass: - case ESM::DialogueCondition::Function_NotRace: - case ESM::DialogueCondition::Function_SameSex: - case ESM::DialogueCondition::Function_SameRace: - case ESM::DialogueCondition::Function_SameFaction: - case ESM::DialogueCondition::Function_RankRequirement: - case ESM::DialogueCondition::Function_Reputation: - case ESM::DialogueCondition::Function_FactionRankDifference: - case ESM::DialogueCondition::Function_Werewolf: - case ESM::DialogueCondition::Function_PcWerewolfKills: - case ESM::DialogueCondition::Function_FacReactionLowest: - case ESM::DialogueCondition::Function_FacReactionHighest: - return true; - default: - return false; - } -} - bool MWDialogue::SelectWrapper::selectCompare(int value) const { return selectCompareImp(mSelect, value); diff --git a/apps/openmw/mwdialogue/selectwrapper.hpp b/apps/openmw/mwdialogue/selectwrapper.hpp index d831b6cea0..d15334cbe1 100644 --- a/apps/openmw/mwdialogue/selectwrapper.hpp +++ b/apps/openmw/mwdialogue/selectwrapper.hpp @@ -28,9 +28,6 @@ namespace MWDialogue Type getType() const; - bool isNpcOnly() const; - ///< \attention Do not call any of the select functions for this select struct! - bool selectCompare(int value) const; bool selectCompare(float value) const; diff --git a/apps/openmw/mwgui/journalbooks.hpp b/apps/openmw/mwgui/journalbooks.hpp index dd6cb402c5..2549b2ad5b 100644 --- a/apps/openmw/mwgui/journalbooks.hpp +++ b/apps/openmw/mwgui/journalbooks.hpp @@ -4,7 +4,7 @@ #include "bookpage.hpp" #include "journalviewmodel.hpp" -#include +#include namespace MWGui { diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 31efa695bb..e324133b44 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -3,7 +3,7 @@ #include "windowbase.hpp" -#include +#include #include diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp index 7eb10def39..425c519175 100644 --- a/apps/openmw/mwgui/merchantrepair.cpp +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -83,7 +83,7 @@ namespace MWGui int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true); std::string name{ iter->getClass().getName(*iter) }; - name += " - " + MyGUI::utility::toString(price) + name += " - " + MyGUI::utility::toString(price) + MWBase::Environment::get().getESMStore()->get().find("sgp")->mValue.getString(); items.emplace_back(name, price, *iter); diff --git a/apps/openmw/mwgui/pickpocketitemmodel.cpp b/apps/openmw/mwgui/pickpocketitemmodel.cpp index fa7bce449b..8756427589 100644 --- a/apps/openmw/mwgui/pickpocketitemmodel.cpp +++ b/apps/openmw/mwgui/pickpocketitemmodel.cpp @@ -101,8 +101,8 @@ namespace MWGui { MWBase::Environment::get().getMechanicsManager()->commitCrime( player, mActor, MWBase::MechanicsManager::OT_Pickpocket, ESM::RefId(), 0, true); - MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container); mPickpocketDetected = true; + MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container); } } @@ -129,8 +129,8 @@ namespace MWGui { MWBase::Environment::get().getMechanicsManager()->commitCrime( player, mActor, MWBase::MechanicsManager::OT_Pickpocket, ESM::RefId(), 0, true); - MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container); mPickpocketDetected = true; + MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container); return false; } else diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index ecbf3e6dfc..96045b8e21 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -434,6 +434,9 @@ namespace MWGui } store.setSelectedEnchantItem(it); + // to reset WindowManager::mSelectedSpell immediately + MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(*it); + MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState::Spell); } } @@ -461,6 +464,9 @@ namespace MWGui store.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight); MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState::Weapon); } + + // Updates the state of equipped/not equipped (skin) in spellwindow + MWBase::Environment::get().getWindowManager()->updateSpellWindow(); } bool QuickKeysMenu::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 2dfcd4cee7..b69b9535ea 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -45,6 +45,7 @@ namespace MWGui { getWidget(mScreenshot, "Screenshot"); getWidget(mCharacterSelection, "SelectCharacter"); + getWidget(mCellName, "CellName"); getWidget(mInfoText, "InfoText"); getWidget(mOkButton, "OkButton"); getWidget(mCancelButton, "CancelButton"); @@ -230,7 +231,8 @@ namespace MWGui title << " (#{OMWEngine:Level} " << signature.mPlayerLevel << " " << MyGUI::TextIterator::toTagsString(MyGUI::UString(className)) << ")"; - mCharacterSelection->addItem(MyGUI::LanguageManager::getInstance().replaceTags(title.str())); + const MyGUI::UString playerDesc = MyGUI::LanguageManager::getInstance().replaceTags(title.str()); + mCharacterSelection->addItem(playerDesc, signature.mPlayerName); if (mCurrentCharacter == &*it || (!mCurrentCharacter && !mSaving @@ -424,6 +426,7 @@ namespace MWGui if (pos == MyGUI::ITEM_NONE || !mCurrentCharacter) { mCurrentSlot = nullptr; + mCellName->setCaption({}); mInfoText->setCaption({}); mScreenshot->setImageTexture({}); return; @@ -445,15 +448,21 @@ namespace MWGui std::stringstream text; - text << Misc::fileTimeToString(mCurrentSlot->mTimeStamp, "%Y.%m.%d %T") << "\n"; + const size_t profileIndex = mCharacterSelection->getIndexSelected(); + const std::string& slotPlayerName = mCurrentSlot->mProfile.mPlayerName; + const std::string& profilePlayerName = *mCharacterSelection->getItemDataAt(profileIndex); + if (slotPlayerName != profilePlayerName) + text << slotPlayerName << "\n"; + + text << "#{OMWEngine:Level} " << mCurrentSlot->mProfile.mPlayerLevel << "\n"; + + if (mCurrentSlot->mProfile.mCurrentDay > 0) + text << "#{Calendar:day} " << mCurrentSlot->mProfile.mCurrentDay << "\n"; if (mCurrentSlot->mProfile.mMaximumHealth > 0) text << "#{OMWEngine:Health} " << static_cast(mCurrentSlot->mProfile.mCurrentHealth) << "/" << static_cast(mCurrentSlot->mProfile.mMaximumHealth) << "\n"; - text << "#{OMWEngine:Level} " << mCurrentSlot->mProfile.mPlayerLevel << "\n"; - text << "#{sCell=" << mCurrentSlot->mProfile.mPlayerCellName << "}\n"; - int hour = int(mCurrentSlot->mProfile.mInGameTime.mGameHour); bool pm = hour >= 12; if (hour >= 13) @@ -461,20 +470,19 @@ namespace MWGui if (hour == 0) hour = 12; - if (mCurrentSlot->mProfile.mCurrentDay > 0) - text << "#{Calendar:day} " << mCurrentSlot->mProfile.mCurrentDay << "\n"; - text << mCurrentSlot->mProfile.mInGameTime.mDay << " " << MWBase::Environment::get().getWorld()->getTimeManager()->getMonthName( mCurrentSlot->mProfile.mInGameTime.mMonth) - << " " << hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}"); + << " " << hour << " " << (pm ? "#{Calendar:pm}" : "#{Calendar:am}") << "\n"; if (mCurrentSlot->mProfile.mTimePlayed > 0) { - text << "\n" - << "#{OMWEngine:TimePlayed}: " << formatTimeplayed(mCurrentSlot->mProfile.mTimePlayed); + text << "#{OMWEngine:TimePlayed}: " << formatTimeplayed(mCurrentSlot->mProfile.mTimePlayed) << "\n"; } + text << Misc::fileTimeToString(mCurrentSlot->mTimeStamp, "%Y.%m.%d %T") << "\n"; + + mCellName->setCaptionWithReplacing("#{sCell=" + mCurrentSlot->mProfile.mPlayerCellName + "}"); mInfoText->setCaptionWithReplacing(text.str()); // Reset the image for the case we're unable to recover a screenshot diff --git a/apps/openmw/mwgui/savegamedialog.hpp b/apps/openmw/mwgui/savegamedialog.hpp index 4717279dfb..13c4588d3f 100644 --- a/apps/openmw/mwgui/savegamedialog.hpp +++ b/apps/openmw/mwgui/savegamedialog.hpp @@ -59,6 +59,7 @@ namespace MWGui bool mSaving; MyGUI::ComboBox* mCharacterSelection; + MyGUI::EditBox* mCellName; MyGUI::EditBox* mInfoText; MyGUI::Button* mOkButton; MyGUI::Button* mCancelButton; diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 754055aee5..5d25dc592c 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -20,6 +20,7 @@ #include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/spells.hpp" +#include "../mwmechanics/spellutil.hpp" namespace MWGui { @@ -52,8 +53,8 @@ namespace MWGui const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore(); int price = std::max(1, - static_cast( - spell.mData.mCost * store.get().find("fSpellValueMult")->mValue.getFloat())); + static_cast(MWMechanics::calcSpellCost(spell) + * store.get().find("fSpellValueMult")->mValue.getFloat())); price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true); MWWorld::Ptr player = MWMechanics::getPlayer(); @@ -71,7 +72,7 @@ namespace MWGui mCurrentY += lineHeight; toAdd->setUserData(price); - toAdd->setCaptionWithReplacing(spell.mName + " - " + MyGUI::utility::toString(price) + "#{sgp}"); + toAdd->setCaptionWithReplacing(spell.mName + " - " + MyGUI::utility::toString(price) + "#{sgp}"); toAdd->setSize(mSpellsView->getWidth(), lineHeight); toAdd->eventMouseWheel += MyGUI::newDelegate(this, &SpellBuyingWindow::onMouseWheel); toAdd->setUserString("ToolTipType", "Spell"); diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index b4c970c9bd..ea21a67423 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -252,22 +252,51 @@ namespace MWGui return; mSpellView->setModel(new SpellModel(MWMechanics::getPlayer())); - - SpellModel::ModelIndex selected = mSpellView->getModel()->getSelectedIndex(); - if (selected < 0) - selected = 0; - - selected += next ? 1 : -1; - int itemcount = mSpellView->getModel()->getItemCount(); - if (itemcount == 0) + int itemCount = mSpellView->getModel()->getItemCount(); + if (itemCount == 0) return; - selected = (selected + itemcount) % itemcount; - const Spell& spell = mSpellView->getModel()->getItem(selected); - if (spell.mType == Spell::Type_EnchantedItem) - onEnchantedItemSelected(spell.mItem, spell.mActive); + SpellModel::ModelIndex nextIndex; + SpellModel::ModelIndex currentIndex = mSpellView->getModel()->getSelectedIndex(); + + // If we have a selected index, search for a valid selection in the target direction + if (currentIndex >= 0) + { + MWWorld::ContainerStore store; + const Spell& currentSpell = mSpellView->getModel()->getItem(currentIndex); + + nextIndex = currentIndex; + for (int i = 0; i < itemCount; i++) + { + nextIndex += next ? 1 : -1; + nextIndex = (nextIndex + itemCount) % itemCount; + + // We can keep this selection if: + // * we're not switching off of an enchanted item + // * we're not switching to an enchanted item + // * the next item wouldn't stack with the current item + if (currentSpell.mType != Spell::Type_EnchantedItem) + break; + + const Spell& nextSpell = mSpellView->getModel()->getItem(nextIndex); + if (nextSpell.mType != Spell::Type_EnchantedItem || !store.stacks(currentSpell.mItem, nextSpell.mItem)) + break; + } + } + // Otherwise, the first selection is always index 0 else - onSpellSelected(spell.mId); + nextIndex = 0; + + // Only trigger the selection event if the selection is actually changing. + // The itemCount check earlier ensures we have at least one spell to select. + if (nextIndex != currentIndex) + { + const Spell& selectedSpell = mSpellView->getModel()->getItem(nextIndex); + if (selectedSpell.mType == Spell::Type_EnchantedItem) + onEnchantedItemSelected(selectedSpell.mItem, selectedSpell.mActive); + else + onSpellSelected(selectedSpell.mId); + } } bool SpellWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg) diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index a667d3905f..5b91a46bf8 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -33,16 +33,10 @@ namespace MWGui { getWidget(mCancelButton, "CancelButton"); getWidget(mPlayerGold, "PlayerGold"); - getWidget(mSelect, "Select"); - getWidget(mDestinations, "Travel"); getWidget(mDestinationsView, "DestinationsView"); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TravelWindow::onCancelButtonClicked); - mDestinations->setCoord(450 / 2 - mDestinations->getTextSize().width / 2, mDestinations->getTop(), - mDestinations->getTextSize().width, mDestinations->getHeight()); - mSelect->setCoord(8, mSelect->getTop(), mSelect->getTextSize().width, mSelect->getHeight()); - if (Settings::gui().mControllerMenus) { mDisableGamepadCursor = true; @@ -100,8 +94,7 @@ namespace MWGui const std::string& nameString = name.getRefIdString(); toAdd->setUserString("price", std::to_string(price)); - toAdd->setCaptionWithReplacing( - "#{sCell=" + nameString + "} - " + MyGUI::utility::toString(price) + "#{sgp}"); + toAdd->setCaptionWithReplacing("#{sCell=" + nameString + "} - " + MyGUI::utility::toString(price) + "#{sgp}"); toAdd->setSize(mDestinationsView->getWidth(), lineHeight); toAdd->eventMouseWheel += MyGUI::newDelegate(this, &TravelWindow::onMouseWheel); toAdd->setUserString("Destination", nameString); diff --git a/apps/openmw/mwgui/travelwindow.hpp b/apps/openmw/mwgui/travelwindow.hpp index 1136718e72..79f5f9abc8 100644 --- a/apps/openmw/mwgui/travelwindow.hpp +++ b/apps/openmw/mwgui/travelwindow.hpp @@ -24,8 +24,7 @@ namespace MWGui protected: MyGUI::Button* mCancelButton; MyGUI::TextBox* mPlayerGold; - MyGUI::TextBox* mDestinations; - MyGUI::TextBox* mSelect; + std::vector mDestinationButtons; MyGUI::ScrollView* mDestinationsView; diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 6cc61fb279..c8f1c7e06c 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include "charactercreation.hpp" #include "controllerbuttonsoverlay.hpp" diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 9e64996e46..0f361f7ffc 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -267,7 +267,7 @@ namespace MWMechanics if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power && !isSpellActive(spell->mId)) { - mSpells.emplace_back(ActiveSpellParams{ spell, ptr }); + mSpells.emplace_back(ActiveSpellParams{ spell, ptr, true }); mSpells.back().setActiveSpellId(MWBase::Environment::get().getESMStore()->generateId()); } } @@ -506,9 +506,9 @@ namespace MWMechanics mQueue.emplace_back(params); } - void ActiveSpells::addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor) + void ActiveSpells::addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor, bool ignoreResistances) { - mQueue.emplace_back(ActiveSpellParams{ spell, actor, true }); + mQueue.emplace_back(ActiveSpellParams{ spell, actor, ignoreResistances }); } void ActiveSpells::purge(ParamsPredicate predicate, const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index e4fa60ddb6..3e4dafdb26 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -137,8 +137,8 @@ namespace MWMechanics /// void addSpell(const ActiveSpellParams& params); - /// Bypasses resistances - void addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor); + /// Force resistances + void addSpell(const ESM::Spell* spell, const MWWorld::Ptr& actor, bool ignoreResistances = true); /// Removes the active effects from this spell/potion/.. with \a id void removeEffectsBySourceSpellId(const MWWorld::Ptr& ptr, const ESM::RefId& id); diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index ca33f5dc90..edb62c97c4 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -119,6 +119,7 @@ namespace MWMechanics /// Reset pathfinding state void reset(); + virtual void resetInitialPosition() {} /// Return if actor's rotation speed is sufficient to rotate to the destination pathpoint on the run. Otherwise /// actor should rotate while standing. diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index 019aaf7c0a..70b94b1eba 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -400,7 +400,7 @@ namespace MWMechanics const auto newTypeId = package.getTypeId(); if (currentTypeId <= MWMechanics::AiPackageTypeId::Wander && !hasPackage(MWMechanics::AiPackageTypeId::InternalTravel) - && (newTypeId <= MWMechanics::AiPackageTypeId::Combat || newTypeId == MWMechanics::AiPackageTypeId::Pursue + && (newTypeId == MWMechanics::AiPackageTypeId::Combat || newTypeId == MWMechanics::AiPackageTypeId::Pursue || newTypeId == MWMechanics::AiPackageTypeId::Cast)) { osg::Vec3f dest; @@ -444,8 +444,15 @@ namespace MWMechanics if ((*it)->getPriority() <= package.getPriority()) { + if (cancelOther && isActualAiPackage((*it)->getTypeId())) + mAiState.reset(); onPackageAdded(package); - mPackages.insert(it, package.clone()); + it = mPackages.insert(it, package.clone()); + if (newTypeId == MWMechanics::AiPackageTypeId::Follow) + { + for (++it; it != mPackages.end(); ++it) + (*it)->resetInitialPosition(); + } return; } } @@ -455,11 +462,7 @@ namespace MWMechanics // Make sure that temporary storage is empty if (cancelOther) - { - mAiState.moveIn(std::make_unique()); - mAiState.moveIn(std::make_unique()); - mAiState.moveIn(std::make_unique()); - } + mAiState.reset(); } bool MWMechanics::AiSequence::isEmpty() const diff --git a/apps/openmw/mwmechanics/aistate.hpp b/apps/openmw/mwmechanics/aistate.hpp index f2ce17fd9c..bb88557b6d 100644 --- a/apps/openmw/mwmechanics/aistate.hpp +++ b/apps/openmw/mwmechanics/aistate.hpp @@ -59,12 +59,7 @@ namespace MWMechanics mStorage = std::make_unique(payload); } - /// \brief takes ownership of the passed object - template - void moveIn(std::unique_ptr&& storage) - { - mStorage = std::move(storage); - } + void reset() { mStorage.reset(); } }; } diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 42667a406a..464d83ad46 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -676,6 +676,13 @@ namespace MWMechanics stopMovement(actor); } + void AiWander::resetInitialPosition() + { + mStoredInitialActorPosition = false; + mPathFinder.clearPath(); + mHasDestination = false; + } + bool AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect) { if ((GroupIndex_MinIdle <= idleSelect) && (idleSelect <= GroupIndex_MaxIdle)) @@ -804,7 +811,7 @@ namespace MWMechanics converter.toWorld(dest); - state.moveIn(std::make_unique()); + state.reset(); osg::Vec3f pos(static_cast(dest.mX), static_cast(dest.mY), static_cast(dest.mZ)); MWBase::Environment::get().getWorld()->moveObject(actor, pos); diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 01a02096a4..f08980ad29 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -122,6 +122,8 @@ namespace MWMechanics static std::string_view getIdleGroupName(size_t index) { return sIdleSelectToGroupName[index]; } + void resetInitialPosition() override; + private: void stopWalking(const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwmechanics/disease.hpp b/apps/openmw/mwmechanics/disease.hpp index c793d5d540..262f813916 100644 --- a/apps/openmw/mwmechanics/disease.hpp +++ b/apps/openmw/mwmechanics/disease.hpp @@ -66,7 +66,9 @@ namespace MWMechanics if (Misc::Rng::rollDice(10000, prng) < x) { // Contracted disease! - actor.getClass().getCreatureStats(actor).getSpells().add(spell); + MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor); + creatureStats.getSpells().add(spell); + creatureStats.getActiveSpells().addSpell(spell, actor, false); MWBase::Environment::get().getWorld()->applyLoopingParticles(actor); std::string msg = MWBase::Environment::get() diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 7d0007f9e3..66bef89e2c 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -185,18 +185,18 @@ namespace MWMechanics * * Formula on UESPWiki is not entirely correct. */ - float Enchanting::getEnchantPoints(bool precise) const + std::vector Enchanting::getEffectCosts() const { + std::vector costs; if (mEffectList.mList.empty()) - // No effects added, cost = 0 - return 0; + return costs; + costs.reserve(mEffectList.mList.size()); const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore(); const float fEffectCostMult = store.get().find("fEffectCostMult")->mValue.getFloat(); const float fEnchantmentConstantDurationMult = store.get().find("fEnchantmentConstantDurationMult")->mValue.getFloat(); - float enchantmentCost = 0.f; float cost = 0.f; for (const ESM::IndexedENAMstruct& effect : mEffectList.mList) { @@ -215,9 +215,18 @@ namespace MWMechanics if (effect.mData.mRange == ESM::RT_Target) cost *= 1.5f; - enchantmentCost += precise ? cost : std::floor(cost); + costs.push_back(cost); } + return costs; + } + + float Enchanting::getEnchantPoints(bool precise) const + { + float enchantmentCost = 0.f; + for (float cost : getEffectCosts()) + enchantmentCost += precise ? cost : std::floor(cost); + return enchantmentCost; } @@ -278,13 +287,19 @@ namespace MWMechanics if (mEnchanter.isEmpty()) return 0; + // Use the final effect's accumulated cost + float finalEffectCost = 0.f; + std::vector effectCosts = getEffectCosts(); + if (!effectCosts.empty()) + finalEffectCost = effectCosts.back(); + float priceMultipler = MWBase::Environment::get() .getESMStore() ->get() .find("fEnchantmentValueMult") ->mValue.getFloat(); int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer( - mEnchanter, static_cast(getEnchantPoints() * priceMultipler), true); + mEnchanter, static_cast(finalEffectCost * priceMultipler), true); price *= count * getTypeMultiplier(); return std::max(1, price); } diff --git a/apps/openmw/mwmechanics/enchanting.hpp b/apps/openmw/mwmechanics/enchanting.hpp index 5db02b8cba..98e0982f7c 100644 --- a/apps/openmw/mwmechanics/enchanting.hpp +++ b/apps/openmw/mwmechanics/enchanting.hpp @@ -2,6 +2,7 @@ #define GAME_MWMECHANICS_ENCHANTING_H #include +#include #include #include @@ -32,6 +33,7 @@ namespace MWMechanics float getTypeMultiplier() const; void payForEnchantment(int count) const; int getEnchantPrice(int count) const; + std::vector getEffectCosts() const; public: Enchanting(); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 47c49a8861..384c25953b 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1232,33 +1232,39 @@ namespace MWMechanics victim.getClass().getCreatureStats(victim).notifyMurder(); // Bounty and disposition penalty for each type of crime - float disp = 0.f, dispVictim = 0.f; + int bounty; + float disp, dispVictim; if (type == OT_Trespassing || type == OT_SleepingInOwnedBed) { - arg = store.find("iCrimeTresspass")->mValue.getInteger(); + bounty = store.find("iCrimeTresspass")->mValue.getInteger(); disp = dispVictim = store.find("iDispTresspass")->mValue.getFloat(); } else if (type == OT_Pickpocket) { - arg = store.find("iCrimePickPocket")->mValue.getInteger(); + bounty = store.find("iCrimePickPocket")->mValue.getInteger(); disp = dispVictim = store.find("fDispPickPocketMod")->mValue.getFloat(); } else if (type == OT_Assault) { - arg = store.find("iCrimeAttack")->mValue.getInteger(); + bounty = store.find("iCrimeAttack")->mValue.getInteger(); disp = store.find("iDispAttackMod")->mValue.getFloat(); dispVictim = store.find("fDispAttacking")->mValue.getFloat(); } else if (type == OT_Murder) { - arg = store.find("iCrimeKilling")->mValue.getInteger(); + bounty = store.find("iCrimeKilling")->mValue.getInteger(); disp = dispVictim = store.find("iDispKilling")->mValue.getFloat(); } else if (type == OT_Theft) { + bounty = static_cast(arg * store.find("fCrimeStealing")->mValue.getFloat()); + bounty = std::max(1, bounty); // Minimum bounty of 1, in case items with zero value are stolen disp = dispVictim = store.find("fDispStealing")->mValue.getFloat() * arg; - arg = static_cast(arg * store.find("fCrimeStealing")->mValue.getFloat()); - arg = std::max(1, arg); // Minimum bounty of 1, in case items with zero value are stolen + } + else + { + bounty = arg; + disp = dispVictim = 0.f; } // Make surrounding actors within alarm distance respond to the crime @@ -1296,7 +1302,7 @@ namespace MWMechanics else if (type == OT_Murder) fight = fightVictim = esmStore.get().find("iFightKilling")->mValue.getInteger(); else if (type == OT_Theft) - fight = fightVictim = esmStore.get().find("fFightStealing")->mValue.getInteger(); + fight = fightVictim = esmStore.get().find("fFightStealing")->mValue.getInteger() * arg; bool reported = false; @@ -1457,7 +1463,7 @@ namespace MWMechanics if (reported) { player.getClass().getNpcStats(player).setBounty( - std::max(0, player.getClass().getNpcStats(player).getBounty() + arg)); + std::max(0, player.getClass().getNpcStats(player).getBounty() + bounty)); // If committing a crime against a faction member, expell from the faction if (!victim.isEmpty() && victim.getClass().isNpc()) diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 07855f18ef..3f84362c34 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -115,6 +115,11 @@ namespace MWScript std::string_view cell = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); + // In Morrowind, using an empty string either errors out (e.g. console) or kills the game + // so it should be reasonable to interrupt the script + if (cell.empty()) + throw std::runtime_error("ShowMap substring must not be empty"); + // "Will match complete or partial cells, so ShowMap, "Vivec" will show cells Vivec and Vivec, Fred's // House as well." http://www.uesp.net/wiki/Tes3Mod:ShowMap diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index ed2ef756e6..95238d4299 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -884,8 +884,8 @@ namespace MWScript return; } - const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); - runtime.push(stats.getActiveSpells().isSpellActive(id)); + const auto& activeSpells = ptr.getClass().getCreatureStats(ptr).getActiveSpells(); + runtime.push(activeSpells.isSpellActive(id) || activeSpells.isEnchantmentActive(id)); } }; diff --git a/apps/openmw/mwsound/efx-presets.h b/apps/openmw/mwsound/efxpresets.h similarity index 99% rename from apps/openmw/mwsound/efx-presets.h rename to apps/openmw/mwsound/efxpresets.h index a9662936d5..a36c41db03 100644 --- a/apps/openmw/mwsound/efx-presets.h +++ b/apps/openmw/mwsound/efxpresets.h @@ -1,7 +1,7 @@ /* Reverb presets for EFX */ -#ifndef EFX_PRESETS_H -#define EFX_PRESETS_H +#ifndef GAME_SOUND_EFXPRESETS_H +#define GAME_SOUND_EFXPRESETS_H #ifndef EFXEAXREVERBPROPERTIES_DEFINED #define EFXEAXREVERBPROPERTIES_DEFINED @@ -852,4 +852,4 @@ typedef struct 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 \ } -#endif /* EFX_PRESETS_H */ +#endif diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpegdecoder.cpp similarity index 93% rename from apps/openmw/mwsound/ffmpeg_decoder.cpp rename to apps/openmw/mwsound/ffmpegdecoder.cpp index 54fd126c41..5a0f336a93 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpegdecoder.cpp @@ -1,4 +1,4 @@ -#include "ffmpeg_decoder.hpp" +#include "ffmpegdecoder.hpp" #include #include @@ -44,11 +44,11 @@ namespace MWSound av_frame_free(&ptr); } - int FFmpeg_Decoder::readPacket(void* user_data, uint8_t* buf, int buf_size) + int FFmpegDecoder::readPacket(void* user_data, uint8_t* buf, int buf_size) { try { - std::istream& stream = *static_cast(user_data)->mDataStream; + std::istream& stream = *static_cast(user_data)->mDataStream; stream.clear(); stream.read((char*)buf, buf_size); std::streamsize count = stream.gcount(); @@ -65,18 +65,18 @@ namespace MWSound } #if OPENMW_FFMPEG_CONST_WRITEPACKET - int FFmpeg_Decoder::writePacket(void*, const uint8_t*, int) + int FFmpegDecoder::writePacket(void*, const uint8_t*, int) #else - int FFmpeg_Decoder::writePacket(void*, uint8_t*, int) + int FFmpegDecoder::writePacket(void*, uint8_t*, int) #endif { Log(Debug::Error) << "can't write to read-only stream"; return -1; } - int64_t FFmpeg_Decoder::seek(void* user_data, int64_t offset, int whence) + int64_t FFmpegDecoder::seek(void* user_data, int64_t offset, int whence) { - std::istream& stream = *static_cast(user_data)->mDataStream; + std::istream& stream = *static_cast(user_data)->mDataStream; whence &= ~AVSEEK_FORCE; @@ -106,7 +106,7 @@ namespace MWSound /* Used by getAV*Data to search for more compressed data, and buffer it in the * correct stream. It won't buffer data for streams that the app doesn't have a * handle for. */ - bool FFmpeg_Decoder::getNextPacket() + bool FFmpegDecoder::getNextPacket() { if (!mStream) return false; @@ -129,7 +129,7 @@ namespace MWSound return false; } - bool FFmpeg_Decoder::getAVAudioData() + bool FFmpegDecoder::getAVAudioData() { bool got_frame = false; @@ -192,7 +192,7 @@ namespace MWSound return true; } - size_t FFmpeg_Decoder::readAVAudioData(void* data, size_t length) + size_t FFmpegDecoder::readAVAudioData(void* data, size_t length) { size_t dec = 0; @@ -227,7 +227,7 @@ namespace MWSound return dec; } - void FFmpeg_Decoder::open(VFS::Path::NormalizedView fname) + void FFmpegDecoder::open(VFS::Path::NormalizedView fname) { close(); mDataStream = mResourceMgr->get(fname); @@ -317,7 +317,7 @@ namespace MWSound mStream = stream; } - void FFmpeg_Decoder::close() + void FFmpegDecoder::close() { mStream = nullptr; mCodecCtx.reset(); @@ -332,7 +332,7 @@ namespace MWSound mDataStream.reset(); } - std::string FFmpeg_Decoder::getName() + std::string FFmpegDecoder::getName() { // In the FFMpeg 4.0 a "filename" field was replaced by "url" #if LIBAVCODEC_VERSION_INT < 3805796 @@ -342,7 +342,7 @@ namespace MWSound #endif } - void FFmpeg_Decoder::getInfo(int* samplerate, ChannelConfig* chans, SampleType* type) + void FFmpegDecoder::getInfo(int* samplerate, ChannelConfig* chans, SampleType* type) { if (!mStream) throw std::runtime_error("No audio stream info"); @@ -459,7 +459,7 @@ namespace MWSound } } - size_t FFmpeg_Decoder::read(char* buffer, size_t bytes) + size_t FFmpegDecoder::read(char* buffer, size_t bytes) { if (!mStream) { @@ -469,7 +469,7 @@ namespace MWSound return readAVAudioData(buffer, bytes); } - void FFmpeg_Decoder::readAll(std::vector& output) + void FFmpegDecoder::readAll(std::vector& output) { if (!mStream) { @@ -490,7 +490,7 @@ namespace MWSound } } - size_t FFmpeg_Decoder::getSampleOffset() + size_t FFmpegDecoder::getSampleOffset() { #if OPENMW_FFMPEG_5_OR_GREATER std::size_t delay = (mFrameSize - mFramePos) / mOutputChannelLayout.nb_channels @@ -501,8 +501,8 @@ namespace MWSound return static_cast(mNextPts * mCodecCtx->sample_rate) - delay; } - FFmpeg_Decoder::FFmpeg_Decoder(const VFS::Manager* vfs) - : Sound_Decoder(vfs) + FFmpegDecoder::FFmpegDecoder(const VFS::Manager* vfs) + : SoundDecoder(vfs) , mStream(nullptr) , mFrameSize(0) , mFramePos(0) @@ -534,7 +534,7 @@ namespace MWSound } } - FFmpeg_Decoder::~FFmpeg_Decoder() + FFmpegDecoder::~FFmpegDecoder() { close(); } diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpegdecoder.hpp similarity index 89% rename from apps/openmw/mwsound/ffmpeg_decoder.hpp rename to apps/openmw/mwsound/ffmpegdecoder.hpp index e67b8efbf3..c71b935bc4 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.hpp +++ b/apps/openmw/mwsound/ffmpegdecoder.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_SOUND_FFMPEG_DECODER_H -#define GAME_SOUND_FFMPEG_DECODER_H +#ifndef GAME_SOUND_FFMPEGDECODER_H +#define GAME_SOUND_FFMPEGDECODER_H #include @@ -31,7 +31,7 @@ extern "C" #include -#include "sound_decoder.hpp" +#include "sounddecoder.hpp" namespace MWSound { @@ -63,7 +63,7 @@ namespace MWSound using AVFramePtr = std::unique_ptr; - class FFmpeg_Decoder final : public Sound_Decoder + class FFmpegDecoder final : public SoundDecoder { AVIOContextPtr mIoCtx; AVFormatContextPtr mFormatCtx; @@ -114,13 +114,13 @@ namespace MWSound void readAll(std::vector& output) override; size_t getSampleOffset() override; - FFmpeg_Decoder& operator=(const FFmpeg_Decoder& rhs); - FFmpeg_Decoder(const FFmpeg_Decoder& rhs); + FFmpegDecoder& operator=(const FFmpegDecoder& rhs); + FFmpegDecoder(const FFmpegDecoder& rhs); public: - explicit FFmpeg_Decoder(const VFS::Manager* vfs); + explicit FFmpegDecoder(const VFS::Manager* vfs); - virtual ~FFmpeg_Decoder(); + virtual ~FFmpegDecoder(); friend class SoundManager; }; diff --git a/apps/openmw/mwsound/loudness.hpp b/apps/openmw/mwsound/loudness.hpp index 1800ec246f..edc201f38a 100644 --- a/apps/openmw/mwsound/loudness.hpp +++ b/apps/openmw/mwsound/loudness.hpp @@ -4,7 +4,7 @@ #include #include -#include "sound_decoder.hpp" +#include "sounddecoder.hpp" namespace MWSound { diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 962086701a..61992bc0d5 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -7,17 +7,17 @@ #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" -#include "sound_decoder.hpp" +#include "sounddecoder.hpp" namespace MWSound { class MovieAudioDecoder; - class MWSoundDecoderBridge final : public Sound_Decoder + class MWSoundDecoderBridge final : public SoundDecoder { public: MWSoundDecoderBridge(MWSound::MovieAudioDecoder* decoder) - : Sound_Decoder(nullptr) + : SoundDecoder(nullptr) , mDecoder(decoder) { } diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openaloutput.cpp similarity index 95% rename from apps/openmw/mwsound/openal_output.cpp rename to apps/openmw/mwsound/openaloutput.cpp index f829ea458a..0f27524912 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openaloutput.cpp @@ -17,14 +17,13 @@ #include #include +#include "efxpresets.h" #include "loudness.hpp" -#include "openal_output.hpp" +#include "openaloutput.hpp" #include "sound.hpp" -#include "sound_decoder.hpp" +#include "sounddecoder.hpp" #include "soundmanagerimp.hpp" -#include "efx-presets.h" - #ifndef ALC_ALL_DEVICES_SPECIFIER #define ALC_ALL_DEVICES_SPECIFIER 0x1013 #endif @@ -301,7 +300,7 @@ namespace MWSound OpenAL_SoundStream(const OpenAL_SoundStream& rhs); OpenAL_SoundStream& operator=(const OpenAL_SoundStream& rhs); - friend class OpenAL_Output; + friend class OpenALOutput; public: OpenAL_SoundStream(ALuint src, DecoderPtr decoder); @@ -323,7 +322,7 @@ namespace MWSound // // A background streaming thread (keeps active streams processed) // - struct OpenAL_Output::StreamThread + struct OpenALOutput::StreamThread { std::vector mStreams; @@ -393,13 +392,13 @@ namespace MWSound StreamThread& operator=(const StreamThread& rhs) = delete; }; - class OpenAL_Output::DefaultDeviceThread + class OpenALOutput::DefaultDeviceThread { public: std::basic_string mCurrentName; private: - OpenAL_Output& mOutput; + OpenALOutput& mOutput; std::atomic mQuitNow; std::mutex mMutex; @@ -433,7 +432,7 @@ namespace MWSound } public: - DefaultDeviceThread(OpenAL_Output& output, std::basic_string_view name = {}) + DefaultDeviceThread(OpenALOutput& output, std::basic_string_view name = {}) : mCurrentName(name) , mOutput(output) , mQuitNow(false) @@ -655,7 +654,7 @@ namespace MWSound // // An OpenAL output device // - std::vector OpenAL_Output::enumerate() + std::vector OpenALOutput::enumerate() { std::vector devlist; const ALCchar* devnames; @@ -672,14 +671,14 @@ namespace MWSound return devlist; } - void OpenAL_Output::eventCallback( + void OpenALOutput::eventCallback( ALenum eventType, ALuint object, ALuint param, ALsizei length, const ALchar* message, void* userParam) { if (eventType == AL_EVENT_TYPE_DISCONNECTED_SOFT) - static_cast(userParam)->onDisconnect(); + static_cast(userParam)->onDisconnect(); } - void OpenAL_Output::onDisconnect() + void OpenALOutput::onDisconnect() { if (!mInitialized || !alcReopenDeviceSOFT) return; @@ -702,7 +701,7 @@ namespace MWSound } } - bool OpenAL_Output::init(const std::string& devname, const std::string& hrtfname, HrtfMode hrtfmode) + bool OpenALOutput::init(const std::string& devname, const std::string& hrtfname, HrtfMode hrtfmode) { deinit(); std::lock_guard lock(mReopenMutex); @@ -802,7 +801,7 @@ namespace MWSound { static const std::array events{ { AL_EVENT_TYPE_DISCONNECTED_SOFT } }; alEventControlSOFT(events.size(), events.data(), AL_TRUE); - alEventCallbackSOFT(&OpenAL_Output::eventCallback, this); + alEventCallbackSOFT(&OpenALOutput::eventCallback, this); } else Log(Debug::Warning) << "Cannot detect audio device changes"; @@ -970,7 +969,7 @@ namespace MWSound return true; } - void OpenAL_Output::deinit() + void OpenALOutput::deinit() { mStreamThread->removeAll(); mDefaultDeviceThread.reset(); @@ -1006,7 +1005,7 @@ namespace MWSound mInitialized = false; } - std::vector OpenAL_Output::enumerateHrtf() + std::vector OpenALOutput::enumerateHrtf() { std::vector ret; @@ -1028,7 +1027,7 @@ namespace MWSound return ret; } - std::pair OpenAL_Output::loadSound(VFS::Path::NormalizedView fname) + std::pair OpenALOutput::loadSound(VFS::Path::NormalizedView fname) { getALError(); @@ -1076,7 +1075,7 @@ namespace MWSound return std::make_pair(MAKE_PTRID(buf), size); } - size_t OpenAL_Output::unloadSound(Sound_Handle data) + size_t OpenALOutput::unloadSound(Sound_Handle data) { ALuint buffer = GET_PTRID(data); if (!buffer) @@ -1105,7 +1104,7 @@ namespace MWSound return size; } - void OpenAL_Output::initCommon2D( + void OpenALOutput::initCommon2D( ALuint source, const osg::Vec3f& pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv) { alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f); @@ -1143,7 +1142,7 @@ namespace MWSound alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); } - void OpenAL_Output::initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist, + void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv) { alSourcef(source, AL_REFERENCE_DISTANCE, mindist); @@ -1183,7 +1182,7 @@ namespace MWSound alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); } - void OpenAL_Output::updateCommon( + void OpenALOutput::updateCommon( ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv) { if (useenv && mListenerEnv == Env_Underwater && !mWaterFilter) @@ -1199,7 +1198,7 @@ namespace MWSound alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); } - bool OpenAL_Output::playSound(Sound* sound, Sound_Handle data, float offset) + bool OpenALOutput::playSound(Sound* sound, Sound_Handle data, float offset) { ALuint source; @@ -1238,7 +1237,7 @@ namespace MWSound return true; } - bool OpenAL_Output::playSound3D(Sound* sound, Sound_Handle data, float offset) + bool OpenALOutput::playSound3D(Sound* sound, Sound_Handle data, float offset) { ALuint source; @@ -1277,7 +1276,7 @@ namespace MWSound return true; } - void OpenAL_Output::finishSound(Sound* sound) + void OpenALOutput::finishSound(Sound* sound) { if (!sound->mHandle) return; @@ -1294,7 +1293,7 @@ namespace MWSound mActiveSounds.erase(std::find(mActiveSounds.begin(), mActiveSounds.end(), sound)); } - bool OpenAL_Output::isSoundPlaying(Sound* sound) + bool OpenALOutput::isSoundPlaying(Sound* sound) { if (!sound->mHandle) return false; @@ -1307,7 +1306,7 @@ namespace MWSound return state == AL_PLAYING || state == AL_PAUSED; } - void OpenAL_Output::updateSound(Sound* sound) + void OpenALOutput::updateSound(Sound* sound) { if (!sound->mHandle) return; @@ -1318,7 +1317,7 @@ namespace MWSound getALError(); } - bool OpenAL_Output::streamSound(DecoderPtr decoder, Stream* sound, bool getLoudnessData) + bool OpenALOutput::streamSound(DecoderPtr decoder, Stream* sound, bool getLoudnessData) { if (mFreeSources.empty()) { @@ -1349,7 +1348,7 @@ namespace MWSound return true; } - bool OpenAL_Output::streamSound3D(DecoderPtr decoder, Stream* sound, bool getLoudnessData) + bool OpenALOutput::streamSound3D(DecoderPtr decoder, Stream* sound, bool getLoudnessData) { if (mFreeSources.empty()) { @@ -1380,7 +1379,7 @@ namespace MWSound return true; } - void OpenAL_Output::finishStream(Stream* sound) + void OpenALOutput::finishStream(Stream* sound) { if (!sound->mHandle) return; @@ -1402,7 +1401,7 @@ namespace MWSound delete stream; } - double OpenAL_Output::getStreamDelay(Stream* sound) + double OpenALOutput::getStreamDelay(Stream* sound) { if (!sound->mHandle) return 0.0; @@ -1410,7 +1409,7 @@ namespace MWSound return stream->getStreamDelay(); } - double OpenAL_Output::getStreamOffset(Stream* sound) + double OpenALOutput::getStreamOffset(Stream* sound) { if (!sound->mHandle) return 0.0; @@ -1419,7 +1418,7 @@ namespace MWSound return stream->getStreamOffset(); } - float OpenAL_Output::getStreamLoudness(Stream* sound) + float OpenALOutput::getStreamLoudness(Stream* sound) { if (!sound->mHandle) return 0.0; @@ -1428,7 +1427,7 @@ namespace MWSound return stream->getCurrentLoudness(); } - bool OpenAL_Output::isStreamPlaying(Stream* sound) + bool OpenALOutput::isStreamPlaying(Stream* sound) { if (!sound->mHandle) return false; @@ -1437,7 +1436,7 @@ namespace MWSound return stream->isPlaying(); } - void OpenAL_Output::updateStream(Stream* sound) + void OpenALOutput::updateStream(Stream* sound) { if (!sound->mHandle) return; @@ -1449,17 +1448,17 @@ namespace MWSound getALError(); } - void OpenAL_Output::startUpdate() + void OpenALOutput::startUpdate() { alcSuspendContext(alcGetCurrentContext()); } - void OpenAL_Output::finishUpdate() + void OpenALOutput::finishUpdate() { alcProcessContext(alcGetCurrentContext()); } - void OpenAL_Output::updateListener( + void OpenALOutput::updateListener( const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env) { if (mContext) @@ -1501,7 +1500,7 @@ namespace MWSound mListenerEnv = env; } - void OpenAL_Output::pauseSounds(int types) + void OpenALOutput::pauseSounds(int types) { std::vector sources; for (Sound* sound : mActiveSounds) @@ -1524,7 +1523,7 @@ namespace MWSound } } - void OpenAL_Output::pauseActiveDevice() + void OpenALOutput::pauseActiveDevice() { if (mDevice == nullptr) return; @@ -1540,7 +1539,7 @@ namespace MWSound alListenerf(AL_GAIN, 0.0f); } - void OpenAL_Output::resumeActiveDevice() + void OpenALOutput::resumeActiveDevice() { if (mDevice == nullptr) return; @@ -1556,7 +1555,7 @@ namespace MWSound alListenerf(AL_GAIN, 1.0f); } - void OpenAL_Output::resumeSounds(int types) + void OpenALOutput::resumeSounds(int types) { std::vector sources; for (Sound* sound : mActiveSounds) @@ -1579,8 +1578,8 @@ namespace MWSound } } - OpenAL_Output::OpenAL_Output(SoundManager& mgr) - : Sound_Output(mgr) + OpenALOutput::OpenALOutput(SoundManager& mgr) + : SoundOutput(mgr) , mDevice(nullptr) , mContext(nullptr) , mListenerPos(0.0f, 0.0f, 0.0f) @@ -1593,12 +1592,12 @@ namespace MWSound { } - OpenAL_Output::~OpenAL_Output() + OpenALOutput::~OpenALOutput() { - OpenAL_Output::deinit(); + OpenALOutput::deinit(); } - float OpenAL_Output::getTimeScaledPitch(SoundBase* sound) + float OpenALOutput::getTimeScaledPitch(SoundBase* sound) { const bool shouldScale = !(sound->mParams.mFlags & PlayMode::NoScaling); return shouldScale ? sound->getPitch() * mManager.getSimulationTimeScale() : sound->getPitch(); diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openaloutput.hpp similarity index 91% rename from apps/openmw/mwsound/openal_output.hpp rename to apps/openmw/mwsound/openaloutput.hpp index b419038eab..4e96dd1627 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openaloutput.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_SOUND_OPENAL_OUTPUT_H -#define GAME_SOUND_OPENAL_OUTPUT_H +#ifndef GAME_SOUND_OPENALOUTPUT_H +#define GAME_SOUND_OPENALOUTPUT_H #include #include @@ -13,7 +13,7 @@ #include "alc.h" #include "alext.h" -#include "sound_output.hpp" +#include "soundoutput.hpp" namespace MWSound { @@ -22,7 +22,7 @@ namespace MWSound class Sound; class Stream; - class OpenAL_Output : public Sound_Output + class OpenALOutput : public SoundOutput { ALCdevice* mDevice; ALCcontext* mContext; @@ -72,8 +72,8 @@ namespace MWSound float getTimeScaledPitch(SoundBase* sound); - OpenAL_Output& operator=(const OpenAL_Output& rhs); - OpenAL_Output(const OpenAL_Output& rhs); + OpenALOutput& operator=(const OpenALOutput& rhs); + OpenALOutput(const OpenALOutput& rhs); static void eventCallback( ALenum eventType, ALuint object, ALuint param, ALsizei length, const ALchar* message, void* userParam); @@ -117,8 +117,8 @@ namespace MWSound void pauseActiveDevice() override; void resumeActiveDevice() override; - OpenAL_Output(SoundManager& mgr); - virtual ~OpenAL_Output(); + OpenALOutput(SoundManager& mgr); + virtual ~OpenALOutput(); }; } diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 48e8975340..5160b2934f 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -3,7 +3,7 @@ #include -#include "sound_output.hpp" +#include "soundoutput.hpp" namespace MWSound { @@ -53,7 +53,7 @@ namespace MWSound protected: Sound_Instance mHandle = nullptr; - friend class OpenAL_Output; + friend class OpenALOutput; public: void setPosition(const osg::Vec3f& pos) { mParams.mPos = pos; } diff --git a/apps/openmw/mwsound/sound_buffer.cpp b/apps/openmw/mwsound/soundbuffer.cpp similarity index 85% rename from apps/openmw/mwsound/sound_buffer.cpp rename to apps/openmw/mwsound/soundbuffer.cpp index f28b268df2..722d89f0eb 100644 --- a/apps/openmw/mwsound/sound_buffer.cpp +++ b/apps/openmw/mwsound/soundbuffer.cpp @@ -1,4 +1,4 @@ -#include "sound_buffer.hpp" +#include "soundbuffer.hpp" #include "../mwbase/environment.hpp" #include "../mwworld/esmstore.hpp" @@ -35,7 +35,7 @@ namespace MWSound } } - SoundBufferPool::SoundBufferPool(Sound_Output& output) + SoundBufferPool::SoundBufferPool(SoundOutput& output) : mOutput(&output) , mBufferCacheMax(Settings::sound().mBufferCacheMax * 1024 * 1024) , mBufferCacheMin( @@ -48,31 +48,31 @@ namespace MWSound clear(); } - Sound_Buffer* SoundBufferPool::lookup(const ESM::RefId& soundId) const + SoundBuffer* SoundBufferPool::lookup(const ESM::RefId& soundId) const { const auto it = mBufferNameMap.find(soundId); if (it != mBufferNameMap.end()) { - Sound_Buffer* sfx = it->second; + SoundBuffer* sfx = it->second; if (sfx->getHandle() != nullptr) return sfx; } return nullptr; } - Sound_Buffer* SoundBufferPool::lookup(std::string_view fileName) const + SoundBuffer* SoundBufferPool::lookup(std::string_view fileName) const { const auto it = mBufferFileNameMap.find(std::string(fileName)); if (it != mBufferFileNameMap.end()) { - Sound_Buffer* sfx = it->second; + SoundBuffer* sfx = it->second; if (sfx->getHandle() != nullptr) return sfx; } return nullptr; } - Sound_Buffer* SoundBufferPool::loadSfx(Sound_Buffer* sfx) + SoundBuffer* SoundBufferPool::loadSfx(SoundBuffer* sfx) { if (sfx->getHandle() != nullptr) return sfx; @@ -95,7 +95,7 @@ namespace MWSound return sfx; } - Sound_Buffer* SoundBufferPool::load(const ESM::RefId& soundId) + SoundBuffer* SoundBufferPool::load(const ESM::RefId& soundId) { if (mBufferNameMap.empty()) { @@ -103,7 +103,7 @@ namespace MWSound insertSound(sound.mId, sound); } - Sound_Buffer* sfx; + SoundBuffer* sfx; const auto it = mBufferNameMap.find(soundId); if (it != mBufferNameMap.end()) sfx = it->second; @@ -118,9 +118,9 @@ namespace MWSound return loadSfx(sfx); } - Sound_Buffer* SoundBufferPool::load(std::string_view fileName) + SoundBuffer* SoundBufferPool::load(std::string_view fileName) { - Sound_Buffer* sfx; + SoundBuffer* sfx; const auto it = mBufferFileNameMap.find(std::string(fileName)); if (it != mBufferFileNameMap.end()) sfx = it->second; @@ -146,7 +146,7 @@ namespace MWSound mUnusedBuffers.clear(); } - Sound_Buffer* SoundBufferPool::insertSound(std::string_view fileName) + SoundBuffer* SoundBufferPool::insertSound(std::string_view fileName) { static const AudioParams audioParams = makeAudioParams(MWBase::Environment::get().getESMStore()->get()); @@ -158,13 +158,13 @@ namespace MWSound min = std::max(min, 1.0f); max = std::max(min, max); - Sound_Buffer& sfx = mSoundBuffers.emplace_back(fileName, volume, min, max); + SoundBuffer& sfx = mSoundBuffers.emplace_back(fileName, volume, min, max); mBufferFileNameMap.emplace(fileName, &sfx); return &sfx; } - Sound_Buffer* SoundBufferPool::insertSound(const ESM::RefId& soundId, const ESM::Sound& sound) + SoundBuffer* SoundBufferPool::insertSound(const ESM::RefId& soundId, const ESM::Sound& sound) { static const AudioParams audioParams = makeAudioParams(MWBase::Environment::get().getESMStore()->get()); @@ -183,7 +183,7 @@ namespace MWSound min = std::max(min, 1.0f); max = std::max(min, max); - Sound_Buffer& sfx = mSoundBuffers.emplace_back( + SoundBuffer& sfx = mSoundBuffers.emplace_back( Misc::ResourceHelpers::correctSoundPath(VFS::Path::Normalized(sound.mSound)), volume, min, max); mBufferNameMap.emplace(soundId, &sfx); @@ -194,7 +194,7 @@ namespace MWSound { while (!mUnusedBuffers.empty() && mBufferCacheSize > mBufferCacheMin) { - Sound_Buffer* const unused = mUnusedBuffers.back(); + SoundBuffer* const unused = mUnusedBuffers.back(); mBufferCacheSize -= mOutput->unloadSound(unused->getHandle()); unused->mHandle = nullptr; diff --git a/apps/openmw/mwsound/sound_buffer.hpp b/apps/openmw/mwsound/soundbuffer.hpp similarity index 68% rename from apps/openmw/mwsound/sound_buffer.hpp rename to apps/openmw/mwsound/soundbuffer.hpp index 7de6dab9ae..f7e7639b2d 100644 --- a/apps/openmw/mwsound/sound_buffer.hpp +++ b/apps/openmw/mwsound/soundbuffer.hpp @@ -1,14 +1,15 @@ -#ifndef GAME_SOUND_SOUND_BUFFER_H -#define GAME_SOUND_SOUND_BUFFER_H +#ifndef GAME_SOUND_SOUNDBUFFER_H +#define GAME_SOUND_SOUNDBUFFER_H #include #include #include #include -#include "sound_output.hpp" #include +#include "soundoutput.hpp" + namespace ESM { struct Sound; @@ -23,11 +24,11 @@ namespace MWSound { class SoundBufferPool; - class Sound_Buffer + class SoundBuffer { public: template - Sound_Buffer(T&& resname, float volume, float mindist, float maxdist) + SoundBuffer(T&& resname, float volume, float mindist, float maxdist) : mResourceName(std::forward(resname)) , mVolume(volume) , mMinDist(mindist) @@ -59,7 +60,7 @@ namespace MWSound class SoundBufferPool { public: - SoundBufferPool(Sound_Output& output); + SoundBufferPool(SoundOutput& output); SoundBufferPool(const SoundBufferPool&) = delete; @@ -67,20 +68,20 @@ namespace MWSound /// Lookup a soundId for its sound data (resource name, local volume, /// minRange, and maxRange) - Sound_Buffer* lookup(const ESM::RefId& soundId) const; + SoundBuffer* lookup(const ESM::RefId& soundId) const; /// Lookup a sound by file name for its sound data (resource name, local volume, /// minRange, and maxRange) - Sound_Buffer* lookup(std::string_view fileName) const; + SoundBuffer* lookup(std::string_view fileName) const; /// Lookup a soundId for its sound data (resource name, local volume, /// minRange, and maxRange), and ensure it's ready for use. - Sound_Buffer* load(const ESM::RefId& soundId); + SoundBuffer* load(const ESM::RefId& soundId); // Lookup for a sound by file name, and ensure it's ready for use. - Sound_Buffer* load(std::string_view fileName); + SoundBuffer* load(std::string_view fileName); - void use(Sound_Buffer& sfx) + void use(SoundBuffer& sfx) { if (sfx.mUses++ == 0) { @@ -90,7 +91,7 @@ namespace MWSound } } - void release(Sound_Buffer& sfx) + void release(SoundBuffer& sfx) { if (--sfx.mUses == 0) mUnusedBuffers.push_front(&sfx); @@ -99,23 +100,23 @@ namespace MWSound void clear(); private: - Sound_Buffer* loadSfx(Sound_Buffer* sfx); + SoundBuffer* loadSfx(SoundBuffer* sfx); - Sound_Output* mOutput; - std::deque mSoundBuffers; - std::unordered_map mBufferNameMap; - std::unordered_map mBufferFileNameMap; + SoundOutput* mOutput; + std::deque mSoundBuffers; + std::unordered_map mBufferNameMap; + std::unordered_map mBufferFileNameMap; std::size_t mBufferCacheMax; std::size_t mBufferCacheMin; std::size_t mBufferCacheSize = 0; // NOTE: unused buffers are stored in front-newest order. - std::deque mUnusedBuffers; + std::deque mUnusedBuffers; - inline Sound_Buffer* insertSound(const ESM::RefId& soundId, const ESM::Sound& sound); - inline Sound_Buffer* insertSound(std::string_view fileName); + inline SoundBuffer* insertSound(const ESM::RefId& soundId, const ESM::Sound& sound); + inline SoundBuffer* insertSound(std::string_view fileName); inline void unloadUnused(); }; } -#endif /* GAME_SOUND_SOUND_BUFFER_H */ +#endif /* GAME_SOUND_SOUNDBUFFER_H */ diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sounddecoder.hpp similarity index 80% rename from apps/openmw/mwsound/sound_decoder.hpp rename to apps/openmw/mwsound/sounddecoder.hpp index 17f9d28909..675fad4197 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sounddecoder.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_SOUND_SOUND_DECODER_H -#define GAME_SOUND_SOUND_DECODER_H +#ifndef GAME_SOUND_SOUNDDECODER_H +#define GAME_SOUND_SOUNDDECODER_H #include @@ -34,7 +34,7 @@ namespace MWSound size_t framesToBytes(size_t frames, ChannelConfig config, SampleType type); size_t bytesToFrames(size_t bytes, ChannelConfig config, SampleType type); - struct Sound_Decoder + struct SoundDecoder { const VFS::Manager* mResourceMgr; @@ -48,15 +48,15 @@ namespace MWSound virtual void readAll(std::vector& output); virtual size_t getSampleOffset() = 0; - Sound_Decoder(const VFS::Manager* resourceMgr) + SoundDecoder(const VFS::Manager* resourceMgr) : mResourceMgr(resourceMgr) { } - virtual ~Sound_Decoder() {} + virtual ~SoundDecoder() {} private: - Sound_Decoder(const Sound_Decoder& rhs); - Sound_Decoder& operator=(const Sound_Decoder& rhs); + SoundDecoder(const SoundDecoder& rhs); + SoundDecoder& operator=(const SoundDecoder& rhs); }; } diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 1d9a6d457c..66bdfbdbfa 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -26,12 +26,12 @@ #include "../mwmechanics/actorutil.hpp" #include "constants.hpp" -#include "ffmpeg_decoder.hpp" -#include "openal_output.hpp" +#include "ffmpegdecoder.hpp" +#include "openaloutput.hpp" #include "sound.hpp" -#include "sound_buffer.hpp" -#include "sound_decoder.hpp" -#include "sound_output.hpp" +#include "soundbuffer.hpp" +#include "sounddecoder.hpp" +#include "soundoutput.hpp" namespace MWSound { @@ -57,7 +57,7 @@ namespace MWSound return settings; } - float initialFadeVolume(float squaredDist, Sound_Buffer* sfx, Type type, PlayMode mode) + float initialFadeVolume(float squaredDist, SoundBuffer* sfx, Type type, PlayMode mode) { // If a sound is farther away than its maximum distance, start playing it with a zero fade volume. // It can still become audible once the player moves closer. @@ -111,7 +111,7 @@ namespace MWSound SoundManager::SoundManager(const VFS::Manager* vfs, bool useSound) : mVFS(vfs) - , mOutput(std::make_unique(*this)) + , mOutput(std::make_unique(*this)) , mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mSoundBuffers(*mOutput) , mMusicType(MWSound::MusicType::Normal) @@ -169,7 +169,7 @@ namespace MWSound // Return a new decoder instance, used as needed by the output implementations DecoderPtr SoundManager::getDecoder() { - return std::make_shared(mVFS); + return std::make_shared(mVFS); } DecoderPtr SoundManager::loadVoice(VFS::Path::NormalizedView voicefile) @@ -459,7 +459,7 @@ namespace MWSound return false; } - Sound* SoundManager::playSound(Sound_Buffer* sfx, float volume, float pitch, Type type, PlayMode mode, float offset) + Sound* SoundManager::playSound(SoundBuffer* sfx, float volume, float pitch, Type type, PlayMode mode, float offset) { if (!mOutput->isInitialized()) return nullptr; @@ -495,7 +495,7 @@ namespace MWSound if (!mVFS->exists(normalizedName)) return nullptr; - Sound_Buffer* sfx = mSoundBuffers.load(normalizedName); + SoundBuffer* sfx = mSoundBuffers.load(normalizedName); if (!sfx) return nullptr; @@ -508,14 +508,14 @@ namespace MWSound if (!mOutput->isInitialized()) return nullptr; - Sound_Buffer* sfx = mSoundBuffers.load(soundId); + SoundBuffer* sfx = mSoundBuffers.load(soundId); if (!sfx) return nullptr; return playSound(sfx, volume, pitch, type, mode, offset); } - Sound* SoundManager::playSound3D(const MWWorld::ConstPtr& ptr, Sound_Buffer* sfx, float volume, float pitch, + Sound* SoundManager::playSound3D(const MWWorld::ConstPtr& ptr, SoundBuffer* sfx, float volume, float pitch, Type type, PlayMode mode, float offset) { if (!mOutput->isInitialized()) @@ -576,7 +576,7 @@ namespace MWSound return nullptr; // Look up the sound in the ESM data - Sound_Buffer* sfx = mSoundBuffers.load(soundId); + SoundBuffer* sfx = mSoundBuffers.load(soundId); if (!sfx) return nullptr; @@ -594,7 +594,7 @@ namespace MWSound if (!mVFS->exists(normalizedName)) return nullptr; - Sound_Buffer* sfx = mSoundBuffers.load(normalizedName); + SoundBuffer* sfx = mSoundBuffers.load(normalizedName); if (!sfx) return nullptr; @@ -608,7 +608,7 @@ namespace MWSound return nullptr; // Look up the sound in the ESM data - Sound_Buffer* sfx = mSoundBuffers.load(soundId); + SoundBuffer* sfx = mSoundBuffers.load(soundId); if (!sfx) return nullptr; @@ -642,7 +642,7 @@ namespace MWSound mOutput->finishSound(sound); } - void SoundManager::stopSound(Sound_Buffer* sfx, const MWWorld::ConstPtr& ptr) + void SoundManager::stopSound(SoundBuffer* sfx, const MWWorld::ConstPtr& ptr) { SoundMap::iterator snditer = mActiveSounds.find(ptr.mRef); if (snditer != mActiveSounds.end()) @@ -660,7 +660,7 @@ namespace MWSound if (!mOutput->isInitialized()) return; - Sound_Buffer* sfx = mSoundBuffers.lookup(soundId); + SoundBuffer* sfx = mSoundBuffers.lookup(soundId); if (!sfx) return; @@ -673,7 +673,7 @@ namespace MWSound return; std::string normalizedName = VFS::Path::normalizeFilename(fileName); - Sound_Buffer* sfx = mSoundBuffers.lookup(normalizedName); + SoundBuffer* sfx = mSoundBuffers.lookup(normalizedName); if (!sfx) return; @@ -725,7 +725,7 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(ptr.mRef); if (snditer != mActiveSounds.end()) { - Sound_Buffer* sfx = mSoundBuffers.lookup(soundId); + SoundBuffer* sfx = mSoundBuffers.lookup(soundId); if (sfx == nullptr) return; for (SoundBufferRefPair& sndbuf : snditer->second.mList) @@ -743,7 +743,7 @@ namespace MWSound SoundMap::const_iterator snditer = mActiveSounds.find(ptr.mRef); if (snditer != mActiveSounds.end()) { - Sound_Buffer* sfx = mSoundBuffers.lookup(normalizedName); + SoundBuffer* sfx = mSoundBuffers.lookup(normalizedName); if (!sfx) return false; @@ -761,7 +761,7 @@ namespace MWSound SoundMap::const_iterator snditer = mActiveSounds.find(ptr.mRef); if (snditer != mActiveSounds.end()) { - Sound_Buffer* sfx = mSoundBuffers.lookup(soundId); + SoundBuffer* sfx = mSoundBuffers.lookup(soundId); if (!sfx) return false; @@ -846,7 +846,7 @@ namespace MWSound const auto update = mWaterSoundUpdater.update(player, *world); WaterSoundAction action; - Sound_Buffer* sfx; + SoundBuffer* sfx; std::tie(action, sfx) = getWaterSoundAction(update, curcell); switch (action) @@ -870,7 +870,7 @@ namespace MWSound mLastCell = curcell; } - std::pair SoundManager::getWaterSoundAction( + std::pair SoundManager::getWaterSoundAction( const WaterSoundUpdate& update, const MWWorld::Cell* cell) const { if (mNearWaterSound) @@ -880,7 +880,7 @@ namespace MWSound bool soundIdChanged = false; - Sound_Buffer* sfx = mSoundBuffers.lookup(update.mId); + SoundBuffer* sfx = mSoundBuffers.lookup(update.mId); if (mLastCell != cell) { const auto snditer = mActiveSounds.find(nullptr); @@ -1168,7 +1168,7 @@ namespace MWSound // Default readAll implementation, for decoders that can't do anything // better - void Sound_Decoder::readAll(std::vector& output) + void SoundDecoder::readAll(std::vector& output) { size_t total = output.size(); size_t got; diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index a5e5b2c45f..8fc7e6701f 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -15,7 +15,7 @@ #include "../mwbase/soundmanager.hpp" #include "regionsoundselector.hpp" -#include "sound_buffer.hpp" +#include "soundbuffer.hpp" #include "type.hpp" #include "watersoundupdater.hpp" @@ -37,8 +37,8 @@ namespace MWWorld namespace MWSound { - class Sound_Output; - struct Sound_Decoder; + class SoundOutput; + struct SoundDecoder; class SoundBase; class Sound; class Stream; @@ -50,7 +50,7 @@ namespace MWSound { const VFS::Manager* mVFS; - std::unique_ptr mOutput; + std::unique_ptr mOutput; WaterSoundUpdater mWaterSoundUpdater; @@ -60,7 +60,7 @@ namespace MWSound Misc::ObjectPool mStreams; - typedef std::pair SoundBufferRefPair; + typedef std::pair SoundBufferRefPair; typedef std::vector SoundBufferRefPairList; struct ActiveSound @@ -109,7 +109,7 @@ namespace MWSound Sound* mCurrentRegionSound; - Sound_Buffer* insertSound(const std::string& soundId, const ESM::Sound* sound); + SoundBuffer* insertSound(const std::string& soundId, const ESM::Sound* sound); // returns a decoder to start streaming, or nullptr if the sound was not found DecoderPtr loadVoice(VFS::Path::NormalizedView voicefile); @@ -126,9 +126,9 @@ namespace MWSound bool remove3DSoundAtDistance(PlayMode mode, const MWWorld::ConstPtr& ptr) const; - Sound* playSound(Sound_Buffer* sfx, float volume, float pitch, Type type = Type::Sfx, + Sound* playSound(SoundBuffer* sfx, float volume, float pitch, Type type = Type::Sfx, PlayMode mode = PlayMode::Normal, float offset = 0); - Sound* playSound3D(const MWWorld::ConstPtr& ptr, Sound_Buffer* sfx, float volume, float pitch, Type type, + Sound* playSound3D(const MWWorld::ConstPtr& ptr, SoundBuffer* sfx, float volume, float pitch, Type type, PlayMode mode, float offset); void updateSounds(float duration); @@ -144,7 +144,7 @@ namespace MWSound PlaySound, }; - std::pair getWaterSoundAction( + std::pair getWaterSoundAction( const WaterSoundUpdate& update, const MWWorld::Cell* cell) const; SoundManager(const SoundManager& rhs); @@ -152,9 +152,9 @@ namespace MWSound protected: DecoderPtr getDecoder(); - friend class OpenAL_Output; + friend class OpenALOutput; - void stopSound(Sound_Buffer* sfx, const MWWorld::ConstPtr& ptr); + void stopSound(SoundBuffer* sfx, const MWWorld::ConstPtr& ptr); ///< Stop the given object from playing given sound buffer. public: diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/soundoutput.hpp similarity index 88% rename from apps/openmw/mwsound/sound_output.hpp rename to apps/openmw/mwsound/soundoutput.hpp index 5a77124985..e5c266b204 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/soundoutput.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_SOUND_SOUND_OUTPUT_H -#define GAME_SOUND_SOUND_OUTPUT_H +#ifndef GAME_SOUND_SOUNDOUTPUT_H +#define GAME_SOUND_SOUNDOUTPUT_H #include #include @@ -13,7 +13,7 @@ namespace MWSound { class SoundManager; - struct Sound_Decoder; + struct SoundDecoder; class Sound; class Stream; @@ -30,7 +30,7 @@ namespace MWSound using HrtfMode = Settings::HrtfMode; - class Sound_Output + class SoundOutput { SoundManager& mManager; @@ -71,24 +71,24 @@ namespace MWSound virtual void pauseActiveDevice() = 0; virtual void resumeActiveDevice() = 0; - Sound_Output& operator=(const Sound_Output& rhs); - Sound_Output(const Sound_Output& rhs); + SoundOutput& operator=(const SoundOutput& rhs); + SoundOutput(const SoundOutput& rhs); protected: bool mInitialized; - Sound_Output(SoundManager& mgr) + SoundOutput(SoundManager& mgr) : mManager(mgr) , mInitialized(false) { } public: - virtual ~Sound_Output() {} + virtual ~SoundOutput() {} bool isInitialized() const { return mInitialized; } - friend class OpenAL_Output; + friend class OpenALOutput; friend class SoundManager; friend class SoundBufferPool; }; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index b997d124c8..498d2ab25a 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -660,11 +660,13 @@ void MWState::StateManager::loadGame(const Character* character, const std::file // Report the last version still capable of reading this save if (e.getFormatVersion() <= ESM::OpenMW0_48SaveGameFormatVersion) release = "OpenMW 0.48.0"; + else if (e.getFormatVersion() <= ESM::OpenMW0_49SaveGameFormatVersion) + release = "OpenMW 0.49.0"; else { // Insert additional else if statements above to cover future releases - static_assert(ESM::MinSupportedSaveGameFormatVersion <= ESM::OpenMW0_49SaveGameFormatVersion); - release = "OpenMW 0.49.0"; + static_assert(ESM::MinSupportedSaveGameFormatVersion <= ESM::OpenMW0_50SaveGameFormatVersion); + release = "OpenMW 0.50.0"; } auto l10n = MWBase::Environment::get().getL10nManager()->getContext("OMWEngine"); std::string error = l10n->formatMessage("LoadingRequiresOldVersionError", { "version" }, { release }); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index fb3aee958c..478bdb5bb8 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -375,7 +375,6 @@ namespace MWWorld if (object->getShapeInstance()->mVisualCollisionType == Resource::VisualCollisionType::None) mNavigator.removeObject(DetourNavigator::ObjectId(object), navigatorUpdateGuard); mPhysics->remove(ptr); - ptr.mRef->mData.mPhysicsPostponed = false; } else if (mPhysics->getActor(ptr)) { @@ -383,6 +382,8 @@ namespace MWWorld mRendering.removeActorPath(ptr); mPhysics->remove(ptr); } + else + ptr.mRef->mData.mPhysicsPostponed = false; MWBase::Environment::get().getLuaManager()->objectRemovedFromScene(ptr); } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 4f6f52a81a..2ee77458d4 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -352,6 +352,30 @@ namespace MWWorld mWeather = 0; } + MoonModel::MoonModel(float fadeInStart, float fadeInFinish, float fadeOutStart, float fadeOutFinish, + float axisOffset, float speed, float dailyIncrement, float fadeStartAngle, float fadeEndAngle, + float moonShadowEarlyFadeAngle) + { + mFadeInStart = fadeInStart; + mFadeInFinish = fadeInFinish; + mFadeOutStart = fadeOutStart; + mFadeOutFinish = fadeOutFinish; + mAxisOffset = axisOffset; + mDailyIncrement = dailyIncrement; + mFadeStartAngle = fadeStartAngle; + mFadeEndAngle = fadeEndAngle; + mMoonShadowEarlyFadeAngle = moonShadowEarlyFadeAngle; + + // Morrowind appears to have a minimum speed to avoid situations where the moon can't + // complete a full rotation in a single 24-hour period. The reverse-engineered formula is + // 180 degrees (full hemisphere) / 23 hours / 15 degrees (1 hour travel at speed 1.0). + mSpeed = std::max(speed, (180.0f / 23.0f / 15.0f)); + + // Morrowind appears to reduce mDailyIncrement with modulo 24.0f to avoid situations where + // the moon would increment more than an entire rotation in a single day. + mDailyIncrement = std::fmod(mDailyIncrement, 24.0f); + } + MoonModel::MoonModel(const std::string& name) : mFadeInStart(Fallback::Map::getFloat("Moons_" + name + "_Fade_In_Start")) , mFadeInFinish(Fallback::Map::getFloat("Moons_" + name + "_Fade_In_Finish")) @@ -364,14 +388,19 @@ namespace MWWorld , mFadeEndAngle(Fallback::Map::getFloat("Moons_" + name + "_Fade_End_Angle")) , mMoonShadowEarlyFadeAngle(Fallback::Map::getFloat("Moons_" + name + "_Moon_Shadow_Early_Fade_Angle")) { - // Morrowind appears to have a minimum speed in order to avoid situations where the moon couldn't conceivably - // complete a rotation in a single 24 hour period. The value of 180/23 was deduced from reverse engineering. - mSpeed = std::min(mSpeed, 180.0f / 23.0f); + // Morrowind appears to have a minimum speed to avoid situations where the moon can't + // complete a full rotation in a single 24-hour period. The reverse-engineered formula is + // 180 degrees (full hemisphere) / 23 hours / 15 degrees (1 hour travel at speed 1.0). + mSpeed = std::max(mSpeed, (180.0f / 23.0f / 15.0f)); + + // Morrowind appears to reduce mDailyIncrement with modulo 24.0f to avoid situations where + // the moon would increment more than an entire rotation in a single day. + mDailyIncrement = std::fmod(mDailyIncrement, 24.0f); } MWRender::MoonState MoonModel::calculateState(const TimeStamp& gameTime) const { - float rotationFromHorizon = angle(gameTime); + float rotationFromHorizon = angle(gameTime.getDay(), gameTime.getHour()); MWRender::MoonState state = { rotationFromHorizon, mAxisOffset, // Reverse engineered from Morrowind's scene graph rotation matrices. phase(gameTime), shadowBlend(rotationFromHorizon), @@ -380,7 +409,7 @@ namespace MWWorld return state; } - inline float MoonModel::angle(const TimeStamp& gameTime) const + inline float MoonModel::angle(int gameDay, float gameHour) const { // Morrowind's moons start travel on one side of the horizon (let's call it H-rise) and travel 180 degrees to // the opposite horizon (let's call it H-set). Upon reaching H-set, they reset to H-rise until the next moon @@ -390,49 +419,83 @@ namespace MWWorld // 1. Moon rises and then sets in one day. // 2. Moon sets and doesn't rise in one day (occurs when the moon rise hour is >= 24). // 3. Moon sets and then rises in one day. - float moonRiseHourToday = moonRiseHour(gameTime.getDay()); - float moonRiseAngleToday = 0; + float moonRiseHourToday = moonRiseHour(gameDay); + float moonRiseAngleToday = 0.0f; - if (gameTime.getHour() < moonRiseHourToday) + if (gameHour < moonRiseHourToday) { - float moonRiseHourYesterday = moonRiseHour(gameTime.getDay() - 1); - if (moonRiseHourYesterday < 24) + // Rise hour increases by mDailyIncrement each day, so yesterday's is easy to calculate + float moonRiseHourYesterday = moonRiseHourToday - mDailyIncrement; + if (moonRiseHourYesterday < 24.0f) { - float moonRiseAngleYesterday = rotation(24 - moonRiseHourYesterday); - if (moonRiseAngleYesterday < 180) + // Morrowind offsets the increment by -1 when the previous day's visible point crosses into the next + // day. The offset lasts from this point until the next 24-day loop starts. To find this point we add + // mDailyIncrement to the previous visible point and check the result. + float moonShadowEarlyFadeAngle1 = mFadeEndAngle - mMoonShadowEarlyFadeAngle; + float timeToVisible = moonShadowEarlyFadeAngle1 / rotation(1.0f); + float cycleOffset = moonRiseHourYesterday + timeToVisible > 24.0f ? mDailyIncrement : 0.0f; + + float moonRiseAngleYesterday = rotation(24.0f - (moonRiseHourYesterday + cycleOffset)); + if (moonRiseAngleYesterday < 180.0f) { // The moon rose but did not set yesterday, so accumulate yesterday's angle with how much we've // travelled today. - moonRiseAngleToday = rotation(gameTime.getHour()) + moonRiseAngleYesterday; + moonRiseAngleToday = rotation(gameHour) + moonRiseAngleYesterday; } } } else { - moonRiseAngleToday = rotation(gameTime.getHour() - moonRiseHourToday); + moonRiseAngleToday = rotation(gameHour - moonRiseHourToday); } - if (moonRiseAngleToday >= 180) + if (moonRiseAngleToday >= 180.0f) { // The moon set today, reset the angle to the horizon. - moonRiseAngleToday = 0; + moonRiseAngleToday = 0.0f; } return moonRiseAngleToday; } - inline float MoonModel::moonRiseHour(unsigned int daysPassed) const + inline float MoonModel::moonPhaseHour(int gameDay) const { + // Morrowind delays moon phase changes until one of these is true: + // * The moon is invisible at midnight. + // * The moon reached moonShadowEarlyFadeAngle2 one daily increment ago (therefore invisible). + if (!isVisible(gameDay, 0.0f)) + return 0.0f; + else + { + // Calculate the angle at which the moon becomes transparent and the starting angle. + float moonShadowEarlyFadeAngle2 = (180.0f - mFadeEndAngle) + mMoonShadowEarlyFadeAngle; + float midnightAngle = angle(gameDay, 0.0f); + + // We can assume that moonShadowEarlyFadeAngle2 > midnightAngle, because the opposite + // case would make the moon invisible at midnight, which is checked above. + return ((moonShadowEarlyFadeAngle2 - midnightAngle) / rotation(1.0f)) + std::max(mDailyIncrement, 0.0f); + } + } + + inline float MoonModel::moonRiseHour(int gameDay) const + { + if (mDailyIncrement == 0.0f) + return 0.0f; + // This arises from the start date of 16 Last Seed, 427 // TODO: Find an alternate formula that doesn't rely on this day being fixed. - static const unsigned int startDay = 16; + constexpr int startDay = 16; + + // This formula finds the number of missed increments necessary to make the rise hour a 24-day loop. + // The offset increases on the first day of the loop and is multiplied by the number of completed loops. + float incrementOffset = (24.0f - std::abs(24.0f / mDailyIncrement)) * std::floor((gameDay + startDay) / 24.0f); // This odd formula arises from the fact that on 16 Last Seed, 17 increments have occurred, meaning // that upon starting a new game, it must only calculate the moon phase as far back as 1 Last Seed. // Note that we don't modulo after adding the latest daily increment because other calculations need to // know if doing so would cause the moon rise to be postponed until the next day (which happens when // the moon rise hour is >= 24 in Morrowind). - return mDailyIncrement + std::fmod((daysPassed - 1 + startDay) * mDailyIncrement, 24.0f); + return mDailyIncrement + std::fmod((gameDay - 1 + startDay - incrementOffset) * mDailyIncrement, 24.0f); } inline float MoonModel::rotation(float hours) const @@ -449,12 +512,18 @@ namespace MWWorld // phase cycle. // If the moon didn't rise yet today, use yesterday's moon phase. - if (gameTime.getHour() < moonRiseHour(gameTime.getDay())) + if (gameTime.getHour() < moonPhaseHour(gameTime.getDay())) return static_cast((gameTime.getDay() / 3) % 8); else return static_cast(((gameTime.getDay() + 1) / 3) % 8); } + inline bool MoonModel::isVisible(int gameDay, float gameHour) const + { + // Moons are "visible" when their alpha value is non-zero. + return hourlyAlpha(gameHour) > 0.f && earlyMoonShadowAlpha(angle(gameDay, gameHour)) > 0.f; + } + inline float MoonModel::shadowBlend(float angle) const { // The Fade End Angle and Fade Start Angle describe a region where the moon transitions from a solid disk @@ -480,6 +549,10 @@ namespace MWWorld inline float MoonModel::hourlyAlpha(float gameHour) const { + // Morrowind culls the moon one minute before mFadeOutFinish + constexpr float oneMinute = 0.0167f; + float adjustedFadeOutFinish = mFadeOutFinish - oneMinute; + // The Fade Out Start / Finish and Fade In Start / Finish describe the hours at which the moon // appears and disappears. // Depending on the current hour, the following values describe how transparent the moon is. @@ -487,9 +560,9 @@ namespace MWWorld // 2. From Fade Out Finish to Fade In Start: 0 (transparent) // 3. From Fade In Start to Fade In Finish: 0..1 // 4. From Fade In Finish to Fade Out Start: 1 (solid) - if ((gameHour >= mFadeOutStart) && (gameHour < mFadeOutFinish)) - return (mFadeOutFinish - gameHour) / (mFadeOutFinish - mFadeOutStart); - else if ((gameHour >= mFadeOutFinish) && (gameHour < mFadeInStart)) + if ((gameHour >= mFadeOutStart) && (gameHour < adjustedFadeOutFinish)) + return (adjustedFadeOutFinish - gameHour) / (adjustedFadeOutFinish - mFadeOutStart); + else if ((gameHour >= adjustedFadeOutFinish) && (gameHour < mFadeInStart)) return 0.0f; else if ((gameHour >= mFadeInStart) && (gameHour < mFadeInFinish)) return (gameHour - mFadeInStart) / (mFadeInFinish - mFadeInStart); diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 0643240dcd..7c27a10316 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -251,6 +251,9 @@ namespace MWWorld { public: MoonModel(const std::string& name); + MoonModel(float fadeInStart, float fadeInFinish, float fadeOutStart, float fadeOutFinish, float axisOffset, + float speed, float dailyIncrement, float fadeStartAngle, float fadeEndAngle, + float moonShadowEarlyFadeAngle); MWRender::MoonState calculateState(const TimeStamp& gameTime) const; @@ -266,10 +269,12 @@ namespace MWWorld float mFadeEndAngle; float mMoonShadowEarlyFadeAngle; - float angle(const TimeStamp& gameTime) const; - float moonRiseHour(unsigned int daysPassed) const; + float angle(int gameDay, float gameHour) const; + float moonPhaseHour(int gameDay) const; + float moonRiseHour(int gameDay) const; float rotation(float hours) const; MWRender::MoonState::Phase phase(const TimeStamp& gameTime) const; + bool isVisible(int gameDay, float gameHour) const; float shadowBlend(float angle) const; float hourlyAlpha(float gameHour) const; float earlyMoonShadowAlpha(float angle) const; diff --git a/apps/openmw_tests/CMakeLists.txt b/apps/openmw_tests/CMakeLists.txt index 9b57113110..adfce32537 100644 --- a/apps/openmw_tests/CMakeLists.txt +++ b/apps/openmw_tests/CMakeLists.txt @@ -6,14 +6,15 @@ file(GLOB UNITTEST_SRC_FILES options.cpp - mwworld/test_store.cpp + mwworld/teststore.cpp mwworld/testduration.cpp mwworld/testtimestamp.cpp mwworld/testptr.cpp + mwworld/testweather.cpp - mwdialogue/test_keywordsearch.cpp + mwdialogue/testkeywordsearch.cpp - mwscript/test_scripts.cpp + mwscript/testscripts.cpp ) source_group(apps\\openmw-tests FILES ${UNITTEST_SRC_FILES}) diff --git a/apps/openmw_tests/mwdialogue/test_keywordsearch.cpp b/apps/openmw_tests/mwdialogue/testkeywordsearch.cpp similarity index 100% rename from apps/openmw_tests/mwdialogue/test_keywordsearch.cpp rename to apps/openmw_tests/mwdialogue/testkeywordsearch.cpp diff --git a/apps/openmw_tests/mwscript/test_scripts.cpp b/apps/openmw_tests/mwscript/testscripts.cpp similarity index 99% rename from apps/openmw_tests/mwscript/test_scripts.cpp rename to apps/openmw_tests/mwscript/testscripts.cpp index 0de542bdc6..b9e422daed 100644 --- a/apps/openmw_tests/mwscript/test_scripts.cpp +++ b/apps/openmw_tests/mwscript/testscripts.cpp @@ -1,7 +1,7 @@ #include #include -#include "test_utils.hpp" +#include "testutils.hpp" namespace { @@ -935,4 +935,4 @@ End)mwscript"; registerExtensions(); EXPECT_FALSE(!compile(sIssue6807)); } -} \ No newline at end of file +} diff --git a/apps/openmw_tests/mwscript/test_utils.hpp b/apps/openmw_tests/mwscript/testutils.hpp similarity index 100% rename from apps/openmw_tests/mwscript/test_utils.hpp rename to apps/openmw_tests/mwscript/testutils.hpp diff --git a/apps/openmw_tests/mwworld/test_store.cpp b/apps/openmw_tests/mwworld/teststore.cpp similarity index 100% rename from apps/openmw_tests/mwworld/test_store.cpp rename to apps/openmw_tests/mwworld/teststore.cpp diff --git a/apps/openmw_tests/mwworld/testweather.cpp b/apps/openmw_tests/mwworld/testweather.cpp new file mode 100644 index 0000000000..4b7fd8f9e2 --- /dev/null +++ b/apps/openmw_tests/mwworld/testweather.cpp @@ -0,0 +1,732 @@ +#include + +#include + +#include "apps/openmw/mwworld/timestamp.hpp" +#include "apps/openmw/mwworld/weather.hpp" + +namespace MWWorld +{ + namespace + { + // MASSER PHASES + + TEST(MWWorldWeatherTest, masserPhasesFullToWaningGibbousAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 2 and 26, 11:57 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 2 + 11.0f + 56.0f / 60.0f); + timeStampAfter += (24.0f * 2 + 11.0f + 58.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 26 + 11.0f + 56.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 26 + 11.0f + 58.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(0)); + EXPECT_EQ(afterState.mPhase, static_cast(1)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(0)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(1)); + } + + TEST(MWWorldWeatherTest, masserPhasesWaningGibbousToThirdQuarterAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 5 and 29, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 4 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 5 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 28 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 29 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(1)); + EXPECT_EQ(afterState.mPhase, static_cast(2)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(1)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(2)); + } + + TEST(MWWorldWeatherTest, masserPhasesThirdQuarterToWaningCrescentAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 8 and 32, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 7 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 8 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 31 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 32 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(2)); + EXPECT_EQ(afterState.mPhase, static_cast(3)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(2)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(3)); + } + + TEST(MWWorldWeatherTest, masserPhasesWaningCrescentToNewAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 11 and 35, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 10 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 11 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 34 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 35 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(3)); + EXPECT_EQ(afterState.mPhase, static_cast(4)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(3)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(4)); + } + + TEST(MWWorldWeatherTest, masserPhasesNewToWaxingCrescentAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 14 and 38, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 13 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 14 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 37 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 38 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(4)); + EXPECT_EQ(afterState.mPhase, static_cast(5)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(4)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(5)); + } + + TEST(MWWorldWeatherTest, masserPhasesWaxingCrescentToFirstQuarterAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 17 and 41, 2:57 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 17 + 2.0f + 56.0f / 60.0f); + timeStampAfter += (24.0f * 17 + 2.0f + 58.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 41 + 2.0f + 56.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 41 + 2.0f + 58.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(5)); + EXPECT_EQ(afterState.mPhase, static_cast(6)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(5)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(6)); + } + + TEST(MWWorldWeatherTest, masserPhasesFirstQuarterToWaxingGibbousAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 20 and 44, 5:57 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 20 + 5.0f + 56.0f / 60.0f); + timeStampAfter += (24.0f * 20 + 5.0f + 58.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 44 + 5.0f + 56.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 44 + 5.0f + 58.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(6)); + EXPECT_EQ(afterState.mPhase, static_cast(7)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(6)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(7)); + } + + TEST(MWWorldWeatherTest, masserPhasesWaxingGibbousToFullAtCorrectTimes) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 35.0f; + + // Days 23 and 47, 8:57 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 23 + 8.0f + 56.0f / 60.0f); + timeStampAfter += (24.0f * 23 + 8.0f + 58.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 47 + 8.0f + 56.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 47 + 8.0f + 58.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(7)); + EXPECT_EQ(afterState.mPhase, static_cast(0)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(7)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(0)); + } + + // SECUNDA PHASES + + TEST(MWWorldWeatherTest, secundaPhasesFullToWaningGibbousAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 2 and 26, 14:19 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 2 + 14.0f + 18.0f / 60.0f); + timeStampAfter += (24.0f * 2 + 14.0f + 20.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 26 + 14.0f + 18.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 26 + 14.0f + 20.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(0)); + EXPECT_EQ(afterState.mPhase, static_cast(1)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(0)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(1)); + } + + TEST(MWWorldWeatherTest, secundaPhasesWaningGibbousToThirdQuarterAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 5 and 29, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 4 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 5 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 28 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 29 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(1)); + EXPECT_EQ(afterState.mPhase, static_cast(2)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(1)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(2)); + } + + TEST(MWWorldWeatherTest, secundaPhasesThirdQuarterToWaningCrescentAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 8 and 32, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 7 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 8 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 31 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 32 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(2)); + EXPECT_EQ(afterState.mPhase, static_cast(3)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(2)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(3)); + } + + TEST(MWWorldWeatherTest, secundaPhasesWaningCrescentToNewAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 11 and 35, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 10 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 11 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 34 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 35 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(3)); + EXPECT_EQ(afterState.mPhase, static_cast(4)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(3)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(4)); + } + + TEST(MWWorldWeatherTest, secundaPhasesNewToWaxingCrescentAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 14 and 38, 0:00 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 13 + 23.0f + 59.0f / 60.0f); + timeStampAfter += (24.0f * 14 + 0.0f + 1.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 37 + 23.0f + 59.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 38 + 0.0f + 1.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(4)); + EXPECT_EQ(afterState.mPhase, static_cast(5)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(4)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(5)); + } + + TEST(MWWorldWeatherTest, secundaPhasesWaxingCrescentToFirstQuarterAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 17 and 41, 3:31 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 17 + 3.0f + 30.0f / 60.0f); + timeStampAfter += (24.0f * 17 + 3.0f + 32.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 41 + 3.0f + 30.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 41 + 3.0f + 32.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(5)); + EXPECT_EQ(afterState.mPhase, static_cast(6)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(5)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(6)); + } + + TEST(MWWorldWeatherTest, secundaPhasesFirstQuarterToWaxingGibbousAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 20 and 44, 7:07 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 20 + 7.0f + 6.0f / 60.0f); + timeStampAfter += (24.0f * 20 + 7.0f + 8.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 44 + 7.0f + 6.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 44 + 7.0f + 8.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(6)); + EXPECT_EQ(afterState.mPhase, static_cast(7)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(6)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(7)); + } + + TEST(MWWorldWeatherTest, secundaPhasesWaxingGibbousToFullAtCorrectTimes) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 23 and 47, 10:43 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 23 + 10.0f + 42.0f / 60.0f); + timeStampAfter += (24.0f * 23 + 10.0f + 44.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 47 + 10.0f + 42.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 47 + 10.0f + 44.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_EQ(beforeState.mPhase, static_cast(7)); + EXPECT_EQ(afterState.mPhase, static_cast(0)); + EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast(7)); + EXPECT_EQ(afterStatePostLoop.mPhase, static_cast(0)); + } + + // OFFSETS + + TEST(MWWorldWeatherTest, secundaShouldApplyIncrementOffsetAfterFirstLoop) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 14.0f; + float fadeInFinish = 15.0f; + float fadeOutStart = 7.0f; + float fadeOutFinish = 10.0f; + float axisOffset = 50.0f; + + // Days 8 and 32, 3:16 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 8 + 3.0f + 15.0f / 60.0f); + timeStampAfter += (24.0f * 8 + 3.0f + 17.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 32 + 3.0f + 15.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 32 + 3.0f + 17.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_LE(beforeState.mMoonAlpha, 0.0f); + EXPECT_GT(afterState.mMoonAlpha, 0.0f); + EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f); + EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f); + } + + TEST(MWWorldWeatherTest, moonWithLowIncrementShouldApplyIncrementOffsetAfterCycle) + { + float dailyIncrement = 0.9f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 0.0f; + float fadeInFinish = 0.0f; + float fadeOutStart = 0.0f; + float fadeOutFinish = 0.0f; + float axisOffset = 35.0f; + + // Days 7 and 31, 1:44 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 7 + 1.0f + 43.0f / 60.0f); + timeStampAfter += (24.0f * 7 + 1.0f + 45.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 31 + 1.0f + 43.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 31 + 1.0f + 45.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_LE(beforeState.mMoonAlpha, 0.0f); + EXPECT_GT(afterState.mMoonAlpha, 0.0f); + EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f); + EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f); + } + + TEST(MWWorldWeatherTest, masserShouldApplyIncrementOffsetAfterCycle) + { + float dailyIncrement = 1.0f; + float speed = 0.5f; + float fadeEndAngle = 40.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 0.0f; + float fadeInFinish = 0.0f; + float fadeOutStart = 0.0f; + float fadeOutFinish = 0.0f; + float axisOffset = 35.0f; + + // Days 4 and 28, 1:02 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 4 + 1.0f + 1.0f / 60.0f); + timeStampAfter += (24.0f * 4 + 1.0f + 3.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 28 + 1.0f + 1.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 28 + 1.0f + 3.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_LE(beforeState.mMoonAlpha, 0.0f); + EXPECT_GT(afterState.mMoonAlpha, 0.0f); + EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f); + EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f); + } + + TEST(MWWorldWeatherTest, secundaShouldApplyIncrementOffsetAfterCycle) + { + float dailyIncrement = 1.2f; + float speed = 0.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 0.0f; + float fadeInFinish = 0.0f; + float fadeOutStart = 0.0f; + float fadeOutFinish = 0.0f; + float axisOffset = 50.0f; + + // Days 3 and 27, 2:04 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 3 + 2.0f + 3.0f / 60.0f); + timeStampAfter += (24.0f * 3 + 2.0f + 5.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 27 + 2.0f + 3.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 27 + 2.0f + 5.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_LE(beforeState.mMoonAlpha, 0.0f); + EXPECT_GT(afterState.mMoonAlpha, 0.0f); + EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f); + EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f); + } + + TEST(MWWorldWeatherTest, moonWithIncreasedSpeedShouldApplyIncrementOffsetAfterCycle) + { + float dailyIncrement = 1.2f; + float speed = 1.6f; + float fadeEndAngle = 30.0f; + float fadeStartAngle = 50.0f; + float moonShadowEarlyFadeAngle = 0.5f; + float fadeInStart = 0.0f; + float fadeInFinish = 0.0f; + float fadeOutStart = 0.0f; + float fadeOutFinish = 0.0f; + float axisOffset = 50.0f; + + // Days 4 and 28, 1:13 + TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop; + timeStampBefore += (24.0f * 4 + 1.0f + 12.0f / 60.0f); + timeStampAfter += (24.0f * 4 + 1.0f + 14.0f / 60.0f); + timeStampBeforePostLoop += (24.0f * 28 + 1.0f + 12.0f / 60.0f); + timeStampAfterPostLoop += (24.0f * 28 + 1.0f + 14.0f / 60.0f); + + MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish, + axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle); + + MWRender::MoonState beforeState = moon.calculateState(timeStampBefore); + MWRender::MoonState afterState = moon.calculateState(timeStampAfter); + MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop); + MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop); + + EXPECT_LE(beforeState.mMoonAlpha, 0.0f); + EXPECT_GT(afterState.mMoonAlpha, 0.0f); + EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f); + EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f); + } + } +} diff --git a/apps/wizard/inisettings.hpp b/apps/wizard/inisettings.hpp index c8cd30c3c1..6ea8fc4adb 100644 --- a/apps/wizard/inisettings.hpp +++ b/apps/wizard/inisettings.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include namespace Wizard { diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 6e6d3ee984..1426a797f7 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -111,7 +111,7 @@ add_component_dir (bgsm ) add_component_dir (bsa - bsa_file compressedbsafile ba2gnrlfile ba2dx10file ba2file memorystream + bsafile compressedbsafile ba2gnrlfile ba2dx10file ba2file memorystream ) add_component_dir (bullethelpers @@ -155,9 +155,9 @@ add_component_dir (nifbullet bulletnifloader ) -add_component_dir (to_utf8 - tables_gen - to_utf8 +add_component_dir (toutf8 + tablesgen + toutf8 ) add_component_dir(esm attr common defs esmcommon records util luascripts format refid esmbridge esmterrain @@ -173,7 +173,7 @@ add_component_dir(esm attr common defs esmcommon records util luascripts format exteriorcelllocation ) -add_component_dir(fx pass technique lexer lexer_types parse_constants widgets stateupdater) +add_component_dir(fx pass technique lexer lexertypes parseconstants widgets stateupdater) add_component_dir(std140 ubo) @@ -362,7 +362,7 @@ add_component_dir (fontloader add_component_dir (sdlutil events - gl4es_init + gl4esinit imagetosurface sdlcursormanager sdlgraphicswindow @@ -390,10 +390,10 @@ copy_resource_file("lua_ui/content.lua" "${OPENMW_RESOURCES_ROOT}" "resources/lu if(WIN32) add_component_dir (crashcatcher - windows_crashcatcher - windows_crashmonitor - windows_crashshm + windowscrashcatcher windowscrashdumppathhelpers + windowscrashmonitor + windowscrashshm ) elseif(NOT ANDROID) add_component_dir (crashcatcher @@ -500,15 +500,15 @@ add_component_dir(platform if (WIN32) add_component_dir(platform - file.win32 + filewin32 ) elseif (UNIX) add_component_dir(platform - file.posix + fileposix ) else () add_component_dir(platform - file.stdio + filestdio ) endif() diff --git a/components/bsa/ba2dx10file.cpp b/components/bsa/ba2dx10file.cpp index 502ca043ab..a438121d5b 100644 --- a/components/bsa/ba2dx10file.cpp +++ b/components/bsa/ba2dx10file.cpp @@ -24,13 +24,15 @@ #endif #include -#include -#include + #include #include #include #include +#include "ba2file.hpp" +#include "memorystream.hpp" + namespace Bsa { BA2DX10File::BA2DX10File() {} diff --git a/components/bsa/ba2dx10file.hpp b/components/bsa/ba2dx10file.hpp index 59db10745b..cd1f822179 100644 --- a/components/bsa/ba2dx10file.hpp +++ b/components/bsa/ba2dx10file.hpp @@ -1,5 +1,5 @@ -#ifndef BSA_BA2_DX10_FILE_H -#define BSA_BA2_DX10_FILE_H +#ifndef OPENMW_COMPONENTS_BSA_BA2DX10FILE_HPP +#define OPENMW_COMPONENTS_BSA_BA2DX10FILE_HPP #include #include @@ -7,7 +7,7 @@ #include #include -#include +#include "bsafile.hpp" namespace Bsa { diff --git a/components/bsa/ba2file.hpp b/components/bsa/ba2file.hpp index 9a68d3afd0..0d51be4c0e 100644 --- a/components/bsa/ba2file.hpp +++ b/components/bsa/ba2file.hpp @@ -1,5 +1,5 @@ -#ifndef BSA_BA2_FILE_H -#define BSA_BA2_FILE_H +#ifndef OPENMW_COMPONENTS_BSA_BA2FILE_HPP +#define OPENMW_COMPONENTS_BSA_BA2FILE_HPP #include #include diff --git a/components/bsa/ba2gnrlfile.cpp b/components/bsa/ba2gnrlfile.cpp index 63dd3d1d50..75e7305245 100644 --- a/components/bsa/ba2gnrlfile.cpp +++ b/components/bsa/ba2gnrlfile.cpp @@ -22,13 +22,15 @@ #endif #include -#include -#include + #include #include #include #include +#include "ba2file.hpp" +#include "memorystream.hpp" + namespace Bsa { // special marker for invalid records, diff --git a/components/bsa/ba2gnrlfile.hpp b/components/bsa/ba2gnrlfile.hpp index 6a212c5e81..0bc94eae0e 100644 --- a/components/bsa/ba2gnrlfile.hpp +++ b/components/bsa/ba2gnrlfile.hpp @@ -1,12 +1,12 @@ -#ifndef BSA_BA2_GNRL_FILE_H -#define BSA_BA2_GNRL_FILE_H +#ifndef OPENMW_COMPONENTS_BSA_BA2GNRLFILE_HPP +#define OPENMW_COMPONENTS_BSA_BA2GNRLFILE_HPP #include #include #include #include -#include +#include "bsafile.hpp" namespace Bsa { diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsafile.cpp similarity index 99% rename from components/bsa/bsa_file.cpp rename to components/bsa/bsafile.cpp index 46639a729e..948b9dac8d 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsafile.cpp @@ -4,7 +4,7 @@ Email: < korslund@gmail.com > WWW: https://openmw.org/ - This file (bsa_file.cpp) is part of the OpenMW package. + This file (bsafile.cpp) is part of the OpenMW package. OpenMW is distributed as free software: you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,10 +21,7 @@ */ -#include "bsa_file.hpp" - -#include -#include +#include "bsafile.hpp" #include #include @@ -32,6 +29,9 @@ #include #include +#include +#include + using namespace Bsa; /// Error handling diff --git a/components/bsa/bsa_file.hpp b/components/bsa/bsafile.hpp similarity index 96% rename from components/bsa/bsa_file.hpp rename to components/bsa/bsafile.hpp index 03a0703885..ad7acdad17 100644 --- a/components/bsa/bsa_file.hpp +++ b/components/bsa/bsafile.hpp @@ -4,7 +4,7 @@ Email: < korslund@gmail.com > WWW: https://openmw.org/ - This file (bsa_file.h) is part of the OpenMW package. + This file (bsafile.hpp) is part of the OpenMW package. OpenMW is distributed as free software: you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,8 +21,8 @@ */ -#ifndef BSA_BSA_FILE_H -#define BSA_BSA_FILE_H +#ifndef OPENMW_COMPONENTS_BSA_BSAFILE_HPP +#define OPENMW_COMPONENTS_BSA_BSAFILE_HPP #include #include diff --git a/components/bsa/compressedbsafile.cpp b/components/bsa/compressedbsafile.cpp index 14d90f5d91..8426c5965c 100644 --- a/components/bsa/compressedbsafile.cpp +++ b/components/bsa/compressedbsafile.cpp @@ -45,11 +45,13 @@ #endif #include -#include + #include #include #include +#include "memorystream.hpp" + namespace Bsa { /// Read header information from the input source diff --git a/components/bsa/compressedbsafile.hpp b/components/bsa/compressedbsafile.hpp index 8fa5c9a62a..83620f11bc 100644 --- a/components/bsa/compressedbsafile.hpp +++ b/components/bsa/compressedbsafile.hpp @@ -23,14 +23,14 @@ */ -#ifndef BSA_COMPRESSED_BSA_FILE_H -#define BSA_COMPRESSED_BSA_FILE_H +#ifndef OPENMW_COMPONENTS_BSA_COMPRESSEDBSAFILE_HPP +#define OPENMW_COMPONENTS_BSA_COMPRESSEDBSAFILE_HPP +#include #include #include -#include -#include +#include "bsafile.hpp" namespace Bsa { diff --git a/components/bsa/memorystream.hpp b/components/bsa/memorystream.hpp index 5662dde8ff..945d0b33d9 100644 --- a/components/bsa/memorystream.hpp +++ b/components/bsa/memorystream.hpp @@ -23,13 +23,14 @@ */ -#ifndef BSA_MEMORY_STREAM_H -#define BSA_MEMORY_STREAM_H +#ifndef OPENMW_COMPONENTS_BSA_MEMORYSTREAM_HPP +#define OPENMW_COMPONENTS_BSA_MEMORYSTREAM_HPP -#include #include #include +#include + namespace Bsa { /** diff --git a/components/crashcatcher/crashcatcher.hpp b/components/crashcatcher/crashcatcher.hpp index 16b416cf98..60f749e57a 100644 --- a/components/crashcatcher/crashcatcher.hpp +++ b/components/crashcatcher/crashcatcher.hpp @@ -1,5 +1,5 @@ -#ifndef CRASHCATCHER_H -#define CRASHCATCHER_H +#ifndef OPENMW_COMPONENTS_CRASHCATCHER_CRASHCATCHER_HPP +#define OPENMW_COMPONENTS_CRASHCATCHER_CRASHCATCHER_HPP #include diff --git a/components/crashcatcher/windows_crashcatcher.cpp b/components/crashcatcher/windowscrashcatcher.cpp similarity index 98% rename from components/crashcatcher/windows_crashcatcher.cpp rename to components/crashcatcher/windowscrashcatcher.cpp index bd5e94a6aa..c89ab9c335 100644 --- a/components/crashcatcher/windows_crashcatcher.cpp +++ b/components/crashcatcher/windowscrashcatcher.cpp @@ -1,17 +1,18 @@ -#include "windows_crashcatcher.hpp" +#include "windowscrashcatcher.hpp" #include #include #include #include -#include "windows_crashmonitor.hpp" -#include "windows_crashshm.hpp" -#include "windowscrashdumppathhelpers.hpp" #include #include +#include "windowscrashdumppathhelpers.hpp" +#include "windowscrashmonitor.hpp" +#include "windowscrashshm.hpp" + namespace Crash { namespace diff --git a/components/crashcatcher/windows_crashcatcher.hpp b/components/crashcatcher/windowscrashcatcher.hpp similarity index 94% rename from components/crashcatcher/windows_crashcatcher.hpp rename to components/crashcatcher/windowscrashcatcher.hpp index 5bc78b19fa..0e550d2c9b 100644 --- a/components/crashcatcher/windows_crashcatcher.hpp +++ b/components/crashcatcher/windowscrashcatcher.hpp @@ -1,11 +1,12 @@ -#ifndef WINDOWS_CRASHCATCHER_HPP -#define WINDOWS_CRASHCATCHER_HPP +#ifndef OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHCATCHER_HPP +#define OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHCATCHER_HPP #include -#include #include +#include "crashcatcher.hpp" + namespace Crash { @@ -80,4 +81,4 @@ namespace Crash } // namespace Crash -#endif // WINDOWS_CRASHCATCHER_HPP +#endif diff --git a/components/crashcatcher/windowscrashdumppathhelpers.hpp b/components/crashcatcher/windowscrashdumppathhelpers.hpp index fa64969301..9e11c57834 100644 --- a/components/crashcatcher/windowscrashdumppathhelpers.hpp +++ b/components/crashcatcher/windowscrashdumppathhelpers.hpp @@ -1,8 +1,10 @@ -#ifndef COMPONENTS_CRASH_WINDOWSCRASHDUMPPATHHELPERS_H -#include "windows_crashshm.hpp" +#ifndef OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHDUMPPATHHELPERS_HPP +#define OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHDUMPPATHHELPERS_HPP #include +#include "windowscrashshm.hpp" + namespace Crash { std::filesystem::path getCrashDumpPath(const CrashSHM& crashShm); diff --git a/components/crashcatcher/windows_crashmonitor.cpp b/components/crashcatcher/windowscrashmonitor.cpp similarity index 99% rename from components/crashcatcher/windows_crashmonitor.cpp rename to components/crashcatcher/windowscrashmonitor.cpp index 116a678fef..de66e20b61 100644 --- a/components/crashcatcher/windows_crashmonitor.cpp +++ b/components/crashcatcher/windowscrashmonitor.cpp @@ -1,4 +1,4 @@ -#include "windows_crashmonitor.hpp" +#include "windowscrashmonitor.hpp" #include #include @@ -10,12 +10,13 @@ #include -#include "windows_crashcatcher.hpp" -#include "windows_crashshm.hpp" -#include "windowscrashdumppathhelpers.hpp" #include #include +#include "windowscrashcatcher.hpp" +#include "windowscrashdumppathhelpers.hpp" +#include "windowscrashshm.hpp" + namespace Crash { std::unordered_map CrashMonitor::smEventHookOwners{}; diff --git a/components/crashcatcher/windows_crashmonitor.hpp b/components/crashcatcher/windowscrashmonitor.hpp similarity index 90% rename from components/crashcatcher/windows_crashmonitor.hpp rename to components/crashcatcher/windowscrashmonitor.hpp index 25ee710fd3..6dfd5cabc6 100644 --- a/components/crashcatcher/windows_crashmonitor.hpp +++ b/components/crashcatcher/windowscrashmonitor.hpp @@ -1,5 +1,5 @@ -#ifndef WINDOWS_CRASHMONITOR_HPP -#define WINDOWS_CRASHMONITOR_HPP +#ifndef OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHMONITOR_HPP +#define OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHMONITOR_HPP #include @@ -60,4 +60,4 @@ namespace Crash } // namespace Crash -#endif // WINDOWS_CRASHMONITOR_HPP +#endif diff --git a/components/crashcatcher/windows_crashshm.hpp b/components/crashcatcher/windowscrashshm.hpp similarity index 90% rename from components/crashcatcher/windows_crashshm.hpp rename to components/crashcatcher/windowscrashshm.hpp index 2cad54b17a..6ac09234ba 100644 --- a/components/crashcatcher/windows_crashshm.hpp +++ b/components/crashcatcher/windowscrashshm.hpp @@ -1,5 +1,5 @@ -#ifndef WINDOWS_CRASHSHM_HPP -#define WINDOWS_CRASHSHM_HPP +#ifndef OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHSHM_HPP +#define OPENMW_COMPONENTS_CRASHCATCHER_WINDOWSCRASHSHM_HPP #include @@ -55,4 +55,4 @@ namespace Crash } // namespace Crash -#endif // WINDOWS_CRASHSHM_HPP +#endif diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index 2ba7b2072e..4cb625c548 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -22,7 +22,7 @@ #include #ifdef _WIN32 -#include +#include #include #include diff --git a/components/esm3/esmreader.hpp b/components/esm3/esmreader.hpp index 5af5e75573..9bae5f217e 100644 --- a/components/esm3/esmreader.hpp +++ b/components/esm3/esmreader.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include "components/esm/decompose.hpp" #include "components/esm/esmcommon.hpp" diff --git a/components/esm3/esmwriter.cpp b/components/esm3/esmwriter.cpp index 47c861e3ca..8bae844585 100644 --- a/components/esm3/esmwriter.cpp +++ b/components/esm3/esmwriter.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "formatversion.hpp" diff --git a/components/esm3/formatversion.hpp b/components/esm3/formatversion.hpp index 32e245d7d1..c205f2fbb7 100644 --- a/components/esm3/formatversion.hpp +++ b/components/esm3/formatversion.hpp @@ -32,7 +32,8 @@ namespace ESM inline constexpr FormatVersion MinSupportedSaveGameFormatVersion = 5; inline constexpr FormatVersion OpenMW0_48SaveGameFormatVersion = 21; - inline constexpr FormatVersion OpenMW0_49SaveGameFormatVersion = CurrentSaveGameFormatVersion; + inline constexpr FormatVersion OpenMW0_49SaveGameFormatVersion = 34; + inline constexpr FormatVersion OpenMW0_50SaveGameFormatVersion = CurrentSaveGameFormatVersion; } #endif diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index 505922601d..43a9e26418 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include "grouptype.hpp" diff --git a/components/files/linuxpath.cpp b/components/files/linuxpath.cpp index 4dbe119917..2e74948fff 100644 --- a/components/files/linuxpath.cpp +++ b/components/files/linuxpath.cpp @@ -7,7 +7,6 @@ #include #include -#include #include namespace @@ -51,14 +50,6 @@ namespace Files LinuxPath::LinuxPath(const std::string& application_name) : mName(application_name) { - std::error_code ec; - current_path(getLocalPath(), ec); - const auto err = ec.value(); - if (err != 0) - { - Log(Debug::Warning) << "Error " << err << " " << std::generic_category().message(errno) - << " when changing current directory"; - } } std::filesystem::path LinuxPath::getUserConfigPath() const diff --git a/components/files/macospath.cpp b/components/files/macospath.cpp index 4b37c2fb26..191f3b15a6 100644 --- a/components/files/macospath.cpp +++ b/components/files/macospath.cpp @@ -64,11 +64,6 @@ namespace Files MacOsPath::MacOsPath(const std::string& application_name) : mName(application_name) { - std::filesystem::path binary_path = getBinaryPath(); - std::error_code ec; - std::filesystem::current_path(binary_path.parent_path(), ec); - if (ec.value() != 0) - Log(Debug::Warning) << "Error " << ec.message() << " when changing current directory"; } std::filesystem::path MacOsPath::getUserConfigPath() const @@ -102,7 +97,7 @@ namespace Files std::filesystem::path MacOsPath::getLocalPath() const { - return std::filesystem::path("../Resources/"); + return getBinaryPath().parent_path().parent_path() / "Resources"; } std::filesystem::path MacOsPath::getGlobalDataPath() const diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index 6fb9845976..77faa23131 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -26,10 +26,6 @@ namespace Files WindowsPath::WindowsPath(const std::string& application_name) : mName(application_name) { - std::error_code ec; - current_path(getLocalPath(), ec); - if (ec.value() != 0) - Log(Debug::Warning) << "Error " << ec.value() << " when changing current directory"; } std::filesystem::path WindowsPath::getUserConfigPath() const diff --git a/components/fontloader/fontloader.hpp b/components/fontloader/fontloader.hpp index a7269f1a56..d0511659a0 100644 --- a/components/fontloader/fontloader.hpp +++ b/components/fontloader/fontloader.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include namespace VFS { diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index 6140c7375c..2fc25e44f1 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -6,7 +6,6 @@ #include #include -#include #include namespace fx diff --git a/components/fx/lexer.hpp b/components/fx/lexer.hpp index fc7d4ec9d7..dda6b3a0f6 100644 --- a/components/fx/lexer.hpp +++ b/components/fx/lexer.hpp @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_FX_LEXER_H -#define OPENMW_COMPONENTS_FX_LEXER_H +#ifndef OPENMW_COMPONENTS_FX_LEXER_HPP +#define OPENMW_COMPONENTS_FX_LEXER_HPP #include #include @@ -7,7 +7,7 @@ #include #include -#include "lexer_types.hpp" +#include "lexertypes.hpp" namespace fx { diff --git a/components/fx/lexer_types.hpp b/components/fx/lexertypes.hpp similarity index 98% rename from components/fx/lexer_types.hpp rename to components/fx/lexertypes.hpp index 9fe13ac827..2a56a84a1a 100644 --- a/components/fx/lexer_types.hpp +++ b/components/fx/lexertypes.hpp @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_FX_LEXER_TYPES_H -#define OPENMW_COMPONENTS_FX_LEXER_TYPES_H +#ifndef OPENMW_COMPONENTS_FX_LEXERTYPES_HPP +#define OPENMW_COMPONENTS_FX_LEXERTYPES_HPP #include #include @@ -165,4 +165,4 @@ namespace fx } } -#endif \ No newline at end of file +#endif diff --git a/components/fx/parse_constants.hpp b/components/fx/parseconstants.hpp similarity index 98% rename from components/fx/parse_constants.hpp rename to components/fx/parseconstants.hpp index 2057476f3e..3ad9abd959 100644 --- a/components/fx/parse_constants.hpp +++ b/components/fx/parseconstants.hpp @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_FX_PARSE_CONSTANTS_H -#define OPENMW_COMPONENTS_FX_PARSE_CONSTANTS_H +#ifndef OPENMW_COMPONENTS_FX_PARSECONSTANTS_HPP +#define OPENMW_COMPONENTS_FX_PARSECONSTANTS_HPP #include #include diff --git a/components/fx/pass.hpp b/components/fx/pass.hpp index e176afc699..1c417ac8cf 100644 --- a/components/fx/pass.hpp +++ b/components/fx/pass.hpp @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_FX_PASS_H -#define OPENMW_COMPONENTS_FX_PASS_H +#ifndef OPENMW_COMPONENTS_FX_PASS_HPP +#define OPENMW_COMPONENTS_FX_PASS_HPP #include #include diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index aaaf56e18a..a8cd455dea 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -17,7 +17,7 @@ #include #include -#include "parse_constants.hpp" +#include "parseconstants.hpp" namespace { diff --git a/components/fx/technique.hpp b/components/fx/technique.hpp index 2778763a9a..ad5e876faa 100644 --- a/components/fx/technique.hpp +++ b/components/fx/technique.hpp @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_FX_TECHNIQUE_H -#define OPENMW_COMPONENTS_FX_TECHNIQUE_H +#ifndef OPENMW_COMPONENTS_FX_TECHNIQUE_HPP +#define OPENMW_COMPONENTS_FX_TECHNIQUE_HPP #include #include diff --git a/components/fx/types.hpp b/components/fx/types.hpp index 596b54c217..1536cda115 100644 --- a/components/fx/types.hpp +++ b/components/fx/types.hpp @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_FX_TYPES_H -#define OPENMW_COMPONENTS_FX_TYPES_H +#ifndef OPENMW_COMPONENTS_FX_TYPES_HPP +#define OPENMW_COMPONENTS_FX_TYPES_HPP #include #include diff --git a/components/fx/widgets.hpp b/components/fx/widgets.hpp index 6217af7fee..59787ed9aa 100644 --- a/components/fx/widgets.hpp +++ b/components/fx/widgets.hpp @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_FX_WIDGETS_H -#define OPENMW_COMPONENTS_FX_WIDGETS_H +#ifndef OPENMW_COMPONENTS_FX_WIDGETS_HPP +#define OPENMW_COMPONENTS_FX_WIDGETS_HPP #include #include diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index 604cf92c33..bd362101c6 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -3,7 +3,9 @@ #ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP #define OPENMW_COMPONENTS_NIF_NIFKEY_HPP +#include #include +#include #include "exception.hpp" #include "niffile.hpp" @@ -17,7 +19,7 @@ namespace Nif InterpolationType_Unknown = 0, InterpolationType_Linear = 1, InterpolationType_Quadratic = 2, - InterpolationType_TBC = 3, + InterpolationType_TCB = 3, InterpolationType_XYZ = 4, InterpolationType_Constant = 5 }; @@ -28,18 +30,19 @@ namespace Nif T mValue; T mInTan; // Only for Quadratic interpolation, and never for QuaternionKeyList T mOutTan; // Only for Quadratic interpolation, and never for QuaternionKeyList - - // FIXME: Implement TBC interpolation - /* - float mTension; // Only for TBC interpolation - float mBias; // Only for TBC interpolation - float mContinuity; // Only for TBC interpolation - */ }; - using FloatKey = KeyT; - using Vector3Key = KeyT; - using Vector4Key = KeyT; - using QuaternionKey = KeyT; + + template + struct TCBKey + { + float mTime; + T mValue{}; + T mInTan{}; + T mOutTan{}; + float mTension; + float mContinuity; + float mBias; + }; template struct KeyMapT @@ -101,15 +104,20 @@ namespace Nif mKeys[time] = key; } } - else if (mInterpolationType == InterpolationType_TBC) + else if (mInterpolationType == InterpolationType_TCB) { - for (size_t i = 0; i < count; i++) + std::vector> tcbKeys(count); + for (TCBKey& key : tcbKeys) { - float time; - nif->read(time); - readTBC(*nif, key); - mKeys[time] = key; + nif->read(key.mTime); + key.mValue = ((*nif).*getValue)(); + nif->read(key.mTension); + nif->read(key.mContinuity); + nif->read(key.mBias); } + generateTCBTangents(tcbKeys); + for (TCBKey& key : tcbKeys) + mKeys[key.mTime] = KeyType{ std::move(key.mValue), std::move(key.mInTan), std::move(key.mOutTan) }; } else if (mInterpolationType == InterpolationType_XYZ) { @@ -140,12 +148,52 @@ namespace Nif static void readQuadratic(NIFStream& nif, KeyT& key) { readValue(nif, key); } - static void readTBC(NIFStream& nif, KeyT& key) + template + static void generateTCBTangents(std::vector>& keys) { - readValue(nif, key); - /*key.mTension = */ nif.get(); - /*key.mBias = */ nif.get(); - /*key.mContinuity = */ nif.get(); + if (keys.size() <= 1) + return; + + std::sort(keys.begin(), keys.end(), [](const auto& a, const auto& b) { return a.mTime < b.mTime; }); + for (size_t i = 0; i < keys.size(); ++i) + { + TCBKey& curr = keys[i]; + const TCBKey& prev = (i == 0) ? curr : keys[i - 1]; + const TCBKey& next = (i == keys.size() - 1) ? curr : keys[i + 1]; + const float prevLen = curr.mTime - prev.mTime; + const float nextLen = next.mTime - curr.mTime; + if (prevLen + nextLen <= 0.f) + continue; + + const U prevDelta = curr.mValue - prev.mValue; + const U nextDelta = next.mValue - curr.mValue; + const float t = curr.mTension; + const float c = curr.mContinuity; + const float b = curr.mBias; + + U x{}, y{}, z{}, w{}; + if (prevLen > 0.f) + x = prevDelta / prevLen * (1 - t) * (1 - c) * (1 + b); + if (nextLen > 0.f) + y = nextDelta / nextLen * (1 - t) * (1 + c) * (1 - b); + if (prevLen > 0.f) + z = prevDelta / prevLen * (1 - t) * (1 + c) * (1 + b); + if (nextLen > 0.f) + w = nextDelta / nextLen * (1 - t) * (1 - c) * (1 - b); + + curr.mInTan = (x + y) * prevLen / (prevLen + nextLen); + curr.mOutTan = (z + w) * nextLen / (prevLen + nextLen); + } + } + + static void generateTCBTangents(std::vector>& keys) + { + // TODO: is this even legal? + } + + static void generateTCBTangents(std::vector>& keys) + { + // TODO: implement TCB interpolation for quaternions } }; using FloatKeyMap = KeyMapT>; diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index ef63bae937..6c361401e8 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -2,9 +2,9 @@ #include -#include "niffile.hpp" +#include -#include "../to_utf8/to_utf8.hpp" +#include "niffile.hpp" namespace { diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 99d3df9545..468668ce76 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -131,6 +131,7 @@ namespace NifOsg case Nif::InterpolationType_Constant: return fraction > 0.5f ? b.mValue : a.mValue; case Nif::InterpolationType_Quadratic: + case Nif::InterpolationType_TCB: { // Using a cubic Hermite spline. // b1(t) = 2t^3 - 3t^2 + 1 @@ -147,7 +148,6 @@ namespace NifOsg 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); } diff --git a/components/platform/file.posix.cpp b/components/platform/fileposix.cpp similarity index 100% rename from components/platform/file.posix.cpp rename to components/platform/fileposix.cpp diff --git a/components/platform/file.stdio.cpp b/components/platform/filestdio.cpp similarity index 100% rename from components/platform/file.stdio.cpp rename to components/platform/filestdio.cpp diff --git a/components/platform/file.win32.cpp b/components/platform/filewin32.cpp similarity index 100% rename from components/platform/file.win32.cpp rename to components/platform/filewin32.cpp diff --git a/components/process/processinvoker.cpp b/components/process/processinvoker.cpp index 9489076acb..f1af67d20d 100644 --- a/components/process/processinvoker.cpp +++ b/components/process/processinvoker.cpp @@ -1,14 +1,11 @@ #include "processinvoker.hpp" +#include #include #include #include #include -#if defined(Q_OS_MAC) -#include -#endif - Process::ProcessInvoker::ProcessInvoker(QObject* parent) : QObject(parent) { @@ -60,12 +57,9 @@ bool Process::ProcessInvoker::startProcess(const QString& name, const QStringLis QString path(name); #ifdef Q_OS_WIN path.append(QLatin1String(".exe")); -#elif defined(Q_OS_MAC) - QDir dir(QCoreApplication::applicationDirPath()); - path = dir.absoluteFilePath(name); -#else - path.prepend(QLatin1String("./")); #endif + QDir dir(QCoreApplication::applicationDirPath()); + path = dir.absoluteFilePath(path); QFileInfo info(path); diff --git a/components/sdlutil/gl4es_init.cpp b/components/sdlutil/gl4esinit.cpp similarity index 97% rename from components/sdlutil/gl4es_init.cpp rename to components/sdlutil/gl4esinit.cpp index 044b54ce02..13015dee82 100644 --- a/components/sdlutil/gl4es_init.cpp +++ b/components/sdlutil/gl4esinit.cpp @@ -1,7 +1,7 @@ // EGL does not work reliably for feature detection. // Instead, we initialize gl4es manually. #ifdef OPENMW_GL4ES_MANUAL_INIT -#include "gl4es_init.h" +#include "gl4esinit.h" // For glHint #include diff --git a/components/sdlutil/gl4es_init.h b/components/sdlutil/gl4esinit.h similarity index 67% rename from components/sdlutil/gl4es_init.h rename to components/sdlutil/gl4esinit.h index 6a19d3dfe5..8916d50a7e 100644 --- a/components/sdlutil/gl4es_init.h +++ b/components/sdlutil/gl4esinit.h @@ -1,5 +1,5 @@ -#ifndef OPENMW_COMPONENTS_SDLUTIL_GL4ES_INIT_H -#define OPENMW_COMPONENTS_SDLUTIL_GL4ES_INIT_H +#ifndef OPENMW_COMPONENTS_SDLUTIL_GL4ESINIT_H +#define OPENMW_COMPONENTS_SDLUTIL_GL4ESINIT_H #ifdef OPENMW_GL4ES_MANUAL_INIT #include @@ -10,4 +10,4 @@ extern "C" void openmw_gl4es_init(SDL_Window* window); #endif // OPENMW_GL4ES_MANUAL_INIT -#endif // OPENMW_COMPONENTS_SDLUTIL_GL4ES_INIT_H +#endif // OPENMW_COMPONENTS_SDLUTIL_GL4ESINIT_H diff --git a/components/sdlutil/sdlgraphicswindow.cpp b/components/sdlutil/sdlgraphicswindow.cpp index 36947460df..9ff0545930 100644 --- a/components/sdlutil/sdlgraphicswindow.cpp +++ b/components/sdlutil/sdlgraphicswindow.cpp @@ -3,7 +3,7 @@ #include #ifdef OPENMW_GL4ES_MANUAL_INIT -#include "gl4es_init.h" +#include "gl4esinit.h" #endif namespace SDLUtil diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index d97276576f..0e6b5e79c6 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -287,11 +287,17 @@ namespace Shader addedState->setName("addedState"); } + // This list is used both for detecting known texture types (including added normal maps etc.) and setting the + // shader defines. Normal maps and normal height maps both get sent to the shader as a normal map, so the latter + // must be detected separately. const char* defaultTextures[] = { "diffuseMap", "normalMap", "emissiveMap", "darkMap", "detailMap", "envMap", "specularMap", "decalMap", "bumpMap", "glossMap" }; bool isTextureNameRecognized(std::string_view name) { - return std::find(std::begin(defaultTextures), std::end(defaultTextures), name) != std::end(defaultTextures); + if (std::find(std::begin(defaultTextures), std::end(defaultTextures), name) != std::end(defaultTextures)) + return true; + else + return name == "normalHeightMap"; } void ShaderVisitor::applyStateSet(osg::ref_ptr stateset, osg::Node& node) @@ -439,8 +445,9 @@ namespace Shader if (!writableStateSet) writableStateSet = getWritableStateSet(node); writableStateSet->setTextureAttributeAndModes(unit, normalMapTex, osg::StateAttribute::ON); - writableStateSet->setTextureAttributeAndModes( - unit, new SceneUtil::TextureType("normalMap"), osg::StateAttribute::ON); + writableStateSet->setTextureAttributeAndModes(unit, + new SceneUtil::TextureType(normalHeight ? "normalHeightMap" : "normalMap"), + osg::StateAttribute::ON); mRequirements.back().mTextures[unit] = "normalMap"; mRequirements.back().mTexStageRequiringTangents = unit; mRequirements.back().mShaderRequired = true; diff --git a/components/to_utf8/.gitignore b/components/to_utf8/.gitignore deleted file mode 100644 index 4e0357749e..0000000000 --- a/components/to_utf8/.gitignore +++ /dev/null @@ -1 +0,0 @@ -gen_iconv diff --git a/components/to_utf8/Makefile b/components/to_utf8/Makefile deleted file mode 100644 index 5234d455ae..0000000000 --- a/components/to_utf8/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -tables_gen.hpp: gen_iconv - ./gen_iconv > tables_gen.hpp - -gen_iconv: gen_iconv.cpp - g++ -Wall $^ -o $@ - -clean: - rm -f ./gen_iconv \ No newline at end of file diff --git a/components/toutf8/.gitignore b/components/toutf8/.gitignore new file mode 100644 index 0000000000..f1f54f5aea --- /dev/null +++ b/components/toutf8/.gitignore @@ -0,0 +1 @@ +geniconv diff --git a/components/toutf8/Makefile b/components/toutf8/Makefile new file mode 100644 index 0000000000..e46176d3ed --- /dev/null +++ b/components/toutf8/Makefile @@ -0,0 +1,8 @@ +tablesgen.hpp: geniconv + ./geniconv > tablesgen.hpp + +geniconv: geniconv.cpp + g++ -Wall $^ -o $@ + +clean: + rm -f ./geniconv diff --git a/components/to_utf8/gen_iconv.cpp b/components/toutf8/geniconv.cpp similarity index 95% rename from components/to_utf8/gen_iconv.cpp rename to components/toutf8/geniconv.cpp index 062b1173fc..48a7fb4627 100644 --- a/components/to_utf8/gen_iconv.cpp +++ b/components/toutf8/geniconv.cpp @@ -1,4 +1,4 @@ -// This program generates the file tables_gen.hpp +// This program generates the file tablesgen.hpp #include @@ -88,7 +88,7 @@ int write_table(const std::string& charset, const std::string& tableName) int main() { // Write header guard - std::cout << "#ifndef COMPONENTS_TOUTF8_TABLE_GEN_H\n#define COMPONENTS_TOUTF8_TABLE_GEN_H\n\n"; + std::cout << "#ifndef OPENMW_COMPONENTS_TOUTF8_TABLESGEN_HPP\n#define OPENMW_COMPONENTS_TOUTF8_TABLESGEN_HPP\n\n"; // Write namespace std::cout << "namespace ToUTF8\n{\n\n"; diff --git a/components/to_utf8/tables_gen.hpp b/components/toutf8/tablesgen.hpp similarity index 99% rename from components/to_utf8/tables_gen.hpp rename to components/toutf8/tablesgen.hpp index b25bb54bab..9ef5097ece 100644 --- a/components/to_utf8/tables_gen.hpp +++ b/components/toutf8/tablesgen.hpp @@ -1,5 +1,5 @@ -#ifndef COMPONENTS_TOUTF8_TABLE_GEN_H -#define COMPONENTS_TOUTF8_TABLE_GEN_H +#ifndef OPENMW_COMPONENTS_TOUTF8_TABLESGEN_HPP +#define OPENMW_COMPONENTS_TOUTF8_TABLESGEN_HPP namespace ToUTF8 { diff --git a/components/to_utf8/to_utf8.cpp b/components/toutf8/toutf8.cpp similarity index 99% rename from components/to_utf8/to_utf8.cpp rename to components/toutf8/toutf8.cpp index 7e34147b1c..03b12042e4 100644 --- a/components/to_utf8/to_utf8.cpp +++ b/components/toutf8/toutf8.cpp @@ -1,4 +1,4 @@ -#include "to_utf8.hpp" +#include "toutf8.hpp" #include #include @@ -41,7 +41,7 @@ */ // Generated tables -#include "tables_gen.hpp" +#include "tablesgen.hpp" using namespace ToUTF8; diff --git a/components/to_utf8/to_utf8.hpp b/components/toutf8/toutf8.hpp similarity index 97% rename from components/to_utf8/to_utf8.hpp rename to components/toutf8/toutf8.hpp index 0dde0fced6..e258a0e94b 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/toutf8/toutf8.hpp @@ -1,5 +1,5 @@ -#ifndef COMPONENTS_TOUTF8_H -#define COMPONENTS_TOUTF8_H +#ifndef OPENMW_COMPONENTS_TOUTF8_TOUTF8_HPP +#define OPENMW_COMPONENTS_TOUTF8_TOUTF8_HPP #include #include diff --git a/components/translation/translation.hpp b/components/translation/translation.hpp index a7b6087ac7..18e40713e5 100644 --- a/components/translation/translation.hpp +++ b/components/translation/translation.hpp @@ -2,7 +2,7 @@ #define COMPONENTS_TRANSLATION_DATA_H #include -#include +#include namespace Translation { diff --git a/components/vfs/bsaarchive.hpp b/components/vfs/bsaarchive.hpp index 664466fa40..2e6fac6558 100644 --- a/components/vfs/bsaarchive.hpp +++ b/components/vfs/bsaarchive.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include diff --git a/files/data/mygui/openmw_hud.layout b/files/data/mygui/openmw_hud.layout index a189075f44..0650df1f43 100644 --- a/files/data/mygui/openmw_hud.layout +++ b/files/data/mygui/openmw_hud.layout @@ -44,8 +44,8 @@ - - + + @@ -56,7 +56,9 @@ - + + + @@ -131,4 +133,4 @@ - \ No newline at end of file + diff --git a/files/data/mygui/openmw_merchantrepair.layout b/files/data/mygui/openmw_merchantrepair.layout index 60f5e05096..940bf10f15 100644 --- a/files/data/mygui/openmw_merchantrepair.layout +++ b/files/data/mygui/openmw_merchantrepair.layout @@ -1,28 +1,28 @@ - + - - - - - + + + + + - - + + - + - + diff --git a/files/data/mygui/openmw_savegame_dialog.layout b/files/data/mygui/openmw_savegame_dialog.layout index 1683326065..5a45810943 100644 --- a/files/data/mygui/openmw_savegame_dialog.layout +++ b/files/data/mygui/openmw_savegame_dialog.layout @@ -37,14 +37,20 @@ + + + + + + + + - - diff --git a/files/data/mygui/openmw_spell_buying_window.layout b/files/data/mygui/openmw_spell_buying_window.layout index 25a02945ee..d3ec75ef45 100644 --- a/files/data/mygui/openmw_spell_buying_window.layout +++ b/files/data/mygui/openmw_spell_buying_window.layout @@ -1,28 +1,28 @@ - + - - - - - + + + + + - - + + - + - + diff --git a/files/data/mygui/openmw_travel_window.layout b/files/data/mygui/openmw_travel_window.layout index 96de2fc08d..03c2e713e5 100644 --- a/files/data/mygui/openmw_travel_window.layout +++ b/files/data/mygui/openmw_travel_window.layout @@ -4,18 +4,17 @@ - - - - - + - + + + + - + diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 8a78a52441..3275d2eb82 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -635,7 +635,7 @@ -- @usage local spell = core.magic.spells.records[1] -- get by index -- @usage -- Print all powers -- for _, spell in pairs(core.magic.spells.records) do --- if spell.types == core.magic.SPELL_TYPE.Power then +-- if spell.type == core.magic.SPELL_TYPE.Power then -- print(spell.name) -- end -- end diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 5aef5fac94..3802ad1492 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -808,8 +808,8 @@ -- A read-only list of all @{#CreatureRecord}s in the world database, may be indexed by recordId. -- Implements [iterables#List](iterables.html#List) of #CreatureRecord. -- @field [parent=#Creature] #list<#CreatureRecord> records --- @usage local record = types.NPC.classes['example_recordid'] --- @usage local record = types.NPC.classes[1] +-- @usage local creature = types.Creature.records['creature id'] -- get by id +-- @usage local creature = types.Creature.records[1] -- get by index --- -- Whether the object is a creature. @@ -876,8 +876,8 @@ -- A read-only list of all @{#NpcRecord}s in the world database, may be indexed by recordId. -- Implements [iterables#List](iterables.html#List) of #NpcRecord. -- @field [parent=#NPC] #map<#NpcRecord> records --- @usage local record = types.NPC.classes['example_recordid'] --- @usage local record = types.NPC.classes[1] +-- @usage local npc = types.NPC.records['npc id'] -- get by id +-- @usage local npc = types.NPC.records[1] -- get by index --- -- Whether the object is an NPC or a Player. @@ -1048,8 +1048,8 @@ -- A read-only list of all @{#ClassRecord}s in the world database, may be indexed by recordId. -- Implements [iterables#List](iterables.html#List) of #ClassRecord. -- @field [parent=#Classes] #list<#ClassRecord> records --- @usage local record = types.NPC.classes['example_recordid'] --- @usage local record = types.NPC.classes[1] +-- @usage local class = types.NPC.classes.records['class id'] -- get by id +-- @usage local class = types.NPC.classes.records[1] -- get by index --- -- Returns a read-only @{#ClassRecord} @@ -1088,8 +1088,8 @@ -- A read-only list of all @{#RaceRecord}s in the world database. -- Implements [iterables#List](iterables.html#List) of #RaceRecord. -- @field [parent=#Races] #list<#RaceRecord> records --- @usage local record = types.NPC.classes['example_recordid'] --- @usage local record = types.NPC.classes[1] +-- @usage local race = types.NPC.races.records['race id'] -- get by id +-- @usage local race = types.NPC.races.records[1] -- get by index --- -- Returns a read-only @{#RaceRecord} @@ -1275,8 +1275,8 @@ -- A read-only list of all @{#BirthSignRecord}s in the world database. -- Implements [iterables#List](iterables.html#List) of #BirthSignRecord. -- @field [parent=#BirthSigns] #list<#BirthSignRecord> records --- @usage local record = types.NPC.classes['example_recordid'] --- @usage local record = types.NPC.classes[1] +-- @usage local birthSign = types.Player.birthSigns.records['birthsign id'] -- get by id +-- @usage local birthSign = types.Player.birthSigns.records[1] -- get by index --- -- Returns a read-only @{#BirthSignRecord}