From d340224c95862be8bf49ca31b0db7d5651d96411 Mon Sep 17 00:00:00 2001 From: bzzt Date: Wed, 20 Feb 2019 13:37:00 +0000 Subject: [PATCH 001/111] shadowsbin for gl state reduction --- components/CMakeLists.txt | 2 +- components/sceneutil/mwshadowtechnique.cpp | 17 ++- components/sceneutil/shadowsbin.cpp | 133 +++++++++++++++++++++ components/sceneutil/shadowsbin.hpp | 58 +++++++++ components/shader/shadervisitor.cpp | 7 -- 5 files changed, 204 insertions(+), 13 deletions(-) create mode 100644 components/sceneutil/shadowsbin.cpp create mode 100644 components/sceneutil/shadowsbin.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 412717aaa..eaf9a6dda 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -51,7 +51,7 @@ add_component_dir (shader add_component_dir (sceneutil clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize optimizer - actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique + actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique shadowsbin ) add_component_dir (nif diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index f31d2faef..bc0bcdf33 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -24,6 +24,7 @@ #include #include +#include "shadowsbin.hpp" namespace { @@ -272,10 +273,20 @@ void VDSMCameraCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) cv->pushCullingSet(); } #endif + // bin has to go inside camera cull or the rendertexture stage will override it + static osg::ref_ptr ss; + if (!ss) + { + ShadowsBinAdder adder("ShadowsBin"); + ss = new osg::StateSet; + ss->setRenderBinDetails(osg::StateSet::OPAQUE_BIN, "ShadowsBin", osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS); + } + cv->pushStateSet(ss); if (_vdsm->getShadowedScene()) { _vdsm->getShadowedScene()->osg::Group::traverse(*nv); } + cv->popStateSet(); #if 1 if (!_polytope.empty()) { @@ -1569,14 +1580,10 @@ void MWShadowTechnique::createShaders() _shadowCastingStateSet->setAttributeAndModes(_castingProgram, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); // The casting program uses a sampler, so to avoid undefined behaviour, we must bind a dummy texture in case no other is supplied _shadowCastingStateSet->setTextureAttributeAndModes(0, _fallbackBaseTexture.get(), osg::StateAttribute::ON); - _shadowCastingStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false)); - + _shadowCastingStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true)); _shadowCastingStateSet->setMode(GL_DEPTH_CLAMP, osg::StateAttribute::ON); - _shadowCastingStateSet->setRenderBinDetails(osg::StateSet::OPAQUE_BIN, "RenderBin", osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS); - // TODO: compare performance when alpha testing is handled here versus using a discard in the fragment shader - // TODO: compare performance when we set a bunch of GL state to the default here with OVERRIDE set so that there are fewer pointless state switches } osg::Polytope MWShadowTechnique::computeLightViewFrustumPolytope(Frustum& frustum, LightData& positionedLight) diff --git a/components/sceneutil/shadowsbin.cpp b/components/sceneutil/shadowsbin.cpp new file mode 100644 index 000000000..2bf2f06f6 --- /dev/null +++ b/components/sceneutil/shadowsbin.cpp @@ -0,0 +1,133 @@ +#include "shadowsbin.hpp" +#include +#include +#include +#include + +using namespace osgUtil; + +namespace +{ + template + inline void accumulateState(T& currentValue, T newValue, bool& isOverride, unsigned int overrideFlags) + { + if (isOverride && !(overrideFlags & osg::StateAttribute::PROTECTED)) return; + + if (overrideFlags & osg::StateAttribute::OVERRIDE) + isOverride = true; + + currentValue = newValue; + } + + inline void accumulateModeState(const osg::StateSet* ss, bool& currentValue, bool& isOverride, int mode) + { + const osg::StateSet::ModeList& l = ss->getModeList(); + osg::StateSet::ModeList::const_iterator mf = l.find(mode); + if (mf == l.end()) + return; + int flags = mf->second; + bool newValue = flags & osg::StateAttribute::ON; + accumulateState(currentValue, newValue, isOverride, ss->getMode(mode)); + } + + inline bool materialNeedShadows(osg::Material* m) + { + return m->getDiffuse(osg::Material::FRONT).a() > 0.5; + } +} + +namespace SceneUtil +{ + +ShadowsBin::ShadowsBin() +{ + mStateSet = new osg::StateSet; + mStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false)); +} + +bool ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::unordered_set& uninteresting) +{ + std::vector return_path; + State state; + StateGraph* sg_new = sg; + do + { + if (uninteresting.find(sg_new) != uninteresting.end()) + break; + return_path.push_back(sg_new); + sg_new = sg_new->_parent; + } while (sg_new && sg_new != root); + for(std::vector::reverse_iterator itr=return_path.rbegin(); itr!=return_path.rend(); ++itr) + { + const osg::StateSet* ss = (*itr)->getStateSet(); + if (!ss) continue; + accumulateModeState(ss, state.mAlphaBlend, state.mAlphaBlendOverride, GL_BLEND); + accumulateModeState(ss, state.mAlphaTest, state.mAlphaTestOverride, GL_ALPHA_TEST); + const osg::StateSet::AttributeList& l = ss->getAttributeList(); + osg::StateSet::AttributeList::const_iterator f = l.find(std::make_pair(osg::StateAttribute::MATERIAL, 0)); + if (f != l.end()) + { + const osg::StateSet::RefAttributePair* rap = &f->second; + accumulateState(state.mMaterial, static_cast(rap->first.get()), state.mMaterialOverride, rap->second); + if (state.mMaterial && !materialNeedShadows(state.mMaterial)) + state.mMaterial = nullptr; + } + f = l.find(std::make_pair(osg::StateAttribute::FRONTFACE, 0)); + if (f != l.end()) + state.mImportantState = true; + if ((*itr) != sg && !state.interesting()) + uninteresting.insert(*itr); + } + + if (!state.needShadows()) + return true; + + if (!state.needTexture() && !state.mImportantState) + { + for (RenderLeaf* leaf : sg->_leaves) + { + leaf->_parent = root; + root->_leaves.push_back(leaf); + } + return true; + } + return false; +} + +bool ShadowsBin::State::needShadows() const +{ + if (!mMaterial) + return true; + return materialNeedShadows(mMaterial); +} + +void ShadowsBin::sortImplementation() +{ + if (!_stateGraphList.size()) + return; + StateGraph* root = _stateGraphList[0]; + while (root->_parent) + { + root = root->_parent; + const osg::StateSet* ss = root->getStateSet(); + if (ss->getMode(GL_NORMALIZE) & osg::StateAttribute::ON // that is root stategraph of renderingmanager cpp + || ss->getAttribute(osg::StateAttribute::VIEWPORT)) // fallback to rendertargets sg just in case + break; + if (!root->_parent) + return; + } + root = root->find_or_insert(mStateSet.get()); + root->_leaves.reserve(_stateGraphList.size()); + StateGraphList newList; + std::unordered_set uninteresting; + for (StateGraph* graph : _stateGraphList) + { + if (!cullStateGraph(graph, root, uninteresting)) + newList.push_back(graph); + } + if (!root->_leaves.empty()) + newList.push_back(root); + _stateGraphList = newList; +} + +} diff --git a/components/sceneutil/shadowsbin.hpp b/components/sceneutil/shadowsbin.hpp new file mode 100644 index 000000000..05926bace --- /dev/null +++ b/components/sceneutil/shadowsbin.hpp @@ -0,0 +1,58 @@ +#ifndef OPENMW_COMPONENTS_SCENEUTIL_SHADOWBIN_H +#define OPENMW_COMPONENTS_SCENEUTIL_SHADOWBIN_H +#include +#include + +namespace osg +{ + class Material; +} + +namespace SceneUtil +{ + + /// renderbin which culls redundent state for shadows rendering + class ShadowsBin : public osgUtil::RenderBin + { + private: + osg::ref_ptr mStateSet; + public: + META_Object(SceneUtil, ShadowsBin) + ShadowsBin(); + ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop), mStateSet(rhs.mStateSet) {} + + virtual void sortImplementation(); + + struct State + { + State():mAlphaBlend(false),mAlphaBlendOverride(false),mAlphaTest(false),mAlphaTestOverride(false),mMaterial(nullptr),mMaterialOverride(false),mImportantState(false){} + bool mAlphaBlend; + bool mAlphaBlendOverride; + bool mAlphaTest; + bool mAlphaTestOverride; + osg::Material* mMaterial; + bool mMaterialOverride; + bool mImportantState; + bool needTexture() const { return mAlphaBlend || mAlphaTest; } + bool needShadows() const; + bool interesting() const { return !needShadows() || needTexture() || mAlphaBlendOverride || mAlphaTestOverride || mMaterialOverride || mImportantState; } + }; + + bool cullStateGraph(osgUtil::StateGraph* sg, osgUtil::StateGraph* root, std::unordered_set& uninteresting); + + static void addPrototype(const std::string& name) + { + osg::ref_ptr bin (new ShadowsBin); + osgUtil::RenderBin::addRenderBinPrototype(name, bin); + } + }; + + class ShadowsBinAdder + { + public: + ShadowsBinAdder(const std::string& name){ ShadowsBin::addPrototype(name); } + }; + +} + +#endif diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index e40cc255b..365cc5b66 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -205,13 +205,6 @@ namespace Shader mRequirements.back().mShaderRequired = true; } } - - if (diffuseMap) - { - if (!writableStateSet) - writableStateSet = getWritableStateSet(node); - writableStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true)); - } } const osg::StateSet::AttributeList& attributes = stateset->getAttributeList(); From f14db21745e1e149e03ad029ce9a3e96208d979d Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Sun, 17 May 2020 19:52:23 +1200 Subject: [PATCH 002/111] Make disableShadowsForStateSet a no-op when shadows are disabled Otherwise the GPU has to do useless shadow comparisons when shadows are disabled. --- components/sceneutil/shadow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index a1cd1d660..8c564f224 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -69,6 +69,9 @@ namespace SceneUtil void ShadowManager::disableShadowsForStateSet(osg::ref_ptr stateset) { + if (!Settings::Manager::getBool("enable shadows", "Shadows")) + return; + int numberOfShadowMapsPerLight = Settings::Manager::getInt("number of shadow maps", "Shadows"); numberOfShadowMapsPerLight = std::max(1, std::min(numberOfShadowMapsPerLight, 8)); From 065ed5138e51468f916cfbe1e8f5a225e9859eca Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 17 Oct 2020 12:26:35 +0400 Subject: [PATCH 003/111] Use emplace_back instead of push_back --- apps/mwiniimporter/importer.cpp | 4 +- apps/opencs/editor.cpp | 4 +- apps/opencs/model/doc/loader.cpp | 2 +- apps/opencs/model/doc/operation.cpp | 2 +- apps/opencs/model/prefs/enumsetting.cpp | 2 +- .../model/prefs/shortcuteventhandler.cpp | 2 +- apps/opencs/model/world/commanddispatcher.cpp | 2 +- apps/opencs/model/world/idtable.cpp | 6 +- apps/opencs/model/world/refidcollection.cpp | 215 +++++++++--------- apps/opencs/view/render/cell.cpp | 2 +- apps/opencs/view/render/worldspacewidget.cpp | 3 +- .../opencs/view/world/datadisplaydelegate.cpp | 2 +- apps/opencs/view/world/enumdelegate.cpp | 2 +- apps/opencs/view/world/regionmap.cpp | 10 +- apps/opencs/view/world/table.cpp | 4 +- apps/opencs/view/world/tablesubview.cpp | 4 +- apps/openmw/mwclass/npc.cpp | 8 +- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 2 +- apps/openmw/mwdialogue/hypertextparser.cpp | 4 +- apps/openmw/mwgui/birth.cpp | 2 +- apps/openmw/mwgui/bookpage.cpp | 4 +- apps/openmw/mwgui/class.cpp | 2 +- apps/openmw/mwgui/companionwindow.cpp | 4 +- apps/openmw/mwgui/containeritemmodel.cpp | 4 +- apps/openmw/mwgui/jailscreen.cpp | 2 +- apps/openmw/mwgui/mainmenu.cpp | 14 +- apps/openmw/mwgui/race.cpp | 2 +- apps/openmw/mwgui/settingswindow.cpp | 2 +- apps/openmw/mwgui/sortfilteritemmodel.cpp | 26 +-- apps/openmw/mwgui/soulgemdialog.cpp | 4 +- apps/openmw/mwgui/spellview.cpp | 10 +- apps/openmw/mwgui/trainingwindow.cpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 2 +- .../mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwrender/animation.cpp | 16 +- apps/openmw/mwrender/localmap.cpp | 4 +- apps/openmw/mwrender/objectpaging.cpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 2 +- apps/openmw/mwrender/sky.cpp | 70 +++--- apps/openmw/mwscript/globalscripts.cpp | 2 +- apps/openmw/mwscript/locals.cpp | 2 +- apps/openmw/mwsound/openal_output.cpp | 4 +- apps/openmw/mwstate/charactermanager.cpp | 2 +- apps/openmw/mwstate/statemanagerimp.cpp | 14 +- apps/openmw/mwworld/cellpreloader.cpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 2 +- apps/openmw/mwworld/localscripts.cpp | 2 +- apps/openmw/mwworld/projectilemanager.cpp | 2 +- apps/openmw/mwworld/scene.cpp | 4 +- apps/openmw/mwworld/store.cpp | 2 +- components/compiler/scanner.cpp | 2 +- components/esm/aisequence.cpp | 2 +- components/esm/inventorystate.cpp | 2 +- components/esm/locals.cpp | 2 +- components/files/escape.cpp | 2 +- components/nifosg/controller.cpp | 2 +- components/sceneutil/lightmanager.cpp | 2 +- components/sceneutil/mwshadowtechnique.cpp | 18 +- components/sceneutil/statesetupdater.cpp | 4 +- components/sceneutil/unrefqueue.cpp | 2 +- components/sceneutil/visitor.cpp | 8 +- components/shader/shadervisitor.cpp | 2 +- components/terrain/chunkmanager.cpp | 2 +- components/terrain/viewdata.cpp | 2 +- components/vfs/bsaarchive.cpp | 2 +- components/widgets/list.cpp | 2 +- 66 files changed, 273 insertions(+), 277 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 600b4917a..3297a7b5e 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -645,7 +645,7 @@ MwIniImporter::MwIniImporter() } for(int i=0; fallback[i]; i++) { - mMergeFallback.push_back(fallback[i]); + mMergeFallback.emplace_back(fallback[i]); } } @@ -910,7 +910,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co std::time_t time = lastWriteTime(path, defaultTime); if (time != defaultTime) { - contentFiles.push_back({time, path}); + contentFiles.emplace_back(time, std::move(path)); found = true; break; } diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 0c3d006c4..37e1ffc9a 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -229,7 +229,7 @@ void CS::Editor::openFiles (const boost::filesystem::path &savePath, const std:: if(discoveredFiles.empty()) { for (const QString &path : mFileDialog.selectedFilePaths()) - files.push_back(path.toUtf8().constData()); + files.emplace_back(path.toUtf8().constData()); } else { @@ -246,7 +246,7 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath) std::vector files; for (const QString &path : mFileDialog.selectedFilePaths()) { - files.push_back(path.toUtf8().constData()); + files.emplace_back(path.toUtf8().constData()); } files.push_back (savePath); diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 44d6883ef..69c78bd5e 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -127,7 +127,7 @@ void CSMDoc::Loader::load() void CSMDoc::Loader::loadDocument (CSMDoc::Document *document) { - mDocuments.push_back (std::make_pair (document, Stage())); + mDocuments.emplace_back (document, Stage()); } void CSMDoc::Loader::abortLoading (CSMDoc::Document *document) diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index a27ee9f51..218e13e38 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -57,7 +57,7 @@ void CSMDoc::Operation::run() void CSMDoc::Operation::appendStage (Stage *stage) { - mStages.push_back (std::make_pair (stage, 0)); + mStages.emplace_back (stage, 0); } void CSMDoc::Operation::setDefaultSeverity (Message::Severity severity) diff --git a/apps/opencs/model/prefs/enumsetting.cpp b/apps/opencs/model/prefs/enumsetting.cpp index 226b17173..62cac062a 100644 --- a/apps/opencs/model/prefs/enumsetting.cpp +++ b/apps/opencs/model/prefs/enumsetting.cpp @@ -35,7 +35,7 @@ CSMPrefs::EnumValues& CSMPrefs::EnumValues::add (const EnumValue& value) CSMPrefs::EnumValues& CSMPrefs::EnumValues::add (const std::string& value, const std::string& tooltip) { - mValues.push_back (EnumValue (value, tooltip)); + mValues.emplace_back(value, tooltip); return *this; } diff --git a/apps/opencs/model/prefs/shortcuteventhandler.cpp b/apps/opencs/model/prefs/shortcuteventhandler.cpp index 07c48fcaa..a4102e1db 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.cpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.cpp @@ -182,7 +182,7 @@ namespace CSMPrefs } else if (pos == lastPos) { - potentials.push_back(std::make_pair(result, shortcut)); + potentials.emplace_back(result, shortcut); } } } diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 2493813a6..36b3ba2e0 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -127,7 +127,7 @@ std::vector CSMWorld::CommandDispatcher::getExtendedTypes if (mId==UniversalId::Type_Cells) { tables.push_back (mId); - tables.push_back (UniversalId::Type_References); + tables.emplace_back(UniversalId::Type_References); /// \todo add other cell-specific types } diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index bc5a8e69d..27d60ae98 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -355,7 +355,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import // If it does not exist or it is in the current plugin, it can be skipped. if (oldRow < 0 || plugin == 0) { - results.recordMapping.push_back(std::make_pair(id, id)); + results.recordMapping.emplace_back(id, id); continue; } @@ -366,7 +366,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import auto searchIt = reverseLookupMap.find(texture); if (searchIt != reverseLookupMap.end()) { - results.recordMapping.push_back(std::make_pair(id, searchIt->second)); + results.recordMapping.emplace_back(id, searchIt->second); continue; } @@ -381,7 +381,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import // Id not taken, clone it cloneRecord(id, newId, UniversalId::Type_LandTexture); results.createdRecords.push_back(newId); - results.recordMapping.push_back(std::make_pair(id, newId)); + results.recordMapping.emplace_back(id, newId); reverseLookupMap.emplace(texture, newId); break; } diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 3502d6319..535a31ddd 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -40,45 +40,45 @@ CSMWorld::RefIdCollection::RefIdCollection() { BaseColumns baseColumns; - mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_Id, - ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false)); + mColumns.emplace_back(Columns::ColumnId_Id, ColumnBase::Display_Id, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false); baseColumns.mId = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState, - ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true, false)); + mColumns.emplace_back(Columns::ColumnId_Modification, ColumnBase::Display_RecordState, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true, false); baseColumns.mModified = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType, - ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false)); + mColumns.emplace_back(Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false); baseColumns.mType = &mColumns.back(); ModelColumns modelColumns (baseColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Model, ColumnBase::Display_Mesh)); + mColumns.emplace_back(Columns::ColumnId_Model, ColumnBase::Display_Mesh); modelColumns.mModel = &mColumns.back(); NameColumns nameColumns (modelColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Name, ColumnBase::Display_String)); + mColumns.emplace_back(Columns::ColumnId_Name, ColumnBase::Display_String); nameColumns.mName = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Script, ColumnBase::Display_Script)); + mColumns.emplace_back(Columns::ColumnId_Script, ColumnBase::Display_Script); nameColumns.mScript = &mColumns.back(); InventoryColumns inventoryColumns (nameColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Icon, ColumnBase::Display_Icon)); + mColumns.emplace_back(Columns::ColumnId_Icon, ColumnBase::Display_Icon); inventoryColumns.mIcon = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Weight, ColumnBase::Display_Float)); + mColumns.emplace_back(Columns::ColumnId_Weight, ColumnBase::Display_Float); inventoryColumns.mWeight = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_CoinValue, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_CoinValue, ColumnBase::Display_Integer); inventoryColumns.mValue = &mColumns.back(); IngredientColumns ingredientColumns (inventoryColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_EffectList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); ingredientColumns.mEffects = &mColumns.back(); std::map ingredientEffectsMap; ingredientEffectsMap.insert(std::make_pair(UniversalId::Type_Ingredient, new IngredEffectRefIdAdapter ())); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), ingredientEffectsMap)); + mNestedAdapters.emplace_back(&mColumns.back(), ingredientEffectsMap); mColumns.back().addColumn( new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_IngredEffectId)); mColumns.back().addColumn( @@ -88,13 +88,13 @@ CSMWorld::RefIdCollection::RefIdCollection() // nested table PotionColumns potionColumns (inventoryColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_EffectList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); potionColumns.mEffects = &mColumns.back(); // see refidadapterimp.hpp std::map effectsMap; effectsMap.insert(std::make_pair(UniversalId::Type_Potion, new EffectsRefIdAdapter (UniversalId::Type_Potion))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), effectsMap)); + mNestedAdapters.emplace_back(&mColumns.back(), effectsMap); mColumns.back().addColumn( new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); mColumns.back().addColumn( @@ -114,67 +114,67 @@ CSMWorld::RefIdCollection::RefIdCollection() EnchantableColumns enchantableColumns (inventoryColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_Enchantment)); + mColumns.emplace_back(Columns::ColumnId_Enchantment, ColumnBase::Display_Enchantment); enchantableColumns.mEnchantment = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer); enchantableColumns.mEnchantmentPoints = &mColumns.back(); ToolColumns toolsColumns (inventoryColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Quality, ColumnBase::Display_Float)); + mColumns.emplace_back(Columns::ColumnId_Quality, ColumnBase::Display_Float); toolsColumns.mQuality = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Charges, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_Charges, ColumnBase::Display_Integer); toolsColumns.mUses = &mColumns.back(); ActorColumns actorsColumns (nameColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_UnsignedInteger16)); + mColumns.emplace_back(Columns::ColumnId_AiHello, ColumnBase::Display_UnsignedInteger16); actorsColumns.mHello = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_UnsignedInteger8)); + mColumns.emplace_back(Columns::ColumnId_AiFlee, ColumnBase::Display_UnsignedInteger8); actorsColumns.mFlee = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFight, ColumnBase::Display_UnsignedInteger8)); + mColumns.emplace_back(Columns::ColumnId_AiFight, ColumnBase::Display_UnsignedInteger8); actorsColumns.mFight = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_AiAlarm, ColumnBase::Display_UnsignedInteger8)); + mColumns.emplace_back(Columns::ColumnId_AiAlarm, ColumnBase::Display_UnsignedInteger8); actorsColumns.mAlarm = &mColumns.back(); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_ActorInventory, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_ActorInventory, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mInventory = &mColumns.back(); std::map inventoryMap; inventoryMap.insert(std::make_pair(UniversalId::Type_Npc, new NestedInventoryRefIdAdapter (UniversalId::Type_Npc))); inventoryMap.insert(std::make_pair(UniversalId::Type_Creature, new NestedInventoryRefIdAdapter (UniversalId::Type_Creature))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), inventoryMap)); + mNestedAdapters.emplace_back(&mColumns.back(), inventoryMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_SpellList, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_SpellList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mSpells = &mColumns.back(); std::map spellsMap; spellsMap.insert(std::make_pair(UniversalId::Type_Npc, new NestedSpellRefIdAdapter (UniversalId::Type_Npc))); spellsMap.insert(std::make_pair(UniversalId::Type_Creature, new NestedSpellRefIdAdapter (UniversalId::Type_Creature))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), spellsMap)); + mNestedAdapters.emplace_back(&mColumns.back(), spellsMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_Spell)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_NpcDestinations, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mDestinations = &mColumns.back(); std::map destMap; destMap.insert(std::make_pair(UniversalId::Type_Npc, new NestedTravelRefIdAdapter (UniversalId::Type_Npc))); destMap.insert(std::make_pair(UniversalId::Type_Creature, new NestedTravelRefIdAdapter (UniversalId::Type_Creature))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), destMap)); + mNestedAdapters.emplace_back(&mColumns.back(), destMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_Cell)); mColumns.back().addColumn( @@ -191,15 +191,15 @@ CSMWorld::RefIdCollection::RefIdCollection() new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Double)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_AiPackageList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mAiPackages = &mColumns.back(); std::map aiMap; aiMap.insert(std::make_pair(UniversalId::Type_Npc, new ActorAiRefIdAdapter (UniversalId::Type_Npc))); aiMap.insert(std::make_pair(UniversalId::Type_Creature, new ActorAiRefIdAdapter (UniversalId::Type_Creature))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), aiMap)); + mNestedAdapters.emplace_back(&mColumns.back(), aiMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_AiPackageType, CSMWorld::ColumnBase::Display_AiPackageType)); mColumns.back().addColumn( @@ -270,56 +270,56 @@ CSMWorld::RefIdCollection::RefIdCollection() for (int i=0; sServiceTable[i].mName!=-1; ++i) { - mColumns.push_back (RefIdColumn (sServiceTable[i].mName, ColumnBase::Display_Boolean)); + mColumns.emplace_back(sServiceTable[i].mName, ColumnBase::Display_Boolean); actorsColumns.mServices.insert (std::make_pair (&mColumns.back(), sServiceTable[i].mFlag)); } - mColumns.push_back (RefIdColumn (Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean, - ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); + mColumns.emplace_back(Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh); const RefIdColumn *autoCalc = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_ApparatusType, - ColumnBase::Display_ApparatusType)); + mColumns.emplace_back(Columns::ColumnId_ApparatusType, + ColumnBase::Display_ApparatusType); const RefIdColumn *apparatusType = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_ArmorType, ColumnBase::Display_ArmorType)); + mColumns.emplace_back(Columns::ColumnId_ArmorType, ColumnBase::Display_ArmorType); const RefIdColumn *armorType = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Health, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_Health, ColumnBase::Display_Integer); const RefIdColumn *health = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_ArmorValue, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_ArmorValue, ColumnBase::Display_Integer); const RefIdColumn *armor = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_BookType, ColumnBase::Display_BookType)); + mColumns.emplace_back(Columns::ColumnId_BookType, ColumnBase::Display_BookType); const RefIdColumn *bookType = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); + mColumns.emplace_back(Columns::ColumnId_Skill, ColumnBase::Display_SkillId); const RefIdColumn *skill = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Text, ColumnBase::Display_LongString)); + mColumns.emplace_back(Columns::ColumnId_Text, ColumnBase::Display_LongString); const RefIdColumn *text = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_ClothingType, ColumnBase::Display_ClothingType)); + mColumns.emplace_back(Columns::ColumnId_ClothingType, ColumnBase::Display_ClothingType); const RefIdColumn *clothingType = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_WeightCapacity, ColumnBase::Display_Float)); + mColumns.emplace_back(Columns::ColumnId_WeightCapacity, ColumnBase::Display_Float); const RefIdColumn *weightCapacity = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_OrganicContainer, ColumnBase::Display_Boolean)); + mColumns.emplace_back(Columns::ColumnId_OrganicContainer, ColumnBase::Display_Boolean); const RefIdColumn *organic = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean)); + mColumns.emplace_back(Columns::ColumnId_Respawn, ColumnBase::Display_Boolean); const RefIdColumn *respawn = &mColumns.back(); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_ContainerContent, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); const RefIdColumn *content = &mColumns.back(); std::map contMap; contMap.insert(std::make_pair(UniversalId::Type_Container, new NestedInventoryRefIdAdapter (UniversalId::Type_Container))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), contMap)); + mNestedAdapters.emplace_back(&mColumns.back(), contMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( @@ -327,11 +327,11 @@ CSMWorld::RefIdCollection::RefIdCollection() CreatureColumns creatureColumns (actorsColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType)); + mColumns.emplace_back(Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType); creatureColumns.mType = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float)); + mColumns.emplace_back(Columns::ColumnId_Scale, ColumnBase::Display_Float); creatureColumns.mScale = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_ParentCreature, ColumnBase::Display_Creature)); + mColumns.emplace_back(Columns::ColumnId_ParentCreature, ColumnBase::Display_Creature); creatureColumns.mOriginal = &mColumns.back(); static const struct @@ -354,7 +354,7 @@ CSMWorld::RefIdCollection::RefIdCollection() for (int i=0; sCreatureFlagTable[i].mName!=-1; ++i) { - mColumns.push_back (RefIdColumn (sCreatureFlagTable[i].mName, ColumnBase::Display_Boolean)); + mColumns.emplace_back(sCreatureFlagTable[i].mName, ColumnBase::Display_Boolean); creatureColumns.mFlags.insert (std::make_pair (&mColumns.back(), sCreatureFlagTable[i].mFlag)); switch (sCreatureFlagTable[i].mFlag) @@ -363,7 +363,7 @@ CSMWorld::RefIdCollection::RefIdCollection() } } - mColumns.push_back(RefIdColumn(Columns::ColumnId_BloodType, ColumnBase::Display_BloodType)); + mColumns.emplace_back(Columns::ColumnId_BloodType, ColumnBase::Display_BloodType); // For re-use in NPC records. const RefIdColumn *bloodType = &mColumns.back(); creatureColumns.mBloodType = bloodType; @@ -371,24 +371,24 @@ CSMWorld::RefIdCollection::RefIdCollection() creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureAttributes, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_CreatureAttributes, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); creatureColumns.mAttributes = &mColumns.back(); std::map creaAttrMap; creaAttrMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttributesRefIdAdapter())); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), creaAttrMap)); + mNestedAdapters.emplace_back(&mColumns.back(), creaAttrMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_AttributeValue, CSMWorld::ColumnBase::Display_Integer)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureAttack, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_CreatureAttack, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); creatureColumns.mAttacks = &mColumns.back(); std::map attackMap; attackMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttackRefIdAdapter())); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attackMap)); + mNestedAdapters.emplace_back(&mColumns.back(), attackMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_CreatureAttack, CSMWorld::ColumnBase::Display_Integer, false, false)); mColumns.back().addColumn( @@ -397,12 +397,12 @@ CSMWorld::RefIdCollection::RefIdCollection() new RefIdColumn (Columns::ColumnId_MaxAttack, CSMWorld::ColumnBase::Display_Integer)); // Nested list - mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureMisc, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List)); + mColumns.emplace_back(Columns::ColumnId_CreatureMisc, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List); creatureColumns.mMisc = &mColumns.back(); std::map creaMiscMap; creaMiscMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureMiscRefIdAdapter())); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), creaMiscMap)); + mNestedAdapters.emplace_back(&mColumns.back(), creaMiscMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); @@ -423,27 +423,27 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer)); - mColumns.push_back (RefIdColumn (Columns::ColumnId_OpenSound, ColumnBase::Display_Sound)); + mColumns.emplace_back(Columns::ColumnId_OpenSound, ColumnBase::Display_Sound); const RefIdColumn *openSound = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_CloseSound, ColumnBase::Display_Sound)); + mColumns.emplace_back(Columns::ColumnId_CloseSound, ColumnBase::Display_Sound); const RefIdColumn *closeSound = &mColumns.back(); LightColumns lightColumns (inventoryColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_Duration, ColumnBase::Display_Integer); lightColumns.mTime = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Radius, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_Radius, ColumnBase::Display_Integer); lightColumns.mRadius = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Colour, ColumnBase::Display_Colour)); + mColumns.emplace_back(Columns::ColumnId_Colour, ColumnBase::Display_Colour); lightColumns.mColor = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Sound, ColumnBase::Display_Sound)); + mColumns.emplace_back(Columns::ColumnId_Sound, ColumnBase::Display_Sound); lightColumns.mSound = &mColumns.back(); - mColumns.push_back(RefIdColumn(Columns::ColumnId_EmitterType, ColumnBase::Display_EmitterType)); + mColumns.emplace_back(Columns::ColumnId_EmitterType, ColumnBase::Display_EmitterType); lightColumns.mEmitterType = &mColumns.back(); static const struct @@ -462,31 +462,31 @@ CSMWorld::RefIdCollection::RefIdCollection() for (int i=0; sLightFlagTable[i].mName!=-1; ++i) { - mColumns.push_back (RefIdColumn (sLightFlagTable[i].mName, ColumnBase::Display_Boolean)); + mColumns.emplace_back(sLightFlagTable[i].mName, ColumnBase::Display_Boolean); lightColumns.mFlags.insert (std::make_pair (&mColumns.back(), sLightFlagTable[i].mFlag)); } - mColumns.push_back (RefIdColumn (Columns::ColumnId_IsKey, ColumnBase::Display_Boolean)); + mColumns.emplace_back(Columns::ColumnId_IsKey, ColumnBase::Display_Boolean); const RefIdColumn *key = &mColumns.back(); NpcColumns npcColumns (actorsColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Race, ColumnBase::Display_Race)); + mColumns.emplace_back(Columns::ColumnId_Race, ColumnBase::Display_Race); npcColumns.mRace = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Class, ColumnBase::Display_Class)); + mColumns.emplace_back(Columns::ColumnId_Class, ColumnBase::Display_Class); npcColumns.mClass = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction)); + mColumns.emplace_back(Columns::ColumnId_Faction, ColumnBase::Display_Faction); npcColumns.mFaction = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_BodyPart)); + mColumns.emplace_back(Columns::Columnid_Hair, ColumnBase::Display_BodyPart); npcColumns.mHair = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_BodyPart)); + mColumns.emplace_back(Columns::ColumnId_Head, ColumnBase::Display_BodyPart); npcColumns.mHead = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Gender, ColumnBase::Display_GenderNpc)); + mColumns.emplace_back(Columns::ColumnId_Gender, ColumnBase::Display_GenderNpc); npcColumns.mGender = &mColumns.back(); npcColumns.mFlags.insert (std::make_pair (essential, ESM::NPC::Essential)); @@ -503,36 +503,36 @@ CSMWorld::RefIdCollection::RefIdCollection() // These needs to be driven from the autocalculated setting. // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcAttributes, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_NpcAttributes, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); npcColumns.mAttributes = &mColumns.back(); std::map attrMap; attrMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcAttributesRefIdAdapter())); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attrMap)); + mNestedAdapters.emplace_back(&mColumns.back(), attrMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_UnsignedInteger8)); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcSkills, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_NpcSkills, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); npcColumns.mSkills = &mColumns.back(); std::map skillsMap; skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter())); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), skillsMap)); + mNestedAdapters.emplace_back(&mColumns.back(), skillsMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_Skill, CSMWorld::ColumnBase::Display_SkillId, false, false)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_UnsignedInteger8)); // Nested list - mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcMisc, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List)); + mColumns.emplace_back(Columns::ColumnId_NpcMisc, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List); npcColumns.mMisc = &mColumns.back(); std::map miscMap; miscMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcMiscRefIdAdapter())); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), miscMap)); + mNestedAdapters.emplace_back(&mColumns.back(), miscMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_SignedInteger16)); mColumns.back().addColumn( @@ -554,15 +554,15 @@ CSMWorld::RefIdCollection::RefIdCollection() WeaponColumns weaponColumns (enchantableColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponType, ColumnBase::Display_WeaponType)); + mColumns.emplace_back(Columns::ColumnId_WeaponType, ColumnBase::Display_WeaponType); weaponColumns.mType = &mColumns.back(); weaponColumns.mHealth = health; - mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponSpeed, ColumnBase::Display_Float)); + mColumns.emplace_back(Columns::ColumnId_WeaponSpeed, ColumnBase::Display_Float); weaponColumns.mSpeed = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float)); + mColumns.emplace_back(Columns::ColumnId_WeaponReach, ColumnBase::Display_Float); weaponColumns.mReach = &mColumns.back(); for (int i=0; i<3; ++i) @@ -572,8 +572,7 @@ CSMWorld::RefIdCollection::RefIdCollection() for (int j=0; j<2; ++j) { - mColumns.push_back ( - RefIdColumn (Columns::ColumnId_MinChop+i*2+j, ColumnBase::Display_Integer)); + mColumns.emplace_back(Columns::ColumnId_MinChop+i*2+j, ColumnBase::Display_Integer); column[j] = &mColumns.back(); } } @@ -591,19 +590,19 @@ CSMWorld::RefIdCollection::RefIdCollection() for (int i=0; sWeaponFlagTable[i].mName!=-1; ++i) { - mColumns.push_back (RefIdColumn (sWeaponFlagTable[i].mName, ColumnBase::Display_Boolean)); + mColumns.emplace_back(sWeaponFlagTable[i].mName, ColumnBase::Display_Boolean); weaponColumns.mFlags.insert (std::make_pair (&mColumns.back(), sWeaponFlagTable[i].mFlag)); } // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_PartRefList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_PartRefList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); const RefIdColumn *partRef = &mColumns.back(); std::map partMap; partMap.insert(std::make_pair(UniversalId::Type_Armor, new BodyPartRefIdAdapter (UniversalId::Type_Armor))); partMap.insert(std::make_pair(UniversalId::Type_Clothing, new BodyPartRefIdAdapter (UniversalId::Type_Clothing))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), partMap)); + mNestedAdapters.emplace_back(&mColumns.back(), partMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_PartRefType)); mColumns.back().addColumn( @@ -614,30 +613,30 @@ CSMWorld::RefIdCollection::RefIdCollection() LevListColumns levListColumns (baseColumns); // Nested table - mColumns.push_back(RefIdColumn (Columns::ColumnId_LevelledList, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + mColumns.emplace_back(Columns::ColumnId_LevelledList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); levListColumns.mLevList = &mColumns.back(); std::map levListMap; levListMap.insert(std::make_pair(UniversalId::Type_CreatureLevelledList, new NestedLevListRefIdAdapter (UniversalId::Type_CreatureLevelledList))); levListMap.insert(std::make_pair(UniversalId::Type_ItemLevelledList, new NestedLevListRefIdAdapter (UniversalId::Type_ItemLevelledList))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), levListMap)); + mNestedAdapters.emplace_back(&mColumns.back(), levListMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer)); // Nested list - mColumns.push_back(RefIdColumn (Columns::ColumnId_LevelledList, - ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List)); + mColumns.emplace_back(Columns::ColumnId_LevelledList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List); levListColumns.mNestedListLevList = &mColumns.back(); std::map nestedListLevListMap; nestedListLevListMap.insert(std::make_pair(UniversalId::Type_CreatureLevelledList, new NestedListLevListRefIdAdapter (UniversalId::Type_CreatureLevelledList))); nestedListLevListMap.insert(std::make_pair(UniversalId::Type_ItemLevelledList, new NestedListLevListRefIdAdapter (UniversalId::Type_ItemLevelledList))); - mNestedAdapters.push_back (std::make_pair(&mColumns.back(), nestedListLevListMap)); + mNestedAdapters.emplace_back(&mColumns.back(), nestedListLevListMap); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_LevelledItemTypeEach, CSMWorld::ColumnBase::Display_Boolean)); mColumns.back().addColumn( diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 056c50e45..859974d01 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -553,7 +553,7 @@ std::vector > CSVRender::Cell::getSelection (un result.push_back (iter->second->getTag()); if (mPathgrid && elementMask & Mask_Pathgrid) if (mPathgrid->isSelected()) - result.push_back(mPathgrid->getTag()); + result.emplace_back(mPathgrid->getTag()); return result; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 916c349d2..4535b5e8a 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -255,8 +255,7 @@ CSVWidget::SceneToolRun *CSVRender::WorldspaceWidget::makeRunTool ( bool default_ = debugProfiles.data (debugProfiles.index (i, defaultColumn)).toInt(); if (state!=CSMWorld::RecordBase::State_Deleted && default_) - profiles.push_back ( - debugProfiles.data (debugProfiles.index (i, idColumn)). + profiles.emplace_back(debugProfiles.data (debugProfiles.index (i, idColumn)). toString().toUtf8().constData()); } diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index f0c364bc2..6da62d408 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -32,7 +32,7 @@ void CSVWorld::DataDisplayDelegate::buildPixmaps () while (it != mIcons.end()) { - mPixmaps.push_back (std::make_pair (it->mValue, it->mIcon.pixmap (mIconSize) ) ); + mPixmaps.emplace_back (it->mValue, it->mIcon.pixmap (mIconSize) ); ++it; } } diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index 8027cec62..3140adc48 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -181,5 +181,5 @@ void CSVWorld::EnumDelegateFactory::add (int value, const QString& name) } } - mValues.push_back(std::make_pair (value, name)); + mValues.emplace_back (value, name); } diff --git a/apps/opencs/view/world/regionmap.cpp b/apps/opencs/view/world/regionmap.cpp index af91464b6..d2d4fbd23 100644 --- a/apps/opencs/view/world/regionmap.cpp +++ b/apps/opencs/view/world/regionmap.cpp @@ -345,18 +345,16 @@ std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() co std::vector ids; for (const QModelIndex& it : selected) { - ids.push_back( - CSMWorld::UniversalId( + ids.emplace_back( CSMWorld::UniversalId::Type_Cell, - model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData())); + model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData()); } selected = getSelectedCells(false, true); for (const QModelIndex& it : selected) { - ids.push_back( - CSMWorld::UniversalId( + ids.emplace_back( CSMWorld::UniversalId::Type_Cell_Missing, - model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData())); + model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData()); } return ids; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 9d47e2fe5..e5f4e36c5 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -452,7 +452,7 @@ std::vector CSVWorld::Table::getSelectedIds() const ++iter) { int row = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)).row(); - ids.push_back (mModel->data (mModel->index (row, columnIndex)).toString().toUtf8().constData()); + ids.emplace_back(mModel->data (mModel->index (row, columnIndex)).toString().toUtf8().constData()); } return ids; } @@ -784,7 +784,7 @@ std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column if (display == columndisplay) { - titles.push_back(mModel->headerData (i, Qt::Horizontal).toString().toUtf8().constData()); + titles.emplace_back(mModel->headerData (i, Qt::Horizontal).toString().toUtf8().constData()); } } return titles; diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index b0bae7fdf..5413f87a6 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -133,12 +133,12 @@ void CSVWorld::TableSubView::createFilterRequest (std::vector< CSMWorld::Univers std::vector col = mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(type)); if(!col.empty()) { - filterSource.push_back(std::make_pair(it->getId(), col)); + filterSource.emplace_back(it->getId(), col); } if(hasRefIdDisplay && CSMWorld::TableMimeData::isReferencable(type)) { - filterSource.push_back(std::make_pair(it->getId(), refIdColumns)); + filterSource.emplace_back(it->getId(), refIdColumns); } } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 0187f2727..22d93e3bc 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -431,12 +431,12 @@ namespace MWClass const MWWorld::LiveCellRef *npc = ptr.get(); const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().search(npc->mBase->mRace); if(race && race->mData.mFlags & ESM::Race::Beast) - models.push_back("meshes\\base_animkna.nif"); + models.emplace_back("meshes\\base_animkna.nif"); // keep these always loaded just in case - models.push_back("meshes/xargonian_swimkna.nif"); - models.push_back("meshes/xbase_anim_female.nif"); - models.push_back("meshes/xbase_anim.nif"); + models.emplace_back("meshes/xargonian_swimkna.nif"); + models.emplace_back("meshes/xbase_anim_female.nif"); + models.emplace_back("meshes/xbase_anim.nif"); if (!npc->mBase->mModel.empty()) models.push_back("meshes/"+npc->mBase->mModel); diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index e3f1796a4..b392ab872 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -468,7 +468,7 @@ namespace MWDialogue void DialogueManager::addChoice (const std::string& text, int choice) { mIsInChoice = true; - mChoices.push_back(std::make_pair(text, choice)); + mChoices.emplace_back(text, choice); } const std::vector >& DialogueManager::getChoices() diff --git a/apps/openmw/mwdialogue/hypertextparser.cpp b/apps/openmw/mwdialogue/hypertextparser.cpp index aa748e772..28e450e2b 100644 --- a/apps/openmw/mwdialogue/hypertextparser.cpp +++ b/apps/openmw/mwdialogue/hypertextparser.cpp @@ -30,7 +30,7 @@ namespace MWDialogue tokenizeKeywords(text.substr(iteration_pos, pos_begin - iteration_pos), result); std::string link = text.substr(pos_begin + 1, pos_end - pos_begin - 1); - result.push_back(Token(link, Token::ExplicitLink)); + result.emplace_back(link, Token::ExplicitLink); iteration_pos = pos_end + 1; } @@ -65,7 +65,7 @@ namespace MWDialogue for (std::vector::Match>::const_iterator it = matches.begin(); it != matches.end(); ++it) { - tokens.push_back(Token(std::string(it->mBeg, it->mEnd), Token::ImplicitKeyword)); + tokens.emplace_back(std::string(it->mBeg, it->mEnd), Token::ImplicitKeyword); } } diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 6f6a621ad..41711f5e4 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -147,7 +147,7 @@ namespace MWGui for (const ESM::BirthSign& sign : signs) { - birthSigns.push_back(std::make_pair(sign.mId, &sign)); + birthSigns.emplace_back(sign.mId, &sign); } std::sort(birthSigns.begin(), birthSigns.end(), sortBirthSigns); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 47027c2b7..f7a86124a 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -524,9 +524,9 @@ struct TypesetBookImpl::Typesetter : BookTypesetter break; if ( lead != origin ) - mPartialWhitespace.push_back (PartialText (style, lead, origin, space_width)); + mPartialWhitespace.emplace_back(style, lead, origin, space_width); if ( origin != extent ) - mPartialWord.push_back (PartialText (style, origin, extent, word_width)); + mPartialWord.emplace_back(style, origin, extent, word_width); } } diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index a92ad934c..cfbf5e5fb 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -217,7 +217,7 @@ namespace MWGui if (store.get().isDynamic(classInfo.mId)) continue; // custom-made class not relevant for this dialog - items.push_back(std::make_pair(classInfo.mId, classInfo.mName)); + items.emplace_back(classInfo.mId, classInfo.mName); } std::sort(items.begin(), items.end(), sortClasses); diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index b3f6e3339..926456219 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -163,8 +163,8 @@ bool CompanionWindow::exit() if (mModel && mModel->hasProfit(mPtr) && getProfit(mPtr) < 0) { std::vector buttons; - buttons.push_back("#{sCompanionWarningButtonOne}"); - buttons.push_back("#{sCompanionWarningButtonTwo}"); + buttons.emplace_back("#{sCompanionWarningButtonOne}"); + buttons.emplace_back("#{sCompanionWarningButtonTwo}"); mMessageBoxManager->createInteractiveMessageBox("#{sCompanionWarningMessage}", buttons); mMessageBoxManager->eventButtonPressed += MyGUI::newDelegate(this, &CompanionWindow::onMessageBoxButtonClicked); return false; diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index 31439f349..56f084bb9 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -49,14 +49,14 @@ ContainerItemModel::ContainerItemModel(const std::vector& itemSour for(const MWWorld::Ptr& source : itemSources) { MWWorld::ContainerStore& store = source.getClass().getContainerStore(source); - mItemSources.push_back(std::make_pair(source, store.resolveTemporarily())); + mItemSources.emplace_back(source, store.resolveTemporarily()); } } ContainerItemModel::ContainerItemModel (const MWWorld::Ptr& source) : mTrading(false) { MWWorld::ContainerStore& store = source.getClass().getContainerStore(source); - mItemSources.push_back(std::make_pair(source, store.resolveTemporarily())); + mItemSources.emplace_back(source, store.resolveTemporarily()); } bool ContainerItemModel::allowedToUseItems() const diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index 67124884f..cc793073e 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -123,7 +123,7 @@ namespace MWGui } std::vector buttons; - buttons.push_back("#{sOk}"); + buttons.emplace_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons); } } diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 4778ee7b0..a5d8f7344 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -231,25 +231,25 @@ namespace MWGui std::vector buttons; if (state==MWBase::StateManager::State_Running) - buttons.push_back("return"); + buttons.emplace_back("return"); - buttons.push_back("newgame"); + buttons.emplace_back("newgame"); if (state==MWBase::StateManager::State_Running && MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1 && MWBase::Environment::get().getWindowManager()->isSavingAllowed()) - buttons.push_back("savegame"); + buttons.emplace_back("savegame"); if (MWBase::Environment::get().getStateManager()->characterBegin()!= MWBase::Environment::get().getStateManager()->characterEnd()) - buttons.push_back("loadgame"); + buttons.emplace_back("loadgame"); - buttons.push_back("options"); + buttons.emplace_back("options"); if (state==MWBase::StateManager::State_NoGame) - buttons.push_back("credits"); + buttons.emplace_back("credits"); - buttons.push_back("exitgame"); + buttons.emplace_back("exitgame"); // Create new buttons if needed std::vector allButtons { "return", "newgame", "savegame", "loadgame", "options", "credits", "exitgame"}; diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index cf69ecca3..457594697 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -358,7 +358,7 @@ namespace MWGui if (!playable) // Only display playable races continue; - items.push_back(std::make_pair(race.mId, race.mName)); + items.emplace_back(race.mId, race.mName); } std::sort(items.begin(), items.end(), sortRaces); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index aec3396a1..0e3ae6ff8 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -244,7 +244,7 @@ namespace MWGui { SDL_DisplayMode mode; SDL_GetDisplayMode(screen, i, &mode); - resolutions.push_back(std::make_pair(mode.w, mode.h)); + resolutions.emplace_back(mode.w, mode.h); } std::sort(resolutions.begin(), resolutions.end(), sortResolutions); for (std::pair& resolution : resolutions) diff --git a/apps/openmw/mwgui/sortfilteritemmodel.cpp b/apps/openmw/mwgui/sortfilteritemmodel.cpp index f18cac681..28b13cdf0 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.cpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.cpp @@ -31,18 +31,18 @@ namespace { // this defines the sorting order of types. types that are first in the vector appear before other types. std::vector mapping; - mapping.push_back( typeid(ESM::Weapon).name() ); - mapping.push_back( typeid(ESM::Armor).name() ); - mapping.push_back( typeid(ESM::Clothing).name() ); - mapping.push_back( typeid(ESM::Potion).name() ); - mapping.push_back( typeid(ESM::Ingredient).name() ); - mapping.push_back( typeid(ESM::Apparatus).name() ); - mapping.push_back( typeid(ESM::Book).name() ); - mapping.push_back( typeid(ESM::Light).name() ); - mapping.push_back( typeid(ESM::Miscellaneous).name() ); - mapping.push_back( typeid(ESM::Lockpick).name() ); - mapping.push_back( typeid(ESM::Repair).name() ); - mapping.push_back( typeid(ESM::Probe).name() ); + mapping.emplace_back(typeid(ESM::Weapon).name() ); + mapping.emplace_back(typeid(ESM::Armor).name() ); + mapping.emplace_back(typeid(ESM::Clothing).name() ); + mapping.emplace_back(typeid(ESM::Potion).name() ); + mapping.emplace_back(typeid(ESM::Ingredient).name() ); + mapping.emplace_back(typeid(ESM::Apparatus).name() ); + mapping.emplace_back(typeid(ESM::Book).name() ); + mapping.emplace_back(typeid(ESM::Light).name() ); + mapping.emplace_back(typeid(ESM::Miscellaneous).name() ); + mapping.emplace_back(typeid(ESM::Lockpick).name() ); + mapping.emplace_back(typeid(ESM::Repair).name() ); + mapping.emplace_back(typeid(ESM::Probe).name() ); assert( std::find(mapping.begin(), mapping.end(), type1) != mapping.end() ); assert( std::find(mapping.begin(), mapping.end(), type2) != mapping.end() ); @@ -166,7 +166,7 @@ namespace MWGui void SortFilterItemModel::addDragItem (const MWWorld::Ptr& dragItem, size_t count) { - mDragItems.push_back(std::make_pair(dragItem, count)); + mDragItems.emplace_back(dragItem, count); } void SortFilterItemModel::clearDragItems() diff --git a/apps/openmw/mwgui/soulgemdialog.cpp b/apps/openmw/mwgui/soulgemdialog.cpp index 104c81eab..345c8b722 100644 --- a/apps/openmw/mwgui/soulgemdialog.cpp +++ b/apps/openmw/mwgui/soulgemdialog.cpp @@ -12,8 +12,8 @@ namespace MWGui { mSoulgem = soulgem; std::vector buttons; - buttons.push_back("#{sRechargeEnchantment}"); - buttons.push_back("#{sMake Enchantment}"); + buttons.emplace_back("#{sRechargeEnchantment}"); + buttons.emplace_back("#{sMake Enchantment}"); mManager->createInteractiveMessageBox("#{sDoYouWantTo}", buttons); mManager->eventButtonPressed += MyGUI::newDelegate(this, &SoulgemDialog::onButtonPressed); } diff --git a/apps/openmw/mwgui/spellview.cpp b/apps/openmw/mwgui/spellview.cpp index f03c1cedb..a8b7cb639 100644 --- a/apps/openmw/mwgui/spellview.cpp +++ b/apps/openmw/mwgui/spellview.cpp @@ -128,10 +128,10 @@ namespace MWGui group.push_back(costChance); Gui::SharedStateButton::createButtonGroup(group); - mLines.push_back(LineInfo(t, costChance, i)); + mLines.emplace_back(t, costChance, i); } else - mLines.push_back(LineInfo(t, (MyGUI::Widget*)nullptr, i)); + mLines.emplace_back(t, (MyGUI::Widget*)nullptr, i); t->setStateSelected(spell.mSelected); } @@ -236,7 +236,7 @@ namespace MWGui MyGUI::IntCoord(0, 0, mScrollView->getWidth(), 18), MyGUI::Align::Left | MyGUI::Align::Top); separator->setNeedMouseFocus(false); - mLines.push_back(LineInfo(separator, (MyGUI::Widget*)nullptr, NoSpellIndex)); + mLines.emplace_back(separator, (MyGUI::Widget*)nullptr, NoSpellIndex); } MyGUI::TextBox* groupWidget = mScrollView->createWidget("SandBrightText", @@ -255,10 +255,10 @@ namespace MWGui groupWidget2->setTextAlign(MyGUI::Align::Right); groupWidget2->setNeedMouseFocus(false); - mLines.push_back(LineInfo(groupWidget, groupWidget2, NoSpellIndex)); + mLines.emplace_back(groupWidget, groupWidget2, NoSpellIndex); } else - mLines.push_back(LineInfo(groupWidget, (MyGUI::Widget*)nullptr, NoSpellIndex)); + mLines.emplace_back(groupWidget, (MyGUI::Widget*)nullptr, NoSpellIndex); } diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index da3c7d186..7fae33bae 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -84,7 +84,7 @@ namespace MWGui { float value = getSkillForTraining(actorStats, i); - skills.push_back(std::make_pair(i, value)); + skills.emplace_back(i, value); } std::sort(skills.begin(), skills.end(), sortSkills); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ec6599093..5c0d48d5b 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -199,7 +199,7 @@ namespace MWMechanics if (sourceId != mSpellId) return; - mMagnitudes.push_back(std::make_pair(key, magnitude)); + mMagnitudes.emplace_back(key, magnitude); } std::vector> mMagnitudes; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 872a66799..b1db2562b 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -971,7 +971,7 @@ namespace MWMechanics { const OwnerMap& owners = it->second; for (OwnerMap::const_iterator ownerIt = owners.begin(); ownerIt != owners.end(); ++ownerIt) - result.push_back(std::make_pair(ownerIt->first.first, ownerIt->second)); + result.emplace_back(ownerIt->first.first, ownerIt->second); return result; } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 3835e26de..fafec7dd4 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -65,7 +65,7 @@ namespace virtual void apply(osg::Node &node) { if (dynamic_cast(&node)) - mToRemove.push_back(&node); + mToRemove.emplace_back(&node); traverse(node); } @@ -73,7 +73,7 @@ namespace virtual void apply(osg::Drawable& drw) { if (osgParticle::ParticleSystem* partsys = dynamic_cast(&drw)) - mToRemove.push_back(partsys); + mToRemove.emplace_back(partsys); } void remove() @@ -277,7 +277,7 @@ namespace if (vfxCallback) { if (vfxCallback->mFinished) - mToRemove.push_back(std::make_pair(group.asNode(), group.getParent(0))); + mToRemove.emplace_back(group.asNode(), group.getParent(0)); else mHasMagicEffects = true; } @@ -330,7 +330,7 @@ namespace { bool toRemove = mEffectId < 0 || vfxCallback->mParams.mEffectId == mEffectId; if (toRemove) - mToRemove.push_back(std::make_pair(group.asNode(), group.getParent(0))); + mToRemove.emplace_back(group.asNode(), group.getParent(0)); else mHasMagicEffects = true; } @@ -431,7 +431,7 @@ namespace node.setStateSet(nullptr); if (node.getNodeMask() == 0x1 && node.getNumParents() == 1) - mToRemove.push_back(std::make_pair(&node, node.getParent(0))); + mToRemove.emplace_back(&node, node.getParent(0)); else traverse(node); } @@ -449,12 +449,12 @@ namespace osg::Group* parentParent = static_cast(*(parent - 1)); if (parentGroup->getNumChildren() == 1 && parentGroup->getDataVariance() == osg::Object::STATIC) { - mToRemove.push_back(std::make_pair(parentGroup, parentParent)); + mToRemove.emplace_back(parentGroup, parentParent); return; } } - mToRemove.push_back(std::make_pair(&node, parentGroup)); + mToRemove.emplace_back(&node, parentGroup); } }; @@ -482,7 +482,7 @@ namespace { osg::Group* parent = static_cast(*(getNodePath().end()-2)); // Not safe to remove in apply(), since the visitor is still iterating the child list - mToRemove.push_back(std::make_pair(&node, parent)); + mToRemove.emplace_back(&node, parent); } } }; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index aaa797ef1..09e1f4001 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -118,7 +118,7 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell) if (segment.mFogOfWarImage && segment.mHasFogState) { std::unique_ptr fog (new ESM::FogState()); - fog->mFogTextures.push_back(ESM::FogTexture()); + fog->mFogTextures.emplace_back(); segment.saveFogOfWar(fog->mFogTextures.back()); @@ -150,7 +150,7 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell) { const MapSegment& segment = mSegments[std::make_pair(x,y)]; - fog->mFogTextures.push_back(ESM::FogTexture()); + fog->mFogTextures.emplace_back(); // saving even if !segment.mHasFogState so we don't mess up the segmenting // plus, older openmw versions can't deal with empty images diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index c756a3fc7..f49767d1d 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -596,7 +596,7 @@ namespace MWRender if (numinstances > 0) { // add a ref to the original template, to hint to the cache that it's still being used and should be kept in cache - templateRefs->mObjects.push_back(cnode); + templateRefs->mObjects.emplace_back(cnode); if (pair.second.mNeedCompile) { diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 5c79a4d26..974b419ed 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -428,7 +428,7 @@ namespace MWRender workItem->mKeyframes.push_back(std::string("meshes/") + basemodels[i] + ".kf"); } - workItem->mTextures.push_back("textures/_land_default.dds"); + workItem->mTextures.emplace_back("textures/_land_default.dds"); mWorkQueue->addWorkItem(workItem); } diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 10fc630bd..cd7a299f7 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1911,42 +1911,42 @@ void SkyManager::setWaterHeight(float height) void SkyManager::listAssetsToPreload(std::vector& models, std::vector& textures) { - models.push_back("meshes/sky_atmosphere.nif"); + models.emplace_back("meshes/sky_atmosphere.nif"); if (mSceneManager->getVFS()->exists("meshes/sky_night_02.nif")) - models.push_back("meshes/sky_night_02.nif"); - models.push_back("meshes/sky_night_01.nif"); - models.push_back("meshes/sky_clouds_01.nif"); - - models.push_back("meshes\\ashcloud.nif"); - models.push_back("meshes\\blightcloud.nif"); - models.push_back("meshes\\snow.nif"); - models.push_back("meshes\\blizzard.nif"); - - textures.push_back("textures/tx_mooncircle_full_s.dds"); - textures.push_back("textures/tx_mooncircle_full_m.dds"); - - textures.push_back("textures/tx_masser_new.dds"); - textures.push_back("textures/tx_masser_one_wax.dds"); - textures.push_back("textures/tx_masser_half_wax.dds"); - textures.push_back("textures/tx_masser_three_wax.dds"); - textures.push_back("textures/tx_masser_one_wan.dds"); - textures.push_back("textures/tx_masser_half_wan.dds"); - textures.push_back("textures/tx_masser_three_wan.dds"); - textures.push_back("textures/tx_masser_full.dds"); - - textures.push_back("textures/tx_secunda_new.dds"); - textures.push_back("textures/tx_secunda_one_wax.dds"); - textures.push_back("textures/tx_secunda_half_wax.dds"); - textures.push_back("textures/tx_secunda_three_wax.dds"); - textures.push_back("textures/tx_secunda_one_wan.dds"); - textures.push_back("textures/tx_secunda_half_wan.dds"); - textures.push_back("textures/tx_secunda_three_wan.dds"); - textures.push_back("textures/tx_secunda_full.dds"); - - textures.push_back("textures/tx_sun_05.dds"); - textures.push_back("textures/tx_sun_flash_grey_05.dds"); - - textures.push_back("textures/tx_raindrop_01.dds"); + models.emplace_back("meshes/sky_night_02.nif"); + models.emplace_back("meshes/sky_night_01.nif"); + models.emplace_back("meshes/sky_clouds_01.nif"); + + models.emplace_back("meshes\\ashcloud.nif"); + models.emplace_back("meshes\\blightcloud.nif"); + models.emplace_back("meshes\\snow.nif"); + models.emplace_back("meshes\\blizzard.nif"); + + textures.emplace_back("textures/tx_mooncircle_full_s.dds"); + textures.emplace_back("textures/tx_mooncircle_full_m.dds"); + + textures.emplace_back("textures/tx_masser_new.dds"); + textures.emplace_back("textures/tx_masser_one_wax.dds"); + textures.emplace_back("textures/tx_masser_half_wax.dds"); + textures.emplace_back("textures/tx_masser_three_wax.dds"); + textures.emplace_back("textures/tx_masser_one_wan.dds"); + textures.emplace_back("textures/tx_masser_half_wan.dds"); + textures.emplace_back("textures/tx_masser_three_wan.dds"); + textures.emplace_back("textures/tx_masser_full.dds"); + + textures.emplace_back("textures/tx_secunda_new.dds"); + textures.emplace_back("textures/tx_secunda_one_wax.dds"); + textures.emplace_back("textures/tx_secunda_half_wax.dds"); + textures.emplace_back("textures/tx_secunda_three_wax.dds"); + textures.emplace_back("textures/tx_secunda_one_wan.dds"); + textures.emplace_back("textures/tx_secunda_half_wan.dds"); + textures.emplace_back("textures/tx_secunda_three_wan.dds"); + textures.emplace_back("textures/tx_secunda_full.dds"); + + textures.emplace_back("textures/tx_sun_05.dds"); + textures.emplace_back("textures/tx_sun_flash_grey_05.dds"); + + textures.emplace_back("textures/tx_raindrop_01.dds"); } void SkyManager::setWaterEnabled(bool enabled) diff --git a/apps/openmw/mwscript/globalscripts.cpp b/apps/openmw/mwscript/globalscripts.cpp index 41f153b28..1a7e3ebbc 100644 --- a/apps/openmw/mwscript/globalscripts.cpp +++ b/apps/openmw/mwscript/globalscripts.cpp @@ -186,7 +186,7 @@ namespace MWScript // make list of global scripts to be added std::vector scripts; - scripts.push_back ("main"); + scripts.emplace_back("main"); for (MWWorld::Store::iterator iter = mStore.get().begin(); diff --git a/apps/openmw/mwscript/locals.cpp b/apps/openmw/mwscript/locals.cpp index 381d73ec8..352dc67b3 100644 --- a/apps/openmw/mwscript/locals.cpp +++ b/apps/openmw/mwscript/locals.cpp @@ -191,7 +191,7 @@ namespace MWScript case 2: value.setType (ESM::VT_Float); value.setFloat (mFloats.at (i2)); break; } - locals.mVariables.push_back (std::make_pair (names[i2], value)); + locals.mVariables.emplace_back (names[i2], value); } } } diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 1606b2979..a7be5a743 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -579,7 +579,7 @@ std::vector OpenAL_Output::enumerate() devnames = alcGetString(nullptr, ALC_DEVICE_SPECIFIER); while(devnames && *devnames) { - devlist.push_back(devnames); + devlist.emplace_back(devnames); devnames += strlen(devnames)+1; } return devlist; @@ -878,7 +878,7 @@ std::vector OpenAL_Output::enumerateHrtf() for(ALCint i = 0;i < num_hrtf;++i) { const ALCchar *entry = alcGetStringiSOFT(mDevice, ALC_HRTF_SPECIFIER_SOFT, i); - ret.push_back(entry); + ret.emplace_back(entry); } return ret; diff --git a/apps/openmw/mwstate/charactermanager.cpp b/apps/openmw/mwstate/charactermanager.cpp index 856264d03..b5868c3e5 100644 --- a/apps/openmw/mwstate/charactermanager.cpp +++ b/apps/openmw/mwstate/charactermanager.cpp @@ -77,7 +77,7 @@ MWState::Character* MWState::CharacterManager::createCharacter(const std::string path = mPath / test.str(); } - mCharacters.push_back (Character (path, mGame)); + mCharacters.emplace_back(path, mGame); return &mCharacters.back(); } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index d59704bf1..f331cea49 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -118,8 +118,8 @@ void MWState::StateManager::askLoadRecent() { MWState::Slot lastSave = *character->begin(); std::vector buttons; - buttons.push_back("#{sYes}"); - buttons.push_back("#{sNo}"); + buttons.emplace_back("#{sYes}"); + buttons.emplace_back("#{sNo}"); std::string tag("%s"); std::string message = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLoadLastSaveMsg", tag); size_t pos = message.find(tag); @@ -165,7 +165,7 @@ void MWState::StateManager::newGame (bool bypass) MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); std::vector buttons; - buttons.push_back("#{sOk}"); + buttons.emplace_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons); } } @@ -306,7 +306,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot Log(Debug::Error) << error.str(); std::vector buttons; - buttons.push_back("#{sOk}"); + buttons.emplace_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons); // If no file was written, clean up the slot @@ -557,7 +557,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); std::vector buttons; - buttons.push_back("#{sOk}"); + buttons.emplace_back("#{sOk}"); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons); } } @@ -633,8 +633,8 @@ bool MWState::StateManager::verifyProfile(const ESM::SavedGame& profile) const if (notFound) { std::vector buttons; - buttons.push_back("#{sYes}"); - buttons.push_back("#{sNo}"); + buttons.emplace_back("#{sYes}"); + buttons.emplace_back("#{sNo}"); MWBase::Environment::get().getWindowManager()->interactiveMessageBox("#{sMissingMastersMsg}", buttons, true); int selectedButton = MWBase::Environment::get().getWindowManager()->readPressedButton(); if (selectedButton == 1 || selectedButton == -1) diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index bee6a957d..9f719178c 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -496,7 +496,7 @@ namespace MWWorld else if (mTerrainViews.size() < positions.size()) { for (unsigned int i=mTerrainViews.size(); icreateView()); + mTerrainViews.emplace_back(mTerrain->createView()); } mTerrainPreloadPositions = positions; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index cf2b97ce7..6164c4f14 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -1012,7 +1012,7 @@ void MWWorld::InventoryStore::writeState(ESM::InventoryState &state) const std::vector > params; for (std::vector::const_iterator pIt = it->second.begin(); pIt != it->second.end(); ++pIt) { - params.push_back(std::make_pair(pIt->mRandom, pIt->mMultiplier)); + params.emplace_back(pIt->mRandom, pIt->mMultiplier); } state.mPermanentMagicEffectMagnitudes[it->first] = params; diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index 8a511030d..42914d4ac 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -101,7 +101,7 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) break; } - mScripts.push_back (std::make_pair (scriptName, ptr)); + mScripts.emplace_back (scriptName, ptr); } catch (const std::exception& exception) { diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index cc906e932..6d75ac2df 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -81,7 +81,7 @@ namespace continue; if (magicEffect->mBolt.empty()) - projectileIDs.push_back("VFX_DefaultBolt"); + projectileIDs.emplace_back("VFX_DefaultBolt"); else projectileIDs.push_back(magicEffect->mBolt); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 684376226..4d3194533 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -563,7 +563,7 @@ namespace MWWorld if (iter==mActiveCells.end()) { refsToLoad += MWBase::Environment::get().getWorld()->getExterior(x, y)->count(); - cellsPositionsToLoad.push_back(std::make_pair(x, y)); + cellsPositionsToLoad.emplace_back(x, y); } } } @@ -1027,7 +1027,7 @@ namespace MWWorld { continue; } - teleportDoors.push_back(MWWorld::ConstPtr(&door, cellStore)); + teleportDoors.emplace_back(&door, cellStore); } } diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 4c4417587..f8ec8c7c2 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -352,7 +352,7 @@ namespace MWWorld //========================================================================= Store::Store() { - mStatic.push_back(LandTextureList()); + mStatic.emplace_back(); LandTextureList <exl = mStatic[0]; // More than enough to hold Morrowind.esm. Extra lists for plugins will we // added on-the-fly in a different method. diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 9f2865868..7f1e5cf2c 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -638,7 +638,7 @@ namespace Compiler void Scanner::listKeywords (std::vector& keywords) { for (int i=0; Compiler::sKeywords[i]; ++i) - keywords.push_back (Compiler::sKeywords[i]); + keywords.emplace_back(Compiler::sKeywords[i]); if (mExtensions) mExtensions->listKeywords (keywords); diff --git a/components/esm/aisequence.cpp b/components/esm/aisequence.cpp index 7891299e3..df3c1ca9d 100644 --- a/components/esm/aisequence.cpp +++ b/components/esm/aisequence.cpp @@ -171,7 +171,7 @@ namespace AiSequence int type; esm.getHT(type); - mPackages.push_back(AiPackageContainer()); + mPackages.emplace_back(); mPackages.back().mType = type; switch (type) diff --git a/components/esm/inventorystate.cpp b/components/esm/inventorystate.cpp index 2392d263f..980d67f7e 100644 --- a/components/esm/inventorystate.cpp +++ b/components/esm/inventorystate.cpp @@ -76,7 +76,7 @@ void ESM::InventoryState::load (ESMReader &esm) float rand, multiplier; esm.getHT (rand); esm.getHNT (multiplier, "MULT"); - params.push_back(std::make_pair(rand, multiplier)); + params.emplace_back(rand, multiplier); } mPermanentMagicEffectMagnitudes[id] = params; } diff --git a/components/esm/locals.cpp b/components/esm/locals.cpp index bd51be08f..4149695fe 100644 --- a/components/esm/locals.cpp +++ b/components/esm/locals.cpp @@ -12,7 +12,7 @@ void ESM::Locals::load (ESMReader &esm) Variant value; value.read (esm, Variant::Format_Local); - mVariables.push_back (std::make_pair (id, value)); + mVariables.emplace_back (id, value); } } diff --git a/components/files/escape.cpp b/components/files/escape.cpp index 93ae9b885..8b11504d3 100644 --- a/components/files/escape.cpp +++ b/components/files/escape.cpp @@ -121,7 +121,7 @@ namespace Files EscapeStringVector * eSV = boost::any_cast(&v); for (std::vector::const_iterator it = tokens.begin(); it != tokens.end(); ++it) - eSV->mVector.push_back(EscapeHashString(*it)); + eSV->mVector.emplace_back(*it); } PathContainer EscapePath::toPathContainer(const EscapePathContainer & escapePathContainer) diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 0f4c4a5bd..9c654b9d1 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -180,7 +180,7 @@ GeomMorpherController::GeomMorpherController(const GeomMorpherController ©, GeomMorpherController::GeomMorpherController(const Nif::NiMorphData *data) { for (unsigned int i=0; imMorphs.size(); ++i) - mKeyFrames.push_back(FloatInterpolator(data->mMorphs[i].mKeyFrames)); + mKeyFrames.emplace_back(data->mMorphs[i].mKeyFrames); } void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable) diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 415bdae3a..83dad7826 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -237,7 +237,7 @@ namespace SceneUtil std::vector > lights; lights.reserve(lightList.size()); for (unsigned int i=0; imLightSource->getLight(frameNum)); + lights.emplace_back(lightList[i]->mLightSource->getLight(frameNum)); // the first light state attribute handles the actual state setting for all lights // it's best to batch these up so that we don't need to touch the modelView matrix more than necessary diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index dc22d4d80..3f080b286 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -1508,7 +1508,7 @@ void MWShadowTechnique::createShaders() { perFrameUniformList.clear(); perFrameUniformList.push_back(baseTextureSampler); - perFrameUniformList.push_back(baseTextureUnit.get()); + perFrameUniformList.emplace_back(baseTextureUnit.get()); perFrameUniformList.push_back(maxDistance); perFrameUniformList.push_back(fadeStart); } @@ -1520,7 +1520,7 @@ void MWShadowTechnique::createShaders() sstr<<"shadowTexture"< shadowTextureSampler = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i)); for (auto& perFrameUniformList : _uniforms) - perFrameUniformList.push_back(shadowTextureSampler.get()); + perFrameUniformList.emplace_back(shadowTextureSampler.get()); } { @@ -1528,7 +1528,7 @@ void MWShadowTechnique::createShaders() sstr<<"shadowTextureUnit"< shadowTextureUnit = new osg::Uniform(sstr.str().c_str(),(int)(settings->getBaseShadowTextureUnit()+sm_i)); for (auto& perFrameUniformList : _uniforms) - perFrameUniformList.push_back(shadowTextureUnit.get()); + perFrameUniformList.emplace_back(shadowTextureUnit.get()); } } @@ -2558,12 +2558,12 @@ bool MWShadowTechnique::cropShadowCameraToMainFrustum(Frustum& frustum, osg::Cam yMax = convexHull.max(1); zMin = convexHull.min(2); - planeList.push_back(osg::Plane(0.0, -1.0, 0.0, yMax)); - planeList.push_back(osg::Plane(0.0, 1.0, 0.0, -yMin)); - planeList.push_back(osg::Plane(-1.0, 0.0, 0.0, xMax)); - planeList.push_back(osg::Plane(1.0, 0.0, 0.0, -xMin)); + planeList.emplace_back(0.0, -1.0, 0.0, yMax); + planeList.emplace_back(0.0, 1.0, 0.0, -yMin); + planeList.emplace_back(-1.0, 0.0, 0.0, xMax); + planeList.emplace_back(1.0, 0.0, 0.0, -xMin); // In view space, the light is at the most positive value, and we want to cull stuff beyond the minimum value. - planeList.push_back(osg::Plane(0.0, 0.0, 1.0, -zMin)); + planeList.emplace_back(0.0, 0.0, 1.0, -zMin); // Don't add a zMax culling plane - we still want those objects, but don't care about their depth buffer value. } @@ -3192,7 +3192,7 @@ void SceneUtil::MWShadowTechnique::DebugHUD::addAnotherShadowMap() mDebugCameras[shadowMapNumber]->setClearColor(osg::Vec4(1.0, 1.0, 0.0, 1.0)); mDebugCameras[shadowMapNumber]->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); - mDebugGeometry.push_back(osg::createTexturedQuadGeometry(osg::Vec3(-1, -1, 0), osg::Vec3(2, 0, 0), osg::Vec3(0, 2, 0))); + mDebugGeometry.emplace_back(osg::createTexturedQuadGeometry(osg::Vec3(-1, -1, 0), osg::Vec3(2, 0, 0), osg::Vec3(0, 2, 0))); mDebugGeometry[shadowMapNumber]->setCullingActive(false); mDebugCameras[shadowMapNumber]->addChild(mDebugGeometry[shadowMapNumber]); osg::ref_ptr stateSet = mDebugGeometry[shadowMapNumber]->getOrCreateStateSet(); diff --git a/components/sceneutil/statesetupdater.cpp b/components/sceneutil/statesetupdater.cpp index 9fb9ba496..5d7dbd755 100644 --- a/components/sceneutil/statesetupdater.cpp +++ b/components/sceneutil/statesetupdater.cpp @@ -73,7 +73,7 @@ namespace SceneUtil : StateSetUpdater(copy, copyop) { for (unsigned int i=0; imObjects.push_back(obj); + mWorkItem->mObjects.emplace_back(obj); } void UnrefQueue::flush(SceneUtil::WorkQueue *workQueue) diff --git a/components/sceneutil/visitor.cpp b/components/sceneutil/visitor.cpp index 876ea920f..00d18ffcb 100644 --- a/components/sceneutil/visitor.cpp +++ b/components/sceneutil/visitor.cpp @@ -101,7 +101,7 @@ namespace SceneUtil node.setStateSet(nullptr); if (node.getNodeMask() == 0x1 && node.getNumParents() == 1) - mToRemove.push_back(std::make_pair(&node, node.getParent(0))); + mToRemove.emplace_back(&node, node.getParent(0)); else traverse(node); } @@ -120,12 +120,12 @@ namespace SceneUtil osg::Group* parentParent = static_cast(*(parent - 1)); if (parentGroup->getNumChildren() == 1 && parentGroup->getDataVariance() == osg::Object::STATIC) { - mToRemove.push_back(std::make_pair(parentGroup, parentParent)); + mToRemove.emplace_back(parentGroup, parentParent); return; } } - mToRemove.push_back(std::make_pair(&node, parentGroup)); + mToRemove.emplace_back(&node, parentGroup); } void RemoveTriBipVisitor::apply(osg::Drawable& drw) @@ -150,7 +150,7 @@ namespace SceneUtil { osg::Group* parent = static_cast(*(getNodePath().end()-2)); // Not safe to remove in apply(), since the visitor is still iterating the child list - mToRemove.push_back(std::make_pair(&node, parent)); + mToRemove.emplace_back(&node, parent); } } } diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index c30307f29..0eab2fd89 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -48,7 +48,7 @@ namespace Shader , mDefaultVsTemplate(defaultVsTemplate) , mDefaultFsTemplate(defaultFsTemplate) { - mRequirements.push_back(ShaderRequirements()); + mRequirements.emplace_back(); } void ShaderVisitor::setForceShaders(bool force) diff --git a/components/terrain/chunkmanager.cpp b/components/terrain/chunkmanager.cpp index 87966b47c..041414a87 100644 --- a/components/terrain/chunkmanager.cpp +++ b/components/terrain/chunkmanager.cpp @@ -112,7 +112,7 @@ void ChunkManager::createCompositeMapGeometry(float chunkSize, const osg::Vec2f& geom->setStateSet(*it); - compositeMap.mDrawables.push_back(geom); + compositeMap.mDrawables.emplace_back(geom); } } } diff --git a/components/terrain/viewdata.cpp b/components/terrain/viewdata.cpp index c24252b7d..e4d043ffc 100644 --- a/components/terrain/viewdata.cpp +++ b/components/terrain/viewdata.cpp @@ -192,7 +192,7 @@ ViewData *ViewDataMap::createOrReuseView() } else { - mViewVector.push_back(ViewData()); + mViewVector.emplace_back(); vd = &mViewVector.back(); } mUsedViews.push_back(vd); diff --git a/components/vfs/bsaarchive.cpp b/components/vfs/bsaarchive.cpp index 9646b62af..ac65c58a1 100644 --- a/components/vfs/bsaarchive.cpp +++ b/components/vfs/bsaarchive.cpp @@ -21,7 +21,7 @@ BsaArchive::BsaArchive(const std::string &filename) const Bsa::BSAFile::FileList &filelist = mFile->getList(); for(Bsa::BSAFile::FileList::const_iterator it = filelist.begin();it != filelist.end();++it) { - mResources.push_back(BsaArchiveFile(&*it, mFile.get())); + mResources.emplace_back(&*it, mFile.get()); } } diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index 73e01675a..bf24acf7e 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -34,7 +34,7 @@ namespace Gui void MWList::addSeparator() { - mItems.push_back(""); + mItems.emplace_back(""); } void MWList::adjustSize() From fb4250a2b726bb7ca27315c2924c0015e95a9944 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Mon, 19 Oct 2020 15:02:10 +0300 Subject: [PATCH 004/111] Strip the plugin index when looking for deleted refs. --- apps/opencs/model/world/refcollection.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 1d91bbd59..344cf1bb5 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -64,9 +64,10 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool // ignore content file number std::map::iterator iter = cache.begin(); + unsigned int thisIndex = ref.mRefNum.mIndex & 0x00ffffff; for (; iter != cache.end(); ++iter) { - if (ref.mRefNum.mIndex == iter->first.mIndex) + if (thisIndex == iter->first.mIndex) break; } From 7da8479d2576da1a59bb5e7346061b0f2aaac8ce Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Wed, 21 Oct 2020 19:25:45 +0300 Subject: [PATCH 005/111] Fix lower body blocking animation priority (bug #5656) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/character.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7c0dd2e2..955ad01a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ Bug #5622: Can't properly interact with the console when in pause menu Bug #5639: Tooltips cover Messageboxes Bug #5644: Summon effects running on the player during game initialization cause crashes + Bug #5656: Sneaking characters block hits while standing Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging Feature #4894: Consider actors as obstacles for pathfinding diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index b0792a9e5..657f2e2ec 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -270,6 +270,7 @@ void CharacterController::refreshHitRecoilAnims(CharacterState& idle) mCurrentHit = "shield"; MWRender::Animation::AnimPriority priorityBlock (Priority_Hit); priorityBlock[MWRender::Animation::BoneGroup_LeftArm] = Priority_Block; + priorityBlock[MWRender::Animation::BoneGroup_LowerBody] = Priority_WeaponLowerBody; mAnimation->play(mCurrentHit, priorityBlock, MWRender::Animation::BlendMask_All, true, 1, "block start", "block stop", 0.0f, 0); } @@ -289,6 +290,8 @@ void CharacterController::refreshHitRecoilAnims(CharacterState& idle) mUpperBodyState = UpperCharState_Nothing; } } + if (mHitState != CharState_None) + idle = CharState_None; } else if(!mAnimation->isPlaying(mCurrentHit)) { @@ -308,8 +311,6 @@ void CharacterController::refreshHitRecoilAnims(CharacterState& idle) mAnimation->disable(mCurrentHit); mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::BlendMask_All, true, 1, "loop stop", "stop", 0.0f, 0); } - if (mHitState != CharState_None) - idle = CharState_None; } void CharacterController::refreshJumpAnims(const std::string& weapShortGroup, JumpingState jump, CharacterState& idle, bool force) From 2916a9462e9b76e9ccbe306a3dde3584f430bad6 Mon Sep 17 00:00:00 2001 From: fredzio Date: Wed, 21 Oct 2020 21:28:01 +0200 Subject: [PATCH 006/111] Fix standing actors logic: it is updated in the solver only if the actor is standing on "something". The ground is not "something", so in case the actor goes from standing on an object to the standing on the ground, this change was not taken into account. Clear the value before the simulation to solve this problem. --- apps/openmw/mwphysics/physicssystem.cpp | 11 ++++++++--- apps/openmw/mwphysics/physicssystem.hpp | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 00068c1e6..5be614b81 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -678,10 +678,10 @@ namespace MWPhysics mTimeAccum -= numSteps * mPhysicsDt; - return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(), mStandingCollisions, skipSimulation); + return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), mStandingCollisions, skipSimulation); } - std::vector PhysicsSystem::prepareFrameData() + std::vector PhysicsSystem::prepareFrameData(int numSteps) { std::vector actorsFrameData; actorsFrameData.reserve(mMovementQueue.size()); @@ -723,7 +723,12 @@ namespace MWPhysics // Slow fall reduces fall speed by a factor of (effect magnitude / 200) const float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f)); - actorsFrameData.emplace_back(std::move(physicActor), character, mStandingCollisions[character], moveToWaterSurface, movement, slowFall, waterlevel); + // Ue current value only if we don't advance the simulation. Otherwise we might get a stale value. + MWWorld::Ptr standingOn; + if (numSteps == 0) + standingOn = mStandingCollisions[character]; + + actorsFrameData.emplace_back(std::move(physicActor), character, standingOn, moveToWaterSurface, movement, slowFall, waterlevel); } mMovementQueue.clear(); return actorsFrameData; diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index f89a29cae..3198c5d44 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -237,7 +237,7 @@ namespace MWPhysics void updateWater(); - std::vector prepareFrameData(); + std::vector prepareFrameData(int numSteps); osg::ref_ptr mUnrefQueue; From 7efd48e6fda066c1a642aa8bbfabf12202e91f9e Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 21 Oct 2020 20:06:16 +0000 Subject: [PATCH 007/111] Copy Chocolatey log so it gets picked up as an artefact --- .gitlab-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3201dd6b7..f35cfb4f3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -120,6 +120,8 @@ variables: &cs-targets Get-ChildItem -Recurse *.pdb | Remove-Item } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' + after_script: + - Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log cache: key: ninja-v2 paths: @@ -208,6 +210,8 @@ Windows_Ninja_CS_RelWithDebInfo: Get-ChildItem -Recurse *.pdb | Remove-Item } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' + after_script: + - Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log cache: key: msbuild-v2 paths: @@ -299,4 +303,4 @@ Debian_AndroidNDK_arm64-v8a: - ccache -s artifacts: paths: - - build/install/ \ No newline at end of file + - build/install/ From 449e7ce86fff99c888a9ce152679d0af79f596f8 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 21 Oct 2020 22:07:00 +0200 Subject: [PATCH 008/111] C++17; make it count --- CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 87551fe01..82d6694dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ project(OpenMW) cmake_minimum_required(VERSION 3.1.0) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) # for link time optimization, remove if cmake version is >= 3.9 if(POLICY CMP0069) @@ -393,9 +395,6 @@ if (NOT WIN32 AND NOT APPLE) "${OpenMW_BINARY_DIR}/org.openmw.cs.desktop") endif() -# CXX Compiler settings -set(CMAKE_CXX_STANDARD 17) - if(OPENMW_LTO_BUILD) if(NOT CMAKE_VERSION VERSION_LESS 3.9) include(CheckIPOSupported) From f1b7cd5404536853f108b04a070ca2512ffb582e Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Thu, 22 Oct 2020 01:57:23 +0300 Subject: [PATCH 009/111] Don't reset temporarily hidden container window --- apps/openmw/mwgui/container.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index fdb27addc..16b38eaf9 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -163,6 +163,10 @@ namespace MWGui { WindowBase::onClose(); + // Make sure the window was actually closed and not temporarily hidden. + if (MWBase::Environment::get().getWindowManager()->containsMode(GM_Container)) + return; + if (mModel) mModel->onClose(); @@ -185,6 +189,7 @@ namespace MWGui // transfer everything into the player's inventory ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel(); + assert(mModel); mModel->update(); // unequip all items to avoid unequipping/reequipping From 534fffb83d0efed3e87245d99366ab39c2ef755c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 21 Oct 2020 23:30:39 +0000 Subject: [PATCH 010/111] Chocolatey has one L --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f35cfb4f3..25a04d536 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -96,7 +96,7 @@ variables: &cs-targets - windows before_script: - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" - - choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolately/" --priority=1 + - choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolatey/" --priority=1 - choco install git --force --params "/GitAndUnixToolsOnPath" -y - choco install 7zip -y - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y @@ -188,7 +188,7 @@ Windows_Ninja_CS_RelWithDebInfo: - windows before_script: - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" - - choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolately/" --priority=1 + - choco source add -n=openmw-proxy -s="https://repo.openmw.org/repository/Chocolatey/" --priority=1 - choco install git --force --params "/GitAndUnixToolsOnPath" -y - choco install 7zip -y - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y From 212b293803a8c518384007a93fd2665c6640d03c Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 18 Oct 2020 00:02:58 +0200 Subject: [PATCH 011/111] Use same parameter name in definition and declaration --- apps/openmw/mwphysics/physicssystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 5be614b81..75827d3f9 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -648,7 +648,7 @@ namespace MWPhysics return false; } - void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &movement) + void PhysicsSystem::queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity) { for(auto& movementItem : mMovementQueue) { From 4fc5b6f6f4e336f78a19beba40c0bcd77afe8c82 Mon Sep 17 00:00:00 2001 From: fredzio Date: Wed, 21 Oct 2020 11:08:40 +0200 Subject: [PATCH 012/111] Sort headers --- apps/openmw/mwphysics/mtphysics.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index 4862393f3..2d0db059d 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -3,10 +3,9 @@ #include #include -#include #include +#include -#include #include #include "physicssystem.hpp" From 1357bba0a000978cf3fff20a32e8140b1697c3d1 Mon Sep 17 00:00:00 2001 From: fredzio Date: Wed, 21 Oct 2020 11:08:59 +0200 Subject: [PATCH 013/111] Use some C++17 where it makes the code more readable Also replace boost::optional --- apps/openmw/mwphysics/mtphysics.cpp | 50 ++++++++++++------------- apps/openmw/mwphysics/mtphysics.hpp | 9 +++-- apps/openmw/mwphysics/physicssystem.cpp | 6 +-- components/misc/barrier.hpp | 2 +- 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 1ad0ae9c0..fa5a193e2 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -185,7 +185,7 @@ namespace MWPhysics mNewFrame = false; if (mLOSCacheExpiry >= 0) { - std::unique_lock lock(mLOSCacheMutex); + std::unique_lock lock(mLOSCacheMutex); mLOSCache.erase( std::remove_if(mLOSCache.begin(), mLOSCache.end(), [](const LOSRequest& req) { return req.mStale; }), @@ -196,7 +196,7 @@ namespace MWPhysics PhysicsTaskScheduler::~PhysicsTaskScheduler() { - std::unique_lock lock(mSimulationMutex); + std::unique_lock lock(mSimulationMutex); mQuit = true; mNumJobs = 0; mRemainingSteps = 0; @@ -211,7 +211,7 @@ namespace MWPhysics // This function run in the main thread. // While the mSimulationMutex is held, background physics threads can't run. - std::unique_lock lock(mSimulationMutex); + std::unique_lock lock(mSimulationMutex); // start by finishing previous background computation if (mNumThreads != 0) @@ -294,25 +294,25 @@ namespace MWPhysics void PhysicsTaskScheduler::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const { - MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); + MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); mCollisionWorld->rayTest(rayFromWorld, rayToWorld, resultCallback); } void PhysicsTaskScheduler::convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, btCollisionWorld::ConvexResultCallback& resultCallback) const { - MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); + MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); mCollisionWorld->convexSweepTest(castShape, from, to, resultCallback); } void PhysicsTaskScheduler::contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback) { - std::shared_lock lock(mCollisionWorldMutex); + std::shared_lock lock(mCollisionWorldMutex); mCollisionWorld->contactTest(colObj, resultCallback); } - boost::optional PhysicsTaskScheduler::getHitPoint(const btTransform& from, btCollisionObject* target) + std::optional PhysicsTaskScheduler::getHitPoint(const btTransform& from, btCollisionObject* target) { - MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); + MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); // target the collision object's world origin, this should be the center of the collision object btTransform rayTo; rayTo.setIdentity(); @@ -323,37 +323,37 @@ namespace MWPhysics mCollisionWorld->rayTestSingle(from, rayTo, target, target->getCollisionShape(), target->getWorldTransform(), cb); if (!cb.hasHit()) // didn't hit the target. this could happen if point is already inside the collision box - return boost::none; + return std::nullopt; return {cb.m_hitPointWorld}; } void PhysicsTaskScheduler::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) { - std::shared_lock lock(mCollisionWorldMutex); + std::shared_lock lock(mCollisionWorldMutex); mCollisionWorld->getBroadphase()->aabbTest(aabbMin, aabbMax, callback); } void PhysicsTaskScheduler::getAabb(const btCollisionObject* obj, btVector3& min, btVector3& max) { - std::shared_lock lock(mCollisionWorldMutex); + std::shared_lock lock(mCollisionWorldMutex); obj->getCollisionShape()->getAabb(obj->getWorldTransform(), min, max); } void PhysicsTaskScheduler::setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask) { - std::unique_lock lock(mCollisionWorldMutex); + std::unique_lock lock(mCollisionWorldMutex); collisionObject->getBroadphaseHandle()->m_collisionFilterMask = collisionFilterMask; } void PhysicsTaskScheduler::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask) { - std::unique_lock lock(mCollisionWorldMutex); + std::unique_lock lock(mCollisionWorldMutex); mCollisionWorld->addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask); } void PhysicsTaskScheduler::removeCollisionObject(btCollisionObject* collisionObject) { - std::unique_lock lock(mCollisionWorldMutex); + std::unique_lock lock(mCollisionWorldMutex); mCollisionWorld->removeCollisionObject(collisionObject); } @@ -361,19 +361,19 @@ namespace MWPhysics { if (mDeferAabbUpdate) { - std::unique_lock lock(mUpdateAabbMutex); + std::unique_lock lock(mUpdateAabbMutex); mUpdateAabb.insert(std::move(ptr)); } else { - std::unique_lock lock(mCollisionWorldMutex); + std::unique_lock lock(mCollisionWorldMutex); updatePtrAabb(ptr); } } bool PhysicsTaskScheduler::getLineOfSight(const std::weak_ptr& actor1, const std::weak_ptr& actor2) { - std::unique_lock lock(mLOSCacheMutex); + std::unique_lock lock(mLOSCacheMutex); auto actorPtr1 = actor1.lock(); auto actorPtr2 = actor2.lock(); @@ -395,7 +395,7 @@ namespace MWPhysics void PhysicsTaskScheduler::refreshLOSCache() { - std::shared_lock lock(mLOSCacheMutex); + std::shared_lock lock(mLOSCacheMutex); int job = 0; int numLOS = mLOSCache.size(); while ((job = mNextLOS.fetch_add(1, std::memory_order_relaxed)) < numLOS) @@ -414,9 +414,7 @@ namespace MWPhysics void PhysicsTaskScheduler::updateAabbs() { - std::unique_lock lock1(mCollisionWorldMutex, std::defer_lock); - std::unique_lock lock2(mUpdateAabbMutex, std::defer_lock); - std::lock(lock1, lock2); + std::scoped_lock lock(mCollisionWorldMutex, mUpdateAabbMutex); std::for_each(mUpdateAabb.begin(), mUpdateAabb.end(), [this](const std::weak_ptr& ptr) { updatePtrAabb(ptr); }); mUpdateAabb.clear(); @@ -441,7 +439,7 @@ namespace MWPhysics void PhysicsTaskScheduler::worker() { - std::shared_lock lock(mSimulationMutex); + std::shared_lock lock(mSimulationMutex); while (!mQuit) { if (!mNewFrame) @@ -453,7 +451,7 @@ namespace MWPhysics int job = 0; while (mRemainingSteps && (job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs) { - MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); + MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); if(const auto actor = mActorsFrameData[job].mActor.lock()) MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld.get(), *mWorldFrameData); } @@ -481,7 +479,7 @@ namespace MWPhysics void PhysicsTaskScheduler::updateActorsPositions() { - std::unique_lock lock(mCollisionWorldMutex); + std::unique_lock lock(mCollisionWorldMutex); for (auto& actorData : mActorsFrameData) { if(const auto actor = actorData.mActor.lock()) @@ -499,7 +497,7 @@ namespace MWPhysics void PhysicsTaskScheduler::udpateActorsAabbs() { - std::unique_lock lock(mCollisionWorldMutex); + std::unique_lock lock(mCollisionWorldMutex); for (const auto& actorData : mActorsFrameData) if (actorData.mPositionChanged) { @@ -517,7 +515,7 @@ namespace MWPhysics resultCallback.m_collisionFilterGroup = 0xFF; resultCallback.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap|CollisionType_Door; - MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); + MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); mCollisionWorld->rayTest(pos1, pos2, resultCallback); return !resultCallback.hasHit(); diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index 2d0db059d..100e71a90 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -35,7 +36,7 @@ namespace MWPhysics void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; void convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, btCollisionWorld::ConvexResultCallback& resultCallback) const; void contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback); - boost::optional getHitPoint(const btTransform& from, btCollisionObject* target); + std::optional getHitPoint(const btTransform& from, btCollisionObject* target); void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback); void getAabb(const btCollisionObject* obj, btVector3& min, btVector3& max); void setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask); @@ -82,9 +83,9 @@ namespace MWPhysics std::atomic mNextLOS; std::vector mThreads; - mutable std::shared_timed_mutex mSimulationMutex; - mutable std::shared_timed_mutex mCollisionWorldMutex; - mutable std::shared_timed_mutex mLOSCacheMutex; + mutable std::shared_mutex mSimulationMutex; + mutable std::shared_mutex mCollisionWorldMutex; + mutable std::shared_mutex mLOSCacheMutex; mutable std::mutex mUpdateAabbMutex; std::condition_variable_any mHasJob; }; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 75827d3f9..e8e342b4b 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -239,7 +239,7 @@ namespace MWPhysics auto hitpoint = mTaskScheduler->getHitPoint(rayFrom, targetCollisionObj); if (hitpoint) - return (point - Misc::Convert::toOsg(hitpoint.get())).length(); + return (point - Misc::Convert::toOsg(*hitpoint)).length(); // didn't hit the target. this could happen if point is already inside the collision box return 0.f; @@ -686,10 +686,8 @@ namespace MWPhysics std::vector actorsFrameData; actorsFrameData.reserve(mMovementQueue.size()); const MWBase::World *world = MWBase::Environment::get().getWorld(); - for (const auto& m : mMovementQueue) + for (const auto& [character, movement] : mMovementQueue) { - const auto& character = m.first; - const auto& movement = m.second; const auto foundActor = mActors.find(character); if (foundActor == mActors.end()) // actor was already removed from the scene { diff --git a/components/misc/barrier.hpp b/components/misc/barrier.hpp index 7259b8452..a5af9f565 100644 --- a/components/misc/barrier.hpp +++ b/components/misc/barrier.hpp @@ -21,7 +21,7 @@ namespace Misc /// @brief stop execution of threads until count distinct threads reach this point void wait() { - std::unique_lock lock(mMutex); + std::unique_lock lock(mMutex); ++mRendezvousCount; const int currentGeneration = mGeneration; From a19db73eca9785ef16c5c3600d40330f1788ba07 Mon Sep 17 00:00:00 2001 From: fredzio Date: Thu, 22 Oct 2020 09:24:56 +0200 Subject: [PATCH 014/111] Fix bad rebase --- apps/openmw/mwphysics/physicssystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index e8e342b4b..a349ee244 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -654,12 +654,12 @@ namespace MWPhysics { if (movementItem.first == ptr) { - movementItem.second = movement; + movementItem.second = velocity; return; } } - mMovementQueue.emplace_back(ptr, movement); + mMovementQueue.emplace_back(ptr, velocity); } void PhysicsSystem::clearQueuedMovement() From 46a1950b0e54d84426805d713629f64e7d2fc92b Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 22 Oct 2020 15:50:47 +0400 Subject: [PATCH 015/111] Do not use deprecated Qt functions --- apps/launcher/maindialog.cpp | 8 ++++---- apps/opencs/main.cpp | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index d88a41117..df2ba6891 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -211,10 +211,10 @@ void Launcher::MainDialog::setVersionLabel() versionLabel->setText(tr("OpenMW development (%1)").arg(revision.left(10))); // Add the compile date and time - versionLabel->setToolTip(tr("Compiled on %1 %2").arg(QLocale(QLocale::C).toDate(QString(__DATE__).simplified(), - QLatin1String("MMM d yyyy")).toString(Qt::SystemLocaleLongDate), - QLocale(QLocale::C).toTime(QString(__TIME__).simplified(), - QLatin1String("hh:mm:ss")).toString(Qt::SystemLocaleShortDate))); + auto compileDate = QLocale(QLocale::C).toDate(QString(__DATE__).simplified(), QLatin1String("MMM d yyyy")); + auto compileTime = QLocale(QLocale::C).toTime(QString(__TIME__).simplified(), QLatin1String("hh:mm:ss")); + versionLabel->setToolTip(tr("Compiled on %1 %2").arg(QLocale::system().toString(compileDate, QLocale::LongFormat), + QLocale::system().toString(compileTime, QLocale::ShortFormat))); } bool Launcher::MainDialog::setup() diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index d1d4944cf..5287c8b19 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -47,9 +47,6 @@ int runApplication(int argc, char *argv[]) setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0); #endif - // To allow background thread drawing in OSG - QApplication::setAttribute(Qt::AA_X11InitThreads, true); - Q_INIT_RESOURCE (resources); qRegisterMetaType ("std::string"); From 6c311f4a3d9a0c6bdc88371563962f4d2ea08a14 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 22 Oct 2020 21:38:22 +0100 Subject: [PATCH 016/111] Partially revert 3a912485 While it solved the bug it was supposed to, it caused a regression where the user config could no longer override the global config. --- components/files/configurationmanager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index 0ba2d1519..c74c39922 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -59,6 +59,10 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m bool silent = mSilent; mSilent = quiet; + // User config has the highest priority. + loadConfig(mFixedPath.getUserConfigPath(), variables, description); + boost::program_options::notify(variables); + // read either local or global config depending on type of installation bool loaded = loadConfig(mFixedPath.getLocalPath(), variables, description); boost::program_options::notify(variables); @@ -68,10 +72,6 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m boost::program_options::notify(variables); } - // User config has the highest priority. - loadConfig(mFixedPath.getUserConfigPath(), variables, description); - boost::program_options::notify(variables); - mSilent = silent; } From d826fbdadfa32f1c4df70ea1dbe52c861626c9e3 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 22 Oct 2020 22:39:59 +0200 Subject: [PATCH 017/111] components/bsa cleanup --- components/bsa/bsa_file.cpp | 2 +- components/bsa/bsa_file.hpp | 5 ++--- components/bsa/compressedbsafile.cpp | 28 +++++++++++++--------------- components/bsa/compressedbsafile.hpp | 2 +- components/bsa/memorystream.hpp | 8 ++++---- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index abeca5326..3fd74dd83 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -150,7 +150,7 @@ void BSAFile::readHeader() /// Get the index of a given file name, or -1 if not found int BSAFile::getIndex(const char *str) const { - Lookup::const_iterator it = mLookup.find(str); + auto it = mLookup.find(str); if(it == mLookup.end()) return -1; diff --git a/components/bsa/bsa_file.hpp b/components/bsa/bsa_file.hpp index d12d01b0c..037802739 100644 --- a/components/bsa/bsa_file.hpp +++ b/components/bsa/bsa_file.hpp @@ -24,7 +24,7 @@ #ifndef BSA_BSA_FILE_H #define BSA_BSA_FILE_H -#include +#include #include #include #include @@ -106,8 +106,7 @@ public: : mIsLoaded(false) { } - virtual ~BSAFile() - { } + virtual ~BSAFile() = default; /// Open an archive file. void open(const std::string &file); diff --git a/components/bsa/compressedbsafile.cpp b/components/bsa/compressedbsafile.cpp index adc98c454..38fab856c 100644 --- a/components/bsa/compressedbsafile.cpp +++ b/components/bsa/compressedbsafile.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -103,8 +102,7 @@ CompressedBSAFile::CompressedBSAFile() : mCompressedByDefault(false), mEmbeddedFileNames(false) { } -CompressedBSAFile::~CompressedBSAFile() -{ } +CompressedBSAFile::~CompressedBSAFile() = default; /// Read header information from the input source void CompressedBSAFile::readHeader() @@ -183,7 +181,7 @@ void CompressedBSAFile::readHeader() else input.read(reinterpret_cast(&fr.offset), 4); // not sure purpose of offset - std::map::const_iterator lb = mFolders.lower_bound(hash); + auto lb = mFolders.lower_bound(hash); if (lb != mFolders.end() && !(mFolders.key_comp()(hash, lb->first))) fail("Archive found duplicate folder name hash"); else @@ -194,7 +192,7 @@ void CompressedBSAFile::readHeader() std::uint64_t fileHash; FileRecord file; - std::string folder(""); + std::string folder; std::uint64_t folderHash; if ((archiveFlags & 0x1) == 0) folderCount = 1; // TODO: not tested - unit test necessary @@ -209,7 +207,7 @@ void CompressedBSAFile::readHeader() folderHash = generateHash(folder, std::string()); - std::map::iterator iter = mFolders.find(folderHash); + auto iter = mFolders.find(folderHash); if (iter == mFolders.end()) fail("Archive folder name hash not found"); @@ -219,13 +217,13 @@ void CompressedBSAFile::readHeader() input.read(reinterpret_cast(&file.size), 4); input.read(reinterpret_cast(&file.offset), 4); - std::map::const_iterator lb = iter->second.files.lower_bound(fileHash); + auto lb = iter->second.files.lower_bound(fileHash); if (lb != iter->second.files.end() && !(iter->second.files.key_comp()(fileHash, lb->first))) fail("Archive found duplicate file name hash"); iter->second.files.insert(lb, std::pair(fileHash, file)); - FileStruct fileStruct; + FileStruct fileStruct{}; fileStruct.fileSize = file.getSizeWithoutCompressionFlag(); fileStruct.offset = file.offset; fileStruct.name = nullptr; @@ -308,12 +306,12 @@ CompressedBSAFile::FileRecord CompressedBSAFile::getFileRecord(const std::string std::string folder = p.string(); std::uint64_t folderHash = generateHash(folder, std::string()); - std::map::const_iterator it = mFolders.find(folderHash); + auto it = mFolders.find(folderHash); if (it == mFolders.end()) return FileRecord(); // folder not found, return default which has offset of sInvalidOffset std::uint64_t fileHash = generateHash(stem, ext); - std::map::const_iterator iter = it->second.files.find(fileHash); + auto iter = it->second.files.find(fileHash); if (iter == it->second.files.end()) return FileRecord(); // file not found, return default which has offset of sInvalidOffset @@ -430,12 +428,12 @@ BsaVersion CompressedBSAFile::detectVersion(std::string filePath) //mFiles used by OpenMW expects uncompressed sizes void CompressedBSAFile::convertCompressedSizesToUncompressed() { - for (auto iter = mFiles.begin(); iter != mFiles.end(); ++iter) + for (auto & mFile : mFiles) { - const FileRecord& fileRecord = getFileRecord(iter->name); + const FileRecord& fileRecord = getFileRecord(mFile.name); if (!fileRecord.isValid()) { - fail("Could not find file " + std::string(iter->name) + " in BSA"); + fail("Could not find file " + std::string(mFile.name) + " in BSA"); } if (!fileRecord.isCompressed(mCompressedByDefault)) @@ -452,11 +450,11 @@ void CompressedBSAFile::convertCompressedSizesToUncompressed() getBZString(embeddedFileName, *(dataBegin.get())); } - dataBegin->read(reinterpret_cast(&(iter->fileSize)), sizeof(iter->fileSize)); + dataBegin->read(reinterpret_cast(&(mFile.fileSize)), sizeof(mFile.fileSize)); } } -std::uint64_t CompressedBSAFile::generateHash(std::string stem, std::string extension) const +std::uint64_t CompressedBSAFile::generateHash(std::string stem, std::string extension) { size_t len = stem.length(); if (len == 0) diff --git a/components/bsa/compressedbsafile.hpp b/components/bsa/compressedbsafile.hpp index f3ad584d8..deddfae38 100644 --- a/components/bsa/compressedbsafile.hpp +++ b/components/bsa/compressedbsafile.hpp @@ -80,7 +80,7 @@ namespace Bsa //mFiles used by OpenMW will contain uncompressed file sizes void convertCompressedSizesToUncompressed(); /// \brief Normalizes given filename or folder and generates format-compatible hash. See https://en.uesp.net/wiki/Tes4Mod:Hash_Calculation. - std::uint64_t generateHash(std::string stem, std::string extension) const; + static std::uint64_t generateHash(std::string stem, std::string extension) ; Files::IStreamPtr getFile(const FileRecord& fileRecord); public: CompressedBSAFile(); diff --git a/components/bsa/memorystream.hpp b/components/bsa/memorystream.hpp index 5dbe16ebe..d168e93d6 100644 --- a/components/bsa/memorystream.hpp +++ b/components/bsa/memorystream.hpp @@ -37,8 +37,8 @@ Class used internally by MemoryInputStream. class MemoryInputStreamBuf : public std::streambuf { public: - MemoryInputStreamBuf(size_t bufferSize); - char* getRawData(); + explicit MemoryInputStreamBuf(size_t bufferSize); + virtual char* getRawData(); private: //correct call to delete [] on C++ 11 std::vector mBufferPtr; @@ -54,8 +54,8 @@ private: */ class MemoryInputStream : virtual MemoryInputStreamBuf, std::istream { public: - MemoryInputStream(size_t bufferSize); - char* getRawData(); + explicit MemoryInputStream(size_t bufferSize); + char* getRawData() override; }; } From 651a5a27f6ca11fb34003bccaa2f6781d46a9e81 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 22 Oct 2020 21:44:47 +0100 Subject: [PATCH 018/111] Fix inconsistent indentation This has been irritating me for years. --- apps/openmw/main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index a39dd2e39..4e18ad95f 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -63,16 +63,16 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("data", bpo::value()->default_value(Files::EscapePathContainer(), "data") ->multitoken()->composing(), "set data directories (later directories have higher priority)") - ("data-local", bpo::value()->default_value(""), + ("data-local", bpo::value()->default_value(""), "set local data directory (highest priority)") ("fallback-archive", bpo::value()->default_value(Files::EscapeStringVector(), "fallback-archive") ->multitoken(), "set fallback BSA archives (later archives have higher priority)") - ("resources", bpo::value()->default_value("resources"), + ("resources", bpo::value()->default_value("resources"), "set resources directory") - ("start", bpo::value()->default_value(""), + ("start", bpo::value()->default_value(""), "set initial cell") ("content", bpo::value()->default_value(Files::EscapeStringVector(), "") @@ -90,7 +90,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("script-console", bpo::value()->implicit_value(true) ->default_value(false), "enable console-only script functionality") - ("script-run", bpo::value()->default_value(""), + ("script-run", bpo::value()->default_value(""), "select a file containing a list of console commands that is executed on startup") ("script-warn", bpo::value()->implicit_value (1) @@ -106,7 +106,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("script-blacklist-use", bpo::value()->implicit_value(true) ->default_value(true), "enable script blacklisting") - ("load-savegame", bpo::value()->default_value(""), + ("load-savegame", bpo::value()->default_value(""), "load a save game file on game startup (specify an absolute filename or a filename relative to the current working directory)") ("skip-menu", bpo::value()->implicit_value(true) @@ -118,14 +118,14 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("fs-strict", bpo::value()->implicit_value(true) ->default_value(false), "strict file system handling (no case folding)") - ("encoding", bpo::value()-> + ("encoding", bpo::value()-> default_value("win1252"), "Character encoding used in OpenMW game messages:\n" "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n" "\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n" "\n\twin1252 - Western European (Latin) alphabet, used by default") - ("fallback", bpo::value()->default_value(FallbackMap(), "") + ("fallback", bpo::value()->default_value(FallbackMap(), "") ->multitoken()->composing(), "fallback values") ("no-grab", bpo::value()->implicit_value(true)->default_value(false), "Don't grab mouse cursor") From 5475e696c8994cf6ac08e68d9241c89839123eee Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 22 Oct 2020 22:46:18 +0200 Subject: [PATCH 019/111] components/bullethelpers cleanup; removed warnings by using override --- components/bullethelpers/processtrianglecallback.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/bullethelpers/processtrianglecallback.hpp b/components/bullethelpers/processtrianglecallback.hpp index b0d156754..22ab30b2a 100644 --- a/components/bullethelpers/processtrianglecallback.hpp +++ b/components/bullethelpers/processtrianglecallback.hpp @@ -11,11 +11,11 @@ namespace BulletHelpers class ProcessTriangleCallback : public btTriangleCallback { public: - ProcessTriangleCallback(Impl impl) + explicit ProcessTriangleCallback(Impl impl) : mImpl(std::move(impl)) {} - void processTriangle(btVector3* triangle, int partId, int triangleIndex) final + void processTriangle(btVector3* triangle, int partId, int triangleIndex) override { return mImpl(triangle, partId, triangleIndex); } From 5a824d03334240cc01dfe65a13c627bad5f7b2f7 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 22 Oct 2020 23:57:53 +0200 Subject: [PATCH 020/111] components/compiler cleanup; also cleaned up related cascading warnings; fixed up final/override issues --- apps/opencs/view/render/terrainshapemode.hpp | 32 ++++++------ apps/opencs/view/render/terrainstorage.hpp | 10 ++-- .../opencs/view/render/terraintexturemode.hpp | 32 ++++++------ apps/openmw/mwclass/creature.hpp | 6 +-- apps/openmw/mwclass/npc.hpp | 6 +-- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 4 +- apps/openmw/mwgui/backgroundimage.hpp | 4 +- apps/openmw/mwgui/bookpage.cpp | 28 +++++------ apps/openmw/mwgui/controllers.hpp | 12 ++--- apps/openmw/mwgui/cursor.hpp | 6 +-- apps/openmw/mwgui/itemchargeview.hpp | 6 +-- apps/openmw/mwgui/itemview.hpp | 8 +-- apps/openmw/mwgui/itemwidget.hpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 4 +- apps/openmw/mwgui/resourceskin.hpp | 2 +- apps/openmw/mwgui/spellview.hpp | 6 +-- apps/openmw/mwgui/widgets.hpp | 12 ++--- apps/openmw/mwmechanics/aiactivate.hpp | 8 +-- apps/openmw/mwmechanics/aiavoiddoor.hpp | 4 +- apps/openmw/mwmechanics/aibreathe.hpp | 2 +- apps/openmw/mwmechanics/aicast.hpp | 4 +- apps/openmw/mwmechanics/aicombat.hpp | 10 ++-- apps/openmw/mwmechanics/aiescort.hpp | 8 +-- apps/openmw/mwmechanics/aiface.hpp | 2 +- apps/openmw/mwmechanics/aifollow.hpp | 8 +-- apps/openmw/mwmechanics/aipursue.hpp | 6 +-- apps/openmw/mwmechanics/aitravel.hpp | 12 ++--- apps/openmw/mwmechanics/aiwander.hpp | 12 ++--- .../mwphysics/hasspherecollisioncallback.hpp | 2 +- apps/openmw/mwphysics/physicssystem.hpp | 8 +-- .../openmw_test_suite/misc/test_stringops.cpp | 4 +- .../mwdialogue/test_keywordsearch.cpp | 4 +- apps/openmw_test_suite/mwworld/test_store.cpp | 20 ++++---- components/compiler/context.hpp | 2 +- components/compiler/controlparser.cpp | 3 +- components/compiler/errorhandler.cpp | 2 +- components/compiler/errorhandler.hpp | 2 +- components/compiler/exception.hpp | 4 +- components/compiler/exprparser.cpp | 31 ++++++------ components/compiler/exprparser.hpp | 2 +- components/compiler/extensions.cpp | 20 +++----- components/compiler/generator.cpp | 6 +-- components/compiler/lineparser.cpp | 2 +- components/compiler/literals.cpp | 17 +++---- components/compiler/locals.cpp | 3 +- components/compiler/opcodes.cpp | 5 +- components/compiler/output.cpp | 1 - components/compiler/parser.cpp | 2 +- components/compiler/scanner.cpp | 3 +- components/compiler/scanner.hpp | 10 ++-- components/compiler/scriptparser.hpp | 1 - components/compiler/streamerrorhandler.cpp | 4 +- components/compiler/stringparser.cpp | 1 - components/compiler/tokenloc.hpp | 2 +- components/detournavigator/navigatorimpl.hpp | 6 +-- components/detournavigator/navigatorstub.hpp | 4 +- components/esm/containerstate.hpp | 8 +-- components/esm/creaturelevliststate.hpp | 8 +-- components/esm/creaturestate.hpp | 10 ++-- components/esm/doorstate.hpp | 8 +-- components/esm/npcstate.hpp | 10 ++-- components/esm/objectstate.hpp | 2 +- components/myguiplatform/additivelayer.hpp | 4 +- components/myguiplatform/scalinglayer.hpp | 10 ++-- components/widgets/box.hpp | 50 +++++++++---------- components/widgets/imagebutton.hpp | 14 +++--- components/widgets/list.hpp | 4 +- components/widgets/numericeditbox.hpp | 8 +-- components/widgets/sharedstatebutton.hpp | 12 ++--- components/widgets/windowcaption.hpp | 8 +-- 70 files changed, 275 insertions(+), 308 deletions(-) diff --git a/apps/opencs/view/render/terrainshapemode.hpp b/apps/opencs/view/render/terrainshapemode.hpp index d0fec764f..a88e60c9c 100644 --- a/apps/opencs/view/render/terrainshapemode.hpp +++ b/apps/opencs/view/render/terrainshapemode.hpp @@ -59,38 +59,38 @@ namespace CSVRender /// Editmode for terrain shape grid TerrainShapeMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr); - void primaryOpenPressed (const WorldspaceHitResult& hit) final; + void primaryOpenPressed (const WorldspaceHitResult& hit) override; /// Create single command for one-click shape editing - void primaryEditPressed (const WorldspaceHitResult& hit) final; + void primaryEditPressed (const WorldspaceHitResult& hit) override; /// Open brush settings window - void primarySelectPressed(const WorldspaceHitResult&) final; + void primarySelectPressed(const WorldspaceHitResult&) override; - void secondarySelectPressed(const WorldspaceHitResult&) final; + void secondarySelectPressed(const WorldspaceHitResult&) override; - void activate(CSVWidget::SceneToolbar*) final; - void deactivate(CSVWidget::SceneToolbar*) final; + void activate(CSVWidget::SceneToolbar*) override; + void deactivate(CSVWidget::SceneToolbar*) override; /// Start shape editing command macro - bool primaryEditStartDrag (const QPoint& pos) final; + bool primaryEditStartDrag (const QPoint& pos) override; - bool secondaryEditStartDrag (const QPoint& pos) final; - bool primarySelectStartDrag (const QPoint& pos) final; - bool secondarySelectStartDrag (const QPoint& pos) final; + bool secondaryEditStartDrag (const QPoint& pos) override; + bool primarySelectStartDrag (const QPoint& pos) override; + bool secondarySelectStartDrag (const QPoint& pos) override; /// Handle shape edit behavior during dragging - void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) final; + void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) override; /// End shape editing command macro - void dragCompleted(const QPoint& pos) final; + void dragCompleted(const QPoint& pos) override; /// Cancel shape editing, and reset all pending changes - void dragAborted() final; + void dragAborted() override; - void dragWheel (int diff, double speedFactor) final; - void dragMoveEvent (QDragMoveEvent *event) final; - void mouseMoveEvent (QMouseEvent *event) final; + void dragWheel (int diff, double speedFactor) override; + void dragMoveEvent (QDragMoveEvent *event) override; + void mouseMoveEvent (QMouseEvent *event) override; private: diff --git a/apps/opencs/view/render/terrainstorage.hpp b/apps/opencs/view/render/terrainstorage.hpp index 21faf9b64..762eb8003 100644 --- a/apps/opencs/view/render/terrainstorage.hpp +++ b/apps/opencs/view/render/terrainstorage.hpp @@ -27,10 +27,10 @@ namespace CSVRender const CSMWorld::Data& mData; std::array mAlteredHeight; - osg::ref_ptr getLand (int cellX, int cellY) final; - const ESM::LandTexture* getLandTexture(int index, short plugin) final; + osg::ref_ptr getLand (int cellX, int cellY) override; + const ESM::LandTexture* getLandTexture(int index, short plugin) override; - void getBounds(float& minX, float& maxX, float& minY, float& maxY) final; + void getBounds(float& minX, float& maxX, float& minY, float& maxY) override; int getThisHeight(int col, int row, const ESM::Land::LandData *heightData) const; int getLeftHeight(int col, int row, const ESM::Land::LandData *heightData) const; @@ -44,8 +44,8 @@ namespace CSVRender bool leftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const; bool rightOrDownIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const; - void adjustColor(int col, int row, const ESM::Land::LandData *heightData, osg::Vec4ub& color) const final; - float getAlteredHeight(int col, int row) const final; + void adjustColor(int col, int row, const ESM::Land::LandData *heightData, osg::Vec4ub& color) const override; + float getAlteredHeight(int col, int row) const override; }; } diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 0d8c4a94a..31932df21 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -53,37 +53,37 @@ namespace CSVRender /// \brief Editmode for terrain texture grid TerrainTextureMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr); - void primaryOpenPressed (const WorldspaceHitResult& hit) final; + void primaryOpenPressed (const WorldspaceHitResult& hit) override; /// \brief Create single command for one-click texture editing - void primaryEditPressed (const WorldspaceHitResult& hit) final; + void primaryEditPressed (const WorldspaceHitResult& hit) override; /// \brief Open brush settings window - void primarySelectPressed(const WorldspaceHitResult&) final; + void primarySelectPressed(const WorldspaceHitResult&) override; - void secondarySelectPressed(const WorldspaceHitResult&) final; + void secondarySelectPressed(const WorldspaceHitResult&) override; - void activate(CSVWidget::SceneToolbar*) final; - void deactivate(CSVWidget::SceneToolbar*) final; + void activate(CSVWidget::SceneToolbar*) override; + void deactivate(CSVWidget::SceneToolbar*) override; /// \brief Start texture editing command macro - bool primaryEditStartDrag (const QPoint& pos) final; + bool primaryEditStartDrag (const QPoint& pos) override; - bool secondaryEditStartDrag (const QPoint& pos) final; - bool primarySelectStartDrag (const QPoint& pos) final; - bool secondarySelectStartDrag (const QPoint& pos) final; + bool secondaryEditStartDrag (const QPoint& pos) override; + bool primarySelectStartDrag (const QPoint& pos) override; + bool secondarySelectStartDrag (const QPoint& pos) override; /// \brief Handle texture edit behavior during dragging - void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) final; + void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) override; /// \brief End texture editing command macro - void dragCompleted(const QPoint& pos) final; + void dragCompleted(const QPoint& pos) override; - void dragAborted() final; - void dragWheel (int diff, double speedFactor) final; - void dragMoveEvent (QDragMoveEvent *event) final; + void dragAborted() override; + void dragWheel (int diff, double speedFactor) override; + void dragMoveEvent (QDragMoveEvent *event) override; - void mouseMoveEvent (QMouseEvent *event) final; + void mouseMoveEvent (QMouseEvent *event) override; private: /// \brief Handle brush mechanics, maths regarding worldspace hit etc. diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 0df782eaf..5bb503034 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -132,11 +132,11 @@ namespace MWClass void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const override; - float getWalkSpeed(const MWWorld::Ptr& ptr) const final; + float getWalkSpeed(const MWWorld::Ptr& ptr) const override; - float getRunSpeed(const MWWorld::Ptr& ptr) const final; + float getRunSpeed(const MWWorld::Ptr& ptr) const override; - float getSwimSpeed(const MWWorld::Ptr& ptr) const final; + float getSwimSpeed(const MWWorld::Ptr& ptr) const override; }; } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index dc5fee73a..612763d12 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -166,11 +166,11 @@ namespace MWClass void modifyBaseInventory(const std::string& actorId, const std::string& itemId, int amount) const override; - float getWalkSpeed(const MWWorld::Ptr& ptr) const final; + float getWalkSpeed(const MWWorld::Ptr& ptr) const override; - float getRunSpeed(const MWWorld::Ptr& ptr) const final; + float getRunSpeed(const MWWorld::Ptr& ptr) const override; - float getSwimSpeed(const MWWorld::Ptr& ptr) const final; + float getSwimSpeed(const MWWorld::Ptr& ptr) const override; }; } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 6c6eb9a9d..b35bee6d4 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -73,9 +73,9 @@ namespace MWDialogue bool startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback) override; std::list getAvailableTopics() override; - int getTopicFlag(const std::string& topicId) final; + int getTopicFlag(const std::string& topicId) override; - bool inJournal (const std::string& topicId, const std::string& infoId) final; + bool inJournal (const std::string& topicId, const std::string& infoId) override; void addTopic (const std::string& topic) override; diff --git a/apps/openmw/mwgui/backgroundimage.hpp b/apps/openmw/mwgui/backgroundimage.hpp index 3ea8b3bba..32cdf1a65 100644 --- a/apps/openmw/mwgui/backgroundimage.hpp +++ b/apps/openmw/mwgui/backgroundimage.hpp @@ -22,8 +22,8 @@ namespace MWGui */ void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool stretch=true); - void setSize (const MyGUI::IntSize &_value) final; - void setCoord (const MyGUI::IntCoord &_value) final; + void setSize (const MyGUI::IntSize &_value) override; + void setCoord (const MyGUI::IntCoord &_value) override; private: MyGUI::ImageBox* mChild; diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index a346526eb..16541dbf0 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -1152,7 +1152,7 @@ public: i->second->createDrawItem (mNode); } - void setVisible (bool newVisible) final + void setVisible (bool newVisible) override { if (mVisible == newVisible) return; @@ -1174,7 +1174,7 @@ public: } } - void createDrawItem(MyGUI::ITexture* texture, MyGUI::ILayerNode* node) final + void createDrawItem(MyGUI::ITexture* texture, MyGUI::ILayerNode* node) override { mNode = node; @@ -1242,9 +1242,9 @@ public: // ISubWidget should not necessarily be a drawitem // in this case, it is not... - void doRender() final { } + void doRender() override { } - void _updateView () final + void _updateView () override { _checkMargin(); @@ -1253,7 +1253,7 @@ public: mNode->outOfDate (i->second->mRenderItem); } - void _correctView() final + void _correctView() override { _checkMargin (); @@ -1263,7 +1263,7 @@ public: } - void destroyDrawItem() final + void destroyDrawItem() override { for (ActiveTextFormats::iterator i = mActiveTextFormats.begin (); i != mActiveTextFormats.end (); ++i) i->second->destroyDrawItem (mNode); @@ -1283,24 +1283,24 @@ public: { } - void showPage (TypesetBook::Ptr book, size_t page) final + void showPage (TypesetBook::Ptr book, size_t page) override { mPageDisplay->showPage (book, page); } - void adviseLinkClicked (std::function linkClicked) final + void adviseLinkClicked (std::function linkClicked) override { mPageDisplay->mLinkClicked = linkClicked; } - void unadviseLinkClicked () final + void unadviseLinkClicked () override { mPageDisplay->mLinkClicked = std::function (); } protected: - void initialiseOverride() final + void initialiseOverride() override { Base::initialiseOverride(); @@ -1314,24 +1314,24 @@ protected: } } - void onMouseLostFocus(Widget* _new) final + void onMouseLostFocus(Widget* _new) override { // NOTE: MyGUI also fires eventMouseLostFocus for widgets that are about to be destroyed (if they had focus). // Child widgets may already be destroyed! So be careful. mPageDisplay->onMouseLostFocus (); } - void onMouseMove(int left, int top) final + void onMouseMove(int left, int top) override { mPageDisplay->onMouseMove (left, top); } - void onMouseButtonPressed (int left, int top, MyGUI::MouseButton id) final + void onMouseButtonPressed (int left, int top, MyGUI::MouseButton id) override { mPageDisplay->onMouseButtonPressed (left, top, id); } - void onMouseButtonReleased(int left, int top, MyGUI::MouseButton id) final + void onMouseButtonReleased(int left, int top, MyGUI::MouseButton id) override { mPageDisplay->onMouseButtonReleased (left, top, id); } diff --git a/apps/openmw/mwgui/controllers.hpp b/apps/openmw/mwgui/controllers.hpp index bd9646ec2..416f104d9 100644 --- a/apps/openmw/mwgui/controllers.hpp +++ b/apps/openmw/mwgui/controllers.hpp @@ -9,21 +9,17 @@ namespace MyGUI class Widget; } -namespace MWGui -{ - namespace Controllers +namespace MWGui::Controllers { /// Automatically positions a widget below the mouse cursor. - class ControllerFollowMouse final : - public MyGUI::ControllerItem + class ControllerFollowMouse final : public MyGUI::ControllerItem { MYGUI_RTTI_DERIVED( ControllerFollowMouse ) private: - bool addTime(MyGUI::Widget* _widget, float _time) final; - void prepareItem(MyGUI::Widget* _widget) final; + bool addTime(MyGUI::Widget* _widget, float _time) override; + void prepareItem(MyGUI::Widget* _widget) override; }; } -} #endif diff --git a/apps/openmw/mwgui/cursor.hpp b/apps/openmw/mwgui/cursor.hpp index ef5099ef8..7e1f9adba 100644 --- a/apps/openmw/mwgui/cursor.hpp +++ b/apps/openmw/mwgui/cursor.hpp @@ -20,10 +20,10 @@ namespace MWGui ResourceImageSetPointerFix(); virtual ~ResourceImageSetPointerFix(); - void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) final; + void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) override; - void setImage(MyGUI::ImageBox* _image) final; - void setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point) final; + void setImage(MyGUI::ImageBox* _image) override; + void setPosition(MyGUI::ImageBox* _image, const MyGUI::IntPoint& _point) override; //and now for the whole point of this class, allow us to get //the hot spot, the image and the size of the cursor. diff --git a/apps/openmw/mwgui/itemchargeview.hpp b/apps/openmw/mwgui/itemchargeview.hpp index 2522f55d1..039dcaf4e 100644 --- a/apps/openmw/mwgui/itemchargeview.hpp +++ b/apps/openmw/mwgui/itemchargeview.hpp @@ -36,7 +36,7 @@ namespace MWGui /// Register needed components with MyGUI's factory manager static void registerComponents(); - void initialiseOverride() final; + void initialiseOverride() override; /// Takes ownership of \a model void setModel(ItemModel* model); @@ -47,8 +47,8 @@ namespace MWGui void layoutWidgets(); void resetScrollbars(); - void setSize(const MyGUI::IntSize& value) final; - void setCoord(const MyGUI::IntCoord& value) final; + void setSize(const MyGUI::IntSize& value) override; + void setCoord(const MyGUI::IntCoord& value) override; MyGUI::delegates::CMultiDelegate2 eventItemClicked; diff --git a/apps/openmw/mwgui/itemview.hpp b/apps/openmw/mwgui/itemview.hpp index a5e537aa0..4074e55e4 100644 --- a/apps/openmw/mwgui/itemview.hpp +++ b/apps/openmw/mwgui/itemview.hpp @@ -13,7 +13,7 @@ namespace MWGui MYGUI_RTTI_DERIVED(ItemView) public: ItemView(); - virtual ~ItemView(); + ~ItemView() override; /// Register needed components with MyGUI's factory manager static void registerComponents (); @@ -33,12 +33,12 @@ namespace MWGui void resetScrollBars(); private: - void initialiseOverride() final; + void initialiseOverride() override; void layoutWidgets(); - void setSize(const MyGUI::IntSize& _value) final; - void setCoord(const MyGUI::IntCoord& _value) final; + void setSize(const MyGUI::IntSize& _value) override; + void setCoord(const MyGUI::IntCoord& _value) override; void onSelectedItem (MyGUI::Widget* sender); void onSelectedBackground (MyGUI::Widget* sender); diff --git a/apps/openmw/mwgui/itemwidget.hpp b/apps/openmw/mwgui/itemwidget.hpp index 748a44445..550d73643 100644 --- a/apps/openmw/mwgui/itemwidget.hpp +++ b/apps/openmw/mwgui/itemwidget.hpp @@ -41,7 +41,7 @@ namespace MWGui void setFrame (const std::string& frame, const MyGUI::IntCoord& coord); protected: - void initialiseOverride() final; + void initialiseOverride() override; MyGUI::ImageBox* mItem; MyGUI::ImageBox* mItemShadow; diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index f0ece76d5..acf131926 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -74,12 +74,12 @@ namespace MyGUI::Colour mNormalColour; MyGUI::Colour mHoverColour; - void onMouseLostFocus(MyGUI::Widget* _new) final + void onMouseLostFocus(MyGUI::Widget* _new) override { setColour(mNormalColour); } - void onMouseSetFocus(MyGUI::Widget* _old) final + void onMouseSetFocus(MyGUI::Widget* _old) override { setColour(mHoverColour); } diff --git a/apps/openmw/mwgui/resourceskin.hpp b/apps/openmw/mwgui/resourceskin.hpp index bdf0d2f0b..fd1977e66 100644 --- a/apps/openmw/mwgui/resourceskin.hpp +++ b/apps/openmw/mwgui/resourceskin.hpp @@ -10,7 +10,7 @@ namespace MWGui MYGUI_RTTI_DERIVED( AutoSizedResourceSkin ) public: - void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) final; + void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) override; }; } diff --git a/apps/openmw/mwgui/spellview.hpp b/apps/openmw/mwgui/spellview.hpp index a387cac39..6b3effc45 100644 --- a/apps/openmw/mwgui/spellview.hpp +++ b/apps/openmw/mwgui/spellview.hpp @@ -47,10 +47,10 @@ namespace MWGui /// Fired when a spell was clicked EventHandle_ModelIndex eventSpellClicked; - void initialiseOverride() final; + void initialiseOverride() override; - void setSize(const MyGUI::IntSize& _value) final; - void setCoord(const MyGUI::IntCoord& _value) final; + void setSize(const MyGUI::IntSize& _value) override; + void setCoord(const MyGUI::IntCoord& _value) override; void resetScrollbars(); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index ff3b2311a..731a41a35 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -116,7 +116,7 @@ namespace MWGui protected: virtual ~MWSkill(); - void initialiseOverride() final; + void initialiseOverride() override; void onClicked(MyGUI::Widget* _sender); @@ -156,7 +156,7 @@ namespace MWGui protected: virtual ~MWAttribute(); - void initialiseOverride() final; + void initialiseOverride() override; void onClicked(MyGUI::Widget* _sender); @@ -199,7 +199,7 @@ namespace MWGui protected: virtual ~MWSpell(); - void initialiseOverride() final; + void initialiseOverride() override; private: void updateWidgets(); @@ -241,7 +241,7 @@ namespace MWGui protected: virtual ~MWEffectList(); - void initialiseOverride() final; + void initialiseOverride() override; private: void updateWidgets(); @@ -265,7 +265,7 @@ namespace MWGui protected: virtual ~MWSpellEffect(); - void initialiseOverride() final; + void initialiseOverride() override; private: static const int sIconOffset = 24; @@ -294,7 +294,7 @@ namespace MWGui protected: virtual ~MWDynamicStat(); - void initialiseOverride() final; + void initialiseOverride() override; private: diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index c53744e88..dc7e0bb26 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -24,15 +24,15 @@ namespace MWMechanics public: /// Constructor /** \param objectId Reference to object to activate **/ - AiActivate(const std::string &objectId); + explicit AiActivate(const std::string &objectId); - AiActivate(const ESM::AiSequence::AiActivate* activate); + explicit AiActivate(const ESM::AiSequence::AiActivate* activate); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Activate; } - void writeState(ESM::AiSequence::AiSequence& sequence) const final; + void writeState(ESM::AiSequence::AiSequence& sequence) const override; private: const std::string mObjectId; diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index cd0718e2e..1781c5e4a 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -20,9 +20,9 @@ namespace MWMechanics { public: /// Avoid door until the door is fully open - AiAvoidDoor(const MWWorld::ConstPtr& doorPtr); + explicit AiAvoidDoor(const MWWorld::ConstPtr& doorPtr); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::AvoidDoor; } diff --git a/apps/openmw/mwmechanics/aibreathe.hpp b/apps/openmw/mwmechanics/aibreathe.hpp index 7e9ac69da..b84c0eb76 100644 --- a/apps/openmw/mwmechanics/aibreathe.hpp +++ b/apps/openmw/mwmechanics/aibreathe.hpp @@ -10,7 +10,7 @@ namespace MWMechanics class AiBreathe final : public TypedAiPackage { public: - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Breathe; } diff --git a/apps/openmw/mwmechanics/aicast.hpp b/apps/openmw/mwmechanics/aicast.hpp index 1175dccd2..9758c2b94 100644 --- a/apps/openmw/mwmechanics/aicast.hpp +++ b/apps/openmw/mwmechanics/aicast.hpp @@ -15,11 +15,11 @@ namespace MWMechanics public: AiCast(const std::string& targetId, const std::string& spellId, bool manualSpell=false); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Cast; } - MWWorld::Ptr getTarget() const final; + MWWorld::Ptr getTarget() const override; static constexpr Options makeDefaultOptions() { diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index ff8a0e081..64645ca94 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -96,13 +96,13 @@ namespace MWMechanics public: ///Constructor /** \param actor Actor to fight **/ - AiCombat(const MWWorld::Ptr& actor); + explicit AiCombat(const MWWorld::Ptr& actor); - AiCombat (const ESM::AiSequence::AiCombat* combat); + explicit AiCombat (const ESM::AiSequence::AiCombat* combat); void init(); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Combat; } @@ -116,9 +116,9 @@ namespace MWMechanics } ///Returns target ID - MWWorld::Ptr getTarget() const final; + MWWorld::Ptr getTarget() const override; - void writeState(ESM::AiSequence::AiSequence &sequence) const final; + void writeState(ESM::AiSequence::AiSequence &sequence) const override; private: /// Returns true if combat should end diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index edfd0ca3f..27a177893 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -30,7 +30,7 @@ namespace MWMechanics AiEscort(const ESM::AiSequence::AiEscort* escort); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Escort; } @@ -42,11 +42,11 @@ namespace MWMechanics return options; } - void writeState(ESM::AiSequence::AiSequence &sequence) const final; + void writeState(ESM::AiSequence::AiSequence &sequence) const override; - void fastForward(const MWWorld::Ptr& actor, AiState& state) final; + void fastForward(const MWWorld::Ptr& actor, AiState& state) override; - osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); } + osg::Vec3f getDestination() const override { return osg::Vec3f(mX, mY, mZ); } private: const std::string mCellId; diff --git a/apps/openmw/mwmechanics/aiface.hpp b/apps/openmw/mwmechanics/aiface.hpp index a5ee67a14..e176eb52e 100644 --- a/apps/openmw/mwmechanics/aiface.hpp +++ b/apps/openmw/mwmechanics/aiface.hpp @@ -10,7 +10,7 @@ namespace MWMechanics public: AiFace(float targetX, float targetY); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Face; } diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index d0c2cec97..e6aeebb24 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -53,7 +53,7 @@ namespace MWMechanics AiFollow(const ESM::AiSequence::AiFollow* follow); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Follow; } @@ -69,15 +69,15 @@ namespace MWMechanics /// Returns the actor being followed std::string getFollowedActor(); - void writeState (ESM::AiSequence::AiSequence& sequence) const final; + void writeState (ESM::AiSequence::AiSequence& sequence) const override; bool isCommanded() const; int getFollowIndex() const; - void fastForward(const MWWorld::Ptr& actor, AiState& state) final; + void fastForward(const MWWorld::Ptr& actor, AiState& state) override; - osg::Vec3f getDestination() const final + osg::Vec3f getDestination() const override { MWWorld::Ptr target = getTarget(); if (target.isEmpty()) diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 64465f530..2fbc13b87 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -26,7 +26,7 @@ namespace MWMechanics AiPursue(const ESM::AiSequence::AiPursue* pursue); - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Pursue; } @@ -38,9 +38,9 @@ namespace MWMechanics return options; } - MWWorld::Ptr getTarget() const final; + MWWorld::Ptr getTarget() const override; - void writeState (ESM::AiSequence::AiSequence& sequence) const final; + void writeState (ESM::AiSequence::AiSequence& sequence) const override; }; } #endif diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp index 0c19572d2..2ea2a8f71 100644 --- a/apps/openmw/mwmechanics/aitravel.hpp +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -25,14 +25,14 @@ namespace MWMechanics AiTravel(float x, float y, float z); - AiTravel(const ESM::AiSequence::AiTravel* travel); + explicit AiTravel(const ESM::AiSequence::AiTravel* travel); /// Simulates the passing of time - void fastForward(const MWWorld::Ptr& actor, AiState& state) final; + void fastForward(const MWWorld::Ptr& actor, AiState& state) override; - void writeState(ESM::AiSequence::AiSequence &sequence) const final; + void writeState(ESM::AiSequence::AiSequence &sequence) const override; - bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Travel; } @@ -44,7 +44,7 @@ namespace MWMechanics return options; } - osg::Vec3f getDestination() const final { return osg::Vec3f(mX, mY, mZ); } + osg::Vec3f getDestination() const override { return osg::Vec3f(mX, mY, mZ); } private: const float mX; @@ -62,7 +62,7 @@ namespace MWMechanics static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::InternalTravel; } - std::unique_ptr clone() const final; + std::unique_ptr clone() const override; }; } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 4165cebbd..68bcddf22 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -89,9 +89,9 @@ namespace MWMechanics \param repeat Repeat wander or not **/ AiWander(int distance, int duration, int timeOfDay, const std::vector& idle, bool repeat); - AiWander (const ESM::AiSequence::AiWander* wander); + explicit AiWander (const ESM::AiSequence::AiWander* wander); - bool execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) final; + bool execute(const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration) override; static constexpr AiPackageTypeId getTypeId() { return AiPackageTypeId::Wander; } @@ -103,13 +103,13 @@ namespace MWMechanics return options; } - void writeState(ESM::AiSequence::AiSequence &sequence) const final; + void writeState(ESM::AiSequence::AiSequence &sequence) const override; - void fastForward(const MWWorld::Ptr& actor, AiState& state) final; + void fastForward(const MWWorld::Ptr& actor, AiState& state) override; - osg::Vec3f getDestination(const MWWorld::Ptr& actor) const final; + osg::Vec3f getDestination(const MWWorld::Ptr& actor) const override; - osg::Vec3f getDestination() const final + osg::Vec3f getDestination() const override { if (!mHasDestination) return osg::Vec3f(0, 0, 0); diff --git a/apps/openmw/mwphysics/hasspherecollisioncallback.hpp b/apps/openmw/mwphysics/hasspherecollisioncallback.hpp index 58e7373e5..275325cf6 100644 --- a/apps/openmw/mwphysics/hasspherecollisioncallback.hpp +++ b/apps/openmw/mwphysics/hasspherecollisioncallback.hpp @@ -35,7 +35,7 @@ namespace MWPhysics { } - bool process(const btBroadphaseProxy* proxy) final + bool process(const btBroadphaseProxy* proxy) override { if (mResult) return false; diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 3198c5d44..96aba99c4 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -156,17 +156,17 @@ namespace MWPhysics /// target vector hits the collision shape and then calculates distance from the intersection point. /// This can be used to find out how much nearer we need to move to the target for a "getHitContact" to be successful. /// \note Only Actor targets are supported at the moment. - float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const final; + float getHitDistance(const osg::Vec3f& point, const MWWorld::ConstPtr& target) const override; /// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors. RayCastingResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(), std::vector targets = std::vector(), - int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const final; + int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const override; - RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const final; + RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const override; /// Return true if actor1 can see actor2. - bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const final; + bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const override; bool isOnGround (const MWWorld::Ptr& actor); diff --git a/apps/openmw_test_suite/misc/test_stringops.cpp b/apps/openmw_test_suite/misc/test_stringops.cpp index 081ca8da6..086908692 100644 --- a/apps/openmw_test_suite/misc/test_stringops.cpp +++ b/apps/openmw_test_suite/misc/test_stringops.cpp @@ -5,14 +5,14 @@ struct PartialBinarySearchTest : public ::testing::Test { protected: std::vector mDataVec; - virtual void SetUp() + void SetUp() override { const char* data[] = { "Head", "Chest", "Tri Head", "Tri Chest", "Bip01", "Tri Bip01" }; mDataVec = std::vector(data, data+sizeof(data)/sizeof(data[0])); std::sort(mDataVec.begin(), mDataVec.end(), Misc::StringUtils::ciLess); } - virtual void TearDown() + void TearDown() override { } diff --git a/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp b/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp index e0e1871d2..431725be2 100644 --- a/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp +++ b/apps/openmw_test_suite/mwdialogue/test_keywordsearch.cpp @@ -4,11 +4,11 @@ struct KeywordSearchTest : public ::testing::Test { protected: - virtual void SetUp() + void SetUp() override { } - virtual void TearDown() + void TearDown() override { } }; diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index 60f60adb3..77aaccfdd 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -22,7 +22,7 @@ struct ContentFileTest : public ::testing::Test { protected: - virtual void SetUp() + void SetUp() override { readContentFiles(); @@ -31,13 +31,13 @@ struct ContentFileTest : public ::testing::Test readerList.resize(mContentFiles.size()); int index=0; - for (std::vector::const_iterator it = mContentFiles.begin(); it != mContentFiles.end(); ++it) + for (const auto & mContentFile : mContentFiles) { ESM::ESMReader lEsm; lEsm.setEncoder(nullptr); lEsm.setIndex(index); lEsm.setGlobalReaderList(&readerList); - lEsm.open(it->string()); + lEsm.open(mContentFile.string()); readerList[index] = lEsm; mEsmStore.load(readerList[index], &dummyListener); @@ -47,7 +47,7 @@ struct ContentFileTest : public ::testing::Test mEsmStore.setUp(); } - virtual void TearDown() + void TearDown() override { } @@ -86,8 +86,8 @@ struct ContentFileTest : public ::testing::Test Files::Collections collections (dataDirs, true); std::vector contentFiles = variables["content"].as >(); - for (std::vector::iterator it = contentFiles.begin(); it != contentFiles.end(); ++it) - mContentFiles.push_back(collections.getPath(*it)); + for (auto & contentFile : contentFiles) + mContentFiles.push_back(collections.getPath(contentFile)); } protected: @@ -111,14 +111,12 @@ TEST_F(ContentFileTest, dialogue_merging_test) stream.open(file); const MWWorld::Store& dialStore = mEsmStore.get(); - for (MWWorld::Store::iterator it = dialStore.begin(); it != dialStore.end(); ++it) + for (const auto & dial : dialStore) { - const ESM::Dialogue& dial = *it; stream << "Dialogue: " << dial.mId << std::endl; - for (ESM::Dialogue::InfoContainer::const_iterator infoIt = dial.mInfo.begin(); infoIt != dial.mInfo.end(); ++infoIt) + for (const auto & info : dial.mInfo) { - const ESM::DialInfo& info = *infoIt; stream << info.mId << std::endl; } stream << std::endl; @@ -229,7 +227,7 @@ template Files::IStreamPtr getEsmFile(T record, bool deleted) { ESM::ESMWriter writer; - std::stringstream* stream = new std::stringstream; + auto* stream = new std::stringstream; writer.setFormat(0); writer.save(*stream); writer.startRecord(T::sRecordId); diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index 84bb89bdc..2d6af0e45 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -15,7 +15,7 @@ namespace Compiler Context() : mExtensions (0) {} - virtual ~Context() {} + virtual ~Context() = default; virtual bool canDeclareLocals() const = 0; ///< Is the compiler allowed to declare local variables? diff --git a/components/compiler/controlparser.cpp b/components/compiler/controlparser.cpp index ebadcbbc6..634180f62 100644 --- a/components/compiler/controlparser.cpp +++ b/components/compiler/controlparser.cpp @@ -1,7 +1,6 @@ #include "controlparser.hpp" #include -#include #include #include "scanner.hpp" @@ -33,7 +32,7 @@ namespace Compiler // store code for if-cascade Codes codes; - for (IfCodes::reverse_iterator iter (mIfCode.rbegin()); + for (auto iter (mIfCode.rbegin()); iter!=mIfCode.rend(); ++iter) { Codes block; diff --git a/components/compiler/errorhandler.cpp b/components/compiler/errorhandler.cpp index 7f02255db..f02097736 100644 --- a/components/compiler/errorhandler.cpp +++ b/components/compiler/errorhandler.cpp @@ -5,7 +5,7 @@ namespace Compiler ErrorHandler::ErrorHandler() : mWarnings (0), mErrors (0), mWarningsMode (1), mDowngradeErrors (false) {} - ErrorHandler::~ErrorHandler() {} + ErrorHandler::~ErrorHandler() = default; // Was compiling successful? diff --git a/components/compiler/errorhandler.hpp b/components/compiler/errorhandler.hpp index ea904e385..dfd29f273 100644 --- a/components/compiler/errorhandler.hpp +++ b/components/compiler/errorhandler.hpp @@ -83,7 +83,7 @@ namespace Compiler public: - ErrorDowngrade (ErrorHandler& handler); + explicit ErrorDowngrade (ErrorHandler& handler); ~ErrorDowngrade(); }; diff --git a/components/compiler/exception.hpp b/components/compiler/exception.hpp index f21f2e586..3aa8997c7 100644 --- a/components/compiler/exception.hpp +++ b/components/compiler/exception.hpp @@ -21,7 +21,7 @@ namespace Compiler { public: - const char *what() const noexcept final { return "Can't read file"; } + const char *what() const noexcept override { return "Can't read file"; } ///< Return error message }; @@ -31,7 +31,7 @@ namespace Compiler { public: - const char *what() const noexcept final { return "End of file"; } + const char *what() const noexcept override { return "End of file"; } ///< Return error message }; } diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 8c8fe640e..7c0635d76 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include @@ -21,7 +19,7 @@ namespace Compiler { - int ExprParser::getPriority (char op) const + int ExprParser::getPriority (char op) { switch (op) { @@ -654,28 +652,27 @@ namespace Compiler std::stack > stack; - for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end(); - ++iter) + for (char argument : arguments) { - if (*iter=='/') + if (argument=='/') { optional = true; } - else if (*iter=='S' || *iter=='c' || *iter=='x') + else if (argument=='S' || argument=='c' || argument=='x') { stringParser.reset(); - if (optional || *iter=='x') + if (optional || argument=='x') stringParser.setOptional (true); - if (*iter=='c') stringParser.smashCase(); - if (*iter=='x') stringParser.discard(); + if (argument=='c') stringParser.smashCase(); + if (argument=='x') stringParser.discard(); scanner.scan (stringParser); - if ((optional || *iter=='x') && stringParser.isEmpty()) + if ((optional || argument=='x') && stringParser.isEmpty()) break; - if (*iter!='x') + if (argument!='x') { std::vector tmp; stringParser.append (tmp); @@ -689,7 +686,7 @@ namespace Compiler getErrorHandler().warning ("Extra argument", stringParser.getTokenLoc()); } - else if (*iter=='X') + else if (argument=='X') { parser.reset(); @@ -702,7 +699,7 @@ namespace Compiler else getErrorHandler().warning("Extra argument", parser.getTokenLoc()); } - else if (*iter=='z') + else if (argument=='z') { discardParser.reset(); discardParser.setOptional (true); @@ -714,7 +711,7 @@ namespace Compiler else getErrorHandler().warning("Extra argument", discardParser.getTokenLoc()); } - else if (*iter=='j') + else if (argument=='j') { /// \todo disable this when operating in strict mode junkParser.reset(); @@ -737,8 +734,8 @@ namespace Compiler char type = parser.append (tmp); - if (type!=*iter) - Generator::convert (tmp, type, *iter); + if (type!=argument) + Generator::convert (tmp, type, argument); stack.push (tmp); diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 0e8ad88c6..2f3eaa8a9 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -28,7 +28,7 @@ namespace Compiler bool mRefOp; bool mMemberOp; - int getPriority (char op) const; + static int getPriority (char op) ; char getOperandType (int Index = 0) const; diff --git a/components/compiler/extensions.cpp b/components/compiler/extensions.cpp index dbb953e20..9646d54a7 100644 --- a/components/compiler/extensions.cpp +++ b/components/compiler/extensions.cpp @@ -12,8 +12,7 @@ namespace Compiler int Extensions::searchKeyword (const std::string& keyword) const { - std::map::const_iterator iter = mKeywords.find (keyword); - + auto iter = mKeywords.find (keyword); if (iter==mKeywords.end()) return 0; @@ -23,8 +22,7 @@ namespace Compiler bool Extensions::isFunction (int keyword, ScriptReturn& returnType, ScriptArgs& argumentType, bool& explicitReference) const { - std::map::const_iterator iter = mFunctions.find (keyword); - + auto iter = mFunctions.find (keyword); if (iter==mFunctions.end()) return false; @@ -39,8 +37,7 @@ namespace Compiler bool Extensions::isInstruction (int keyword, ScriptArgs& argumentType, bool& explicitReference) const { - std::map::const_iterator iter = mInstructions.find (keyword); - + auto iter = mInstructions.find (keyword); if (iter==mInstructions.end()) return false; @@ -115,8 +112,7 @@ namespace Compiler { assert (optionalArguments>=0); - std::map::const_iterator iter = mFunctions.find (keyword); - + auto iter = mFunctions.find (keyword); if (iter==mFunctions.end()) throw std::logic_error ("unknown custom function keyword"); @@ -164,8 +160,7 @@ namespace Compiler { assert (optionalArguments>=0); - std::map::const_iterator iter = mInstructions.find (keyword); - + auto iter = mInstructions.find (keyword); if (iter==mInstructions.end()) throw std::logic_error ("unknown custom instruction keyword"); @@ -209,8 +204,7 @@ namespace Compiler void Extensions::listKeywords (std::vector& keywords) const { - for (std::map::const_iterator iter (mKeywords.begin()); - iter!=mKeywords.end(); ++iter) - keywords.push_back (iter->first); + for (const auto & mKeyword : mKeywords) + keywords.push_back (mKeyword.first); } } diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 2787488c2..717f05980 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include "literals.hpp" @@ -283,9 +282,7 @@ namespace } } -namespace Compiler -{ - namespace Generator +namespace Compiler::Generator { void pushInt (CodeContainer& code, Literals& literals, int value) { @@ -732,4 +729,3 @@ namespace Compiler } } } -} diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 829ad6f08..77afaee8b 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -260,7 +260,7 @@ namespace Compiler /// \todo add option to disable this std::unique_ptr errorDowngrade (nullptr); if (Misc::StringUtils::lowerCase (loc.mLiteral)=="positioncell") - errorDowngrade.reset (new ErrorDowngrade (getErrorHandler())); + errorDowngrade = std::make_unique (getErrorHandler()); std::vector code; int optionals = mExprParser.parseArguments (argumentType, scanner, code, keyword); diff --git a/components/compiler/literals.cpp b/components/compiler/literals.cpp index ee2c4d345..774ca4ca7 100644 --- a/components/compiler/literals.cpp +++ b/components/compiler/literals.cpp @@ -30,13 +30,11 @@ namespace Compiler void Literals::append (std::vector& code) const { - for (std::vector::const_iterator iter (mIntegers.begin()); - iter!=mIntegers.end(); ++iter) - code.push_back (*reinterpret_cast (&*iter)); + for (const int & mInteger : mIntegers) + code.push_back (*reinterpret_cast (&mInteger)); - for (std::vector::const_iterator iter (mFloats.begin()); - iter!=mFloats.end(); ++iter) - code.push_back (*reinterpret_cast (&*iter)); + for (const float & mFloat : mFloats) + code.push_back (*reinterpret_cast (&mFloat)); int stringBlockSize = getStringSize(); int size = static_cast (code.size()); @@ -45,12 +43,11 @@ namespace Compiler int offset = 0; - for (std::vector::const_iterator iter (mStrings.begin()); - iter!=mStrings.end(); ++iter) + for (const auto & mString : mStrings) { - int stringSize = iter->size()+1; + int stringSize = mString.size()+1; - std::copy (iter->c_str(), iter->c_str()+stringSize, + std::copy (mString.c_str(), mString.c_str()+stringSize, reinterpret_cast (&code[size]) + offset); offset += stringSize; } diff --git a/components/compiler/locals.cpp b/components/compiler/locals.cpp index a7102c38d..9b233b8f5 100644 --- a/components/compiler/locals.cpp +++ b/components/compiler/locals.cpp @@ -25,8 +25,7 @@ namespace Compiler { const std::vector& collection = get (type); - std::vector::const_iterator iter = - std::find (collection.begin(), collection.end(), name); + auto iter = std::find (collection.begin(), collection.end(), name); if (iter==collection.end()) return -1; diff --git a/components/compiler/opcodes.cpp b/components/compiler/opcodes.cpp index 03081dff9..9e2356d0e 100644 --- a/components/compiler/opcodes.cpp +++ b/components/compiler/opcodes.cpp @@ -1,8 +1,6 @@ #include "opcodes.hpp" -namespace Compiler -{ - namespace Control +namespace Compiler::Control { const char *controls[numberOfControls] = { @@ -10,4 +8,3 @@ namespace Compiler "playerviewswitch", "vanitymode" }; } -} diff --git a/components/compiler/output.cpp b/components/compiler/output.cpp index 785b2ce84..a78c44b8d 100644 --- a/components/compiler/output.cpp +++ b/components/compiler/output.cpp @@ -2,7 +2,6 @@ #include #include -#include #include "locals.hpp" diff --git a/components/compiler/parser.cpp b/components/compiler/parser.cpp index 62265d8a1..ffa393a29 100644 --- a/components/compiler/parser.cpp +++ b/components/compiler/parser.cpp @@ -58,7 +58,7 @@ namespace Compiler // destructor - Parser::~Parser() {} + Parser::~Parser() = default; // Handle an int token. // \return fetch another token? diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 9f2865868..14745ac98 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -1,7 +1,6 @@ #include "scanner.hpp" #include -#include #include "exception.hpp" #include "errorhandler.hpp" @@ -266,7 +265,7 @@ namespace Compiler "messagebox", "set", "to", "getsquareroot", - 0 + nullptr }; bool Scanner::scanName (MultiChar& c, Parser& parser, bool& cont) diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index b6321a92d..2139f04b2 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -28,7 +28,7 @@ namespace Compiler blank(); } - MultiChar(const char ch) + explicit MultiChar(const char ch) { blank(); mData[0] = ch; @@ -36,7 +36,7 @@ namespace Compiler mLength = getCharLength(ch); } - int getCharLength(const char ch) + static int getCharLength(const char ch) { unsigned char c = ch; if (c<=127) return 0; @@ -170,8 +170,8 @@ namespace Compiler } private: - char mData[4]; - int mLength; + char mData[4]{}; + int mLength{}; }; class Scanner @@ -251,7 +251,7 @@ namespace Compiler public: Scanner (ErrorHandler& errorHandler, std::istream& inputStream, - const Extensions *extensions = 0); + const Extensions *extensions = nullptr); ///< constructor void scan (Parser& parser); diff --git a/components/compiler/scriptparser.hpp b/components/compiler/scriptparser.hpp index d6dfe768c..0433a23a3 100644 --- a/components/compiler/scriptparser.hpp +++ b/components/compiler/scriptparser.hpp @@ -1,7 +1,6 @@ #ifndef COMPILER_SCRIPTPARSER_H_INCLUDED #define COMPILER_SCRIPTPARSER_H_INCLUDED - #include "parser.hpp" #include "lineparser.hpp" #include "controlparser.hpp" diff --git a/components/compiler/streamerrorhandler.cpp b/components/compiler/streamerrorhandler.cpp index 1c41d3f7f..e48e69894 100644 --- a/components/compiler/streamerrorhandler.cpp +++ b/components/compiler/streamerrorhandler.cpp @@ -1,7 +1,5 @@ #include "streamerrorhandler.hpp" -#include - #include #include "tokenloc.hpp" @@ -61,7 +59,7 @@ namespace Compiler mContext = context; } - StreamErrorHandler::StreamErrorHandler() {} + StreamErrorHandler::StreamErrorHandler() = default; ContextOverride::ContextOverride(StreamErrorHandler& handler, const std::string& context) : mHandler(handler), mContext(handler.mContext) { diff --git a/components/compiler/stringparser.cpp b/components/compiler/stringparser.cpp index 1bacf7941..f4f612d6f 100644 --- a/components/compiler/stringparser.cpp +++ b/components/compiler/stringparser.cpp @@ -1,7 +1,6 @@ #include "stringparser.hpp" #include -#include #include diff --git a/components/compiler/tokenloc.hpp b/components/compiler/tokenloc.hpp index 62b5cdee5..ff715c5e9 100644 --- a/components/compiler/tokenloc.hpp +++ b/components/compiler/tokenloc.hpp @@ -13,7 +13,7 @@ namespace Compiler int mLine; std::string mLiteral; - TokenLoc() : mColumn (0), mLine (0), mLiteral ("") {} + TokenLoc() : mColumn (0), mLine (0), mLiteral () {} }; } diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index a1d66463c..e197c71b7 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -15,7 +15,7 @@ namespace DetourNavigator * @brief Navigator constructor initializes all internal data. Constructed object is ready to build a scene. * @param settings allows to customize navigator work. Constructor is only place to set navigator settings. */ - NavigatorImpl(const Settings& settings); + explicit NavigatorImpl(const Settings& settings); void addAgent(const osg::Vec3f& agentHalfExtents) override; @@ -40,9 +40,9 @@ namespace DetourNavigator bool removeWater(const osg::Vec2i& cellPosition) override; - void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) final; + void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) override; - void removePathgrid(const ESM::Pathgrid& pathgrid) final; + void removePathgrid(const ESM::Pathgrid& pathgrid) override; void update(const osg::Vec3f& playerPosition) override; diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index 9279e77e3..8b81bde19 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -60,9 +60,9 @@ namespace DetourNavigator return false; } - void addPathgrid(const ESM::Cell& /*cell*/, const ESM::Pathgrid& /*pathgrid*/) final {} + void addPathgrid(const ESM::Cell& /*cell*/, const ESM::Pathgrid& /*pathgrid*/) override {} - void removePathgrid(const ESM::Pathgrid& /*pathgrid*/) final {} + void removePathgrid(const ESM::Pathgrid& /*pathgrid*/) override {} void update(const osg::Vec3f& /*playerPosition*/) override {} diff --git a/components/esm/containerstate.hpp b/components/esm/containerstate.hpp index b0c4da2d1..7f1afd077 100644 --- a/components/esm/containerstate.hpp +++ b/components/esm/containerstate.hpp @@ -12,14 +12,14 @@ namespace ESM { InventoryState mInventory; - void load (ESMReader &esm) final; - void save (ESMWriter &esm, bool inInventory = false) const final; + void load (ESMReader &esm) override; + void save (ESMWriter &esm, bool inInventory = false) const override; - ContainerState& asContainerState() final + ContainerState& asContainerState() override { return *this; } - const ContainerState& asContainerState() const final + const ContainerState& asContainerState() const override { return *this; } diff --git a/components/esm/creaturelevliststate.hpp b/components/esm/creaturelevliststate.hpp index ec0bc8667..2ee9e511f 100644 --- a/components/esm/creaturelevliststate.hpp +++ b/components/esm/creaturelevliststate.hpp @@ -12,14 +12,14 @@ namespace ESM int mSpawnActorId; bool mSpawn; - void load (ESMReader &esm) final; - void save (ESMWriter &esm, bool inInventory = false) const final; + void load (ESMReader &esm) override; + void save (ESMWriter &esm, bool inInventory = false) const override; - CreatureLevListState& asCreatureLevListState() final + CreatureLevListState& asCreatureLevListState() override { return *this; } - const CreatureLevListState& asCreatureLevListState() const final + const CreatureLevListState& asCreatureLevListState() const override { return *this; } diff --git a/components/esm/creaturestate.hpp b/components/esm/creaturestate.hpp index 3e9a44d56..4b4c59d71 100644 --- a/components/esm/creaturestate.hpp +++ b/components/esm/creaturestate.hpp @@ -15,16 +15,16 @@ namespace ESM CreatureStats mCreatureStats; /// Initialize to default state - void blank(); + void blank() override; - void load (ESMReader &esm) final; - void save (ESMWriter &esm, bool inInventory = false) const final; + void load (ESMReader &esm) override; + void save (ESMWriter &esm, bool inInventory = false) const override; - CreatureState& asCreatureState() final + CreatureState& asCreatureState() override { return *this; } - const CreatureState& asCreatureState() const final + const CreatureState& asCreatureState() const override { return *this; } diff --git a/components/esm/doorstate.hpp b/components/esm/doorstate.hpp index 04ad110d6..c3aeb42e3 100644 --- a/components/esm/doorstate.hpp +++ b/components/esm/doorstate.hpp @@ -11,14 +11,14 @@ namespace ESM { int mDoorState = 0; - void load (ESMReader &esm) final; - void save (ESMWriter &esm, bool inInventory = false) const final; + void load (ESMReader &esm) override; + void save (ESMWriter &esm, bool inInventory = false) const override; - DoorState& asDoorState() final + DoorState& asDoorState() override { return *this; } - const DoorState& asDoorState() const final + const DoorState& asDoorState() const override { return *this; } diff --git a/components/esm/npcstate.hpp b/components/esm/npcstate.hpp index 6c0469050..fc6b91764 100644 --- a/components/esm/npcstate.hpp +++ b/components/esm/npcstate.hpp @@ -17,16 +17,16 @@ namespace ESM CreatureStats mCreatureStats; /// Initialize to default state - void blank(); + void blank() override; - void load (ESMReader &esm) final; - void save (ESMWriter &esm, bool inInventory = false) const final; + void load (ESMReader &esm) override; + void save (ESMWriter &esm, bool inInventory = false) const override; - NpcState& asNpcState() final + NpcState& asNpcState() override { return *this; } - const NpcState& asNpcState() const final + const NpcState& asNpcState() const override { return *this; } diff --git a/components/esm/objectstate.hpp b/components/esm/objectstate.hpp index 1079d6c72..6b0fca5ea 100644 --- a/components/esm/objectstate.hpp +++ b/components/esm/objectstate.hpp @@ -49,7 +49,7 @@ namespace ESM virtual void save (ESMWriter &esm, bool inInventory = false) const; - /// Initialize to default state + virtual /// Initialize to default state void blank(); virtual ~ObjectState(); diff --git a/components/myguiplatform/additivelayer.hpp b/components/myguiplatform/additivelayer.hpp index f0cfc1b41..f89e1d007 100644 --- a/components/myguiplatform/additivelayer.hpp +++ b/components/myguiplatform/additivelayer.hpp @@ -20,9 +20,9 @@ namespace osgMyGUI MYGUI_RTTI_DERIVED( AdditiveLayer ) AdditiveLayer(); - ~AdditiveLayer(); + ~AdditiveLayer() override; - void renderToTarget(MyGUI::IRenderTarget* _target, bool _update) final; + void renderToTarget(MyGUI::IRenderTarget* _target, bool _update) override; private: osg::ref_ptr mStateSet; diff --git a/components/myguiplatform/scalinglayer.hpp b/components/myguiplatform/scalinglayer.hpp index 7ce5f84f7..f9fd92a78 100644 --- a/components/myguiplatform/scalinglayer.hpp +++ b/components/myguiplatform/scalinglayer.hpp @@ -13,13 +13,13 @@ namespace osgMyGUI public: MYGUI_RTTI_DERIVED(ScalingLayer) - void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) final; + void deserialization(MyGUI::xml::ElementPtr _node, MyGUI::Version _version) override; - MyGUI::ILayerItem* getLayerItemByPoint(int _left, int _top) const final; - MyGUI::IntPoint getPosition(int _left, int _top) const final; - void renderToTarget(MyGUI::IRenderTarget* _target, bool _update) final; + MyGUI::ILayerItem* getLayerItemByPoint(int _left, int _top) const override; + MyGUI::IntPoint getPosition(int _left, int _top) const override; + void renderToTarget(MyGUI::IRenderTarget* _target, bool _update) override; - void resizeView(const MyGUI::IntSize& _viewSize) final; + void resizeView(const MyGUI::IntSize& _viewSize) override; private: void screenToLayerCoords(int& _left, int& _top) const; diff --git a/components/widgets/box.hpp b/components/widgets/box.hpp index e84c3bb1f..60d0ea67a 100644 --- a/components/widgets/box.hpp +++ b/components/widgets/box.hpp @@ -46,11 +46,11 @@ namespace Gui MYGUI_RTTI_DERIVED( AutoSizedTextBox ) public: - MyGUI::IntSize getRequestedSize() final; - void setCaption(const MyGUI::UString& _value) final; + MyGUI::IntSize getRequestedSize() override; + void setCaption(const MyGUI::UString& _value) override; protected: - void setPropertyOverride(const std::string& _key, const std::string& _value) final; + void setPropertyOverride(const std::string& _key, const std::string& _value) override; std::string mFontSize; }; @@ -60,13 +60,13 @@ namespace Gui public: - MyGUI::IntSize getRequestedSize() final; - void setCaption(const MyGUI::UString& _value) final; + MyGUI::IntSize getRequestedSize() override; + void setCaption(const MyGUI::UString& _value) override; - void initialiseOverride() final; + void initialiseOverride() override; protected: - void setPropertyOverride(const std::string& _key, const std::string& _value) final; + void setPropertyOverride(const std::string& _key, const std::string& _value) override; int getWidth(); std::string mFontSize; bool mShrink = false; @@ -79,11 +79,11 @@ namespace Gui MYGUI_RTTI_DERIVED( AutoSizedButton ) public: - MyGUI::IntSize getRequestedSize() final; - void setCaption(const MyGUI::UString& _value) final; + MyGUI::IntSize getRequestedSize() override; + void setCaption(const MyGUI::UString& _value) override; protected: - void setPropertyOverride(const std::string& _key, const std::string& _value) final; + void setPropertyOverride(const std::string& _key, const std::string& _value) override; std::string mFontSize; }; @@ -118,7 +118,7 @@ namespace Gui public: Spacer(); - MyGUI::IntSize getRequestedSize() final { return MyGUI::IntSize(0,0); } + MyGUI::IntSize getRequestedSize() override { return MyGUI::IntSize(0,0); } }; class HBox : public Box, public MyGUI::Widget @@ -126,18 +126,18 @@ namespace Gui MYGUI_RTTI_DERIVED( HBox ) public: - void setSize (const MyGUI::IntSize &_value) final; - void setCoord (const MyGUI::IntCoord &_value) final; + void setSize (const MyGUI::IntSize &_value) override; + void setCoord (const MyGUI::IntCoord &_value) override; protected: - void initialiseOverride() final; + void initialiseOverride() override; - void align() final; - MyGUI::IntSize getRequestedSize() final; + void align() override; + MyGUI::IntSize getRequestedSize() override; - void setPropertyOverride(const std::string& _key, const std::string& _value) final; + void setPropertyOverride(const std::string& _key, const std::string& _value) override; - void onWidgetCreated(MyGUI::Widget* _widget) final; + void onWidgetCreated(MyGUI::Widget* _widget) override; }; class VBox : public Box, public MyGUI::Widget @@ -145,18 +145,18 @@ namespace Gui MYGUI_RTTI_DERIVED( VBox) public: - void setSize (const MyGUI::IntSize &_value) final; - void setCoord (const MyGUI::IntCoord &_value) final; + void setSize (const MyGUI::IntSize &_value) override; + void setCoord (const MyGUI::IntCoord &_value) override; protected: - void initialiseOverride() final; + void initialiseOverride() override; - void align() final; - MyGUI::IntSize getRequestedSize() final; + void align() override; + MyGUI::IntSize getRequestedSize() override; - void setPropertyOverride(const std::string& _key, const std::string& _value) final; + void setPropertyOverride(const std::string& _key, const std::string& _value) override; - void onWidgetCreated(MyGUI::Widget* _widget) final; + void onWidgetCreated(MyGUI::Widget* _widget) override; }; } diff --git a/components/widgets/imagebutton.hpp b/components/widgets/imagebutton.hpp index 160f24e99..6e3fc1733 100644 --- a/components/widgets/imagebutton.hpp +++ b/components/widgets/imagebutton.hpp @@ -31,13 +31,13 @@ namespace Gui static bool sDefaultNeedKeyFocus; protected: - void setPropertyOverride(const std::string& _key, const std::string& _value) final; - void onMouseLostFocus(MyGUI::Widget* _new) final; - void onMouseSetFocus(MyGUI::Widget* _old) final; - void onMouseButtonPressed(int _left, int _top, MyGUI::MouseButton _id) final; - void onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id) final; - void onKeySetFocus(MyGUI::Widget* _old) final; - void onKeyLostFocus(MyGUI::Widget* _new) final; + void setPropertyOverride(const std::string& _key, const std::string& _value) override; + void onMouseLostFocus(MyGUI::Widget* _new) override; + void onMouseSetFocus(MyGUI::Widget* _old) override; + void onMouseButtonPressed(int _left, int _top, MyGUI::MouseButton _id) override; + void onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id) override; + void onKeySetFocus(MyGUI::Widget* _old) override; + void onKeyLostFocus(MyGUI::Widget* _new) override; std::string mImageHighlighted; std::string mImageNormal; diff --git a/components/widgets/list.hpp b/components/widgets/list.hpp index 604d5dada..be0339f33 100644 --- a/components/widgets/list.hpp +++ b/components/widgets/list.hpp @@ -48,10 +48,10 @@ namespace Gui void scrollToTop(); - void setPropertyOverride(const std::string& _key, const std::string& _value) final; + void setPropertyOverride(const std::string& _key, const std::string& _value) override; protected: - void initialiseOverride() final; + void initialiseOverride() override; void redraw(bool scrollbarShown = false); diff --git a/components/widgets/numericeditbox.hpp b/components/widgets/numericeditbox.hpp index ff16424d0..e1f33e887 100644 --- a/components/widgets/numericeditbox.hpp +++ b/components/widgets/numericeditbox.hpp @@ -22,8 +22,8 @@ namespace Gui { } - void initialiseOverride() final; - void shutdownOverride() final; + void initialiseOverride() override; + void shutdownOverride() override; typedef MyGUI::delegates::CMultiDelegate1 EventHandle_ValueChanged; EventHandle_ValueChanged eventValueChanged; @@ -36,8 +36,8 @@ namespace Gui void setMaxValue(int maxValue); private: void onEditTextChange(MyGUI::EditBox* sender); - void onKeyLostFocus(MyGUI::Widget* _new) final; - void onKeyButtonPressed(MyGUI::KeyCode key, MyGUI::Char character) final; + void onKeyLostFocus(MyGUI::Widget* _new) override; + void onKeyButtonPressed(MyGUI::KeyCode key, MyGUI::Char character) override; int mValue; diff --git a/components/widgets/sharedstatebutton.hpp b/components/widgets/sharedstatebutton.hpp index 859543d20..42c6424b2 100644 --- a/components/widgets/sharedstatebutton.hpp +++ b/components/widgets/sharedstatebutton.hpp @@ -23,13 +23,13 @@ namespace Gui protected: void updateButtonState(); - void onMouseButtonPressed(int _left, int _top, MyGUI::MouseButton _id) final; - void onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id) final; - void onMouseSetFocus(MyGUI::Widget* _old) final; - void onMouseLostFocus(MyGUI::Widget* _new) final; - void baseUpdateEnable() final; + void onMouseButtonPressed(int _left, int _top, MyGUI::MouseButton _id) override; + void onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id) override; + void onMouseSetFocus(MyGUI::Widget* _old) override; + void onMouseLostFocus(MyGUI::Widget* _new) override; + void baseUpdateEnable() override; - void shutdownOverride() final; + void shutdownOverride() override; bool _setState(const std::string &_value); diff --git a/components/widgets/windowcaption.hpp b/components/widgets/windowcaption.hpp index f8c1a310c..256c82831 100644 --- a/components/widgets/windowcaption.hpp +++ b/components/widgets/windowcaption.hpp @@ -14,11 +14,11 @@ namespace Gui public: WindowCaption(); - void setCaption(const MyGUI::UString &_value) final; - void initialiseOverride() final; + void setCaption(const MyGUI::UString &_value) override; + void initialiseOverride() override; - void setSize(const MyGUI::IntSize& _value) final; - void setCoord(const MyGUI::IntCoord& _value) final; + void setSize(const MyGUI::IntSize& _value) override; + void setCoord(const MyGUI::IntCoord& _value) override; private: MyGUI::Widget* mLeft; From e51ca542d4f451ed4b140a20ff1f682c4ddc0897 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 23 Oct 2020 00:03:14 +0200 Subject: [PATCH 021/111] components/config cleanup --- components/config/gamesettings.cpp | 73 +++++++++----------------- components/config/gamesettings.hpp | 2 +- components/config/launchersettings.cpp | 8 +-- components/config/settingsbase.hpp | 2 +- 4 files changed, 30 insertions(+), 55 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index b771b7fc8..b228d23c6 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -7,24 +7,6 @@ #include -#include - -/** - * Workaround for problems with whitespaces in paths in older versions of Boost library - */ -#if (BOOST_VERSION <= 104600) -namespace boost -{ - - template<> - inline boost::filesystem::path lexical_cast(const std::string& arg) - { - return boost::filesystem::path(arg); - } - -} /* namespace boost */ -#endif /* (BOOST_VERSION <= 104600) */ - const char Config::GameSettings::sContentKey[] = "content"; Config::GameSettings::GameSettings(Files::ConfigurationManager &cfg) @@ -32,9 +14,7 @@ Config::GameSettings::GameSettings(Files::ConfigurationManager &cfg) { } -Config::GameSettings::~GameSettings() -{ -} +Config::GameSettings::~GameSettings() = default; void Config::GameSettings::validatePaths() { @@ -51,8 +31,8 @@ void Config::GameSettings::validatePaths() mCfgMgr.processPaths(dataDirs); mDataDirs.clear(); - for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { - QString path = QString::fromUtf8(it->string().c_str()); + for (auto & dataDir : dataDirs) { + QString path = QString::fromUtf8(dataDir.string().c_str()); QDir dir(path); if (dir.exists()) @@ -186,11 +166,11 @@ bool Config::GameSettings::writeFile(QTextStream &stream) QString string = i.value(); stream << delim; - for (QString::const_iterator it = string.begin(); it != string.end(); ++it) + for (auto it : string) { - if (*it == delim || *it == escape) + if (it == delim || it == escape) stream << escape; - stream << *it; + stream << it; } stream << delim; @@ -219,7 +199,7 @@ bool Config::GameSettings::writeFile(QTextStream &stream) return true; } -bool Config::GameSettings::isOrderedLine(const QString& line) const +bool Config::GameSettings::isOrderedLine(const QString& line) { return line.contains(QRegExp("^\\s*fallback-archive\\s*=")) || line.contains(QRegExp("^\\s*fallback\\s*=")) @@ -287,9 +267,9 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) // QRegExp settingRegex("^([^=]+)\\s*=\\s*([^,]+)(.*)$"); std::vector comments; - std::vector::iterator commentStart = fileCopy.end(); + auto commentStart = fileCopy.end(); std::map > commentsMap; - for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + for (auto iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) { if (isOrderedLine(*iter)) { @@ -339,9 +319,9 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) if (commentStart == fileCopy.end()) throw std::runtime_error("Config::GameSettings: failed to parse settings - iterator is past of end of settings file"); - for (std::vector::const_iterator it = comments.begin(); it != comments.end(); ++it) + for (const auto & comment : comments) { - *commentStart = *it; + *commentStart = comment; ++commentStart; } comments.clear(); @@ -383,16 +363,16 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) } // comments at top of file - for (std::vector::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) + for (auto & iter : fileCopy) { - if ((*iter).isNull()) + if (iter.isNull()) continue; // Below is based on readFile() code, if that changes corresponding change may be // required (for example duplicates may be inserted if the rules don't match) - if (/*(*iter).isEmpty() ||*/ (*iter).contains(QRegExp("^\\s*#"))) + if (/*(*iter).isEmpty() ||*/ iter.contains(QRegExp("^\\s*#"))) { - stream << *iter << "\n"; + stream << iter << "\n"; continue; } } @@ -416,11 +396,11 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) QString string = it.value(); settingLine += delim; - for (QString::const_iterator iter = string.begin(); iter != string.end(); ++iter) + for (auto iter : string) { - if (*iter == delim || *iter == escape) + if (iter == delim || iter == escape) settingLine += escape; - settingLine += *iter; + settingLine += iter; } settingLine += delim; } @@ -438,8 +418,7 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) if (settingRegex.indexIn(settingLine) != -1) { - std::map >::iterator i = - commentsMap.find(settingRegex.cap(1)+"="+settingRegex.cap(2)); + auto i = commentsMap.find(settingRegex.cap(1)+"="+settingRegex.cap(2)); // check if previous removed content item with comments if (i == commentsMap.end()) @@ -448,8 +427,8 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) if (i != commentsMap.end()) { std::vector cLines = i->second; - for (std::vector::const_iterator ci = cLines.begin(); ci != cLines.end(); ++ci) - stream << *ci << "\n"; + for (const auto & cLine : cLines) + stream << cLine << "\n"; commentsMap.erase(i); } @@ -461,14 +440,14 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) // flush any removed settings if (!commentsMap.empty()) { - std::map >::const_iterator i = commentsMap.begin(); + auto i = commentsMap.begin(); for (; i != commentsMap.end(); ++i) { if (i->first.contains(QRegExp("^\\s*content\\s*="))) { std::vector cLines = i->second; - for (std::vector::const_iterator ci = cLines.begin(); ci != cLines.end(); ++ci) - stream << *ci << "\n"; + for (const auto & cLine : cLines) + stream << cLine << "\n"; // mark the content line entry for future preocessing stream << "##" << i->first << "\n"; @@ -481,8 +460,8 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) // flush any end comments if (!comments.empty()) { - for (std::vector::const_iterator ci = comments.begin(); ci != comments.end(); ++ci) - stream << *ci << "\n"; + for (const auto & comment : comments) + stream << comment << "\n"; } file.resize(file.pos()); diff --git a/components/config/gamesettings.hpp b/components/config/gamesettings.hpp index a6876b83d..ccb1d5fd2 100644 --- a/components/config/gamesettings.hpp +++ b/components/config/gamesettings.hpp @@ -88,7 +88,7 @@ namespace Config static const char sContentKey[]; - bool isOrderedLine(const QString& line) const; + static bool isOrderedLine(const QString& line) ; }; } #endif // GAMESETTINGS_HPP diff --git a/components/config/launchersettings.cpp b/components/config/launchersettings.cpp index ae591ef58..ff2c38438 100644 --- a/components/config/launchersettings.cpp +++ b/components/config/launchersettings.cpp @@ -12,13 +12,9 @@ const char Config::LauncherSettings::sLauncherConfigFileName[] = "launcher.cfg"; const char Config::LauncherSettings::sContentListsSectionPrefix[] = "Profiles/"; const char Config::LauncherSettings::sContentListSuffix[] = "/content"; -Config::LauncherSettings::LauncherSettings() -{ -} +Config::LauncherSettings::LauncherSettings() = default; -Config::LauncherSettings::~LauncherSettings() -{ -} +Config::LauncherSettings::~LauncherSettings() = default; QStringList Config::LauncherSettings::subKeys(const QString &key) { diff --git a/components/config/settingsbase.hpp b/components/config/settingsbase.hpp index 119971716..86fa962ae 100644 --- a/components/config/settingsbase.hpp +++ b/components/config/settingsbase.hpp @@ -15,7 +15,7 @@ namespace Config public: SettingsBase() { mMultiValue = false; } - ~SettingsBase() {} + ~SettingsBase() = default; inline QString value(const QString &key, const QString &defaultValue = QString()) const { From 5aa053c53e39d0d155a5bdc33dc4dae773c7a715 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 23 Oct 2020 00:13:51 +0200 Subject: [PATCH 022/111] components/compiler/streamerrorhandler.cpp needs sstream for MacOS --- components/compiler/streamerrorhandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/compiler/streamerrorhandler.cpp b/components/compiler/streamerrorhandler.cpp index e48e69894..030d02d1d 100644 --- a/components/compiler/streamerrorhandler.cpp +++ b/components/compiler/streamerrorhandler.cpp @@ -1,5 +1,7 @@ #include "streamerrorhandler.hpp" +#include + #include #include "tokenloc.hpp" From cf81f1bbb72b511ac785822bc125a9543d457e01 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 01:41:28 +0100 Subject: [PATCH 023/111] Make composing variables compose in the expected order --- apps/openmw/main.cpp | 2 + components/files/configurationmanager.cpp | 63 ++++++++++++++++++++++- components/files/configurationmanager.hpp | 4 ++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 4e18ad95f..0c46903c9 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -164,7 +164,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat return false; } + bpo::variables_map composingVariables = cfgMgr.separateComposingVariables(variables, desc); cfgMgr.readConfiguration(variables, desc); + cfgMgr.mergeComposingVariables(variables, composingVariables, desc); Version::Version v = Version::getOpenmwVersion(variables["resources"].as().toStdString()); std::cout << v.describe() << std::endl; diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index c74c39922..42639d3e5 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -2,6 +2,7 @@ #include #include +#include #include /** @@ -58,23 +59,83 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m { bool silent = mSilent; mSilent = quiet; - + // User config has the highest priority. + auto composingVariables = separateComposingVariables(variables, description); + Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the user config"; loadConfig(mFixedPath.getUserConfigPath(), variables, description); + mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); // read either local or global config depending on type of installation + composingVariables = separateComposingVariables(variables, description); + Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the local config"; bool loaded = loadConfig(mFixedPath.getLocalPath(), variables, description); + mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); if (!loaded) { + composingVariables = separateComposingVariables(variables, description); + Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the global config"; loadConfig(mFixedPath.getGlobalConfigPath(), variables, description); + mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); } mSilent = silent; } +boost::program_options::variables_map ConfigurationManager::separateComposingVariables(boost::program_options::variables_map & variables, boost::program_options::options_description& description) +{ + boost::program_options::variables_map composingVariables; + for (auto itr = variables.begin(); itr != variables.end();) + { + if (description.find((*itr).first, false).semantic()->is_composing()) + { + composingVariables.emplace(*itr); + itr = variables.erase(itr); + } + else + ++itr; + } + return composingVariables; +} + +void ConfigurationManager::mergeComposingVariables(boost::program_options::variables_map & first, boost::program_options::variables_map & second, boost::program_options::options_description& description) +{ + for (auto& [name, variableValue] : first) + { + if (description.find(name, false).semantic()->is_composing()) + { + if (second[name].defaulted() || second[name].empty()) + continue; + + boost::any& firstValue = variableValue.value(); + const boost::any& secondValue = second[name].value(); + + if (firstValue.type() == typeid(Files::EscapePathContainer)) + { + auto& firstPathContainer = boost::any_cast(firstValue); + const auto& secondPathContainer = boost::any_cast(secondValue); + + firstPathContainer.insert(firstPathContainer.end(), secondPathContainer.begin(), secondPathContainer.end()); + } + else if (firstValue.type() == typeid(Fallback::FallbackMap)) + { + auto& firstMap = boost::any_cast(firstValue); + const auto& secondMap = boost::any_cast(secondValue); + + std::map tempMap(secondMap.mMap); + tempMap.merge(firstMap.mMap); + firstMap.mMap.swap(tempMap); + } + else + Log(Debug::Error) << "Unexpected composing variable type. Curse boost and their blasted arcane templates."; + } + } + +} + void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool create) { std::string path; diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 446abd4dc..0ec0a1f67 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -25,6 +25,10 @@ struct ConfigurationManager void readConfiguration(boost::program_options::variables_map& variables, boost::program_options::options_description& description, bool quiet=false); + boost::program_options::variables_map separateComposingVariables(boost::program_options::variables_map& variables, boost::program_options::options_description& description); + + void mergeComposingVariables(boost::program_options::variables_map& first, boost::program_options::variables_map& second, boost::program_options::options_description& description); + void processPaths(Files::PathContainer& dataDirs, bool create = false); ///< \param create Try creating the directory, if it does not exist. From fca8634b74d19cb8faf6c20df3e5b4a2461cb239 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 01:46:49 +0100 Subject: [PATCH 024/111] Remove debugging lines --- components/files/configurationmanager.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index 42639d3e5..c50c7713e 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -62,21 +62,18 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m // User config has the highest priority. auto composingVariables = separateComposingVariables(variables, description); - Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the user config"; loadConfig(mFixedPath.getUserConfigPath(), variables, description); mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); // read either local or global config depending on type of installation composingVariables = separateComposingVariables(variables, description); - Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the local config"; bool loaded = loadConfig(mFixedPath.getLocalPath(), variables, description); mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); if (!loaded) { composingVariables = separateComposingVariables(variables, description); - Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the global config"; loadConfig(mFixedPath.getGlobalConfigPath(), variables, description); mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); From 8b28b6e55e2eb2479f9e8ba7afd053fe718c80cf Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 01:58:43 +0100 Subject: [PATCH 025/111] Compose BSA, context and script blacklist lists These would only take their value from the highest priority source, so specifying `openmw --content anExtraEsp.esp` would override all the content files in the user cfg file, and the user cfg file would override any in the global/local one. --- apps/openmw/main.cpp | 6 +++--- components/files/configurationmanager.cpp | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 0c46903c9..a860438ce 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -67,7 +67,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat "set local data directory (highest priority)") ("fallback-archive", bpo::value()->default_value(Files::EscapeStringVector(), "fallback-archive") - ->multitoken(), "set fallback BSA archives (later archives have higher priority)") + ->multitoken()->composing(), "set fallback BSA archives (later archives have higher priority)") ("resources", bpo::value()->default_value("resources"), "set resources directory") @@ -76,7 +76,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat "set initial cell") ("content", bpo::value()->default_value(Files::EscapeStringVector(), "") - ->multitoken(), "content file(s): esm/esp, or omwgame/omwaddon") + ->multitoken()->composing(), "content file(s): esm/esp, or omwgame/omwaddon") ("no-sound", bpo::value()->implicit_value(true) ->default_value(false), "disable all sounds") @@ -101,7 +101,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat "\t2 - treat warnings as errors") ("script-blacklist", bpo::value()->default_value(Files::EscapeStringVector(), "") - ->multitoken(), "ignore the specified script (if the use of the blacklist is enabled)") + ->multitoken()->composing(), "ignore the specified script (if the use of the blacklist is enabled)") ("script-blacklist-use", bpo::value()->implicit_value(true) ->default_value(true), "enable script blacklisting") diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index c50c7713e..c7847b122 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -109,7 +109,7 @@ void ConfigurationManager::mergeComposingVariables(boost::program_options::varia boost::any& firstValue = variableValue.value(); const boost::any& secondValue = second[name].value(); - + if (firstValue.type() == typeid(Files::EscapePathContainer)) { auto& firstPathContainer = boost::any_cast(firstValue); @@ -117,6 +117,13 @@ void ConfigurationManager::mergeComposingVariables(boost::program_options::varia firstPathContainer.insert(firstPathContainer.end(), secondPathContainer.begin(), secondPathContainer.end()); } + else if (firstValue.type() == typeid(Files::EscapeStringVector)) + { + auto& firstVector = boost::any_cast(firstValue); + const auto& secondVector = boost::any_cast(secondValue); + + firstVector.mVector.insert(firstVector.mVector.end(), secondVector.mVector.begin(), secondVector.mVector.end()); + } else if (firstValue.type() == typeid(Fallback::FallbackMap)) { auto& firstMap = boost::any_cast(firstValue); From 129bd516721b25b69b4b2e21a7b3a519f91f9c92 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Fri, 23 Oct 2020 14:04:21 +0300 Subject: [PATCH 026/111] Add compressed BSA support to bsatool --- apps/bsatool/bsatool.cpp | 53 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/apps/bsatool/bsatool.cpp b/apps/bsatool/bsatool.cpp index ed86a3a42..3afbd777f 100644 --- a/apps/bsatool/bsatool.cpp +++ b/apps/bsatool/bsatool.cpp @@ -6,7 +6,8 @@ #include #include -#include +#include +#include #define BSATOOL_VERSION 1.1 @@ -25,16 +26,6 @@ struct Arguments bool fullpath; }; -void replaceAll(std::string& str, const std::string& needle, const std::string& substitute) -{ - size_t pos = str.find(needle); - while(pos != std::string::npos) - { - str.replace(pos, needle.size(), substitute); - pos = str.find(needle); - } -} - bool parseOptions (int argc, char** argv, Arguments &info) { bpo::options_description desc("Inspect and extract files from Bethesda BSA archives\n\n" @@ -144,9 +135,9 @@ bool parseOptions (int argc, char** argv, Arguments &info) return true; } -int list(Bsa::BSAFile& bsa, Arguments& info); -int extract(Bsa::BSAFile& bsa, Arguments& info); -int extractAll(Bsa::BSAFile& bsa, Arguments& info); +int list(std::unique_ptr& bsa, Arguments& info); +int extract(std::unique_ptr& bsa, Arguments& info); +int extractAll(std::unique_ptr& bsa, Arguments& info); int main(int argc, char** argv) { @@ -157,8 +148,16 @@ int main(int argc, char** argv) return 1; // Open file - Bsa::BSAFile bsa; - bsa.open(info.filename); + std::unique_ptr bsa; + + Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(info.filename); + + if (bsaVersion == Bsa::BSAVER_COMPRESSED) + bsa = std::make_unique(Bsa::CompressedBSAFile()); + else + bsa = std::make_unique(Bsa::BSAFile()); + + bsa->open(info.filename); if (info.mode == "list") return list(bsa, info); @@ -179,10 +178,10 @@ int main(int argc, char** argv) } } -int list(Bsa::BSAFile& bsa, Arguments& info) +int list(std::unique_ptr& bsa, Arguments& info) { // List all files - const Bsa::BSAFile::FileList &files = bsa.getList(); + const Bsa::BSAFile::FileList &files = bsa->getList(); for (const auto& file : files) { if(info.longformat) @@ -201,15 +200,15 @@ int list(Bsa::BSAFile& bsa, Arguments& info) return 0; } -int extract(Bsa::BSAFile& bsa, Arguments& info) +int extract(std::unique_ptr& bsa, Arguments& info) { std::string archivePath = info.extractfile; - replaceAll(archivePath, "/", "\\"); + Misc::StringUtils::replaceAll(archivePath, "/", "\\"); std::string extractPath = info.extractfile; - replaceAll(extractPath, "\\", "/"); + Misc::StringUtils::replaceAll(extractPath, "\\", "/"); - if (!bsa.exists(archivePath.c_str())) + if (!bsa->exists(archivePath.c_str())) { std::cout << "ERROR: file '" << archivePath << "' not found\n"; std::cout << "In archive: " << info.filename << std::endl; @@ -237,7 +236,7 @@ int extract(Bsa::BSAFile& bsa, Arguments& info) } // Get a stream for the file to extract - Files::IStreamPtr stream = bsa.getFile(archivePath.c_str()); + Files::IStreamPtr stream = bsa->getFile(archivePath.c_str()); bfs::ofstream out(target, std::ios::binary); @@ -250,12 +249,12 @@ int extract(Bsa::BSAFile& bsa, Arguments& info) return 0; } -int extractAll(Bsa::BSAFile& bsa, Arguments& info) +int extractAll(std::unique_ptr& bsa, Arguments& info) { - for (const auto &file : bsa.getList()) + for (const auto &file : bsa->getList()) { std::string extractPath(file.name); - replaceAll(extractPath, "\\", "/"); + Misc::StringUtils::replaceAll(extractPath, "\\", "/"); // Get the target path (the path the file will be extracted to) bfs::path target (info.outdir); @@ -273,7 +272,7 @@ int extractAll(Bsa::BSAFile& bsa, Arguments& info) // Get a stream for the file to extract // (inefficient because getFile iter on the list again) - Files::IStreamPtr data = bsa.getFile(file.name); + Files::IStreamPtr data = bsa->getFile(file.name); bfs::ofstream out(target, std::ios::binary); // Write the file to disk From 350f6e61f760da7b9f4ac2f4e2eb5027cdbddd2e Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 13:03:36 +0100 Subject: [PATCH 027/111] Move FallbackMap validator implementation to source file --- components/fallback/validate.cpp | 28 ++++++++++++++++++++++++++++ components/fallback/validate.hpp | 27 +-------------------------- 2 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 components/fallback/validate.cpp diff --git a/components/fallback/validate.cpp b/components/fallback/validate.cpp new file mode 100644 index 000000000..24865a039 --- /dev/null +++ b/components/fallback/validate.cpp @@ -0,0 +1,28 @@ +#include "validate.hpp" + +void Fallback::validate(boost::any& v, std::vector const& tokens, FallbackMap*, int) +{ + if (v.empty()) + { + v = boost::any(FallbackMap()); + } + + FallbackMap *map = boost::any_cast(&v); + + for (std::vector::const_iterator it = tokens.begin(); it != tokens.end(); ++it) + { + std::string temp = Files::EscapeHashString::processString(*it); + int sep = temp.find(","); + if (sep < 1 || sep == (int)temp.length() - 1) +#if (BOOST_VERSION < 104200) + throw boost::program_options::validation_error("invalid value"); +#else + throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); +#endif + + std::string key(temp.substr(0, sep)); + std::string value(temp.substr(sep + 1)); + + map->mMap[key] = value; + } +} diff --git a/components/fallback/validate.hpp b/components/fallback/validate.hpp index cef52e462..96690f50a 100644 --- a/components/fallback/validate.hpp +++ b/components/fallback/validate.hpp @@ -16,32 +16,7 @@ namespace Fallback std::map mMap; }; - void validate(boost::any &v, std::vector const &tokens, FallbackMap*, int) - { - if (v.empty()) - { - v = boost::any(FallbackMap()); - } - - FallbackMap *map = boost::any_cast(&v); - - for (std::vector::const_iterator it = tokens.begin(); it != tokens.end(); ++it) - { - std::string temp = Files::EscapeHashString::processString(*it); - int sep = temp.find(","); - if (sep < 1 || sep == (int)temp.length() - 1) -#if (BOOST_VERSION < 104200) - throw boost::program_options::validation_error("invalid value"); -#else - throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); -#endif - - std::string key(temp.substr(0, sep)); - std::string value(temp.substr(sep + 1)); - - map->mMap[key] = value; - } - } + void validate(boost::any &v, std::vector const &tokens, FallbackMap*, int); } #endif From ce0966b9b7f11f8f6a899fc0bdf570ce6dd83b16 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 13:13:47 +0100 Subject: [PATCH 028/111] Improve validate implementation --- components/fallback/validate.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/fallback/validate.cpp b/components/fallback/validate.cpp index 24865a039..27f1f233e 100644 --- a/components/fallback/validate.cpp +++ b/components/fallback/validate.cpp @@ -9,11 +9,11 @@ void Fallback::validate(boost::any& v, std::vector const& tokens, F FallbackMap *map = boost::any_cast(&v); - for (std::vector::const_iterator it = tokens.begin(); it != tokens.end(); ++it) + for (const auto& token : tokens) { - std::string temp = Files::EscapeHashString::processString(*it); - int sep = temp.find(","); - if (sep < 1 || sep == (int)temp.length() - 1) + std::string temp = Files::EscapeHashString::processString(token); + size_t sep = temp.find(","); + if (sep < 1 || sep == temp.length() - 1) #if (BOOST_VERSION < 104200) throw boost::program_options::validation_error("invalid value"); #else From f57851587dcf766843b2e9dc25ad2cb9c1e0ed6e Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 13:16:51 +0100 Subject: [PATCH 029/111] Fix edge case where FallbackMap has no comma --- components/fallback/validate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/fallback/validate.cpp b/components/fallback/validate.cpp index 27f1f233e..98c6c39fd 100644 --- a/components/fallback/validate.cpp +++ b/components/fallback/validate.cpp @@ -13,7 +13,7 @@ void Fallback::validate(boost::any& v, std::vector const& tokens, F { std::string temp = Files::EscapeHashString::processString(token); size_t sep = temp.find(","); - if (sep < 1 || sep == temp.length() - 1) + if (sep < 1 || sep == temp.length() - 1 || sep == std::string::npos) #if (BOOST_VERSION < 104200) throw boost::program_options::validation_error("invalid value"); #else From 538314b03aad22d0f334bc0c18814eb1437a128b Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 15:34:41 +0100 Subject: [PATCH 030/111] Make path settings have path type --- apps/opencs/editor.cpp | 15 +++------ apps/openmw/main.cpp | 23 ++++++-------- components/config/gamesettings.cpp | 50 ++++++++++++------------------ 3 files changed, 34 insertions(+), 54 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 0c3d006c4..0dce198f8 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -89,10 +89,10 @@ std::pair > CS::Editor::readConfi desc.add_options() ("data", boost::program_options::value()->default_value(Files::EscapePathContainer(), "data")->multitoken()->composing()) - ("data-local", boost::program_options::value()->default_value("")) + ("data-local", boost::program_options::value()->default_value(Files::EscapePath(), "")) ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) ("encoding", boost::program_options::value()->default_value("win1252")) - ("resources", boost::program_options::value()->default_value("resources")) + ("resources", boost::program_options::value()->default_value(Files::EscapePath(), "resources")) ("fallback-archive", boost::program_options::value()-> default_value(Files::EscapeStringVector(), "fallback-archive")->multitoken()) ("fallback", boost::program_options::value()->default_value(FallbackMap(), "") @@ -112,7 +112,7 @@ std::pair > CS::Editor::readConfi mDocumentManager.setEncoding(ToUTF8::calculateEncoding(mEncodingName)); mFileDialog.setEncoding (QString::fromUtf8(mEncodingName.c_str())); - mDocumentManager.setResourceDir (mResources = variables["resources"].as().toStdString()); + mDocumentManager.setResourceDir (mResources = variables["resources"].as().mPath); if (variables["script-blacklist-use"].as()) mDocumentManager.setBlacklistedScripts ( @@ -125,14 +125,9 @@ std::pair > CS::Editor::readConfi dataDirs = Files::PathContainer(Files::EscapePath::toPathContainer(variables["data"].as())); } - std::string local = variables["data-local"].as().toStdString(); + Files::PathContainer::value_type local(variables["data-local"].as().mPath); if (!local.empty()) - { - if (local.front() == '\"') - local = local.substr(1, local.length() - 2); - - dataLocal.push_back(Files::PathContainer::value_type(local)); - } + dataLocal.push_back(local); mCfgMgr.processPaths (dataDirs); mCfgMgr.processPaths (dataLocal, true); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index a860438ce..adf4bf18c 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -63,13 +63,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("data", bpo::value()->default_value(Files::EscapePathContainer(), "data") ->multitoken()->composing(), "set data directories (later directories have higher priority)") - ("data-local", bpo::value()->default_value(""), + ("data-local", bpo::value()->default_value(Files::EscapePath(), ""), "set local data directory (highest priority)") ("fallback-archive", bpo::value()->default_value(Files::EscapeStringVector(), "fallback-archive") ->multitoken()->composing(), "set fallback BSA archives (later archives have higher priority)") - ("resources", bpo::value()->default_value("resources"), + ("resources", bpo::value()->default_value(Files::EscapePath(), "resources"), "set resources directory") ("start", bpo::value()->default_value(""), @@ -106,7 +106,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("script-blacklist-use", bpo::value()->implicit_value(true) ->default_value(true), "enable script blacklisting") - ("load-savegame", bpo::value()->default_value(""), + ("load-savegame", bpo::value()->default_value(Files::EscapePath(), ""), "load a save game file on game startup (specify an absolute filename or a filename relative to the current working directory)") ("skip-menu", bpo::value()->implicit_value(true) @@ -159,7 +159,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat { cfgMgr.readConfiguration(variables, desc, true); - Version::Version v = Version::getOpenmwVersion(variables["resources"].as().toStdString()); + Version::Version v = Version::getOpenmwVersion(variables["resources"].as().mPath.string()); std::cout << v.describe() << std::endl; return false; } @@ -168,7 +168,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat cfgMgr.readConfiguration(variables, desc); cfgMgr.mergeComposingVariables(variables, composingVariables, desc); - Version::Version v = Version::getOpenmwVersion(variables["resources"].as().toStdString()); + Version::Version v = Version::getOpenmwVersion(variables["resources"].as().mPath.string()); std::cout << v.describe() << std::endl; engine.setGrabMouse(!variables["no-grab"].as()); @@ -183,18 +183,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat Files::PathContainer dataDirs(Files::EscapePath::toPathContainer(variables["data"].as())); - std::string local(variables["data-local"].as().toStdString()); + Files::PathContainer::value_type local(variables["data-local"].as().mPath); if (!local.empty()) - { - if (local.front() == '\"') - local = local.substr(1, local.length() - 2); - - dataDirs.push_back(Files::PathContainer::value_type(local)); - } + dataDirs.push_back(local); cfgMgr.processPaths(dataDirs); - engine.setResourceDir(variables["resources"].as().toStdString()); + engine.setResourceDir(variables["resources"].as().mPath); engine.setDataDirs(dataDirs); // fallback archives @@ -232,7 +227,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setWarningsMode (variables["script-warn"].as()); engine.setScriptBlacklist (variables["script-blacklist"].as().toStdStringVector()); engine.setScriptBlacklistUse (variables["script-blacklist-use"].as()); - engine.setSaveGameFile (variables["load-savegame"].as().toStdString()); + engine.setSaveGameFile (variables["load-savegame"].as().mPath.string()); // other settings Fallback::Map::init(variables["fallback"].as().mMap); diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index b771b7fc8..223045ab5 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -118,12 +118,19 @@ bool Config::GameSettings::readFile(QTextStream &stream, QMultiMap(hash) << 32; } - return hash + hash2; + if (extension.empty()) + return result; + Misc::StringUtils::lowerCaseInPlace(extension); + if (extension == ".kf") result |= 0x80; + else if (extension == ".nif") result |= 0x8000; + else if (extension == ".dds") result |= 0x8080; + else if (extension == ".wav") result |= 0x80000000; + uint32_t hash = 0; + for (const char &c : extension) + hash = hash * 0x1003f + c; + result += static_cast(hash) << 32; + return result; } } //namespace Bsa From 1ce296aa7f0e73e5b72d29ba1141602fbbc728f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 Oct 2020 18:54:46 +0200 Subject: [PATCH 034/111] Use fallback values for region sounds and fix probability --- apps/openmw/mwsound/regionsoundselector.cpp | 16 ++++++++++++---- apps/openmw/mwsound/regionsoundselector.hpp | 4 ++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwsound/regionsoundselector.cpp b/apps/openmw/mwsound/regionsoundselector.cpp index ac5f66721..55afd6ab6 100644 --- a/apps/openmw/mwsound/regionsoundselector.cpp +++ b/apps/openmw/mwsound/regionsoundselector.cpp @@ -1,5 +1,6 @@ #include "regionsoundselector.hpp" +#include #include #include @@ -18,6 +19,12 @@ namespace MWSound } } + RegionSoundSelector::RegionSoundSelector() + { + mMinTimeBetweenSounds = Fallback::Map::getFloat("Weather_Minimum_Time_Between_Environmental_Sounds"); + mMaxTimeBetweenSounds = Fallback::Map::getFloat("Weather_Maximum_Time_Between_Environmental_Sounds"); + } + boost::optional RegionSoundSelector::getNextRandom(float duration, const std::string& regionName, const MWBase::World& world) { @@ -27,9 +34,7 @@ namespace MWSound return {}; const float a = Misc::Rng::rollClosedProbability(); - // NOTE: We should use the "Minimum Time Between Environmental Sounds" and - // "Maximum Time Between Environmental Sounds" fallback settings here. - mTimeToNextEnvSound = 5.0f * a + 15.0f * (1.0f - a); + mTimeToNextEnvSound = mMinTimeBetweenSounds + (mMaxTimeBetweenSounds - mMinTimeBetweenSounds) * a; mTimePassed = 0; if (mLastRegionName != regionName) @@ -50,7 +55,7 @@ namespace MWSound return {}; } - const int r = Misc::Rng::rollDice(mSumChance); + const int r = Misc::Rng::rollDice(std::max(mSumChance, 100)); int pos = 0; const auto isSelected = [&] (const ESM::Region::SoundRef& sound) @@ -66,6 +71,9 @@ namespace MWSound if (it == region->mSoundList.end()) return {}; + // TODO + // mTimeToNextEnvSound += soundDuration + return it->mSound; } } diff --git a/apps/openmw/mwsound/regionsoundselector.hpp b/apps/openmw/mwsound/regionsoundselector.hpp index 00a2d5ca8..13510a0f6 100644 --- a/apps/openmw/mwsound/regionsoundselector.hpp +++ b/apps/openmw/mwsound/regionsoundselector.hpp @@ -18,11 +18,15 @@ namespace MWSound boost::optional getNextRandom(float duration, const std::string& regionName, const MWBase::World& world); + RegionSoundSelector(); + private: float mTimeToNextEnvSound = 0.0f; int mSumChance = 0; std::string mLastRegionName; float mTimePassed = 0.0; + float mMinTimeBetweenSounds; + float mMaxTimeBetweenSounds; }; } From e7f9fefd2af1971575ff9d446813781c93c8d34d Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 24 Oct 2020 22:03:46 +0300 Subject: [PATCH 035/111] Document object paging settings (task #5512) --- .../reference/modding/settings/terrain.rst | 112 +++++++++++++++++- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/docs/source/reference/modding/settings/terrain.rst b/docs/source/reference/modding/settings/terrain.rst index 824c27913..149ef979e 100644 --- a/docs/source/reference/modding/settings/terrain.rst +++ b/docs/source/reference/modding/settings/terrain.rst @@ -8,21 +8,19 @@ distant terrain :Range: True/False :Default: False -Controls whether the engine will use paging and LOD algorithms to load the terrain of the entire world at all times. +Controls whether the engine will use paging (chunking) and LOD algorithms to load the terrain of the entire world at all times. Otherwise, only the terrain of the surrounding cells is loaded. .. note:: When enabling distant terrain, make sure the 'viewing distance' in the camera section is set to a larger value so - that you can actually see the additional terrain. + that you can actually see the additional terrain and objects. To avoid frame drops as the player moves around, nearby terrain pages are always preloaded in the background, regardless of the preloading settings in the 'Cells' section, but the preloading of terrain behind a door or a travel destination, for example, will still be controlled by cell preloading settings. -The distant terrain engine is currently considered experimental -and may receive updates and/or further configuration options in the future. -The glaring omission of non-terrain objects in the distance somewhat limits this setting's usefulness. +The distant terrain engine is currently considered experimental and may receive updates in the future. vertex lod mod -------------- @@ -101,3 +99,107 @@ max composite geometry size Controls the maximum size of simple composite geometry chunk in cell units. With small values there will more draw calls and small textures, but higher values create more overdraw (not every texture layer is used everywhere). + +object paging +------------- + +:Type: boolean +:Range: True/False +:Default: True + +Controls whether the engine will use paging (chunking) algorithms to load non-terrain objects +outside of the active cell grid. + +Depending on the settings below every object in the game world has a chance +to be batched and be visible in the game world, effectively allowing +the engine to render distant objects with a relatively low performance impact automatically. + +In general, an object is more likely to be batched if the number of the object's vertices +and the corresponding memory cost of merging the object is low compared to +the expected number of the draw calls that are going to be optimized out. +This memory cost and the saved number of draw calls shall be called +the "merging cost" and the "merging benefit" in the following documentation. + +Objects that are scripted to disappear from the game world +will be handled properly as long as their scripts have a chance to actually disable them. + +This setting has no effect if distant terrain is disabled. + +object paging active grid +------------------------- +:Type: boolean +:Range: True/False +:Default: False + +Controls whether the objects in the active cells use the mentioned paging algorithms. +Active grid paging significantly improves the framerate when your setup is CPU-limited. + +.. note:: + Given that only 8 light sources may affect an object at a time at the moment, + lighting issues arising due to merged objects being considered a single object + may disrupt your gameplay experience. + +object paging merge factor +-------------------------- +:Type: float +:Range: >0 +:Default: 250.0 + +Affects the likelyhood of objects being merged. +Higher values improve the framerate at the cost of memory. + +Technically this is implemented as a multiplier to the merging benefit, and since +an object has a lot of vertices, sometimes in terms of hundreds and thousands, +and doesn't often need as much draw calls to be rendered (typically that number is in 1 or 2 digits) +this value needs to be large enough, as this is what makes +the merging cost and the merging benefit actually comparable for the sake of paging. + +object paging min size +---------------------- +:Type: float +:Range: >0 +:Default: 0.01 + +Controls how large an object must be to be visible in the scene. +The object's size is divided by its distance to the camera +and the result of the division is compared with this value. +The smaller this value is, the more objects you will see in the scene. + +object paging min size merge factor +----------------------------------- +:Type: float +:Range: >0 +:Default: 0.3 + +This setting gives inexpensive objects a chance to be rendered from a greater distance +even if the engine would rather discard them according to the previous setting. + +It controls the factor that the minimum size is multiplied by +roughly according to the following formula: + + factor = merge cost * min size cost multiplier / merge benefit + + factor = factor + (1 - factor) * min size merge factor + +Since the larger this factor is, the smaller chance a large object has to be rendered, +decreasing this value makes more objects visible in the scene +without impacting the performance as dramatically as the minimum size setting. + +object paging min size cost multiplier +-------------------------------------- +:Type: float +:Range: >0 +:Default: 25.0 + +This setting adjusts the calculated cost of merging an object used in the mentioned functionality. +The larger this value is, the less expensive objects can be before they are discarded. +See the formula above to figure out the math. + +object paging debug batches +--------------------------- +:Type: boolean +:Range: True/False +:Default: False + +This debug setting allows you to see what objects have been merged in the scene +by making them colored randomly. From 62b0781f7dd59084c717d68803b900d963a9411c Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 25 Oct 2020 00:33:41 +0200 Subject: [PATCH 036/111] use std::optional instead of boost::optional --- apps/openmw/mwsound/regionsoundselector.cpp | 2 +- apps/openmw/mwsound/regionsoundselector.hpp | 2 +- .../detournavigator/asyncnavmeshupdater.cpp | 6 +++--- .../detournavigator/asyncnavmeshupdater.hpp | 6 +++--- .../detournavigator/cachedrecastmeshmanager.cpp | 4 ++-- .../detournavigator/cachedrecastmeshmanager.hpp | 4 ++-- .../findrandompointaroundcircle.cpp | 10 +++++----- .../findrandompointaroundcircle.hpp | 2 +- components/detournavigator/findsmoothpath.cpp | 6 +++--- components/detournavigator/findsmoothpath.hpp | 8 ++++---- components/detournavigator/navigator.cpp | 8 ++++---- components/detournavigator/navigator.hpp | 2 +- components/detournavigator/recastmeshmanager.cpp | 8 ++++---- components/detournavigator/recastmeshmanager.hpp | 4 ++-- components/detournavigator/settings.cpp | 4 ++-- components/detournavigator/settings.hpp | 2 +- .../tilecachedrecastmeshmanager.cpp | 16 ++++++++-------- .../tilecachedrecastmeshmanager.hpp | 6 +++--- 18 files changed, 50 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwsound/regionsoundselector.cpp b/apps/openmw/mwsound/regionsoundselector.cpp index ac5f66721..c95ed9c72 100644 --- a/apps/openmw/mwsound/regionsoundselector.cpp +++ b/apps/openmw/mwsound/regionsoundselector.cpp @@ -18,7 +18,7 @@ namespace MWSound } } - boost::optional RegionSoundSelector::getNextRandom(float duration, const std::string& regionName, + std::optional RegionSoundSelector::getNextRandom(float duration, const std::string& regionName, const MWBase::World& world) { mTimePassed += duration; diff --git a/apps/openmw/mwsound/regionsoundselector.hpp b/apps/openmw/mwsound/regionsoundselector.hpp index 00a2d5ca8..0dce5a7aa 100644 --- a/apps/openmw/mwsound/regionsoundselector.hpp +++ b/apps/openmw/mwsound/regionsoundselector.hpp @@ -15,7 +15,7 @@ namespace MWSound class RegionSoundSelector { public: - boost::optional getNextRandom(float duration, const std::string& regionName, + std::optional getNextRandom(float duration, const std::string& regionName, const MWBase::World& world); private: diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 878b8130a..1ac928f07 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -198,7 +198,7 @@ namespace DetourNavigator return isSuccess(status); } - boost::optional AsyncNavMeshUpdater::getNextJob() + std::optional AsyncNavMeshUpdater::getNextJob() { std::unique_lock lock(mMutex); @@ -217,7 +217,7 @@ namespace DetourNavigator mFirstStart.lock()->reset(); if (mJobs.empty() && getTotalThreadJobsUnsafe() == 0) mDone.notify_all(); - return boost::none; + return std::nullopt; } Log(Debug::Debug) << "Got " << mJobs.size() << " navigator jobs and " @@ -239,7 +239,7 @@ namespace DetourNavigator } } - boost::optional AsyncNavMeshUpdater::getJob(Jobs& jobs, Pushed& pushed, bool changeLastUpdate) + std::optional AsyncNavMeshUpdater::getJob(Jobs& jobs, Pushed& pushed, bool changeLastUpdate) { const auto now = std::chrono::steady_clock::now(); diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index 26f886512..fcdc0f21a 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -106,7 +106,7 @@ namespace DetourNavigator Jobs mJobs; std::map> mPushed; Misc::ScopeGuarded mPlayerTile; - Misc::ScopeGuarded> mFirstStart; + Misc::ScopeGuarded> mFirstStart; NavMeshTilesCache mNavMeshTilesCache; Misc::ScopeGuarded>> mProcessingTiles; std::map> mLastUpdates; @@ -117,9 +117,9 @@ namespace DetourNavigator bool processJob(const Job& job); - boost::optional getNextJob(); + std::optional getNextJob(); - boost::optional getJob(Jobs& jobs, Pushed& pushed, bool changeLastUpdate); + std::optional getJob(Jobs& jobs, Pushed& pushed, bool changeLastUpdate); void postThreadJob(Job&& job, Queue& queue); diff --git a/components/detournavigator/cachedrecastmeshmanager.cpp b/components/detournavigator/cachedrecastmeshmanager.cpp index da0f6c874..90b426610 100644 --- a/components/detournavigator/cachedrecastmeshmanager.cpp +++ b/components/detournavigator/cachedrecastmeshmanager.cpp @@ -25,7 +25,7 @@ namespace DetourNavigator return true; } - boost::optional CachedRecastMeshManager::removeObject(const ObjectId id) + std::optional CachedRecastMeshManager::removeObject(const ObjectId id) { const auto object = mImpl.removeObject(id); if (object) @@ -42,7 +42,7 @@ namespace DetourNavigator return true; } - boost::optional CachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition) + std::optional CachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition) { const auto water = mImpl.removeWater(cellPosition); if (water) diff --git a/components/detournavigator/cachedrecastmeshmanager.hpp b/components/detournavigator/cachedrecastmeshmanager.hpp index 5efb315e8..8ce2e48c2 100644 --- a/components/detournavigator/cachedrecastmeshmanager.hpp +++ b/components/detournavigator/cachedrecastmeshmanager.hpp @@ -19,9 +19,9 @@ namespace DetourNavigator bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const btTransform& transform); - boost::optional removeWater(const osg::Vec2i& cellPosition); + std::optional removeWater(const osg::Vec2i& cellPosition); - boost::optional removeObject(const ObjectId id); + std::optional removeObject(const ObjectId id); std::shared_ptr getMesh(); diff --git a/components/detournavigator/findrandompointaroundcircle.cpp b/components/detournavigator/findrandompointaroundcircle.cpp index 263dba68e..f2e815c91 100644 --- a/components/detournavigator/findrandompointaroundcircle.cpp +++ b/components/detournavigator/findrandompointaroundcircle.cpp @@ -10,12 +10,12 @@ namespace DetourNavigator { - boost::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, + std::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const Settings& settings) { dtNavMeshQuery navMeshQuery; if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes)) - return boost::optional(); + return std::optional(); dtQueryFilter queryFilter; queryFilter.setIncludeFlags(includeFlags); @@ -31,7 +31,7 @@ namespace DetourNavigator } if (startRef == 0) - return boost::optional(); + return std::optional(); dtPolyRef resultRef = 0; osg::Vec3f resultPosition; @@ -39,8 +39,8 @@ namespace DetourNavigator []() { return Misc::Rng::rollProbability(); }, &resultRef, resultPosition.ptr()); if (resultRef == 0) - return boost::optional(); + return std::optional(); - return boost::optional(resultPosition); + return std::optional(resultPosition); } } diff --git a/components/detournavigator/findrandompointaroundcircle.hpp b/components/detournavigator/findrandompointaroundcircle.hpp index 841508f67..fb0b5c5ba 100644 --- a/components/detournavigator/findrandompointaroundcircle.hpp +++ b/components/detournavigator/findrandompointaroundcircle.hpp @@ -13,7 +13,7 @@ namespace DetourNavigator { struct Settings; - boost::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, + std::optional findRandomPointAroundCircle(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const Settings& settings); } diff --git a/components/detournavigator/findsmoothpath.cpp b/components/detournavigator/findsmoothpath.cpp index ef0341d72..8e443def9 100644 --- a/components/detournavigator/findsmoothpath.cpp +++ b/components/detournavigator/findsmoothpath.cpp @@ -103,7 +103,7 @@ namespace DetourNavigator return result; } - boost::optional getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, + std::optional getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const float minTargetDist, const std::vector& path) { // Find steer target. @@ -117,7 +117,7 @@ namespace DetourNavigator steerPathFlags.data(), steerPathPolys.data(), &nsteerPath, MAX_STEER_POINTS); assert(nsteerPath >= 0); if (!nsteerPath) - return boost::none; + return std::nullopt; // Find vertex far enough to steer to. std::size_t ns = 0; @@ -131,7 +131,7 @@ namespace DetourNavigator } // Failed to find good point to steer to. if (ns >= static_cast(nsteerPath)) - return boost::none; + return std::nullopt; dtVcopy(result.steerPos.ptr(), &steerPath[ns * 3]); result.steerPos.y() = startPos[1]; diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index f1de71207..23609ab09 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -58,7 +58,7 @@ namespace DetourNavigator dtPolyRef steerPosRef; }; - boost::optional getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, + std::optional getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const float minTargetDist, const std::vector& path); template @@ -111,7 +111,7 @@ namespace DetourNavigator std::vector mVisited; }; - inline boost::optional moveAlongSurface(const dtNavMeshQuery& navMeshQuery, + inline std::optional moveAlongSurface(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& filter, const std::size_t maxVisitedSize) { @@ -128,7 +128,7 @@ namespace DetourNavigator return {std::move(result)}; } - inline boost::optional> findPath(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef, + inline std::optional> findPath(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef, const dtPolyRef endRef, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& queryFilter, const std::size_t maxSize) { @@ -144,7 +144,7 @@ namespace DetourNavigator return {std::move(result)}; } - inline boost::optional getPolyHeight(const dtNavMeshQuery& navMeshQuery, const dtPolyRef ref, const osg::Vec3f& pos) + inline std::optional getPolyHeight(const dtNavMeshQuery& navMeshQuery, const dtPolyRef ref, const osg::Vec3f& pos) { float result = 0.0f; const auto status = navMeshQuery.getPolyHeight(ref, pos.ptr(), &result); diff --git a/components/detournavigator/navigator.cpp b/components/detournavigator/navigator.cpp index a58a4f876..658e539ad 100644 --- a/components/detournavigator/navigator.cpp +++ b/components/detournavigator/navigator.cpp @@ -3,18 +3,18 @@ namespace DetourNavigator { - boost::optional Navigator::findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents, + std::optional Navigator::findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) const { const auto navMesh = getNavMesh(agentHalfExtents); if (!navMesh) - return boost::optional(); + return std::optional(); const auto settings = getSettings(); const auto result = DetourNavigator::findRandomPointAroundCircle(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, start), toNavMeshCoordinates(settings, maxRadius), includeFlags, settings); if (!result) - return boost::optional(); - return boost::optional(fromNavMeshCoordinates(settings, *result)); + return std::optional(); + return std::optional(fromNavMeshCoordinates(settings, *result)); } } diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 3e7f54178..a79aa59d4 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -220,7 +220,7 @@ namespace DetourNavigator * @param includeFlags setup allowed surfaces for actor to walk. * @return not empty optional with position if point is found and empty optional if point is not found. */ - boost::optional findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents, + std::optional findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents, const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) const; virtual RecastMeshTiles getRecastMeshTiles() = 0; diff --git a/components/detournavigator/recastmeshmanager.cpp b/components/detournavigator/recastmeshmanager.cpp index 05f250596..3796c9816 100644 --- a/components/detournavigator/recastmeshmanager.cpp +++ b/components/detournavigator/recastmeshmanager.cpp @@ -34,11 +34,11 @@ namespace DetourNavigator return true; } - boost::optional RecastMeshManager::removeObject(const ObjectId id) + std::optional RecastMeshManager::removeObject(const ObjectId id) { const auto object = mObjects.find(id); if (object == mObjects.end()) - return boost::none; + return std::nullopt; const RemovedRecastMeshObject result {object->second->getShape(), object->second->getTransform()}; mObjectsOrder.erase(object->second); mObjects.erase(object); @@ -59,11 +59,11 @@ namespace DetourNavigator return true; } - boost::optional RecastMeshManager::removeWater(const osg::Vec2i& cellPosition) + std::optional RecastMeshManager::removeWater(const osg::Vec2i& cellPosition) { const auto water = mWater.find(cellPosition); if (water == mWater.end()) - return boost::none; + return std::nullopt; ++mRevision; const auto result = *water->second; mWaterOrder.erase(water->second); diff --git a/components/detournavigator/recastmeshmanager.hpp b/components/detournavigator/recastmeshmanager.hpp index f1870ec6b..47f5f5190 100644 --- a/components/detournavigator/recastmeshmanager.hpp +++ b/components/detournavigator/recastmeshmanager.hpp @@ -43,9 +43,9 @@ namespace DetourNavigator bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const btTransform& transform); - boost::optional removeWater(const osg::Vec2i& cellPosition); + std::optional removeWater(const osg::Vec2i& cellPosition); - boost::optional removeObject(const ObjectId id); + std::optional removeObject(const ObjectId id); std::shared_ptr getMesh(); diff --git a/components/detournavigator/settings.cpp b/components/detournavigator/settings.cpp index 49aec41ff..977b80cf5 100644 --- a/components/detournavigator/settings.cpp +++ b/components/detournavigator/settings.cpp @@ -4,10 +4,10 @@ namespace DetourNavigator { - boost::optional makeSettingsFromSettingsManager() + std::optional makeSettingsFromSettingsManager() { if (!::Settings::Manager::getBool("enable", "Navigator")) - return boost::optional(); + return std::optional(); Settings navigatorSettings; diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index 939d825a5..290e763a9 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -42,7 +42,7 @@ namespace DetourNavigator std::chrono::milliseconds mMinUpdateInterval; }; - boost::optional makeSettingsFromSettingsManager(); + std::optional makeSettingsFromSettingsManager(); } #endif diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 9debe5dea..fddaa88f1 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -31,12 +31,12 @@ namespace DetourNavigator return result; } - boost::optional TileCachedRecastMeshManager::removeObject(const ObjectId id) + std::optional TileCachedRecastMeshManager::removeObject(const ObjectId id) { const auto object = mObjectsTilesPositions.find(id); if (object == mObjectsTilesPositions.end()) - return boost::none; - boost::optional result; + return std::nullopt; + std::optional result; { auto tiles = mTiles.lock(); for (const auto& tilePosition : object->second) @@ -100,12 +100,12 @@ namespace DetourNavigator return result; } - boost::optional TileCachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition) + std::optional TileCachedRecastMeshManager::removeWater(const osg::Vec2i& cellPosition) { const auto object = mWaterTilesPositions.find(cellPosition); if (object == mWaterTilesPositions.end()) - return boost::none; - boost::optional result; + return std::nullopt; + std::optional result; for (const auto& tilePosition : object->second) { const auto tiles = mTiles.lock(); @@ -168,12 +168,12 @@ namespace DetourNavigator return tile != tiles.end() && tile->second.updateObject(id, transform, areaType); } - boost::optional TileCachedRecastMeshManager::removeTile(const ObjectId id, + std::optional TileCachedRecastMeshManager::removeTile(const ObjectId id, const TilePosition& tilePosition, std::map& tiles) { const auto tile = tiles.find(tilePosition); if (tile == tiles.end()) - return boost::optional(); + return std::optional(); const auto tileResult = tile->second.removeObject(id); if (tile->second.isEmpty()) { diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index 557cde1be..fa192bd73 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -69,11 +69,11 @@ namespace DetourNavigator return changed; } - boost::optional removeObject(const ObjectId id); + std::optional removeObject(const ObjectId id); bool addWater(const osg::Vec2i& cellPosition, const int cellSize, const btTransform& transform); - boost::optional removeWater(const osg::Vec2i& cellPosition); + std::optional removeWater(const osg::Vec2i& cellPosition); std::shared_ptr getMesh(const TilePosition& tilePosition); @@ -103,7 +103,7 @@ namespace DetourNavigator bool updateTile(const ObjectId id, const btTransform& transform, const AreaType areaType, const TilePosition& tilePosition, std::map& tiles); - boost::optional removeTile(const ObjectId id, const TilePosition& tilePosition, + std::optional removeTile(const ObjectId id, const TilePosition& tilePosition, std::map& tiles); }; } From f6bead88a989a617eb7dccd52d53e7c93fbd81a2 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 25 Oct 2020 00:58:44 +0200 Subject: [PATCH 037/111] purge boost/optional.hpp headers --- apps/openmw/mwsound/regionsoundselector.hpp | 3 +-- apps/openmw_test_suite/detournavigator/navigator.cpp | 3 --- components/detournavigator/asyncnavmeshupdater.hpp | 2 -- components/detournavigator/cachedrecastmeshmanager.hpp | 2 -- components/detournavigator/findrandompointaroundcircle.hpp | 3 +-- components/detournavigator/findsmoothpath.hpp | 2 -- components/detournavigator/recastmeshmanager.hpp | 2 -- components/detournavigator/settings.hpp | 5 ++--- 8 files changed, 4 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwsound/regionsoundselector.hpp b/apps/openmw/mwsound/regionsoundselector.hpp index 0dce5a7aa..ede42c294 100644 --- a/apps/openmw/mwsound/regionsoundselector.hpp +++ b/apps/openmw/mwsound/regionsoundselector.hpp @@ -1,8 +1,7 @@ #ifndef GAME_SOUND_REGIONSOUNDSELECTOR_H #define GAME_SOUND_REGIONSOUNDSELECTOR_H -#include - +#include #include namespace MWBase diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index 5a92d5d28..ae345d187 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -8,12 +8,9 @@ #include #include -#include - #include #include -#include #include MATCHER_P3(Vec3fEq, x, y, z, "") diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index fcdc0f21a..53e7fd7c1 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -9,8 +9,6 @@ #include -#include - #include #include #include diff --git a/components/detournavigator/cachedrecastmeshmanager.hpp b/components/detournavigator/cachedrecastmeshmanager.hpp index 8ce2e48c2..54574aa99 100644 --- a/components/detournavigator/cachedrecastmeshmanager.hpp +++ b/components/detournavigator/cachedrecastmeshmanager.hpp @@ -3,8 +3,6 @@ #include "recastmeshmanager.hpp" -#include - namespace DetourNavigator { class CachedRecastMeshManager diff --git a/components/detournavigator/findrandompointaroundcircle.hpp b/components/detournavigator/findrandompointaroundcircle.hpp index fb0b5c5ba..d0dc2bbbc 100644 --- a/components/detournavigator/findrandompointaroundcircle.hpp +++ b/components/detournavigator/findrandompointaroundcircle.hpp @@ -3,8 +3,7 @@ #include "flags.hpp" -#include - +#include #include class dtNavMesh; diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 23609ab09..2fc39d63f 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -18,8 +18,6 @@ #include -#include - #include #include diff --git a/components/detournavigator/recastmeshmanager.hpp b/components/detournavigator/recastmeshmanager.hpp index 47f5f5190..3e9b2b1c3 100644 --- a/components/detournavigator/recastmeshmanager.hpp +++ b/components/detournavigator/recastmeshmanager.hpp @@ -9,8 +9,6 @@ #include -#include - #include #include #include diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index 290e763a9..d73087b21 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -1,10 +1,9 @@ #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGS_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGS_H -#include - -#include #include +#include +#include namespace DetourNavigator { From 4a54d375cc5091ffbcfcd76aa6001638a964ed34 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 25 Oct 2020 01:31:05 +0200 Subject: [PATCH 038/111] add cassert for windows --- components/detournavigator/findsmoothpath.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 2fc39d63f..dcdddce8a 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -19,7 +19,7 @@ #include #include - +#include #include class dtNavMesh; From 0e0c091e15c4ae7156762645c90fd7181b8ef73d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 25 Oct 2020 01:34:04 +0200 Subject: [PATCH 039/111] add more optionals and casserts for windows --- components/detournavigator/recastmeshbuilder.cpp | 1 + components/detournavigator/recastmeshmanager.hpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index 59f60394d..ee014b932 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -17,6 +17,7 @@ #include #include +#include #include namespace DetourNavigator diff --git a/components/detournavigator/recastmeshmanager.hpp b/components/detournavigator/recastmeshmanager.hpp index 3e9b2b1c3..5b568e004 100644 --- a/components/detournavigator/recastmeshmanager.hpp +++ b/components/detournavigator/recastmeshmanager.hpp @@ -9,9 +9,10 @@ #include +#include #include +#include #include -#include class btCollisionShape; From eebb320916f1a96aa02576487c478063ab09d2c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 25 Oct 2020 12:20:14 +0100 Subject: [PATCH 040/111] Wait for the previous sound to stop --- CHANGELOG.md | 1 + apps/openmw/mwsound/regionsoundselector.cpp | 10 +++------- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +++- apps/openmw/mwsound/soundmanagerimp.hpp | 2 ++ 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3c5fe557..0d5132207 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ Bug #5639: Tooltips cover Messageboxes Bug #5644: Summon effects running on the player during game initialization cause crashes Bug #5656: Sneaking characters block hits while standing + Bug #5661: Region sounds don't play at the right interval Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging Feature #2404: Levelled List can not be placed into a container diff --git a/apps/openmw/mwsound/regionsoundselector.cpp b/apps/openmw/mwsound/regionsoundselector.cpp index 55afd6ab6..df2125e6d 100644 --- a/apps/openmw/mwsound/regionsoundselector.cpp +++ b/apps/openmw/mwsound/regionsoundselector.cpp @@ -20,10 +20,9 @@ namespace MWSound } RegionSoundSelector::RegionSoundSelector() - { - mMinTimeBetweenSounds = Fallback::Map::getFloat("Weather_Minimum_Time_Between_Environmental_Sounds"); - mMaxTimeBetweenSounds = Fallback::Map::getFloat("Weather_Maximum_Time_Between_Environmental_Sounds"); - } + : mMinTimeBetweenSounds(Fallback::Map::getFloat("Weather_Minimum_Time_Between_Environmental_Sounds")) + , mMaxTimeBetweenSounds(Fallback::Map::getFloat("Weather_Maximum_Time_Between_Environmental_Sounds")) + {} boost::optional RegionSoundSelector::getNextRandom(float duration, const std::string& regionName, const MWBase::World& world) @@ -71,9 +70,6 @@ namespace MWSound if (it == region->mSoundList.end()) return {}; - // TODO - // mTimeToNextEnvSound += soundDuration - return it->mSound; } } diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 17aa184a7..d33b3d26e 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -895,9 +895,11 @@ namespace MWSound if (!cell->isExterior()) return; + if (mCurrentRegionSound && mOutput->isSoundPlaying(mCurrentRegionSound)) + return; if (const auto next = mRegionSoundSelector.getNextRandom(duration, cell->mRegion, *world)) - playSound(*next, 1.0f, 1.0f); + mCurrentRegionSound = playSound(*next, 1.0f, 1.0f); } void SoundManager::updateWaterSound() diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 37b099c02..0c82528b5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -120,6 +120,8 @@ namespace MWSound const ESM::Cell *mLastCell = nullptr; + Sound* mCurrentRegionSound; + Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); Sound_Buffer *lookupSound(const std::string &soundId) const; From 71056c601468da5ac86f9ff1745c63accb137dc3 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 25 Oct 2020 14:24:56 +0300 Subject: [PATCH 041/111] Clean up palettized NiPixelData loading --- components/nifosg/nifloader.cpp | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 65f62346d..0807abd11 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1401,32 +1401,16 @@ namespace NifOsg } // We're going to convert the indices that pixel data contains // into real colors using the palette. - const std::vector& palette = pixelData->palette->colors; - if (pixelData->fmt == Nif::NiPixelData::NIPXFMT_PAL8) + const auto& palette = pixelData->palette->colors; + const int numChannels = pixelformat == GL_RGBA ? 4 : 3; + unsigned char* data = new unsigned char[pixels.size() * numChannels]; + unsigned char* pixel = data; + for (unsigned char index : pixels) { - unsigned char* data = new unsigned char[pixels.size() * 3]; - for (size_t i = 0; i < pixels.size(); i++) - { - unsigned int color = palette[pixels[i]]; - data[i * 3 + 0] = (color >> 0) & 0xFF; - data[i * 3 + 1] = (color >> 8) & 0xFF; - data[i * 3 + 2] = (color >> 16) & 0xFF; - } - image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE); - } - else // if (fmt = NIPXFMT_PALA8) - { - unsigned char* data = new unsigned char[pixels.size() * 4]; - for (size_t i = 0; i < pixels.size(); i++) - { - unsigned int color = palette[pixels[i]]; - data[i * 4 + 0] = (color >> 0) & 0xFF; - data[i * 4 + 1] = (color >> 8) & 0xFF; - data[i * 4 + 2] = (color >> 16) & 0xFF; - data[i * 4 + 3] = (color >> 24) & 0xFF; - } - image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE); + memcpy(pixel, &palette[index], sizeof(unsigned char) * numChannels); + pixel += numChannels; } + image->setImage(width, height, 1, pixelformat, pixelformat, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE); break; } default: From 71e78c66cda7eeadb3bb2118683a00621201c319 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 25 Oct 2020 14:33:23 +0100 Subject: [PATCH 042/111] Re-add missing includes removed in 5a824d03334240cc01dfe65a13c627bad5f7b2f7 --- components/compiler/controlparser.cpp | 1 + components/compiler/exprparser.cpp | 2 ++ components/compiler/generator.cpp | 1 + components/compiler/output.cpp | 1 + components/compiler/stringparser.cpp | 1 + 5 files changed, 6 insertions(+) diff --git a/components/compiler/controlparser.cpp b/components/compiler/controlparser.cpp index 634180f62..ec69fffa2 100644 --- a/components/compiler/controlparser.cpp +++ b/components/compiler/controlparser.cpp @@ -1,6 +1,7 @@ #include "controlparser.hpp" #include +#include #include #include "scanner.hpp" diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 7c0635d76..0afe3de6d 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 717f05980..34da1c412 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "literals.hpp" diff --git a/components/compiler/output.cpp b/components/compiler/output.cpp index a78c44b8d..785b2ce84 100644 --- a/components/compiler/output.cpp +++ b/components/compiler/output.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "locals.hpp" diff --git a/components/compiler/stringparser.cpp b/components/compiler/stringparser.cpp index f4f612d6f..1bacf7941 100644 --- a/components/compiler/stringparser.cpp +++ b/components/compiler/stringparser.cpp @@ -1,6 +1,7 @@ #include "stringparser.hpp" #include +#include #include From 660df19ff7c346843697958f9a88e3454afc6235 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 25 Oct 2020 18:22:16 +0400 Subject: [PATCH 043/111] Allow to assign custom shaders to nodes --- components/resource/scenemanager.cpp | 8 ++++---- components/resource/scenemanager.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index b87446351..571ea6d0d 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -242,9 +242,9 @@ namespace Resource return mForceShaders; } - void SceneManager::recreateShaders(osg::ref_ptr node) + void SceneManager::recreateShaders(osg::ref_ptr node, const std::string& shaderPrefix) { - osg::ref_ptr shaderVisitor(createShaderVisitor()); + osg::ref_ptr shaderVisitor(createShaderVisitor(shaderPrefix)); shaderVisitor->setAllowedToModifyStateSets(false); node->accept(*shaderVisitor); } @@ -761,9 +761,9 @@ namespace Resource stats->setAttribute(frameNumber, "Node Instance", mInstanceCache->getCacheSize()); } - Shader::ShaderVisitor *SceneManager::createShaderVisitor() + Shader::ShaderVisitor *SceneManager::createShaderVisitor(const std::string& shaderPrefix) { - Shader::ShaderVisitor* shaderVisitor = new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl"); + Shader::ShaderVisitor* shaderVisitor = new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, shaderPrefix+"_vertex.glsl", shaderPrefix+"_fragment.glsl"); shaderVisitor->setForceShaders(mForceShaders); shaderVisitor->setAutoUseNormalMaps(mAutoUseNormalMaps); shaderVisitor->setNormalMapPattern(mNormalMapPattern); diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index 3a72caf6a..0ee32a9b7 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -51,7 +51,7 @@ namespace Resource Shader::ShaderManager& getShaderManager(); /// Re-create shaders for this node, need to call this if texture stages or vertex color mode have changed. - void recreateShaders(osg::ref_ptr node); + void recreateShaders(osg::ref_ptr node, const std::string& shaderPrefix = "objects"); /// @see ShaderVisitor::setForceShaders void setForceShaders(bool force); @@ -146,7 +146,7 @@ namespace Resource private: - Shader::ShaderVisitor* createShaderVisitor(); + Shader::ShaderVisitor* createShaderVisitor(const std::string& shaderPrefix = "objects"); std::unique_ptr mShaderManager; bool mForceShaders; From 4032b754e40bf9865ce7924063caa892424df68f Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 25 Oct 2020 22:43:10 +0100 Subject: [PATCH 044/111] set minimal boost version; remove #ifdef boost version checks --- CMakeLists.txt | 2 +- apps/mwiniimporter/importer.cpp | 7 ------- apps/openmw/main.cpp | 16 ---------------- components/fallback/validate.cpp | 4 ---- 4 files changed, 1 insertion(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82d6694dc..37696f44c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -308,7 +308,7 @@ endif() set(Boost_NO_BOOST_CMAKE ON) -find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) +find_package(Boost 1.6.2 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(MyGUI 3.2.2 REQUIRED) find_package(SDL2 2.0.9 REQUIRED) find_package(OpenAL REQUIRED) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 600b4917a..4670e8948 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -985,14 +985,7 @@ std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename std::time_t writeTime(defaultTime); if (boost::filesystem::exists(filename)) { - // FixMe: remove #if when Boost dependency for Linux builds updated - // This allows Linux to build until then -#if (BOOST_VERSION >= 104800) - // need to resolve any symlinks so that we get time of file, not symlink boost::filesystem::path resolved = boost::filesystem::canonical(filename); -#else - boost::filesystem::path resolved = filename; -#endif writeTime = boost::filesystem::last_write_time(resolved); // print timestamp diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index adf4bf18c..d3d984901 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -21,22 +21,6 @@ #include #endif -/** - * Workaround for problems with whitespaces in paths in older versions of Boost library - */ -#if (BOOST_VERSION <= 104600) -namespace boost -{ - -template<> -inline boost::filesystem::path lexical_cast(const std::string& arg) -{ - return boost::filesystem::path(arg); -} - -} /* namespace boost */ -#endif /* (BOOST_VERSION <= 104600) */ - using namespace Fallback; diff --git a/components/fallback/validate.cpp b/components/fallback/validate.cpp index 98c6c39fd..982c709af 100644 --- a/components/fallback/validate.cpp +++ b/components/fallback/validate.cpp @@ -14,11 +14,7 @@ void Fallback::validate(boost::any& v, std::vector const& tokens, F std::string temp = Files::EscapeHashString::processString(token); size_t sep = temp.find(","); if (sep < 1 || sep == temp.length() - 1 || sep == std::string::npos) -#if (BOOST_VERSION < 104200) - throw boost::program_options::validation_error("invalid value"); -#else throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); -#endif std::string key(temp.substr(0, sep)); std::string value(temp.substr(sep + 1)); From 4fc5e22e9e58857b4be89cbd17c2db7a52f24cc8 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Mon, 26 Oct 2020 02:36:32 +0300 Subject: [PATCH 045/111] NIF fixes and cleanup Get rid of NodeIndexHolder Use unsigned 32-bit type for NIF record index Fix calculation of the number of UV sets --- components/nif/data.cpp | 17 ++++++------- components/nif/niffile.cpp | 8 +++--- components/nif/record.hpp | 6 ++--- components/nifosg/nifloader.cpp | 3 +-- components/nifosg/nodeindexholder.hpp | 35 --------------------------- components/nifosg/particle.cpp | 23 +++++++----------- components/nifosg/particle.hpp | 4 +-- components/sceneutil/serialize.cpp | 1 - 8 files changed, 27 insertions(+), 70 deletions(-) delete mode 100644 components/nifosg/nodeindexholder.hpp diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 91b3beba4..5b0b99c53 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -67,19 +67,18 @@ void NiGeometryData::read(NIFStream *nif) if (nif->getBoolean()) nif->getVector4s(colors, verts); - // Only the first 6 bits are used as a count. I think the rest are - // flags of some sort. unsigned int numUVs = dataFlags; if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0)) - { numUVs = nif->getUShort(); - // In Morrowind this field only corresponds to the number of UV sets. - // NifTools research is inaccurate. - if (nif->getVersion() > NIFFile::NIFVersion::VER_MW) - numUVs &= 0x3f; + + // In Morrowind this field only corresponds to the number of UV sets. + // In later games only the first 6 bits are used as a count and the rest are flags. + if (nif->getVersion() > NIFFile::NIFVersion::VER_MW) + { + numUVs &= 0x3f; + if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 0) + numUVs &= 0x1; } - if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 0) - numUVs &= 0x1; bool hasUVs = true; if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 8d65753d2..5642dfebb 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -160,7 +160,7 @@ void NIFFile::parse(Files::IStreamPtr stream) userVer = nif.getUInt(); // Number of records - size_t recNum = nif.getUInt(); + unsigned int recNum = nif.getUInt(); records.resize(recNum); // Bethesda stream header @@ -212,7 +212,7 @@ void NIFFile::parse(Files::IStreamPtr stream) } const bool hasRecordSeparators = ver >= NIFStream::generateVersion(10,0,0,0) && ver < NIFStream::generateVersion(10,2,0,0); - for(size_t i = 0;i < recNum;i++) + for (unsigned int i = 0; i < recNum; i++) { Record *r = nullptr; @@ -253,11 +253,11 @@ void NIFFile::parse(Files::IStreamPtr stream) r->read(&nif); } - size_t rootNum = nif.getUInt(); + unsigned int rootNum = nif.getUInt(); roots.resize(rootNum); //Determine which records are roots - for(size_t i = 0;i < rootNum;i++) + for (unsigned int i = 0; i < rootNum; i++) { int idx = nif.getInt(); if (idx >= 0 && idx < int(records.size())) diff --git a/components/nif/record.hpp b/components/nif/record.hpp index f9bb613a0..eb26b0cce 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -116,11 +116,11 @@ enum RecordType struct Record { // Record type and type name - int recType; + int recType{RC_MISSING}; std::string recName; - size_t recIndex; + unsigned int recIndex{~0u}; - Record() : recType(RC_MISSING), recIndex(~(size_t)0) {} + Record() = default; /// Parses the record from file virtual void read(NIFStream *nif) = 0; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 0807abd11..7a592fb4a 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -43,7 +43,6 @@ #include #include "matrixtransform.hpp" -#include "nodeindexholder.hpp" #include "particle.hpp" namespace @@ -527,7 +526,7 @@ namespace NifOsg // - finding the correct emitter node for a particle system // - establishing connections to the animated collision shapes, which are handled in a separate loader // - finding a random child NiNode in NiBspArrayController - node->getOrCreateUserDataContainer()->addUserObject(new NodeIndexHolder(nifNode->recIndex)); + node->setUserValue("recIndex", nifNode->recIndex); for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next) { diff --git a/components/nifosg/nodeindexholder.hpp b/components/nifosg/nodeindexholder.hpp deleted file mode 100644 index e7d4f0db3..000000000 --- a/components/nifosg/nodeindexholder.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef OPENMW_COMPONENTS_NIFOSG_NODEINDEXHOLDER_H -#define OPENMW_COMPONENTS_NIFOSG_NODEINDEXHOLDER_H - -#include - -namespace NifOsg -{ - - class NodeIndexHolder : public osg::Object - { - public: - NodeIndexHolder() = default; - NodeIndexHolder(int index) - : mIndex(index) - { - } - NodeIndexHolder(const NodeIndexHolder& copy, const osg::CopyOp& copyop) - : Object(copy, copyop) - , mIndex(copy.mIndex) - { - } - - META_Object(NifOsg, NodeIndexHolder) - - int getIndex() const { return mIndex; } - - private: - - // NIF record index - int mIndex{0}; - }; - -} - -#endif diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index 0cbc3f22b..b223b23e3 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -11,8 +11,6 @@ #include #include -#include "nodeindexholder.hpp" - namespace NifOsg { @@ -357,7 +355,7 @@ void Emitter::emitParticles(double dt) } } -FindGroupByRecIndex::FindGroupByRecIndex(int recIndex) +FindGroupByRecIndex::FindGroupByRecIndex(unsigned int recIndex) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) , mFound(nullptr) , mRecIndex(recIndex) @@ -381,19 +379,16 @@ void FindGroupByRecIndex::apply(osg::Geometry &node) void FindGroupByRecIndex::applyNode(osg::Node &searchNode) { - if (searchNode.getUserDataContainer() && searchNode.getUserDataContainer()->getNumUserObjects()) + unsigned int recIndex; + if (searchNode.getUserValue("recIndex", recIndex) && mRecIndex == recIndex) { - NodeIndexHolder* holder = dynamic_cast(searchNode.getUserDataContainer()->getUserObject(0)); - if (holder && holder->getIndex() == mRecIndex) - { - osg::Group* group = searchNode.asGroup(); - if (!group) - group = searchNode.getParent(0); + osg::Group* group = searchNode.asGroup(); + if (!group) + group = searchNode.getParent(0); - mFound = group; - mFoundPath = getNodePath(); - return; - } + mFound = group; + mFoundPath = getNodePath(); + return; } traverse(searchNode); } diff --git a/components/nifosg/particle.hpp b/components/nifosg/particle.hpp index 724a8a721..dd89f4501 100644 --- a/components/nifosg/particle.hpp +++ b/components/nifosg/particle.hpp @@ -204,7 +204,7 @@ namespace NifOsg class FindGroupByRecIndex : public osg::NodeVisitor { public: - FindGroupByRecIndex(int recIndex); + FindGroupByRecIndex(unsigned int recIndex); void apply(osg::Node &node) override; @@ -218,7 +218,7 @@ namespace NifOsg osg::Group* mFound; osg::NodePath mFoundPath; private: - int mRecIndex; + unsigned int mRecIndex; }; // Subclass emitter to support randomly choosing one of the child node's transforms for the emit position of new particles. diff --git a/components/sceneutil/serialize.cpp b/components/sceneutil/serialize.cpp index 9e7aa83f6..d03612fc1 100644 --- a/components/sceneutil/serialize.cpp +++ b/components/sceneutil/serialize.cpp @@ -144,7 +144,6 @@ void registerSerializers() "NifOsg::UpdateMorphGeometry", "NifOsg::UVController", "NifOsg::VisController", - "NifOsg::NodeIndexHolder", "osgMyGUI::Drawable", "osg::DrawCallback", "osgOQ::ClearQueriesCallback", From 7e521788e9f2c5acb587af85e946e93f5e4d21f3 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Mon, 26 Oct 2020 15:09:31 +0300 Subject: [PATCH 046/111] Try to fix build --- components/nifosg/particle.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index b223b23e3..2cb0ffc62 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include From 435b2e37f840f7265f22908ee14bd4c9a3201578 Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 25 Oct 2020 22:33:19 +0100 Subject: [PATCH 047/111] Allow to display collision points in the debug viewer --- apps/openmw/mwphysics/physicssystem.cpp | 22 +++++---- apps/openmw/mwphysics/physicssystem.hpp | 2 + apps/openmw/mwrender/bulletdebugdraw.cpp | 57 +++++++++++++++++------- apps/openmw/mwrender/bulletdebugdraw.hpp | 18 ++++++++ 4 files changed, 74 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index a349ee244..8f169dfe3 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1,5 +1,8 @@ #include "physicssystem.hpp" +#include +#include +#include #include #include @@ -90,6 +93,7 @@ namespace MWPhysics } mTaskScheduler = std::make_unique(mPhysicsDt, mCollisionWorld); + mDebugDrawer = std::make_unique(mParentNode, mCollisionWorld.get()); } PhysicsSystem::~PhysicsSystem() @@ -124,14 +128,8 @@ namespace MWPhysics { mDebugDrawEnabled = !mDebugDrawEnabled; - if (mDebugDrawEnabled && !mDebugDrawer) - { - mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mCollisionWorld.get())); - mCollisionWorld->setDebugDrawer(mDebugDrawer.get()); - mDebugDrawer->setDebugMode(mDebugDrawEnabled); - } - else if (mDebugDrawer) - mDebugDrawer->setDebugMode(mDebugDrawEnabled); + mCollisionWorld->setDebugDrawer(mDebugDrawEnabled ? mDebugDrawer.get() : nullptr); + mDebugDrawer->setDebugMode(mDebugDrawEnabled); return mDebugDrawEnabled; } @@ -758,7 +756,7 @@ namespace MWPhysics void PhysicsSystem::debugDraw() { - if (mDebugDrawer) + if (mDebugDrawEnabled) mDebugDrawer->step(); } @@ -864,6 +862,12 @@ namespace MWPhysics stats.setAttribute(frameNumber, "Physics HeightFields", mHeightFields.size()); } + void PhysicsSystem::reportCollision(const btVector3& position, const btVector3& normal) + { + if (mDebugDrawEnabled) + mDebugDrawer->addCollision(position, normal); + } + ActorFrameData::ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr character, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel) : mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn), diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 96aba99c4..31707465b 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -45,6 +45,7 @@ class btDefaultCollisionConfiguration; class btCollisionDispatcher; class btCollisionObject; class btCollisionShape; +class btVector3; namespace MWPhysics { @@ -232,6 +233,7 @@ namespace MWPhysics bool isAreaOccupiedByOtherActor(const osg::Vec3f& position, const float radius, const MWWorld::ConstPtr& ignore) const; void reportStats(unsigned int frameNumber, osg::Stats& stats) const; + void reportCollision(const btVector3& position, const btVector3& normal); private: diff --git a/apps/openmw/mwrender/bulletdebugdraw.cpp b/apps/openmw/mwrender/bulletdebugdraw.cpp index 4cf76e473..61570be45 100644 --- a/apps/openmw/mwrender/bulletdebugdraw.cpp +++ b/apps/openmw/mwrender/bulletdebugdraw.cpp @@ -1,4 +1,4 @@ -#include "bulletdebugdraw.hpp" +#include #include @@ -6,17 +6,11 @@ #include #include +#include +#include "bulletdebugdraw.hpp" #include "vismask.hpp" -namespace -{ - osg::Vec3f toOsg(const btVector3& vec) - { - return osg::Vec3f(vec.x(), vec.y(), vec.z()); - } -} - namespace MWRender { @@ -37,11 +31,14 @@ void DebugDrawer::createGeometry() mGeometry->setNodeMask(Mask_Debug); mVertices = new osg::Vec3Array; + mColors = new osg::Vec4Array; mDrawArrays = new osg::DrawArrays(osg::PrimitiveSet::LINES); mGeometry->setUseDisplayList(false); mGeometry->setVertexArray(mVertices); + mGeometry->setColorArray(mColors); + mGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); mGeometry->setDataVariance(osg::Object::DYNAMIC); mGeometry->addPrimitiveSet(mDrawArrays); @@ -70,23 +67,53 @@ void DebugDrawer::step() if (mDebugOn) { mVertices->clear(); + mColors->clear(); mWorld->debugDrawWorld(); + showCollisions(); mDrawArrays->setCount(mVertices->size()); mVertices->dirty(); + mColors->dirty(); mGeometry->dirtyBound(); } } void DebugDrawer::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color) { - mVertices->push_back(toOsg(from)); - mVertices->push_back(toOsg(to)); + mVertices->push_back(Misc::Convert::toOsg(from)); + mVertices->push_back(Misc::Convert::toOsg(to)); + mColors->push_back({1,1,1,1}); + mColors->push_back({1,1,1,1}); +} + +void DebugDrawer::addCollision(const btVector3& orig, const btVector3& normal) +{ + mCollisionViews.emplace_back(orig, normal); +} + +void DebugDrawer::showCollisions() +{ + const auto now = std::chrono::steady_clock::now(); + for (auto& [from, to , created] : mCollisionViews) + { + if (now - created < std::chrono::seconds(2)) + { + mVertices->push_back(Misc::Convert::toOsg(from)); + mVertices->push_back(Misc::Convert::toOsg(to)); + mColors->push_back({1,0,0,1}); + mColors->push_back({1,0,0,1}); + } + } + mCollisionViews.erase(std::remove_if(mCollisionViews.begin(), mCollisionViews.end(), + [&now](const CollisionView& view) { return now - view.mCreated >= std::chrono::seconds(2); }), + mCollisionViews.end()); } void DebugDrawer::drawContactPoint(const btVector3 &PointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color) { - mVertices->push_back(toOsg(PointOnB)); - mVertices->push_back(toOsg(PointOnB) + (toOsg(normalOnB) * distance * 20)); + mVertices->push_back(Misc::Convert::toOsg(PointOnB)); + mVertices->push_back(Misc::Convert::toOsg(PointOnB) + (Misc::Convert::toOsg(normalOnB) * distance * 20)); + mColors->push_back({1,1,1,1}); + mColors->push_back({1,1,1,1}); } void DebugDrawer::reportErrorWarning(const char *warningString) @@ -96,7 +123,7 @@ void DebugDrawer::reportErrorWarning(const char *warningString) void DebugDrawer::setDebugMode(int isOn) { - mDebugOn = (isOn == 0) ? false : true; + mDebugOn = (isOn != 0); if (!mDebugOn) destroyGeometry(); @@ -109,6 +136,4 @@ int DebugDrawer::getDebugMode() const return mDebugOn; } - - } diff --git a/apps/openmw/mwrender/bulletdebugdraw.hpp b/apps/openmw/mwrender/bulletdebugdraw.hpp index 30cabc4f9..f07ce2e2e 100644 --- a/apps/openmw/mwrender/bulletdebugdraw.hpp +++ b/apps/openmw/mwrender/bulletdebugdraw.hpp @@ -1,6 +1,9 @@ #ifndef OPENMW_MWRENDER_BULLETDEBUGDRAW_H #define OPENMW_MWRENDER_BULLETDEBUGDRAW_H +#include +#include + #include #include #include @@ -20,11 +23,22 @@ namespace MWRender class DebugDrawer : public btIDebugDraw { +private: + struct CollisionView + { + btVector3 mOrig; + btVector3 mEnd; + std::chrono::time_point mCreated; + CollisionView(btVector3 orig, btVector3 normal) : mOrig(orig), mEnd(orig + normal * 20), mCreated(std::chrono::steady_clock::now()) {}; + }; + std::vector mCollisionViews; + protected: osg::ref_ptr mParentNode; btCollisionWorld *mWorld; osg::ref_ptr mGeometry; osg::ref_ptr mVertices; + osg::ref_ptr mColors; osg::ref_ptr mDrawArrays; bool mDebugOn; @@ -41,6 +55,10 @@ public: void drawLine(const btVector3& from,const btVector3& to,const btVector3& color) override; + void addCollision(const btVector3& orig, const btVector3& normal); + + void showCollisions(); + void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) override; void reportErrorWarning(const char* warningString) override; From 574ccbf7bd433357b873f89369f8b4da350ae9c3 Mon Sep 17 00:00:00 2001 From: Frederic Chardon Date: Mon, 26 Oct 2020 13:40:56 +0100 Subject: [PATCH 048/111] Visualize hand to hand hits --- .../mwphysics/deepestnotmecontacttestresultcallback.cpp | 1 + .../mwphysics/deepestnotmecontacttestresultcallback.hpp | 1 + apps/openmw/mwphysics/physicssystem.cpp | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.cpp b/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.cpp index 0baaa6241..7744af14b 100644 --- a/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.cpp +++ b/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.cpp @@ -39,6 +39,7 @@ namespace MWPhysics mObject = collisionObject; mLeastDistSqr = distsqr; mContactPoint = cp.getPositionWorldOnA(); + mContactNormal = cp.m_normalWorldOnB; } } diff --git a/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp b/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp index 9b2e97e65..00cb5c01f 100644 --- a/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp +++ b/apps/openmw/mwphysics/deepestnotmecontacttestresultcallback.hpp @@ -20,6 +20,7 @@ namespace MWPhysics public: const btCollisionObject *mObject{nullptr}; btVector3 mContactPoint{0,0,0}; + btVector3 mContactNormal{0,0,0}; btScalar mLeastDistSqr; DeepestNotMeContactTestResultCallback(const btCollisionObject* me, const std::vector& targets, const btVector3 &origin); diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 8f169dfe3..513e8d59b 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -173,6 +173,7 @@ namespace MWPhysics if (result.mHit) { + reportCollision(Misc::Convert::toBullet(result.mHitPos), Misc::Convert::toBullet(result.mHitNormal)); return std::make_pair(result.mHitObject, result.mHitPos); } @@ -217,7 +218,10 @@ namespace MWPhysics { PtrHolder* holder = static_cast(resultCallback.mObject->getUserPointer()); if (holder) + { + reportCollision(resultCallback.mContactPoint, resultCallback.mContactNormal); return std::make_pair(holder->getPtr(), Misc::Convert::toOsg(resultCallback.mContactPoint)); + } } return std::make_pair(MWWorld::Ptr(), osg::Vec3f()); } From e8c0a7bec0f03df96331e068acced2815a9e9fd3 Mon Sep 17 00:00:00 2001 From: fredzio Date: Mon, 26 Oct 2020 13:53:36 +0100 Subject: [PATCH 049/111] Visualie projectile hits --- apps/openmw/mwworld/projectilemanager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 2c6feef46..e8810151e 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -442,6 +443,7 @@ namespace MWWorld cast.mSourceName = it->mSourceName; cast.mStack = false; cast.inflict(result.mHitObject, caster, it->mEffects, ESM::RT_Target, false, true); + mPhysics->reportCollision(Misc::Convert::toBullet(result.mHitPos), Misc::Convert::toBullet(result.mHitNormal)); } } @@ -522,6 +524,7 @@ namespace MWWorld caster = result.mHitObject; MWMechanics::projectileHit(caster, result.mHitObject, bow, projectileRef.getPtr(), result.mHit ? result.mHitPos : newPos, it->mAttackStrength); + mPhysics->reportCollision(Misc::Convert::toBullet(result.mHitPos), Misc::Convert::toBullet(result.mHitNormal)); if (underwater) mRendering->emitWaterRipple(newPos); From 0512a574e810de21c49668b5f8958c2718af9736 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 26 Oct 2020 20:13:24 +0100 Subject: [PATCH 050/111] Fix remove item regression --- apps/openmw/mwscript/containerextensions.cpp | 2 +- apps/openmw/mwworld/containerstore.cpp | 14 ++++------ apps/openmw/mwworld/containerstore.hpp | 6 ++--- apps/openmw/mwworld/inventorystore.cpp | 28 ++------------------ apps/openmw/mwworld/inventorystore.hpp | 7 ++--- 5 files changed, 12 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 2e78fe374..186940dd9 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -246,7 +246,7 @@ namespace MWScript auto& store = container.getClass().getContainerStore(container); // Note that unlike AddItem, RemoveItem only removes from unresolved containers if(!store.isResolved()) - store.remove(item, count, ptr, false); + store.remove(item, count, ptr, false, false); } } return; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 3852b1abe..6fad42926 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -463,7 +463,7 @@ void MWWorld::ContainerStore::updateRechargingItems() } } -int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor, bool resolveFirst) +int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement, bool resolveFirst) { if(resolveFirst) resolve(); @@ -471,7 +471,7 @@ int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter) if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId)) - toRemove -= removeImp(*iter, toRemove, actor); + toRemove -= remove(*iter, toRemove, actor, equipReplacement, resolveFirst); flagAsModified(); @@ -490,16 +490,12 @@ bool MWWorld::ContainerStore::hasVisibleItems() const return false; } -int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor) +int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement, bool resolveFirst) { assert(this == item.getContainerStore()); - resolve(); - - return removeImp(item, count, actor); -} + if(resolveFirst) + resolve(); -int MWWorld::ContainerStore::removeImp(const Ptr& item, int count, const Ptr& actor) -{ int toRemove = count; RefData& itemRef = item.getRefData(); diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 9092d41fc..e0843efba 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -129,8 +129,6 @@ namespace MWWorld void addInitialItem (const std::string& id, const std::string& owner, int count, Misc::Rng::Seed* seed, bool topLevel=true); void addInitialItemImp (const MWWorld::Ptr& ptr, const std::string& owner, int count, Misc::Rng::Seed* seed, bool topLevel=true); - int removeImp(const Ptr& item, int count, const Ptr& actor); - template ContainerStoreIterator getState (CellRefList& collection, const ESM::ObjectState& state); @@ -180,12 +178,12 @@ namespace MWWorld ContainerStoreIterator add(const std::string& id, int count, const Ptr& actorPtr); ///< Utility to construct a ManualRef and call add(ptr, count, actorPtr, true) - int remove(const std::string& itemId, int count, const Ptr& actor, bool resolve = true); + int remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement = 0, bool resolve = true); ///< Remove \a count item(s) designated by \a itemId from this container. /// /// @return the number of items actually removed - virtual int remove(const Ptr& item, int count, const Ptr& actor); + virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement = 0, bool resolve = true); ///< Remove \a count item(s) designated by \a item from this inventory. /// /// @return the number of items actually removed diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index c2785579b..9dcddb921 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -710,33 +710,9 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem( return mSelectedEnchantItem; } -int MWWorld::InventoryStore::remove(const std::string& itemId, int count, const Ptr& actor) +int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement, bool resolve) { - return remove(itemId, count, actor, false); -} - -int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor) -{ - return remove(item, count, actor, false); -} - -int MWWorld::InventoryStore::remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement) -{ - int toRemove = count; - - for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter) - if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId)) - toRemove -= remove(*iter, toRemove, actor, equipReplacement); - - flagAsModified(); - - // number of removed items - return count - toRemove; -} - -int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement) -{ - int retCount = ContainerStore::remove(item, count, actor); + int retCount = ContainerStore::remove(item, count, actor, equipReplacement, resolve); bool wasEquipped = false; if (!item.getRefData().getCount()) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 12306f809..e70c21480 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -165,11 +165,8 @@ namespace MWWorld bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const override; ///< @return true if the two specified objects can stack with each other - virtual int remove(const std::string& itemId, int count, const Ptr& actor); - virtual int remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement); - - int remove(const Ptr& item, int count, const Ptr& actor) override; - virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement); + using ContainerStore::remove; + int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement = 0, bool resolve = true) override; ///< Remove \a count item(s) designated by \a item from this inventory. /// /// @return the number of items actually removed From 2c4cafa41a8c75c296ebdf516b232f1350769b29 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 26 Oct 2020 22:16:31 +0100 Subject: [PATCH 051/111] Change moon phase to an enum class --- apps/openmw/mwrender/sky.cpp | 36 ++++++++++++++++----------------- apps/openmw/mwrender/sky.hpp | 20 +++++++++--------- apps/openmw/mwworld/weather.cpp | 10 ++++----- apps/openmw/mwworld/weather.hpp | 3 ++- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 7ba490b92..070f941d6 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -941,10 +941,10 @@ public: Moon(osg::Group* parentNode, Resource::ImageManager& imageManager, float scaleFactor, Type type) : CelestialBody(parentNode, scaleFactor, 2) , mType(type) - , mPhase(MoonState::Phase_Unspecified) + , mPhase(MoonState::Phase::Unspecified) , mUpdater(new Updater(imageManager)) { - setPhase(MoonState::Phase_Full); + setPhase(MoonState::Phase::Full); setVisible(true); mGeom->addUpdateCallback(mUpdater); @@ -993,14 +993,14 @@ public: unsigned int getPhaseInt() const { - if (mPhase == MoonState::Phase_New) return 0; - else if (mPhase == MoonState::Phase_WaxingCrescent) return 1; - else if (mPhase == MoonState::Phase_WaningCrescent) return 1; - else if (mPhase == MoonState::Phase_FirstQuarter) return 2; - else if (mPhase == MoonState::Phase_ThirdQuarter) return 2; - else if (mPhase == MoonState::Phase_WaxingGibbous) return 3; - else if (mPhase == MoonState::Phase_WaningGibbous) return 3; - else if (mPhase == MoonState::Phase_Full) return 4; + if (mPhase == MoonState::Phase::New) return 0; + else if (mPhase == MoonState::Phase::WaxingCrescent) return 1; + else if (mPhase == MoonState::Phase::WaningCrescent) return 1; + else if (mPhase == MoonState::Phase::FirstQuarter) return 2; + else if (mPhase == MoonState::Phase::ThirdQuarter) return 2; + else if (mPhase == MoonState::Phase::WaxingGibbous) return 3; + else if (mPhase == MoonState::Phase::WaningGibbous) return 3; + else if (mPhase == MoonState::Phase::Full) return 4; return 0; } @@ -1090,14 +1090,14 @@ private: else textureName += "masser_"; - if (phase == MoonState::Phase_New) textureName += "new"; - else if(phase == MoonState::Phase_WaxingCrescent) textureName += "one_wax"; - else if(phase == MoonState::Phase_FirstQuarter) textureName += "half_wax"; - else if(phase == MoonState::Phase_WaxingGibbous) textureName += "three_wax"; - else if(phase == MoonState::Phase_WaningCrescent) textureName += "one_wan"; - else if(phase == MoonState::Phase_ThirdQuarter) textureName += "half_wan"; - else if(phase == MoonState::Phase_WaningGibbous) textureName += "three_wan"; - else if(phase == MoonState::Phase_Full) textureName += "full"; + if (phase == MoonState::Phase::New) textureName += "new"; + else if(phase == MoonState::Phase::WaxingCrescent) textureName += "one_wax"; + else if(phase == MoonState::Phase::FirstQuarter) textureName += "half_wax"; + else if(phase == MoonState::Phase::WaxingGibbous) textureName += "three_wax"; + else if(phase == MoonState::Phase::WaningCrescent) textureName += "one_wan"; + else if(phase == MoonState::Phase::ThirdQuarter) textureName += "half_wan"; + else if(phase == MoonState::Phase::WaningGibbous) textureName += "three_wan"; + else if(phase == MoonState::Phase::Full) textureName += "full"; textureName += ".dds"; diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 9727529d9..cf697bd44 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -99,17 +99,17 @@ namespace MWRender struct MoonState { - enum Phase + enum class Phase { - Phase_Full = 0, - Phase_WaningGibbous, - Phase_ThirdQuarter, - Phase_WaningCrescent, - Phase_New, - Phase_WaxingCrescent, - Phase_FirstQuarter, - Phase_WaxingGibbous, - Phase_Unspecified + Full = 0, + WaningGibbous, + ThirdQuarter, + WaningCrescent, + New, + WaxingCrescent, + FirstQuarter, + WaxingGibbous, + Unspecified }; float mRotationFromHorizon; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 2f054488b..6a4a227a4 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -370,7 +370,7 @@ MWRender::MoonState MoonModel::calculateState(const TimeStamp& gameTime) const { rotationFromHorizon, mAxisOffset, // Reverse engineered from Morrowind's scene graph rotation matrices. - static_cast(phase(gameTime)), + phase(gameTime), shadowBlend(rotationFromHorizon), earlyMoonShadowAlpha(rotationFromHorizon) * hourlyAlpha(gameTime.getHour()) }; @@ -439,17 +439,15 @@ inline float MoonModel::rotation(float hours) const return 15.0f * mSpeed * hours; } -inline unsigned int MoonModel::phase(const TimeStamp& gameTime) const +MWRender::MoonState::Phase MoonModel::phase(const TimeStamp& gameTime) const { // Morrowind starts with a full moon on 16 Last Seed and then begins to wane 17 Last Seed, working on 3 day phase cycle. - // Note: this is an internal helper, and as such we don't want to return MWRender::MoonState::Phase since we can't - // forward declare it (C++11 strongly typed enums solve this). // If the moon didn't rise yet today, use yesterday's moon phase. if(gameTime.getHour() < moonRiseHour(gameTime.getDay())) - return (gameTime.getDay() / 3) % 8; + return static_cast((gameTime.getDay() / 3) % 8); else - return ((gameTime.getDay() + 1) / 3) % 8; + return static_cast(((gameTime.getDay() + 1) / 3) % 8); } inline float MoonModel::shadowBlend(float angle) const diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 696f7c688..92f2ce6a4 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -24,6 +24,7 @@ namespace ESM namespace MWRender { class RenderingManager; + enum class MoonState::Phase; } namespace Loading @@ -261,7 +262,7 @@ namespace MWWorld float angle(const TimeStamp& gameTime) const; float moonRiseHour(unsigned int daysPassed) const; float rotation(float hours) const; - unsigned int phase(const TimeStamp& gameTime) const; + MWRender::MoonState::Phase phase(const TimeStamp& gameTime) const; float shadowBlend(float angle) const; float hourlyAlpha(float gameHour) const; float earlyMoonShadowAlpha(float angle) const; From 976399589208256599a4df082319949dcc276180 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Tue, 27 Oct 2020 18:08:14 +0300 Subject: [PATCH 052/111] Fix regression #5666 --- apps/openmw/mwgui/tradewindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index e7dbd4447..81d6a8ab3 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -519,6 +519,9 @@ namespace MWGui void TradeWindow::onClose() { + // Make sure the window was actually closed and not temporarily hidden. + if (MWBase::Environment::get().getWindowManager()->containsMode(GM_Barter)) + return; resetReference(); } } From 3bf5247c0b677bb070e130bb4905aac45b1e99ad Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Tue, 27 Oct 2020 19:23:07 +0100 Subject: [PATCH 053/111] remove forward declaration --- apps/openmw/mwworld/weather.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 92f2ce6a4..a3928465c 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -24,7 +24,6 @@ namespace ESM namespace MWRender { class RenderingManager; - enum class MoonState::Phase; } namespace Loading From 5869ac71e3655eeeeb822518941a7cd0b7526ba5 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 28 Oct 2020 00:36:49 +0000 Subject: [PATCH 054/111] Merge all composing variables, not just those in destination already This resolves a regression where the local openmw.cfg doesn't exist, so we fall back to the global openmw.cfg, but because we've not loaded anything from the local openmw.cfg, there are no variables with which to merge. --- components/files/configurationmanager.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index c7847b122..92d35a6b6 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -87,7 +87,7 @@ boost::program_options::variables_map ConfigurationManager::separateComposingVar boost::program_options::variables_map composingVariables; for (auto itr = variables.begin(); itr != variables.end();) { - if (description.find((*itr).first, false).semantic()->is_composing()) + if (description.find(itr->first, false).semantic()->is_composing()) { composingVariables.emplace(*itr); itr = variables.erase(itr); @@ -100,14 +100,23 @@ boost::program_options::variables_map ConfigurationManager::separateComposingVar void ConfigurationManager::mergeComposingVariables(boost::program_options::variables_map & first, boost::program_options::variables_map & second, boost::program_options::options_description& description) { - for (auto& [name, variableValue] : first) + for (const auto& option : description.options()) { - if (description.find(name, false).semantic()->is_composing()) + if (option->semantic()->is_composing()) { + std::string name = option->canonical_display_name(); + + auto firstPosition = first.find(name); + if (firstPosition == first.end()) + { + first.emplace(name, second[name]); + continue; + } + if (second[name].defaulted() || second[name].empty()) continue; - boost::any& firstValue = variableValue.value(); + boost::any& firstValue = firstPosition->second.value(); const boost::any& secondValue = second[name].value(); if (firstValue.type() == typeid(Files::EscapePathContainer)) From 00503d86e1ad925a4fd72a7b2b01fec1c70f1b4a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 28 Oct 2020 14:21:45 +0400 Subject: [PATCH 055/111] Try to disable CoverityScan warning in code with explanation --- components/crashcatcher/crashcatcher.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/crashcatcher/crashcatcher.cpp b/components/crashcatcher/crashcatcher.cpp index 99df2cfd8..307c08d95 100644 --- a/components/crashcatcher/crashcatcher.cpp +++ b/components/crashcatcher/crashcatcher.cpp @@ -143,8 +143,14 @@ static void gdb_info(pid_t pid) FILE *f; int fd; - /* Create a temp file to put gdb commands into */ + /* + * Create a temp file to put gdb commands into. + * Note: POSIX.1-2008 declares that the file should be already created with mode 0600 by default. + * Modern systems implement it and and suggest to do not touch masks in multithreaded applications. + * So CoverityScan warning is valid only for ancient versions of stdlib. + */ strcpy(respfile, "/tmp/gdb-respfile-XXXXXX"); + // coverity[secure_temp] if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != nullptr) { fprintf(f, "attach %d\n" From 64ba81ecf2dc6c1b8fd6e20a5fe0dc62467c7057 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 28 Oct 2020 18:02:31 +0400 Subject: [PATCH 056/111] Fix some issues, found by CoverityScan --- apps/openmw/mwmechanics/actors.cpp | 6 ++++-- apps/openmw/mwphysics/mtphysics.cpp | 1 + apps/openmw/mwrender/camera.cpp | 6 ++++++ apps/openmw/mwrender/camera.hpp | 4 ++-- apps/openmw/mwsound/soundmanagerimp.cpp | 3 +++ apps/openmw/mwsound/soundmanagerimp.hpp | 4 ++-- components/esm/loadland.cpp | 5 +++-- components/esm/loadland.hpp | 2 +- 8 files changed, 22 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 4d7841010..c027e1c89 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -590,7 +590,9 @@ namespace MWMechanics if (!actorState.isTurningToPlayer()) { - float angle = std::atan2(dir.x(), dir.y()); + float from = dir.x(); + float to = dir.y(); + float angle = std::atan2(from, to); actorState.setAngleToPlayer(angle); float deltaAngle = Misc::normalizeAngle(angle - actor.getRefData().getPosition().rot[2]); if (!mSmoothMovement || std::abs(deltaAngle) > osg::DegreesToRadians(60.f)) @@ -1723,7 +1725,7 @@ namespace MWMechanics shouldAvoidCollision = true; else if (package->getTypeId() == AiPackageTypeId::Wander && giveWayWhenIdle) { - if (!dynamic_cast(package.get())->isStationary()) + if (!static_cast(package.get())->isStationary()) shouldAvoidCollision = true; } else if (package->getTypeId() == AiPackageTypeId::Combat || package->getTypeId() == AiPackageTypeId::Pursue) diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index fa5a193e2..f105efce5 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -142,6 +142,7 @@ namespace MWPhysics { PhysicsTaskScheduler::PhysicsTaskScheduler(float physicsDt, std::shared_ptr collisionWorld) : mPhysicsDt(physicsDt) + , mTimeAccum(0.f) , mCollisionWorld(std::move(collisionWorld)) , mNumJobs(0) , mRemainingSteps(0) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 5b95b302b..b964eacff 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -66,6 +66,9 @@ namespace MWRender mIsNearest(false), mHeight(124.f), mBaseCameraDistance(Settings::Manager::getFloat("third person camera distance", "Camera")), + mPitch(0.f), + mYaw(0.f), + mRoll(0.f), mVanityToggleQueued(false), mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), @@ -81,6 +84,9 @@ namespace MWRender mDynamicCameraDistanceEnabled(false), mShowCrosshairInThirdPersonMode(false), mHeadBobbingEnabled(Settings::Manager::getBool("head bobbing", "Camera")), + mHeadBobbingOffset(0.f), + mHeadBobbingWeight(0.f), + mTotalMovement(0.f), mDeferredRotation(osg::Vec3f()), mDeferredRotationDisabled(false) { diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 6fe392683..9e2b608df 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -74,8 +74,8 @@ namespace MWRender bool mHeadBobbingEnabled; float mHeadBobbingOffset; - float mHeadBobbingWeight = 0; // Value from 0 to 1 for smooth enabling/disabling. - float mTotalMovement = 0; // Needed for head bobbing. + float mHeadBobbingWeight; // Value from 0 to 1 for smooth enabling/disabling. + float mTotalMovement; // Needed for head bobbing. void updateHeadBobbing(float duration); void updateFocalPointOffset(float duration); diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index d33b3d26e..1a90dceed 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -65,6 +65,9 @@ namespace MWSound , mUnderwaterSound(nullptr) , mNearWaterSound(nullptr) , mPlaybackPaused(false) + , mTimePassed(0.f) + , mLastCell(nullptr) + , mCurrentRegionSound(nullptr) { mBufferCacheMin = std::max(Settings::Manager::getInt("buffer cache min", "Sound"), 1); mBufferCacheMax = std::max(Settings::Manager::getInt("buffer cache max", "Sound"), 1); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 0c82528b5..f69171a09 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -116,9 +116,9 @@ namespace MWSound RegionSoundSelector mRegionSoundSelector; - float mTimePassed = 0; + float mTimePassed; - const ESM::Cell *mLastCell = nullptr; + const ESM::Cell *mLastCell; Sound* mCurrentRegionSound; diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 3064d0c31..2aa8f21db 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -331,9 +331,10 @@ namespace ESM std::copy(land.mWnam, land.mWnam + LAND_GLOBAL_MAP_LOD_SIZE, mWnam); } - Land& Land::operator= (Land land) + Land& Land::operator= (const Land& land) { - swap (land); + Land tmp(land); + swap(tmp); return *this; } diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index e5faf4b31..2a1140ad2 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -148,7 +148,7 @@ struct Land Land (const Land& land); - Land& operator= (Land land); + Land& operator= (const Land& land); void swap (Land& land); From 7065282127c374432f2f4f93ac4d36ab6d9495be Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 29 Oct 2020 13:55:24 +0100 Subject: [PATCH 057/111] Save and load container records; fixes #5668 --- apps/openmw/mwstate/statemanagerimp.cpp | 1 + apps/openmw/mwworld/esmstore.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index d59704bf1..8b245479e 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -451,6 +451,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str case ESM::REC_LEVC: case ESM::REC_LEVI: case ESM::REC_CREA: + case ESM::REC_CONT: MWBase::Environment::get().getWorld()->readRecord(reader, n.intval, contentFileMap); break; diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index aea9a5e4f..942d5feeb 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -345,7 +345,8 @@ void ESMStore::validate() +mWeapons.getDynamicSize() +mCreatureLists.getDynamicSize() +mItemLists.getDynamicSize() - +mCreatures.getDynamicSize(); + +mCreatures.getDynamicSize() + +mContainers.getDynamicSize(); } void ESMStore::write (ESM::ESMWriter& writer, Loading::Listener& progress) const @@ -368,6 +369,7 @@ void ESMStore::validate() mItemLists.write (writer, progress); mCreatureLists.write (writer, progress); mCreatures.write (writer, progress); + mContainers.write (writer, progress); } bool ESMStore::readRecord (ESM::ESMReader& reader, uint32_t type) @@ -386,6 +388,7 @@ void ESMStore::validate() case ESM::REC_LEVI: case ESM::REC_LEVC: case ESM::REC_CREA: + case ESM::REC_CONT: mStores[type]->read (reader); return true; From 48769691531fd40822cb9166183a047d6f13762c Mon Sep 17 00:00:00 2001 From: fredzio Date: Fri, 30 Oct 2020 23:53:07 +0100 Subject: [PATCH 058/111] Use the PhysicsSystem::movementQueue instead of a serie of setPosition(getPosition() + diff) to move actor in scripts. With background physics, this is very slightly off with the collision object position. When the script run long enough (a few dozen frames for instance), the accumulated error becomes too big. It make actors fall through lifts floors. --- apps/openmw/mwscript/transformationextensions.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index ce45729b3..41df1870c 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -32,11 +32,7 @@ namespace MWScript std::vector actors; MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors); for (auto& actor : actors) - { - osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3()); - actorPos += diff; - MWBase::Environment::get().getWorld()->moveObject(actor, actorPos.x(), actorPos.y(), actorPos.z()); - } + MWBase::Environment::get().getWorld()->queueMovement(actor, diff); } template From 449506fef155f1d0d4bcaa833604409babfe7bf8 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 31 Oct 2020 19:06:20 +0000 Subject: [PATCH 059/111] Attempt to explain what shadowsbin is doing --- components/sceneutil/shadowsbin.cpp | 44 ++++++++++++++++++++--------- components/sceneutil/shadowsbin.hpp | 19 +++++++------ 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/components/sceneutil/shadowsbin.cpp b/components/sceneutil/shadowsbin.cpp index 2bf2f06f6..e0a141ffb 100644 --- a/components/sceneutil/shadowsbin.cpp +++ b/components/sceneutil/shadowsbin.cpp @@ -32,6 +32,7 @@ namespace inline bool materialNeedShadows(osg::Material* m) { + // I'm pretty sure this needs to check the colour mode - vertex colours might override this value. return m->getDiffuse(osg::Material::FRONT).a() > 0.5; } } @@ -45,38 +46,45 @@ ShadowsBin::ShadowsBin() mStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false)); } -bool ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::unordered_set& uninteresting) +bool ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::unordered_set& uninterestingCache) { std::vector return_path; State state; StateGraph* sg_new = sg; do { - if (uninteresting.find(sg_new) != uninteresting.end()) + if (uninterestingCache.find(sg_new) != uninterestingCache.end()) break; return_path.push_back(sg_new); sg_new = sg_new->_parent; } while (sg_new && sg_new != root); - for(std::vector::reverse_iterator itr=return_path.rbegin(); itr!=return_path.rend(); ++itr) + + for(auto itr=return_path.rbegin(); itr!=return_path.rend(); ++itr) { const osg::StateSet* ss = (*itr)->getStateSet(); - if (!ss) continue; + if (!ss) + continue; + accumulateModeState(ss, state.mAlphaBlend, state.mAlphaBlendOverride, GL_BLEND); accumulateModeState(ss, state.mAlphaTest, state.mAlphaTestOverride, GL_ALPHA_TEST); - const osg::StateSet::AttributeList& l = ss->getAttributeList(); - osg::StateSet::AttributeList::const_iterator f = l.find(std::make_pair(osg::StateAttribute::MATERIAL, 0)); - if (f != l.end()) + + const osg::StateSet::AttributeList& attributes = ss->getAttributeList(); + osg::StateSet::AttributeList::const_iterator found = attributes.find(std::make_pair(osg::StateAttribute::MATERIAL, 0)); + if (found != attributes.end()) { - const osg::StateSet::RefAttributePair* rap = &f->second; - accumulateState(state.mMaterial, static_cast(rap->first.get()), state.mMaterialOverride, rap->second); + const osg::StateSet::RefAttributePair& rap = found->second; + accumulateState(state.mMaterial, static_cast(rap.first.get()), state.mMaterialOverride, rap.second); if (state.mMaterial && !materialNeedShadows(state.mMaterial)) state.mMaterial = nullptr; } - f = l.find(std::make_pair(osg::StateAttribute::FRONTFACE, 0)); - if (f != l.end()) + + // osg::FrontFace specifies triangle winding, not front-face culling. We can't safely reparent anything under it. + found = attributes.find(std::make_pair(osg::StateAttribute::FRONTFACE, 0)); + if (found != attributes.end()) state.mImportantState = true; + if ((*itr) != sg && !state.interesting()) - uninteresting.insert(*itr); + uninterestingCache.insert(*itr); } if (!state.needShadows()) @@ -103,6 +111,10 @@ bool ShadowsBin::State::needShadows() const void ShadowsBin::sortImplementation() { + // The cull visitor contains a stategraph. + // When a stateset is pushed, it's added/found as a child of the current stategraph node, then that node becomes the new current stategraph node. + // When a drawable is added, the current stategraph node is added to the current renderbin (if it's not there already) and the drawable is added as a renderleaf to the stategraph + // This means our list only contains stategraph nodes with directly-attached renderleaves, but they might have parents with more state set that needs to be considered. if (!_stateGraphList.size()) return; StateGraph* root = _stateGraphList[0]; @@ -117,12 +129,16 @@ void ShadowsBin::sortImplementation() return; } root = root->find_or_insert(mStateSet.get()); + // root is now a stategraph with useDiffuseMapForShadowAlpha disabled but minimal other state root->_leaves.reserve(_stateGraphList.size()); StateGraphList newList; - std::unordered_set uninteresting; + std::unordered_set uninterestingCache; for (StateGraph* graph : _stateGraphList) { - if (!cullStateGraph(graph, root, uninteresting)) + // Render leaves which shouldn't use the diffuse map for shadow alpha but do cast shadows become children of root, so graph is now empty. Don't add to newList. + // Graphs containing just render leaves which don't cast shadows are discarded. Don't add to newList. + // Graphs containing other leaves need to be in newList. + if (!cullStateGraph(graph, root, uninterestingCache)) newList.push_back(graph); } if (!root->_leaves.empty()) diff --git a/components/sceneutil/shadowsbin.hpp b/components/sceneutil/shadowsbin.hpp index 05926bace..6302d5974 100644 --- a/components/sceneutil/shadowsbin.hpp +++ b/components/sceneutil/shadowsbin.hpp @@ -17,11 +17,11 @@ namespace SceneUtil private: osg::ref_ptr mStateSet; public: - META_Object(SceneUtil, ShadowsBin) - ShadowsBin(); - ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop), mStateSet(rhs.mStateSet) {} + META_Object(SceneUtil, ShadowsBin) + ShadowsBin(); + ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop), mStateSet(rhs.mStateSet) {} - virtual void sortImplementation(); + virtual void sortImplementation(); struct State { @@ -35,16 +35,17 @@ namespace SceneUtil bool mImportantState; bool needTexture() const { return mAlphaBlend || mAlphaTest; } bool needShadows() const; + // A state is interesting if there's anything about it that might affect whether we can optimise child state bool interesting() const { return !needShadows() || needTexture() || mAlphaBlendOverride || mAlphaTestOverride || mMaterialOverride || mImportantState; } }; bool cullStateGraph(osgUtil::StateGraph* sg, osgUtil::StateGraph* root, std::unordered_set& uninteresting); - static void addPrototype(const std::string& name) - { - osg::ref_ptr bin (new ShadowsBin); - osgUtil::RenderBin::addRenderBinPrototype(name, bin); - } + static void addPrototype(const std::string& name) + { + osg::ref_ptr bin (new ShadowsBin); + osgUtil::RenderBin::addRenderBinPrototype(name, bin); + } }; class ShadowsBinAdder From 73f866fc6504b24df3ca67a38a480c1e35be3bde Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 1 Nov 2020 01:32:36 +0300 Subject: [PATCH 060/111] Add missing changelog entries --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d5132207..304892ca4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Bug #5403: Enchantment effect doesn't show on an enemy during death animation Bug #5415: Environment maps in ebony cuirass and HiRez Armors Indoril cuirass don't work Bug #5416: Junk non-node records before the root node are not handled gracefully + Bug #5422: The player loses all spells when resurrected Bug #5424: Creatures do not headtrack player Bug #5425: Poison effect only appears for one frame Bug #5427: GetDistance unknown ID error is misleading @@ -57,6 +58,7 @@ Bug #5603: Setting constant effect cast style doesn't correct effects view Bug #5611: Usable items with "0 Uses" should be used only once Bug #5622: Can't properly interact with the console when in pause menu + Bug #5633: Damage Spells in effect before god mode is enabled continue to hurt the player character and can kill them Bug #5639: Tooltips cover Messageboxes Bug #5644: Summon effects running on the player during game initialization cause crashes Bug #5656: Sneaking characters block hits while standing From f49bf028b97dfbd4e7242d6cd10754eacb76cda4 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 1 Nov 2020 02:14:25 +0300 Subject: [PATCH 061/111] Put a stretch menu background checkbox into the launcher (#5672) --- CHANGELOG.md | 1 + apps/launcher/advancedpage.cpp | 2 ++ docs/source/reference/modding/settings/GUI.rst | 2 +- files/ui/advancedpage.ui | 10 ++++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 304892ca4..69cc077ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ Feature #5610: Actors movement should be smoother Feature #5642: Ability to attach arrows to actor skeleton instead of bow mesh Feature #5649: Skyrim SE compressed BSA format support + Feature #5672: Make stretch menu background configuration more accessible Task #5480: Drop Qt4 support Task #5520: Improve cell name autocompleter implementation diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 050ab8d21..b35e78639 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -152,6 +152,7 @@ bool Launcher::AdvancedPage::loadSettings() // Match the index with the option (only 0, 1, 2, or 3 are valid). Will default to 0 if invalid. if (showOwnedIndex >= 0 && showOwnedIndex <= 3) showOwnedComboBox->setCurrentIndex(showOwnedIndex); + loadSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI"); } // Bug fixes @@ -277,6 +278,7 @@ void Launcher::AdvancedPage::saveSettings() int showOwnedCurrentIndex = showOwnedComboBox->currentIndex(); if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game")) mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex); + saveSettingBool(stretchBackgroundCheckBox, "stretch menu background", "GUI"); } // Bug fixes diff --git a/docs/source/reference/modding/settings/GUI.rst b/docs/source/reference/modding/settings/GUI.rst index 349a98697..cad04ab5c 100644 --- a/docs/source/reference/modding/settings/GUI.rst +++ b/docs/source/reference/modding/settings/GUI.rst @@ -72,7 +72,7 @@ The Bethesda provided assets have a 4:3 aspect ratio, but other assets are permi If this setting is false, the assets will be centered in their correct aspect ratio, with black bars filling the remainder of the screen. -This setting can only be configured by editing the settings configuration file. +This setting can be configured in the Interface section of Advanced tab of the launcher. subtitles --------- diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index c678ffbba..3f53180da 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -714,6 +714,16 @@ True: In non-combat mode camera is positioned behind the character's shoulder. C + + + + <html><head/><body><p>Stretch menus, load screens, etc. to the window aspect ratio.</p></body></html> + + + Stretch menu background + + + From 18e38d8810be4e397861d0ce8adad4747353dbd3 Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 1 Nov 2020 22:30:48 +0100 Subject: [PATCH 062/111] Do not block a door when it turns away. --- .../mwphysics/contacttestresultcallback.cpp | 4 +++- .../mwphysics/contacttestresultcallback.hpp | 4 +++- apps/openmw/mwphysics/physicssystem.cpp | 14 +++++++++++--- apps/openmw/mwphysics/physicssystem.hpp | 8 ++++++++ apps/openmw/mwworld/worldimp.cpp | 15 ++++++++++----- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwphysics/contacttestresultcallback.cpp b/apps/openmw/mwphysics/contacttestresultcallback.cpp index f8209e363..5829ee02f 100644 --- a/apps/openmw/mwphysics/contacttestresultcallback.cpp +++ b/apps/openmw/mwphysics/contacttestresultcallback.cpp @@ -2,6 +2,8 @@ #include +#include "components/misc/convert.hpp" + #include "ptrholder.hpp" namespace MWPhysics @@ -20,7 +22,7 @@ namespace MWPhysics collisionObject = col1Wrap->m_collisionObject; PtrHolder* holder = static_cast(collisionObject->getUserPointer()); if (holder) - mResult.push_back(holder->getPtr()); + mResult.emplace_back(ContactPoint{holder->getPtr(), Misc::Convert::toOsg(cp.m_positionWorldOnB), Misc::Convert::toOsg(cp.m_normalWorldOnB)}); return 0.f; } diff --git a/apps/openmw/mwphysics/contacttestresultcallback.hpp b/apps/openmw/mwphysics/contacttestresultcallback.hpp index 03fc36299..fbe12d5dc 100644 --- a/apps/openmw/mwphysics/contacttestresultcallback.hpp +++ b/apps/openmw/mwphysics/contacttestresultcallback.hpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "physicssystem.hpp" + class btCollisionObject; struct btCollisionObjectWrapper; @@ -23,7 +25,7 @@ namespace MWPhysics const btCollisionObjectWrapper* col0Wrap,int partId0,int index0, const btCollisionObjectWrapper* col1Wrap,int partId1,int index1) override; - std::vector mResult; + std::vector mResult; }; } diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 513e8d59b..9a777bd45 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -403,15 +403,15 @@ namespace MWPhysics return osg::Vec3f(); } - std::vector PhysicsSystem::getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const + std::vector PhysicsSystem::getCollisionsPoints(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const { btCollisionObject* me = nullptr; - ObjectMap::const_iterator found = mObjects.find(ptr); + auto found = mObjects.find(ptr); if (found != mObjects.end()) me = found->second->getCollisionObject(); else - return std::vector(); + return {}; ContactTestResultCallback resultCallback (me); resultCallback.m_collisionFilterGroup = collisionGroup; @@ -420,6 +420,14 @@ namespace MWPhysics return resultCallback.mResult; } + std::vector PhysicsSystem::getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const + { + std::vector actors; + for (auto& [actor, point, normal] : getCollisionsPoints(ptr, collisionGroup, collisionMask)) + actors.emplace_back(actor); + return actors; + } + osg::Vec3f PhysicsSystem::traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, float maxHeight) { ActorMap::iterator found = mActors.find(ptr); diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 31707465b..36ef762d3 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -57,6 +57,13 @@ namespace MWPhysics class Actor; class PhysicsTaskScheduler; + struct ContactPoint + { + MWWorld::Ptr mObject; + osg::Vec3f mPoint; + osg::Vec3f mNormal; + }; + struct LOSRequest { LOSRequest(const std::weak_ptr& a1, const std::weak_ptr& a2); @@ -145,6 +152,7 @@ namespace MWPhysics void debugDraw(); std::vector getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with + std::vector getCollisionsPoints(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; osg::Vec3f traceDown(const MWWorld::Ptr &ptr, const osg::Vec3f& position, float maxHeight); std::pair getHitContact(const MWWorld::ConstPtr& actor, diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index dbe6af326..095bb1454 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1577,21 +1577,26 @@ namespace MWWorld float minRot = door.getCellRef().getPosition().rot[2]; float maxRot = minRot + osg::DegreesToRadians(90.f); - float diff = duration * osg::DegreesToRadians(90.f); - float targetRot = std::min(std::max(minRot, oldRot + diff * (state == MWWorld::DoorState::Opening ? 1 : -1)), maxRot); + float diff = duration * osg::DegreesToRadians(90.f) * (state == MWWorld::DoorState::Opening ? 1 : -1); + float targetRot = std::min(std::max(minRot, oldRot + diff), maxRot); rotateObject(door, objPos.rot[0], objPos.rot[1], targetRot, MWBase::RotationFlag_none); bool reached = (targetRot == maxRot && state != MWWorld::DoorState::Idle) || targetRot == minRot; /// \todo should use convexSweepTest here bool collisionWithActor = false; - std::vector collisions = mPhysics->getCollisions(door, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor); - for (MWWorld::Ptr& ptr : collisions) + for (auto& [ptr, point, normal] : mPhysics->getCollisionsPoints(door, MWPhysics::CollisionType_Door, MWPhysics::CollisionType_Actor)) { + if (ptr.getClass().isActor()) { + osg::Vec3f direction = osg::Quat(diff, osg::Vec3f(0, 0, 1)) * point - point; + direction.normalize(); + if (direction * normal < 0) // door is turning away from actor + continue; + collisionWithActor = true; - + // Collided with actor, ask actor to try to avoid door if(ptr != getPlayerPtr() ) { From ecd10a731eb5c4abb1f6b24e33f0abd57ade395a Mon Sep 17 00:00:00 2001 From: Frederic Chardon Date: Mon, 2 Nov 2020 13:52:36 +0100 Subject: [PATCH 063/111] Compute the rotation normal relative to the door axe, not the world. --- apps/openmw/mwworld/worldimp.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 095bb1454..be32765ad 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1590,8 +1590,10 @@ namespace MWWorld if (ptr.getClass().isActor()) { - osg::Vec3f direction = osg::Quat(diff, osg::Vec3f(0, 0, 1)) * point - point; + auto localPoint = objPos.asVec3() - point; + osg::Vec3f direction = osg::Quat(diff, osg::Vec3f(0, 0, 1)) * localPoint - localPoint; direction.normalize(); + mPhysics->reportCollision(Misc::Convert::toBullet(point), Misc::Convert::toBullet(normal)); if (direction * normal < 0) // door is turning away from actor continue; From c1d56d94c4b3329b50afd0863f0284ef7753a7bc Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 2 Nov 2020 17:51:36 +0400 Subject: [PATCH 064/111] Do not remove active effects in loop (bug #3789) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/spellcasting.cpp | 31 +++++++++++++++++++++ apps/openmw/mwmechanics/tickableeffects.cpp | 18 ------------ apps/openmw/mwmechanics/tickableeffects.hpp | 1 + 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 304892ca4..5bda1ff5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Bug #2976 [reopened]: Issues combining settings from the command line and both config files Bug #3676: NiParticleColorModifier isn't applied properly Bug #3714: Savegame fails to load due to conflict between SpellState and MagicEffects + Bug #3789: Crash in visitEffectSources while in battle Bug #3862: Random container contents behave differently than vanilla Bug #3929: Leveled list merchant containers respawn on barter Bug #4021: Attributes and skills are not stored as floats diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 81b3a353d..beab36cbf 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -381,6 +381,37 @@ namespace MWMechanics target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude, true); return true; } + else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CurePoison) + { + target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison); + return true; + } + else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureParalyzation) + { + target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze); + return true; + } + else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureCommonDisease) + { + target.getClass().getCreatureStats(target).getSpells().purgeCommonDisease(); + return true; + } + else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureBlightDisease) + { + target.getClass().getCreatureStats(target).getSpells().purgeBlightDisease(); + return true; + } + else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureCorprusDisease) + { + target.getClass().getCreatureStats(target).getActiveSpells().purgeCorprusDisease(); + target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease(); + return true; + } + else if (target.getClass().isActor() && effectId == ESM::MagicEffect::RemoveCurse) + { + target.getClass().getCreatureStats(target).getSpells().purgeCurses(); + return true; + } else if (target.getClass().isActor() && target == getPlayer()) { MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mCaster); diff --git a/apps/openmw/mwmechanics/tickableeffects.cpp b/apps/openmw/mwmechanics/tickableeffects.cpp index fa3b6ac20..5056179f8 100644 --- a/apps/openmw/mwmechanics/tickableeffects.cpp +++ b/apps/openmw/mwmechanics/tickableeffects.cpp @@ -205,24 +205,6 @@ namespace MWMechanics break; } - case ESM::MagicEffect::CurePoison: - actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison); - break; - case ESM::MagicEffect::CureParalyzation: - actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze); - break; - case ESM::MagicEffect::CureCommonDisease: - actor.getClass().getCreatureStats(actor).getSpells().purgeCommonDisease(); - break; - case ESM::MagicEffect::CureBlightDisease: - actor.getClass().getCreatureStats(actor).getSpells().purgeBlightDisease(); - break; - case ESM::MagicEffect::CureCorprusDisease: - actor.getClass().getCreatureStats(actor).getSpells().purgeCorprusDisease(); - break; - case ESM::MagicEffect::RemoveCurse: - actor.getClass().getCreatureStats(actor).getSpells().purgeCurses(); - break; default: return false; } diff --git a/apps/openmw/mwmechanics/tickableeffects.hpp b/apps/openmw/mwmechanics/tickableeffects.hpp index c4abed6a3..ccd42ca19 100644 --- a/apps/openmw/mwmechanics/tickableeffects.hpp +++ b/apps/openmw/mwmechanics/tickableeffects.hpp @@ -12,6 +12,7 @@ namespace MWMechanics struct EffectKey; /// Apply a magic effect that is applied in tick intervals until its remaining time ends or it is removed + /// Note: this function works in loop, so magic effects should not be removed here to avoid iterator invalidation. /// @return Was the effect a tickable effect with a magnitude? bool effectTick(CreatureStats& creatureStats, const MWWorld::Ptr& actor, const EffectKey& effectKey, float magnitude); } From 0e971dccf02b669bda291be91b10025aba5511c0 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 4 Nov 2020 13:33:54 +0400 Subject: [PATCH 065/111] Rework cure effects --- apps/openmw/mwmechanics/actors.cpp | 42 ++++++++++++++++++++++++ apps/openmw/mwmechanics/actors.hpp | 1 + apps/openmw/mwmechanics/spellcasting.cpp | 31 ----------------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index a3865983e..8f3675ef7 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -916,12 +916,54 @@ namespace MWMechanics } }; + void Actors::applyCureEffects(const MWWorld::Ptr& actor) + { + CreatureStats &creatureStats = actor.getClass().getCreatureStats(actor); + const MagicEffects &effects = creatureStats.getMagicEffects(); + + if (effects.get(ESM::MagicEffect::CurePoison).getModifier() > 0) + { + creatureStats.getActiveSpells().purgeEffect(ESM::MagicEffect::Poison); + creatureStats.getSpells().purgeEffect(ESM::MagicEffect::Poison); + if (actor.getClass().hasInventoryStore(actor)) + actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Poison); + } + else if (effects.get(ESM::MagicEffect::CureParalyzation).getModifier() > 0) + { + creatureStats.getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze); + creatureStats.getSpells().purgeEffect(ESM::MagicEffect::Paralyze); + if (actor.getClass().hasInventoryStore(actor)) + actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Paralyze); + } + else if (effects.get(ESM::MagicEffect::CureCommonDisease).getModifier() > 0) + { + creatureStats.getSpells().purgeCommonDisease(); + } + else if (effects.get(ESM::MagicEffect::CureBlightDisease).getModifier() > 0) + { + creatureStats.getSpells().purgeBlightDisease(); + } + else if (effects.get(ESM::MagicEffect::CureCorprusDisease).getModifier() > 0) + { + creatureStats.getActiveSpells().purgeCorprusDisease(); + creatureStats.getSpells().purgeCorprusDisease(); + if (actor.getClass().hasInventoryStore(actor)) + actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Corprus, true); + } + else if (effects.get(ESM::MagicEffect::RemoveCurse).getModifier() > 0) + { + creatureStats.getSpells().purgeCurses(); + } + } + void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr, float duration) { CreatureStats &creatureStats = ptr.getClass().getCreatureStats(ptr); const MagicEffects &effects = creatureStats.getMagicEffects(); bool godmode = ptr == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState(); + applyCureEffects(ptr); + bool wasDead = creatureStats.isDead(); if (duration > 0) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 9299d468c..453540001 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -206,6 +206,7 @@ namespace MWMechanics private: void updateVisibility (const MWWorld::Ptr& ptr, CharacterController* ctrl); + void applyCureEffects (const MWWorld::Ptr& actor); PtrActorMap mActors; float mTimerDisposeSummonsCorpses; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index beab36cbf..81b3a353d 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -381,37 +381,6 @@ namespace MWMechanics target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude, true); return true; } - else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CurePoison) - { - target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison); - return true; - } - else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureParalyzation) - { - target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze); - return true; - } - else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureCommonDisease) - { - target.getClass().getCreatureStats(target).getSpells().purgeCommonDisease(); - return true; - } - else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureBlightDisease) - { - target.getClass().getCreatureStats(target).getSpells().purgeBlightDisease(); - return true; - } - else if (target.getClass().isActor() && effectId == ESM::MagicEffect::CureCorprusDisease) - { - target.getClass().getCreatureStats(target).getActiveSpells().purgeCorprusDisease(); - target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease(); - return true; - } - else if (target.getClass().isActor() && effectId == ESM::MagicEffect::RemoveCurse) - { - target.getClass().getCreatureStats(target).getSpells().purgeCurses(); - return true; - } else if (target.getClass().isActor() && target == getPlayer()) { MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(mCaster); From 64ff09883f9245d96ec16d36154865a04f15541e Mon Sep 17 00:00:00 2001 From: Atahualpa Date: Thu, 5 Nov 2020 13:30:56 +0100 Subject: [PATCH 066/111] Add #4083 to the changelog. The entry for the release changelog is going to be included in my upcoming MR which will update the whole release changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12dd019d8..1f19783ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Bug #3929: Leveled list merchant containers respawn on barter Bug #4021: Attributes and skills are not stored as floats Bug #4055: Local scripts don't inherit variables from their base record + Bug #4083: Door animation freezes when colliding with actors Bug #4623: Corprus implementation is incorrect Bug #4631: Setting MSAA level too high doesn't fall back to highest supported level Bug #4764: Data race in osg ParticleSystem From 9859565f8dbc00fbec9518618345e232f4fc4708 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 7 Nov 2020 02:18:36 +0300 Subject: [PATCH 067/111] Improve grammar in [Physics] category of the default settings --- files/settings-default.cfg | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 143523750..b9fb2fbf7 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -933,13 +933,15 @@ object shadows = false enable indoor shadows = true [Physics] -# how much background thread to use in the physics solver. 0 to disable (i.e solver run in the main thread) +# Set the number of background threads used for physics. +# If no background threads are used, physics calculations are processed in the main thread +# and the settings below have no effect. async num threads = 0 -# maintain a cache of lineofsight request in the bacground physics thread -# determines for how much frames an inactive lineofsight request should be kept updated in the cache -# -1 to disable (i.e the LOS will be calculated only on request) +# Set the number of frames an inactive line-of-sight request will be kept +# refreshed in the background physics thread cache. +# If this is set to -1, line-of-sight requests are never cached. lineofsight keep inactive cache = 0 -# wether to defer aabb update till before collision detection +# Defer bounding boxes update until collision detection. defer aabb update = true From 7e63afdecfb9b453c566d127c40f68fe8c3aeb0c Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 7 Nov 2020 02:05:16 +0300 Subject: [PATCH 068/111] Allow loading arbitrary NIF files --- components/nif/niffile.cpp | 43 +++++++++++++++++-- .../reference/modding/settings/index.rst | 1 + .../reference/modding/settings/models.rst | 27 ++++++++++++ files/settings-default.cfg | 5 +++ 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 docs/source/reference/modding/settings/models.rst diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 5642dfebb..098f6aba2 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -1,9 +1,12 @@ #include "niffile.hpp" #include "effect.hpp" +#include #include #include +#include + namespace Nif { @@ -137,15 +140,46 @@ void NIFFile::parse(Files::IStreamPtr stream) // Check the header string std::string head = nif.getVersionString(); - if(head.compare(0, 22, "NetImmerse File Format") != 0) + static const std::array verStrings = + { + "NetImmerse File Format", + "Gamebryo File Format" + }; + bool supported = false; + for (const std::string& verString : verStrings) + { + supported = (head.compare(0, verString.size(), verString) == 0); + if (supported) + break; + } + if (!supported) fail("Invalid NIF header: " + head); + supported = false; + // Get BCD version ver = nif.getUInt(); // 4.0.0.0 is an older, practically identical version of the format. // It's not used by Morrowind assets but Morrowind supports it. - if(ver != NIFStream::generateVersion(4,0,0,0) && ver != VER_MW) - fail("Unsupported NIF version: " + printVersion(ver)); + static const std::array supportedVers = + { + NIFStream::generateVersion(4,0,0,0), + VER_MW + }; + for (uint32_t supportedVer : supportedVers) + { + supported = (ver == supportedVer); + if (supported) + break; + } + if (!supported) + { + static const bool ignoreUnsupported = Settings::Manager::getBool("load unsupported nif files", "Models"); + if (ignoreUnsupported) + warn("Unsupported NIF version: " + printVersion(ver) + ". Proceed with caution!"); + else + fail("Unsupported NIF version: " + printVersion(ver)); + } // NIF data endianness if (ver >= NIFStream::generateVersion(20,0,0,4)) @@ -245,6 +279,9 @@ void NIFFile::parse(Files::IStreamPtr stream) else fail("Unknown record type " + rec); + if (!supported) + Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " (" << filename << ")"; + assert(r != nullptr); assert(r->recType != RC_MISSING); r->recName = rec; diff --git a/docs/source/reference/modding/settings/index.rst b/docs/source/reference/modding/settings/index.rst index 2261fe8e1..586a99dbb 100644 --- a/docs/source/reference/modding/settings/index.rst +++ b/docs/source/reference/modding/settings/index.rst @@ -58,3 +58,4 @@ The ranges included with each setting are the physically possible ranges, not re windows navigator physics + models diff --git a/docs/source/reference/modding/settings/models.rst b/docs/source/reference/modding/settings/models.rst new file mode 100644 index 000000000..da56a1709 --- /dev/null +++ b/docs/source/reference/modding/settings/models.rst @@ -0,0 +1,27 @@ +Models Settings +############### + +load unsupported nif files +-------------------------- + +:Type: boolean +:Range: True/False +:Default: False + +At the moment OpenMW's NIF loader is only tailored to load models +that can also load in Morrowind. + +However, you can enable its limited and experimental support for updates in +the definitions of record types from later NIF revisions by toggling on +this setting. + +You must keep in mind that loading unsupported NIF files may fail, +and the degree of this failure may vary. In milder cases, OpenMW will reject +the file anyway because it lacks a definition for a certain record type +that the file may use. In more severe cases OpenMW's +incomplete understanding of a record type can lead to memory corruption, +crashes or even freezes. Don't enable this if you're not sure that +you know what you're doing. + +To help debug possible issues OpenMW will log its progress in loading +every file that uses an unsupported NIF version. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index b9fb2fbf7..0b307ba09 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -945,3 +945,8 @@ lineofsight keep inactive cache = 0 # Defer bounding boxes update until collision detection. defer aabb update = true + +[Models] +# Attempt to load any valid NIF file regardless of its version and track the progress. +# Loading arbitrary meshes is not advised and may cause instability. +load unsupported nif files = false From c79f50965229c3773069bea851d49e0f96bf76fc Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 7 Nov 2020 03:33:04 +0300 Subject: [PATCH 069/111] Misc NIF loader improvements Bullet NIF loader cleanup Collect all extra records of a node Remove code duplication in geometry type detection in OSG-side NIF loader --- components/nifbullet/bulletnifloader.cpp | 53 ++++++++++-------------- components/nifosg/nifloader.cpp | 30 ++++++++++++-- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 15834ffad..5b531121e 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -24,11 +25,6 @@ osg::Matrixf getWorldTransform(const Nif::Node *node) return node->trafo.toMatrix(); } -btVector3 getbtVector(const osg::Vec3f &v) -{ - return btVector3(v.x(), v.y(), v.z()); -} - bool pathFileNameStartsWithX(const std::string& path) { const std::size_t slashpos = path.find_last_of("/\\"); @@ -36,7 +32,7 @@ bool pathFileNameStartsWithX(const std::string& path) return letterPos < path.size() && (path[letterPos] == 'x' || path[letterPos] == 'X'); } -void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriShapeData& data, const osg::Matrixf &transform) +void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriShapeData& data, const osg::Matrixf &transform) { mesh.preallocateVertices(static_cast(data.vertices.size())); mesh.preallocateIndices(static_cast(data.triangles.size())); @@ -47,20 +43,20 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriShapeDa for (std::size_t i = 0; i < triangles.size(); i += 3) { mesh.addTriangle( - getbtVector(vertices[triangles[i + 0]] * transform), - getbtVector(vertices[triangles[i + 1]] * transform), - getbtVector(vertices[triangles[i + 2]] * transform) + Misc::Convert::toBullet(vertices[triangles[i + 0]] * transform), + Misc::Convert::toBullet(vertices[triangles[i + 1]] * transform), + Misc::Convert::toBullet(vertices[triangles[i + 2]] * transform) ); } } -void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsData& data, const osg::Matrixf &transform) +void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriStripsData& data, const osg::Matrixf &transform) { const std::vector &vertices = data.vertices; const std::vector> &strips = data.strips; if (vertices.empty() || strips.empty()) return; - mesh.preallocateVertices(static_cast(data.vertices.size())); + mesh.preallocateVertices(static_cast(vertices.size())); int numTriangles = 0; for (const std::vector& strip : strips) { @@ -88,17 +84,17 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD if (i%2==0) { mesh.addTriangle( - getbtVector(vertices[a] * transform), - getbtVector(vertices[b] * transform), - getbtVector(vertices[c] * transform) + Misc::Convert::toBullet(vertices[a] * transform), + Misc::Convert::toBullet(vertices[b] * transform), + Misc::Convert::toBullet(vertices[c] * transform) ); } else { mesh.addTriangle( - getbtVector(vertices[a] * transform), - getbtVector(vertices[c] * transform), - getbtVector(vertices[b] * transform) + Misc::Convert::toBullet(vertices[a] * transform), + Misc::Convert::toBullet(vertices[c] * transform), + Misc::Convert::toBullet(vertices[b] * transform) ); } } @@ -106,17 +102,12 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD } } -void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::Node* nifNode, const osg::Matrixf &transform) +void fillTriangleMesh(btTriangleMesh& mesh, const Nif::Node* nifNode, const osg::Matrixf &transform = osg::Matrixf()) { if (nifNode->recType == Nif::RC_NiTriShape) - fillTriangleMeshWithTransform(mesh, static_cast(nifNode)->data.get(), transform); - else // if (nifNode->recType == Nif::RC_NiTriStrips) - fillTriangleMeshWithTransform(mesh, static_cast(nifNode)->data.get(), transform); -} - -void fillTriangleMesh(btTriangleMesh& mesh, const Nif::Node* node) -{ - fillTriangleMeshWithTransform(mesh, node, osg::Matrixf()); + fillTriangleMesh(mesh, static_cast(nifNode)->data.get(), transform); + else if (nifNode->recType == Nif::RC_NiTriStrips) + fillTriangleMesh(mesh, static_cast(nifNode)->data.get(), transform); } } @@ -149,10 +140,12 @@ osg::ref_ptr BulletNifLoader::load(const Nif::File& nif) if (findBoundingBox(node)) { + const btVector3 halfExtents = Misc::Convert::toBullet(mShape->mCollisionBoxHalfExtents); + const btVector3 origin = Misc::Convert::toBullet(mShape->mCollisionBoxTranslate); std::unique_ptr compound (new btCompoundShape); - std::unique_ptr boxShape(new btBoxShape(getbtVector(mShape->mCollisionBoxHalfExtents))); + std::unique_ptr boxShape(new btBoxShape(halfExtents)); btTransform transform = btTransform::getIdentity(); - transform.setOrigin(getbtVector(mShape->mCollisionBoxTranslate)); + transform.setOrigin(origin); compound->addChildShape(transform, boxShape.get()); boxShape.release(); @@ -383,7 +376,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons if (!mAvoidStaticMesh) mAvoidStaticMesh.reset(new btTriangleMesh(false)); - fillTriangleMeshWithTransform(*mAvoidStaticMesh, nifNode, transform); + fillTriangleMesh(*mAvoidStaticMesh, nifNode, transform); } else { @@ -391,7 +384,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons mStaticMesh.reset(new btTriangleMesh(false)); // Static shape, just transform all vertices into position - fillTriangleMeshWithTransform(*mStaticMesh, nifNode, transform); + fillTriangleMesh(*mStaticMesh, nifNode, transform); } } diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 7a592fb4a..805283b42 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -60,6 +60,18 @@ namespace } } + bool isTypeGeometry(int type) + { + switch (type) + { + case Nif::RC_NiTriShape: + case Nif::RC_NiTriStrips: + case Nif::RC_NiLines: + return true; + } + return false; + } + // Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the node hierarchy above it. void collectDrawableProperties(const Nif::Node* nifNode, std::vector& out) { @@ -528,7 +540,19 @@ namespace NifOsg // - finding a random child NiNode in NiBspArrayController node->setUserValue("recIndex", nifNode->recIndex); + std::vector extraCollection; + for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next) + extraCollection.emplace_back(e); + + for (size_t i = 0; i < nifNode->extralist.length(); ++i) + { + Nif::ExtraPtr e = nifNode->extralist[i]; + if (!e.empty()) + extraCollection.emplace_back(e); + } + + for (const auto& e : extraCollection) { if(e->recType == Nif::RC_NiTextKeyExtraData && textKeys) { @@ -584,7 +608,7 @@ namespace NifOsg applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags); - const bool isGeometry = nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines; + const bool isGeometry = isTypeGeometry(nifNode->recType); if (isGeometry && !skipMeshes) { @@ -1175,7 +1199,7 @@ namespace NifOsg void handleGeometry(const Nif::Node* nifNode, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { - assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines); + assert(isTypeGeometry(nifNode->recType)); osg::ref_ptr drawable; osg::ref_ptr geom (new osg::Geometry); handleNiGeometry(nifNode, geom, parentNode, composite, boundTextures, animflags); @@ -1220,7 +1244,7 @@ namespace NifOsg void handleSkinnedGeometry(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { - assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines); + assert(isTypeGeometry(nifNode->recType)); osg::ref_ptr geometry (new osg::Geometry); handleNiGeometry(nifNode, geometry, parentNode, composite, boundTextures, animflags); osg::ref_ptr rig(new SceneUtil::RigGeometry); From afea11b70a851e6d56c7e8da355c533b73659b15 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 7 Nov 2020 03:40:21 +0300 Subject: [PATCH 070/111] Read NiStringPalette and NiBoolData --- components/nif/data.cpp | 25 +++++++++++++++++++++++++ components/nif/data.hpp | 12 ++++++++++++ components/nif/niffile.cpp | 2 ++ components/nif/record.hpp | 4 +++- components/nif/recordptr.hpp | 2 ++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 5b0b99c53..4df464fdf 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -392,4 +392,29 @@ void NiPalette::read(NIFStream *nif) colors[i] = nif->getUInt() | alphaMask; } +void NiStringPalette::read(NIFStream *nif) +{ + unsigned int size = nif->getUInt(); + if (!size) + return; + std::vector source; + nif->getChars(source, size); + if (nif->getUInt() != size) + nif->file->warn("Failed size check in NiStringPalette"); + if (source[source.size()-1] != '\0') + source.emplace_back('\0'); + const char* buffer = source.data(); + while (static_cast(buffer - source.data()) < source.size()) + { + palette.emplace_back(buffer); + buffer += palette.back().size() + 1; + } +} + +void NiBoolData::read(NIFStream *nif) +{ + mKeyList = std::make_shared(); + mKeyList->read(nif); +} + } // Namespace diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 0ba544645..d0ea150e0 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -240,5 +240,17 @@ public: void read(NIFStream *nif) override; }; +struct NiStringPalette : public Record +{ + std::vector palette; + void read(NIFStream *nif) override; +}; + +struct NiBoolData : public Record +{ + ByteKeyMapPtr mKeyList; + void read(NIFStream *nif) override; +}; + } // Namespace #endif diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 098f6aba2..b50b602d5 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -116,6 +116,8 @@ static std::map makeFactory() factory["NiColorExtraData"] = {&construct , RC_NiColorExtraData }; factory["NiFloatExtraData"] = {&construct , RC_NiFloatExtraData }; factory["NiFloatsExtraData"] = {&construct , RC_NiFloatsExtraData }; + factory["NiStringPalette"] = {&construct , RC_NiStringPalette }; + factory["NiBoolData"] = {&construct , RC_NiBoolData }; return factory; } diff --git a/components/nif/record.hpp b/components/nif/record.hpp index eb26b0cce..0e8b80ffa 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -109,7 +109,9 @@ enum RecordType RC_NiVectorExtraData, RC_NiColorExtraData, RC_NiFloatExtraData, - RC_NiFloatsExtraData + RC_NiFloatsExtraData, + RC_NiStringPalette, + RC_NiBoolData }; /// Base class for all records diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 57607cb6a..d0b3d00ab 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -143,6 +143,7 @@ class NiAutoNormalParticlesData; class NiPalette; struct NiParticleModifier; struct NiLinesData; +struct NiBoolData; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -166,6 +167,7 @@ using NiRotatingParticlesDataPtr = RecordPtrT; using NiAutoNormalParticlesDataPtr = RecordPtrT; using NiPalettePtr = RecordPtrT; using NiParticleModifierPtr = RecordPtrT; +using NiBoolDataPtr = RecordPtrT; using NodeList = RecordListT; using PropertyList = RecordListT; From a38c6294250b043cb6180670956e5af12ffb99fa Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 7 Nov 2020 04:04:46 +0300 Subject: [PATCH 071/111] Read NiSkinPartition --- components/nif/data.cpp | 65 +++++++++++++++++++++++++++++++++++- components/nif/data.hpp | 20 +++++++++++ components/nif/niffile.cpp | 1 + components/nif/record.hpp | 3 +- components/nif/recordptr.hpp | 2 ++ 5 files changed, 89 insertions(+), 2 deletions(-) diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 4df464fdf..6bbab9786 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -320,7 +320,7 @@ void NiSkinData::read(NIFStream *nif) int boneNum = nif->getInt(); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFStream::generateVersion(10,1,0,0)) - nif->skip(4); // NiSkinPartition link + partitions.read(nif); // Has vertex weights flag if (nif->getVersion() > NIFStream::generateVersion(4,2,1,0) && !nif->getBoolean()) @@ -345,6 +345,69 @@ void NiSkinData::read(NIFStream *nif) } } +void NiSkinData::post(NIFFile *nif) +{ + partitions.post(nif); +} + +void NiSkinPartition::read(NIFStream *nif) +{ + unsigned int num = nif->getUInt(); + data.resize(num); + for (auto& partition : data) + partition.read(nif); +} + +void NiSkinPartition::Partition::read(NIFStream *nif) +{ + unsigned short numVertices = nif->getUShort(); + unsigned short numTriangles = nif->getUShort(); + unsigned short numBones = nif->getUShort(); + unsigned short numStrips = nif->getUShort(); + unsigned short bonesPerVertex = nif->getUShort(); + if (numBones) + nif->getUShorts(bones, numBones); + + bool hasVertexMap = true; + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + hasVertexMap = nif->getBoolean(); + if (hasVertexMap && numVertices) + nif->getUShorts(vertexMap, numVertices); + + bool hasVertexWeights = true; + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + hasVertexWeights = nif->getBoolean(); + if (hasVertexWeights && numVertices && bonesPerVertex) + nif->getFloats(weights, numVertices * bonesPerVertex); + + std::vector stripLengths; + if (numStrips) + nif->getUShorts(stripLengths, numStrips); + + bool hasFaces = true; + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0)) + hasFaces = nif->getBoolean(); + if (hasFaces) + { + if (numStrips) + { + strips.resize(numStrips); + for (unsigned short i = 0; i < numStrips; i++) + nif->getUShorts(strips[i], stripLengths[i]); + } + else if (numTriangles) + nif->getUShorts(triangles, numTriangles * 3); + } + bool hasBoneIndices = nif->getChar() != 0; + if (hasBoneIndices && numVertices && bonesPerVertex) + nif->getChars(boneIndices, numVertices * bonesPerVertex); + if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3) + { + nif->getChar(); // LOD level + nif->getBoolean(); // Global VB + } +} + void NiMorphData::read(NIFStream *nif) { int morphCount = nif->getInt(); diff --git a/components/nif/data.hpp b/components/nif/data.hpp index d0ea150e0..4d13afb9d 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -174,6 +174,7 @@ class NiSkinInstance : public Record { public: NiSkinDataPtr data; + NiSkinPartitionPtr partitions; NodePtr root; NodeList bones; @@ -200,6 +201,25 @@ public: Transformation trafo; std::vector bones; + NiSkinPartitionPtr partitions; + + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiSkinPartition : public Record +{ + struct Partition + { + std::vector bones; + std::vector vertexMap; + std::vector weights; + std::vector> strips; + std::vector triangles; + std::vector boneIndices; + void read(NIFStream *nif); + }; + std::vector data; void read(NIFStream *nif) override; }; diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index b50b602d5..04cac535c 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -118,6 +118,7 @@ static std::map makeFactory() factory["NiFloatsExtraData"] = {&construct , RC_NiFloatsExtraData }; factory["NiStringPalette"] = {&construct , RC_NiStringPalette }; factory["NiBoolData"] = {&construct , RC_NiBoolData }; + factory["NiSkinPartition"] = {&construct , RC_NiSkinPartition }; return factory; } diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 0e8b80ffa..2a6be58e2 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -111,7 +111,8 @@ enum RecordType RC_NiFloatExtraData, RC_NiFloatsExtraData, RC_NiStringPalette, - RC_NiBoolData + RC_NiBoolData, + RC_NiSkinPartition }; /// Base class for all records diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index d0b3d00ab..2748f4073 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -144,6 +144,7 @@ class NiPalette; struct NiParticleModifier; struct NiLinesData; struct NiBoolData; +struct NiSkinPartition; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -168,6 +169,7 @@ using NiAutoNormalParticlesDataPtr = RecordPtrT; using NiPalettePtr = RecordPtrT; using NiParticleModifierPtr = RecordPtrT; using NiBoolDataPtr = RecordPtrT; +using NiSkinPartitionPtr = RecordPtrT; using NodeList = RecordListT; using PropertyList = RecordListT; From 96769ab4a5a1c8df30842497a2e94be7f83a780d Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 8 Nov 2020 13:53:52 +0300 Subject: [PATCH 072/111] Try to reword unsupported NIF loading docs --- .../reference/modding/settings/models.rst | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/source/reference/modding/settings/models.rst b/docs/source/reference/modding/settings/models.rst index da56a1709..b0da374d6 100644 --- a/docs/source/reference/modding/settings/models.rst +++ b/docs/source/reference/modding/settings/models.rst @@ -8,20 +8,24 @@ load unsupported nif files :Range: True/False :Default: False -At the moment OpenMW's NIF loader is only tailored to load models -that can also load in Morrowind. +Allow the engine to load arbitrary NIF files as long as they appear to be valid. -However, you can enable its limited and experimental support for updates in -the definitions of record types from later NIF revisions by toggling on -this setting. +OpenMW has limited and **experimental** support for NIF files +that Morrowind itself cannot load, which normally goes unused. -You must keep in mind that loading unsupported NIF files may fail, -and the degree of this failure may vary. In milder cases, OpenMW will reject -the file anyway because it lacks a definition for a certain record type -that the file may use. In more severe cases OpenMW's -incomplete understanding of a record type can lead to memory corruption, -crashes or even freezes. Don't enable this if you're not sure that -you know what you're doing. +If enabled, this setting allows the NIF loader to make use of that functionality. + +.. warning:: + You must keep in mind that since the mentioned support is experimental, + loading unsupported NIF files may fail, and the degree of this failure may vary. + + In milder cases, OpenMW will reject the file anyway because + it lacks a definition for a certain record type that the file may use. + + In more severe cases OpenMW's incomplete understanding of a record type + can lead to memory corruption, freezes or even crashes. + + **Do not enable** this if you're not so sure that you know what you're doing. To help debug possible issues OpenMW will log its progress in loading every file that uses an unsupported NIF version. From 1d07361f08233dce6e02e73fae51859861430b14 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Mon, 9 Nov 2020 00:19:35 +0300 Subject: [PATCH 073/111] Read a few more NIF types BSXFlags, NiTransformData, BSBound, BSFadeNode, bhkBlendController --- components/nif/controller.cpp | 6 ++++++ components/nif/controller.hpp | 5 +++++ components/nif/extra.cpp | 6 ++++++ components/nif/extra.hpp | 7 +++++++ components/nif/niffile.cpp | 5 +++++ components/nif/record.hpp | 5 ++++- 6 files changed, 33 insertions(+), 1 deletion(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 07699239e..1f1dd01c1 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -228,4 +228,10 @@ namespace Nif mSources.post(nif); } + void bhkBlendController::read(NIFStream *nif) + { + Controller::read(nif); + nif->getUInt(); // Zero + } + } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 54cf9bf8f..ac6783b8d 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -183,5 +183,10 @@ public: void post(NIFFile *nif) override; }; +struct bhkBlendController : public Controller +{ + void read(NIFStream *nif) override; +}; + } // Namespace #endif diff --git a/components/nif/extra.cpp b/components/nif/extra.cpp index d08e5d738..eeaf9d3ac 100644 --- a/components/nif/extra.cpp +++ b/components/nif/extra.cpp @@ -80,5 +80,11 @@ void NiFloatsExtraData::read(NIFStream *nif) nif->getFloats(data, num); } +void BSBound::read(NIFStream *nif) +{ + Extra::read(nif); + center = nif->getVector3(); + halfExtents = nif->getVector3(); +} } diff --git a/components/nif/extra.hpp b/components/nif/extra.hpp index 3be627004..5d7aa0c3b 100644 --- a/components/nif/extra.hpp +++ b/components/nif/extra.hpp @@ -109,5 +109,12 @@ struct NiFloatsExtraData : public Extra void read(NIFStream *nif) override; }; +struct BSBound : public Extra +{ + osg::Vec3f center, halfExtents; + + void read(NIFStream *nif) override; +}; + } // Namespace #endif diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 04cac535c..8214a8288 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -119,6 +119,11 @@ static std::map makeFactory() factory["NiStringPalette"] = {&construct , RC_NiStringPalette }; factory["NiBoolData"] = {&construct , RC_NiBoolData }; factory["NiSkinPartition"] = {&construct , RC_NiSkinPartition }; + factory["BSXFlags"] = {&construct , RC_BSXFlags }; + factory["BSBound"] = {&construct , RC_BSBound }; + factory["NiTransformData"] = {&construct , RC_NiKeyframeData }; + factory["BSFadeNode"] = {&construct , RC_NiNode }; + factory["bhkBlendController"] = {&construct , RC_bhkBlendController }; return factory; } diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 2a6be58e2..d3ee01fd4 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -112,7 +112,10 @@ enum RecordType RC_NiFloatsExtraData, RC_NiStringPalette, RC_NiBoolData, - RC_NiSkinPartition + RC_NiSkinPartition, + RC_BSXFlags, + RC_BSBound, + RC_bhkBlendController }; /// Base class for all records From b52357409011ce7b19bf9df8b554975a7fcf9e7c Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Mon, 9 Nov 2020 13:53:58 +0300 Subject: [PATCH 074/111] Remove shader visitor settings manager dependency --- apps/openmw/mwrender/renderingmanager.cpp | 1 + components/resource/scenemanager.cpp | 7 +++++++ components/resource/scenemanager.hpp | 3 +++ components/shader/shadervisitor.cpp | 13 ++++++++----- components/shader/shadervisitor.hpp | 4 ++++ 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 0aef614c8..8e5a01eaf 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -216,6 +216,7 @@ namespace MWRender resourceSystem->getSceneManager()->setNormalHeightMapPattern(Settings::Manager::getString("normal height map pattern", "Shaders")); resourceSystem->getSceneManager()->setAutoUseSpecularMaps(Settings::Manager::getBool("auto use object specular maps", "Shaders")); resourceSystem->getSceneManager()->setSpecularMapPattern(Settings::Manager::getString("specular map pattern", "Shaders")); + resourceSystem->getSceneManager()->setApplyLightingToEnvMaps(Settings::Manager::getBool("apply lighting to environment maps", "Shaders")); osg::ref_ptr sceneRoot = new SceneUtil::LightManager; sceneRoot->setLightingMask(Mask_Lighting); diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 571ea6d0d..44ba7e687 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -220,6 +220,7 @@ namespace Resource , mClampLighting(true) , mAutoUseNormalMaps(false) , mAutoUseSpecularMaps(false) + , mApplyLightingToEnvMaps(false) , mInstanceCache(new MultiObjectCache) , mSharedStateManager(new SharedStateManager) , mImageManager(imageManager) @@ -284,6 +285,11 @@ namespace Resource mSpecularMapPattern = pattern; } + void SceneManager::setApplyLightingToEnvMaps(bool apply) + { + mApplyLightingToEnvMaps = apply; + } + SceneManager::~SceneManager() { // this has to be defined in the .cpp file as we can't delete incomplete types @@ -770,6 +776,7 @@ namespace Resource shaderVisitor->setNormalHeightMapPattern(mNormalHeightMapPattern); shaderVisitor->setAutoUseSpecularMaps(mAutoUseSpecularMaps); shaderVisitor->setSpecularMapPattern(mSpecularMapPattern); + shaderVisitor->setApplyLightingToEnvMaps(mApplyLightingToEnvMaps); return shaderVisitor; } diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index 0ee32a9b7..8df556158 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -73,6 +73,8 @@ namespace Resource void setSpecularMapPattern(const std::string& pattern); + void setApplyLightingToEnvMaps(bool apply); + void setShaderPath(const std::string& path); /// Check if a given scene is loaded and if so, update its usage timestamp to prevent it from being unloaded @@ -156,6 +158,7 @@ namespace Resource std::string mNormalHeightMapPattern; bool mAutoUseSpecularMaps; std::string mSpecularMapPattern; + bool mApplyLightingToEnvMaps; osg::ref_ptr mInstanceCache; diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 0eab2fd89..e11f09930 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include "shadermanager.hpp" @@ -43,6 +42,7 @@ namespace Shader , mAllowedToModifyStateSets(true) , mAutoUseNormalMaps(false) , mAutoUseSpecularMaps(false) + , mApplyLightingToEnvMaps(false) , mShaderManager(shaderManager) , mImageManager(imageManager) , mDefaultVsTemplate(defaultVsTemplate) @@ -144,11 +144,9 @@ namespace Shader // Bump maps are off by default as well writableStateSet->setTextureMode(unit, GL_TEXTURE_2D, osg::StateAttribute::ON); } - else if (texName == "envMap") + else if (texName == "envMap" && mApplyLightingToEnvMaps) { - static const bool preLightEnv = Settings::Manager::getBool("apply lighting to environment maps", "Shaders"); - if (preLightEnv) - mRequirements.back().mShaderRequired = true; + mRequirements.back().mShaderRequired = true; } } else @@ -477,4 +475,9 @@ namespace Shader mSpecularMapPattern = pattern; } + void ShaderVisitor::setApplyLightingToEnvMaps(bool apply) + { + mApplyLightingToEnvMaps = apply; + } + } diff --git a/components/shader/shadervisitor.hpp b/components/shader/shadervisitor.hpp index bf1022180..3089845a3 100644 --- a/components/shader/shadervisitor.hpp +++ b/components/shader/shadervisitor.hpp @@ -38,6 +38,8 @@ namespace Shader void setSpecularMapPattern(const std::string& pattern); + void setApplyLightingToEnvMaps(bool apply); + void apply(osg::Node& node) override; void apply(osg::Drawable& drawable) override; @@ -59,6 +61,8 @@ namespace Shader bool mAutoUseSpecularMaps; std::string mSpecularMapPattern; + bool mApplyLightingToEnvMaps; + ShaderManager& mShaderManager; Resource::ImageManager& mImageManager; From c857588ee9234972918d727ed076269f43abcaa4 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Mon, 9 Nov 2020 14:22:48 +0300 Subject: [PATCH 075/111] Remove NIFFile settings manager dependency --- apps/niftest/niftest.cpp | 1 + apps/openmw/mwrender/renderingmanager.cpp | 1 + components/nif/niffile.cpp | 12 ++++++++---- components/nif/niffile.hpp | 4 ++++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/niftest/niftest.cpp b/apps/niftest/niftest.cpp index f848ae330..e9484d5f5 100644 --- a/apps/niftest/niftest.cpp +++ b/apps/niftest/niftest.cpp @@ -132,6 +132,7 @@ int main(int argc, char **argv) if(!parseOptions (argc, argv, files)) return 1; + Nif::NIFFile::setLoadUnsupportedFiles(true); // std::cout << "Reading Files" << std::endl; for(std::vector::const_iterator it=files.begin(); it!=files.end(); ++it) { diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 0aef614c8..068b3e46c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -361,6 +361,7 @@ namespace MWRender mViewer->getCamera()->setCullMask(~(Mask_UpdateVisitor|Mask_SimpleWater)); NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor); NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect); + Nif::NIFFile::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models")); mNearClip = Settings::Manager::getFloat("near clip", "Camera"); mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera"); diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 8214a8288..06b4a89d0 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -5,8 +5,6 @@ #include #include -#include - namespace Nif { @@ -182,8 +180,7 @@ void NIFFile::parse(Files::IStreamPtr stream) } if (!supported) { - static const bool ignoreUnsupported = Settings::Manager::getBool("load unsupported nif files", "Models"); - if (ignoreUnsupported) + if (sLoadUnsupportedFiles) warn("Unsupported NIF version: " + printVersion(ver) + ". Proceed with caution!"); else fail("Unsupported NIF version: " + printVersion(ver)); @@ -331,4 +328,11 @@ bool NIFFile::getUseSkinning() const return mUseSkinning; } +bool NIFFile::sLoadUnsupportedFiles = false; + +void NIFFile::setLoadUnsupportedFiles(bool load) +{ + sLoadUnsupportedFiles = load; +} + } diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 9d8edac26..c6dd8af75 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -62,6 +62,8 @@ class NIFFile final : public File bool mUseSkinning = false; + static bool sLoadUnsupportedFiles; + /// Parse the file void parse(Files::IStreamPtr stream); @@ -149,6 +151,8 @@ public: /// Get the Bethesda version of the NIF format used unsigned int getBethVersion() const override { return bethVer; } + + static void setLoadUnsupportedFiles(bool load); }; using NIFFilePtr = std::shared_ptr; From b8ed3b0059758a9f0dfd87ef4dd1430e1ac0dca4 Mon Sep 17 00:00:00 2001 From: corristo Date: Tue, 10 Nov 2020 08:21:46 +0000 Subject: [PATCH 076/111] [macOS, CI] Update dependencies, don't use lz4 from Homebrew Also, enable double precision support for Bullet. --- CI/before_install.osx.sh | 5 +---- CI/before_script.osx.sh | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh index fd77e0693..85434fa06 100755 --- a/CI/before_install.osx.sh +++ b/CI/before_install.osx.sh @@ -5,8 +5,5 @@ command -v ccache >/dev/null 2>&1 || brew install ccache command -v cmake >/dev/null 2>&1 || brew install cmake command -v qmake >/dev/null 2>&1 || brew install qt -brew link --overwrite lz4 # overwrite system lz4; use brew -brew reinstall lz4 - -curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-ef2462c.zip -o ~/openmw-deps.zip +curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-f8918dd.zip -o ~/openmw-deps.zip unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index e11ef1b58..8f9be16e1 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -25,5 +25,6 @@ cmake \ -D BUILD_BSATOOL=TRUE \ -D BUILD_ESSIMPORTER=TRUE \ -D BUILD_NIFTEST=TRUE \ +-D BULLET_USE_DOUBLES=TRUE \ -G"Unix Makefiles" \ .. From f3f5dcb016507e3661583c40661137dc53200b83 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Tue, 10 Nov 2020 22:30:44 +0300 Subject: [PATCH 077/111] Read a few more NIF types NiFloatInterpolator, NiPoint3Interpolator, NiTransformInterpolator, NiBoolInterpolator Update a few existing controller records Update NiSkinInstance --- components/nif/controller.cpp | 96 +++++++++++++++++++++++++++++++- components/nif/controller.hpp | 42 ++++++++++++++ components/nif/data.cpp | 5 +- components/nif/niffile.cpp | 5 ++ components/nif/nifkey.hpp | 15 ++++- components/nif/record.hpp | 6 +- components/nif/recordptr.hpp | 7 +++ components/nifosg/controller.cpp | 53 ++++++++++++++++-- components/nifosg/controller.hpp | 41 ++++++++++++++ components/nifosg/nifloader.cpp | 50 +++++++++++++---- 10 files changed, 299 insertions(+), 21 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 1f1dd01c1..2cd61950b 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -92,6 +92,8 @@ namespace Nif void NiMaterialColorController::read(NIFStream *nif) { Controller::read(nif); + if (nif->getVersion() > NIFStream::generateVersion(10,1,0,103)) + interpolator.read(nif); // Two bits that correspond to the controlled material color. // 00: Ambient // 01: Diffuse @@ -101,12 +103,14 @@ namespace Nif targetColor = nif->getUShort() & 3; else targetColor = (flags >> 4) & 3; - data.read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) + data.read(nif); } void NiMaterialColorController::post(NIFFile *nif) { Controller::post(nif); + interpolator.post(nif); data.post(nif); } @@ -161,25 +165,33 @@ namespace Nif void NiKeyframeController::read(NIFStream *nif) { Controller::read(nif); - data.read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) + data.read(nif); + else + interpolator.read(nif); } void NiKeyframeController::post(NIFFile *nif) { Controller::post(nif); data.post(nif); + interpolator.post(nif); } void NiFloatInterpController::read(NIFStream *nif) { Controller::read(nif); - data.read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) + data.read(nif); + else + interpolator.read(nif); } void NiFloatInterpController::post(NIFFile *nif) { Controller::post(nif); data.post(nif); + interpolator.post(nif); } void NiGeomMorpherController::read(NIFStream *nif) @@ -189,13 +201,33 @@ namespace Nif /*bool updateNormals = !!*/nif->getUShort(); data.read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) + { /*bool alwaysActive = */nif->getChar(); // Always 0 + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,106)) + { + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) + { + interpolators.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0) && nif->getBethVersion() > 9) + { + unsigned int numUnknown = nif->getUInt(); + nif->skip(4 * numUnknown); + } + } + else + { + unsigned int numInterps = nif->getUInt(); + nif->skip(8 * numInterps); + } + } + } } void NiGeomMorpherController::post(NIFFile *nif) { Controller::post(nif); data.post(nif); + interpolators.post(nif); } void NiVisController::read(NIFStream *nif) @@ -213,6 +245,8 @@ namespace Nif void NiFlipController::read(NIFStream *nif) { Controller::read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,2,0,0)) + mInterpolator.read(nif); mTexSlot = nif->getUInt(); if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,103)) { @@ -225,6 +259,7 @@ namespace Nif void NiFlipController::post(NIFFile *nif) { Controller::post(nif); + mInterpolator.post(nif); mSources.post(nif); } @@ -234,4 +269,59 @@ namespace Nif nif->getUInt(); // Zero } + void NiPoint3Interpolator::read(NIFStream *nif) + { + defaultVal = nif->getVector3(); + data.read(nif); + } + + void NiPoint3Interpolator::post(NIFFile *nif) + { + data.post(nif); + } + + void NiBoolInterpolator::read(NIFStream *nif) + { + defaultVal = nif->getBoolean(); + data.read(nif); + } + + void NiBoolInterpolator::post(NIFFile *nif) + { + data.post(nif); + } + + void NiFloatInterpolator::read(NIFStream *nif) + { + defaultVal = nif->getFloat(); + data.read(nif); + } + + void NiFloatInterpolator::post(NIFFile *nif) + { + data.post(nif); + } + + void NiTransformInterpolator::read(NIFStream *nif) + { + defaultPos = nif->getVector3(); + defaultRot = nif->getQuaternion(); + defaultScale = nif->getFloat(); + if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,109)) + { + if (!nif->getBoolean()) + defaultPos = osg::Vec3f(); + if (!nif->getBoolean()) + defaultRot = osg::Quat(); + if (!nif->getBoolean()) + defaultScale = 1.f; + } + data.read(nif); + } + + void NiTransformInterpolator::post(NIFFile *nif) + { + data.post(nif); + } + } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index ac6783b8d..6b84d3749 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -83,6 +83,7 @@ using NiBSPArrayController = NiParticleSystemController; class NiMaterialColorController : public Controller { public: + NiPoint3InterpolatorPtr interpolator; NiPosDataPtr data; unsigned int targetColor; @@ -138,6 +139,7 @@ class NiKeyframeController : public Controller { public: NiKeyframeDataPtr data; + NiTransformInterpolatorPtr interpolator; void read(NIFStream *nif) override; void post(NIFFile *nif) override; @@ -146,6 +148,7 @@ public: struct NiFloatInterpController : public Controller { NiFloatDataPtr data; + NiFloatInterpolatorPtr interpolator; void read(NIFStream *nif) override; void post(NIFFile *nif) override; @@ -158,6 +161,7 @@ class NiGeomMorpherController : public Controller { public: NiMorphDataPtr data; + NiFloatInterpolatorList interpolators; void read(NIFStream *nif) override; void post(NIFFile *nif) override; @@ -175,6 +179,7 @@ public: class NiFlipController : public Controller { public: + NiFloatInterpolatorPtr mInterpolator; int mTexSlot; // NiTexturingProperty::TextureType float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources NiSourceTextureList mSources; @@ -188,5 +193,42 @@ struct bhkBlendController : public Controller void read(NIFStream *nif) override; }; +struct Interpolator : public Record { }; + +struct NiPoint3Interpolator : public Interpolator +{ + osg::Vec3f defaultVal; + NiPosDataPtr data; + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiBoolInterpolator : public Interpolator +{ + bool defaultVal; + NiBoolDataPtr data; + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiFloatInterpolator : public Interpolator +{ + float defaultVal; + NiFloatDataPtr data; + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + +struct NiTransformInterpolator : public Interpolator +{ + osg::Vec3f defaultPos; + osg::Quat defaultRot; + float defaultScale; + NiKeyframeDataPtr data; + + void read(NIFStream *nif) override; + void post(NIFFile *nif) override; +}; + } // Namespace #endif diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 6bbab9786..1eb5c40fe 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -6,6 +6,8 @@ namespace Nif void NiSkinInstance::read(NIFStream *nif) { data.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,101)) + partitions.read(nif); root.read(nif); bones.read(nif); } @@ -13,6 +15,7 @@ void NiSkinInstance::read(NIFStream *nif) void NiSkinInstance::post(NIFFile *nif) { data.post(nif); + partitions.post(nif); root.post(nif); bones.post(nif); @@ -418,7 +421,7 @@ void NiMorphData::read(NIFStream *nif) for(int i = 0;i < morphCount;i++) { mMorphs[i].mKeyFrames = std::make_shared(); - mMorphs[i].mKeyFrames->read(nif, true); + mMorphs[i].mKeyFrames->read(nif, true, /*morph*/true); nif->getVector3s(mMorphs[i].mVertices, vertCount); } } diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 06b4a89d0..7915908d1 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -122,6 +122,11 @@ static std::map makeFactory() factory["NiTransformData"] = {&construct , RC_NiKeyframeData }; factory["BSFadeNode"] = {&construct , RC_NiNode }; factory["bhkBlendController"] = {&construct , RC_bhkBlendController }; + factory["NiFloatInterpolator"] = {&construct , RC_NiFloatInterpolator }; + factory["NiBoolInterpolator"] = {&construct , RC_NiBoolInterpolator }; + factory["NiPoint3Interpolator"] = {&construct , RC_NiPoint3Interpolator }; + factory["NiTransformController"] = {&construct , RC_NiKeyframeController }; + factory["NiTransformInterpolator"] = {&construct , RC_NiTransformInterpolator }; return factory; } diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index 4c10327e1..de2fa31c8 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -52,16 +52,27 @@ struct KeyMapT { MapType mKeys; //Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) - void read(NIFStream *nif, bool force=false) + void read(NIFStream *nif, bool force = false, bool morph = false) { assert(nif); mInterpolationType = InterpolationType_Unknown; + if (morph && nif->getVersion() >= NIFStream::generateVersion(10,1,0,106)) + nif->getString(); // Frame name + size_t count = nif->getUInt(); - if(count == 0 && !force) + if (count == 0 && !force && !morph) return; + if (morph && nif->getVersion() > NIFStream::generateVersion(10,1,0,0)) + { + if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,104) && + nif->getVersion() <= NIFStream::generateVersion(20,1,0,2) && nif->getBethVersion() < 10) + nif->getFloat(); // Legacy weight + return; + } + mKeys.clear(); mInterpolationType = nif->getUInt(); diff --git a/components/nif/record.hpp b/components/nif/record.hpp index d3ee01fd4..c5773643a 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -115,7 +115,11 @@ enum RecordType RC_NiSkinPartition, RC_BSXFlags, RC_BSBound, - RC_bhkBlendController + RC_bhkBlendController, + RC_NiFloatInterpolator, + RC_NiPoint3Interpolator, + RC_NiBoolInterpolator, + RC_NiTransformInterpolator, }; /// Base class for all records diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 2748f4073..b40a17583 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -145,6 +145,9 @@ struct NiParticleModifier; struct NiLinesData; struct NiBoolData; struct NiSkinPartition; +struct NiFloatInterpolator; +struct NiPoint3Interpolator; +struct NiTransformInterpolator; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -170,11 +173,15 @@ using NiPalettePtr = RecordPtrT; using NiParticleModifierPtr = RecordPtrT; using NiBoolDataPtr = RecordPtrT; using NiSkinPartitionPtr = RecordPtrT; +using NiFloatInterpolatorPtr = RecordPtrT; +using NiPoint3InterpolatorPtr = RecordPtrT; +using NiTransformInterpolatorPtr = RecordPtrT; using NodeList = RecordListT; using PropertyList = RecordListT; using ExtraList = RecordListT; using NiSourceTextureList = RecordListT; +using NiFloatInterpolatorList = RecordListT; } // Namespace #endif diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 9c654b9d1..c0f7522d5 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -92,6 +92,26 @@ KeyframeController::KeyframeController(const Nif::NiKeyframeData *data) { } +KeyframeController::KeyframeController(const Nif::NiTransformInterpolator* interpolator) + : mRotations(interpolator->data->mRotations, interpolator->defaultRot) + , mXRotations(interpolator->data->mXRotations, 0.f) + , mYRotations(interpolator->data->mYRotations, 0.f) + , mZRotations(interpolator->data->mZRotations, 0.f) + , mTranslations(interpolator->data->mTranslations, interpolator->defaultPos) + , mScales(interpolator->data->mScales, interpolator->defaultScale) +{ +} + +KeyframeController::KeyframeController(const float scale, const osg::Vec3f& pos, const osg::Quat& rot) + : mRotations(Nif::QuaternionKeyMapPtr(), rot) + , mXRotations(Nif::FloatKeyMapPtr(), 0.f) + , mYRotations(Nif::FloatKeyMapPtr(), 0.f) + , mZRotations(Nif::FloatKeyMapPtr(), 0.f) + , mTranslations(Nif::Vector3KeyMapPtr(), pos) + , mScales(Nif::FloatKeyMapPtr(), scale) +{ +} + osg::Quat KeyframeController::getXYZRotation(float time) const { float xrot = 0, yrot = 0, zrot = 0; @@ -313,6 +333,11 @@ RollController::RollController(const Nif::NiFloatData *data) { } +RollController::RollController(const Nif::NiFloatInterpolator* interpolator) + : mData(interpolator) +{ +} + RollController::RollController(const RollController ©, const osg::CopyOp ©op) : osg::NodeCallback(copy, copyop) , Controller(copy) @@ -344,6 +369,10 @@ void RollController::operator() (osg::Node* node, osg::NodeVisitor* nv) } } +AlphaController::AlphaController() +{ +} + AlphaController::AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial) : mData(data->mKeyList, 1.f) , mBaseMaterial(baseMaterial) @@ -351,7 +380,9 @@ AlphaController::AlphaController(const Nif::NiFloatData *data, const osg::Materi } -AlphaController::AlphaController() +AlphaController::AlphaController(const Nif::NiFloatInterpolator* interpolator, const osg::Material* baseMaterial) + : mData(interpolator) + , mBaseMaterial(baseMaterial) { } @@ -379,6 +410,10 @@ void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv) } } +MaterialColorController::MaterialColorController() +{ +} + MaterialColorController::MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial) : mData(data->mKeyList, osg::Vec3f(1,1,1)) , mTargetColor(color) @@ -386,7 +421,10 @@ MaterialColorController::MaterialColorController(const Nif::NiPosData *data, Tar { } -MaterialColorController::MaterialColorController() +MaterialColorController::MaterialColorController(const Nif::NiPoint3Interpolator* interpolator, TargetColor color, const osg::Material* baseMaterial) + : mData(interpolator) + , mTargetColor(color) + , mBaseMaterial(baseMaterial) { } @@ -448,6 +486,8 @@ FlipController::FlipController(const Nif::NiFlipController *ctrl, const std::vec , mDelta(ctrl->mDelta) , mTextures(textures) { + if (!ctrl->mInterpolator.empty()) + mData = ctrl->mInterpolator.getPtr(); } FlipController::FlipController(int texSlot, float delta, const std::vector >& textures) @@ -463,14 +503,19 @@ FlipController::FlipController(const FlipController ©, const osg::CopyOp &co , mTexSlot(copy.mTexSlot) , mDelta(copy.mDelta) , mTextures(copy.mTextures) + , mData(copy.mData) { } void FlipController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv) { - if (hasInput() && mDelta != 0 && !mTextures.empty()) + if (hasInput() && !mTextures.empty()) { - int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size(); + int curTexture = 0; + if (mDelta != 0) + curTexture = int(getInputValue(nv) / mDelta) % mTextures.size(); + else + curTexture = int(mData.interpKey(getInputValue(nv))) % mTextures.size(); stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]); } } diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index c087e635f..fa154d207 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -58,6 +58,8 @@ namespace NifOsg using ValueT = typename MapT::ValueType; ValueInterpolator() = default; + ValueInterpolator(const Nif::NiFloatInterpolator* interpolator) = delete; + ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator) = delete; ValueInterpolator(std::shared_ptr keys, ValueT defaultVal = ValueT()) : mKeys(keys) @@ -161,6 +163,34 @@ namespace NifOsg using Vec3Interpolator = ValueInterpolator; using Vec4Interpolator = ValueInterpolator; + template<> + inline FloatInterpolator::ValueInterpolator(const Nif::NiFloatInterpolator* interpolator) + : mDefaultVal(interpolator->defaultVal) + { + if (interpolator->data.empty()) + return; + mKeys = interpolator->data->mKeyList; + if (mKeys) + { + mLastLowKey = mKeys->mKeys.end(); + mLastHighKey = mKeys->mKeys.end(); + } + } + + template<> + inline Vec3Interpolator::ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator) + : mDefaultVal(interpolator->defaultVal) + { + if (interpolator->data.empty()) + return; + mKeys = interpolator->data->mKeyList; + if (mKeys) + { + mLastLowKey = mKeys->mKeys.end(); + mLastHighKey = mKeys->mKeys.end(); + } + } + class ControllerFunction : public SceneUtil::ControllerFunction { private: @@ -203,7 +233,14 @@ namespace NifOsg class KeyframeController : public osg::NodeCallback, public SceneUtil::Controller { public: + // This is used if there's no interpolator but there is data (Morrowind meshes). KeyframeController(const Nif::NiKeyframeData *data); + // This is used if the interpolator has data. + KeyframeController(const Nif::NiTransformInterpolator* interpolator); + // This is used if there are default values available (e.g. from a data-less interpolator). + // If there's neither keyframe data nor an interpolator a KeyframeController must not be created. + KeyframeController(const float scale, const osg::Vec3f& pos, const osg::Quat& rot); + KeyframeController(); KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop); @@ -272,6 +309,7 @@ namespace NifOsg public: RollController(const Nif::NiFloatData *data); + RollController(const Nif::NiFloatInterpolator* interpolator); RollController() = default; RollController(const RollController& copy, const osg::CopyOp& copyop); @@ -287,6 +325,7 @@ namespace NifOsg osg::ref_ptr mBaseMaterial; public: AlphaController(const Nif::NiFloatData *data, const osg::Material* baseMaterial); + AlphaController(const Nif::NiFloatInterpolator* interpolator, const osg::Material* baseMaterial); AlphaController(); AlphaController(const AlphaController& copy, const osg::CopyOp& copyop); @@ -308,6 +347,7 @@ namespace NifOsg Emissive = 3 }; MaterialColorController(const Nif::NiPosData *data, TargetColor color, const osg::Material* baseMaterial); + MaterialColorController(const Nif::NiPoint3Interpolator* interpolator, TargetColor color, const osg::Material* baseMaterial); MaterialColorController(); MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop); @@ -329,6 +369,7 @@ namespace NifOsg int mTexSlot{0}; float mDelta{0.f}; std::vector > mTextures; + FloatInterpolator mData; public: FlipController(const Nif::NiFlipController* ctrl, const std::vector >& textures); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 805283b42..030252412 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -281,10 +281,10 @@ namespace NifOsg const Nif::NiStringExtraData *strdata = static_cast(extra.getPtr()); const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); - if(key->data.empty()) + if (key->data.empty() && key->interpolator.empty()) continue; - osg::ref_ptr callback(new NifOsg::KeyframeController(key->data.getPtr())); + osg::ref_ptr callback(handleKeyframeController(key)); callback->setFunction(std::shared_ptr(new NifOsg::ControllerFunction(key))); if (!target.mKeyframeControllers.emplace(strdata->string, callback).second) @@ -725,6 +725,24 @@ namespace NifOsg } } + static osg::ref_ptr handleKeyframeController(const Nif::NiKeyframeController* keyctrl) + { + osg::ref_ptr ctrl; + if (!keyctrl->interpolator.empty()) + { + const Nif::NiTransformInterpolator* interp = keyctrl->interpolator.getPtr(); + if (!interp->data.empty()) + ctrl = new NifOsg::KeyframeController(interp); + else + ctrl = new NifOsg::KeyframeController(interp->defaultScale, interp->defaultPos, interp->defaultRot); + } + else if (!keyctrl->data.empty()) + { + ctrl = new NifOsg::KeyframeController(keyctrl->data.getPtr()); + } + return ctrl; + } + void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated) { for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next) @@ -734,9 +752,9 @@ namespace NifOsg if (ctrl->recType == Nif::RC_NiKeyframeController) { const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); - if (key->data.empty()) + if (key->data.empty() && key->interpolator.empty()) continue; - osg::ref_ptr callback(new KeyframeController(key->data.getPtr())); + osg::ref_ptr callback(handleKeyframeController(key)); setupController(key, callback, animflags); node->addUpdateCallback(callback); isAnimated = true; @@ -763,9 +781,13 @@ namespace NifOsg else if (ctrl->recType == Nif::RC_NiRollController) { const Nif::NiRollController *rollctrl = static_cast(ctrl.getPtr()); - if (rollctrl->data.empty()) + if (rollctrl->data.empty() && rollctrl->interpolator.empty()) continue; - osg::ref_ptr callback(new RollController(rollctrl->data.getPtr())); + osg::ref_ptr callback; + if (!rollctrl->interpolator.empty()) + callback = new RollController(rollctrl->interpolator.getPtr()); + else // if (!rollctrl->data.empty()) + callback = new RollController(rollctrl->data.getPtr()); setupController(rollctrl, callback, animflags); node->addUpdateCallback(callback); isAnimated = true; @@ -791,19 +813,27 @@ namespace NifOsg if (ctrl->recType == Nif::RC_NiAlphaController) { const Nif::NiAlphaController* alphactrl = static_cast(ctrl.getPtr()); - if (alphactrl->data.empty()) + if (alphactrl->data.empty() && alphactrl->interpolator.empty()) continue; - osg::ref_ptr osgctrl(new AlphaController(alphactrl->data.getPtr(), baseMaterial)); + osg::ref_ptr osgctrl; + if (!alphactrl->interpolator.empty()) + osgctrl = new AlphaController(alphactrl->interpolator.getPtr(), baseMaterial); + else // if (!alphactrl->data.empty()) + osgctrl = new AlphaController(alphactrl->data.getPtr(), baseMaterial); setupController(alphactrl, osgctrl, animflags); composite->addController(osgctrl); } else if (ctrl->recType == Nif::RC_NiMaterialColorController) { const Nif::NiMaterialColorController* matctrl = static_cast(ctrl.getPtr()); - if (matctrl->data.empty()) + if (matctrl->data.empty() && matctrl->interpolator.empty()) continue; + osg::ref_ptr osgctrl; auto targetColor = static_cast(matctrl->targetColor); - osg::ref_ptr osgctrl(new MaterialColorController(matctrl->data.getPtr(), targetColor, baseMaterial)); + if (!matctrl->interpolator.empty()) + osgctrl = new MaterialColorController(matctrl->interpolator.getPtr(), targetColor, baseMaterial); + else // if (!matctrl->data.empty()) + osgctrl = new MaterialColorController(matctrl->data.getPtr(), targetColor, baseMaterial); setupController(matctrl, osgctrl, animflags); composite->addController(osgctrl); } From a46699fb1e91a0fa21cdb2a1c78eaa134246d5ee Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Tue, 10 Nov 2020 23:23:11 +0300 Subject: [PATCH 078/111] Handle NiGeomMorpherController interpolator list --- components/nif/controller.cpp | 1 + components/nifosg/controller.cpp | 21 ++++++++++++++++++--- components/nifosg/controller.hpp | 2 +- components/nifosg/nifloader.cpp | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 2cd61950b..1e909120e 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -216,6 +216,7 @@ namespace Nif } else { + // TODO: handle weighted interpolators unsigned int numInterps = nif->getUInt(); nif->skip(8 * numInterps); } diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index c0f7522d5..64e9f7de6 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -197,10 +197,25 @@ GeomMorpherController::GeomMorpherController(const GeomMorpherController ©, { } -GeomMorpherController::GeomMorpherController(const Nif::NiMorphData *data) +GeomMorpherController::GeomMorpherController(const Nif::NiGeomMorpherController* ctrl) { - for (unsigned int i=0; imMorphs.size(); ++i) - mKeyFrames.emplace_back(data->mMorphs[i].mKeyFrames); + if (ctrl->interpolators.length() == 0) + { + if (ctrl->data.empty()) + return; + for (const auto& morph : ctrl->data->mMorphs) + mKeyFrames.emplace_back(morph.mKeyFrames); + } + else + { + for (size_t i = 0; i < ctrl->interpolators.length(); ++i) + { + if (!ctrl->interpolators[i].empty()) + mKeyFrames.emplace_back(ctrl->interpolators[i].getPtr()); + else + mKeyFrames.emplace_back(); + } + } } void GeomMorpherController::update(osg::NodeVisitor *nv, osg::Drawable *drawable) diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index fa154d207..dd3068ac8 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -218,7 +218,7 @@ namespace NifOsg class GeomMorpherController : public osg::Drawable::UpdateCallback, public SceneUtil::Controller { public: - GeomMorpherController(const Nif::NiMorphData* data); + GeomMorpherController(const Nif::NiGeomMorpherController* ctrl); GeomMorpherController(); GeomMorpherController(const GeomMorpherController& copy, const osg::CopyOp& copyop); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 030252412..a5a61b317 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1244,7 +1244,7 @@ namespace NifOsg continue; drawable = handleMorphGeometry(nimorphctrl, geom, parentNode, composite, boundTextures, animflags); - osg::ref_ptr morphctrl = new GeomMorpherController(nimorphctrl->data.getPtr()); + osg::ref_ptr morphctrl = new GeomMorpherController(nimorphctrl); setupController(ctrl.getPtr(), morphctrl, animflags); drawable->setUpdateCallback(morphctrl); break; From 5d046bc95dfc9e848b03772f4e53521fd2a1c343 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 11 Nov 2020 14:58:06 +0000 Subject: [PATCH 079/111] Mark override --- components/sceneutil/shadowsbin.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/sceneutil/shadowsbin.hpp b/components/sceneutil/shadowsbin.hpp index 6302d5974..6c35e1779 100644 --- a/components/sceneutil/shadowsbin.hpp +++ b/components/sceneutil/shadowsbin.hpp @@ -21,7 +21,7 @@ namespace SceneUtil ShadowsBin(); ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop), mStateSet(rhs.mStateSet) {} - virtual void sortImplementation(); + void sortImplementation() override; struct State { From 72f7e6a702cef495159869e3bde2de1d4627c7b8 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 12 Nov 2020 00:26:30 +0000 Subject: [PATCH 080/111] Handle all shadow alpha uniforms in shadowsbin --- apps/openmw/mwrender/animation.cpp | 12 ++------ components/sceneutil/mwshadowtechnique.cpp | 11 +------- components/sceneutil/mwshadowtechnique.hpp | 1 - components/sceneutil/shadowsbin.cpp | 33 ++++++++++++++-------- components/sceneutil/shadowsbin.hpp | 7 +++-- components/shader/shadermanager.cpp | 10 ------- components/shader/shadermanager.hpp | 6 ---- components/shader/shadervisitor.cpp | 28 +----------------- components/shader/shadervisitor.hpp | 1 - 9 files changed, 29 insertions(+), 80 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 29645a7c1..94a521960 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -37,8 +36,6 @@ #include -#include - #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwworld/esmstore.hpp" @@ -493,9 +490,8 @@ namespace MWRender class TransparencyUpdater : public SceneUtil::StateSetUpdater { public: - TransparencyUpdater(const float alpha, osg::ref_ptr shadowUniform) + TransparencyUpdater(const float alpha) : mAlpha(alpha) - , mShadowUniform(shadowUniform) { } @@ -509,9 +505,6 @@ namespace MWRender { osg::BlendFunc* blendfunc (new osg::BlendFunc); stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); - // TODO: don't do this anymore once custom shadow renderbin is handling it - if (mShadowUniform) - stateset->addUniform(mShadowUniform); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); stateset->setRenderBinMode(osg::StateSet::OVERRIDE_RENDERBIN_DETAILS); @@ -533,7 +526,6 @@ namespace MWRender private: float mAlpha; - osg::ref_ptr mShadowUniform; }; struct Animation::AnimSource @@ -1773,7 +1765,7 @@ namespace MWRender { if (mTransparencyUpdater == nullptr) { - mTransparencyUpdater = new TransparencyUpdater(alpha, mResourceSystem->getSceneManager()->getShaderManager().getShadowMapAlphaTestEnableUniform()); + mTransparencyUpdater = new TransparencyUpdater(alpha); mObjectRoot->addCullCallback(mTransparencyUpdater); } else diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index c8a241c36..06a1efd2a 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -885,15 +885,6 @@ void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & sh _castingProgram->addShader(shaderManager.getShader("shadowcasting_vertex.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::VERTEX)); _castingProgram->addShader(shaderManager.getShader("shadowcasting_fragment.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::FRAGMENT)); - - _shadowMapAlphaTestDisableUniform = shaderManager.getShadowMapAlphaTestDisableUniform(); - _shadowMapAlphaTestDisableUniform->setName("alphaTestShadows"); - _shadowMapAlphaTestDisableUniform->setType(osg::Uniform::BOOL); - _shadowMapAlphaTestDisableUniform->set(false); - - shaderManager.getShadowMapAlphaTestEnableUniform()->setName("alphaTestShadows"); - shaderManager.getShadowMapAlphaTestEnableUniform()->setType(osg::Uniform::BOOL); - shaderManager.getShadowMapAlphaTestEnableUniform()->set(true); } MWShadowTechnique::ViewDependentData* MWShadowTechnique::createViewDependentData(osgUtil::CullVisitor* /*cv*/) @@ -1595,7 +1586,7 @@ void MWShadowTechnique::createShaders() // The casting program uses a sampler, so to avoid undefined behaviour, we must bind a dummy texture in case no other is supplied _shadowCastingStateSet->setTextureAttributeAndModes(0, _fallbackBaseTexture.get(), osg::StateAttribute::ON); _shadowCastingStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true)); - _shadowCastingStateSet->addUniform(_shadowMapAlphaTestDisableUniform); + _shadowCastingStateSet->addUniform(new osg::Uniform("alphaTestShadows", false)); osg::ref_ptr depth = new osg::Depth; depth->setWriteMask(true); _shadowCastingStateSet->setAttribute(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); diff --git a/components/sceneutil/mwshadowtechnique.hpp b/components/sceneutil/mwshadowtechnique.hpp index 23a8e009a..a7208cfa6 100644 --- a/components/sceneutil/mwshadowtechnique.hpp +++ b/components/sceneutil/mwshadowtechnique.hpp @@ -288,7 +288,6 @@ namespace SceneUtil { osg::ref_ptr _debugHud; osg::ref_ptr _castingProgram; - osg::ref_ptr _shadowMapAlphaTestDisableUniform; }; } diff --git a/components/sceneutil/shadowsbin.cpp b/components/sceneutil/shadowsbin.cpp index e0a141ffb..4c0c78cab 100644 --- a/components/sceneutil/shadowsbin.cpp +++ b/components/sceneutil/shadowsbin.cpp @@ -42,11 +42,16 @@ namespace SceneUtil ShadowsBin::ShadowsBin() { - mStateSet = new osg::StateSet; - mStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false)); + mNoTestStateSet = new osg::StateSet; + mNoTestStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false)); + mNoTestStateSet->addUniform(new osg::Uniform("alphaTestShadows", false)); + + mShaderAlphaTestStateSet = new osg::StateSet; + mShaderAlphaTestStateSet->addUniform(new osg::Uniform("alphaTestShadows", true)); + mShaderAlphaTestStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); } -bool ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::unordered_set& uninterestingCache) +StateGraph* ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::unordered_set& uninterestingCache) { std::vector return_path; State state; @@ -88,7 +93,7 @@ bool ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::unordered } if (!state.needShadows()) - return true; + return nullptr; if (!state.needTexture() && !state.mImportantState) { @@ -97,9 +102,12 @@ bool ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::unordered leaf->_parent = root; root->_leaves.push_back(leaf); } - return true; + return nullptr; } - return false; + + if (state.mAlphaBlend) + return sg->find_or_insert(mShaderAlphaTestStateSet); + return sg; } bool ShadowsBin::State::needShadows() const @@ -128,9 +136,9 @@ void ShadowsBin::sortImplementation() if (!root->_parent) return; } - root = root->find_or_insert(mStateSet.get()); + StateGraph* noTestRoot = root->find_or_insert(mNoTestStateSet.get()); // root is now a stategraph with useDiffuseMapForShadowAlpha disabled but minimal other state - root->_leaves.reserve(_stateGraphList.size()); + noTestRoot->_leaves.reserve(_stateGraphList.size()); StateGraphList newList; std::unordered_set uninterestingCache; for (StateGraph* graph : _stateGraphList) @@ -138,11 +146,12 @@ void ShadowsBin::sortImplementation() // Render leaves which shouldn't use the diffuse map for shadow alpha but do cast shadows become children of root, so graph is now empty. Don't add to newList. // Graphs containing just render leaves which don't cast shadows are discarded. Don't add to newList. // Graphs containing other leaves need to be in newList. - if (!cullStateGraph(graph, root, uninterestingCache)) - newList.push_back(graph); + StateGraph* graphToAdd = cullStateGraph(graph, noTestRoot, uninterestingCache); + if (graphToAdd) + newList.push_back(graphToAdd); } - if (!root->_leaves.empty()) - newList.push_back(root); + if (!noTestRoot->_leaves.empty()) + newList.push_back(noTestRoot); _stateGraphList = newList; } diff --git a/components/sceneutil/shadowsbin.hpp b/components/sceneutil/shadowsbin.hpp index 6c35e1779..13f68ec90 100644 --- a/components/sceneutil/shadowsbin.hpp +++ b/components/sceneutil/shadowsbin.hpp @@ -15,11 +15,12 @@ namespace SceneUtil class ShadowsBin : public osgUtil::RenderBin { private: - osg::ref_ptr mStateSet; + osg::ref_ptr mNoTestStateSet; + osg::ref_ptr mShaderAlphaTestStateSet; public: META_Object(SceneUtil, ShadowsBin) ShadowsBin(); - ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop), mStateSet(rhs.mStateSet) {} + ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop), mNoTestStateSet(rhs.mNoTestStateSet), mShaderAlphaTestStateSet(rhs.mShaderAlphaTestStateSet) {} void sortImplementation() override; @@ -39,7 +40,7 @@ namespace SceneUtil bool interesting() const { return !needShadows() || needTexture() || mAlphaBlendOverride || mAlphaTestOverride || mMaterialOverride || mImportantState; } }; - bool cullStateGraph(osgUtil::StateGraph* sg, osgUtil::StateGraph* root, std::unordered_set& uninteresting); + osgUtil::StateGraph* cullStateGraph(osgUtil::StateGraph* sg, osgUtil::StateGraph* root, std::unordered_set& uninteresting); static void addPrototype(const std::string& name) { diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index bfaa11282..788a8720b 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -384,14 +384,4 @@ namespace Shader program.second->releaseGLObjects(state); } - const osg::ref_ptr ShaderManager::getShadowMapAlphaTestEnableUniform() - { - return mShadowMapAlphaTestEnableUniform; - } - - const osg::ref_ptr ShaderManager::getShadowMapAlphaTestDisableUniform() - { - return mShadowMapAlphaTestDisableUniform; - } - } diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index ed5bbc907..13db30b01 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -43,9 +43,6 @@ namespace Shader void releaseGLObjects(osg::State* state); - const osg::ref_ptr getShadowMapAlphaTestEnableUniform(); - const osg::ref_ptr getShadowMapAlphaTestDisableUniform(); - private: std::string mPath; @@ -63,9 +60,6 @@ namespace Shader ProgramMap mPrograms; std::mutex mMutex; - - const osg::ref_ptr mShadowMapAlphaTestEnableUniform = new osg::Uniform(); - const osg::ref_ptr mShadowMapAlphaTestDisableUniform = new osg::Uniform(); }; bool parseFors(std::string& source, const std::string& templateName); diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index c30307f29..f17c4a80c 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -1,7 +1,5 @@ #include "shadervisitor.hpp" -#include -#include #include #include #include @@ -25,7 +23,6 @@ namespace Shader : mShaderRequired(false) , mColorMode(0) , mMaterialOverridden(false) - , mBlendFuncOverridden(false) , mNormalHeight(false) , mTexStageRequiringTangents(-1) , mNode(nullptr) @@ -233,14 +230,11 @@ namespace Shader if (!writableStateSet) writableStateSet = getWritableStateSet(node); // We probably shouldn't construct a new version of this each time as Uniforms use pointer comparison for early-out. - // Also it should probably belong to the shader manager + // Also it should probably belong to the shader manager or be applied by the shadows bin writableStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true)); } } - bool alphaSettingsChanged = false; - bool alphaTestShadows = false; - const osg::StateSet::AttributeList& attributes = stateset->getAttributeList(); for (osg::StateSet::AttributeList::const_iterator it = attributes.begin(); it != attributes.end(); ++it) { @@ -284,28 +278,8 @@ namespace Shader mRequirements.back().mColorMode = colorMode; } } - else if (it->first.first == osg::StateAttribute::BLENDFUNC) - { - if (!mRequirements.back().mBlendFuncOverridden || it->second.second & osg::StateAttribute::PROTECTED) - { - if (it->second.second & osg::StateAttribute::OVERRIDE) - mRequirements.back().mBlendFuncOverridden = true; - - const osg::BlendFunc* blend = static_cast(it->second.first.get()); - if (blend->getSource() == osg::BlendFunc::SRC_ALPHA || blend->getSource() == osg::BlendFunc::SRC_COLOR) - alphaTestShadows = true; - alphaSettingsChanged = true; - } - } // Eventually, move alpha testing to discard in shader adn remove deprecated state here } - // we don't need to check for glEnable/glDisable of blending as we always set it at the same time - if (alphaSettingsChanged) - { - if (!writableStateSet) - writableStateSet = getWritableStateSet(node); - writableStateSet->addUniform(alphaTestShadows ? mShaderManager.getShadowMapAlphaTestEnableUniform() : mShaderManager.getShadowMapAlphaTestDisableUniform()); - } } void ShaderVisitor::pushRequirements(osg::Node& node) diff --git a/components/shader/shadervisitor.hpp b/components/shader/shadervisitor.hpp index bf1022180..ae157b976 100644 --- a/components/shader/shadervisitor.hpp +++ b/components/shader/shadervisitor.hpp @@ -75,7 +75,6 @@ namespace Shader int mColorMode; bool mMaterialOverridden; - bool mBlendFuncOverridden; bool mNormalHeight; // true if normal map has height info in alpha channel From 296dce470a6b2fe26894daaf5d9b3b3e6923a787 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 12 Nov 2020 16:58:29 +0000 Subject: [PATCH 081/111] Spelling fix --- components/sceneutil/shadowsbin.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/sceneutil/shadowsbin.hpp b/components/sceneutil/shadowsbin.hpp index 13f68ec90..86fd47cc0 100644 --- a/components/sceneutil/shadowsbin.hpp +++ b/components/sceneutil/shadowsbin.hpp @@ -11,7 +11,7 @@ namespace osg namespace SceneUtil { - /// renderbin which culls redundent state for shadows rendering + /// renderbin which culls redundant state for shadow map rendering class ShadowsBin : public osgUtil::RenderBin { private: From cdbf19a5086e33ee790be9854a366b4ef65e928d Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 12 Nov 2020 17:04:23 +0000 Subject: [PATCH 082/111] Tidy up run-on lines --- components/sceneutil/shadowsbin.hpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/components/sceneutil/shadowsbin.hpp b/components/sceneutil/shadowsbin.hpp index 86fd47cc0..cc6fd3525 100644 --- a/components/sceneutil/shadowsbin.hpp +++ b/components/sceneutil/shadowsbin.hpp @@ -20,13 +20,26 @@ namespace SceneUtil public: META_Object(SceneUtil, ShadowsBin) ShadowsBin(); - ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) : osgUtil::RenderBin(rhs, copyop), mNoTestStateSet(rhs.mNoTestStateSet), mShaderAlphaTestStateSet(rhs.mShaderAlphaTestStateSet) {} + ShadowsBin(const ShadowsBin& rhs, const osg::CopyOp& copyop) + : osgUtil::RenderBin(rhs, copyop) + , mNoTestStateSet(rhs.mNoTestStateSet) + , mShaderAlphaTestStateSet(rhs.mShaderAlphaTestStateSet) + {} void sortImplementation() override; struct State { - State():mAlphaBlend(false),mAlphaBlendOverride(false),mAlphaTest(false),mAlphaTestOverride(false),mMaterial(nullptr),mMaterialOverride(false),mImportantState(false){} + State() + : mAlphaBlend(false) + , mAlphaBlendOverride(false) + , mAlphaTest(false) + , mAlphaTestOverride(false) + , mMaterial(nullptr) + , mMaterialOverride(false) + , mImportantState(false) + {} + bool mAlphaBlend; bool mAlphaBlendOverride; bool mAlphaTest; @@ -37,7 +50,10 @@ namespace SceneUtil bool needTexture() const { return mAlphaBlend || mAlphaTest; } bool needShadows() const; // A state is interesting if there's anything about it that might affect whether we can optimise child state - bool interesting() const { return !needShadows() || needTexture() || mAlphaBlendOverride || mAlphaTestOverride || mMaterialOverride || mImportantState; } + bool interesting() const + { + return !needShadows() || needTexture() || mAlphaBlendOverride || mAlphaTestOverride || mMaterialOverride || mImportantState; + } }; osgUtil::StateGraph* cullStateGraph(osgUtil::StateGraph* sg, osgUtil::StateGraph* root, std::unordered_set& uninteresting); From 55f65752fd3b39bb12660c4f77da3f53bf044ac1 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 12 Nov 2020 17:55:10 +0000 Subject: [PATCH 083/111] Don't bind unnecessary colour buffer when drawing shadow maps --- components/sceneutil/mwshadowtechnique.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 76eaf0bb7..3f60f79b9 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -555,6 +555,7 @@ MWShadowTechnique::ShadowData::ShadowData(MWShadowTechnique::ViewDependentData* _camera = new osg::Camera; _camera->setName("ShadowCamera"); _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT); + _camera->setImplicitBufferAttachmentMask(0, 0); //_camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); _camera->setClearColor(osg::Vec4(0.0f,0.0f,0.0f,0.0f)); From d8d435196226f4750d9797936d8fc939bdb2db60 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 12 Nov 2020 19:45:32 +0100 Subject: [PATCH 084/111] fix MSVC2017 builds --- components/nifosg/controller.hpp | 63 +++++++++++++++++--------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index dd3068ac8..f08f28612 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -10,6 +10,7 @@ #include #include +#include #include @@ -58,8 +59,38 @@ namespace NifOsg using ValueT = typename MapT::ValueType; ValueInterpolator() = default; - ValueInterpolator(const Nif::NiFloatInterpolator* interpolator) = delete; - ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator) = delete; + + template + inline ValueInterpolator(typename std::enable_if< + std::is_same::value, + const Nif::NiFloatInterpolator + >::type * interpolator) : mDefaultVal(interpolator->defaultVal) + { + if (interpolator->data.empty()) + return; + mKeys = interpolator->data->mKeyList; + if (mKeys) + { + mLastLowKey = mKeys->mKeys.end(); + mLastHighKey = mKeys->mKeys.end(); + } + }; + + template + inline ValueInterpolator(typename std::enable_if< + std::is_same::value, + const Nif::NiPoint3Interpolator + >::type * interpolator) : mDefaultVal(interpolator->defaultVal) + { + if (interpolator->data.empty()) + return; + mKeys = interpolator->data->mKeyList; + if (mKeys) + { + mLastLowKey = mKeys->mKeys.end(); + mLastHighKey = mKeys->mKeys.end(); + } + } ValueInterpolator(std::shared_ptr keys, ValueT defaultVal = ValueT()) : mKeys(keys) @@ -163,34 +194,6 @@ namespace NifOsg using Vec3Interpolator = ValueInterpolator; using Vec4Interpolator = ValueInterpolator; - template<> - inline FloatInterpolator::ValueInterpolator(const Nif::NiFloatInterpolator* interpolator) - : mDefaultVal(interpolator->defaultVal) - { - if (interpolator->data.empty()) - return; - mKeys = interpolator->data->mKeyList; - if (mKeys) - { - mLastLowKey = mKeys->mKeys.end(); - mLastHighKey = mKeys->mKeys.end(); - } - } - - template<> - inline Vec3Interpolator::ValueInterpolator(const Nif::NiPoint3Interpolator* interpolator) - : mDefaultVal(interpolator->defaultVal) - { - if (interpolator->data.empty()) - return; - mKeys = interpolator->data->mKeyList; - if (mKeys) - { - mLastLowKey = mKeys->mKeys.end(); - mLastHighKey = mKeys->mKeys.end(); - } - } - class ControllerFunction : public SceneUtil::ControllerFunction { private: From d8897c4509ac06e9b59685c32c019320e7b1fa87 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 12 Nov 2020 20:46:45 +0100 Subject: [PATCH 085/111] remove inline and use enable_if_t --- components/nifosg/controller.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index f08f28612..17ad9564c 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -61,10 +61,10 @@ namespace NifOsg ValueInterpolator() = default; template - inline ValueInterpolator(typename std::enable_if< + ValueInterpolator(typename std::enable_if_t< std::is_same::value, const Nif::NiFloatInterpolator - >::type * interpolator) : mDefaultVal(interpolator->defaultVal) + > * interpolator) : mDefaultVal(interpolator->defaultVal) { if (interpolator->data.empty()) return; @@ -77,10 +77,10 @@ namespace NifOsg }; template - inline ValueInterpolator(typename std::enable_if< + ValueInterpolator(typename std::enable_if_t< std::is_same::value, const Nif::NiPoint3Interpolator - >::type * interpolator) : mDefaultVal(interpolator->defaultVal) + > * interpolator) : mDefaultVal(interpolator->defaultVal) { if (interpolator->data.empty()) return; From fcfd340c697afdaee2fd989e7d782283c929eade Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 12 Nov 2020 23:23:40 +0000 Subject: [PATCH 086/111] Actually copy alpha blended drawables to the new stategraph --- components/sceneutil/shadowsbin.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/components/sceneutil/shadowsbin.cpp b/components/sceneutil/shadowsbin.cpp index 4c0c78cab..520ad0362 100644 --- a/components/sceneutil/shadowsbin.cpp +++ b/components/sceneutil/shadowsbin.cpp @@ -106,7 +106,15 @@ StateGraph* ShadowsBin::cullStateGraph(StateGraph* sg, StateGraph* root, std::un } if (state.mAlphaBlend) - return sg->find_or_insert(mShaderAlphaTestStateSet); + { + sg_new = sg->find_or_insert(mShaderAlphaTestStateSet); + for (RenderLeaf* leaf : sg->_leaves) + { + leaf->_parent = sg_new; + sg_new->_leaves.push_back(leaf); + } + return sg_new; + } return sg; } From dee91d12c2ee9633a20e37c4beb1a54982bad95d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 13 Nov 2020 16:26:08 +0100 Subject: [PATCH 087/111] Update .travis.yml --- .travis.yml | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f457798a..fb029fcf3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,13 +2,7 @@ language: cpp branches: only: - master - - coverity_scan - /openmw-.*$/ -env: - global: - # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created - # via the "travis encrypt" command using the project repo's public key - - secure: "jybGzAdUbqt9vWR/GEnRd96BgAi/7Zd1+2HK68j/i/8+/1YH2XxLOy4Jv/DUBhBlJIkxs/Xv8dRcUlFOclZDHX1d/9Qnsqd3oUVkD7k1y7cTOWy9TBQaE/v/kZo3LpzA3xPwwthrb0BvqIbOfIELi5fS5s8ba85WFRg3AX70wWE=" cache: ccache addons: apt: @@ -27,28 +21,17 @@ addons: # The other ones from OpenMW ppa libbullet-dev, libopenscenegraph-dev, libmygui-dev ] - coverity_scan: # TODO: currently takes too long, disabled openmw/openmw-cs for now. - project: - name: "OpenMW/openmw" - description: "" - branch_pattern: coverity_scan - notification_email: 1122069+psi29a@users.noreply.github.com - build_command_prepend: "cov-configure --comptype gcc --compiler gcc-5 --template; cmake . -DBUILD_OPENMW=FALSE -DBUILD_OPENCS=FALSE" - build_command: "make VERBOSE=1 -j3" matrix: include: - name: OpenMW (all) on MacOS 10.15 with Xcode 11.6 os: osx osx_image: xcode11.6 - if: branch != coverity_scan - name: OpenMW (all) on Ubuntu Focal with GCC os: linux dist: focal - if: branch != coverity_scan - name: OpenMW (tests only) on Ubuntu Focal with GCC os: linux dist: focal - if: branch != coverity_scan env: - BUILD_TESTS_ONLY: 1 - name: OpenMW (openmw) on Ubuntu Focal with Clang's Static Analysis @@ -57,16 +40,7 @@ matrix: env: - MATRIX_EVAL="CC=clang && CXX=clang++" - ANALYZE="scan-build --force-analyze-debug-code --use-cc clang --use-c++ clang++" - if: branch != coverity_scan compiler: clang - - name: OpenMW Components Coverity Scan - os: linux - dist: focal - if: branch = coverity_scan -# allow_failures: -# - name: OpenMW (openmw) on Ubuntu Focal with GCC-10 -# env: -# - MATRIX_EVAL="CC=gcc-10 && CXX=g++-10" before_install: - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then eval "${MATRIX_EVAL}"; fi From df2ae6e86651935c4c3c95bec84bedcb9d011230 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 13 Nov 2020 16:29:11 +0100 Subject: [PATCH 088/111] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb029fcf3..8ec35a671 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: cpp +dist: focal branches: only: - master @@ -8,7 +9,6 @@ addons: apt: sources: - sourceline: 'ppa:openmw/openmw' - # - ubuntu-toolchain-r-test # for GCC-10 packages: [ # Dev build-essential, cmake, clang-tools, ccache, From e15716eb0c09dcaa834a99982c169042feaa9bc7 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 13 Nov 2020 16:38:53 +0100 Subject: [PATCH 089/111] Update .travis.yml --- .travis.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ec35a671..956997f25 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: cpp +os: [ linux, osx ] dist: focal branches: only: @@ -17,7 +18,7 @@ addons: # FFmpeg libavcodec-dev, libavformat-dev, libavutil-dev, libswresample-dev, libswscale-dev, # Audio, Video and Misc. deps - libsdl2-dev, libqt5opengl5-dev, libopenal-dev, libunshield-dev, libtinyxml-dev, liblz4-dev + libsdl2-dev, libqt5opengl5-dev, libopenal-dev, libunshield-dev, libtinyxml-dev, liblz4-dev, # The other ones from OpenMW ppa libbullet-dev, libopenscenegraph-dev, libmygui-dev ] @@ -44,17 +45,17 @@ matrix: before_install: - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then eval "${MATRIX_EVAL}"; fi - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_install.${TRAVIS_OS_NAME}.sh; fi + - ./CI/before_install.${TRAVIS_OS_NAME}.sh before_script: - ccache -z - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./CI/before_script.${TRAVIS_OS_NAME}.sh; fi + - ./CI/before_script.${TRAVIS_OS_NAME}.sh script: - cd ./build - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ${ANALYZE} make -j3; fi - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ] && [ "${BUILD_TESTS_ONLY}" ]; then ./openmw_test_suite; fi - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi + - ${ANALYZE} make -j3; + - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi + - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi + - if [ "${TRAVIS_OS_NAME}" = "linux" ] && [ "${BUILD_TESTS_ONLY}" ]; then ./openmw_test_suite; fi + - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi - cd "${TRAVIS_BUILD_DIR}" - ccache -s deploy: From 94c89e6d5ef170933e2d791be6bab5e119982397 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 13 Nov 2020 16:41:45 +0100 Subject: [PATCH 090/111] check ValueTs --- components/nifosg/controller.hpp | 35 +++++++++++++------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 17ad9564c..a29fabefd 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -60,11 +60,20 @@ namespace NifOsg ValueInterpolator() = default; - template - ValueInterpolator(typename std::enable_if_t< - std::is_same::value, - const Nif::NiFloatInterpolator - > * interpolator) : mDefaultVal(interpolator->defaultVal) + template< + class T, + typename = std::enable_if_t< + std::conjunction_v< + std::disjunction< + std::is_same, + std::is_same + >, + std::is_same + >, + T + > + > + ValueInterpolator(const T* interpolator) : mDefaultVal(interpolator->defaultVal) { if (interpolator->data.empty()) return; @@ -76,22 +85,6 @@ namespace NifOsg } }; - template - ValueInterpolator(typename std::enable_if_t< - std::is_same::value, - const Nif::NiPoint3Interpolator - > * interpolator) : mDefaultVal(interpolator->defaultVal) - { - if (interpolator->data.empty()) - return; - mKeys = interpolator->data->mKeyList; - if (mKeys) - { - mLastLowKey = mKeys->mKeys.end(); - mLastHighKey = mKeys->mKeys.end(); - } - } - ValueInterpolator(std::shared_ptr keys, ValueT defaultVal = ValueT()) : mKeys(keys) , mDefaultVal(defaultVal) From 8b0475037d30453dad616ca69be3b090331c0bd7 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 13 Nov 2020 16:42:10 +0100 Subject: [PATCH 091/111] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 956997f25..54ef00698 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,7 @@ before_install: - ./CI/before_install.${TRAVIS_OS_NAME}.sh before_script: - ccache -z - - ./CI/before_script.${TRAVIS_OS_NAME}.sh + - ./CI/before_script.${TRAVIS_OS_NAME}.sh script: - cd ./build - ${ANALYZE} make -j3; From 68836aa0fd35a8c3938177a16d197ca9d5d4224d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 13 Nov 2020 16:44:06 +0100 Subject: [PATCH 092/111] Update .travis.yml --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 54ef00698..e84a9ad71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: cpp -os: [ linux, osx ] -dist: focal branches: only: - master From 8a6d3d1b4f2836e09d663354a4074d8bdce0e46d Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Fri, 13 Nov 2020 22:53:12 +0300 Subject: [PATCH 093/111] Minor fixes Fix extra semicolon Disable collision avoidance if AI is disabled --- apps/openmw/mwmechanics/actors.cpp | 3 +++ components/nifosg/controller.hpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 8f3675ef7..047741bac 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1731,6 +1731,9 @@ namespace MWMechanics void Actors::predictAndAvoidCollisions() { + if (!MWBase::Environment::get().getMechanicsManager()->isAIActive()) + return; + const float minGap = 10.f; const float maxDistForPartialAvoiding = 200.f; const float maxDistForStrictAvoiding = 100.f; diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index a29fabefd..996e4ef97 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -83,7 +83,7 @@ namespace NifOsg mLastLowKey = mKeys->mKeys.end(); mLastHighKey = mKeys->mKeys.end(); } - }; + } ValueInterpolator(std::shared_ptr keys, ValueT defaultVal = ValueT()) : mKeys(keys) From 117697ea227933cf8c3a6c4b784bc8d659991559 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 14 Nov 2020 01:12:32 +0300 Subject: [PATCH 094/111] Fix NiStringPalette loading --- components/nif/data.cpp | 16 ++-------------- components/nif/data.hpp | 2 +- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/components/nif/data.cpp b/components/nif/data.cpp index 1eb5c40fe..235825e4a 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -460,21 +460,9 @@ void NiPalette::read(NIFStream *nif) void NiStringPalette::read(NIFStream *nif) { - unsigned int size = nif->getUInt(); - if (!size) - return; - std::vector source; - nif->getChars(source, size); - if (nif->getUInt() != size) + palette = nif->getString(); + if (nif->getUInt() != palette.size()) nif->file->warn("Failed size check in NiStringPalette"); - if (source[source.size()-1] != '\0') - source.emplace_back('\0'); - const char* buffer = source.data(); - while (static_cast(buffer - source.data()) < source.size()) - { - palette.emplace_back(buffer); - buffer += palette.back().size() + 1; - } } void NiBoolData::read(NIFStream *nif) diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 4d13afb9d..35f329573 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -262,7 +262,7 @@ public: struct NiStringPalette : public Record { - std::vector palette; + std::string palette; void read(NIFStream *nif) override; }; From 89d73c5fc74ecc1a2f8c4b807f06967d5e83a960 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 14 Nov 2020 02:04:46 +0000 Subject: [PATCH 095/111] Only reroute stdout etc. to new console if not already redirected This should fix the issue where Windows Release builds (compiled as /SUBSYSTEM:WINDOWS instead of /SUBSYSTEM:CONSOLE) can't have their output redirected. Basically, a console application creates a console if not given one, so you get a console window behind OpenMW while it's running. It was decided that this was ugly, so we set Release builds to be windows applications, which don't get an automatic console and don't automatically connect to a console if given one anyway. Of course, we still wanted to actually be able to print to a console if given one, so we manually attach to the parent process' console if it exists, then reopen the standard streams connected to CON, the Windows pseudo-file representing the current console. This is a little like connecting a second wire into a dumb terminal in that you're pumping characters into the display rather than onto a pipeline, so output can't be redirected. It turns out, though, that if a /SUBSYSTEM:WINDOWS application has its standard streams redirected by the calling process, it still gets its handles as normal, so everything starts off connected just how we want it and we were clobbering this good setup with the straight-to-console fix. All we need to do to fix that is check if we've got valid standard handles and that they go somewhere useful, and if so, avoid reopening them once the console is attached. Simples. --- components/debug/debugging.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index dfed077e3..c4f3af307 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -11,11 +11,22 @@ namespace Debug { #ifdef _WIN32 + bool isRedirected(DWORD nStdHandle) + { + DWORD fileType = GetFileType(GetStdHandle(nStdHandle)); + + return (fileType == FILE_TYPE_DISK) || (fileType == FILE_TYPE_PIPE); + } + bool attachParentConsole() { if (GetConsoleWindow() != nullptr) return true; + bool inRedirected = isRedirected(STD_INPUT_HANDLE); + bool outRedirected = isRedirected(STD_OUTPUT_HANDLE); + bool errRedirected = isRedirected(STD_ERROR_HANDLE); + if (AttachConsole(ATTACH_PARENT_PROCESS)) { fflush(stdout); @@ -24,12 +35,21 @@ namespace Debug std::cerr.flush(); // this looks dubious but is really the right way - _wfreopen(L"CON", L"w", stdout); - _wfreopen(L"CON", L"w", stderr); - _wfreopen(L"CON", L"r", stdin); - freopen("CON", "w", stdout); - freopen("CON", "w", stderr); - freopen("CON", "r", stdin); + if (!inRedirected) + { + _wfreopen(L"CON", L"r", stdin); + freopen("CON", "r", stdin); + } + if (!outRedirected) + { + _wfreopen(L"CON", L"w", stdout); + freopen("CON", "w", stdout); + } + if (!errRedirected) + { + _wfreopen(L"CON", L"w", stderr); + freopen("CON", "w", stderr); + } return true; } From df9667e92348a9fadb4615c911ef54ef266ee05a Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 14 Nov 2020 03:42:15 +0300 Subject: [PATCH 096/111] Read NIF bounding volume data correctly --- .../nifloader/testbulletnifloader.cpp | 66 ++++++---- components/nif/node.hpp | 124 ++++++++++++++++-- components/nifbullet/bulletnifloader.cpp | 27 +++- components/nifbullet/bulletnifloader.hpp | 4 +- 4 files changed, 178 insertions(+), 43 deletions(-) diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index 72dcd3066..7da8f0fd5 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -373,6 +373,7 @@ namespace TEST_F(TestBulletNifLoader, for_zero_num_roots_should_return_default) { EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(0)); + EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); const auto result = mLoader.load(mNifFile); Resource::BulletShape expected; @@ -422,11 +423,13 @@ namespace { mNode.hasBounds = true; mNode.flags |= Nif::NiNode::Flag_BBoxCollision; - mNode.boundXYZ = osg::Vec3f(1, 2, 3); - mNode.boundPos = osg::Vec3f(-1, -2, -3); + mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode)); + EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); const auto result = mLoader.load(mNifFile); Resource::BulletShape expected; @@ -444,12 +447,14 @@ namespace { mNode.hasBounds = true; mNode.flags |= Nif::NiNode::Flag_BBoxCollision; - mNode.boundXYZ = osg::Vec3f(1, 2, 3); - mNode.boundPos = osg::Vec3f(-1, -2, -3); + mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNiNode.children = Nif::NodeList(std::vector({Nif::NodePtr(&mNode)})); EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); + EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); const auto result = mLoader.load(mNifFile); Resource::BulletShape expected; @@ -467,16 +472,19 @@ namespace { mNode.hasBounds = true; mNode.flags |= Nif::NiNode::Flag_BBoxCollision; - mNode.boundXYZ = osg::Vec3f(1, 2, 3); - mNode.boundPos = osg::Vec3f(-1, -2, -3); + mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNiNode.hasBounds = true; - mNiNode.boundXYZ = osg::Vec3f(4, 5, 6); - mNiNode.boundPos = osg::Vec3f(-4, -5, -6); + mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiNode.bounds.box.extents = osg::Vec3f(4, 5, 6); + mNiNode.bounds.box.center = osg::Vec3f(-4, -5, -6); mNiNode.children = Nif::NodeList(std::vector({Nif::NodePtr(&mNode)})); EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); + EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); const auto result = mLoader.load(mNifFile); Resource::BulletShape expected; @@ -494,20 +502,24 @@ namespace { mNode.hasBounds = true; mNode.flags |= Nif::NiNode::Flag_BBoxCollision; - mNode.boundXYZ = osg::Vec3f(1, 2, 3); - mNode.boundPos = osg::Vec3f(-1, -2, -3); + mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode2.hasBounds = true; - mNode2.boundXYZ = osg::Vec3f(4, 5, 6); - mNode2.boundPos = osg::Vec3f(-4, -5, -6); + mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6); + mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6); mNiNode.hasBounds = true; - mNiNode.boundXYZ = osg::Vec3f(7, 8, 9); - mNiNode.boundPos = osg::Vec3f(-7, -8, -9); + mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiNode.bounds.box.extents = osg::Vec3f(7, 8, 9); + mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9); mNiNode.children = Nif::NodeList(std::vector({Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2)})); EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); + EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); const auto result = mLoader.load(mNifFile); Resource::BulletShape expected; @@ -524,21 +536,25 @@ namespace TEST_F(TestBulletNifLoader, for_root_and_two_children_where_both_with_bounds_but_only_second_with_flag_should_use_second_bounds) { mNode.hasBounds = true; - mNode.boundXYZ = osg::Vec3f(1, 2, 3); - mNode.boundPos = osg::Vec3f(-1, -2, -3); + mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode2.hasBounds = true; mNode2.flags |= Nif::NiNode::Flag_BBoxCollision; - mNode2.boundXYZ = osg::Vec3f(4, 5, 6); - mNode2.boundPos = osg::Vec3f(-4, -5, -6); + mNode2.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode2.bounds.box.extents = osg::Vec3f(4, 5, 6); + mNode2.bounds.box.center = osg::Vec3f(-4, -5, -6); mNiNode.hasBounds = true; - mNiNode.boundXYZ = osg::Vec3f(7, 8, 9); - mNiNode.boundPos = osg::Vec3f(-7, -8, -9); + mNiNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiNode.bounds.box.extents = osg::Vec3f(7, 8, 9); + mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9); mNiNode.children = Nif::NodeList(std::vector({Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2)})); EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); + EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); const auto result = mLoader.load(mNifFile); Resource::BulletShape expected; @@ -555,8 +571,9 @@ namespace TEST_F(TestBulletNifLoader, for_root_nif_node_with_bounds_but_without_flag_should_return_shape_with_bounds_but_with_null_collision_shape) { mNode.hasBounds = true; - mNode.boundXYZ = osg::Vec3f(1, 2, 3); - mNode.boundPos = osg::Vec3f(-1, -2, -3); + mNode.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); + mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode)); @@ -588,8 +605,9 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_root_node_with_bounds_should_return_shape_with_bounds_but_with_null_collision_shape) { mNiTriShape.hasBounds = true; - mNiTriShape.boundXYZ = osg::Vec3f(1, 2, 3); - mNiTriShape.boundPos = osg::Vec3f(-1, -2, -3); + mNiTriShape.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; + mNiTriShape.bounds.box.extents = osg::Vec3f(1, 2, 3); + mNiTriShape.bounds.box.center = osg::Vec3f(-1, -2, -3); EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape)); diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 72adfe06c..0b958d2c2 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -16,6 +16,117 @@ namespace Nif struct NiNode; +struct NiBoundingVolume +{ + enum Type + { + SPHERE_BV = 0, + BOX_BV = 1, + CAPSULE_BV = 2, + LOZENGE_BV = 3, + UNION_BV = 4, + HALFSPACE_BV = 5 + }; + + struct NiSphereBV + { + osg::Vec3f center; + float radius{0.f}; + }; + + struct NiBoxBV + { + osg::Vec3f center; + Matrix3 axis; + osg::Vec3f extents; + }; + + struct NiCapsuleBV + { + osg::Vec3f center, axis; + float extent{0.f}, radius{0.f}; + }; + + struct NiLozengeBV + { + float radius{0.f}, extent0{0.f}, extent1{0.f}; + osg::Vec3f center, axis0, axis1; + }; + + struct NiHalfSpaceBV + { + osg::Vec3f center, normal; + }; + + unsigned int type; + NiSphereBV sphere; + NiBoxBV box; + NiCapsuleBV capsule; + NiLozengeBV lozenge; + std::vector children; + NiHalfSpaceBV plane; + void read(NIFStream* nif) + { + type = nif->getUInt(); + switch (type) + { + case SPHERE_BV: + { + sphere.center = nif->getVector3(); + sphere.radius = nif->getFloat(); + break; + } + case BOX_BV: + { + box.center = nif->getVector3(); + box.axis = nif->getMatrix3(); + box.extents = nif->getVector3(); + break; + } + case CAPSULE_BV: + { + capsule.center = nif->getVector3(); + capsule.axis = nif->getVector3(); + capsule.extent = nif->getFloat(); + capsule.radius = nif->getFloat(); + break; + } + case LOZENGE_BV: + { + lozenge.radius = nif->getFloat(); + lozenge.extent0 = nif->getFloat(); + lozenge.extent1 = nif->getFloat(); + lozenge.center = nif->getVector3(); + lozenge.axis0 = nif->getVector3(); + lozenge.axis1 = nif->getVector3(); + break; + } + case UNION_BV: + { + unsigned int numChildren = nif->getUInt(); + if (numChildren == 0) + break; + children.resize(numChildren); + for (NiBoundingVolume& child : children) + child.read(nif); + break; + } + case HALFSPACE_BV: + { + plane.center = nif->getVector3(); + plane.normal = nif->getVector3(); + break; + } + default: + { + std::stringstream error; + error << "Unhandled NiBoundingVolume type: " << type; + nif->file->fail(error.str()); + } + } + } +}; + /** A Node is an object that's part of the main NIF tree. It has parent node (unless it's the root), and transformation (location and rotation) relative to it's parent. @@ -31,9 +142,7 @@ public: // Bounding box info bool hasBounds{false}; - osg::Vec3f boundPos; - Matrix3 boundRot; - osg::Vec3f boundXYZ; // Box size + NiBoundingVolume bounds; void read(NIFStream *nif) override { @@ -48,13 +157,8 @@ public: if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0)) hasBounds = nif->getBoolean(); - if(hasBounds) - { - nif->getInt(); // always 1 - boundPos = nif->getVector3(); - boundRot = nif->getMatrix3(); - boundXYZ = nif->getVector3(); - } + if (hasBounds) + bounds.read(nif); // Reference to the collision object in Gamebryo files. if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0)) nif->skip(4); diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 5b531121e..b1461e536 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -132,13 +132,14 @@ osg::ref_ptr BulletNifLoader::load(const Nif::File& nif) if ((node = dynamic_cast(r))) break; } + const std::string filename = nif.getFilename(); if (!node) { - warn("Found no root nodes in NIF."); + warn("Found no root nodes in NIF file " + filename); return mShape; } - if (findBoundingBox(node)) + if (findBoundingBox(node, filename)) { const btVector3 halfExtents = Misc::Convert::toBullet(mShape->mCollisionBoxHalfExtents); const btVector3 origin = Misc::Convert::toBullet(mShape->mCollisionBoxTranslate); @@ -158,7 +159,6 @@ osg::ref_ptr BulletNifLoader::load(const Nif::File& nif) // files with the name convention xmodel.nif usually have keyframes stored in a separate file xmodel.kf (see Animation::addAnimSource). // assume all nodes in the file will be animated - const auto filename = nif.getFilename(); const bool isAnimated = pathFileNameStartsWithX(filename); handleNode(filename, node, 0, autogenerated, isAnimated, autogenerated); @@ -194,12 +194,25 @@ osg::ref_ptr BulletNifLoader::load(const Nif::File& nif) // Find a boundingBox in the node hierarchy. // Return: use bounding box for collision? -bool BulletNifLoader::findBoundingBox(const Nif::Node* node) +bool BulletNifLoader::findBoundingBox(const Nif::Node* node, const std::string& filename) { if (node->hasBounds) { - mShape->mCollisionBoxHalfExtents = node->boundXYZ; - mShape->mCollisionBoxTranslate = node->boundPos; + unsigned int type = node->bounds.type; + switch (type) + { + case Nif::NiBoundingVolume::Type::BOX_BV: + mShape->mCollisionBoxHalfExtents = node->bounds.box.extents; + mShape->mCollisionBoxTranslate = node->bounds.box.center; + break; + default: + { + std::stringstream warning; + warning << "Unsupported NiBoundingVolume type " << type << " in node " << node->recIndex; + warning << " in file " << filename; + warn(warning.str()); + } + } if (node->flags & Nif::NiNode::Flag_BBoxCollision) { @@ -215,7 +228,7 @@ bool BulletNifLoader::findBoundingBox(const Nif::Node* node) { if(!list[i].empty()) { - bool found = findBoundingBox (list[i].getPtr()); + bool found = findBoundingBox (list[i].getPtr(), filename); if (found) return true; } diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index e423e5149..054b33fed 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -40,7 +40,7 @@ class BulletNifLoader public: void warn(const std::string &msg) { - Log(Debug::Warning) << "NIFLoader: Warn:" << msg; + Log(Debug::Warning) << "NIFLoader: Warn: " << msg; } void fail(const std::string &msg) @@ -52,7 +52,7 @@ public: osg::ref_ptr load(const Nif::File& file); private: - bool findBoundingBox(const Nif::Node* node); + bool findBoundingBox(const Nif::Node* node, const std::string& filename); void handleNode(const std::string& fileName, Nif::Node const *node, int flags, bool isCollisionNode, bool isAnimated=false, bool autogenerated=false, bool avoid=false); From e5fa457fe7bcd4d346b8d10c33e4ee6601bac37b Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 1 Nov 2020 17:14:59 +0100 Subject: [PATCH 097/111] Properly account for interleaved move of actors. Before this change, if an actor position was changed while the physics simulation was running, the simulation result would be discarded. It is fine in case of one off event such as teleport, but in the case of scripts making use of this functionality to make lifts or conveyor (such as Sotha Sil Expanded mod) it broke actor movement. To alleviate this issue, at the end of the simulation, the position of the Actor in the world is compared to the position it had at the beginning of the simulation. A difference indicate a force move occured. In this case, the Actor mPosition and mPreviousPosition are translated by the difference of position. Since the Actor position will be really set while the next simulation runs, we save it in the mNextPosition field. --- apps/openmw/mwphysics/actor.cpp | 90 ++++++++----------- apps/openmw/mwphysics/actor.hpp | 19 ++-- apps/openmw/mwphysics/mtphysics.cpp | 53 +++++------ apps/openmw/mwphysics/mtphysics.hpp | 1 - apps/openmw/mwphysics/physicssystem.cpp | 7 +- apps/openmw/mwphysics/physicssystem.hpp | 3 +- .../mwscript/transformationextensions.cpp | 6 +- apps/openmw/mwworld/worldimp.cpp | 6 +- 8 files changed, 91 insertions(+), 94 deletions(-) diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index 5caaba5c9..760e21cce 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -75,9 +75,10 @@ Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, Physic updateRotation(); updateScale(); updatePosition(); + setPosition(mWorldPosition, true); addCollisionMask(getCollisionMask()); - commitPositionChange(); + updateCollisionObjectPosition(); } Actor::~Actor() @@ -122,88 +123,77 @@ int Actor::getCollisionMask() const void Actor::updatePosition() { - std::unique_lock lock(mPositionMutex); - osg::Vec3f position = mPtr.getRefData().getPosition().asVec3(); + std::scoped_lock lock(mPositionMutex); + mWorldPosition = mPtr.getRefData().getPosition().asVec3(); +} - mPosition = position; - mPreviousPosition = position; +osg::Vec3f Actor::getWorldPosition() const +{ + std::scoped_lock lock(mPositionMutex); + return mWorldPosition; +} - mTransformUpdatePending = true; - updateCollisionObjectPosition(); +void Actor::setNextPosition(const osg::Vec3f& position) +{ + mNextPosition = position; +} + +osg::Vec3f Actor::getNextPosition() const +{ + return mNextPosition; } void Actor::updateCollisionObjectPosition() { + std::scoped_lock lock(mPositionMutex); + mShape->setLocalScaling(Misc::Convert::toBullet(mScale)); osg::Vec3f scaledTranslation = mRotation * osg::componentMultiply(mMeshTranslation, mScale); osg::Vec3f newPosition = scaledTranslation + mPosition; mLocalTransform.setOrigin(Misc::Convert::toBullet(newPosition)); mLocalTransform.setRotation(Misc::Convert::toBullet(mRotation)); - -} - -void Actor::commitPositionChange() -{ - std::unique_lock lock(mPositionMutex); - if (mScaleUpdatePending) - { - mShape->setLocalScaling(Misc::Convert::toBullet(mScale)); - mScaleUpdatePending = false; - } - if (mTransformUpdatePending) - { - mCollisionObject->setWorldTransform(mLocalTransform); - mTransformUpdatePending = false; - } + mCollisionObject->setWorldTransform(mLocalTransform); } osg::Vec3f Actor::getCollisionObjectPosition() const { - std::unique_lock lock(mPositionMutex); + std::scoped_lock lock(mPositionMutex); return Misc::Convert::toOsg(mLocalTransform.getOrigin()); } -void Actor::setPosition(const osg::Vec3f &position, bool updateCollisionObject) +void Actor::setPosition(const osg::Vec3f& position, bool reset) { - std::unique_lock lock(mPositionMutex); - if (mTransformUpdatePending) + if (reset) { - mCollisionObject->setWorldTransform(mLocalTransform); - mTransformUpdatePending = false; + mPreviousPosition = position; + mNextPosition = position; } else - { mPreviousPosition = mPosition; + mPosition = position; +} - mPosition = position; - if (updateCollisionObject) - { - updateCollisionObjectPosition(); - mCollisionObject->setWorldTransform(mLocalTransform); - } - } +void Actor::adjustPosition(const osg::Vec3f& offset) +{ + mPosition += offset; + mPreviousPosition += offset; } osg::Vec3f Actor::getPosition() const { - std::unique_lock lock(mPositionMutex); return mPosition; } osg::Vec3f Actor::getPreviousPosition() const { - std::unique_lock lock(mPositionMutex); return mPreviousPosition; } void Actor::updateRotation () { - std::unique_lock lock(mPositionMutex); + std::scoped_lock lock(mPositionMutex); if (mRotation == mPtr.getRefData().getBaseNode()->getAttitude()) return; mRotation = mPtr.getRefData().getBaseNode()->getAttitude(); - - mTransformUpdatePending = true; - updateCollisionObjectPosition(); } bool Actor::isRotationallyInvariant() const @@ -213,37 +203,33 @@ bool Actor::isRotationallyInvariant() const void Actor::updateScale() { - std::unique_lock lock(mPositionMutex); + std::scoped_lock lock(mPositionMutex); float scale = mPtr.getCellRef().getScale(); osg::Vec3f scaleVec(scale,scale,scale); mPtr.getClass().adjustScale(mPtr, scaleVec, false); mScale = scaleVec; - mScaleUpdatePending = true; scaleVec = osg::Vec3f(scale,scale,scale); mPtr.getClass().adjustScale(mPtr, scaleVec, true); mRenderingScale = scaleVec; - - mTransformUpdatePending = true; - updateCollisionObjectPosition(); } osg::Vec3f Actor::getHalfExtents() const { - std::unique_lock lock(mPositionMutex); + std::scoped_lock lock(mPositionMutex); return osg::componentMultiply(mHalfExtents, mScale); } osg::Vec3f Actor::getOriginalHalfExtents() const { - std::unique_lock lock(mPositionMutex); + std::scoped_lock lock(mPositionMutex); return mHalfExtents; } osg::Vec3f Actor::getRenderingHalfExtents() const { - std::unique_lock lock(mPositionMutex); + std::scoped_lock lock(mPositionMutex); return osg::componentMultiply(mHalfExtents, mRenderingScale); } @@ -274,7 +260,7 @@ void Actor::setWalkingOnWater(bool walkingOnWater) void Actor::setCanWaterWalk(bool waterWalk) { - std::unique_lock lock(mPositionMutex); + std::scoped_lock lock(mPositionMutex); if (waterWalk != mCanWaterWalk) { mCanWaterWalk = waterWalk; diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index ef7b368b9..00ba162af 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -57,13 +57,20 @@ namespace MWPhysics bool isRotationallyInvariant() const; /** - * Set mPosition and mPreviousPosition to the position in the Ptr's RefData. This should be used + * Set mWorldPosition to the position in the Ptr's RefData. This is used by the physics simulation to account for * when an object is "instantly" moved/teleported as opposed to being moved by the physics simulation. */ void updatePosition(); + osg::Vec3f getWorldPosition() const; + + /** + * Used by the physics simulation to store the simulation result. Used in conjunction with mWorldPosition + * to account for e.g. scripted movements + */ + void setNextPosition(const osg::Vec3f& position); + osg::Vec3f getNextPosition() const; void updateCollisionObjectPosition(); - void commitPositionChange(); /** * Returns the half extents of the collision body (scaled according to collision scale) @@ -83,9 +90,9 @@ namespace MWPhysics /** * Store the current position into mPreviousPosition, then move to this position. - * Optionally, inform the physics engine about the change of position. */ - void setPosition(const osg::Vec3f& position, bool updateCollisionObject=true); + void setPosition(const osg::Vec3f& position, bool reset=false); + void adjustPosition(const osg::Vec3f& offset); osg::Vec3f getPosition() const; @@ -159,11 +166,11 @@ namespace MWPhysics osg::Vec3f mScale; osg::Vec3f mRenderingScale; + osg::Vec3f mWorldPosition; + osg::Vec3f mNextPosition; osg::Vec3f mPosition; osg::Vec3f mPreviousPosition; btTransform mLocalTransform; - bool mScaleUpdatePending; - bool mTransformUpdatePending; mutable std::mutex mPositionMutex; osg::Vec3f mForce; diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index f105efce5..1b99b4c3f 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -102,9 +102,18 @@ namespace stats.addToFallHeight(-actorData.mFallHeight); } - osg::Vec3f interpolateMovements(const MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt) + osg::Vec3f interpolateMovements(MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt) { const float interpolationFactor = timeAccum / physicsDt; + + // account for force change of actor's position in the main thread + const auto correction = actorData.mActorRaw->getWorldPosition() - actorData.mOrigin; + if (correction.length() != 0) + { + actorData.mActorRaw->adjustPosition(correction); + actorData.mPosition = actorData.mActorRaw->getPosition(); + } + return actorData.mPosition * interpolationFactor + actorData.mActorRaw->getPreviousPosition() * (1.f - interpolationFactor); } @@ -182,7 +191,6 @@ namespace MWPhysics mPostSimBarrier = std::make_unique(mNumThreads, [&]() { - udpateActorsAabbs(); mNewFrame = false; if (mLOSCacheExpiry >= 0) { @@ -229,6 +237,9 @@ namespace MWPhysics updateMechanics(data); if (mAdvanceSimulation) updateStandingCollision(data, standingCollisions); + + if (mMovementResults.find(data.mPtr) != mMovementResults.end()) + data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]); } } @@ -245,10 +256,6 @@ namespace MWPhysics if (mAdvanceSimulation) mWorldFrameData = std::make_unique(); - // update each actor position based on latest data - for (auto& data : mActorsFrameData) - data.updatePosition(); - // we are asked to skip the simulation (load a savegame for instance) // just return the actors' reference position without applying the movements if (skipSimulation) @@ -256,7 +263,10 @@ namespace MWPhysics standingCollisions.clear(); mMovementResults.clear(); for (const auto& m : mActorsFrameData) - mMovementResults[m.mPtr] = m.mPosition; + { + m.mActorRaw->setPosition(m.mActorRaw->getWorldPosition(), true); + mMovementResults[m.mPtr] = m.mActorRaw->getWorldPosition(); + } return mMovementResults; } @@ -271,6 +281,11 @@ namespace MWPhysics for (auto& data : mActorsFrameData) updateStandingCollision(data, standingCollisions); } + for (auto& data : mActorsFrameData) + { + if (mMovementResults.find(data.mPtr) != mMovementResults.end()) + data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]); + } return mMovementResults; } @@ -427,7 +442,7 @@ namespace MWPhysics { if (const auto actor = std::dynamic_pointer_cast(p)) { - actor->commitPositionChange(); + actor->updateCollisionObjectPosition(); mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); } else if (const auto object = std::dynamic_pointer_cast(p)) @@ -485,28 +500,17 @@ namespace MWPhysics { if(const auto actor = actorData.mActor.lock()) { - if (actorData.mPosition == actor->getPosition()) - actor->setPosition(actorData.mPosition, false); // update previous position to make sure interpolation is correct - else + bool positionChanged = actorData.mPosition != actorData.mActorRaw->getPosition(); + actorData.mActorRaw->setPosition(actorData.mPosition); + if (positionChanged) { - actorData.mPositionChanged = true; - actor->setPosition(actorData.mPosition); + actor->updateCollisionObjectPosition(); + mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); } } } } - void PhysicsTaskScheduler::udpateActorsAabbs() - { - std::unique_lock lock(mCollisionWorldMutex); - for (const auto& actorData : mActorsFrameData) - if (actorData.mPositionChanged) - { - if(const auto actor = actorData.mActor.lock()) - mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); - } - } - bool PhysicsTaskScheduler::hasLineOfSight(const Actor* actor1, const Actor* actor2) { btVector3 pos1 = Misc::Convert::toBullet(actor1->getCollisionObjectPosition() + osg::Vec3f(0,0,actor1->getHalfExtents().z() * 0.9)); // eye level @@ -538,6 +542,5 @@ namespace MWPhysics mMovementResults[actorData.mPtr] = interpolateMovements(actorData, mTimeAccum, mPhysicsDt); updateMechanics(actorData); } - udpateActorsAabbs(); } } diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index 100e71a90..84ea93c08 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -49,7 +49,6 @@ namespace MWPhysics void syncComputation(); void worker(); void updateActorsPositions(); - void udpateActorsAabbs(); bool hasLineOfSight(const Actor* actor1, const Actor* actor2); void refreshLOSCache(); void updateAabbs(); diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 9a777bd45..6b94ef43b 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -883,7 +883,7 @@ namespace MWPhysics ActorFrameData::ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr character, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel) : mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn), - mPositionChanged(false), mDidJump(false), mNeedLand(false), mMoveToWaterSurface(moveToWaterSurface), + mDidJump(false), mNeedLand(false), mMoveToWaterSurface(moveToWaterSurface), mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(movement), mPosition(), mRefpos() { const MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -893,10 +893,9 @@ namespace MWPhysics mWantJump = mPtr.getClass().getMovementSettings(mPtr).mPosition[2] != 0; mIsDead = mPtr.getClass().getCreatureStats(mPtr).isDead(); mWasOnGround = actor->getOnGround(); - } - void ActorFrameData::updatePosition() - { + mActorRaw->updatePosition(); + mOrigin = mActorRaw->getNextPosition(); mPosition = mActorRaw->getPosition(); if (mMoveToWaterSurface) { diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 36ef762d3..4844b5e8e 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -78,14 +78,12 @@ namespace MWPhysics struct ActorFrameData { ActorFrameData(const std::shared_ptr& actor, const MWWorld::Ptr character, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel); - void updatePosition(); std::weak_ptr mActor; Actor* mActorRaw; MWWorld::Ptr mPtr; MWWorld::Ptr mStandingOn; bool mFlying; bool mSwimming; - bool mPositionChanged; bool mWasOnGround; bool mWantJump; bool mDidJump; @@ -97,6 +95,7 @@ namespace MWPhysics float mOldHeight; float mFallHeight; osg::Vec3f mMovement; + osg::Vec3f mOrigin; osg::Vec3f mPosition; ESM::Position mRefpos; }; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 41df1870c..ce45729b3 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -32,7 +32,11 @@ namespace MWScript std::vector actors; MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors); for (auto& actor : actors) - MWBase::Environment::get().getWorld()->queueMovement(actor, diff); + { + osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3()); + actorPos += diff; + MWBase::Environment::get().getWorld()->moveObject(actor, actorPos.x(), actorPos.y(), actorPos.z()); + } } template diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index be32765ad..ad6c33790 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1504,11 +1504,11 @@ namespace MWWorld const auto results = mPhysics->applyQueuedMovement(duration, mDiscardMovements); mDiscardMovements = false; - for(const auto& result : results) + for(const auto& [actor, position]: results) { // Handle player last, in case a cell transition occurs - if(result.first != getPlayerPtr()) - moveObjectImp(result.first, result.second.x(), result.second.y(), result.second.z(), false); + if(actor != getPlayerPtr()) + moveObjectImp(actor, position.x(), position.y(), position.z(), false); } const auto player = results.find(getPlayerPtr()); From d64ed6cf53f9d35edfd9dddc5521939db89cb4f5 Mon Sep 17 00:00:00 2001 From: fredzio Date: Sat, 7 Nov 2020 18:30:52 +0100 Subject: [PATCH 098/111] Get rid of the StandingActorsMap. Just embed the necessary info into Actor class. --- apps/openmw/mwphysics/actor.cpp | 14 ++++++- apps/openmw/mwphysics/actor.hpp | 4 ++ apps/openmw/mwphysics/mtphysics.cpp | 25 +++--------- apps/openmw/mwphysics/mtphysics.hpp | 2 +- apps/openmw/mwphysics/physicssystem.cpp | 51 +++++++++---------------- apps/openmw/mwphysics/physicssystem.hpp | 8 ---- 6 files changed, 40 insertions(+), 64 deletions(-) diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index 760e21cce..0f3d69d21 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -19,7 +19,7 @@ namespace MWPhysics Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler) - : mCanWaterWalk(false), mWalkingOnWater(false) + : mStandingOnPtr(nullptr), mCanWaterWalk(false), mWalkingOnWater(false) , mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBoxTranslate), mHalfExtents(shape->mCollisionBoxHalfExtents) , mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false) , mInternalCollisionMode(true) @@ -268,4 +268,16 @@ void Actor::setCanWaterWalk(bool waterWalk) } } +MWWorld::Ptr Actor::getStandingOnPtr() const +{ + std::scoped_lock lock(mPositionMutex); + return mStandingOnPtr; +} + +void Actor::setStandingOnPtr(const MWWorld::Ptr& ptr) +{ + std::scoped_lock lock(mPositionMutex); + mStandingOnPtr = ptr; +} + } diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 00ba162af..6b23b31d3 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -144,7 +144,11 @@ namespace MWPhysics void setWalkingOnWater(bool walkingOnWater); bool isWalkingOnWater() const; + MWWorld::Ptr getStandingOnPtr() const; + void setStandingOnPtr(const MWWorld::Ptr& ptr); + private: + MWWorld::Ptr mStandingOnPtr; /// Removes then re-adds the collision object to the dynamics world void updateCollisionMask(); void addCollisionMask(int collisionMask); diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 1b99b4c3f..ff676413b 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -82,14 +82,6 @@ namespace ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0; } - void updateStandingCollision(MWPhysics::ActorFrameData& actorData, MWPhysics::CollisionMap& standingCollisions) - { - if (!actorData.mStandingOn.isEmpty()) - standingCollisions[actorData.mPtr] = actorData.mStandingOn; - else - standingCollisions.erase(actorData.mPtr); - } - void updateMechanics(MWPhysics::ActorFrameData& actorData) { if (actorData.mDidJump) @@ -215,7 +207,7 @@ namespace MWPhysics thread.join(); } - const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector&& actorsData, CollisionMap& standingCollisions, bool skipSimulation) + const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skipSimulation) { // This function run in the main thread. // While the mSimulationMutex is held, background physics threads can't run. @@ -225,9 +217,6 @@ namespace MWPhysics // start by finishing previous background computation if (mNumThreads != 0) { - if (mAdvanceSimulation) - standingCollisions.clear(); - for (auto& data : mActorsFrameData) { // Ignore actors that were deleted while the background thread was running @@ -236,7 +225,7 @@ namespace MWPhysics updateMechanics(data); if (mAdvanceSimulation) - updateStandingCollision(data, standingCollisions); + data.mActorRaw->setStandingOnPtr(data.mStandingOn); if (mMovementResults.find(data.mPtr) != mMovementResults.end()) data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]); @@ -260,10 +249,10 @@ namespace MWPhysics // just return the actors' reference position without applying the movements if (skipSimulation) { - standingCollisions.clear(); mMovementResults.clear(); for (const auto& m : mActorsFrameData) { + m.mActorRaw->setStandingOnPtr(nullptr); m.mActorRaw->setPosition(m.mActorRaw->getWorldPosition(), true); mMovementResults[m.mPtr] = m.mActorRaw->getWorldPosition(); } @@ -275,14 +264,10 @@ namespace MWPhysics mMovementResults.clear(); syncComputation(); - if (mAdvanceSimulation) - { - standingCollisions.clear(); - for (auto& data : mActorsFrameData) - updateStandingCollision(data, standingCollisions); - } for (auto& data : mActorsFrameData) { + if (mAdvanceSimulation) + data.mActorRaw->setStandingOnPtr(data.mStandingOn); if (mMovementResults.find(data.mPtr) != mMovementResults.end()) data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]); } diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index 84ea93c08..ef1c90b87 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -30,7 +30,7 @@ namespace MWPhysics /// @param timeAccum accumulated time from previous run to interpolate movements /// @param actorsData per actor data needed to compute new positions /// @return new position of each actor - const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector&& actorsData, CollisionMap& standingCollisions, bool skip); + const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skip); // Thread safe wrappers void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 6b94ef43b..5de26fdfc 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -148,11 +148,11 @@ namespace MWPhysics if (!physactor || !physactor->getOnGround()) return false; - CollisionMap::const_iterator found = mStandingCollisions.find(actor); - if (found == mStandingCollisions.end()) + const auto obj = physactor->getStandingOnPtr(); + if (obj.isEmpty()) return true; // assume standing on terrain (which is a non-object, so not collision tracked) - ObjectMap::const_iterator foundObj = mObjects.find(found->second); + ObjectMap::const_iterator foundObj = mObjects.find(obj); if (foundObj == mObjects.end()) return false; @@ -501,22 +501,6 @@ namespace MWPhysics } } - void PhysicsSystem::updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated) - { - CollisionMap::iterator found = map.find(old); - if (found != map.end()) - { - map[updated] = found->second; - map.erase(found); - } - - for (auto& collision : map) - { - if (collision.second == old) - collision.second = updated; - } - } - void PhysicsSystem::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated) { ObjectMap::iterator found = mObjects.find(old); @@ -537,7 +521,11 @@ namespace MWPhysics mActors.emplace(updated, std::move(actor)); } - updateCollisionMapPtr(mStandingCollisions, old, updated); + for (auto& [_, actor] : mActors) + { + if (actor->getStandingOnPtr() == old) + actor->setStandingOnPtr(updated); + } } Actor *PhysicsSystem::getActor(const MWWorld::Ptr &ptr) @@ -675,7 +663,6 @@ namespace MWPhysics void PhysicsSystem::clearQueuedMovement() { mMovementQueue.clear(); - mStandingCollisions.clear(); } const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation) @@ -688,7 +675,7 @@ namespace MWPhysics mTimeAccum -= numSteps * mPhysicsDt; - return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), mStandingCollisions, skipSimulation); + return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), skipSimulation); } std::vector PhysicsSystem::prepareFrameData(int numSteps) @@ -700,10 +687,8 @@ namespace MWPhysics { const auto foundActor = mActors.find(character); if (foundActor == mActors.end()) // actor was already removed from the scene - { - mStandingCollisions.erase(character); continue; - } + auto physicActor = foundActor->second; float waterlevel = -std::numeric_limits::max(); @@ -734,7 +719,7 @@ namespace MWPhysics // Ue current value only if we don't advance the simulation. Otherwise we might get a stale value. MWWorld::Ptr standingOn; if (numSteps == 0) - standingOn = mStandingCollisions[character]; + standingOn = physicActor->getStandingOnPtr(); actorsFrameData.emplace_back(std::move(physicActor), character, standingOn, moveToWaterSurface, movement, slowFall, waterlevel); } @@ -774,20 +759,18 @@ namespace MWPhysics bool PhysicsSystem::isActorStandingOn(const MWWorld::Ptr &actor, const MWWorld::ConstPtr &object) const { - for (const auto& standingActor : mStandingCollisions) - { - if (standingActor.first == actor && standingActor.second == object) - return true; - } + const auto physActor = mActors.find(actor); + if (physActor != mActors.end()) + return physActor->second->getStandingOnPtr() == object; return false; } void PhysicsSystem::getActorsStandingOn(const MWWorld::ConstPtr &object, std::vector &out) const { - for (const auto& standingActor : mStandingCollisions) + for (const auto& [_, actor] : mActors) { - if (standingActor.second == object) - out.push_back(standingActor.first); + if (actor->getStandingOnPtr() == object) + out.emplace_back(actor->getPtr()); } } diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 4844b5e8e..ccfca5422 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -50,7 +50,6 @@ class btVector3; namespace MWPhysics { using PtrPositionList = std::map; - using CollisionMap = std::map; class HeightField; class Object; @@ -272,13 +271,6 @@ namespace MWPhysics bool mDebugDrawEnabled; - // Tracks standing collisions happening during a single frame. - // This will detect standing on an object, but won't detect running e.g. against a wall. - CollisionMap mStandingCollisions; - - // replaces all occurrences of 'old' in the map by 'updated', no matter if it's a key or value - void updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated); - using PtrVelocityList = std::vector>; PtrVelocityList mMovementQueue; From bb5213670c41634c666dd705e196832c74b8aa52 Mon Sep 17 00:00:00 2001 From: Frederic Chardon Date: Mon, 16 Nov 2020 11:09:08 +0100 Subject: [PATCH 099/111] Use bigger hammer to set Actor's position after teleporting. Otherwise traceDown() would use old collision object transform and gives incorrect results, making the Actor "fall" in the new position. --- apps/openmw/mwphysics/actor.cpp | 24 ++++++++++++------------ apps/openmw/mwphysics/actor.hpp | 3 ++- apps/openmw/mwphysics/mtphysics.cpp | 2 +- apps/openmw/mwphysics/physicssystem.cpp | 4 ++-- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index 0f3d69d21..430bd4dee 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -74,11 +74,8 @@ Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, Physic updateRotation(); updateScale(); - updatePosition(); - setPosition(mWorldPosition, true); - + resetPosition(); addCollisionMask(getCollisionMask()); - updateCollisionObjectPosition(); } Actor::~Actor() @@ -160,15 +157,9 @@ osg::Vec3f Actor::getCollisionObjectPosition() const return Misc::Convert::toOsg(mLocalTransform.getOrigin()); } -void Actor::setPosition(const osg::Vec3f& position, bool reset) +void Actor::setPosition(const osg::Vec3f& position) { - if (reset) - { - mPreviousPosition = position; - mNextPosition = position; - } - else - mPreviousPosition = mPosition; + mPreviousPosition = mPosition; mPosition = position; } @@ -178,6 +169,15 @@ void Actor::adjustPosition(const osg::Vec3f& offset) mPreviousPosition += offset; } +void Actor::resetPosition() +{ + updatePosition(); + mPreviousPosition = mWorldPosition; + mPosition = mWorldPosition; + mNextPosition = mWorldPosition; + updateCollisionObjectPosition(); +} + osg::Vec3f Actor::getPosition() const { return mPosition; diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 6b23b31d3..3d6f93ae0 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -91,7 +91,8 @@ namespace MWPhysics /** * Store the current position into mPreviousPosition, then move to this position. */ - void setPosition(const osg::Vec3f& position, bool reset=false); + void setPosition(const osg::Vec3f& position); + void resetPosition(); void adjustPosition(const osg::Vec3f& offset); osg::Vec3f getPosition() const; diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index ff676413b..dbb714fac 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -253,7 +253,7 @@ namespace MWPhysics for (const auto& m : mActorsFrameData) { m.mActorRaw->setStandingOnPtr(nullptr); - m.mActorRaw->setPosition(m.mActorRaw->getWorldPosition(), true); + m.mActorRaw->resetPosition(); mMovementResults[m.mPtr] = m.mActorRaw->getWorldPosition(); } return mMovementResults; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 5de26fdfc..42ead3606 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -433,8 +433,8 @@ namespace MWPhysics ActorMap::iterator found = mActors.find(ptr); if (found == mActors.end()) return ptr.getRefData().getPosition().asVec3(); - else - return MovementSolver::traceDown(ptr, position, found->second.get(), mCollisionWorld.get(), maxHeight); + found->second->resetPosition(); + return MovementSolver::traceDown(ptr, position, found->second.get(), mCollisionWorld.get(), maxHeight); } void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject) From 7768556ce64c240bdcf361910e6520b2e32b224f Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 16 Nov 2020 21:01:20 +0000 Subject: [PATCH 100/111] Set dummy state when disabling shadows indoors As we don't reconfigure all shaders without shadows when we disable them indoors (as it'd probably add a hitch to transitioning in and out) we need to set up dummy state so the shaders don't do anything illegal. This hadn't had symptoms for most objects as when indoors, nearly everything would be drawn first in one of the water RTTs, which had dummy state to disable shadows already. This wasn't true of the water plane itself, though, yet somehow it took until just now for anyone to report that. This resolves vtastek's issue where the water would be invisible indoors --- components/sceneutil/mwshadowtechnique.cpp | 26 +++++++++++++++++++++- components/sceneutil/mwshadowtechnique.hpp | 3 ++- components/sceneutil/shadow.cpp | 2 +- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 0411dbc43..c49a14777 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -820,9 +820,10 @@ void MWShadowTechnique::enableShadows() _enableShadows = true; } -void MWShadowTechnique::disableShadows() +void MWShadowTechnique::disableShadows(bool setDummyState) { _enableShadows = false; + mSetDummyStateWhenDisabled = setDummyState; } void SceneUtil::MWShadowTechnique::enableDebugHUD() @@ -914,7 +915,28 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) { if (!_enableShadows) { + if (mSetDummyStateWhenDisabled) + { + osg::ref_ptr dummyState = new osg::StateSet(); + + ShadowSettings* settings = getShadowedScene()->getShadowSettings(); + int baseUnit = settings->getBaseShadowTextureUnit(); + int endUnit = baseUnit + settings->getNumShadowMapsPerLight(); + for (int i = baseUnit; i < endUnit; ++i) + { + dummyState->setTextureAttributeAndModes(i, _fallbackShadowMapTexture, osg::StateAttribute::ON); + dummyState->addUniform(new osg::Uniform(("shadowTexture" + std::to_string(i - baseUnit)).c_str(), i)); + dummyState->addUniform(new osg::Uniform(("shadowTextureUnit" + std::to_string(i - baseUnit)).c_str(), i)); + } + + cv.pushStateSet(dummyState); + } + _shadowedScene->osg::Group::traverse(cv); + + if (mSetDummyStateWhenDisabled) + cv.popStateSet(); + return; } @@ -1577,6 +1599,8 @@ void MWShadowTechnique::createShaders() _fallbackShadowMapTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT); _fallbackShadowMapTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST); _fallbackShadowMapTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST); + _fallbackShadowMapTexture->setShadowComparison(true); + _fallbackShadowMapTexture->setShadowCompareFunc(osg::Texture::ShadowCompareFunc::ALWAYS); } diff --git a/components/sceneutil/mwshadowtechnique.hpp b/components/sceneutil/mwshadowtechnique.hpp index a7208cfa6..5125247dd 100644 --- a/components/sceneutil/mwshadowtechnique.hpp +++ b/components/sceneutil/mwshadowtechnique.hpp @@ -67,7 +67,7 @@ namespace SceneUtil { virtual void enableShadows(); - virtual void disableShadows(); + virtual void disableShadows(bool setDummyState = false); virtual void enableDebugHUD(); @@ -252,6 +252,7 @@ namespace SceneUtil { osg::ref_ptr _program; bool _enableShadows; + bool mSetDummyStateWhenDisabled; double _splitPointUniformLogRatio = 0.5; double _splitPointDeltaBias = 0.0; diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index 1e14fbbb1..35646b834 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -168,7 +168,7 @@ namespace SceneUtil if (Settings::Manager::getBool("enable indoor shadows", "Shadows")) mShadowSettings->setCastsShadowTraversalMask(mIndoorShadowCastingMask); else - mShadowTechnique->disableShadows(); + mShadowTechnique->disableShadows(true); } void ShadowManager::enableOutdoorMode() From 06ae2a0536274b45fc04d0b1a1a3585fda25ac3a Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 16 Nov 2020 21:07:30 +0000 Subject: [PATCH 101/111] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f19783ef..51babd907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Bug #5644: Summon effects running on the player during game initialization cause crashes Bug #5656: Sneaking characters block hits while standing Bug #5661: Region sounds don't play at the right interval + Bug #5688: Water shader broken indoors with enable indoor shadows = false Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging Feature #2404: Levelled List can not be placed into a container From 211894a178481ff4ae5434840e4da1bbacf32247 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 17 Nov 2020 16:14:05 +0000 Subject: [PATCH 102/111] Fix extraction with 7z 9.10 This is still used in the wild as lots of people install 7zip and never update it because it works. We can't check the version and abort if it's too old as the changelog doesn't make it clear which version fixed the behaviour. --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 2a0db9c91..0ef67f47e 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -913,7 +913,7 @@ printf "LZ4 1.9.2... " printf "Exists. " elif [ -z $SKIP_EXTRACT ]; then rm -rf LZ4_1.9.2 - eval 7z x -y lz4_win${BITS}_v1_9_2.7z -o./LZ4_1.9.2 $STRIP + eval 7z x -y lz4_win${BITS}_v1_9_2.7z -o$(real_pwd)/LZ4_1.9.2 $STRIP fi export LZ4DIR="$(real_pwd)/LZ4_1.9.2" add_cmake_opts -DLZ4_INCLUDE_DIR="${LZ4DIR}/include" \ From 48ea9960b92c2e31c6888e04775aae8aaab4981a Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 17 Nov 2020 16:45:13 +0000 Subject: [PATCH 103/111] Fix Debian GCC timeout on forks --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 25a04d536..810e23d38 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,6 +37,8 @@ Debian_GCC: CC: gcc CXX: g++ CCACHE_SIZE: 3G + # When CCache doesn't exist (e.g. first build on a fork), build takes more than 1h, which is the default for forks. + timeout: 2h Debian_GCC_tests: extends: .Debian From 06d1e70aacba6b18a9751e99db5625dc4a7e39ff Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 18 Nov 2020 15:34:21 +0000 Subject: [PATCH 104/111] Make Bullet DebugDrawer's default state match the physics system --- apps/openmw/mwphysics/physicssystem.cpp | 2 +- apps/openmw/mwrender/bulletdebugdraw.cpp | 8 +++----- apps/openmw/mwrender/bulletdebugdraw.hpp | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 42ead3606..8a58919ca 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -93,7 +93,7 @@ namespace MWPhysics } mTaskScheduler = std::make_unique(mPhysicsDt, mCollisionWorld); - mDebugDrawer = std::make_unique(mParentNode, mCollisionWorld.get()); + mDebugDrawer = std::make_unique(mParentNode, mCollisionWorld.get(), mDebugDrawEnabled); } PhysicsSystem::~PhysicsSystem() diff --git a/apps/openmw/mwrender/bulletdebugdraw.cpp b/apps/openmw/mwrender/bulletdebugdraw.cpp index 61570be45..00529ef80 100644 --- a/apps/openmw/mwrender/bulletdebugdraw.cpp +++ b/apps/openmw/mwrender/bulletdebugdraw.cpp @@ -14,13 +14,11 @@ namespace MWRender { -DebugDrawer::DebugDrawer(osg::ref_ptr parentNode, btCollisionWorld *world) +DebugDrawer::DebugDrawer(osg::ref_ptr parentNode, btCollisionWorld *world, int debugMode) : mParentNode(parentNode), - mWorld(world), - mDebugOn(true) + mWorld(world) { - - createGeometry(); + setDebugMode(debugMode); } void DebugDrawer::createGeometry() diff --git a/apps/openmw/mwrender/bulletdebugdraw.hpp b/apps/openmw/mwrender/bulletdebugdraw.hpp index f07ce2e2e..ec421bd74 100644 --- a/apps/openmw/mwrender/bulletdebugdraw.hpp +++ b/apps/openmw/mwrender/bulletdebugdraw.hpp @@ -48,7 +48,7 @@ protected: public: - DebugDrawer(osg::ref_ptr parentNode, btCollisionWorld *world); + DebugDrawer(osg::ref_ptr parentNode, btCollisionWorld *world, int debugMode = 1); ~DebugDrawer(); void step(); From c126d8801f938c6b188d8ab4bd708a9f4e48ba82 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 18 Nov 2020 17:28:09 +0100 Subject: [PATCH 105/111] Fix #5689 --- apps/openmw/mwstate/statemanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index e409e5b3b..72e4b1ae0 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -48,8 +48,8 @@ void MWState::StateManager::cleanup (bool force) MWBase::Environment::get().getDialogueManager()->clear(); MWBase::Environment::get().getJournal()->clear(); MWBase::Environment::get().getScriptManager()->clear(); - MWBase::Environment::get().getWorld()->clear(); MWBase::Environment::get().getWindowManager()->clear(); + MWBase::Environment::get().getWorld()->clear(); MWBase::Environment::get().getInputManager()->clear(); MWBase::Environment::get().getMechanicsManager()->clear(); From 9363bc2d4825705fcf8c60f42b150828b3ba332b Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 18 Nov 2020 18:03:29 +0100 Subject: [PATCH 106/111] Update recastnavigation to 6624e7aef5e15df11cb2f5673574df8e4c96af6a --- extern/recastnavigation/.id | 2 +- extern/recastnavigation/CMakeLists.txt | 6 ++++++ .../DebugUtils/CMakeLists.txt | 19 ++++++++++--------- extern/recastnavigation/Detour/CMakeLists.txt | 19 ++++++++++--------- .../DetourCrowd/CMakeLists.txt | 19 ++++++++++--------- .../DetourCrowd/Source/DetourCrowd.cpp | 8 +++++--- .../DetourTileCache/CMakeLists.txt | 19 ++++++++++--------- extern/recastnavigation/Recast/CMakeLists.txt | 19 ++++++++++--------- 8 files changed, 62 insertions(+), 49 deletions(-) diff --git a/extern/recastnavigation/.id b/extern/recastnavigation/.id index 81e564671..b53727263 100644 --- a/extern/recastnavigation/.id +++ b/extern/recastnavigation/.id @@ -1 +1 @@ -57610fa6ef31b39020231906f8c5d40eaa8294ae +6624e7aef5e15df11cb2f5673574df8e4c96af6a diff --git a/extern/recastnavigation/CMakeLists.txt b/extern/recastnavigation/CMakeLists.txt index 0d31c2e36..cf35af1e8 100644 --- a/extern/recastnavigation/CMakeLists.txt +++ b/extern/recastnavigation/CMakeLists.txt @@ -13,6 +13,12 @@ SET(VERSION 1.0.0) option(RECASTNAVIGATION_STATIC "Build static libraries" ON) +if(MSVC AND BUILD_SHARED_LIBS) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +endif() + +include(GNUInstallDirs) + add_subdirectory(DebugUtils) add_subdirectory(Detour) add_subdirectory(DetourCrowd) diff --git a/extern/recastnavigation/DebugUtils/CMakeLists.txt b/extern/recastnavigation/DebugUtils/CMakeLists.txt index 8b6a3fcf6..21d8f8f9d 100644 --- a/extern/recastnavigation/DebugUtils/CMakeLists.txt +++ b/extern/recastnavigation/DebugUtils/CMakeLists.txt @@ -1,12 +1,8 @@ file(GLOB SOURCES Source/*.cpp) - -if (RECASTNAVIGATION_STATIC) - add_library(DebugUtils STATIC ${SOURCES}) -else() - add_library(DebugUtils SHARED ${SOURCES}) -endif() +add_library(DebugUtils ${SOURCES}) add_library(RecastNavigation::DebugUtils ALIAS DebugUtils) +set_target_properties(DebugUtils PROPERTIES DEBUG_POSTFIX -d) set(DebugUtils_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") @@ -23,13 +19,18 @@ target_link_libraries(DebugUtils set_target_properties(DebugUtils PROPERTIES SOVERSION ${SOVERSION} VERSION ${VERSION} + COMPILE_PDB_OUTPUT_DIRECTORY . + COMPILE_PDB_NAME "DebugUtils-d" ) install(TARGETS DebugUtils - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ) file(GLOB INCLUDES Include/*.h) -install(FILES ${INCLUDES} DESTINATION include) +install(FILES ${INCLUDES} DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) +install(FILES "$/DebugUtils-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib") diff --git a/extern/recastnavigation/Detour/CMakeLists.txt b/extern/recastnavigation/Detour/CMakeLists.txt index de88111d5..5cb47ec0e 100644 --- a/extern/recastnavigation/Detour/CMakeLists.txt +++ b/extern/recastnavigation/Detour/CMakeLists.txt @@ -1,12 +1,8 @@ file(GLOB SOURCES Source/*.cpp) - -if(RECASTNAVIGATION_STATIC) - add_library(Detour STATIC ${SOURCES}) -else() - add_library(Detour SHARED ${SOURCES}) -endif() +add_library(Detour ${SOURCES}) add_library(RecastNavigation::Detour ALIAS Detour) +set_target_properties(Detour PROPERTIES DEBUG_POSTFIX -d) set(Detour_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") @@ -17,13 +13,18 @@ target_include_directories(Detour PUBLIC set_target_properties(Detour PROPERTIES SOVERSION ${SOVERSION} VERSION ${VERSION} + COMPILE_PDB_OUTPUT_DIRECTORY . + COMPILE_PDB_NAME "Detour-d" ) install(TARGETS Detour - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ) file(GLOB INCLUDES Include/*.h) -install(FILES ${INCLUDES} DESTINATION include) +install(FILES ${INCLUDES} DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) +install(FILES "$/Detour-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib") diff --git a/extern/recastnavigation/DetourCrowd/CMakeLists.txt b/extern/recastnavigation/DetourCrowd/CMakeLists.txt index 73cdf7ce8..d0e186be0 100644 --- a/extern/recastnavigation/DetourCrowd/CMakeLists.txt +++ b/extern/recastnavigation/DetourCrowd/CMakeLists.txt @@ -1,12 +1,8 @@ file(GLOB SOURCES Source/*.cpp) - -if (RECASTNAVIGATION_STATIC) - add_library(DetourCrowd STATIC ${SOURCES}) -else () - add_library(DetourCrowd SHARED ${SOURCES}) -endif () +add_library(DetourCrowd ${SOURCES}) add_library(RecastNavigation::DetourCrowd ALIAS DetourCrowd) +set_target_properties(DetourCrowd PROPERTIES DEBUG_POSTFIX -d) set(DetourCrowd_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") @@ -21,13 +17,18 @@ target_link_libraries(DetourCrowd set_target_properties(DetourCrowd PROPERTIES SOVERSION ${SOVERSION} VERSION ${VERSION} + COMPILE_PDB_OUTPUT_DIRECTORY . + COMPILE_PDB_NAME "DetourCrowd-d" ) install(TARGETS DetourCrowd - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ) file(GLOB INCLUDES Include/*.h) -install(FILES ${INCLUDES} DESTINATION include) +install(FILES ${INCLUDES} DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) +install(FILES "$/DetourCrowd-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib") diff --git a/extern/recastnavigation/DetourCrowd/Source/DetourCrowd.cpp b/extern/recastnavigation/DetourCrowd/Source/DetourCrowd.cpp index 1e76e40ce..3f0311f7f 100644 --- a/extern/recastnavigation/DetourCrowd/Source/DetourCrowd.cpp +++ b/extern/recastnavigation/DetourCrowd/Source/DetourCrowd.cpp @@ -1409,12 +1409,14 @@ void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug) } // Update agents using off-mesh connection. - for (int i = 0; i < m_maxAgents; ++i) + for (int i = 0; i < nagents; ++i) { - dtCrowdAgentAnimation* anim = &m_agentAnims[i]; + dtCrowdAgent* ag = agents[i]; + const int idx = (int)(ag - m_agents); + dtCrowdAgentAnimation* anim = &m_agentAnims[idx]; if (!anim->active) continue; - dtCrowdAgent* ag = agents[i]; + anim->t += dt; if (anim->t > anim->tmax) diff --git a/extern/recastnavigation/DetourTileCache/CMakeLists.txt b/extern/recastnavigation/DetourTileCache/CMakeLists.txt index 121b8edcc..3703ebb92 100644 --- a/extern/recastnavigation/DetourTileCache/CMakeLists.txt +++ b/extern/recastnavigation/DetourTileCache/CMakeLists.txt @@ -1,12 +1,8 @@ file(GLOB SOURCES Source/*.cpp) - -if (RECASTNAVIGATION_STATIC) - add_library(DetourTileCache STATIC ${SOURCES}) -else () - add_library(DetourTileCache SHARED ${SOURCES}) -endif () +add_library(DetourTileCache ${SOURCES}) add_library(RecastNavigation::DetourTileCache ALIAS DetourTileCache) +set_target_properties(DetourTileCache PROPERTIES DEBUG_POSTFIX -d) set(DetourTileCache_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") @@ -21,14 +17,19 @@ target_link_libraries(DetourTileCache set_target_properties(DetourTileCache PROPERTIES SOVERSION ${SOVERSION} VERSION ${VERSION} + COMPILE_PDB_OUTPUT_DIRECTORY . + COMPILE_PDB_NAME "DetourTileCache-d" ) install(TARGETS DetourTileCache - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ) file(GLOB INCLUDES Include/*.h) -install(FILES ${INCLUDES} DESTINATION include) +install(FILES ${INCLUDES} DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) +install(FILES "$/DetourTileCache-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib") diff --git a/extern/recastnavigation/Recast/CMakeLists.txt b/extern/recastnavigation/Recast/CMakeLists.txt index 5e843762e..360654464 100644 --- a/extern/recastnavigation/Recast/CMakeLists.txt +++ b/extern/recastnavigation/Recast/CMakeLists.txt @@ -1,12 +1,8 @@ file(GLOB SOURCES Source/*.cpp) - -if (RECASTNAVIGATION_STATIC) - add_library(Recast STATIC ${SOURCES}) -else () - add_library(Recast SHARED ${SOURCES}) -endif () +add_library(Recast ${SOURCES}) add_library(RecastNavigation::Recast ALIAS Recast) +set_target_properties(Recast PROPERTIES DEBUG_POSTFIX -d) set(Recast_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") @@ -17,13 +13,18 @@ target_include_directories(Recast PUBLIC set_target_properties(Recast PROPERTIES SOVERSION ${SOVERSION} VERSION ${VERSION} + COMPILE_PDB_OUTPUT_DIRECTORY . + COMPILE_PDB_NAME "Recast-d" ) install(TARGETS Recast - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ) file(GLOB INCLUDES Include/*.h) -install(FILES ${INCLUDES} DESTINATION include) +install(FILES ${INCLUDES} DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) +install(FILES "$/Recast-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib") From 9b11b8a27b42782ea528b1b2f5e2f884352bdb13 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 18 Nov 2020 18:52:00 +0100 Subject: [PATCH 107/111] Fix boundary check --- components/detournavigator/chunkytrimesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/detournavigator/chunkytrimesh.cpp b/components/detournavigator/chunkytrimesh.cpp index 3a8fc3480..ffd39d0a9 100644 --- a/components/detournavigator/chunkytrimesh.cpp +++ b/components/detournavigator/chunkytrimesh.cpp @@ -51,7 +51,7 @@ namespace DetourNavigator const auto inum = imax - imin; const auto icur = curNode; - if (curNode > nodes.size()) + if (curNode >= nodes.size()) return; ChunkyTriMeshNode& node = nodes[curNode++]; From 2413de38b52d6c6184f5b393f800d20086345b37 Mon Sep 17 00:00:00 2001 From: jefetienne Date: Tue, 17 Nov 2020 19:47:56 -0500 Subject: [PATCH 108/111] Extend spell/item search to search by magic effect name --- apps/openmw/mwgui/spellmodel.cpp | 46 +++++++++++++++++++++++++++++--- apps/openmw/mwgui/spellmodel.hpp | 3 +++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index 1dedfa10b..2ae92e33f 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -42,6 +42,44 @@ namespace MWGui { } + bool SpellModel::matchingEffectExists(std::string filter, const ESM::EffectList &effects) + { + auto wm = MWBase::Environment::get().getWindowManager(); + const MWWorld::ESMStore &store = + MWBase::Environment::get().getWorld()->getStore(); + + for (unsigned int i = 0; i < effects.mList.size(); ++i) + { + short effectId = effects.mList[i].mEffectID; + const ESM::MagicEffect *magicEffect = + store.get().search(effectId); + + if (effectId != -1) + { + std::string effectIDStr = ESM::MagicEffect::effectIdToString(effectId); + std::string fullEffectName = wm->getGameSettingString(effectIDStr, ""); + + if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill && effects.mList[i].mSkill != -1) + { + fullEffectName += " " + wm->getGameSettingString(ESM::Skill::sSkillNameIds[effects.mList[i].mSkill], ""); + } + + if (magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute && effects.mList[i].mAttribute != -1) + { + fullEffectName += " " + wm->getGameSettingString(ESM::Attribute::sGmstAttributeIds[effects.mList[i].mAttribute], ""); + } + + std::string convert = Misc::StringUtils::lowerCaseUtf8(fullEffectName); + if (convert.find(filter) != std::string::npos) + { + return true; + } + } + } + + return false; + } + void SpellModel::update() { mSpells.clear(); @@ -61,8 +99,9 @@ namespace MWGui continue; std::string name = Misc::StringUtils::lowerCaseUtf8(spell->mName); - - if (name.find(filter) == std::string::npos) + + if (name.find(filter) == std::string::npos + && !matchingEffectExists(filter, spell->mEffects)) continue; Spell newSpell; @@ -103,7 +142,8 @@ namespace MWGui std::string name = Misc::StringUtils::lowerCaseUtf8(item.getClass().getName(item)); - if (name.find(filter) == std::string::npos) + if (name.find(filter) == std::string::npos + && !matchingEffectExists(filter, enchant->mEffects)) continue; Spell newSpell; diff --git a/apps/openmw/mwgui/spellmodel.hpp b/apps/openmw/mwgui/spellmodel.hpp index d191cba0e..2404610bf 100644 --- a/apps/openmw/mwgui/spellmodel.hpp +++ b/apps/openmw/mwgui/spellmodel.hpp @@ -2,6 +2,7 @@ #define OPENMW_GUI_SPELLMODEL_H #include "../mwworld/ptr.hpp" +#include namespace MWGui { @@ -57,6 +58,8 @@ namespace MWGui std::vector mSpells; std::string mFilter; + + bool matchingEffectExists(std::string filter, const ESM::EffectList &effects); }; } From bc6f46465f9d3bf09aebbd44689898673998efe4 Mon Sep 17 00:00:00 2001 From: jefetienne Date: Wed, 18 Nov 2020 14:30:41 -0500 Subject: [PATCH 109/111] Add to changelog, authors. Move variable declaration inside block --- AUTHORS.md | 1 + CHANGELOG.md | 1 + apps/openmw/mwgui/spellmodel.cpp | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index 25004078e..09ab78412 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -96,6 +96,7 @@ Programmers Jan Borsodi (am0s) Jason Hooks (jhooks) jeaye + jefetienne Jeffrey Haines (Jyby) Jengerer Jiří Kuneš (kunesj) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51babd907..8f909a19f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,7 @@ Feature #5642: Ability to attach arrows to actor skeleton instead of bow mesh Feature #5649: Skyrim SE compressed BSA format support Feature #5672: Make stretch menu background configuration more accessible + Feature #5692: Improve spell/magic item search to factor in magic effect names Task #5480: Drop Qt4 support Task #5520: Improve cell name autocompleter implementation diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index 2ae92e33f..136547c4c 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -51,11 +51,11 @@ namespace MWGui for (unsigned int i = 0; i < effects.mList.size(); ++i) { short effectId = effects.mList[i].mEffectID; - const ESM::MagicEffect *magicEffect = - store.get().search(effectId); if (effectId != -1) { + const ESM::MagicEffect *magicEffect = + store.get().search(effectId); std::string effectIDStr = ESM::MagicEffect::effectIdToString(effectId); std::string fullEffectName = wm->getGameSettingString(effectIDStr, ""); From 9aba55a21a0d7423b91a40ae9234144e3b823ec2 Mon Sep 17 00:00:00 2001 From: Frederic Chardon Date: Fri, 20 Nov 2020 13:11:53 +0100 Subject: [PATCH 110/111] Add the async physics worker to the profiler overlay. --- apps/openmw/engine.cpp | 10 +++++++++- apps/openmw/mwbase/world.hpp | 4 +++- apps/openmw/mwphysics/mtphysics.cpp | 17 ++++++++++++++++- apps/openmw/mwphysics/mtphysics.hpp | 10 +++++++++- apps/openmw/mwphysics/physicssystem.cpp | 5 +++-- apps/openmw/mwphysics/physicssystem.hpp | 3 ++- apps/openmw/mwworld/worldimp.cpp | 9 +++++---- apps/openmw/mwworld/worldimp.hpp | 4 ++-- 8 files changed, 49 insertions(+), 13 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 49a4b4059..0bfd67dd7 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -94,6 +94,7 @@ namespace Script, Mechanics, Physics, + PhysicsWorker, World, Gui, @@ -124,6 +125,9 @@ namespace template <> const UserStats UserStatsValue::sValue {"Phys", "physics"}; + template <> + const UserStats UserStatsValue::sValue {" -Async", "physicsworker"}; + template <> const UserStats UserStatsValue::sValue {"World", "world"}; @@ -203,6 +207,10 @@ namespace profiler.addUserStatsLine(v.mLabel, textColor, barColor, v.mTaken, multiplier, average, averageInInverseSpace, v.mBegin, v.mEnd, maxValue); }); + // the forEachUserStatsValue loop is "run" at compile time, hence the settings manager is not available. + // Unconditionnally add the async physics stats, and then remove it at runtime if necessary + if (Settings::Manager::getInt("async num threads", "Physics") == 0) + profiler.removeUserStatsLine(" -Async"); } } @@ -318,7 +326,7 @@ bool OMW::Engine::frame(float frametime) if (mEnvironment.getStateManager()->getState() != MWBase::StateManager::State_NoGame) { - mEnvironment.getWorld()->updatePhysics(frametime, guiActive); + mEnvironment.getWorld()->updatePhysics(frametime, guiActive, frameStart, frameNumber, *stats); } } diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index f9cbc8972..49bc76a76 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -10,6 +10,8 @@ #include +#include + #include "../mwworld/ptr.hpp" #include "../mwworld/doorstate.hpp" @@ -391,7 +393,7 @@ namespace MWBase /// \return pointer to created record virtual void update (float duration, bool paused) = 0; - virtual void updatePhysics (float duration, bool paused) = 0; + virtual void updatePhysics (float duration, bool paused, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) = 0; virtual void updateWindowManager () = 0; diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index dbb714fac..8c06e0140 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include "components/debug/debuglog.hpp" #include #include "components/misc/convert.hpp" @@ -154,6 +156,8 @@ namespace MWPhysics , mQuit(false) , mNextJob(0) , mNextLOS(0) + , mFrameNumber(0) + , mTimer(osg::Timer::instance()) { mNumThreads = Config::computeNumThreads(mThreadSafeBullet); @@ -192,6 +196,7 @@ namespace MWPhysics [](const LOSRequest& req) { return req.mStale; }), mLOSCache.end()); } + mTimeEnd = mTimer->tick(); }); } @@ -207,7 +212,7 @@ namespace MWPhysics thread.join(); } - const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skipSimulation) + const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { // This function run in the main thread. // While the mSimulationMutex is held, background physics threads can't run. @@ -230,6 +235,16 @@ namespace MWPhysics if (mMovementResults.find(data.mPtr) != mMovementResults.end()) data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]); } + + if (mFrameNumber == frameNumber - 1) + { + stats.setAttribute(mFrameNumber, "physicsworker_time_begin", mTimer->delta_s(mFrameStart, mTimeBegin)); + stats.setAttribute(mFrameNumber, "physicsworker_time_taken", mTimer->delta_s(mTimeBegin, mTimeEnd)); + stats.setAttribute(mFrameNumber, "physicsworker_time_end", mTimer->delta_s(mFrameStart, mTimeEnd)); + } + mFrameStart = frameStart; + mTimeBegin = mTimer->tick(); + mFrameNumber = frameNumber; } // init diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index ef1c90b87..c061fe01d 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -9,6 +9,8 @@ #include +#include + #include "physicssystem.hpp" #include "ptrholder.hpp" @@ -30,7 +32,7 @@ namespace MWPhysics /// @param timeAccum accumulated time from previous run to interpolate movements /// @param actorsData per actor data needed to compute new positions /// @return new position of each actor - const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skip); + const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skip, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); // Thread safe wrappers void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; @@ -87,6 +89,12 @@ namespace MWPhysics mutable std::shared_mutex mLOSCacheMutex; mutable std::mutex mUpdateAabbMutex; std::condition_variable_any mHasJob; + + unsigned int mFrameNumber; + const osg::Timer* mTimer; + osg::Timer_t mTimeBegin; + osg::Timer_t mTimeEnd; + osg::Timer_t mFrameStart; }; } diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 8a58919ca..1ceba2f31 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -665,7 +666,7 @@ namespace MWPhysics mMovementQueue.clear(); } - const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation) + const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { mTimeAccum += dt; @@ -675,7 +676,7 @@ namespace MWPhysics mTimeAccum -= numSteps * mPhysicsDt; - return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), skipSimulation); + return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), skipSimulation, frameStart, frameNumber, stats); } std::vector PhysicsSystem::prepareFrameData(int numSteps) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index ccfca5422..379aea1dd 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "../mwworld/ptr.hpp" @@ -200,7 +201,7 @@ namespace MWPhysics void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity); /// Apply all queued movements, then clear the list. - const PtrPositionList& applyQueuedMovement(float dt, bool skipSimulation); + const PtrPositionList& applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); /// Clear the queued movements list without applying. void clearQueuedMovement(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ad6c33790..54b94833e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -1494,14 +1495,14 @@ namespace MWWorld mPhysics->updateAnimatedCollisionShape(ptr); } - void World::doPhysics(float duration) + void World::doPhysics(float duration, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { mPhysics->stepSimulation(); processDoors(duration); mProjectileManager->update(duration); - const auto results = mPhysics->applyQueuedMovement(duration, mDiscardMovements); + const auto results = mPhysics->applyQueuedMovement(duration, mDiscardMovements, frameStart, frameNumber, stats); mDiscardMovements = false; for(const auto& [actor, position]: results) @@ -1830,11 +1831,11 @@ namespace MWWorld } } - void World::updatePhysics (float duration, bool paused) + void World::updatePhysics (float duration, bool paused, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { if (!paused) { - doPhysics (duration); + doPhysics (duration, frameStart, frameNumber, stats); } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 909ac1d41..41ab9cf2c 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -157,7 +157,7 @@ namespace MWWorld void processDoors(float duration); ///< Run physics simulation and modify \a world accordingly. - void doPhysics(float duration); + void doPhysics(float duration, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); ///< Run physics simulation and modify \a world accordingly. void updateNavigator(); @@ -493,7 +493,7 @@ namespace MWWorld /// \return pointer to created record void update (float duration, bool paused) override; - void updatePhysics (float duration, bool paused) override; + void updatePhysics (float duration, bool paused, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) override; void updateWindowManager () override; From 96e22bd44e58e69487456759ffc0a11125ecc7b7 Mon Sep 17 00:00:00 2001 From: psi29a Date: Mon, 23 Nov 2020 06:05:45 +0000 Subject: [PATCH 111/111] Merge branch 'fastforwardpos' into 'master' Discard physics simulation results after fast forward See merge request OpenMW/openmw!423 (cherry picked from commit ff2d7695698341ef059c75707aa092cef48deea4) 03a37433 In case of time fast forward (resting, jail), force reset of positions --- apps/openmw/mwworld/worldimp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 54b94833e..20ee7625b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -890,6 +890,7 @@ namespace MWWorld { mRendering->notifyWorldSpaceChanged(); mProjectileManager->clear(); + mDiscardMovements = true; } }