mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-29 04:20:29 +00:00
Merge branch 'master' into 'OpenCS-preserve-blocked'
# Conflicts: # CHANGELOG.md
This commit is contained in:
commit
18f5762a76
50
.github/workflows/cmake.yml
vendored
Normal file
50
.github/workflows/cmake.yml
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
name: CMake
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Add OpenMW PPA Dependancies
|
||||
run: sudo add-apt-repository ppa:openmw/openmw; sudo apt-get update
|
||||
|
||||
- name: Install Building Dependancies
|
||||
run: sudo CI/install_debian_deps.sh gcc openmw-deps openmw-deps-dynamic
|
||||
|
||||
- name: Prime ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ matrix.os }}-${{ env.BUILD_TYPE }}
|
||||
max-size: 1000M
|
||||
|
||||
- name: Configure
|
||||
run: cmake -S . -B . -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
run: cmake --build . --config ${{env.BUILD_TYPE}} --parallel 3
|
||||
|
||||
- name: Install
|
||||
shell: bash
|
||||
run: cmake --install .
|
||||
|
||||
- name: Create Artifact
|
||||
shell: bash
|
||||
working-directory: install
|
||||
run: |
|
||||
ls -laR
|
||||
7z a ../build_artifact.7z .
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
path: ./build_artifact.7z
|
||||
name: build_artifact.7z
|
@ -223,6 +223,18 @@ variables: &tests-targets
|
||||
- choco install ninja -y
|
||||
- choco install python -y
|
||||
- refreshenv
|
||||
- |
|
||||
function Make-SafeFileName {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[String]
|
||||
$FileName
|
||||
)
|
||||
[IO.Path]::GetInvalidFileNameChars() | ForEach-Object {
|
||||
$FileName = $FileName.Replace($_, '_')
|
||||
}
|
||||
return $FileName
|
||||
}
|
||||
stage: build
|
||||
script:
|
||||
- $time = (Get-Date -Format "HH:mm:ss")
|
||||
@ -237,10 +249,10 @@ variables: &tests-targets
|
||||
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
||||
- |
|
||||
if (Get-ChildItem -Recurse *.pdb) {
|
||||
7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' CI-ID.txt
|
||||
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
||||
Get-ChildItem -Recurse *.pdb | Remove-Item
|
||||
}
|
||||
- 7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}.zip '*'
|
||||
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
||||
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
||||
after_script:
|
||||
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
||||
@ -326,6 +338,18 @@ Windows_Ninja_Tests_RelWithDebInfo:
|
||||
- choco install vswhere -y
|
||||
- choco install python -y
|
||||
- refreshenv
|
||||
- |
|
||||
function Make-SafeFileName {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[String]
|
||||
$FileName
|
||||
)
|
||||
[IO.Path]::GetInvalidFileNameChars() | ForEach-Object {
|
||||
$FileName = $FileName.Replace($_, '_')
|
||||
}
|
||||
return $FileName
|
||||
}
|
||||
stage: build
|
||||
script:
|
||||
- $time = (Get-Date -Format "HH:mm:ss")
|
||||
@ -339,10 +363,10 @@ Windows_Ninja_Tests_RelWithDebInfo:
|
||||
- Get-ChildItem -Recurse *.ilk | Remove-Item
|
||||
- |
|
||||
if (Get-ChildItem -Recurse *.pdb) {
|
||||
7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' CI-ID.txt
|
||||
7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip"))" '*.pdb' CI-ID.txt
|
||||
Get-ChildItem -Recurse *.pdb | Remove-Item
|
||||
}
|
||||
- 7z a -tzip ..\..\OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}.zip '*'
|
||||
- 7z a -tzip "..\..\$(Make-SafeFileName("OpenMW_MSVC2019_64_${package}_${config}_${CI_COMMIT_REF_NAME}.zip"))" '*'
|
||||
- if ($executables) { foreach ($exe in $executables.Split(',')) { & .\$exe } }
|
||||
after_script:
|
||||
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
|
||||
|
@ -44,6 +44,7 @@ Programmers
|
||||
Austin Salgat (Salgat)
|
||||
Ben Shealy (bentsherman)
|
||||
Berulacks
|
||||
Bo Svensson
|
||||
Britt Mathis (galdor557)
|
||||
Capostrophic
|
||||
Carl Maxwell
|
||||
@ -99,6 +100,7 @@ Programmers
|
||||
James Stephens (james-h-stephens)
|
||||
Jan-Peter Nilsson (peppe)
|
||||
Jan Borsodi (am0s)
|
||||
JanuarySnow
|
||||
Jason Hooks (jhooks)
|
||||
jeaye
|
||||
jefetienne
|
||||
|
@ -7,6 +7,7 @@
|
||||
Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes
|
||||
Bug #3905: Great House Dagoth issues
|
||||
Bug #4203: Resurrecting an actor should close the loot GUI
|
||||
Bug #4602: Robert's Bodies: crash inside createInstance()
|
||||
Bug #4700: Editor: Incorrect command implementation
|
||||
Bug #4744: Invisible particles must still be processed
|
||||
Bug #4752: UpdateCellCommand doesn't undo properly
|
||||
@ -36,6 +37,7 @@
|
||||
Bug #6174: Spellmaking and Enchanting sliders differences from vanilla
|
||||
Bug #6184: Command and Calm and Demoralize and Frenzy and Rally magic effects inconsistencies with vanilla
|
||||
Bug #6197: Infinite Casting Loop
|
||||
Bug #6273: Respawning NPCs rotation is inconsistent
|
||||
Feature #2554: Modifying an object triggers the instances table to scroll to the corresponding record
|
||||
Feature #2780: A way to see current OpenMW version in the console
|
||||
Feature #3616: Allow Zoom levels on the World Map
|
||||
@ -47,7 +49,11 @@
|
||||
Feature #6032: Reverse-z depth buffer
|
||||
Feature #6162: Refactor GUI to use shaders and to be GLES and GL3+ friendly
|
||||
Feature #6199: Support FBO Rendering
|
||||
Editor: Preserve the "blocked" record flag for referenceable objects.
|
||||
Feature #6251: OpenMW-CS: Set instance movement based on camera zoom
|
||||
Feature #6288: Preserve the "blocked" record flag for referenceable objects.
|
||||
Task #6201: Remove the "Note: No relevant classes found. No output generated" warnings
|
||||
Task #6264: Remove the old classes in animation.cpp
|
||||
|
||||
|
||||
0.47.0
|
||||
------
|
||||
|
@ -14,6 +14,12 @@ if [[ "${BUILD_TESTS_ONLY}" ]]; then
|
||||
BUILD_BENCHMARKS=ON
|
||||
fi
|
||||
|
||||
CXX_FLAGS='-Werror -Wno-error=deprecated-declarations -Wno-error=nonnull -Wno-error=deprecated-copy'
|
||||
|
||||
if [[ "${CXX}" == 'clang++' ]]; then
|
||||
CXX_FLAGS="${CXX_FLAGS} -Wno-error=unused-lambda-capture -Wno-error=gnu-zero-variadic-macro-arguments"
|
||||
fi
|
||||
|
||||
declare -a CMAKE_CONF_OPTS=(
|
||||
-DCMAKE_C_COMPILER="${CC:-/usr/bin/cc}"
|
||||
-DCMAKE_CXX_COMPILER="${CXX:-/usr/bin/c++}"
|
||||
@ -24,6 +30,8 @@ declare -a CMAKE_CONF_OPTS=(
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DUSE_SYSTEM_TINYXML=ON
|
||||
-DCMAKE_INSTALL_PREFIX=install
|
||||
-DCMAKE_C_FLAGS='-Werror'
|
||||
-DCMAKE_CXX_FLAGS="${CXX_FLAGS}"
|
||||
)
|
||||
|
||||
if [[ $CI_OPENMW_USE_STATIC_DEPS ]]; then
|
||||
|
@ -13,6 +13,11 @@ if(POLICY CMP0083)
|
||||
cmake_policy(SET CMP0083 NEW)
|
||||
endif()
|
||||
|
||||
# to link with freetype library
|
||||
if(POLICY CMP0079)
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
endif()
|
||||
|
||||
option(OPENMW_GL4ES_MANUAL_INIT "Manually initialize gl4es. This is more reliable on platforms without a windowing system. Requires gl4es to be configured with -DNOEGL=ON -DNO_LOADER=ON -DNO_INIT_CONSTRUCTOR=ON." OFF)
|
||||
if(OPENMW_GL4ES_MANUAL_INIT)
|
||||
add_definitions(-DOPENMW_GL4ES_MANUAL_INIT)
|
||||
@ -202,8 +207,6 @@ if (USE_QT)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5OpenGL REQUIRED)
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
#set(CMAKE_AUTOMOC ON)
|
||||
endif()
|
||||
|
||||
set(USED_OSG_COMPONENTS
|
||||
@ -512,7 +515,7 @@ endif()
|
||||
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -pedantic -Wno-long-long")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wundef -Wno-unused-parameter -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
|
||||
add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS=ON )
|
||||
|
||||
if (APPLE)
|
||||
|
@ -36,23 +36,6 @@ set(LAUNCHER_HEADER
|
||||
)
|
||||
|
||||
# Headers that must be pre-processed
|
||||
set(LAUNCHER_HEADER_MOC
|
||||
datafilespage.hpp
|
||||
graphicspage.hpp
|
||||
maindialog.hpp
|
||||
playpage.hpp
|
||||
textslotmsgbox.hpp
|
||||
settingspage.hpp
|
||||
advancedpage.hpp
|
||||
|
||||
utils/cellnameloader.hpp
|
||||
utils/textinputdialog.hpp
|
||||
utils/profilescombobox.hpp
|
||||
utils/lineedit.hpp
|
||||
utils/openalutil.hpp
|
||||
|
||||
)
|
||||
|
||||
set(LAUNCHER_UI
|
||||
${CMAKE_SOURCE_DIR}/files/ui/datafilespage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/graphicspage.ui
|
||||
@ -74,7 +57,6 @@ if(WIN32)
|
||||
endif(WIN32)
|
||||
|
||||
QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
||||
QT5_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||
QT5_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
@ -109,4 +91,7 @@ if (BUILD_WITH_CODE_COVERAGE)
|
||||
target_link_libraries(openmw-launcher gcov)
|
||||
endif()
|
||||
|
||||
if(USE_QT)
|
||||
set_property(TARGET openmw-launcher PROPERTY AUTOMOC ON)
|
||||
endif(USE_QT)
|
||||
|
||||
|
@ -52,11 +52,8 @@ void readVFS(VFS::Archive* anArchive,std::string archivePath = "")
|
||||
myManager.addArchive(anArchive);
|
||||
myManager.buildIndex();
|
||||
|
||||
std::map<std::string, VFS::File*> files=myManager.getIndex();
|
||||
for(auto it=files.begin(); it!=files.end(); ++it)
|
||||
for(const auto& name : myManager.getRecursiveDirectoryIterator(""))
|
||||
{
|
||||
std::string name = it->first;
|
||||
|
||||
try{
|
||||
if(isNIF(name))
|
||||
{
|
||||
|
@ -8,11 +8,11 @@ opencs_units (model/doc
|
||||
document operation saving documentmanager loader runner operationholder
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/doc
|
||||
opencs_units (model/doc
|
||||
stage savingstate savingstages blacklist messages
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/doc
|
||||
opencs_hdrs (model/doc
|
||||
state
|
||||
)
|
||||
|
||||
@ -23,14 +23,14 @@ opencs_units (model/world
|
||||
)
|
||||
|
||||
|
||||
opencs_units_noqt (model/world
|
||||
opencs_units (model/world
|
||||
universalid record commands columnbase columnimp scriptcontext cell refidcollection
|
||||
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
|
||||
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
|
||||
idcompletionmanager metadata defaultgmsts infoselectwrapper commandmacro
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/world
|
||||
opencs_hdrs (model/world
|
||||
columnimp idcollection collection info subcellcollection
|
||||
)
|
||||
|
||||
@ -39,14 +39,14 @@ opencs_units (model/tools
|
||||
tools reportmodel mergeoperation
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/tools
|
||||
opencs_units (model/tools
|
||||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
|
||||
startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck
|
||||
mergestages gmstcheck topicinfocheck journalcheck enchantmentcheck
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/tools
|
||||
opencs_hdrs (model/tools
|
||||
mergestate
|
||||
)
|
||||
|
||||
@ -57,11 +57,11 @@ opencs_units (view/doc
|
||||
)
|
||||
|
||||
|
||||
opencs_units_noqt (view/doc
|
||||
opencs_units (view/doc
|
||||
subviewfactory
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (view/doc
|
||||
opencs_hdrs (view/doc
|
||||
subviewfactoryimp
|
||||
)
|
||||
|
||||
@ -74,7 +74,7 @@ opencs_units (view/world
|
||||
bodypartcreator landtexturecreator landcreator
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/world
|
||||
opencs_units (view/world
|
||||
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||
scripthighlighter idvalidator dialoguecreator idcompletiondelegate
|
||||
colordelegate dragdroputils
|
||||
@ -92,12 +92,12 @@ opencs_units (view/render
|
||||
cellwater terraintexturemode actor terrainselection terrainshapemode brushdraw commands
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/render
|
||||
opencs_units (view/render
|
||||
lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase
|
||||
cellarrow cellmarker cellborder pathgrid
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (view/render
|
||||
opencs_hdrs (view/render
|
||||
mask
|
||||
)
|
||||
|
||||
@ -106,7 +106,7 @@ opencs_units (view/tools
|
||||
reportsubview reporttable searchsubview searchbox merge
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/tools
|
||||
opencs_units (view/tools
|
||||
subviews
|
||||
)
|
||||
|
||||
@ -119,11 +119,11 @@ opencs_units (model/prefs
|
||||
shortcuteventhandler shortcutmanager shortcutsetting modifiersetting stringsetting
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/prefs
|
||||
opencs_units (model/prefs
|
||||
category
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/filter
|
||||
opencs_units (model/filter
|
||||
node unarynode narynode leafnode booleannode parser andnode ornode notnode textnode valuenode
|
||||
)
|
||||
|
||||
@ -150,7 +150,6 @@ if(WIN32)
|
||||
endif(WIN32)
|
||||
|
||||
qt5_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||
qt5_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
||||
qt5_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||
|
||||
# for compiled .ui files
|
||||
@ -232,31 +231,6 @@ target_link_libraries(openmw-cs
|
||||
components_qt
|
||||
)
|
||||
|
||||
if(OSG_STATIC)
|
||||
unset(_osg_plugins_static_files)
|
||||
add_library(openmw_cs_osg_plugins INTERFACE)
|
||||
foreach(_plugin ${USED_OSG_PLUGINS})
|
||||
string(TOUPPER ${_plugin} _plugin_uc)
|
||||
if(OPENMW_USE_SYSTEM_OSG)
|
||||
list(APPEND _osg_plugins_static_files ${${_plugin_uc}_LIBRARY})
|
||||
else()
|
||||
list(APPEND _osg_plugins_static_files $<TARGET_FILE:${${_plugin_uc}_LIBRARY}>)
|
||||
target_link_libraries(openmw_cs_osg_plugins INTERFACE $<TARGET_PROPERTY:${${_plugin_uc}_LIBRARY},LINK_LIBRARIES>)
|
||||
add_dependencies(openmw_cs_osg_plugins ${${_plugin_uc}_LIBRARY})
|
||||
endif()
|
||||
endforeach()
|
||||
# We use --whole-archive because OSG plugins use registration.
|
||||
get_whole_archive_options(_opts ${_osg_plugins_static_files})
|
||||
target_link_options(openmw_cs_osg_plugins INTERFACE ${_opts})
|
||||
target_link_libraries(openmw-cs openmw_cs_osg_plugins)
|
||||
|
||||
if(OPENMW_USE_SYSTEM_OSG)
|
||||
# OSG plugin pkgconfig files are missing these dependencies.
|
||||
# https://github.com/openscenegraph/OpenSceneGraph/issues/1052
|
||||
target_link_libraries(openmw freetype jpeg png)
|
||||
endif()
|
||||
endif(OSG_STATIC)
|
||||
|
||||
target_link_libraries(openmw-cs Qt5::Widgets Qt5::Core Qt5::Network Qt5::OpenGL)
|
||||
|
||||
if (WIN32)
|
||||
@ -284,3 +258,7 @@ endif (MSVC)
|
||||
if(APPLE)
|
||||
INSTALL(TARGETS openmw-cs BUNDLE DESTINATION "." COMPONENT Bundle)
|
||||
endif()
|
||||
|
||||
if(USE_QT)
|
||||
set_property(TARGET openmw-cs PROPERTY AUTOMOC ON)
|
||||
endif(USE_QT)
|
||||
|
@ -9,6 +9,9 @@
|
||||
|
||||
#include "data.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
const std::string& ActorAdapter::RaceData::getId() const
|
||||
@ -121,7 +124,7 @@ namespace CSMWorld
|
||||
return SceneUtil::getActorSkeleton(firstPerson, mFemale, beast, werewolf);
|
||||
}
|
||||
|
||||
const std::string ActorAdapter::ActorData::getPart(ESM::PartReferenceType index) const
|
||||
std::string_view ActorAdapter::ActorData::getPart(ESM::PartReferenceType index) const
|
||||
{
|
||||
auto it = mParts.find(index);
|
||||
if (it == mParts.end())
|
||||
@ -131,7 +134,7 @@ namespace CSMWorld
|
||||
if (mFemale)
|
||||
{
|
||||
// Note: we should use male parts for females as fallback
|
||||
const std::string femalePart = mRaceData->getFemalePart(index);
|
||||
const std::string& femalePart = mRaceData->getFemalePart(index);
|
||||
if (!femalePart.empty())
|
||||
return femalePart;
|
||||
}
|
||||
@ -139,11 +142,10 @@ namespace CSMWorld
|
||||
return mRaceData->getMalePart(index);
|
||||
}
|
||||
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::string& partName = it->second.first;
|
||||
return partName;
|
||||
return it->second.first;
|
||||
}
|
||||
|
||||
bool ActorAdapter::ActorData::hasDependency(const std::string& id) const
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <QObject>
|
||||
#include <QModelIndex>
|
||||
@ -93,7 +95,7 @@ namespace CSMWorld
|
||||
/// Returns the skeleton the actor should use for attaching parts to
|
||||
std::string getSkeleton() const;
|
||||
/// Retrieves the associated actor part
|
||||
const std::string getPart(ESM::PartReferenceType index) const;
|
||||
std::string_view getPart(ESM::PartReferenceType index) const;
|
||||
/// Checks if the actor has a data dependency
|
||||
bool hasDependency(const std::string& id) const;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
@ -153,7 +154,7 @@ namespace CSMWorld
|
||||
///< Change the state of a record from base to modified, if it is not already.
|
||||
/// \return True if the record was changed.
|
||||
|
||||
int searchId (const std::string& id) const override;
|
||||
int searchId(std::string_view id) const override;
|
||||
////< Search record with \a id.
|
||||
/// \return index of record (if found) or -1 (not found)
|
||||
|
||||
@ -476,7 +477,7 @@ namespace CSMWorld
|
||||
}
|
||||
|
||||
template<typename ESXRecordT, typename IdAccessorT>
|
||||
int Collection<ESXRecordT, IdAccessorT>::searchId (const std::string& id) const
|
||||
int Collection<ESXRecordT, IdAccessorT>::searchId(std::string_view id) const
|
||||
{
|
||||
std::string id2 = Misc::StringUtils::lowerCase(id);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include "universalid.hpp"
|
||||
#include "columns.hpp"
|
||||
@ -61,7 +62,7 @@ namespace CSMWorld
|
||||
UniversalId::Type type = UniversalId::Type_None) = 0;
|
||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||
|
||||
virtual int searchId (const std::string& id) const = 0;
|
||||
virtual int searchId(std::string_view id) const = 0;
|
||||
////< Search record with \a id.
|
||||
/// \return index of record (if found) or -1 (not found)
|
||||
|
||||
|
@ -392,7 +392,7 @@ int CSMWorld::Columns::getId (const std::string& name)
|
||||
std::string name2 = Misc::StringUtils::lowerCase (name);
|
||||
|
||||
for (int i=0; sNames[i].mName; ++i)
|
||||
if (Misc::StringUtils::ciEqual(sNames[i].mName, name2))
|
||||
if (Misc::StringUtils::ciEqual(std::string_view(sNames[i].mName), name2))
|
||||
return sNames[i].mId;
|
||||
|
||||
return -1;
|
||||
|
@ -97,7 +97,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
|
||||
}
|
||||
}
|
||||
|
||||
int CSMWorld::InfoCollection::getInfoIndex (const std::string& id, const std::string& topic) const
|
||||
int CSMWorld::InfoCollection::getInfoIndex(std::string_view id, std::string_view topic) const
|
||||
{
|
||||
// find the topic first
|
||||
std::unordered_map<std::string, std::vector<std::pair<std::string, int> > >::const_iterator iter
|
||||
@ -345,12 +345,12 @@ void CSMWorld::InfoCollection::appendBlankRecord (const std::string& id, Univer
|
||||
insertRecord(std::move(record2), getInsertIndex(id, type, nullptr), type); // call InfoCollection::insertRecord()
|
||||
}
|
||||
|
||||
int CSMWorld::InfoCollection::searchId (const std::string& id) const
|
||||
int CSMWorld::InfoCollection::searchId(std::string_view id) const
|
||||
{
|
||||
std::string::size_type separator = id.find_last_of('#');
|
||||
|
||||
if (separator == std::string::npos)
|
||||
throw std::runtime_error("invalid info ID: " + id);
|
||||
throw std::runtime_error("invalid info ID: " + std::string(id));
|
||||
|
||||
return getInfoIndex(id.substr(separator+1), id.substr(0, separator));
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define CSM_WOLRD_INFOCOLLECTION_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
|
||||
#include "collection.hpp"
|
||||
#include "info.hpp"
|
||||
@ -43,7 +44,7 @@ namespace CSMWorld
|
||||
|
||||
void load (const Info& record, bool base);
|
||||
|
||||
int getInfoIndex (const std::string& id, const std::string& topic) const;
|
||||
int getInfoIndex(std::string_view id, std::string_view topic) const;
|
||||
///< Return index for record \a id or -1 (if not present; deleted records are considered)
|
||||
///
|
||||
/// \param id info ID without topic prefix
|
||||
@ -79,7 +80,7 @@ namespace CSMWorld
|
||||
void appendBlankRecord (const std::string& id,
|
||||
UniversalId::Type type = UniversalId::Type_None) override;
|
||||
|
||||
int searchId (const std::string& id) const override;
|
||||
int searchId(std::string_view id) const override;
|
||||
|
||||
void appendRecord (std::unique_ptr<RecordBase> record,
|
||||
UniversalId::Type type = UniversalId::Type_None) override;
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "universalid.hpp"
|
||||
#include "record.hpp"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
template<>
|
||||
@ -261,7 +263,7 @@ void CSMWorld::RefCollection::cloneRecord (const std::string& origin,
|
||||
insertRecord(std::move(copy), getAppendIndex(destination, type)); // call RefCollection::insertRecord()
|
||||
}
|
||||
|
||||
int CSMWorld::RefCollection::searchId (const std::string& id) const
|
||||
int CSMWorld::RefCollection::searchId(std::string_view id) const
|
||||
{
|
||||
return searchId(extractIdNum(id));
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define CSM_WOLRD_REFCOLLECTION_H
|
||||
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
@ -56,7 +57,7 @@ namespace CSMWorld
|
||||
const std::string& destination,
|
||||
const UniversalId::Type type);
|
||||
|
||||
virtual int searchId (const std::string& id) const;
|
||||
virtual int searchId(std::string_view id) const;
|
||||
|
||||
virtual void appendRecord (std::unique_ptr<RecordBase> record,
|
||||
UniversalId::Type type = UniversalId::Type_None);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
@ -790,7 +791,7 @@ void CSMWorld::RefIdCollection::appendBlankRecord (const std::string& id, Univer
|
||||
mData.appendRecord (type, id, false);
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdCollection::searchId (const std::string& id) const
|
||||
int CSMWorld::RefIdCollection::searchId(std::string_view id) const
|
||||
{
|
||||
RefIdData::LocalIndex localIndex = mData.searchId (id);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <string_view>
|
||||
|
||||
#include "columnbase.hpp"
|
||||
#include "collectionbase.hpp"
|
||||
@ -85,7 +86,7 @@ namespace CSMWorld
|
||||
void appendBlankRecord (const std::string& id, UniversalId::Type type) override;
|
||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||
|
||||
int searchId (const std::string& id) const override;
|
||||
int searchId(std::string_view id) const override;
|
||||
////< Search record with \a id.
|
||||
/// \return index of record (if found) or -1 (not found)
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
|
||||
|
||||
@ -74,8 +75,7 @@ int CSMWorld::RefIdData::localToGlobalIndex (const LocalIndex& index)
|
||||
return globalIndex;
|
||||
}
|
||||
|
||||
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId (
|
||||
const std::string& id) const
|
||||
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId(std::string_view id) const
|
||||
{
|
||||
std::string id2 = Misc::StringUtils::lowerCase (id);
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <string_view>
|
||||
|
||||
#include <components/esm/loadacti.hpp>
|
||||
#include <components/esm/loadalch.hpp>
|
||||
@ -277,7 +278,7 @@ namespace CSMWorld
|
||||
|
||||
int localToGlobalIndex (const LocalIndex& index) const;
|
||||
|
||||
LocalIndex searchId (const std::string& id) const;
|
||||
LocalIndex searchId(std::string_view id) const;
|
||||
|
||||
void erase (int index, int count);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
@ -22,10 +23,8 @@ void CSMWorld::Resources::recreate(const VFS::Manager* vfs, const char * const *
|
||||
|
||||
size_t baseSize = mBaseDirectory.size();
|
||||
|
||||
const std::map<std::string, VFS::File*>& index = vfs->getIndex();
|
||||
for (std::map<std::string, VFS::File*>::const_iterator it = index.begin(); it != index.end(); ++it)
|
||||
for (const auto& filepath : vfs->getRecursiveDirectoryIterator(""))
|
||||
{
|
||||
std::string filepath = it->first;
|
||||
if (filepath.size()<baseSize+1 ||
|
||||
filepath.substr (0, baseSize)!=mBaseDirectory ||
|
||||
(filepath[baseSize]!='/' && filepath[baseSize]!='\\'))
|
||||
@ -83,7 +82,7 @@ int CSMWorld::Resources::getIndex (const std::string& id) const
|
||||
return index;
|
||||
}
|
||||
|
||||
int CSMWorld::Resources::searchId (const std::string& id) const
|
||||
int CSMWorld::Resources::searchId(std::string_view id) const
|
||||
{
|
||||
std::string id2 = Misc::StringUtils::lowerCase (id);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
|
||||
#include "universalid.hpp"
|
||||
|
||||
@ -35,7 +36,7 @@ namespace CSMWorld
|
||||
|
||||
int getIndex (const std::string& id) const;
|
||||
|
||||
int searchId (const std::string& id) const;
|
||||
int searchId(std::string_view id) const;
|
||||
|
||||
UniversalId::Type getType() const;
|
||||
};
|
||||
|
@ -96,7 +96,7 @@ namespace CSVRender
|
||||
for (int i = 0; i < ESM::PRT_Count; ++i)
|
||||
{
|
||||
auto type = (ESM::PartReferenceType) i;
|
||||
std::string partId = mActorData->getPart(type);
|
||||
const std::string_view partId = mActorData->getPart(type);
|
||||
attachBodyPart(type, getBodyPartMesh(partId));
|
||||
}
|
||||
}
|
||||
@ -115,7 +115,7 @@ namespace CSVRender
|
||||
}
|
||||
}
|
||||
|
||||
std::string Actor::getBodyPartMesh(const std::string& bodyPartId)
|
||||
std::string Actor::getBodyPartMesh(std::string_view bodyPartId)
|
||||
{
|
||||
const auto& bodyParts = mData.getBodyParts();
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define OPENCS_VIEW_RENDER_ACTOR_H
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
@ -54,7 +55,7 @@ namespace CSVRender
|
||||
void loadBodyParts();
|
||||
void attachBodyPart(ESM::PartReferenceType, const std::string& mesh);
|
||||
|
||||
std::string getBodyPartMesh(const std::string& bodyPartId);
|
||||
std::string getBodyPartMesh(std::string_view bodyPartId);
|
||||
|
||||
static const std::string MeshPrefix;
|
||||
|
||||
|
@ -297,6 +297,8 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
||||
return false;
|
||||
}
|
||||
|
||||
mObjectsAtDragStart.clear();
|
||||
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
|
||||
iter!=selection.end(); ++iter)
|
||||
{
|
||||
@ -305,6 +307,12 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
||||
if (mSubModeId == "move")
|
||||
{
|
||||
objectTag->mObject->setEdited (Object::Override_Position);
|
||||
float x = objectTag->mObject->getPosition().pos[0];
|
||||
float y = objectTag->mObject->getPosition().pos[1];
|
||||
float z = objectTag->mObject->getPosition().pos[2];
|
||||
osg::Vec3f thisPoint(x, y, z);
|
||||
mDragStart = getMousePlaneCoords(pos, getProjectionSpaceCoords(thisPoint));
|
||||
mObjectsAtDragStart.emplace_back(thisPoint);
|
||||
mDragMode = DragMode_Move;
|
||||
}
|
||||
else if (mSubModeId == "rotate")
|
||||
@ -392,29 +400,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
||||
|
||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
|
||||
if (mDragMode == DragMode_Move)
|
||||
{
|
||||
osg::Vec3f eye, centre, up;
|
||||
getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up);
|
||||
|
||||
if (diffY)
|
||||
{
|
||||
offset += up * diffY * speedFactor;
|
||||
}
|
||||
if (diffX)
|
||||
{
|
||||
offset += ((centre-eye) ^ up) * diffX * speedFactor;
|
||||
}
|
||||
|
||||
if (mDragAxis!=-1)
|
||||
{
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
if (i!=mDragAxis)
|
||||
offset[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDragMode == DragMode_Move) {}
|
||||
else if (mDragMode == DragMode_Rotate)
|
||||
{
|
||||
osg::Vec3f eye, centre, up;
|
||||
@ -514,17 +500,32 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
||||
return;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
// Apply
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin()); iter!=selection.end(); ++iter)
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin()); iter!=selection.end(); ++iter, i++)
|
||||
{
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
|
||||
{
|
||||
if (mDragMode == DragMode_Move)
|
||||
{
|
||||
ESM::Position position = objectTag->mObject->getPosition();
|
||||
for (int i=0; i<3; ++i)
|
||||
osg::Vec3f mousePos = getMousePlaneCoords(pos, getProjectionSpaceCoords(mDragStart));
|
||||
float addToX = mousePos.x() - mDragStart.x();
|
||||
float addToY = mousePos.y() - mDragStart.y();
|
||||
float addToZ = mousePos.z() - mDragStart.z();
|
||||
position.pos[0] = mObjectsAtDragStart[i].x() + addToX;
|
||||
position.pos[1] = mObjectsAtDragStart[i].y() + addToY;
|
||||
position.pos[2] = mObjectsAtDragStart[i].z() + addToZ;
|
||||
|
||||
// XYZ-locking
|
||||
if (mDragAxis != -1)
|
||||
{
|
||||
position.pos[i] += offset[i];
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
if (j != mDragAxis)
|
||||
position.pos[j] = mObjectsAtDragStart[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
objectTag->mObject->setPosition(position.pos);
|
||||
@ -608,6 +609,7 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
||||
}
|
||||
}
|
||||
|
||||
mObjectsAtDragStart.clear();
|
||||
mDragMode = DragMode_None;
|
||||
}
|
||||
|
||||
@ -634,8 +636,10 @@ void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
|
||||
std::vector<osg::ref_ptr<TagBase> > selection =
|
||||
getWorldspaceWidget().getEdited (Mask_Reference);
|
||||
|
||||
int j = 0;
|
||||
|
||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
|
||||
iter!=selection.end(); ++iter)
|
||||
iter!=selection.end(); ++iter, j++)
|
||||
{
|
||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
|
||||
{
|
||||
@ -643,6 +647,9 @@ void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
|
||||
for (int i=0; i<3; ++i)
|
||||
position.pos[i] += offset[i];
|
||||
objectTag->mObject->setPosition (position.pos);
|
||||
osg::Vec3f thisPoint(position.pos[0], position.pos[1], position.pos[2]);
|
||||
mDragStart = getMousePlaneCoords(getWorldspaceWidget().mapFromGlobal(QCursor::pos()), getProjectionSpaceCoords(thisPoint));
|
||||
mObjectsAtDragStart[j] = thisPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ namespace CSVRender
|
||||
bool mLocked;
|
||||
float mUnitScaleDist;
|
||||
osg::ref_ptr<osg::Group> mParentNode;
|
||||
osg::Vec3f mDragStart;
|
||||
std::vector<osg::Vec3f> mObjectsAtDragStart;
|
||||
|
||||
int getSubModeFromId (const std::string& id) const;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef CSV_TOOLS_REPORTTABLE_H
|
||||
#define CSV_TOOLS_REPORTTABLE_H
|
||||
#ifndef CSV_TOOLS_MERGE_H
|
||||
#define CSV_TOOLS_MERGE_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
|
@ -36,7 +36,7 @@ void CSVTools::SearchSubView::replace (bool selection)
|
||||
// in a single string.
|
||||
for (std::vector<int>::const_reverse_iterator iter (indices.rbegin()); iter!=indices.rend(); ++iter)
|
||||
{
|
||||
CSMWorld::UniversalId id = model.getUniversalId (*iter);
|
||||
const CSMWorld::UniversalId& id = model.getUniversalId (*iter);
|
||||
|
||||
CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::getParentType (id.getType());
|
||||
|
||||
|
@ -22,7 +22,8 @@ CSVWorld::ReferenceableCreator::ReferenceableCreator (CSMWorld::Data& data, QUnd
|
||||
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listReferenceableTypes();
|
||||
|
||||
mType = new QComboBox (this);
|
||||
|
||||
mType->setMaxVisibleItems(20);
|
||||
|
||||
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
|
||||
iter!=types.end(); ++iter)
|
||||
{
|
||||
@ -31,7 +32,9 @@ CSVWorld::ReferenceableCreator::ReferenceableCreator (CSMWorld::Data& data, QUnd
|
||||
mType->addItem (QIcon (id2.getIcon().c_str()), id2.getTypeName().c_str(),
|
||||
static_cast<int> (id2.getType()));
|
||||
}
|
||||
|
||||
|
||||
mType->model()->sort(0);
|
||||
|
||||
insertBeforeButtons (mType, false);
|
||||
|
||||
connect (mType, SIGNAL (currentIndexChanged (int)), this, SLOT (setType (int)));
|
||||
|
@ -155,31 +155,6 @@ target_link_libraries(openmw
|
||||
${LUA_LIBRARIES}
|
||||
)
|
||||
|
||||
if(OSG_STATIC)
|
||||
unset(_osg_plugins_static_files)
|
||||
add_library(openmw_osg_plugins INTERFACE)
|
||||
foreach(_plugin ${USED_OSG_PLUGINS})
|
||||
string(TOUPPER ${_plugin} _plugin_uc)
|
||||
if(OPENMW_USE_SYSTEM_OSG)
|
||||
list(APPEND _osg_plugins_static_files ${${_plugin_uc}_LIBRARY})
|
||||
else()
|
||||
list(APPEND _osg_plugins_static_files $<TARGET_FILE:${${_plugin_uc}_LIBRARY}>)
|
||||
target_link_libraries(openmw_osg_plugins INTERFACE $<TARGET_PROPERTY:${${_plugin_uc}_LIBRARY},LINK_LIBRARIES>)
|
||||
add_dependencies(openmw_osg_plugins ${${_plugin_uc}_LIBRARY})
|
||||
endif()
|
||||
endforeach()
|
||||
# We use --whole-archive because OSG plugins use registration.
|
||||
get_whole_archive_options(_opts ${_osg_plugins_static_files})
|
||||
target_link_options(openmw_osg_plugins INTERFACE ${_opts})
|
||||
target_link_libraries(openmw openmw_osg_plugins)
|
||||
|
||||
if(OPENMW_USE_SYSTEM_OSG)
|
||||
# OSG plugin pkgconfig files are missing these dependencies.
|
||||
# https://github.com/openscenegraph/OpenSceneGraph/issues/1052
|
||||
target_link_libraries(openmw freetype jpeg png)
|
||||
endif()
|
||||
endif(OSG_STATIC)
|
||||
|
||||
if (ANDROID)
|
||||
target_link_libraries(openmw EGL android log z)
|
||||
endif (ANDROID)
|
||||
|
@ -521,7 +521,7 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
||||
throw std::runtime_error ("No default settings file found! Make sure the file \"defaults.bin\" was properly installed.");
|
||||
|
||||
// load user settings if they exist
|
||||
const std::string settingspath = (mCfgMgr.getUserConfigPath() / "settings.cfg").string();
|
||||
std::string settingspath = (mCfgMgr.getUserConfigPath() / "settings.cfg").string();
|
||||
if (boost::filesystem::exists(settingspath))
|
||||
settings.loadUser(settingspath);
|
||||
|
||||
|
@ -846,6 +846,7 @@ namespace MWClass
|
||||
|
||||
// Reset to original position
|
||||
MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().getPosition().asVec3());
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr, ptr.getCellRef().getPosition().asRotationVec3(), MWBase::RotationFlag_none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1397,6 +1397,7 @@ namespace MWClass
|
||||
|
||||
// Reset to original position
|
||||
MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().getPosition().asVec3());
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr, ptr.getCellRef().getPosition().asRotationVec3(), MWBase::RotationFlag_none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -491,7 +491,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
{
|
||||
add_partial_text();
|
||||
stream.consume ();
|
||||
mLine = nullptr, mRun = nullptr;
|
||||
mLine = nullptr;
|
||||
mRun = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -551,7 +552,9 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
|
||||
if (left + space_width + word_width > mPageWidth)
|
||||
{
|
||||
mLine = nullptr, mRun = nullptr, left = 0;
|
||||
mLine = nullptr;
|
||||
mRun = nullptr;
|
||||
left = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -517,6 +517,7 @@ namespace MWGui
|
||||
std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMajorSkills() const
|
||||
{
|
||||
std::vector<ESM::Skill::SkillEnum> v;
|
||||
v.reserve(5);
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
v.push_back(mMajorSkill[i]->getSkillId());
|
||||
@ -527,6 +528,7 @@ namespace MWGui
|
||||
std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMinorSkills() const
|
||||
{
|
||||
std::vector<ESM::Skill::SkillEnum> v;
|
||||
v.reserve(5);
|
||||
for(int i=0; i < 5; i++)
|
||||
{
|
||||
v.push_back(mMinorSkill[i]->getSkillId());
|
||||
|
@ -704,7 +704,7 @@ namespace MWGui
|
||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(GW_Inventory))
|
||||
return;
|
||||
// make sure the object is of a type that can be picked up
|
||||
std::string type = object.getTypeName();
|
||||
const std::string& type = object.getTypeName();
|
||||
if ( (type != typeid(ESM::Apparatus).name())
|
||||
&& (type != typeid(ESM::Armor).name())
|
||||
&& (type != typeid(ESM::Book).name())
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/myguiplatform/myguitexture.hpp>
|
||||
@ -66,35 +67,15 @@ namespace MWGui
|
||||
|
||||
void LoadingScreen::findSplashScreens()
|
||||
{
|
||||
const std::map<std::string, VFS::File*>& index = mResourceSystem->getVFS()->getIndex();
|
||||
std::string pattern = "Splash/";
|
||||
mResourceSystem->getVFS()->normalizeFilename(pattern);
|
||||
auto isSupportedExtension = [](const std::string_view& ext) {
|
||||
static const std::array<std::string, 7> supported_extensions{ {"tga", "dds", "ktx", "png", "bmp", "jpeg", "jpg"} };
|
||||
return !ext.empty() && std::find(supported_extensions.begin(), supported_extensions.end(), ext) != supported_extensions.end();
|
||||
};
|
||||
|
||||
/* priority given to the left */
|
||||
const std::array<std::string, 7> supported_extensions {{".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}};
|
||||
|
||||
auto found = index.lower_bound(pattern);
|
||||
while (found != index.end())
|
||||
for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator("Splash/"))
|
||||
{
|
||||
const std::string& name = found->first;
|
||||
if (name.size() >= pattern.size() && name.substr(0, pattern.size()) == pattern)
|
||||
{
|
||||
size_t pos = name.find_last_of('.');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
for(auto const& extension: supported_extensions)
|
||||
{
|
||||
if (name.compare(pos, name.size() - pos, extension) == 0)
|
||||
{
|
||||
mSplashScreens.push_back(found->first);
|
||||
break; /* based on priority */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
++found;
|
||||
if (isSupportedExtension(Misc::getFileExtension(name)))
|
||||
mSplashScreens.push_back(name);
|
||||
}
|
||||
if (mSplashScreens.empty())
|
||||
Log(Debug::Warning) << "Warning: no splash screens found!";
|
||||
|
@ -988,7 +988,8 @@ namespace MWGui
|
||||
if (mInterior)
|
||||
{
|
||||
auto pos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition();
|
||||
x = pos.x(), y = pos.y();
|
||||
x = pos.x();
|
||||
y = pos.y();
|
||||
}
|
||||
setGlobalMapPlayerPosition(x, y);
|
||||
|
||||
@ -1160,7 +1161,8 @@ namespace MWGui
|
||||
void MapWindow::worldPosToGlobalMapImageSpace(float x, float y, float& imageX, float& imageY) const
|
||||
{
|
||||
mGlobalMapRender->worldPosToImageSpace(x, y, imageX, imageY);
|
||||
imageX *= mGlobalMapZoom, imageY *= mGlobalMapZoom;
|
||||
imageX *= mGlobalMapZoom;
|
||||
imageY *= mGlobalMapZoom;
|
||||
}
|
||||
|
||||
void MapWindow::updateCustomMarkers()
|
||||
|
@ -376,7 +376,9 @@ namespace MWGui
|
||||
{
|
||||
for (const std::string& keyword : keywords)
|
||||
{
|
||||
if(Misc::StringUtils::ciEqual(MyGUI::LanguageManager::getInstance().replaceTags("#{" + keyword + "}"), button->getCaption()))
|
||||
if (Misc::StringUtils::ciEqual(
|
||||
MyGUI::LanguageManager::getInstance().replaceTags("#{" + keyword + "}").asUTF8(),
|
||||
button->getCaption().asUTF8()))
|
||||
{
|
||||
return button;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace MWLua
|
||||
else
|
||||
{
|
||||
const std::string& recordId = std::get<std::string>(item);
|
||||
if (old_it != store.end() && *old_it->getCellRef().getRefIdPtr() == recordId)
|
||||
if (old_it != store.end() && old_it->getCellRef().getRefIdRef() == recordId)
|
||||
return true; // already equipped
|
||||
itemPtr = store.search(recordId);
|
||||
if (itemPtr.isEmpty() || itemPtr.getRefData().getCount() == 0)
|
||||
|
@ -284,7 +284,7 @@ namespace MWLua
|
||||
std::shared_ptr<LocalScripts> scripts;
|
||||
// When loading a game, it can be called before LuaManager::setPlayer,
|
||||
// so we can't just check ptr == mPlayer here.
|
||||
if (*ptr.getCellRef().getRefIdPtr() == "player")
|
||||
if (ptr.getCellRef().getRefIdRef() == "player")
|
||||
{
|
||||
scripts = std::make_shared<PlayerScripts>(&mLua, LObject(getId(ptr), mWorldView.getObjectRegistry()));
|
||||
scripts->addPackage("openmw.ui", mUserInterfacePackage);
|
||||
|
@ -51,13 +51,13 @@ namespace MWLua
|
||||
|
||||
bool isMarker(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
std::string_view id = *ptr.getCellRef().getRefIdPtr();
|
||||
std::string_view id = ptr.getCellRef().getRefIdRef();
|
||||
return id == "prisonmarker" || id == "divinemarker" || id == "templemarker" || id == "northmarker";
|
||||
}
|
||||
|
||||
std::string_view getMWClassName(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
if (*ptr.getCellRef().getRefIdPtr() == "player")
|
||||
if (ptr.getCellRef().getRefIdRef() == "player")
|
||||
return "Player";
|
||||
if (isMarker(ptr))
|
||||
return "Marker";
|
||||
@ -71,7 +71,7 @@ namespace MWLua
|
||||
res.append(" (");
|
||||
res.append(getMWClassName(ptr));
|
||||
res.append(", ");
|
||||
res.append(*ptr.getCellRef().getRefIdPtr());
|
||||
res.append(ptr.getCellRef().getRefIdRef());
|
||||
res.append(")");
|
||||
return res;
|
||||
}
|
||||
|
@ -1653,7 +1653,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||
MWRender::Animation::BlendMask_All, false,
|
||||
weapSpeed, startKey, stopKey,
|
||||
0.0f, 0);
|
||||
if(mAnimation->isPlaying(mCurrentWeapon))
|
||||
if(mAnimation->getCurrentTime(mCurrentWeapon) != -1.f)
|
||||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||
}
|
||||
}
|
||||
|
@ -206,9 +206,6 @@ namespace MWMechanics
|
||||
endPointInLocalCoords,
|
||||
startNode);
|
||||
|
||||
if (!endNode.second)
|
||||
return;
|
||||
|
||||
// if it's shorter for actor to travel from start to end, than to travel from either
|
||||
// start or end to nearest pathgrid point, just travel from start to end.
|
||||
float startToEndLength2 = (endPointInLocalCoords - startPointInLocalCoords).length2();
|
||||
@ -279,7 +276,8 @@ namespace MWMechanics
|
||||
// unreachable pathgrid point.
|
||||
//
|
||||
// The AI routines will have to deal with such situations.
|
||||
*out++ = endPoint;
|
||||
if (endNode.second)
|
||||
*out++ = endPoint;
|
||||
}
|
||||
|
||||
float PathFinder::getZAngleToNext(float x, float y) const
|
||||
|
@ -181,7 +181,7 @@ namespace MWPhysics
|
||||
|
||||
void PhysicsSystem::markAsNonSolid(const MWWorld::ConstPtr &ptr)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(ptr);
|
||||
ObjectMap::iterator found = mObjects.find(ptr.mRef);
|
||||
if (found == mObjects.end())
|
||||
return;
|
||||
|
||||
@ -198,7 +198,7 @@ namespace MWPhysics
|
||||
if (obj.isEmpty())
|
||||
return true; // assume standing on terrain (which is a non-object, so not collision tracked)
|
||||
|
||||
ObjectMap::const_iterator foundObj = mObjects.find(obj);
|
||||
ObjectMap::const_iterator foundObj = mObjects.find(obj.mRef);
|
||||
if (foundObj == mObjects.end())
|
||||
return false;
|
||||
|
||||
@ -374,8 +374,8 @@ namespace MWPhysics
|
||||
|
||||
bool PhysicsSystem::getLineOfSight(const MWWorld::ConstPtr &actor1, const MWWorld::ConstPtr &actor2) const
|
||||
{
|
||||
const auto it1 = mActors.find(actor1);
|
||||
const auto it2 = mActors.find(actor2);
|
||||
const auto it1 = mActors.find(actor1.mRef);
|
||||
const auto it2 = mActors.find(actor2.mRef);
|
||||
if (it1 == mActors.end() || it2 == mActors.end())
|
||||
return false;
|
||||
|
||||
@ -441,7 +441,7 @@ namespace MWPhysics
|
||||
{
|
||||
btCollisionObject* me = nullptr;
|
||||
|
||||
auto found = mObjects.find(ptr);
|
||||
auto found = mObjects.find(ptr.mRef);
|
||||
if (found != mObjects.end())
|
||||
me = found->second->getCollisionObject();
|
||||
else
|
||||
@ -464,7 +464,7 @@ namespace MWPhysics
|
||||
|
||||
osg::Vec3f PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, float maxHeight)
|
||||
{
|
||||
ActorMap::iterator found = mActors.find(ptr);
|
||||
ActorMap::iterator found = mActors.find(ptr.mRef);
|
||||
if (found == mActors.end())
|
||||
return ptr.getRefData().getPosition().asVec3();
|
||||
return MovementSolver::traceDown(ptr, position, found->second.get(), mCollisionWorld.get(), maxHeight);
|
||||
@ -504,7 +504,7 @@ namespace MWPhysics
|
||||
assert(!getObject(ptr));
|
||||
|
||||
auto obj = std::make_shared<Object>(ptr, shapeInstance, rotation, collisionType, mTaskScheduler.get());
|
||||
mObjects.emplace(ptr, obj);
|
||||
mObjects.emplace(ptr.mRef, obj);
|
||||
|
||||
if (obj->isAnimated())
|
||||
mAnimatedObjects.insert(obj.get());
|
||||
@ -512,8 +512,7 @@ namespace MWPhysics
|
||||
|
||||
void PhysicsSystem::remove(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(ptr);
|
||||
if (found != mObjects.end())
|
||||
if (auto found = mObjects.find(ptr.mRef); found != mObjects.end())
|
||||
{
|
||||
if (mUnrefQueue.get())
|
||||
mUnrefQueue->push(found->second->getShapeInstance());
|
||||
@ -522,11 +521,9 @@ namespace MWPhysics
|
||||
|
||||
mObjects.erase(found);
|
||||
}
|
||||
|
||||
ActorMap::iterator foundActor = mActors.find(ptr);
|
||||
if (foundActor != mActors.end())
|
||||
else if (auto found = mActors.find(ptr.mRef); found != mActors.end())
|
||||
{
|
||||
mActors.erase(foundActor);
|
||||
mActors.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,22 +536,10 @@ namespace MWPhysics
|
||||
|
||||
void PhysicsSystem::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(old);
|
||||
if (found != mObjects.end())
|
||||
{
|
||||
auto obj = found->second;
|
||||
obj->updatePtr(updated);
|
||||
mObjects.erase(found);
|
||||
mObjects.emplace(updated, std::move(obj));
|
||||
}
|
||||
|
||||
auto actorNode = mActors.extract(old);
|
||||
if (!actorNode.empty())
|
||||
{
|
||||
actorNode.key() = updated;
|
||||
actorNode.mapped()->updatePtr(updated);
|
||||
mActors.insert(std::move(actorNode));
|
||||
}
|
||||
if (auto found = mObjects.find(old.mRef); found != mObjects.end())
|
||||
found->second->updatePtr(updated);
|
||||
else if (auto found = mActors.find(old.mRef); found != mActors.end())
|
||||
found->second->updatePtr(updated);
|
||||
|
||||
for (auto& [_, actor] : mActors)
|
||||
{
|
||||
@ -572,7 +557,7 @@ namespace MWPhysics
|
||||
|
||||
Actor *PhysicsSystem::getActor(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
ActorMap::iterator found = mActors.find(ptr);
|
||||
ActorMap::iterator found = mActors.find(ptr.mRef);
|
||||
if (found != mActors.end())
|
||||
return found->second.get();
|
||||
return nullptr;
|
||||
@ -580,7 +565,7 @@ namespace MWPhysics
|
||||
|
||||
const Actor *PhysicsSystem::getActor(const MWWorld::ConstPtr &ptr) const
|
||||
{
|
||||
ActorMap::const_iterator found = mActors.find(ptr);
|
||||
ActorMap::const_iterator found = mActors.find(ptr.mRef);
|
||||
if (found != mActors.end())
|
||||
return found->second.get();
|
||||
return nullptr;
|
||||
@ -588,7 +573,7 @@ namespace MWPhysics
|
||||
|
||||
const Object* PhysicsSystem::getObject(const MWWorld::ConstPtr &ptr) const
|
||||
{
|
||||
ObjectMap::const_iterator found = mObjects.find(ptr);
|
||||
ObjectMap::const_iterator found = mObjects.find(ptr.mRef);
|
||||
if (found != mObjects.end())
|
||||
return found->second.get();
|
||||
return nullptr;
|
||||
@ -604,20 +589,16 @@ namespace MWPhysics
|
||||
|
||||
void PhysicsSystem::updateScale(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(ptr);
|
||||
if (found != mObjects.end())
|
||||
if (auto found = mObjects.find(ptr.mRef); found != mObjects.end())
|
||||
{
|
||||
float scale = ptr.getCellRef().getScale();
|
||||
found->second->setScale(scale);
|
||||
mTaskScheduler->updateSingleAabb(found->second);
|
||||
return;
|
||||
}
|
||||
ActorMap::iterator foundActor = mActors.find(ptr);
|
||||
if (foundActor != mActors.end())
|
||||
else if (auto found = mActors.find(ptr.mRef); found != mActors.end())
|
||||
{
|
||||
foundActor->second->updateScale();
|
||||
mTaskScheduler->updateSingleAabb(foundActor->second);
|
||||
return;
|
||||
found->second->updateScale();
|
||||
mTaskScheduler->updateSingleAabb(found->second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -650,40 +631,32 @@ namespace MWPhysics
|
||||
|
||||
void PhysicsSystem::updateRotation(const MWWorld::Ptr &ptr, osg::Quat rotate)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(ptr);
|
||||
if (found != mObjects.end())
|
||||
if (auto found = mObjects.find(ptr.mRef); found != mObjects.end())
|
||||
{
|
||||
found->second->setRotation(rotate);
|
||||
mTaskScheduler->updateSingleAabb(found->second);
|
||||
return;
|
||||
}
|
||||
ActorMap::iterator foundActor = mActors.find(ptr);
|
||||
if (foundActor != mActors.end())
|
||||
else if (auto found = mActors.find(ptr.mRef); found != mActors.end())
|
||||
{
|
||||
if (!foundActor->second->isRotationallyInvariant())
|
||||
if (!found->second->isRotationallyInvariant())
|
||||
{
|
||||
foundActor->second->setRotation(rotate);
|
||||
mTaskScheduler->updateSingleAabb(foundActor->second);
|
||||
found->second->setRotation(rotate);
|
||||
mTaskScheduler->updateSingleAabb(found->second);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::updatePosition(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(ptr);
|
||||
if (found != mObjects.end())
|
||||
if (auto found = mObjects.find(ptr.mRef); found != mObjects.end())
|
||||
{
|
||||
found->second->updatePosition();
|
||||
mTaskScheduler->updateSingleAabb(found->second);
|
||||
return;
|
||||
}
|
||||
ActorMap::iterator foundActor = mActors.find(ptr);
|
||||
if (foundActor != mActors.end())
|
||||
else if (auto found = mActors.find(ptr.mRef); found != mActors.end())
|
||||
{
|
||||
foundActor->second->updatePosition();
|
||||
mTaskScheduler->updateSingleAabb(foundActor->second, true);
|
||||
return;
|
||||
found->second->updatePosition();
|
||||
mTaskScheduler->updateSingleAabb(found->second, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -710,7 +683,7 @@ namespace MWPhysics
|
||||
|
||||
auto actor = std::make_shared<Actor>(ptr, shape, mTaskScheduler.get(), canWaterWalk);
|
||||
|
||||
mActors.emplace(ptr, std::move(actor));
|
||||
mActors.emplace(ptr.mRef, std::move(actor));
|
||||
}
|
||||
|
||||
int PhysicsSystem::addProjectile (const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater)
|
||||
@ -738,7 +711,7 @@ namespace MWPhysics
|
||||
|
||||
bool PhysicsSystem::toggleCollisionMode()
|
||||
{
|
||||
ActorMap::iterator found = mActors.find(MWMechanics::getPlayer());
|
||||
ActorMap::iterator found = mActors.find(MWMechanics::getPlayer().mRef);
|
||||
if (found != mActors.end())
|
||||
{
|
||||
bool cmode = found->second->getCollisionMode();
|
||||
@ -753,7 +726,7 @@ namespace MWPhysics
|
||||
|
||||
void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity)
|
||||
{
|
||||
ActorMap::iterator found = mActors.find(ptr);
|
||||
ActorMap::iterator found = mActors.find(ptr.mRef);
|
||||
if (found != mActors.end())
|
||||
found->second->setVelocity(velocity);
|
||||
}
|
||||
@ -770,13 +743,13 @@ namespace MWPhysics
|
||||
framedata.first.reserve(mActors.size());
|
||||
framedata.second.reserve(mActors.size());
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
for (const auto& [actor, physicActor] : mActors)
|
||||
for (const auto& [ref, physicActor] : mActors)
|
||||
{
|
||||
auto ptr = physicActor->getPtr();
|
||||
if (!actor.getClass().isMobile(ptr))
|
||||
if (!ptr.getClass().isMobile(ptr))
|
||||
continue;
|
||||
float waterlevel = -std::numeric_limits<float>::max();
|
||||
const MWWorld::CellStore *cell = actor.getCell();
|
||||
const MWWorld::CellStore *cell = ptr.getCell();
|
||||
if(cell->getCell()->hasWater())
|
||||
waterlevel = cell->getWaterLevel();
|
||||
|
||||
@ -786,7 +759,7 @@ namespace MWPhysics
|
||||
bool waterCollision = false;
|
||||
if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude())
|
||||
{
|
||||
if (physicActor->getCollisionMode() || !world->isUnderwater(actor.getCell(), actor.getRefData().getPosition().asVec3()))
|
||||
if (physicActor->getCollisionMode() || !world->isUnderwater(ptr.getCell(), ptr.getRefData().getPosition().asVec3()))
|
||||
waterCollision = true;
|
||||
}
|
||||
|
||||
@ -813,7 +786,7 @@ namespace MWPhysics
|
||||
{
|
||||
if (animatedObject->animateCollisionShapes())
|
||||
{
|
||||
auto obj = mObjects.find(animatedObject->getPtr());
|
||||
auto obj = mObjects.find(animatedObject->getPtr().mRef);
|
||||
assert(obj != mObjects.end());
|
||||
mTaskScheduler->updateSingleAabb(obj->second);
|
||||
}
|
||||
@ -840,18 +813,26 @@ namespace MWPhysics
|
||||
{
|
||||
auto* player = getActor(MWMechanics::getPlayer());
|
||||
auto* world = MWBase::Environment::get().getWorld();
|
||||
for (auto& [ptr, physicActor] : mActors)
|
||||
|
||||
// copy new ptr position in temporary vector. player is handled separately as its movement might change active cell.
|
||||
std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>> newPositions;
|
||||
newPositions.reserve(mActors.size() - 1);
|
||||
for (const auto& [ptr, physicActor] : mActors)
|
||||
{
|
||||
if (physicActor.get() == player)
|
||||
continue;
|
||||
world->moveObject(physicActor->getPtr(), physicActor->getSimulationPosition(), false, false);
|
||||
newPositions.emplace_back(physicActor->getPtr(), physicActor->getSimulationPosition());
|
||||
}
|
||||
|
||||
for (auto& [ptr, pos] : newPositions)
|
||||
world->moveObject(ptr, pos, false, false);
|
||||
|
||||
world->moveObject(player->getPtr(), player->getSimulationPosition(), false, false);
|
||||
}
|
||||
|
||||
void PhysicsSystem::updateAnimatedCollisionShape(const MWWorld::Ptr& object)
|
||||
{
|
||||
ObjectMap::iterator found = mObjects.find(object);
|
||||
ObjectMap::iterator found = mObjects.find(object.mRef);
|
||||
if (found != mObjects.end())
|
||||
if (found->second->animateCollisionShapes())
|
||||
mTaskScheduler->updateSingleAabb(found->second);
|
||||
@ -865,7 +846,7 @@ namespace MWPhysics
|
||||
|
||||
bool PhysicsSystem::isActorStandingOn(const MWWorld::Ptr &actor, const MWWorld::ConstPtr &object) const
|
||||
{
|
||||
const auto physActor = mActors.find(actor);
|
||||
const auto physActor = mActors.find(actor.mRef);
|
||||
if (physActor != mActors.end())
|
||||
return physActor->second->getStandingOnPtr() == object;
|
||||
return false;
|
||||
@ -943,7 +924,7 @@ namespace MWPhysics
|
||||
bool PhysicsSystem::isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const
|
||||
{
|
||||
btCollisionObject* object = nullptr;
|
||||
const auto it = mActors.find(ignore);
|
||||
const auto it = mActors.find(ignore.mRef);
|
||||
if (it != mActors.end())
|
||||
object = it->second->getCollisionObject();
|
||||
const auto bulletPosition = Misc::Convert::toBullet(position);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <osg/Quat>
|
||||
@ -56,7 +57,7 @@ namespace MWPhysics
|
||||
class PhysicsTaskScheduler;
|
||||
class Projectile;
|
||||
|
||||
using ActorMap = std::map<MWWorld::ConstPtr, std::shared_ptr<Actor>>;
|
||||
using ActorMap = std::unordered_map<const MWWorld::LiveCellRefBase*, std::shared_ptr<Actor>>;
|
||||
|
||||
struct ContactPoint
|
||||
{
|
||||
@ -272,7 +273,7 @@ namespace MWPhysics
|
||||
std::unique_ptr<Resource::BulletShapeManager> mShapeManager;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
using ObjectMap = std::map<MWWorld::ConstPtr, std::shared_ptr<Object>>;
|
||||
using ObjectMap = std::unordered_map<const MWWorld::LiveCellRefBase*, std::shared_ptr<Object>>;
|
||||
ObjectMap mObjects;
|
||||
|
||||
std::set<Object*> mAnimatedObjects; // stores pointers to elements in mObjects
|
||||
|
@ -271,7 +271,7 @@ bool ActorAnimation::useShieldAnimations() const
|
||||
return false;
|
||||
}
|
||||
|
||||
osg::Group* ActorAnimation::getBoneByName(const std::string& boneName)
|
||||
osg::Group* ActorAnimation::getBoneByName(const std::string& boneName) const
|
||||
{
|
||||
if (!mObjectRoot)
|
||||
return nullptr;
|
||||
|
@ -41,7 +41,7 @@ class ActorAnimation : public Animation, public MWWorld::ContainerStoreListener
|
||||
bool updateCarriedLeftVisible(const int weaptype) const override;
|
||||
|
||||
protected:
|
||||
osg::Group* getBoneByName(const std::string& boneName);
|
||||
osg::Group* getBoneByName(const std::string& boneName) const;
|
||||
virtual void updateHolsteredWeapon(bool showHolsteredWeapons);
|
||||
virtual void updateHolsteredShield(bool showCarriedLeft);
|
||||
virtual void updateQuiver();
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <components/resource/keyframemanager.hpp>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
||||
#include <components/sceneutil/keyframe.hpp>
|
||||
@ -196,32 +197,6 @@ namespace
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/// @brief Base class for visitors that remove nodes from a scene graph.
|
||||
/// Subclasses need to fill the mToRemove vector.
|
||||
/// To use, node->accept(removeVisitor); removeVisitor.remove();
|
||||
class RemoveVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
RemoveVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
for (RemoveVec::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
{
|
||||
if (!it->second->removeChild(it->first))
|
||||
Log(Debug::Error) << "Error removing " << it->first->getName();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// <node to remove, parent node to remove it from>
|
||||
typedef std::vector<std::pair<osg::Node*, osg::Group*> > RemoveVec;
|
||||
std::vector<std::pair<osg::Node*, osg::Group*> > mToRemove;
|
||||
};
|
||||
|
||||
class GetExtendedBonesVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
@ -244,7 +219,7 @@ namespace
|
||||
std::vector<std::pair<osg::Node*, osg::Group*> > mFoundBones;
|
||||
};
|
||||
|
||||
class RemoveFinishedCallbackVisitor : public RemoveVisitor
|
||||
class RemoveFinishedCallbackVisitor : public SceneUtil::RemoveVisitor
|
||||
{
|
||||
public:
|
||||
bool mHasMagicEffects;
|
||||
@ -289,7 +264,7 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
class RemoveCallbackVisitor : public RemoveVisitor
|
||||
class RemoveCallbackVisitor : public SceneUtil::RemoveVisitor
|
||||
{
|
||||
public:
|
||||
bool mHasMagicEffects;
|
||||
@ -397,90 +372,6 @@ namespace
|
||||
private:
|
||||
int mEffectId;
|
||||
};
|
||||
|
||||
// Removes all drawables from a graph.
|
||||
class CleanObjectRootVisitor : public RemoveVisitor
|
||||
{
|
||||
public:
|
||||
void apply(osg::Drawable& drw) override
|
||||
{
|
||||
applyDrawable(drw);
|
||||
}
|
||||
|
||||
void apply(osg::Group& node) override
|
||||
{
|
||||
applyNode(node);
|
||||
}
|
||||
void apply(osg::MatrixTransform& node) override
|
||||
{
|
||||
applyNode(node);
|
||||
}
|
||||
void apply(osg::Node& node) override
|
||||
{
|
||||
applyNode(node);
|
||||
}
|
||||
|
||||
void applyNode(osg::Node& node)
|
||||
{
|
||||
if (node.getStateSet())
|
||||
node.setStateSet(nullptr);
|
||||
|
||||
if (node.getNodeMask() == 0x1 && node.getNumParents() == 1)
|
||||
mToRemove.emplace_back(&node, node.getParent(0));
|
||||
else
|
||||
traverse(node);
|
||||
}
|
||||
void applyDrawable(osg::Node& node)
|
||||
{
|
||||
osg::NodePath::iterator parent = getNodePath().end()-2;
|
||||
// We know that the parent is a Group because only Groups can have children.
|
||||
osg::Group* parentGroup = static_cast<osg::Group*>(*parent);
|
||||
|
||||
// Try to prune nodes that would be empty after the removal
|
||||
if (parent != getNodePath().begin())
|
||||
{
|
||||
// This could be extended to remove the parent's parent, and so on if they are empty as well.
|
||||
// But for NIF files, there won't be a benefit since only TriShapes can be set to STATIC dataVariance.
|
||||
osg::Group* parentParent = static_cast<osg::Group*>(*(parent - 1));
|
||||
if (parentGroup->getNumChildren() == 1 && parentGroup->getDataVariance() == osg::Object::STATIC)
|
||||
{
|
||||
mToRemove.emplace_back(parentGroup, parentParent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mToRemove.emplace_back(&node, parentGroup);
|
||||
}
|
||||
};
|
||||
|
||||
class RemoveTriBipVisitor : public RemoveVisitor
|
||||
{
|
||||
public:
|
||||
void apply(osg::Drawable& drw) override
|
||||
{
|
||||
applyImpl(drw);
|
||||
}
|
||||
|
||||
void apply(osg::Group& node) override
|
||||
{
|
||||
traverse(node);
|
||||
}
|
||||
void apply(osg::MatrixTransform& node) override
|
||||
{
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
void applyImpl(osg::Node& node)
|
||||
{
|
||||
const std::string toFind = "tri bip";
|
||||
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
|
||||
{
|
||||
osg::Group* parent = static_cast<osg::Group*>(*(getNodePath().end()-2));
|
||||
// Not safe to remove in apply(), since the visitor is still iterating the child list
|
||||
mToRemove.emplace_back(&node, parent);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
@ -701,8 +592,6 @@ namespace MWRender
|
||||
|
||||
void Animation::loadAllAnimationsInFolder(const std::string &model, const std::string &baseModel)
|
||||
{
|
||||
const std::map<std::string, VFS::File*>& index = mResourceSystem->getVFS()->getIndex();
|
||||
|
||||
std::string animationPath = model;
|
||||
if (animationPath.find("meshes") == 0)
|
||||
{
|
||||
@ -710,21 +599,10 @@ namespace MWRender
|
||||
}
|
||||
animationPath.replace(animationPath.size()-3, 3, "/");
|
||||
|
||||
mResourceSystem->getVFS()->normalizeFilename(animationPath);
|
||||
|
||||
std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(animationPath);
|
||||
while (found != index.end())
|
||||
for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath))
|
||||
{
|
||||
const std::string& name = found->first;
|
||||
if (name.size() >= animationPath.size() && name.substr(0, animationPath.size()) == animationPath)
|
||||
{
|
||||
size_t pos = name.find_last_of('.');
|
||||
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".kf") == 0)
|
||||
addSingleAnimSource(name, baseModel);
|
||||
}
|
||||
else
|
||||
break;
|
||||
++found;
|
||||
if (Misc::getFileExtension(name) == "kf")
|
||||
addSingleAnimSource(name, baseModel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1405,8 +1283,6 @@ namespace MWRender
|
||||
if (model.empty())
|
||||
return;
|
||||
|
||||
const std::map<std::string, VFS::File*>& index = resourceSystem->getVFS()->getIndex();
|
||||
|
||||
std::string animationPath = model;
|
||||
if (animationPath.find("meshes") == 0)
|
||||
{
|
||||
@ -1414,21 +1290,10 @@ namespace MWRender
|
||||
}
|
||||
animationPath.replace(animationPath.size()-4, 4, "/");
|
||||
|
||||
resourceSystem->getVFS()->normalizeFilename(animationPath);
|
||||
|
||||
std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(animationPath);
|
||||
while (found != index.end())
|
||||
for (const auto& name : resourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath))
|
||||
{
|
||||
const std::string& name = found->first;
|
||||
if (name.size() >= animationPath.size() && name.substr(0, animationPath.size()) == animationPath)
|
||||
{
|
||||
size_t pos = name.find_last_of('.');
|
||||
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".nif") == 0)
|
||||
loadBonesFromFile(node, name, resourceSystem);
|
||||
}
|
||||
else
|
||||
break;
|
||||
++found;
|
||||
if (Misc::getFileExtension(name) == "nif")
|
||||
loadBonesFromFile(node, name, resourceSystem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
|
||||
|
||||
try
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(itemModel);
|
||||
osg::ref_ptr<const osg::Node> node = mResourceSystem->getSceneManager()->getTemplate(itemModel);
|
||||
|
||||
const NodeMap& nodeMap = getNodeMap();
|
||||
NodeMap::const_iterator found = nodeMap.find(Misc::StringUtils::lowerCase(bonename));
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "groundcover.hpp"
|
||||
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/VertexAttribDivisor>
|
||||
|
||||
@ -66,18 +67,6 @@ namespace MWRender
|
||||
{
|
||||
}
|
||||
|
||||
void apply(osg::Node& node) override
|
||||
{
|
||||
osg::ref_ptr<osg::StateSet> ss = node.getStateSet();
|
||||
if (ss != nullptr)
|
||||
{
|
||||
ss->removeAttribute(osg::StateAttribute::MATERIAL);
|
||||
removeAlpha(ss);
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
void apply(osg::Geometry& geom) override
|
||||
{
|
||||
for (unsigned int i = 0; i < geom.getNumPrimitiveSets(); ++i)
|
||||
@ -110,32 +99,14 @@ namespace MWRender
|
||||
|
||||
// Display lists do not support instancing in OSG 3.4
|
||||
geom.setUseDisplayList(false);
|
||||
geom.setUseVertexBufferObjects(true);
|
||||
|
||||
geom.setVertexAttribArray(6, transforms.get(), osg::Array::BIND_PER_VERTEX);
|
||||
geom.setVertexAttribArray(7, rotations.get(), osg::Array::BIND_PER_VERTEX);
|
||||
|
||||
osg::ref_ptr<osg::StateSet> ss = geom.getOrCreateStateSet();
|
||||
ss->setAttribute(new osg::VertexAttribDivisor(6, 1));
|
||||
ss->setAttribute(new osg::VertexAttribDivisor(7, 1));
|
||||
|
||||
ss->removeAttribute(osg::StateAttribute::MATERIAL);
|
||||
removeAlpha(ss);
|
||||
|
||||
traverse(geom);
|
||||
}
|
||||
private:
|
||||
std::vector<Groundcover::GroundcoverEntry> mInstances;
|
||||
osg::Vec3f mChunkPosition;
|
||||
|
||||
void removeAlpha(osg::StateSet* stateset)
|
||||
{
|
||||
// MGE uses default alpha settings for groundcover, so we can not rely on alpha properties
|
||||
stateset->removeAttribute(osg::StateAttribute::ALPHAFUNC);
|
||||
stateset->removeMode(GL_ALPHA_TEST);
|
||||
stateset->removeAttribute(osg::StateAttribute::BLENDFUNC);
|
||||
stateset->removeMode(GL_BLEND);
|
||||
stateset->setRenderBinToInherit();
|
||||
}
|
||||
};
|
||||
|
||||
class DensityCalculator
|
||||
@ -180,11 +151,11 @@ namespace MWRender
|
||||
|
||||
osg::ref_ptr<osg::Node> Groundcover::getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile)
|
||||
{
|
||||
ChunkId id = std::make_tuple(center, size, activeGrid);
|
||||
GroundcoverChunkId id = std::make_tuple(center, size);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(id);
|
||||
if (obj)
|
||||
return obj->asNode();
|
||||
return static_cast<osg::Node*>(obj.get());
|
||||
else
|
||||
{
|
||||
InstanceMap instances;
|
||||
@ -196,10 +167,19 @@ namespace MWRender
|
||||
}
|
||||
|
||||
Groundcover::Groundcover(Resource::SceneManager* sceneManager, float density)
|
||||
: GenericResourceManager<ChunkId>(nullptr)
|
||||
: GenericResourceManager<GroundcoverChunkId>(nullptr)
|
||||
, mSceneManager(sceneManager)
|
||||
, mDensity(density)
|
||||
, mStateset(new osg::StateSet)
|
||||
{
|
||||
// MGE uses default alpha settings for groundcover, so we can not rely on alpha properties
|
||||
// Force a unified alpha handling instead of data from meshes
|
||||
osg::ref_ptr<osg::AlphaFunc> alpha = new osg::AlphaFunc(osg::AlphaFunc::GEQUAL, 128.f / 255.f);
|
||||
mStateset->setAttributeAndModes(alpha.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
mStateset->setAttributeAndModes(new osg::BlendFunc, osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
|
||||
mStateset->setRenderBinDetails(0, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
|
||||
mStateset->setAttribute(new osg::VertexAttribDivisor(6, 1));
|
||||
mStateset->setAttribute(new osg::VertexAttribDivisor(7, 1));
|
||||
}
|
||||
|
||||
void Groundcover::collectInstances(InstanceMap& instances, float size, const osg::Vec2f& center)
|
||||
@ -255,27 +235,23 @@ namespace MWRender
|
||||
for (auto& pair : instances)
|
||||
{
|
||||
const osg::Node* temp = mSceneManager->getTemplate(pair.first);
|
||||
osg::ref_ptr<osg::Node> node = static_cast<osg::Node*>(temp->clone(osg::CopyOp::DEEP_COPY_ALL&(~osg::CopyOp::DEEP_COPY_TEXTURES)));
|
||||
osg::ref_ptr<osg::Node> node = static_cast<osg::Node*>(temp->clone(osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES|osg::CopyOp::DEEP_COPY_USERDATA|osg::CopyOp::DEEP_COPY_ARRAYS|osg::CopyOp::DEEP_COPY_PRIMITIVES));
|
||||
|
||||
// Keep link to original mesh to keep it in cache
|
||||
group->getOrCreateUserDataContainer()->addUserObject(new Resource::TemplateRef(temp));
|
||||
|
||||
mSceneManager->reinstateRemovedState(node);
|
||||
|
||||
InstancingVisitor visitor(pair.second, worldCenter);
|
||||
node->accept(visitor);
|
||||
group->addChild(node);
|
||||
}
|
||||
|
||||
// Force a unified alpha handling instead of data from meshes
|
||||
osg::ref_ptr<osg::AlphaFunc> alpha = new osg::AlphaFunc(osg::AlphaFunc::GEQUAL, 128.f / 255.f);
|
||||
group->getOrCreateStateSet()->setAttributeAndModes(alpha.get(), osg::StateAttribute::ON);
|
||||
group->getBound();
|
||||
group->setStateSet(mStateset);
|
||||
group->setNodeMask(Mask_Groundcover);
|
||||
if (mSceneManager->getLightingMethod() != SceneUtil::LightingMethod::FFP)
|
||||
group->setCullCallback(new SceneUtil::LightListCallback);
|
||||
mSceneManager->recreateShaders(group, "groundcover", false, true);
|
||||
|
||||
mSceneManager->shareState(group);
|
||||
group->getBound();
|
||||
return group;
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,8 @@ namespace MWRender
|
||||
osg::Vec3f mPlayerPos;
|
||||
};
|
||||
|
||||
typedef std::tuple<osg::Vec2f, float, bool> ChunkId; // Center, Size, ActiveGrid
|
||||
class Groundcover : public Resource::GenericResourceManager<ChunkId>, public Terrain::QuadTreeWorld::ChunkManager
|
||||
typedef std::tuple<osg::Vec2f, float> GroundcoverChunkId; // Center, Size
|
||||
class Groundcover : public Resource::GenericResourceManager<GroundcoverChunkId>, public Terrain::QuadTreeWorld::ChunkManager
|
||||
{
|
||||
public:
|
||||
Groundcover(Resource::SceneManager* sceneManager, float density);
|
||||
@ -56,6 +56,7 @@ namespace MWRender
|
||||
private:
|
||||
Resource::SceneManager* mSceneManager;
|
||||
float mDensity;
|
||||
osg::ref_ptr<osg::StateSet> mStateset;
|
||||
|
||||
typedef std::map<std::string, std::vector<GroundcoverEntry>> InstanceMap;
|
||||
osg::ref_ptr<osg::Node> createChunk(InstanceMap& instances, const osg::Vec2f& center);
|
||||
|
@ -714,14 +714,14 @@ void NpcAnimation::updateParts()
|
||||
|
||||
PartHolderPtr NpcAnimation::insertBoundedPart(const std::string& model, const std::string& bonename, const std::string& bonefilter, bool enchantedGlow, osg::Vec4f* glowColor)
|
||||
{
|
||||
osg::ref_ptr<osg::Node> instance = mResourceSystem->getSceneManager()->getInstance(model);
|
||||
osg::ref_ptr<const osg::Node> templateNode = mResourceSystem->getSceneManager()->getTemplate(model);
|
||||
|
||||
const NodeMap& nodeMap = getNodeMap();
|
||||
NodeMap::const_iterator found = nodeMap.find(Misc::StringUtils::lowerCase(bonename));
|
||||
if (found == nodeMap.end())
|
||||
throw std::runtime_error("Can't find attachment node " + bonename);
|
||||
|
||||
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, found->second);
|
||||
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(templateNode, mObjectRoot, bonefilter, found->second);
|
||||
if (enchantedGlow)
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(attached, mResourceSystem, *glowColor);
|
||||
|
||||
|
@ -77,7 +77,7 @@ namespace MWRender
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(id);
|
||||
if (obj)
|
||||
return obj->asNode();
|
||||
return static_cast<osg::Node*>(obj.get());
|
||||
else
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = createChunk(size, center, activeGrid, viewPoint, compile);
|
||||
|
@ -373,7 +373,9 @@ namespace MWRender
|
||||
mTerrainStorage.reset(new TerrainStorage(mResourceSystem, normalMapPattern, heightMapPattern, useTerrainNormalMaps, specularMapPattern, useTerrainSpecularMaps));
|
||||
const float lodFactor = Settings::Manager::getFloat("lod factor", "Terrain");
|
||||
|
||||
if (Settings::Manager::getBool("distant terrain", "Terrain"))
|
||||
bool groundcover = Settings::Manager::getBool("enabled", "Groundcover");
|
||||
bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||
if (distantTerrain || groundcover)
|
||||
{
|
||||
const int compMapResolution = Settings::Manager::getInt("composite map resolution", "Terrain");
|
||||
int compMapPower = Settings::Manager::getInt("composite map level", "Terrain");
|
||||
@ -398,41 +400,27 @@ namespace MWRender
|
||||
mTerrain->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells"));
|
||||
mTerrain->setWorkQueue(mWorkQueue.get());
|
||||
|
||||
if (Settings::Manager::getBool("enabled", "Groundcover"))
|
||||
osg::ref_ptr<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater;
|
||||
|
||||
if (groundcover)
|
||||
{
|
||||
osg::ref_ptr<osg::Group> groundcoverRoot = new osg::Group;
|
||||
groundcoverRoot->setNodeMask(Mask_Groundcover);
|
||||
groundcoverRoot->setName("Groundcover Root");
|
||||
sceneRoot->addChild(groundcoverRoot);
|
||||
|
||||
mGroundcoverUpdater = new GroundcoverUpdater;
|
||||
groundcoverRoot->addUpdateCallback(mGroundcoverUpdater);
|
||||
|
||||
float chunkSize = Settings::Manager::getFloat("min chunk size", "Groundcover");
|
||||
if (chunkSize >= 1.0f)
|
||||
chunkSize = 1.0f;
|
||||
else if (chunkSize >= 0.5f)
|
||||
chunkSize = 0.5f;
|
||||
else if (chunkSize >= 0.25f)
|
||||
chunkSize = 0.25f;
|
||||
else if (chunkSize != 0.125f)
|
||||
chunkSize = 0.125f;
|
||||
|
||||
float density = Settings::Manager::getFloat("density", "Groundcover");
|
||||
density = std::clamp(density, 0.f, 1.f);
|
||||
|
||||
mGroundcoverWorld.reset(new Terrain::QuadTreeWorld(groundcoverRoot, mTerrainStorage.get(), Mask_Groundcover, lodFactor, chunkSize));
|
||||
mGroundcoverUpdater = new GroundcoverUpdater;
|
||||
composite->addController(mGroundcoverUpdater);
|
||||
|
||||
mGroundcover.reset(new Groundcover(mResourceSystem->getSceneManager(), density));
|
||||
static_cast<Terrain::QuadTreeWorld*>(mGroundcoverWorld.get())->addChunkManager(mGroundcover.get());
|
||||
static_cast<Terrain::QuadTreeWorld*>(mTerrain.get())->addChunkManager(mGroundcover.get());
|
||||
mResourceSystem->addResourceManager(mGroundcover.get());
|
||||
|
||||
// Groundcover it is handled in the same way indifferently from if it is from active grid or from distant cell.
|
||||
// Use a stub grid to avoid splitting between chunks for active grid and chunks for distant cells.
|
||||
mGroundcoverWorld->setActiveGrid(osg::Vec4i(0, 0, 0, 0));
|
||||
float groundcoverDistance = std::max(0.f, Settings::Manager::getFloat("rendering distance", "Groundcover"));
|
||||
mGroundcover->setViewDistance(groundcoverDistance);
|
||||
}
|
||||
|
||||
mStateUpdater = new StateUpdater;
|
||||
sceneRoot->addUpdateCallback(mStateUpdater);
|
||||
composite->addController(mStateUpdater);
|
||||
sceneRoot->addUpdateCallback(composite);
|
||||
|
||||
mSharedUniformStateUpdater = new SharedUniformStateUpdater;
|
||||
rootNode->addUpdateCallback(mSharedUniformStateUpdater);
|
||||
@ -693,8 +681,6 @@ namespace MWRender
|
||||
if (store->getCell()->isExterior())
|
||||
{
|
||||
mTerrain->loadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
||||
if (mGroundcoverWorld)
|
||||
mGroundcoverWorld->loadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
||||
}
|
||||
}
|
||||
void RenderingManager::removeCell(const MWWorld::CellStore *store)
|
||||
@ -706,8 +692,6 @@ namespace MWRender
|
||||
if (store->getCell()->isExterior())
|
||||
{
|
||||
mTerrain->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
||||
if (mGroundcoverWorld)
|
||||
mGroundcoverWorld->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
||||
}
|
||||
|
||||
mWater->removeCell(store);
|
||||
@ -718,8 +702,6 @@ namespace MWRender
|
||||
if (!enable)
|
||||
mWater->setCullCallback(nullptr);
|
||||
mTerrain->enable(enable);
|
||||
if (mGroundcoverWorld)
|
||||
mGroundcoverWorld->enable(enable);
|
||||
}
|
||||
|
||||
void RenderingManager::setSkyEnabled(bool enabled)
|
||||
@ -1179,12 +1161,6 @@ namespace MWRender
|
||||
fov = std::min(mFieldOfView, 140.f);
|
||||
float distanceMult = std::cos(osg::DegreesToRadians(fov)/2.f);
|
||||
mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f/distanceMult : 1.f));
|
||||
|
||||
if (mGroundcoverWorld)
|
||||
{
|
||||
float groundcoverDistance = std::max(0.f, Settings::Manager::getFloat("rendering distance", "Groundcover"));
|
||||
mGroundcoverWorld->setViewDistance(groundcoverDistance * (distanceMult ? 1.f/distanceMult : 1.f));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::updateTextureFiltering()
|
||||
|
@ -262,8 +262,6 @@ namespace MWRender
|
||||
osg::ref_ptr<osg::Group> mSceneRoot;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
osg::ref_ptr<GroundcoverUpdater> mGroundcoverUpdater;
|
||||
|
||||
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
|
||||
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||
|
||||
@ -278,10 +276,10 @@ namespace MWRender
|
||||
std::unique_ptr<Objects> mObjects;
|
||||
std::unique_ptr<Water> mWater;
|
||||
std::unique_ptr<Terrain::World> mTerrain;
|
||||
std::unique_ptr<Terrain::World> mGroundcoverWorld;
|
||||
std::unique_ptr<TerrainStorage> mTerrainStorage;
|
||||
std::unique_ptr<ObjectPaging> mObjectPaging;
|
||||
std::unique_ptr<Groundcover> mGroundcover;
|
||||
osg::ref_ptr<GroundcoverUpdater> mGroundcoverUpdater;
|
||||
std::unique_ptr<SkyManager> mSky;
|
||||
std::unique_ptr<FogManager> mFog;
|
||||
std::unique_ptr<ScreenshotManager> mScreenshotManager;
|
||||
|
@ -191,6 +191,7 @@ namespace MWRender
|
||||
screenshotH = screenshotW; // use square resolution for planet mapping
|
||||
|
||||
std::vector<osg::ref_ptr<osg::Image>> images;
|
||||
images.reserve(6);
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
images.push_back(new osg::Image);
|
||||
|
@ -33,7 +33,10 @@ namespace MWRender
|
||||
|
||||
void TerrainStorage::getBounds(float& minX, float& maxX, float& minY, float& maxY)
|
||||
{
|
||||
minX = 0, minY = 0, maxX = 0, maxY = 0;
|
||||
minX = 0;
|
||||
minY = 0;
|
||||
maxX = 0;
|
||||
maxY = 0;
|
||||
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
@ -131,7 +131,7 @@ namespace MWSound
|
||||
max = std::max(min, max);
|
||||
|
||||
Sound_Buffer& sfx = mSoundBuffers.emplace_back("Sound/" + sound.mSound, volume, min, max);
|
||||
mVfs->normalizeFilename(sfx.mResourceName);
|
||||
sfx.mResourceName = mVfs->normalizeFilename(sfx.mResourceName);
|
||||
|
||||
mBufferNameMap.emplace(soundId, &sfx);
|
||||
return &sfx;
|
||||
|
@ -294,20 +294,9 @@ namespace MWSound
|
||||
if (mMusicFiles.find(playlist) == mMusicFiles.end())
|
||||
{
|
||||
std::vector<std::string> filelist;
|
||||
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
||||
|
||||
std::string pattern = "Music/" + playlist;
|
||||
mVFS->normalizeFilename(pattern);
|
||||
|
||||
std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(pattern);
|
||||
while (found != index.end())
|
||||
{
|
||||
if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern)
|
||||
filelist.push_back(found->first);
|
||||
else
|
||||
break;
|
||||
++found;
|
||||
}
|
||||
for (const auto& name : mVFS->getRecursiveDirectoryIterator("Music/" + playlist))
|
||||
filelist.push_back(name);
|
||||
|
||||
mMusicFiles[playlist] = filelist;
|
||||
}
|
||||
@ -327,13 +316,11 @@ namespace MWSound
|
||||
if (mMusicFiles.find("Title") == mMusicFiles.end())
|
||||
{
|
||||
std::vector<std::string> filelist;
|
||||
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
||||
// Is there an ini setting for this filename or something?
|
||||
std::string filename = "music/special/morrowind title.mp3";
|
||||
auto found = index.find(filename);
|
||||
if (found != index.end())
|
||||
if (mVFS->exists(filename))
|
||||
{
|
||||
filelist.emplace_back(found->first);
|
||||
filelist.emplace_back(filename);
|
||||
mMusicFiles["Title"] = filelist;
|
||||
}
|
||||
else
|
||||
@ -355,10 +342,7 @@ namespace MWSound
|
||||
if(!mOutput->isInitialized())
|
||||
return;
|
||||
|
||||
std::string voicefile = "Sound/"+filename;
|
||||
|
||||
mVFS->normalizeFilename(voicefile);
|
||||
DecoderPtr decoder = loadVoice(voicefile);
|
||||
DecoderPtr decoder = loadVoice(mVFS->normalizeFilename("Sound/" + filename));
|
||||
if (!decoder)
|
||||
return;
|
||||
|
||||
@ -389,10 +373,7 @@ namespace MWSound
|
||||
if(!mOutput->isInitialized())
|
||||
return;
|
||||
|
||||
std::string voicefile = "Sound/"+filename;
|
||||
|
||||
mVFS->normalizeFilename(voicefile);
|
||||
DecoderPtr decoder = loadVoice(voicefile);
|
||||
DecoderPtr decoder = loadVoice(mVFS->normalizeFilename("Sound/" + filename));
|
||||
if (!decoder)
|
||||
return;
|
||||
|
||||
|
@ -14,12 +14,36 @@
|
||||
#include <components/terrain/world.hpp>
|
||||
#include <components/sceneutil/unrefqueue.hpp>
|
||||
#include <components/esm/loadcell.hpp>
|
||||
#include <components/loadinglistener/reporter.hpp>
|
||||
|
||||
#include "../mwrender/landmanager.hpp"
|
||||
|
||||
#include "cellstore.hpp"
|
||||
#include "class.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
template <class Contained>
|
||||
bool contains(const std::vector<MWWorld::CellPreloader::PositionCellGrid>& container,
|
||||
const Contained& contained, float tolerance=1.f)
|
||||
{
|
||||
for (const auto& pos : contained)
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto& pos2 : container)
|
||||
{
|
||||
if ((pos.first-pos2.first).length2() < tolerance*tolerance && pos.second == pos2.second)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
||||
@ -94,7 +118,6 @@ namespace MWWorld
|
||||
{
|
||||
mesh = Misc::ResourceHelpers::correctActorModelPath(mesh, mSceneManager->getVFS());
|
||||
|
||||
bool animated = false;
|
||||
size_t slashpos = mesh.find_last_of("/\\");
|
||||
if (slashpos != std::string::npos && slashpos != mesh.size()-1)
|
||||
{
|
||||
@ -106,17 +129,11 @@ namespace MWWorld
|
||||
{
|
||||
kfname.replace(kfname.size()-4, 4, ".kf");
|
||||
if (mSceneManager->getVFS()->exists(kfname))
|
||||
{
|
||||
mPreloadedObjects.insert(mKeyframeManager->get(kfname));
|
||||
animated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mPreloadInstances && animated)
|
||||
mPreloadedObjects.insert(mSceneManager->cacheInstance(mesh));
|
||||
else
|
||||
mPreloadedObjects.insert(mSceneManager->getTemplate(mesh));
|
||||
mPreloadedObjects.insert(mSceneManager->getTemplate(mesh));
|
||||
if (mPreloadInstances)
|
||||
mPreloadedObjects.insert(mBulletShapeManager->cacheInstance(mesh));
|
||||
else
|
||||
@ -157,8 +174,6 @@ namespace MWWorld
|
||||
public:
|
||||
TerrainPreloadItem(const std::vector<osg::ref_ptr<Terrain::View> >& views, Terrain::World* world, const std::vector<CellPreloader::PositionCellGrid>& preloadPositions)
|
||||
: mAbort(false)
|
||||
, mProgress(views.size())
|
||||
, mProgressRange(0)
|
||||
, mTerrainViews(views)
|
||||
, mWorld(world)
|
||||
, mPreloadPositions(preloadPositions)
|
||||
@ -178,8 +193,9 @@ namespace MWWorld
|
||||
for (unsigned int i=0; i<mTerrainViews.size() && i<mPreloadPositions.size() && !mAbort; ++i)
|
||||
{
|
||||
mTerrainViews[i]->reset();
|
||||
mWorld->preload(mTerrainViews[i], mPreloadPositions[i].first, mPreloadPositions[i].second, mAbort, mProgress[i], mProgressRange);
|
||||
mWorld->preload(mTerrainViews[i], mPreloadPositions[i].first, mPreloadPositions[i].second, mAbort, mLoadingReporter);
|
||||
}
|
||||
mLoadingReporter.complete();
|
||||
}
|
||||
|
||||
void abort() override
|
||||
@ -187,16 +203,17 @@ namespace MWWorld
|
||||
mAbort = true;
|
||||
}
|
||||
|
||||
int getProgress() const { return !mProgress.empty() ? mProgress[0].load() : 0; }
|
||||
int getProgressRange() const { return !mProgress.empty() && mProgress[0].load() ? mProgressRange : 0; }
|
||||
void wait(Loading::Listener& listener) const
|
||||
{
|
||||
mLoadingReporter.wait(listener);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> mAbort;
|
||||
std::vector<std::atomic<int>> mProgress;
|
||||
int mProgressRange;
|
||||
std::vector<osg::ref_ptr<Terrain::View> > mTerrainViews;
|
||||
Terrain::World* mWorld;
|
||||
std::vector<CellPreloader::PositionCellGrid> mPreloadPositions;
|
||||
Loading::Reporter mLoadingReporter;
|
||||
};
|
||||
|
||||
/// Worker thread item: update the resource system's cache, effectively deleting unused entries.
|
||||
@ -230,6 +247,7 @@ namespace MWWorld
|
||||
, mPreloadInstances(true)
|
||||
, mLastResourceCacheUpdate(0.0)
|
||||
, mStoreViewsFailCount(0)
|
||||
, mLoadedTerrainTimestamp(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -375,7 +393,11 @@ namespace MWWorld
|
||||
setTerrainPreloadPositions(std::vector<PositionCellGrid>());
|
||||
}
|
||||
else
|
||||
{
|
||||
mStoreViewsFailCount = 0;
|
||||
mLoadedTerrainPositions = mTerrainPreloadPositions;
|
||||
mLoadedTerrainTimestamp = timestamp;
|
||||
}
|
||||
mTerrainPreloadItem = nullptr;
|
||||
}
|
||||
}
|
||||
@ -415,7 +437,7 @@ namespace MWWorld
|
||||
mUnrefQueue = unrefQueue;
|
||||
}
|
||||
|
||||
bool CellPreloader::syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, int& progress, int& progressRange, double timestamp)
|
||||
bool CellPreloader::syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, double timestamp, Loading::Listener& listener)
|
||||
{
|
||||
if (!mTerrainPreloadItem)
|
||||
return true;
|
||||
@ -435,18 +457,15 @@ namespace MWWorld
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = mTerrainPreloadItem->getProgress();
|
||||
progressRange = mTerrainPreloadItem->getProgressRange();
|
||||
return false;
|
||||
mTerrainPreloadItem->wait(listener);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid *exceptPos)
|
||||
{
|
||||
const float resetThreshold = ESM::Land::REAL_SIZE;
|
||||
for (const auto& pos : mTerrainPreloadPositions)
|
||||
if (exceptPos && (pos.first-exceptPos->first).length2() < resetThreshold*resetThreshold && pos.second == exceptPos->second)
|
||||
return;
|
||||
if (exceptPos && contains(mTerrainPreloadPositions, std::array {*exceptPos}, ESM::Land::REAL_SIZE))
|
||||
return;
|
||||
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
|
||||
{
|
||||
mTerrainPreloadItem->abort();
|
||||
@ -455,28 +474,13 @@ namespace MWWorld
|
||||
setTerrainPreloadPositions(std::vector<CellPreloader::PositionCellGrid>());
|
||||
}
|
||||
|
||||
bool contains(const std::vector<CellPreloader::PositionCellGrid>& container, const std::vector<CellPreloader::PositionCellGrid>& contained)
|
||||
{
|
||||
for (const auto& pos : contained)
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto& pos2 : container)
|
||||
{
|
||||
if ((pos.first-pos2.first).length2() < 1 && pos.second == pos2.second)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CellPreloader::setTerrainPreloadPositions(const std::vector<CellPreloader::PositionCellGrid> &positions)
|
||||
{
|
||||
if (positions.empty())
|
||||
{
|
||||
mTerrainPreloadPositions.clear();
|
||||
mLoadedTerrainPositions.clear();
|
||||
}
|
||||
else if (contains(mTerrainPreloadPositions, positions))
|
||||
return;
|
||||
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
|
||||
@ -503,5 +507,10 @@ namespace MWWorld
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CellPreloader::isTerrainLoaded(const CellPreloader::PositionCellGrid &position, double referenceTime) const
|
||||
{
|
||||
return mLoadedTerrainTimestamp + mResourceSystem->getSceneManager()->getExpiryDelay() > referenceTime && contains(mLoadedTerrainPositions, std::array {position}, ESM::Land::REAL_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,11 @@ namespace MWRender
|
||||
class LandManager;
|
||||
}
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class CellStore;
|
||||
@ -72,8 +77,9 @@ namespace MWWorld
|
||||
typedef std::pair<osg::Vec3f, osg::Vec4i> PositionCellGrid;
|
||||
void setTerrainPreloadPositions(const std::vector<PositionCellGrid>& positions);
|
||||
|
||||
bool syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, int& progress, int& progressRange, double timestamp);
|
||||
bool syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, double timestamp, Loading::Listener& listener);
|
||||
void abortTerrainPreloadExcept(const PositionCellGrid *exceptPos);
|
||||
bool isTerrainLoaded(const CellPreloader::PositionCellGrid &position, double referenceTime) const;
|
||||
|
||||
private:
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
@ -114,6 +120,9 @@ namespace MWWorld
|
||||
std::vector<PositionCellGrid> mTerrainPreloadPositions;
|
||||
osg::ref_ptr<TerrainPreloadItem> mTerrainPreloadItem;
|
||||
osg::ref_ptr<SceneUtil::WorkItem> mUpdateCacheItem;
|
||||
|
||||
std::vector<PositionCellGrid> mLoadedTerrainPositions;
|
||||
double mLoadedTerrainTimestamp;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -48,11 +48,6 @@ namespace MWWorld
|
||||
return mCellRef.mRefID;
|
||||
}
|
||||
|
||||
const std::string* CellRef::getRefIdPtr() const
|
||||
{
|
||||
return &mCellRef.mRefID;
|
||||
}
|
||||
|
||||
bool CellRef::getTeleport() const
|
||||
{
|
||||
return mCellRef.mTeleport;
|
||||
|
@ -38,8 +38,8 @@ namespace MWWorld
|
||||
// Id of object being referenced
|
||||
std::string getRefId() const;
|
||||
|
||||
// Pointer to ID of the object being referenced
|
||||
const std::string* getRefIdPtr() const;
|
||||
// Reference to ID of the object being referenced
|
||||
const std::string& getRefIdRef() const { return mCellRef.mRefID; }
|
||||
|
||||
// For doors - true if this door teleports to somewhere else, false
|
||||
// if it should open through animation.
|
||||
|
@ -36,7 +36,7 @@ namespace
|
||||
}
|
||||
bool cont = cell.second.forEach([&] (MWWorld::Ptr ptr)
|
||||
{
|
||||
if(*ptr.getCellRef().getRefIdPtr() == id)
|
||||
if (ptr.getCellRef().getRefIdRef() == id)
|
||||
{
|
||||
return visitor(ptr);
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ namespace
|
||||
{
|
||||
for (typename MWWorld::CellRefList<T>::List::iterator iter (collection.mList.begin());
|
||||
iter!=collection.mList.end(); ++iter)
|
||||
if (iter->mRef.getRefNum()==state.mRef.mRefNum && *iter->mRef.getRefIdPtr() == state.mRef.mRefID)
|
||||
if (iter->mRef.getRefNum()==state.mRef.mRefNum && iter->mRef.getRefIdRef() == state.mRef.mRefID)
|
||||
{
|
||||
// overwrite existing reference
|
||||
float oldscale = iter->mRef.getScale();
|
||||
@ -417,7 +417,7 @@ namespace MWWorld
|
||||
const std::string *mIdToFind;
|
||||
bool operator()(const PtrType& ptr)
|
||||
{
|
||||
if (*ptr.getCellRef().getRefIdPtr() == *mIdToFind)
|
||||
if (ptr.getCellRef().getRefIdRef() == *mIdToFind)
|
||||
{
|
||||
mFound = ptr;
|
||||
return false;
|
||||
|
@ -184,7 +184,7 @@ int MWWorld::ContainerStore::count(const std::string &id) const
|
||||
{
|
||||
int total=0;
|
||||
for (const auto&& iter : *this)
|
||||
if (Misc::StringUtils::ciEqual(iter.getCellRef().getRefId(), id))
|
||||
if (Misc::StringUtils::ciEqual(iter.getCellRef().getRefIdRef(), id))
|
||||
total += iter.getRefData().getCount();
|
||||
return total;
|
||||
}
|
||||
@ -249,7 +249,7 @@ bool MWWorld::ContainerStore::stacks(const ConstPtr& ptr1, const ConstPtr& ptr2)
|
||||
const MWWorld::Class& cls1 = ptr1.getClass();
|
||||
const MWWorld::Class& cls2 = ptr2.getClass();
|
||||
|
||||
if (!Misc::StringUtils::ciEqual(ptr1.getCellRef().getRefId(), ptr2.getCellRef().getRefId()))
|
||||
if (!Misc::StringUtils::ciEqual(ptr1.getCellRef().getRefIdRef(), ptr2.getCellRef().getRefIdRef()))
|
||||
return false;
|
||||
|
||||
// If it has an enchantment, don't stack when some of the charge is already used
|
||||
@ -364,7 +364,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImp (const Ptr& ptr,
|
||||
|
||||
for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual((*iter).getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId))
|
||||
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefIdRef(), MWWorld::ContainerStore::sGoldId))
|
||||
{
|
||||
iter->getRefData().setCount(addItems(iter->getRefData().getCount(false), realCount));
|
||||
flagAsModified();
|
||||
@ -465,7 +465,7 @@ int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const
|
||||
int toRemove = count;
|
||||
|
||||
for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter)
|
||||
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId))
|
||||
if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefIdRef(), itemId))
|
||||
toRemove -= remove(*iter, toRemove, actor, equipReplacement, resolveFirst);
|
||||
|
||||
flagAsModified();
|
||||
@ -740,7 +740,7 @@ MWWorld::Ptr MWWorld::ContainerStore::findReplacement(const std::string& id)
|
||||
for (auto&& iter : *this)
|
||||
{
|
||||
int iterHealth = iter.getClass().hasItemHealth(iter) ? iter.getClass().getItemHealth(iter) : 1;
|
||||
if (Misc::StringUtils::ciEqual(iter.getCellRef().getRefId(), id))
|
||||
if (Misc::StringUtils::ciEqual(iter.getCellRef().getRefIdRef(), id))
|
||||
{
|
||||
// Prefer the stack with the lowest remaining uses
|
||||
// Try to get item with zero durability only if there are no other items found
|
||||
|
@ -143,7 +143,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr,
|
||||
if (allowAutoEquip && actorPtr != MWMechanics::getPlayer()
|
||||
&& actorPtr.getClass().isNpc() && !actorPtr.getClass().getNpcStats(actorPtr).isWerewolf())
|
||||
{
|
||||
std::string type = itemPtr.getTypeName();
|
||||
const std::string& type = itemPtr.getTypeName();
|
||||
if (type == typeid(ESM::Armor).name() || type == typeid(ESM::Clothing).name())
|
||||
autoEquip(actorPtr);
|
||||
}
|
||||
@ -748,7 +748,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
|
||||
if (equipReplacement && wasEquipped && (actor != MWMechanics::getPlayer())
|
||||
&& actor.getClass().isNpc() && !actor.getClass().getNpcStats(actor).isWerewolf())
|
||||
{
|
||||
std::string type = item.getTypeName();
|
||||
const std::string& type = item.getTypeName();
|
||||
if (type == typeid(ESM::Armor).name() || type == typeid(ESM::Clothing).name())
|
||||
autoEquip(actor);
|
||||
}
|
||||
|
@ -628,7 +628,10 @@ namespace MWWorld
|
||||
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
|
||||
mRendering.setActiveGrid(newGrid);
|
||||
|
||||
preloadTerrain(pos, true);
|
||||
if (mRendering.pagingUnlockCache())
|
||||
mPreloader->abortTerrainPreloadExcept(nullptr);
|
||||
if (!mPreloader->isTerrainLoaded(std::make_pair(pos, newGrid), mRendering.getReferenceTime()))
|
||||
preloadTerrain(pos, true);
|
||||
mPagedRefs.clear();
|
||||
mRendering.getPagedRefnums(newGrid, mPagedRefs);
|
||||
|
||||
@ -742,14 +745,12 @@ namespace MWWorld
|
||||
{
|
||||
loadingListener->setLabel("Testing exterior cells ("+std::to_string(i)+"/"+std::to_string(cells.getExtSize())+")...");
|
||||
|
||||
CellStoreCollection::iterator iter = mActiveCells.begin();
|
||||
|
||||
CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(it->mData.mX, it->mData.mY);
|
||||
loadInactiveCell (cell, loadingListener, true);
|
||||
activateCell (cell, loadingListener, false, true);
|
||||
|
||||
iter = mActiveCells.begin();
|
||||
while (iter != mActiveCells.end())
|
||||
auto iter = mInactiveCells.begin();
|
||||
while (iter != mInactiveCells.end())
|
||||
{
|
||||
if (it->isExterior() && it->mData.mX == (*iter)->getCell()->getGridX() &&
|
||||
it->mData.mY == (*iter)->getCell()->getGridY())
|
||||
@ -796,8 +797,8 @@ namespace MWWorld
|
||||
loadInactiveCell (cell, loadingListener, true);
|
||||
activateCell (cell, loadingListener, false, true);
|
||||
|
||||
CellStoreCollection::iterator iter = mActiveCells.begin();
|
||||
while (iter != mActiveCells.end())
|
||||
auto iter = mInactiveCells.begin();
|
||||
while (iter != mInactiveCells.end())
|
||||
{
|
||||
assert (!(*iter)->getCell()->isExterior());
|
||||
|
||||
@ -1243,32 +1244,16 @@ namespace MWWorld
|
||||
{
|
||||
std::vector<PositionCellGrid> vec;
|
||||
vec.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos)));
|
||||
if (sync && mRendering.pagingUnlockCache())
|
||||
mPreloader->abortTerrainPreloadExcept(nullptr);
|
||||
else
|
||||
mPreloader->abortTerrainPreloadExcept(&vec[0]);
|
||||
mPreloader->abortTerrainPreloadExcept(&vec[0]);
|
||||
mPreloader->setTerrainPreloadPositions(vec);
|
||||
if (!sync) return;
|
||||
|
||||
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||
Loading::ScopedLoad load(loadingListener);
|
||||
int progress = 0, initialProgress = -1, progressRange = 0;
|
||||
while (!mPreloader->syncTerrainLoad(vec, progress, progressRange, mRendering.getReferenceTime()))
|
||||
{
|
||||
if (initialProgress == -1)
|
||||
{
|
||||
loadingListener->setLabel("#{sLoadingMessage4}");
|
||||
initialProgress = progress;
|
||||
}
|
||||
if (progress)
|
||||
{
|
||||
loadingListener->setProgressRange(std::max(0, progressRange-initialProgress));
|
||||
loadingListener->setProgress(progress-initialProgress);
|
||||
}
|
||||
else
|
||||
loadingListener->setProgress(0);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
loadingListener->setLabel("#{sLoadingMessage4}");
|
||||
|
||||
while (!mPreloader->syncTerrainLoad(vec, mRendering.getReferenceTime(), *loadingListener)) {}
|
||||
}
|
||||
|
||||
void Scene::reloadTerrain()
|
||||
|
@ -520,7 +520,8 @@ namespace MWWorld
|
||||
const ESM::Cell *Store<ESM::Cell>::search(int x, int y) const
|
||||
{
|
||||
ESM::Cell cell;
|
||||
cell.mData.mX = x, cell.mData.mY = y;
|
||||
cell.mData.mX = x;
|
||||
cell.mData.mY = y;
|
||||
|
||||
std::pair<int, int> key(x, y);
|
||||
DynamicExt::const_iterator it = mExt.find(key);
|
||||
@ -538,7 +539,8 @@ namespace MWWorld
|
||||
const ESM::Cell *Store<ESM::Cell>::searchStatic(int x, int y) const
|
||||
{
|
||||
ESM::Cell cell;
|
||||
cell.mData.mX = x, cell.mData.mY = y;
|
||||
cell.mData.mX = x;
|
||||
cell.mData.mY = y;
|
||||
|
||||
std::pair<int, int> key(x, y);
|
||||
DynamicExt::const_iterator it = mExt.find(key);
|
||||
|
@ -428,7 +428,7 @@ namespace MWWorld
|
||||
const ESM::WeaponType *search(const int id) const;
|
||||
const ESM::WeaponType *find(const int id) const;
|
||||
|
||||
RecordId load(ESM::ESMReader &esm) override { return RecordId(nullptr, false); }
|
||||
RecordId load(ESM::ESMReader &esm) override { return RecordId({}, false); }
|
||||
|
||||
ESM::WeaponType* insert(const ESM::WeaponType &weaponType);
|
||||
|
||||
|
@ -77,6 +77,14 @@ return {
|
||||
EXPECT_EQ(LuaUtil::call(script1["get"]).get<int>(), 45);
|
||||
}
|
||||
|
||||
TEST_F(LuaStateTest, ToString)
|
||||
{
|
||||
EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.sol(), 3.14)), "3.14");
|
||||
EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.sol(), true)), "true");
|
||||
EXPECT_EQ(LuaUtil::toString(sol::nil), "nil");
|
||||
EXPECT_EQ(LuaUtil::toString(sol::make_object(mLua.sol(), "something")), "\"something\"");
|
||||
}
|
||||
|
||||
TEST_F(LuaStateTest, ErrorHandling)
|
||||
{
|
||||
EXPECT_ERROR(mLua.runInNewSandbox("invalid.lua"), "[string \"invalid.lua\"]:1:");
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "gmock/gmock.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/lua/utilpackage.hpp>
|
||||
|
||||
#include "testing_util.hpp"
|
||||
@ -45,6 +46,7 @@ namespace
|
||||
EXPECT_FLOAT_EQ(lua.safe_script("return v.y").get<float>(), 12);
|
||||
EXPECT_FLOAT_EQ(lua.safe_script("return v.z").get<float>(), 13);
|
||||
EXPECT_EQ(lua.safe_script("return tostring(v)").get<std::string>(), "(5, 12, 13)");
|
||||
EXPECT_EQ(LuaUtil::toString(lua.safe_script("return v")), "(5, 12, 13)");
|
||||
EXPECT_FLOAT_EQ(lua.safe_script("return util.vector3(4, 0, 3):length()").get<float>(), 5);
|
||||
EXPECT_FLOAT_EQ(lua.safe_script("return util.vector3(4, 0, 3):length2()").get<float>(), 25);
|
||||
EXPECT_FALSE(lua.safe_script("return util.vector3(1, 2, 3) == util.vector3(1, 3, 2)").get<bool>());
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "components/misc/stringops.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
struct PartialBinarySearchTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
@ -12,10 +16,6 @@ struct PartialBinarySearchTest : public ::testing::Test
|
||||
std::sort(mDataVec.begin(), mDataVec.end(), Misc::StringUtils::ciLess);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
}
|
||||
|
||||
bool matches(const std::string& keyword)
|
||||
{
|
||||
return Misc::StringUtils::partialBinarySearch(mDataVec.begin(), mDataVec.end(), keyword) != mDataVec.end();
|
||||
@ -51,3 +51,97 @@ TEST_F (PartialBinarySearchTest, ci_test)
|
||||
std::string unicode1 = "\u04151 \u0418"; // CYRILLIC CAPITAL LETTER IE, CYRILLIC CAPITAL LETTER I
|
||||
EXPECT_TRUE( Misc::StringUtils::lowerCase(unicode1) == unicode1 );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
using ::Misc::StringUtils;
|
||||
using namespace ::testing;
|
||||
|
||||
template <class T>
|
||||
struct MiscStringUtilsCiEqualEmptyTest : Test {};
|
||||
|
||||
TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualEmptyTest);
|
||||
|
||||
TYPED_TEST_P(MiscStringUtilsCiEqualEmptyTest, empty_strings_should_be_equal)
|
||||
{
|
||||
EXPECT_TRUE(StringUtils::ciEqual(typename TypeParam::first_type {}, typename TypeParam::second_type {}));
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualEmptyTest,
|
||||
empty_strings_should_be_equal
|
||||
);
|
||||
|
||||
using EmptyStringTypePairsTypes = Types<
|
||||
std::pair<std::string, std::string>,
|
||||
std::pair<std::string, std::string_view>,
|
||||
std::pair<std::string, const char[1]>,
|
||||
std::pair<std::string_view, std::string>,
|
||||
std::pair<std::string_view, std::string_view>,
|
||||
std::pair<std::string_view, const char[1]>,
|
||||
std::pair<const char[1], std::string>,
|
||||
std::pair<const char[1], std::string_view>,
|
||||
std::pair<const char[1], const char[1]>
|
||||
>;
|
||||
|
||||
INSTANTIATE_TYPED_TEST_SUITE_P(EmptyStringTypePairs, MiscStringUtilsCiEqualEmptyTest, EmptyStringTypePairsTypes);
|
||||
|
||||
template <class T>
|
||||
struct MiscStringUtilsCiEqualNotEmptyTest : Test {};
|
||||
|
||||
TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualNotEmptyTest);
|
||||
|
||||
using RawValue = const char[4];
|
||||
|
||||
constexpr RawValue foo = "foo";
|
||||
constexpr RawValue fooUpper = "FOO";
|
||||
constexpr RawValue bar = "bar";
|
||||
|
||||
template <typename T>
|
||||
using Value = std::conditional_t<std::is_same_v<T, RawValue>, RawValue&, T>;
|
||||
|
||||
TYPED_TEST_P(MiscStringUtilsCiEqualNotEmptyTest, same_strings_should_be_equal)
|
||||
{
|
||||
const Value<typename TypeParam::first_type> a {foo};
|
||||
const Value<typename TypeParam::second_type> b {foo};
|
||||
EXPECT_TRUE(StringUtils::ciEqual(a, b)) << a << "\n" << b;
|
||||
}
|
||||
|
||||
TYPED_TEST_P(MiscStringUtilsCiEqualNotEmptyTest, same_strings_with_different_case_sensetivity_should_be_equal)
|
||||
{
|
||||
const Value<typename TypeParam::first_type> a {foo};
|
||||
const Value<typename TypeParam::second_type> b {fooUpper};
|
||||
EXPECT_TRUE(StringUtils::ciEqual(a, b)) << a << "\n" << b;
|
||||
}
|
||||
|
||||
TYPED_TEST_P(MiscStringUtilsCiEqualNotEmptyTest, different_strings_content_should_not_be_equal)
|
||||
{
|
||||
const Value<typename TypeParam::first_type> a {foo};
|
||||
const Value<typename TypeParam::second_type> b {bar};
|
||||
EXPECT_FALSE(StringUtils::ciEqual(a, b)) << a << "\n" << b;
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualNotEmptyTest,
|
||||
same_strings_should_be_equal,
|
||||
same_strings_with_different_case_sensetivity_should_be_equal,
|
||||
different_strings_content_should_not_be_equal
|
||||
);
|
||||
|
||||
using NotEmptyStringTypePairsTypes = Types<
|
||||
std::pair<std::string, std::string>,
|
||||
std::pair<std::string, std::string_view>,
|
||||
std::pair<std::string, const char[4]>,
|
||||
std::pair<std::string_view, std::string>,
|
||||
std::pair<std::string_view, std::string_view>,
|
||||
std::pair<std::string_view, const char[4]>,
|
||||
std::pair<const char[4], std::string>,
|
||||
std::pair<const char[4], std::string_view>,
|
||||
std::pair<const char[4], const char[4]>
|
||||
>;
|
||||
|
||||
INSTANTIATE_TYPED_TEST_SUITE_P(NotEmptyStringTypePairs, MiscStringUtilsCiEqualNotEmptyTest, NotEmptyStringTypePairsTypes);
|
||||
|
||||
TEST(MiscStringUtilsCiEqualTest, string_with_different_length_should_not_be_equal)
|
||||
{
|
||||
EXPECT_FALSE(StringUtils::ciEqual(std::string("a"), std::string("aa")));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
set(WIZARD
|
||||
componentselectionpage.cpp
|
||||
conclusionpage.cpp
|
||||
@ -34,21 +33,6 @@ set(WIZARD_HEADER
|
||||
utils/componentlistwidget.hpp
|
||||
)
|
||||
|
||||
# Headers that must be pre-processed
|
||||
set(WIZARD_HEADER_MOC
|
||||
componentselectionpage.hpp
|
||||
conclusionpage.hpp
|
||||
existinginstallationpage.hpp
|
||||
importpage.hpp
|
||||
installationtargetpage.hpp
|
||||
intropage.hpp
|
||||
languageselectionpage.hpp
|
||||
mainwizard.hpp
|
||||
methodselectionpage.hpp
|
||||
|
||||
utils/componentlistwidget.hpp
|
||||
)
|
||||
|
||||
set(WIZARD_UI
|
||||
${CMAKE_SOURCE_DIR}/files/ui/wizard/componentselectionpage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/wizard/conclusionpage.ui
|
||||
@ -63,7 +47,6 @@ set(WIZARD_UI
|
||||
if (OPENMW_USE_UNSHIELD)
|
||||
set (WIZARD ${WIZARD} installationpage.cpp unshield/unshieldworker.cpp)
|
||||
set (WIZARD_HEADER ${WIZARD_HEADER} installationpage.hpp unshield/unshieldworker.hpp)
|
||||
set (WIZARD_HEADER_MOC ${WIZARD_HEADER_MOC} installationpage.hpp unshield/unshieldworker.hpp)
|
||||
set (WIZARD_UI ${WIZARD_UI} ${CMAKE_SOURCE_DIR}/files/ui/wizard/installationpage.ui)
|
||||
add_definitions(-DOPENMW_USE_UNSHIELD)
|
||||
endif (OPENMW_USE_UNSHIELD)
|
||||
@ -80,7 +63,6 @@ if(WIN32)
|
||||
endif(WIN32)
|
||||
|
||||
QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/wizard/wizard.qrc)
|
||||
QT5_WRAP_CPP(MOC_SRCS ${WIZARD_HEADER_MOC})
|
||||
QT5_WRAP_UI(UI_HDRS ${WIZARD_UI})
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
@ -94,7 +76,6 @@ openmw_add_executable(openmw-wizard
|
||||
${WIZARD}
|
||||
${WIZARD_HEADER}
|
||||
${RCC_SRCS}
|
||||
${MOC_SRCS}
|
||||
${UI_HDRS}
|
||||
)
|
||||
|
||||
@ -125,3 +106,7 @@ endif()
|
||||
if (WIN32)
|
||||
INSTALL(TARGETS openmw-wizard RUNTIME DESTINATION ".")
|
||||
endif(WIN32)
|
||||
|
||||
if(USE_QT)
|
||||
set_property(TARGET openmw-wizard PROPERTY AUTOMOC ON)
|
||||
endif(USE_QT)
|
||||
|
@ -80,10 +80,6 @@ foreach (f ${ALL})
|
||||
list (APPEND files "${f}")
|
||||
list (APPEND COMPONENT_QT_FILES "${f}")
|
||||
endforeach (f)
|
||||
file (GLOB MOC_H "${dir}/${u}.hpp")
|
||||
foreach (fi ${MOC_H})
|
||||
list (APPEND COMPONENT_MOC_FILES "${fi}")
|
||||
endforeach (fi)
|
||||
endforeach (u)
|
||||
source_group ("components\\${dir}" FILES ${files})
|
||||
endmacro (add_component_qt_dir)
|
||||
@ -97,44 +93,21 @@ add_file (${project} _HDR ${comp} "${dir}/${unit}.hpp")
|
||||
add_file (${project} _SRC ${comp} "${dir}/${unit}.cpp")
|
||||
endmacro (add_unit)
|
||||
|
||||
macro (add_qt_unit project dir unit)
|
||||
add_file (${project} _HDR ${comp} "${dir}/${unit}.hpp")
|
||||
add_file (${project} _HDR_QT ${comp} "${dir}/${unit}.hpp")
|
||||
add_file (${project} _SRC ${comp} "${dir}/${unit}.cpp")
|
||||
endmacro (add_qt_unit)
|
||||
|
||||
macro (add_hdr project dir unit)
|
||||
add_file (${project} _HDR ${comp} "${dir}/${unit}.hpp")
|
||||
endmacro (add_hdr)
|
||||
|
||||
macro (add_qt_hdr project dir unit)
|
||||
add_file (${project} _HDR ${comp} "${dir}/${unit}.hpp")
|
||||
add_file (${project} _HDR_QT ${comp} "${dir}/${unit}.hpp")
|
||||
endmacro (add_qt_hdr)
|
||||
|
||||
macro (opencs_units dir)
|
||||
foreach (u ${ARGN})
|
||||
add_qt_unit (OPENCS ${dir} ${u})
|
||||
endforeach (u)
|
||||
endmacro (opencs_units)
|
||||
|
||||
macro (opencs_units_noqt dir)
|
||||
foreach (u ${ARGN})
|
||||
add_unit (OPENCS ${dir} ${u})
|
||||
endforeach (u)
|
||||
endmacro (opencs_units_noqt)
|
||||
endmacro (opencs_units)
|
||||
|
||||
macro (opencs_hdrs dir)
|
||||
foreach (u ${ARGN})
|
||||
add_qt_hdr (OPENCS ${dir} ${u})
|
||||
endforeach (u)
|
||||
endmacro (opencs_hdrs)
|
||||
|
||||
macro (opencs_hdrs_noqt dir)
|
||||
foreach (u ${ARGN})
|
||||
add_hdr (OPENCS ${dir} ${u})
|
||||
endforeach (u)
|
||||
endmacro (opencs_hdrs_noqt)
|
||||
endmacro (opencs_hdrs)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
|
@ -197,6 +197,10 @@ add_component_dir(detournavigator
|
||||
navmeshcacheitem
|
||||
)
|
||||
|
||||
add_component_dir(loadinglistener
|
||||
reporter
|
||||
)
|
||||
|
||||
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||
)
|
||||
|
||||
@ -222,7 +226,6 @@ if (USE_QT)
|
||||
)
|
||||
|
||||
QT5_WRAP_UI(ESM_UI_HDR ${ESM_UI})
|
||||
QT5_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES})
|
||||
endif()
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
@ -276,7 +279,7 @@ if (WIN32)
|
||||
endif()
|
||||
|
||||
if (USE_QT)
|
||||
add_library(components_qt STATIC ${COMPONENT_QT_FILES} ${MOC_SRCS} ${ESM_UI_HDR})
|
||||
add_library(components_qt STATIC ${COMPONENT_QT_FILES} ${ESM_UI_HDR})
|
||||
target_link_libraries(components_qt components Qt5::Widgets Qt5::Core)
|
||||
target_compile_definitions(components_qt PRIVATE OPENMW_DOC_BASEURL="${OPENMW_DOC_BASEURL}")
|
||||
endif()
|
||||
@ -285,6 +288,15 @@ if (GIT_CHECKOUT)
|
||||
add_dependencies (components git-version)
|
||||
endif (GIT_CHECKOUT)
|
||||
|
||||
if (OSG_STATIC AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
find_package(X11 REQUIRED COMPONENTS Xinerama Xrandr)
|
||||
target_link_libraries(components ${CMAKE_DL_LIBS} X11::X11 X11::Xinerama X11::Xrandr)
|
||||
find_package(Fontconfig MODULE)
|
||||
if(Fontconfig_FOUND)
|
||||
target_link_libraries(components Fontconfig::Fontconfig)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(components shlwapi)
|
||||
endif()
|
||||
@ -304,3 +316,35 @@ endif()
|
||||
set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE)
|
||||
|
||||
target_compile_definitions(components PUBLIC BT_USE_DOUBLE_PRECISION)
|
||||
|
||||
if(OSG_STATIC)
|
||||
unset(_osg_plugins_static_files)
|
||||
add_library(components_osg_plugins INTERFACE)
|
||||
foreach(_plugin ${USED_OSG_PLUGINS})
|
||||
string(TOUPPER ${_plugin} _plugin_uc)
|
||||
if(OPENMW_USE_SYSTEM_OSG)
|
||||
list(APPEND _osg_plugins_static_files ${${_plugin_uc}_LIBRARY})
|
||||
else()
|
||||
list(APPEND _osg_plugins_static_files $<TARGET_FILE:${${_plugin_uc}_LIBRARY}>)
|
||||
target_link_libraries(components_osg_plugins INTERFACE $<TARGET_PROPERTY:${${_plugin_uc}_LIBRARY},LINK_LIBRARIES>)
|
||||
add_dependencies(components_osg_plugins ${${_plugin_uc}_LIBRARY})
|
||||
endif()
|
||||
endforeach()
|
||||
# We use --whole-archive because OSG plugins use registration.
|
||||
get_whole_archive_options(_opts ${_osg_plugins_static_files})
|
||||
target_link_options(components_osg_plugins INTERFACE ${_opts})
|
||||
target_link_libraries(components components_osg_plugins)
|
||||
|
||||
if(OPENMW_USE_SYSTEM_OSG)
|
||||
# OSG plugin pkgconfig files are missing these dependencies.
|
||||
# https://github.com/openscenegraph/OpenSceneGraph/issues/1052
|
||||
find_package(Freetype REQUIRED)
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
target_link_libraries(components Freetype::Freetype JPEG::JPEG PNG::PNG)
|
||||
endif()
|
||||
endif(OSG_STATIC)
|
||||
|
||||
if(USE_QT)
|
||||
set_property(TARGET components_qt PROPERTY AUTOMOC ON)
|
||||
endif(USE_QT)
|
||||
|
@ -27,7 +27,7 @@ namespace DetourNavigator
|
||||
|
||||
std::optional<RemovedRecastMeshObject> CachedRecastMeshManager::removeObject(const ObjectId id)
|
||||
{
|
||||
const auto object = mImpl.removeObject(id);
|
||||
auto object = mImpl.removeObject(id);
|
||||
if (object)
|
||||
mCached.lock()->reset();
|
||||
return object;
|
||||
|
@ -248,7 +248,7 @@ namespace DetourNavigator
|
||||
const auto tile = tiles.find(tilePosition);
|
||||
if (tile == tiles.end())
|
||||
return std::optional<RemovedRecastMeshObject>();
|
||||
const auto tileResult = tile->second->removeObject(id);
|
||||
auto tileResult = tile->second->removeObject(id);
|
||||
if (tile->second->isEmpty())
|
||||
{
|
||||
tiles.erase(tile);
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <components/myguiplatform/myguitexture.hpp>
|
||||
@ -191,24 +192,10 @@ namespace Gui
|
||||
|
||||
void FontLoader::loadBitmapFonts(bool exportToFile)
|
||||
{
|
||||
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
||||
|
||||
std::string pattern = "Fonts/";
|
||||
mVFS->normalizeFilename(pattern);
|
||||
|
||||
std::map<std::string, VFS::File*>::const_iterator found = index.lower_bound(pattern);
|
||||
while (found != index.end())
|
||||
for (const auto& name : mVFS->getRecursiveDirectoryIterator("Fonts/"))
|
||||
{
|
||||
const std::string& name = found->first;
|
||||
if (name.size() >= pattern.size() && name.substr(0, pattern.size()) == pattern)
|
||||
{
|
||||
size_t pos = name.find_last_of('.');
|
||||
if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".fnt") == 0)
|
||||
loadBitmapFont(name, exportToFile);
|
||||
}
|
||||
else
|
||||
break;
|
||||
++found;
|
||||
if (Misc::getFileExtension(name) == "fnt")
|
||||
loadBitmapFont(name, exportToFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
41
components/loadinglistener/reporter.cpp
Normal file
41
components/loadinglistener/reporter.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "reporter.hpp"
|
||||
#include "loadinglistener.hpp"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
void Reporter::addTotal(std::size_t value)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
mTotal += value;
|
||||
mUpdated.notify_all();
|
||||
}
|
||||
|
||||
void Reporter::addProgress(std::size_t value)
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
mProgress += value;
|
||||
mUpdated.notify_all();
|
||||
}
|
||||
|
||||
void Reporter::complete()
|
||||
{
|
||||
const std::lock_guard lock(mMutex);
|
||||
mDone = true;
|
||||
mUpdated.notify_all();
|
||||
}
|
||||
|
||||
void Reporter::wait(Listener& listener) const
|
||||
{
|
||||
std::unique_lock lock(mMutex);
|
||||
while (!mDone)
|
||||
{
|
||||
listener.setProgressRange(mTotal);
|
||||
listener.setProgress(mProgress);
|
||||
mUpdated.wait(lock);
|
||||
}
|
||||
}
|
||||
}
|
32
components/loadinglistener/reporter.hpp
Normal file
32
components/loadinglistener/reporter.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef COMPONENTS_LOADINGLISTENER_REPORTER_H
|
||||
#define COMPONENTS_LOADINGLISTENER_REPORTER_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
|
||||
class Reporter
|
||||
{
|
||||
public:
|
||||
void addTotal(std::size_t value);
|
||||
|
||||
void addProgress(std::size_t value);
|
||||
|
||||
void complete();
|
||||
|
||||
void wait(Listener& listener) const;
|
||||
|
||||
private:
|
||||
std::size_t mProgress = 0;
|
||||
std::size_t mTotal = 0;
|
||||
bool mDone = false;
|
||||
mutable std::mutex mMutex;
|
||||
mutable std::condition_variable mUpdated;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -167,4 +167,14 @@ namespace LuaUtil
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string toString(const sol::object& obj)
|
||||
{
|
||||
if (obj == sol::nil)
|
||||
return "nil";
|
||||
else if (obj.get_type() == sol::type::string)
|
||||
return "\"" + obj.as<std::string>() + "\"";
|
||||
else
|
||||
return call(sol::state_view(obj.lua_state())["tostring"], obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -103,6 +103,9 @@ namespace LuaUtil
|
||||
return getFieldOrNil(table.as<sol::table>()[first], str...);
|
||||
}
|
||||
|
||||
// String representation of a Lua object. Should be used for debugging/logging purposes only.
|
||||
std::string toString(const sol::object&);
|
||||
|
||||
}
|
||||
|
||||
#endif // COMPONENTS_LUA_LUASTATE_H
|
||||
|
19
components/misc/pathhelpers.hpp
Normal file
19
components/misc/pathhelpers.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef OPENMW_COMPONENTS_MISC_PATHHELPERS_H
|
||||
#define OPENMW_COMPONENTS_MISC_PATHHELPERS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
inline std::string_view getFileExtension(std::string_view file)
|
||||
{
|
||||
if (auto extPos = file.find_last_of('.'); extPos != std::string::npos)
|
||||
{
|
||||
file.remove_prefix(extPos + 1);
|
||||
return file;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -4,6 +4,8 @@
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
|
||||
#include "utf8stream.hpp"
|
||||
|
||||
@ -109,18 +111,34 @@ public:
|
||||
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci());
|
||||
}
|
||||
|
||||
static bool ciEqual(const std::string &x, const std::string &y) {
|
||||
if (x.size() != y.size()) {
|
||||
template <class X, class Y>
|
||||
static bool ciEqual(const X& x, const Y& y)
|
||||
{
|
||||
if (std::size(x) != std::size(y))
|
||||
return false;
|
||||
}
|
||||
std::string::const_iterator xit = x.begin();
|
||||
std::string::const_iterator yit = y.begin();
|
||||
for (; xit != x.end(); ++xit, ++yit) {
|
||||
if (toLower(*xit) != toLower(*yit)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return std::equal(std::begin(x), std::end(x), std::begin(y),
|
||||
[] (char l, char r) { return toLower(l) == toLower(r); });
|
||||
}
|
||||
|
||||
template <std::size_t n>
|
||||
static auto ciEqual(const char(& x)[n], const char(& y)[n])
|
||||
{
|
||||
static_assert(n > 0);
|
||||
return ciEqual(std::string_view(x, n - 1), std::string_view(y, n - 1));
|
||||
}
|
||||
|
||||
template <std::size_t n, class T>
|
||||
static auto ciEqual(const char(& x)[n], const T& y)
|
||||
{
|
||||
static_assert(n > 0);
|
||||
return ciEqual(std::string_view(x, n - 1), y);
|
||||
}
|
||||
|
||||
template <std::size_t n, class T>
|
||||
static auto ciEqual(const T& x, const char(& y)[n])
|
||||
{
|
||||
static_assert(n > 0);
|
||||
return ciEqual(x, std::string_view(y, n - 1));
|
||||
}
|
||||
|
||||
static int ciCompareLen(const std::string &x, const std::string &y, size_t len)
|
||||
@ -157,9 +175,9 @@ public:
|
||||
}
|
||||
|
||||
/// Returns lower case copy of input string
|
||||
static std::string lowerCase(const std::string &in)
|
||||
static std::string lowerCase(std::string_view in)
|
||||
{
|
||||
std::string out = in;
|
||||
std::string out(in);
|
||||
lowerCaseInPlace(out);
|
||||
return out;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ btCollisionShape* BulletShape::duplicateCollisionShape(const btCollisionShape *s
|
||||
for(int i = 0;i < numShapes;++i)
|
||||
{
|
||||
btCollisionShape *child = duplicateCollisionShape(comp->getChildShape(i));
|
||||
btTransform trans = comp->getChildTransform(i);
|
||||
const btTransform& trans = comp->getChildTransform(i);
|
||||
newShape->addChildShape(trans, child);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <BulletCollision/CollisionShapes/btTriangleMesh.h>
|
||||
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
@ -121,8 +122,7 @@ BulletShapeManager::~BulletShapeManager()
|
||||
|
||||
osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string &name)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<BulletShape> shape;
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
@ -130,12 +130,7 @@ osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string &
|
||||
shape = osg::ref_ptr<BulletShape>(static_cast<BulletShape*>(obj.get()));
|
||||
else
|
||||
{
|
||||
size_t extPos = normalized.find_last_of('.');
|
||||
std::string ext;
|
||||
if (extPos != std::string::npos && extPos+1 < normalized.size())
|
||||
ext = normalized.substr(extPos+1);
|
||||
|
||||
if (ext == "nif")
|
||||
if (Misc::getFileExtension(normalized) == "nif")
|
||||
{
|
||||
NifBullet::BulletNifLoader loader;
|
||||
shape = loader.load(*mNifFileManager->get(normalized));
|
||||
@ -180,8 +175,7 @@ osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string &
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::cacheInstance(const std::string &name)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> instance = createInstance(normalized);
|
||||
if (instance)
|
||||
@ -191,8 +185,7 @@ osg::ref_ptr<BulletShapeInstance> BulletShapeManager::cacheInstance(const std::s
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::getInstance(const std::string &name)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mInstanceCache->takeFromObjectCache(normalized);
|
||||
if (obj.get())
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
#include "objectcache.hpp"
|
||||
@ -83,8 +84,7 @@ namespace Resource
|
||||
|
||||
osg::ref_ptr<osg::Image> ImageManager::getImage(const std::string &filename)
|
||||
{
|
||||
std::string normalized = filename;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
const std::string normalized = mVFS->normalizeFilename(filename);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
if (obj)
|
||||
@ -103,10 +103,7 @@ namespace Resource
|
||||
return mWarningImage;
|
||||
}
|
||||
|
||||
size_t extPos = normalized.find_last_of('.');
|
||||
std::string ext;
|
||||
if (extPos != std::string::npos && extPos+1 < normalized.size())
|
||||
ext = normalized.substr(extPos+1);
|
||||
const std::string ext(Misc::getFileExtension(normalized));
|
||||
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
|
||||
if (!reader)
|
||||
{
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
#include <components/sceneutil/keyframe.hpp>
|
||||
#include <components/sceneutil/osgacontroller.hpp>
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "animation.hpp"
|
||||
@ -30,7 +31,7 @@ namespace Resource
|
||||
|
||||
std::vector<SceneUtil::EmulatedAnimation> emulatedAnimations;
|
||||
|
||||
for (auto animation : mAnimationManager->getAnimationList())
|
||||
for (const auto& animation : mAnimationManager->getAnimationList())
|
||||
{
|
||||
if (animation)
|
||||
{
|
||||
@ -133,8 +134,7 @@ namespace Resource
|
||||
|
||||
osg::ref_ptr<const SceneUtil::KeyframeHolder> KeyframeManager::get(const std::string &name)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
if (obj)
|
||||
@ -142,8 +142,7 @@ namespace Resource
|
||||
else
|
||||
{
|
||||
osg::ref_ptr<SceneUtil::KeyframeHolder> loaded (new SceneUtil::KeyframeHolder);
|
||||
std::string ext = Resource::getFileExtension(normalized);
|
||||
if (ext == "kf")
|
||||
if (Misc::getFileExtension(normalized) == "kf")
|
||||
{
|
||||
NifOsg::Loader::loadKf(Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get());
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ namespace Resource
|
||||
|
||||
/// How long to keep objects in cache after no longer being referenced.
|
||||
void setExpiryDelay (double expiryDelay) override { mExpiryDelay = expiryDelay; }
|
||||
float getExpiryDelay() const { return mExpiryDelay; }
|
||||
|
||||
const VFS::Manager* getVFS() const { return mVFS; }
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
#include <components/nif/niffile.hpp>
|
||||
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
@ -358,10 +359,7 @@ namespace Resource
|
||||
|
||||
bool SceneManager::checkLoaded(const std::string &name, double timeStamp)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
|
||||
return mCache->checkInObjectCache(normalized, timeStamp);
|
||||
return mCache->checkInObjectCache(mVFS->normalizeFilename(name), timeStamp);
|
||||
}
|
||||
|
||||
/// @brief Callback to read image files from the VFS.
|
||||
@ -391,12 +389,12 @@ namespace Resource
|
||||
|
||||
osg::ref_ptr<osg::Node> load (const std::string& normalizedFilename, const VFS::Manager* vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager)
|
||||
{
|
||||
std::string ext = Resource::getFileExtension(normalizedFilename);
|
||||
auto ext = Misc::getFileExtension(normalizedFilename);
|
||||
if (ext == "nif")
|
||||
return NifOsg::Loader::load(nifFileManager->get(normalizedFilename), imageManager);
|
||||
else
|
||||
{
|
||||
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
|
||||
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(std::string(ext));
|
||||
if (!reader)
|
||||
{
|
||||
std::stringstream errormsg;
|
||||
@ -533,8 +531,7 @@ namespace Resource
|
||||
|
||||
osg::ref_ptr<const osg::Node> SceneManager::getTemplate(const std::string &name, bool compile)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
std::string normalized = mVFS->normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
if (obj)
|
||||
@ -603,8 +600,7 @@ namespace Resource
|
||||
|
||||
osg::ref_ptr<osg::Node> SceneManager::cacheInstance(const std::string &name)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Node> node = createInstance(normalized);
|
||||
|
||||
@ -642,8 +638,7 @@ namespace Resource
|
||||
|
||||
osg::ref_ptr<osg::Node> SceneManager::getInstance(const std::string &name)
|
||||
{
|
||||
std::string normalized = name;
|
||||
mVFS->normalizeFilename(normalized);
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mInstanceCache->takeFromObjectCache(normalized);
|
||||
if (obj.get())
|
||||
@ -822,12 +817,4 @@ namespace Resource
|
||||
shaderVisitor->setTranslucentFramebuffer(translucentFramebuffer);
|
||||
return shaderVisitor;
|
||||
}
|
||||
|
||||
std::string getFileExtension(const std::string& file)
|
||||
{
|
||||
size_t extPos = file.find_last_of('.');
|
||||
if (extPos != std::string::npos && extPos+1 < file.size())
|
||||
return file.substr(extPos+1);
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <components/sceneutil/skeleton.hpp>
|
||||
|
||||
#include "visitor.hpp"
|
||||
#include "clone.hpp"
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
@ -49,10 +50,10 @@ namespace SceneUtil
|
||||
return;
|
||||
|
||||
osg::Node* node = &drawable;
|
||||
while (node->getNumParents())
|
||||
for (auto it = getNodePath().rbegin()+1; it != getNodePath().rend(); ++it)
|
||||
{
|
||||
osg::Group* parent = node->getParent(0);
|
||||
if (!parent || !filterMatches(parent->getName()))
|
||||
osg::Node* parent = *it;
|
||||
if (!filterMatches(parent->getName()))
|
||||
break;
|
||||
node = parent;
|
||||
}
|
||||
@ -63,12 +64,7 @@ namespace SceneUtil
|
||||
{
|
||||
for (const osg::ref_ptr<osg::Node>& node : mToCopy)
|
||||
{
|
||||
if (node->getNumParents() > 1)
|
||||
Log(Debug::Error) << "Error CopyRigVisitor: node has " << node->getNumParents() << " parents";
|
||||
while (node->getNumParents())
|
||||
node->getParent(0)->removeChild(node);
|
||||
|
||||
mParent->addChild(node);
|
||||
mParent->addChild(static_cast<osg::Node*>(node->clone(SceneUtil::CopyOp())));
|
||||
}
|
||||
mToCopy.clear();
|
||||
}
|
||||
@ -90,25 +86,28 @@ namespace SceneUtil
|
||||
std::string mFilter2;
|
||||
};
|
||||
|
||||
void mergeUserData(osg::UserDataContainer* source, osg::Object* target)
|
||||
void mergeUserData(const osg::UserDataContainer* source, osg::Object* target)
|
||||
{
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
if (!target->getUserDataContainer())
|
||||
target->setUserDataContainer(source);
|
||||
target->setUserDataContainer(osg::clone(source, osg::CopyOp::SHALLOW_COPY));
|
||||
else
|
||||
{
|
||||
for (unsigned int i=0; i<source->getNumUserObjects(); ++i)
|
||||
target->getUserDataContainer()->addUserObject(source->getUserObject(i));
|
||||
target->getUserDataContainer()->addUserObject(osg::clone(source->getUserObject(i), osg::CopyOp::SHALLOW_COPY));
|
||||
}
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<osg::Node> toAttach, osg::Node *master, const std::string &filter, osg::Group* attachNode)
|
||||
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<const osg::Node> toAttach, osg::Node *master, const std::string &filter, osg::Group* attachNode)
|
||||
{
|
||||
if (dynamic_cast<SceneUtil::Skeleton*>(toAttach.get()))
|
||||
if (dynamic_cast<const SceneUtil::Skeleton*>(toAttach.get()))
|
||||
{
|
||||
osg::ref_ptr<osg::Group> handle = new osg::Group;
|
||||
|
||||
CopyRigVisitor copyVisitor(handle, filter);
|
||||
toAttach->accept(copyVisitor);
|
||||
const_cast<osg::Node*>(toAttach.get())->accept(copyVisitor);
|
||||
copyVisitor.doCopy();
|
||||
|
||||
if (handle->getNumChildren() == 1)
|
||||
@ -122,14 +121,16 @@ namespace SceneUtil
|
||||
else
|
||||
{
|
||||
master->asGroup()->addChild(handle);
|
||||
handle->setUserDataContainer(toAttach->getUserDataContainer());
|
||||
mergeUserData(toAttach->getUserDataContainer(), handle);
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::ref_ptr<osg::Node> clonedToAttach = static_cast<osg::Node*>(toAttach->clone(SceneUtil::CopyOp()));
|
||||
|
||||
FindByNameVisitor findBoneOffset("BoneOffset");
|
||||
toAttach->accept(findBoneOffset);
|
||||
clonedToAttach->accept(findBoneOffset);
|
||||
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> trans;
|
||||
|
||||
@ -172,13 +173,13 @@ namespace SceneUtil
|
||||
if (trans)
|
||||
{
|
||||
attachNode->addChild(trans);
|
||||
trans->addChild(toAttach);
|
||||
trans->addChild(clonedToAttach);
|
||||
return trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
attachNode->addChild(toAttach);
|
||||
return toAttach;
|
||||
attachNode->addChild(clonedToAttach);
|
||||
return clonedToAttach;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,12 +14,12 @@ namespace osg
|
||||
namespace SceneUtil
|
||||
{
|
||||
|
||||
/// Attach parts of the \a toAttach scenegraph to the \a master scenegraph, using the specified filter and attachment node.
|
||||
/// Clone and attach parts of the \a toAttach scenegraph to the \a master scenegraph, using the specified filter and attachment node.
|
||||
/// If the \a toAttach scene graph contains skinned objects, we will attach only those (filtered by the \a filter).
|
||||
/// Otherwise, just attach all of the toAttach scenegraph to the attachment node on the master scenegraph, with no filtering.
|
||||
/// @note The master scene graph is expected to include a skeleton.
|
||||
/// @return A newly created node that is directly attached to the master scene graph
|
||||
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<osg::Node> toAttach, osg::Node* master, const std::string& filter, osg::Group* attachNode);
|
||||
osg::ref_ptr<osg::Node> attach(osg::ref_ptr<const osg::Node> toAttach, osg::Node* master, const std::string& filter, osg::Group* attachNode);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
|
||||
@ -35,11 +33,6 @@ namespace SceneUtil
|
||||
mUpdaterToOldPs[cloned] = updater->getParticleSystem(0);
|
||||
return cloned;
|
||||
}
|
||||
|
||||
if (dynamic_cast<const osgAnimation::Bone*>(node) || dynamic_cast<const osgAnimation::Skeleton*>(node))
|
||||
{
|
||||
return osg::clone(node, *this);
|
||||
}
|
||||
return osg::CopyOp::operator()(node);
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@ ShadowsBin::ShadowsBin()
|
||||
|
||||
mShaderAlphaTestStateSet = new osg::StateSet;
|
||||
mShaderAlphaTestStateSet->addUniform(new osg::Uniform("alphaTestShadows", true));
|
||||
mShaderAlphaTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true));
|
||||
mShaderAlphaTestStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE);
|
||||
|
||||
for (size_t i = 0; i < sCastingPrograms.size(); ++i)
|
||||
|
@ -9,6 +9,9 @@
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
|
||||
@ -24,7 +27,7 @@ namespace SceneUtil
|
||||
|
||||
void FindByClassVisitor::apply(osg::Node &node)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(node.className(), mNameToFind))
|
||||
if (Misc::StringUtils::ciEqual(std::string_view(node.className()), mNameToFind))
|
||||
mFoundNodes.push_back(&node);
|
||||
|
||||
traverse(node);
|
||||
@ -32,13 +35,13 @@ namespace SceneUtil
|
||||
|
||||
void FindByNameVisitor::apply(osg::Group &group)
|
||||
{
|
||||
if (!checkGroup(group))
|
||||
if (!mFoundNode && !checkGroup(group))
|
||||
traverse(group);
|
||||
}
|
||||
|
||||
void FindByNameVisitor::apply(osg::MatrixTransform &node)
|
||||
{
|
||||
if (!checkGroup(node))
|
||||
if (!mFoundNode && !checkGroup(node))
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
|
@ -371,11 +371,10 @@ namespace Shader
|
||||
void ShaderManager::setGlobalDefines(DefineMap & globalDefines)
|
||||
{
|
||||
mGlobalDefines = globalDefines;
|
||||
for (auto shaderMapElement: mShaders)
|
||||
for (const auto& [key, shader]: mShaders)
|
||||
{
|
||||
std::string templateId = shaderMapElement.first.first;
|
||||
ShaderManager::DefineMap defines = shaderMapElement.first.second;
|
||||
osg::ref_ptr<osg::Shader> shader = shaderMapElement.second;
|
||||
std::string templateId = key.first;
|
||||
ShaderManager::DefineMap defines = key.second;
|
||||
if (shader == nullptr)
|
||||
// I'm not sure how to handle a shader that was already broken as there's no way to get a potential replacement to the nodes that need it.
|
||||
continue;
|
||||
@ -391,13 +390,13 @@ namespace Shader
|
||||
void ShaderManager::releaseGLObjects(osg::State *state)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
for (auto shader : mShaders)
|
||||
for (const auto& [_, shader] : mShaders)
|
||||
{
|
||||
if (shader.second != nullptr)
|
||||
shader.second->releaseGLObjects(state);
|
||||
if (shader != nullptr)
|
||||
shader->releaseGLObjects(state);
|
||||
}
|
||||
for (auto program : mPrograms)
|
||||
program.second->releaseGLObjects(state);
|
||||
for (const auto& [_, program] : mPrograms)
|
||||
program->releaseGLObjects(state);
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user